Skip to content

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

from backend.services import AnalyticsService

analytics = AnalyticsService()

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

beta = analytics.calculate_beta(asset_prices, benchmark_prices)

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 (requires FRED_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

  • BaseService and CacheableMixin from redhound.services
  • numpy for numerical operations
  • Redis for caching (via CacheableMixin)
  • BacktestEngine for backtesting support
  • EconomicCalendar for FRED API integration (MarketIntelligenceService)
  • pandas for time-series computations (MarketIntelligenceService)