centralize portfolio load
This commit is contained in:
parent
fe0e10eaca
commit
68392efec4
4 changed files with 69 additions and 54 deletions
|
|
@ -5,24 +5,12 @@ const fmt = cli.fmt;
|
|||
|
||||
/// CLI `analysis` command: show portfolio analysis breakdowns.
|
||||
pub fn run(allocator: std.mem.Allocator, svc: *zfin.DataService, file_path: []const u8, color: bool, out: *std.Io.Writer) !void {
|
||||
// Load portfolio
|
||||
const file_data = std.fs.cwd().readFileAlloc(allocator, file_path, 10 * 1024 * 1024) catch {
|
||||
try cli.stderrPrint("Error: Cannot read portfolio file\n");
|
||||
return;
|
||||
};
|
||||
defer allocator.free(file_data);
|
||||
var loaded = cli.loadPortfolio(allocator, file_path) orelse return;
|
||||
defer loaded.deinit(allocator);
|
||||
|
||||
var portfolio = zfin.cache.deserializePortfolio(allocator, file_data) catch {
|
||||
try cli.stderrPrint("Error: Cannot parse portfolio file\n");
|
||||
return;
|
||||
};
|
||||
defer portfolio.deinit();
|
||||
|
||||
const positions = try portfolio.positions(allocator);
|
||||
defer allocator.free(positions);
|
||||
|
||||
const syms = try portfolio.stockSymbols(allocator);
|
||||
defer allocator.free(syms);
|
||||
const portfolio = loaded.portfolio;
|
||||
const positions = loaded.positions;
|
||||
const syms = loaded.syms;
|
||||
|
||||
// Build prices from cache
|
||||
var prices = std.StringHashMap(f64).init(allocator);
|
||||
|
|
|
|||
|
|
@ -250,6 +250,60 @@ pub fn loadPortfolioPrices(
|
|||
return result;
|
||||
}
|
||||
|
||||
// ── Portfolio loading ────────────────────────────────────────
|
||||
|
||||
/// Result of loading and parsing a portfolio file. Caller must call deinit().
|
||||
pub const LoadedPortfolio = struct {
|
||||
file_data: []const u8,
|
||||
portfolio: zfin.Portfolio,
|
||||
positions: []const zfin.Position,
|
||||
syms: []const []const u8,
|
||||
|
||||
pub fn deinit(self: *LoadedPortfolio, allocator: std.mem.Allocator) void {
|
||||
allocator.free(self.syms);
|
||||
allocator.free(self.positions);
|
||||
self.portfolio.deinit();
|
||||
allocator.free(self.file_data);
|
||||
}
|
||||
};
|
||||
|
||||
/// Read, deserialize, and extract positions + symbols from a portfolio file.
|
||||
/// Returns null (with stderr message) on read/parse errors.
|
||||
pub fn loadPortfolio(allocator: std.mem.Allocator, file_path: []const u8) ?LoadedPortfolio {
|
||||
const file_data = std.fs.cwd().readFileAlloc(allocator, file_path, 10 * 1024 * 1024) catch {
|
||||
stderrPrint("Error: Cannot read portfolio file\n") catch {};
|
||||
return null;
|
||||
};
|
||||
|
||||
var portfolio = zfin.cache.deserializePortfolio(allocator, file_data) catch {
|
||||
allocator.free(file_data);
|
||||
stderrPrint("Error: Cannot parse portfolio file\n") catch {};
|
||||
return null;
|
||||
};
|
||||
|
||||
const positions = portfolio.positions(allocator) catch {
|
||||
portfolio.deinit();
|
||||
allocator.free(file_data);
|
||||
stderrPrint("Error: Cannot compute positions\n") catch {};
|
||||
return null;
|
||||
};
|
||||
|
||||
const syms = portfolio.stockSymbols(allocator) catch {
|
||||
allocator.free(positions);
|
||||
portfolio.deinit();
|
||||
allocator.free(file_data);
|
||||
stderrPrint("Error: Cannot get stock symbols\n") catch {};
|
||||
return null;
|
||||
};
|
||||
|
||||
return .{
|
||||
.file_data = file_data,
|
||||
.portfolio = portfolio,
|
||||
.positions = positions,
|
||||
.syms = syms,
|
||||
};
|
||||
}
|
||||
|
||||
// ── Portfolio data pipeline ──────────────────────────────────
|
||||
|
||||
/// Result of the shared portfolio data pipeline. Caller must call deinit().
|
||||
|
|
|
|||
|
|
@ -11,33 +11,18 @@ fn setIntentFg(out: *std.Io.Writer, color: bool, intent: fmt.StyleIntent) !void
|
|||
|
||||
pub fn run(allocator: std.mem.Allocator, svc: *zfin.DataService, file_path: []const u8, watchlist_path: ?[]const u8, force_refresh: bool, color: bool, out: *std.Io.Writer) !void {
|
||||
// Load portfolio from SRF file
|
||||
const data = std.fs.cwd().readFileAlloc(allocator, file_path, 10 * 1024 * 1024) catch |err| {
|
||||
try cli.stderrPrint("Error reading portfolio file: ");
|
||||
try cli.stderrPrint(@errorName(err));
|
||||
try cli.stderrPrint("\n");
|
||||
return;
|
||||
};
|
||||
defer allocator.free(data);
|
||||
var loaded = cli.loadPortfolio(allocator, file_path) orelse return;
|
||||
defer loaded.deinit(allocator);
|
||||
|
||||
var portfolio = zfin.cache.deserializePortfolio(allocator, data) catch {
|
||||
try cli.stderrPrint("Error parsing portfolio file.\n");
|
||||
return;
|
||||
};
|
||||
defer portfolio.deinit();
|
||||
const portfolio = loaded.portfolio;
|
||||
const positions = loaded.positions;
|
||||
const syms = loaded.syms;
|
||||
|
||||
if (portfolio.lots.len == 0) {
|
||||
try cli.stderrPrint("Portfolio is empty.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get stock/ETF positions (excludes options, CDs, cash)
|
||||
const positions = try portfolio.positions(allocator);
|
||||
defer allocator.free(positions);
|
||||
|
||||
// Get unique stock/ETF symbols and fetch current prices
|
||||
const syms = try portfolio.stockSymbols(allocator);
|
||||
defer allocator.free(syms);
|
||||
|
||||
var prices = std.StringHashMap(f64).init(allocator);
|
||||
defer prices.deinit();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,24 +19,12 @@ const stock_benchmark = "SPY";
|
|||
const bond_benchmark = "AGG";
|
||||
|
||||
pub fn run(allocator: std.mem.Allocator, svc: *zfin.DataService, file_path: []const u8, color: bool, out: *std.Io.Writer) !void {
|
||||
// Load portfolio
|
||||
const file_data = std.fs.cwd().readFileAlloc(allocator, file_path, 10 * 1024 * 1024) catch {
|
||||
try cli.stderrPrint("Error: Cannot read portfolio file\n");
|
||||
return;
|
||||
};
|
||||
defer allocator.free(file_data);
|
||||
var loaded = cli.loadPortfolio(allocator, file_path) orelse return;
|
||||
defer loaded.deinit(allocator);
|
||||
|
||||
var portfolio = zfin.cache.deserializePortfolio(allocator, file_data) catch {
|
||||
try cli.stderrPrint("Error: Cannot parse portfolio file\n");
|
||||
return;
|
||||
};
|
||||
defer portfolio.deinit();
|
||||
|
||||
const positions = try portfolio.positions(allocator);
|
||||
defer allocator.free(positions);
|
||||
|
||||
const syms = try portfolio.stockSymbols(allocator);
|
||||
defer allocator.free(syms);
|
||||
const portfolio = loaded.portfolio;
|
||||
const positions = loaded.positions;
|
||||
const syms = loaded.syms;
|
||||
|
||||
// Build prices from cache
|
||||
var prices = std.StringHashMap(f64).init(allocator);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue