switch earnings cache ttl to 30 days + day after earnings
This commit is contained in:
parent
78a15b89be
commit
6a680a2381
3 changed files with 22 additions and 6 deletions
|
|
@ -40,7 +40,7 @@ zfin aggregates data from multiple free-tier APIs. Each provider is used for the
|
|||
| Dividends | Polygon | `POLYGON_API_KEY` | 5 req/min | 7 days |
|
||||
| Splits | Polygon | `POLYGON_API_KEY` | 5 req/min | 7 days |
|
||||
| Options chains | CBOE | None required | ~30 req/min (self-imposed) | 1 hour |
|
||||
| Earnings | Finnhub | `FINNHUB_API_KEY` | 60 req/min | 24 hours |
|
||||
| Earnings | Finnhub | `FINNHUB_API_KEY` | 60 req/min | 30 days* |
|
||||
| ETF profiles | Alpha Vantage | `ALPHAVANTAGE_API_KEY` | 25 req/day | 30 days |
|
||||
|
||||
### TwelveData
|
||||
|
|
@ -127,10 +127,12 @@ Cache files use [SRF](https://github.com/lobo/srf) (Simple Record Format), a lin
|
|||
| Dividends | 7 days | Declared well in advance |
|
||||
| Splits | 7 days | Rare corporate events |
|
||||
| Options | 1 hour | Prices change continuously during market hours |
|
||||
| Earnings | 24 hours | Quarterly events, estimates update periodically |
|
||||
| Earnings | 30 days* | Quarterly events; smart refresh after announcements |
|
||||
| ETF profiles | 30 days | Holdings/weights change slowly |
|
||||
| Quotes | Never cached | Intended for live price checks |
|
||||
|
||||
\* **Earnings smart refresh:** Even within the 30-day TTL, cached earnings are automatically re-fetched when an earnings date has passed but the cache still has no actual results for it. This ensures results appear promptly after an announcement without wasteful daily polling.
|
||||
|
||||
Manual refresh (`r` / `F5` in TUI) invalidates the cache for the current tab's data before re-fetching.
|
||||
|
||||
### Rate limiting
|
||||
|
|
|
|||
4
src/cache/store.zig
vendored
4
src/cache/store.zig
vendored
|
|
@ -28,8 +28,8 @@ pub const Ttl = struct {
|
|||
pub const splits: i64 = 7 * 24 * 3600;
|
||||
/// Options chains refresh hourly
|
||||
pub const options: i64 = 3600;
|
||||
/// Earnings refresh daily
|
||||
pub const earnings: i64 = 24 * 3600;
|
||||
/// Earnings refresh monthly, with smart refresh after announcements
|
||||
pub const earnings: i64 = 30 * 24 * 3600;
|
||||
/// ETF profiles refresh monthly
|
||||
pub const etf_profile: i64 = 30 * 24 * 3600;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -248,20 +248,34 @@ pub const DataService = struct {
|
|||
|
||||
/// Fetch earnings history for a symbol (5 years back, 1 year forward).
|
||||
/// Checks cache first; fetches from Finnhub if stale/missing.
|
||||
/// Smart refresh: even if cache is fresh, re-fetches when a past earnings
|
||||
/// date has no actual results yet (i.e. results just came out).
|
||||
pub fn getEarnings(self: *DataService, symbol: []const u8) DataError!struct { data: []EarningsEvent, source: Source, timestamp: i64 } {
|
||||
var s = self.store();
|
||||
const today = todayDate();
|
||||
|
||||
const cached_raw = s.readRaw(symbol, .earnings) catch return DataError.CacheError;
|
||||
if (cached_raw) |data| {
|
||||
defer self.allocator.free(data);
|
||||
if (cache.Store.isFreshData(data, self.allocator)) {
|
||||
const events = cache.Store.deserializeEarnings(self.allocator, data) catch null;
|
||||
if (events) |e| return .{ .data = e, .source = .cached, .timestamp = s.getMtime(symbol, .earnings) orelse std.time.timestamp() };
|
||||
if (events) |e| {
|
||||
// Check if any past/today earnings event is still missing actual results.
|
||||
// If so, the announcement likely just happened — force a refresh.
|
||||
const needs_refresh = for (e) |ev| {
|
||||
if (ev.actual == null and !today.lessThan(ev.date)) break true;
|
||||
} else false;
|
||||
|
||||
if (!needs_refresh) {
|
||||
return .{ .data = e, .source = .cached, .timestamp = s.getMtime(symbol, .earnings) orelse std.time.timestamp() };
|
||||
}
|
||||
// Stale: free cached events and re-fetch below
|
||||
self.allocator.free(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var fh = try self.getFinnhub();
|
||||
const today = todayDate();
|
||||
const from = today.subtractYears(5);
|
||||
const to = today.addDays(365);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue