refactor(msn): remove HistoryProvider — Finance/Charts 404s on all IDX stocks

MSN Finance/Charts does not serve OHLCV data for XIDX stocks (returns 404).
Following the FP principle of not exposing capabilities a provider cannot fulfil:

- Remove impl HistoryProvider for MsnProvider entirely
- Remove fetch_charts from MsnClient
- Remove parse_chart_history, resample_history, trim_history_to_period from map.rs
- Remove MsnChart, ChartSeries, RawChart from raw_types.rs
- Remove parse_history_from_str, parse_close_only_history from parse.rs
- Decouple HistoryProvider from MarketDataProvider trait bound
- Add history_provider() factory: returns None for MSN, Some(Yahoo) for Yahoo
- CLI gates History/Technical on history_provider(), fails fast for MSN
- MSN mock returns Err(Unsupported); tests verify the behaviour explicitly
This commit is contained in:
Ciphercat 2026-03-06 20:55:35 +00:00
commit 6d6d51a04f
8 changed files with 71 additions and 504 deletions

View file

@ -6,9 +6,8 @@ use serde::de::DeserializeOwned;
use crate::error::IdxError;
use super::raw_types::{
KeyRatios, MsnQuote, RawChart, RawEarningsResponse, RawEquity, RawFinancialStatement,
RawInsight, RawNewsFeed, RawScreenerResponse, RawSentiment, ScreenerFilter, ScreenerOrder,
ScreenerRequest,
KeyRatios, MsnQuote, RawEarningsResponse, RawEquity, RawFinancialStatement, RawInsight,
RawNewsFeed, RawScreenerResponse, RawSentiment, ScreenerFilter, ScreenerOrder, ScreenerRequest,
};
use super::symbols::resolve_msn_id;
@ -182,19 +181,6 @@ impl MsnClient {
self.get_json(&url, symbol, "earnings")
}
pub(super) fn fetch_charts(
&self,
symbol: &str,
chart_type: &str,
) -> Result<Vec<RawChart>, IdxError> {
let id =
resolve_msn_id(symbol).ok_or_else(|| IdxError::SymbolNotFound(symbol.to_string()))?;
let url = format!(
"{MSN_ASSETS_BASE_URL}Finance/Charts?apikey={MSN_API_KEY}&ids={id}&chartType={chart_type}&wrapodata=false"
);
self.get_json(&url, symbol, "charts")
}
pub(super) fn fetch_sentiment(&self, symbol: &str) -> Result<Vec<RawSentiment>, IdxError> {
let id =
resolve_msn_id(symbol).ok_or_else(|| IdxError::SymbolNotFound(symbol.to_string()))?;