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

@ -5,23 +5,22 @@ mod raw_types;
mod symbols;
use crate::api::types::{
Bar, CompanyProfile, EarningsReport, FinancialStatements, Fundamentals, InsightData, Interval,
NewsItem, Period, Quote, SentimentData,
CompanyProfile, EarningsReport, FinancialStatements, Fundamentals, InsightData, NewsItem,
Quote, SentimentData,
};
use crate::api::{
EarningsProvider, FinancialsProvider, FundamentalsProvider, HistoryProvider, InsightsProvider,
NewsProvider, ProfileProvider, QuoteProvider, SentimentProvider,
EarningsProvider, FinancialsProvider, FundamentalsProvider, InsightsProvider, NewsProvider,
ProfileProvider, QuoteProvider, SentimentProvider,
};
use crate::error::IdxError;
use client::MsnClient;
use map::{
parse_chart_history, parse_earnings, parse_financial_statements, parse_fundamentals,
parse_insights, parse_news, parse_profile, parse_quote, parse_screener_results,
parse_sentiment,
parse_earnings, parse_financial_statements, parse_fundamentals, parse_insights, parse_news,
parse_profile, parse_quote, parse_screener_results, parse_sentiment,
};
pub(crate) use parse::{parse_fundamentals_from_str, parse_history_from_str, parse_quote_from_str};
pub(crate) use parse::{parse_fundamentals_from_str, parse_quote_from_str};
pub struct MsnProvider {
client: MsnClient,
@ -60,31 +59,6 @@ impl FundamentalsProvider for MsnProvider {
}
}
impl HistoryProvider for MsnProvider {
fn history(
&self,
symbol: &str,
period: &Period,
_interval: &Interval,
) -> Result<Vec<Bar>, IdxError> {
let chart_type = period_to_chart_type(period);
let raw = self.client.fetch_charts(symbol, chart_type).map_err(|e| {
// Finance/Charts returns 404 for IDX stocks — MSN doesn't provide
// OHLCV chart history for the Indonesian exchange (XIDX).
if matches!(e, IdxError::SymbolNotFound(_)) {
IdxError::Unsupported(
"MSN Finance/Charts does not provide OHLCV history for IDX (XIDX) stocks. \
Use --provider yahoo for historical data."
.to_string(),
)
} else {
e
}
})?;
parse_chart_history(symbol, period, &raw)
}
}
impl ProfileProvider for MsnProvider {
fn profile(&self, symbol: &str) -> Result<CompanyProfile, IdxError> {
let raw = self.client.fetch_equities(symbol)?;
@ -126,16 +100,3 @@ impl NewsProvider for MsnProvider {
parse_news(&raw)
}
}
fn period_to_chart_type(period: &Period) -> &'static str {
match period {
Period::OneDay => "1D",
Period::FiveDays => "1W",
Period::OneMonth => "1M",
Period::ThreeMonths => "3M",
Period::SixMonths => "6M",
Period::OneYear => "1Y",
Period::TwoYears => "3Y",
Period::FiveYears => "5Y",
}
}