mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-11-07 09:45:36 +00:00
fix(quote): report missing change and volume as null, not zero
change, change_pct and volume were `unwrap_or(0)` when the provider omitted them (MSN quotes and screener rows; Yahoo with no previous close), so "unknown" read as "unchanged, zero volume". They are now Option fields that serialize as null when missing. The table shows "-", and the performers screens sort unknown changes last in both directions. Present values are unchanged and cached 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:
parent
4ddf1118d4
commit
135034966c
6 changed files with 106 additions and 62 deletions
|
|
@ -29,8 +29,7 @@ pub(super) fn parse_quote(symbol: &str, quotes: &[MsnQuote]) -> Result<Quote, Id
|
|||
let price = round_price(raw_price);
|
||||
let change = prev_close
|
||||
.map(|previous| price - previous)
|
||||
.or_else(|| quote.price_change.map(round_price))
|
||||
.unwrap_or(0);
|
||||
.or_else(|| quote.price_change.map(round_price));
|
||||
|
||||
let ticker = quote
|
||||
.symbol
|
||||
|
|
@ -57,8 +56,8 @@ pub(super) fn parse_quote(symbol: &str, quotes: &[MsnQuote]) -> Result<Quote, Id
|
|||
symbol: normalized_symbol(symbol, &ticker),
|
||||
price,
|
||||
change,
|
||||
change_pct: quote.price_change_percent.unwrap_or(0.0),
|
||||
volume: round_u64(quote.accumulated_volume).unwrap_or(0),
|
||||
change_pct: quote.price_change_percent,
|
||||
volume: round_u64(quote.accumulated_volume),
|
||||
market_cap: round_u64(quote.market_cap),
|
||||
week52_high: quote.price_52w_high.map(round_price),
|
||||
week52_low: quote.price_52w_low.map(round_price),
|
||||
|
|
@ -592,8 +591,7 @@ pub(super) fn parse_screener_results(raw: &RawScreenerResponse) -> Result<Vec<Qu
|
|||
let prev_close = q.price_previous_close.map(round_price);
|
||||
let change = prev_close
|
||||
.map(|pc| price - pc)
|
||||
.or_else(|| q.price_change.map(round_price))
|
||||
.unwrap_or(0);
|
||||
.or_else(|| q.price_change.map(round_price));
|
||||
let ticker = q
|
||||
.symbol
|
||||
.as_deref()
|
||||
|
|
@ -617,8 +615,8 @@ pub(super) fn parse_screener_results(raw: &RawScreenerResponse) -> Result<Vec<Qu
|
|||
symbol: normalized_symbol(&ticker, &ticker),
|
||||
price,
|
||||
change,
|
||||
change_pct: q.price_change_percent.unwrap_or(0.0),
|
||||
volume: round_u64(q.accumulated_volume).unwrap_or(0),
|
||||
change_pct: q.price_change_percent,
|
||||
volume: round_u64(q.accumulated_volume),
|
||||
market_cap: round_u64(q.market_cap),
|
||||
week52_high: q.price_52w_high.map(round_price),
|
||||
week52_low: q.price_52w_low.map(round_price),
|
||||
|
|
@ -868,7 +866,7 @@ mod tests {
|
|||
assert_eq!(quotes.len(), 2);
|
||||
assert_eq!(quotes[0].symbol, "BBCA.JK");
|
||||
assert_eq!(quotes[0].price, 9_875);
|
||||
assert_eq!(quotes[0].change, 117);
|
||||
assert_eq!(quotes[0].change, Some(117));
|
||||
assert_eq!(quotes[0].market_cap, Some(1_215_200_000_000_000));
|
||||
assert_eq!(quotes[0].range_signal.as_deref(), Some("upper"));
|
||||
assert_eq!(quotes[0].avg_volume, Some(10_000_000));
|
||||
|
|
@ -957,6 +955,18 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_change_and_volume_stay_missing() {
|
||||
let raw: Vec<MsnQuote> = serde_json::from_str(r#"[{"symbol":"BBCA","price":6100.0}]"#)
|
||||
.expect("quote should deserialize");
|
||||
let quote = parse_quote("BBCA.JK", &raw).expect("quote parsed");
|
||||
assert_eq!(quote.change, None);
|
||||
assert_eq!(quote.change_pct, None);
|
||||
assert_eq!(quote.volume, None);
|
||||
let json = serde_json::to_value("e).unwrap();
|
||||
assert!(json["change_pct"].is_null() && json["volume"].is_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn listed_quote_without_price_is_no_market_data() {
|
||||
let raw: Vec<MsnQuote> = serde_json::from_str(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue