clean up history/enrich
This commit is contained in:
parent
1cdf228fc1
commit
be42f9e15a
2 changed files with 36 additions and 42 deletions
|
|
@ -3,6 +3,36 @@ const zfin = @import("../root.zig");
|
|||
const cli = @import("common.zig");
|
||||
const isCusipLike = @import("../models/portfolio.zig").isCusipLike;
|
||||
|
||||
const OverviewMeta = struct {
|
||||
sector: []const u8,
|
||||
geo: []const u8,
|
||||
asset_class: []const u8,
|
||||
};
|
||||
|
||||
/// Derive sector, geo, and asset_class from an Alpha Vantage company overview.
|
||||
fn deriveMetadata(overview: zfin.CompanyOverview, sector_buf: []u8) OverviewMeta {
|
||||
const sector_raw = overview.sector orelse "Unknown";
|
||||
const sector_str = cli.fmt.toTitleCase(sector_buf, sector_raw);
|
||||
const country_str = overview.country orelse "US";
|
||||
const geo_str = if (std.mem.eql(u8, country_str, "USA")) "US" else country_str;
|
||||
|
||||
const asset_class_str = blk: {
|
||||
if (overview.asset_type) |at| {
|
||||
if (std.mem.eql(u8, at, "ETF")) break :blk "ETF";
|
||||
if (std.mem.eql(u8, at, "Mutual Fund")) break :blk "Mutual Fund";
|
||||
}
|
||||
if (overview.market_cap) |mc_str| {
|
||||
const mc = std.fmt.parseInt(u64, mc_str, 10) catch 0;
|
||||
if (mc >= 10_000_000_000) break :blk "US Large Cap";
|
||||
if (mc >= 2_000_000_000) break :blk "US Mid Cap";
|
||||
break :blk "US Small Cap";
|
||||
}
|
||||
break :blk "US Large Cap";
|
||||
};
|
||||
|
||||
return .{ .sector = sector_str, .geo = geo_str, .asset_class = asset_class_str };
|
||||
}
|
||||
|
||||
/// CLI `enrich` command: bootstrap a metadata.srf file from Alpha Vantage OVERVIEW data.
|
||||
/// Reads the portfolio, extracts stock symbols, fetches sector/industry/country for each,
|
||||
/// and outputs a metadata SRF file to stdout.
|
||||
|
|
@ -50,31 +80,14 @@ fn enrichSymbol(allocator: std.mem.Allocator, svc: *zfin.DataService, sym: []con
|
|||
if (overview.asset_type) |at| allocator.free(at);
|
||||
}
|
||||
|
||||
const sector_raw = overview.sector orelse "Unknown";
|
||||
var sector_buf: [64]u8 = undefined;
|
||||
const sector_str = cli.fmt.toTitleCase(§or_buf, sector_raw);
|
||||
const country_str = overview.country orelse "US";
|
||||
const geo_str = if (std.mem.eql(u8, country_str, "USA")) "US" else country_str;
|
||||
|
||||
const asset_class_str = blk: {
|
||||
if (overview.asset_type) |at| {
|
||||
if (std.mem.eql(u8, at, "ETF")) break :blk "ETF";
|
||||
if (std.mem.eql(u8, at, "Mutual Fund")) break :blk "Mutual Fund";
|
||||
}
|
||||
if (overview.market_cap) |mc_str| {
|
||||
const mc = std.fmt.parseInt(u64, mc_str, 10) catch 0;
|
||||
if (mc >= 10_000_000_000) break :blk "US Large Cap";
|
||||
if (mc >= 2_000_000_000) break :blk "US Mid Cap";
|
||||
break :blk "US Small Cap";
|
||||
}
|
||||
break :blk "US Large Cap";
|
||||
};
|
||||
const meta = deriveMetadata(overview, §or_buf);
|
||||
|
||||
if (overview.name) |name| {
|
||||
try out.print("# {s}\n", .{name});
|
||||
}
|
||||
try out.print("symbol::{s},sector::{s},geo::{s},asset_class::{s}\n", .{
|
||||
sym, sector_str, geo_str, asset_class_str,
|
||||
sym, meta.sector, meta.geo, meta.asset_class,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -159,34 +172,15 @@ fn enrichPortfolio(allocator: std.mem.Allocator, svc: *zfin.DataService, file_pa
|
|||
if (overview.asset_type) |at| allocator.free(at);
|
||||
}
|
||||
|
||||
const sector_raw = overview.sector orelse "Unknown";
|
||||
var sector_buf: [64]u8 = undefined;
|
||||
const sector_str = cli.fmt.toTitleCase(§or_buf, sector_raw);
|
||||
const country_str = overview.country orelse "US";
|
||||
const geo_str = if (std.mem.eql(u8, country_str, "USA")) "US" else country_str;
|
||||
|
||||
// Determine asset_class from asset type + market cap
|
||||
const asset_class_str = blk: {
|
||||
if (overview.asset_type) |at| {
|
||||
if (std.mem.eql(u8, at, "ETF")) break :blk "ETF";
|
||||
if (std.mem.eql(u8, at, "Mutual Fund")) break :blk "Mutual Fund";
|
||||
}
|
||||
// For common stocks, infer from market cap
|
||||
if (overview.market_cap) |mc_str| {
|
||||
const mc = std.fmt.parseInt(u64, mc_str, 10) catch 0;
|
||||
if (mc >= 10_000_000_000) break :blk "US Large Cap";
|
||||
if (mc >= 2_000_000_000) break :blk "US Mid Cap";
|
||||
break :blk "US Small Cap";
|
||||
}
|
||||
break :blk "US Large Cap";
|
||||
};
|
||||
const meta = deriveMetadata(overview, §or_buf);
|
||||
|
||||
// Comment with the name for readability
|
||||
if (overview.name) |name| {
|
||||
try out.print("# {s}\n", .{name});
|
||||
}
|
||||
try out.print("symbol::{s},sector::{s},geo::{s},asset_class::{s}\n\n", .{
|
||||
sym, sector_str, geo_str, asset_class_str,
|
||||
sym, meta.sector, meta.geo, meta.asset_class,
|
||||
});
|
||||
success += 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const fmt = cli.fmt;
|
|||
pub fn run(allocator: std.mem.Allocator, svc: *zfin.DataService, symbol: []const u8, color: bool, out: *std.Io.Writer) !void {
|
||||
const result = svc.getCandles(symbol) catch |err| switch (err) {
|
||||
zfin.DataError.NoApiKey => {
|
||||
try cli.stderrPrint("Error: TWELVEDATA_API_KEY not set.\n");
|
||||
try cli.stderrPrint("Error: No API key configured for candle data.\n");
|
||||
return;
|
||||
},
|
||||
else => {
|
||||
|
|
@ -46,7 +46,7 @@ pub fn display(candles: []const zfin.Candle, symbol: []const u8, color: bool, ou
|
|||
for (candles) |candle| {
|
||||
var db: [10]u8 = undefined;
|
||||
var vb: [32]u8 = undefined;
|
||||
try cli.setGainLoss(out, color, if (candle.close >= candle.open) @as(f64, 1) else @as(f64, -1));
|
||||
try cli.setGainLoss(out, color, if (candle.close >= candle.open) 1.0 else -1.0);
|
||||
try out.print("{s:>12} {d:>10.2} {d:>10.2} {d:>10.2} {d:>10.2} {s:>12}\n", .{
|
||||
candle.date.format(&db), candle.open, candle.high, candle.low, candle.close, fmt.fmtIntCommas(&vb, candle.volume),
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue