Skip to content

Commit 5aa9471

Browse files
committed
Print current holding in summary mode
1 parent 6e503ea commit 5aa9471

File tree

1 file changed

+100
-83
lines changed

1 file changed

+100
-83
lines changed

src/main.rs

+100-83
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,95 @@ async fn process_account_cost_basis(
21542154
Ok(())
21552155
}
21562156

2157+
fn print_current_holdings(
2158+
held_tokens: &BTreeMap::<MaybeToken, (/*price*/ Option<Decimal>, /*amount*/ u64, RealizedGain)>,
2159+
tax_rate: Option<&TaxRate>,
2160+
) {
2161+
println!("Current Holdings");
2162+
let mut held_tokens = held_tokens
2163+
.into_iter()
2164+
.map(
2165+
|(held_token, (current_token_price, total_held_amount, unrealized_gain))| {
2166+
let total_value = current_token_price.map(|current_token_price| {
2167+
f64::try_from(
2168+
Decimal::from_f64(held_token.ui_amount(*total_held_amount)).unwrap()
2169+
* current_token_price,
2170+
)
2171+
.unwrap()
2172+
});
2173+
2174+
(
2175+
held_token,
2176+
total_value,
2177+
current_token_price,
2178+
total_held_amount,
2179+
unrealized_gain,
2180+
)
2181+
},
2182+
)
2183+
.collect::<Vec<_>>();
2184+
2185+
// Order current holdings by `total_value`
2186+
held_tokens
2187+
.sort_unstable_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
2188+
2189+
for (held_token, total_value, current_token_price, total_held_amount, unrealized_gain) in
2190+
held_tokens
2191+
{
2192+
if *total_held_amount == 0 {
2193+
continue;
2194+
}
2195+
2196+
let estimated_tax = tax_rate
2197+
.and_then(|tax_rate| {
2198+
let tax = unrealized_gain.short_term_cap_gain * tax_rate.short_term_gain
2199+
+ unrealized_gain.long_term_cap_gain * tax_rate.long_term_gain;
2200+
2201+
if tax > 0. {
2202+
Some(format!(
2203+
"; ${} estimated tax",
2204+
tax.separated_string_with_fixed_place(2)
2205+
))
2206+
} else {
2207+
None
2208+
}
2209+
})
2210+
.unwrap_or_default();
2211+
2212+
if held_token.fiat_fungible() {
2213+
println!(
2214+
" {:<7} {:<22}",
2215+
held_token.to_string(),
2216+
held_token.format_amount(*total_held_amount)
2217+
);
2218+
} else {
2219+
println!(
2220+
" {:<7} {:<22} [{}; ${:>4} per {:>4}{}]",
2221+
held_token.to_string(),
2222+
held_token.format_amount(*total_held_amount),
2223+
total_value
2224+
.map(|tv| {
2225+
format!(
2226+
"${:14} ({:>8}%)",
2227+
tv.separated_string_with_fixed_place(2),
2228+
((tv - unrealized_gain.basis) / unrealized_gain.basis * 100.)
2229+
.separated_string_with_fixed_place(2)
2230+
)
2231+
})
2232+
.unwrap_or_else(|| "?".into()),
2233+
current_token_price
2234+
.map(|current_token_price| f64::try_from(current_token_price)
2235+
.unwrap()
2236+
.separated_string_with_fixed_place(3))
2237+
.unwrap_or_else(|| "?".into()),
2238+
held_token,
2239+
estimated_tax,
2240+
);
2241+
}
2242+
}
2243+
println!();
2244+
}
2245+
21572246
async fn process_account_list(
21582247
db: &Db,
21592248
rpc_client: &RpcClient,
@@ -2266,6 +2355,13 @@ async fn process_account_list(
22662355
account.assert_lot_balance();
22672356

22682357
if summary_only {
2358+
if !account.lots.is_empty() {
2359+
let mut account_basis = 0.;
2360+
for lot in account.lots.iter() {
2361+
account_basis += lot.basis(account.token);
2362+
}
2363+
held_token.2.basis += account_basis;
2364+
}
22692365
continue;
22702366
}
22712367

@@ -2433,6 +2529,9 @@ async fn process_account_list(
24332529
println!();
24342530
}
24352531

2532+
if summary_only {
2533+
print_current_holdings(&held_tokens, db.get_tax_rate());
2534+
}
24362535
if account_filter.is_some() || summary_only {
24372536
return Ok(());
24382537
}
@@ -2600,89 +2699,7 @@ async fn process_account_list(
26002699
}
26012700
println!();
26022701

2603-
println!("Current Holdings");
2604-
let mut held_tokens = held_tokens
2605-
.into_iter()
2606-
.map(
2607-
|(held_token, (current_token_price, total_held_amount, unrealized_gain))| {
2608-
let total_value = current_token_price.map(|current_token_price| {
2609-
f64::try_from(
2610-
Decimal::from_f64(held_token.ui_amount(total_held_amount)).unwrap()
2611-
* current_token_price,
2612-
)
2613-
.unwrap()
2614-
});
2615-
2616-
(
2617-
held_token,
2618-
total_value,
2619-
current_token_price,
2620-
total_held_amount,
2621-
unrealized_gain,
2622-
)
2623-
},
2624-
)
2625-
.collect::<Vec<_>>();
2626-
2627-
// Order current holdings by `total_value`
2628-
held_tokens
2629-
.sort_unstable_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
2630-
2631-
for (held_token, total_value, current_token_price, total_held_amount, unrealized_gain) in
2632-
held_tokens
2633-
{
2634-
if total_held_amount == 0 {
2635-
continue;
2636-
}
2637-
2638-
let estimated_tax = tax_rate
2639-
.and_then(|tax_rate| {
2640-
let tax = unrealized_gain.short_term_cap_gain * tax_rate.short_term_gain
2641-
+ unrealized_gain.long_term_cap_gain * tax_rate.long_term_gain;
2642-
2643-
if tax > 0. {
2644-
Some(format!(
2645-
"; ${} estimated tax",
2646-
tax.separated_string_with_fixed_place(2)
2647-
))
2648-
} else {
2649-
None
2650-
}
2651-
})
2652-
.unwrap_or_default();
2653-
2654-
if held_token.fiat_fungible() {
2655-
println!(
2656-
" {:<7} {:<22}",
2657-
held_token.to_string(),
2658-
held_token.format_amount(total_held_amount)
2659-
);
2660-
} else {
2661-
println!(
2662-
" {:<7} {:<22} [{}; ${:>4} per {:>4}{}]",
2663-
held_token.to_string(),
2664-
held_token.format_amount(total_held_amount),
2665-
total_value
2666-
.map(|tv| {
2667-
format!(
2668-
"${:14} ({:>8}%)",
2669-
tv.separated_string_with_fixed_place(2),
2670-
((tv - unrealized_gain.basis) / unrealized_gain.basis * 100.)
2671-
.separated_string_with_fixed_place(2)
2672-
)
2673-
})
2674-
.unwrap_or_else(|| "?".into()),
2675-
current_token_price
2676-
.map(|current_token_price| f64::try_from(current_token_price)
2677-
.unwrap()
2678-
.separated_string_with_fixed_place(3))
2679-
.unwrap_or_else(|| "?".into()),
2680-
held_token,
2681-
estimated_tax,
2682-
);
2683-
}
2684-
}
2685-
println!();
2702+
print_current_holdings(&held_tokens, tax_rate);
26862703

26872704
println!("Summary");
26882705
println!(

0 commit comments

Comments
 (0)