feat(quote): add as_of last-trade time and flag stale quotes

Quotes had no timestamp, so a suspended stock's last price looked
current: Yahoo returns WIKA at 204 with regularMarketTime 2025-02-17.
Add `as_of` (RFC 3339 in WIB) from MSN `timeLastTraded` / Yahoo
`regularMarketTime`, also on screener rows. The table prints a note
under any quote whose last trade is over a week old. The field is
additive and defaults to null, so existing cache entries still load.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ld3fDSDiBzAaQvgZJX5NKM
This commit is contained in:
Claude 2026-10-02 14:32:16 +00:00
commit 4ddf1118d4
No known key found for this signature in database
8 changed files with 98 additions and 2 deletions

View file

@ -19,6 +19,13 @@ pub(crate) fn idx_offset() -> FixedOffset {
FixedOffset::east_opt(IDX_UTC_OFFSET_SECS).expect("valid WIB offset")
}
/// Parse a provider's RFC 3339 trade time and express it in WIB.
pub(crate) fn parse_as_of(raw: Option<&str>) -> Option<chrono::DateTime<FixedOffset>> {
chrono::DateTime::parse_from_rfc3339(raw?)
.ok()
.map(|t| t.with_timezone(&idx_offset()))
}
pub trait QuoteProvider {
fn quote(&self, symbol: &str) -> Result<Quote, IdxError>;
}