Market Data Service & Analytics Service¶
Overview¶
These services provide unified market data access and advanced analytics for the multi-agent trading system.
- MarketDataService – orchestrates data fetching from multiple vendors with automatic fallback, data quality validation, and multi-level caching.
- AnalyticsService – performs time-series analysis, statistical calculations, correlation analysis, trend detection, and backtesting.
MarketDataService¶
Architecture¶
Client
│
▼
MarketDataService
├─ Cache check (Redis via CacheableMixin)
├─ Vendor 1 ──► fallback to Vendor 2 ──► fallback to Vendor N
├─ Data quality validation & enrichment
└─ Cache write
Initialisation¶
from backend.services import MarketDataService
service = MarketDataService(vendors=[primary_vendor, secondary_vendor])
Methods¶
| Method | Sync | Async | Description |
|---|---|---|---|
get_stock_data(symbol, start_date, end_date) |
✅ | ✅ | OHLCV price data |
get_technical_indicators(symbol, indicators) |
✅ | ✅ | RSI, MACD, etc. |
get_fundamental_data(symbol) |
✅ | ✅ | PE ratio, market cap, etc. |
get_news(symbol, limit) |
✅ | ✅ | News articles |
Vendor Fallback¶
Vendors are tried in order. If a vendor raises an exception the service logs a warning and attempts the next vendor. If all vendors fail a ServiceError is raised.
News Vendor Contract (get_news Response Formats)¶
Vendors implementing get_news must return one of the following formats for correct parsing by NewsAnalyst and SentimentAnalyst:
| Format | Vendor | Structure |
|---|---|---|
| list | FMP | [{"title": str, "date": str, "source": str, "link": str}, ...] |
| dict | Alpha Vantage | {"feed": [{"title": str, "time_published": str, "summary": str, "source": str, "url": str}, ...]} |
| str | Local (finnhub, google, reddit) | Markdown with ### headline (date) or ### headline (source: X) headers |
The shared parser (backend.data.utils.news_parser.parse_news_response) normalizes all formats to NewsItem (headline, date, summary, source, url, relevance_score). The Sentiment Analyst scores both headlines and summaries when available, using a configurable weighted average (default 0.6 headline, 0.4 summary) for richer sentiment analysis.
Data Quality Validation¶
Stock data is automatically validated:
- Null responses raise DataQualityError
- Empty lists raise DataQualityError
- OHLCV data missing required fields emits a warning
- All dict responses are enriched with _metadata (symbol, source, timestamp)
Caching¶
| Data Type | TTL |
|---|---|
| Stock data | 5 minutes |
| Technical indicators | 5 minutes |
| Fundamental data | 1 hour |
| News | 5 minutes |
AnalyticsService¶
Initialisation¶
Volatility Analysis¶
result = analytics.calculate_volatility(prices, window=20)
# Returns: volatility, daily_std, var_95, var_99, rolling_volatility,
# window, num_observations
# Cached version keyed by symbol:
result = analytics.get_volatility("AAPL", prices, window=20)
Correlation Analysis¶
result = analytics.calculate_correlation(
{"AAPL": aapl_prices, "GOOG": goog_prices, "MSFT": msft_prices},
method="pearson", # or "spearman"
)
# Returns: symbols, matrix, pairs, method
Trend Analysis¶
result = analytics.analyse_trends(prices, short_window=20, long_window=50)
# Returns: trend (bullish/bearish/neutral), trend_strength, sma_short,
# sma_long, support, resistance, slope
Statistical Metrics¶
result = analytics.calculate_statistics(prices)
# Returns: count, mean, median, std, min, max, skewness, kurtosis,
# avg_return, cumulative_return
Beta Calculation¶
Backtesting¶
The service delegates to the existing BacktestEngine:
result = analytics.run_backtest(
signal_aggregator=aggregator,
symbols=["AAPL", "GOOG"],
start_date="2024-01-01",
end_date="2024-06-30",
)
# Returns: win_rate, sharpe_ratio, max_drawdown, profit_factor, trades
MarketIntelligenceService¶
Overview¶
The MarketIntelligenceService aggregates market-wide data for the /market page. It composes data from MarketDataService, the vendor routing layer, AnalyticsService, and EconomicCalendar into page-ready payloads. All results are cached (Redis + in-memory) and computed on the fly — no additional database tables are required.
Initialisation¶
from backend.services.market_intelligence_service import MarketIntelligenceService
from backend.services.market_data_service import MarketDataService
service = MarketIntelligenceService(market_data_service=MarketDataService(vendors=[...]))
Endpoints¶
All endpoints are served under /api/v1/market/.
| Endpoint | Method | Description | Cache TTL |
|---|---|---|---|
/overview |
GET | Major index prices (SPY, QQQ, DIA, IWM, VIX, TLT, GLD) | 60s |
/sectors |
GET | 11 GICS sector ETF performance (daily, 5d, 1m, YTD) | 5 min |
/breadth |
GET | Advance/decline ratio, VIX regime, 52w highs/lows | 5 min |
/fear-greed |
GET | Composite Fear & Greed index (0-100) with component breakdown | 5 min |
/calendar |
GET | Recent and upcoming FRED economic releases | 1 hour |
/compare?symbols=A,B |
GET | Side-by-side ticker comparison (price, P/E, RSI, beta, etc.) | 5 min |
/news?symbols=A,B&limit=50 |
GET | Aggregated news feed, optionally filtered by symbols | 5 min |
/sentiment/{symbol}?days=30 |
GET | Daily average sentiment trend for a ticker | 10 min |
Fear & Greed Index¶
A composite score from 0 (Extreme Fear) to 100 (Extreme Greed) computed from four components:
| Component | Weight | Logic |
|---|---|---|
| VIX Level | 30% | VIX 10 → score 100, VIX 40+ → score 0 |
| Market Momentum | 25% | SPY deviation from 125-day SMA |
| Sector Breadth | 20% | Fraction of 11 sector ETFs advancing |
| Safe-Haven Demand | 25% | TLT deviation from 20-day SMA (inverse) |
Labels: Extreme Fear (0-20), Fear (21-40), Neutral (41-60), Greed (61-80), Extreme Greed (81-100).
Sector ETFs Tracked¶
| ETF | Sector |
|---|---|
| XLB | Materials |
| XLC | Communication Services |
| XLE | Energy |
| XLF | Financials |
| XLI | Industrials |
| XLK | Technology |
| XLP | Consumer Staples |
| XLRE | Real Estate |
| XLU | Utilities |
| XLV | Health Care |
| XLY | Consumer Discretionary |
Data Sources¶
- Index/ETF prices: fetched via
route_to_vendor("get_stock_data", ...)with automatic vendor fallback - Economic calendar: FRED API via
EconomicCalendar(requiresFRED_API_KEY) - News:
MarketDataService.get_news_async()for stock-specific,route_to_vendor("get_global_news")for market-wide - Sentiment: keyword heuristic fallback when the DeBERTa-v3 model is unavailable
Frontend¶
The Market Intelligence page is accessible at /market with four tabs:
- Overview: Indices cards, Fear & Greed gauge, sector heatmap, market breadth panel
- News & Sentiment: Filterable news feed alongside a sentiment trend chart
- Calendar: Economic calendar with upcoming and recent FRED releases
- Compare: Side-by-side ticker comparison with key metrics table
Dependencies¶
BaseServiceandCacheableMixinfromredhound.servicesnumpyfor numerical operations- Redis for caching (via
CacheableMixin) BacktestEnginefor backtesting supportEconomicCalendarfor FRED API integration (MarketIntelligenceService)pandasfor time-series computations (MarketIntelligenceService)