refresh fixes
This commit is contained in:
parent
32cc139ef1
commit
c596d8c12f
1 changed files with 33 additions and 25 deletions
58
src/main.zig
58
src/main.zig
|
|
@ -261,7 +261,22 @@ fn upperDupe(allocator: std.mem.Allocator, s: []const u8) ![]u8 {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format as percentage string for XML (e.g., 0.1234 -> "12.34000")
|
fn printRateLimitWait(svc: *zfin.DataService, stdout: *std.Io.Writer) !void {
|
||||||
|
if (svc.estimateWaitSeconds()) |wait| {
|
||||||
|
if (wait > 0) {
|
||||||
|
try stdout.print("\n (rate limit -- waiting {d}s)\n ", .{wait});
|
||||||
|
try stdout.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutual funds typically have 5-letter tickers ending in X.
|
||||||
|
/// These don't have quarterly earnings on Finnhub.
|
||||||
|
fn isMutualFund(symbol: []const u8) bool {
|
||||||
|
return symbol.len == 5 and symbol[4] == 'X';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format as percentage (e.g., 0.1234 -> "12.34000"), or "null" if absent.
|
||||||
fn fmtPct(arena: std.mem.Allocator, value: ?f64) []const u8 {
|
fn fmtPct(arena: std.mem.Allocator, value: ?f64) []const u8 {
|
||||||
if (value) |v| return std.fmt.allocPrint(arena, "{d:.5}", .{v * 100.0}) catch "null";
|
if (value) |v| return std.fmt.allocPrint(arena, "{d:.5}", .{v * 100.0}) catch "null";
|
||||||
return "null";
|
return "null";
|
||||||
|
|
@ -345,16 +360,11 @@ fn refresh(allocator: std.mem.Allocator) !void {
|
||||||
};
|
};
|
||||||
defer allocator.free(data);
|
defer allocator.free(data);
|
||||||
|
|
||||||
const portfolio = zfin.cache.deserializePortfolio(allocator, data) catch {
|
var portfolio = zfin.cache.deserializePortfolio(allocator, data) catch {
|
||||||
log.err("failed to parse portfolio", .{});
|
log.err("failed to parse portfolio", .{});
|
||||||
return error.ParseFailed;
|
return error.ParseFailed;
|
||||||
};
|
};
|
||||||
defer {
|
defer portfolio.deinit();
|
||||||
for (portfolio.lots) |*lot| {
|
|
||||||
if (lot.note) |n| allocator.free(n);
|
|
||||||
}
|
|
||||||
allocator.free(portfolio.lots);
|
|
||||||
}
|
|
||||||
|
|
||||||
var symbols = std.StringHashMap(void).init(allocator);
|
var symbols = std.StringHashMap(void).init(allocator);
|
||||||
defer symbols.deinit();
|
defer symbols.deinit();
|
||||||
|
|
@ -382,21 +392,13 @@ fn refresh(allocator: std.mem.Allocator) !void {
|
||||||
var it = symbols.iterator();
|
var it = symbols.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
const sym = entry.key_ptr.*;
|
const sym = entry.key_ptr.*;
|
||||||
|
|
||||||
// Check if we need to wait for rate limits
|
|
||||||
if (svc.estimateWaitSeconds()) |wait| {
|
|
||||||
if (wait > 0) {
|
|
||||||
try stdout.print(" (rate limit -- waiting {d}s)\n", .{wait});
|
|
||||||
try stdout.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try stdout.print("{s}: ", .{sym});
|
try stdout.print("{s}: ", .{sym});
|
||||||
try stdout.flush();
|
try stdout.flush();
|
||||||
|
|
||||||
var sym_ok = true;
|
var sym_ok = true;
|
||||||
|
|
||||||
// Candles
|
// Candles
|
||||||
|
try printRateLimitWait(&svc, stdout);
|
||||||
if (svc.getCandles(sym)) |result| {
|
if (svc.getCandles(sym)) |result| {
|
||||||
allocator.free(result.data);
|
allocator.free(result.data);
|
||||||
try stdout.print("candles ok", .{});
|
try stdout.print("candles ok", .{});
|
||||||
|
|
@ -406,21 +408,27 @@ fn refresh(allocator: std.mem.Allocator) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dividends
|
// Dividends
|
||||||
|
try printRateLimitWait(&svc, stdout);
|
||||||
if (svc.getDividends(sym)) |result| {
|
if (svc.getDividends(sym)) |result| {
|
||||||
allocator.free(result.data);
|
zfin.Dividend.freeSlice(allocator, result.data);
|
||||||
try stdout.print(", dividends ok", .{});
|
try stdout.print(", dividends ok", .{});
|
||||||
} else |err| {
|
} else |err| {
|
||||||
try stdout.print(", dividends FAILED ({s})", .{@errorName(err)});
|
try stdout.print(", dividends FAILED ({s})", .{@errorName(err)});
|
||||||
sym_ok = false;
|
sym_ok = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Earnings
|
// Earnings (skip for mutual funds — they don't report quarterly earnings)
|
||||||
if (svc.getEarnings(sym)) |result| {
|
if (!isMutualFund(sym)) {
|
||||||
allocator.free(result.data);
|
try printRateLimitWait(&svc, stdout);
|
||||||
try stdout.print(", earnings ok", .{});
|
if (svc.getEarnings(sym)) |result| {
|
||||||
} else |err| {
|
allocator.free(result.data);
|
||||||
try stdout.print(", earnings FAILED ({s})", .{@errorName(err)});
|
try stdout.print(", earnings ok", .{});
|
||||||
sym_ok = false;
|
} else |err| {
|
||||||
|
try stdout.print(", earnings FAILED ({s})", .{@errorName(err)});
|
||||||
|
sym_ok = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try stdout.print(", earnings skipped (fund)", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
try stdout.print("\n", .{});
|
try stdout.print("\n", .{});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue