make price ratio non-null
All checks were successful
Generic zig build / build (push) Successful in 29s

This commit is contained in:
Emil Lerch 2026-03-11 15:34:47 -07:00
parent f8a9607bc9
commit 7ba1df8ba9
Signed by: lobo
GPG key ID: A7B62D657EF764F8
3 changed files with 11 additions and 13 deletions

View file

@ -163,7 +163,7 @@ pub fn portfolioSummary(
// Only apply price_ratio to live/fetched prices. Manual/fallback prices
// (avg_cost) are already in the correct terms for the share class.
const is_manual = if (manual_prices) |mp| mp.contains(pos.symbol) else false;
const price = if (is_manual) raw_price else raw_price * (pos.price_ratio orelse 1.0);
const price = if (is_manual) raw_price else raw_price * pos.price_ratio;
const mv = pos.shares * price;
total_value += mv;
total_cost += pos.total_cost;

11
src/cache/store.zig vendored
View file

@ -906,13 +906,12 @@ test "portfolio: price_ratio round-trip" {
try std.testing.expectEqualStrings("02315N600", portfolio.lots[0].symbol);
try std.testing.expectEqualStrings("VTTHX", portfolio.lots[0].ticker.?);
try std.testing.expectEqualStrings("VTTHX", portfolio.lots[0].priceSymbol());
try std.testing.expect(portfolio.lots[0].price_ratio != null);
try std.testing.expectApproxEqAbs(@as(f64, 5.185), portfolio.lots[0].price_ratio.?, 0.001);
try std.testing.expectApproxEqAbs(@as(f64, 5.185), portfolio.lots[0].price_ratio, 0.001);
try std.testing.expectEqualStrings("VANGUARD TARGET 2035", portfolio.lots[0].note.?);
// Regular lot no price_ratio
// Regular lot no price_ratio (default 1.0)
try std.testing.expectEqualStrings("AAPL", portfolio.lots[1].symbol);
try std.testing.expect(portfolio.lots[1].price_ratio == null);
try std.testing.expectApproxEqAbs(@as(f64, 1.0), portfolio.lots[1].price_ratio, 0.001);
try std.testing.expect(portfolio.lots[1].ticker == null);
// Round-trip: serialize and deserialize again
@ -923,7 +922,7 @@ test "portfolio: price_ratio round-trip" {
defer portfolio2.deinit();
try std.testing.expectEqual(@as(usize, 2), portfolio2.lots.len);
try std.testing.expectApproxEqAbs(@as(f64, 5.185), portfolio2.lots[0].price_ratio.?, 0.001);
try std.testing.expectApproxEqAbs(@as(f64, 5.185), portfolio2.lots[0].price_ratio, 0.001);
try std.testing.expectEqualStrings("VTTHX", portfolio2.lots[0].ticker.?);
try std.testing.expect(portfolio2.lots[1].price_ratio == null);
try std.testing.expectApproxEqAbs(@as(f64, 1.0), portfolio2.lots[1].price_ratio, 0.001);
}

View file

@ -66,7 +66,7 @@ pub const Lot = struct {
/// (from the `ticker` symbol) is multiplied by this ratio to get the actual
/// institutional NAV. E.g. if VTTHX (investor) is $27.78 and the institutional
/// class trades at $144.04, price_ratio = 144.04 / 27.78 5.185.
price_ratio: ?f64 = null,
price_ratio: f64 = 1.0,
/// The symbol to use for price fetching (ticker if set, else symbol).
pub fn priceSymbol(self: Lot) []const u8 {
@ -129,7 +129,7 @@ pub const Position = struct {
/// Currently positions() takes the ratio from the first lot that has one.
/// Supporting dual-holding of investor + institutional shares of the same
/// ticker would require a different grouping key in positions().
price_ratio: ?f64 = null,
price_ratio: f64 = 1.0,
};
/// A portfolio is a collection of lots.
@ -250,7 +250,7 @@ pub const Portfolio = struct {
entry.value_ptr.account = "Multiple";
}
// Propagate price_ratio from the first lot that has one
if (entry.value_ptr.price_ratio == null and lot.price_ratio != null) {
if (entry.value_ptr.price_ratio == 1.0 and lot.price_ratio != 1.0) {
entry.value_ptr.price_ratio = lot.price_ratio;
}
}
@ -537,11 +537,10 @@ test "positions propagates price_ratio from lot" {
for (pos) |p| {
if (std.mem.eql(u8, p.symbol, "VTTHX")) {
try std.testing.expectApproxEqAbs(@as(f64, 150.0), p.shares, 0.01);
try std.testing.expect(p.price_ratio != null);
try std.testing.expectApproxEqAbs(@as(f64, 5.185), p.price_ratio.?, 0.001);
try std.testing.expectApproxEqAbs(@as(f64, 5.185), p.price_ratio, 0.001);
} else {
try std.testing.expectEqualStrings("AAPL", p.symbol);
try std.testing.expect(p.price_ratio == null);
try std.testing.expectApproxEqAbs(@as(f64, 1.0), p.price_ratio, 0.001);
}
}
}