zfin/src/models/etf_profile.zig

70 lines
2.2 KiB
Zig

const Date = @import("date.zig").Date;
/// Top holding in an ETF.
pub const Holding = struct {
symbol: ?[]const u8 = null,
name: []const u8,
weight: f64,
};
/// Sector allocation in an ETF.
pub const SectorWeight = struct {
name: []const u8,
weight: f64,
};
/// ETF profile and metadata.
pub const EtfProfile = struct {
symbol: []const u8,
name: ?[]const u8 = null,
asset_class: ?[]const u8 = null,
/// Expense ratio as a decimal (e.g., 0.0003 for 0.03%)
expense_ratio: ?f64 = null,
/// Net assets in USD
net_assets: ?f64 = null,
/// Morningstar-style category (e.g., "Large Blend")
category: ?[]const u8 = null,
/// Investment focus description
description: ?[]const u8 = null,
/// Top holdings
holdings: ?[]const Holding = null,
/// Number of total holdings in the fund
total_holdings: ?u32 = null,
/// Sector allocations
sectors: ?[]const SectorWeight = null,
/// Dividend yield as decimal (e.g., 0.0111 for 1.11%)
dividend_yield: ?f64 = null,
/// Portfolio turnover as decimal
portfolio_turnover: ?f64 = null,
/// Fund inception date
inception_date: ?Date = null,
/// Whether the fund is leveraged
leveraged: bool = false,
/// Returns true if the profile contains meaningful ETF data.
/// Non-ETF symbols return empty profiles from Alpha Vantage.
pub fn isEtf(self: EtfProfile) bool {
return self.expense_ratio != null or
self.net_assets != null or
self.holdings != null or
self.sectors != null or
self.total_holdings != null;
}
};
const std = @import("std");
test "isEtf" {
// Empty profile -> not an ETF
const empty = EtfProfile{ .symbol = "AAPL" };
try std.testing.expect(!empty.isEtf());
// Has expense_ratio -> is ETF
const with_er = EtfProfile{ .symbol = "VTI", .expense_ratio = 0.0003 };
try std.testing.expect(with_er.isEtf());
// Has net_assets -> is ETF
const with_na = EtfProfile{ .symbol = "SPY", .net_assets = 500_000_000_000 };
try std.testing.expect(with_na.isEtf());
// Has total_holdings -> is ETF
const with_th = EtfProfile{ .symbol = "QQQ", .total_holdings = 100 };
try std.testing.expect(with_th.isEtf());
}