End-to-end Market Risk Engine with a FastAPI backend and a modern React/TypeScript frontend.
Built to feel like a real risk desk: VaR, CVaR, stress testing, rich analytics, and VaR backtesting.
Best experienced on desktop for the full multi-panel analytics layout.
Designed as a realistic, production-style risk stack: data ingestion, cleaning, portfolio construction, risk analytics, visualization, and export β all in one repo.
Premium, end-to-end Market Risk Engine with:
- A FastAPI service for high-performance risk calculations.
- A React 19 + Vite SPA with a fintech-inspired dark theme.
- Integrated Google Sheets opt-in and deploy-ready configs (Railway + GitHub Pages).
- System Overview
- Core Capabilities
- Frontend Experience
- Backend API Reference
- Frontend Pages Reference
- Methods & Assumptions
- Getting Started
- Running Tests
- Configuration
- Typical Workflow
- Design Principles
- License
- Backend (
backend/): FastAPI service providing market data, risk metrics, VaR/CVaR, stress tests, and VaR backtesting - Frontend (
frontend/): Fintech-style dashboard (React + TypeScript + Vite + Tailwind + shadcn/ui) for interactive exploration - Data Source: Yahoo Finance via
yfinance(daily bars, broad symbol coverage)
project-root/
backend/ FastAPI backend (Python)
app/
api/ ββ REST endpoints (market, portfolio, risk, stress, backtest)
core/ ββ config + logging
models/ ββ Pydantic schemas (requests/responses)
services/ ββ risk, VaR, stress, data, backtest business logic
utils/ ββ caching, date & math helpers
backend_data/ ββ raw & processed Parquet caches
tests/ ββ pytest suites (risk, VaR, stress)
frontend/ React 19 + TypeScript + Vite SPA
src/
app/ ββ router, query client, providers
pages/ ββ Portfolio, MarketData, RiskMetrics, VaR, StressTests, Backtesting, Export, Overview
components/ ββ layout, charts, tables, forms, UI
lib/ ββ typed API client, types, validators, utils, constants
For deeper detail:
- Backend: see
backend/README.md - Frontend: see
frontend/README.md
- Annualized return & volatility
- Drawdown profile: max drawdown & drawdown duration
- Sharpe & Sortino ratios
- Tail / distribution metrics: skew, kurtosis, hit ratio, downside deviation, Calmar ratio
- Correlation matrix across assets
- Benchmark analytics: beta, alpha, RΒ², tracking error, information ratio
- Rolling analytics: rolling volatility and rolling Sharpe
- Risk contributions: MCTR/CCTR and % contribution to total risk
- Methods:
- Historical (equal-weighted or EWMA)
- Parametric (Normal or Student-t)
- Monte Carlo (multivariate normal, capped simulations)
- Controls:
- Confidence level and lookback window
- Return type:
return_type(simpleorlog) - Horizon:
horizon_days(β₯ 1) - Drift handling:
drift(ignore/include) - Historical weighting:
hs_weighting(none/ewma) withhs_lambda - Distribution:
parametric_dist(normal/student_t) - Simulation controls:
mc_sims,rolling_window - Currency scaling: optional
portfolio_valuefor currency VaR/CVaR
- Outputs:
- VaR/CVaR as positive loss fractions
- Histograms (realized & simulated), rolling VaR vs realized returns
- Component VaR (when covariance is available)
- Rich
metadataandwarningsfor diagnostics
- Scenario types:
- Quick equity:
EQUITY_-5,EQUITY_-10,EQUITY_-20 - Historical crises:
COVID_CRASH,FINANCIAL_CRISIS,DOTCOM_BUBBLE,BLACK_MONDAY,TAPER_TANTRUM,EUROPEAN_DEBT,FLASH_CRASH(multi-asset aware) - Multi-factor:
STAGFLATION,RATE_SHOCK,LIQUIDITY_CRISIS,CORRELATION_BREAKDOWN - Custom: user-defined symbol shocks (case-insensitive)
- Quick equity:
- Modes:
- Return shock (default): linear model, P&L = weight Γ shock
- Duration/rate shock (advanced, optional): for bonds, rate shocks in bps β price impact via duration / DV01 approximation
- Outputs:
- Portfolio P&L and by-asset P&L
- Net / gross exposure, top loss contributors
- Optional transparency fields per asset:
asset_type,shock_type,rate_bps_applied
- Rolling VaR backtesting with:
lookback,backtest_days,confidence,method,mc_sims
- Validation:
- Kupiec Proportion-of-Failures (POF) test (LR & p-value)
- Exception series and exception table
The frontend is a single-page app that exposes the full engine via a clean, trading-terminal style UI:
| Area | What you see | Why it matters |
|---|---|---|
| Portfolio | Editable table, CSV/JSON upload, quick templates, long/short weights, basic sanity checks | Build realistic books in seconds |
| Market Data | Price & normalized return charts, stats KPIs, missing-data matrix, correlation heatmap | Understand return drivers & data quality |
| Risk Metrics | Vol/Sharpe/Sortino, drawdowns, risk contributions, benchmark analytics | Decompose and attribute portfolio risk |
| VaR / CVaR | Historical / Parametric / MC methods, tails, rolling VaR | Compare methodologies and tail behavior |
| Stress Tests | Quick, historical, and multi-factor scenarios, bond duration mode, tornado/waterfall | Answer βwhat if?β across regimes |
| Backtesting | Exception paths, Kupiec tests, realized vs VaR | Validate if your VaR is doing its job |
| Export | JSON snapshot of config + results, CSV exports | Share and document your risk runs |
π The UI ships with a dark, fintech-inspired theme and responsive layout so it feels at home on large monitors and still works on laptops.
git clone <this-repo-url> # replace with your repo URL
cd "untitled folder 3" # or your chosen project directory- Python 3.11+
cd backend
pip install -r requirements.txt
# Start the API server
uvicorn app.main:app --reload --port 8000- API base URL:
http://localhost:8000 - Swagger UI:
http://localhost:8000/docs
For more backend details and curl examples, see backend/README.md.
- Node.js 18+ and npm
cd ../frontend
npm install
# Optional: configure backend URL
cp .env.example .env
# then edit .env and set:
# VITE_API_URL=http://localhost:8000
npm run dev- App URL:
http://localhost:5173
For more frontend details, see frontend/README.md.
cd backend
pytest -v
# Focused suites
pytest tests/test_risk_service.py -v
pytest tests/test_var_service.py -v
pytest tests/test_stress_service.py tests/test_stress_service_advanced.py -vYou can also run the high-level stress verification script:
python verify_stress_upgrade.pycd frontend
npm testDefined in backend/app/core/config.py and environment variables:
DATA_DIR,RAW_DIR,PROCESSED_DIRβ data/cache directoriesTRADING_DAYS_PER_YEARβ annualization convention (default: 252)MIN_OBS,MAX_FFILL_GAPβ data quality thresholdsDEFAULT_BACKTEST_LOOKBACK,DEFAULT_MC_SIMSβ reasonable risk defaultsCACHE_TTL_SECONDSβ in-memory cache TTL
.env/.env.local:VITE_API_URLβ backend base URL
localStorage:- Portfolio, date ranges
- VaR method & confidence, risk settings
- Theme (light/dark)
- Build a portfolio on the Portfolio page (or upload CSV/JSON)
- Inspect market data for your symbols (prices, stats, correlation)
- Run risk metrics to understand vol, drawdown, beta, correlations, contributions
- Estimate VaR/CVaR for tail risk under different methods and horizons
- Apply stress tests (equity, historical, multi-factor, or custom), optionally enabling advanced bond mode
- Backtest VaR to validate model performance with Kupiec tests and exception analysis
- Export a JSON snapshot for documentation or offline analysis
The FastAPI backend exposes the following REST endpoints (all under /api prefix):
| Endpoint | Method | Description | Request Body |
|---|---|---|---|
/api/market/prices |
POST | Fetch historical prices for symbols | symbols[], start, end |
/api/market/correlation |
POST | Compute correlation matrix | symbols[], start, end |
/api/portfolio/normalize |
POST | Normalize portfolio weights | portfolio[] |
/api/risk/metrics |
POST | Compute comprehensive risk metrics | portfolio[], start, end, benchmark_symbol?, risk_free_rate? |
/api/risk/var |
POST | Calculate VaR/CVaR | portfolio[], method, confidence, start, end, lookback?, horizon_days?, return_type?, drift?, parametric_dist?, hs_weighting?, mc_sims? |
/api/stress/run |
POST | Run stress test scenario | portfolio[], scenario, shocks? (for CUSTOM), stress_mode? |
/api/backtest/var |
POST | Backtest VaR model | portfolio[], method, confidence, lookback, backtest_days, start, end, mc_sims? |
/api/optin |
POST | Record opt-in (name/email) | name, email |
/health |
GET | Health check | - |
/ |
GET | API info | - |
/docs |
GET | Swagger UI | - |
Note: All endpoints return JSON. See http://localhost:8000/docs for interactive API documentation.
The React SPA includes the following main pages (accessible via hash routing):
| Page | Route | Purpose | Key Features |
|---|---|---|---|
| Portfolio | /#/portfolio |
Build and manage portfolios | Editable table, CSV/JSON upload, quick templates, weight normalization, pie chart |
| Market Data | /#/market-data |
Inspect price data and quality | Price charts, normalized returns, stats KPIs, missing data matrix, correlation heatmap |
| Risk Metrics | /#/risk-metrics |
Comprehensive risk analytics | Volatility, Sharpe/Sortino, drawdowns, correlation matrix, risk contributions, benchmark analytics, rolling metrics |
| VaR / CVaR | /#/var |
Value at Risk estimation | Historical/Parametric/Monte Carlo methods, tail diagnostics, rolling VaR, multi-confidence ladder, method comparison |
| Stress Tests | /#/stress-tests |
Scenario-based stress testing | Quick equity, historical crises, multi-factor, custom scenarios, duration/rate shock mode, waterfall/tornado charts |
| Backtesting | /#/backtesting |
VaR model validation | Rolling backtest, Kupiec POF test, exception analysis, realized vs VaR charts, CSV/JSON export |
| Export | /#/export |
Export configuration and results | JSON snapshot, CSV exports, selectable sections, markdown/JSON preview |
Note: Portfolio data, date ranges, and VaR settings are persisted in localStorage for convenience.
- Method: Percentile-based on historical returns
- Assumptions:
- Past returns are representative of future risk
- Equal weighting (default) or EWMA weighting (optional)
- No distributional assumptions
- Limitations: Requires sufficient historical data; may underestimate tail risk in calm periods
- Methods: Normal distribution or Student-t distribution
- Assumptions:
- Returns follow specified distribution (Normal or Student-t)
- Constant volatility (no GARCH effects)
- For Student-t: degrees of freedom estimated from data
- Limitations: May underestimate tail risk if returns are non-normal; assumes stationarity
- Method: Multivariate normal simulation
- Assumptions:
- Asset returns follow multivariate normal distribution
- Covariance matrix is stable
- Horizon scaling via
sqrt(horizon_days)approximation for variance
- Limitations:
- Multivariate normal may not capture tail dependencies
- Simulations capped at 10,000 for performance
- Requires asset-level returns (not just portfolio returns)
- Annualization: Uses 252 trading days per year (configurable)
- Return Types: Supports both simple and log returns (log returns default for risk metrics)
- Benchmark Analytics: Requires benchmark symbol to be in portfolio or fetched separately
- Risk Contributions: Based on sample covariance matrix; assumes linear portfolio structure
- Return Shock Mode (default): Linear model
P&L = weight Γ shock; no correlation effects - Duration/Rate Shock Mode (advanced):
- Bond price impact approximated via
ΞP/P β -duration Γ Ξy(where Ξy in decimal) - Falls back to return shock if duration/DV01 not provided
- Bond price impact approximated via
- Historical Scenarios: Uniform shocks (approximations); not actual historical replay
- Multi-Factor Scenarios: Asset type inferred from symbol (e.g., TLT=bond, GLD=commodity)
- Data Source: Yahoo Finance via
yfinance(daily bars) - Missing Data: Forward-fills gaps up to 2 trading days; symbols with excessive gaps are filtered
- Minimum Observations: Requires β₯60 observations for reliable metrics (configurable)
- Symbol Format:
- US stocks: plain symbol (e.g.,
AAPL) - NSE stocks: append
.NS(e.g.,RELIANCE.NS) - Indices: use
^prefix (e.g.,^NSEIfor NIFTY 50)
- US stocks: plain symbol (e.g.,
- Rolling Window: Uses expanding window (all prior data up to each test date)
- Exception Definition: Realized return < -VaR threshold
- Kupiec Test: Assumes exceptions follow binomial distribution; requires sufficient backtest days for statistical power
- No Real-Time Data: All data is historical (end-of-day)
- No Options/Derivatives: Only handles stocks, ETFs, indices
- No Transaction Costs: All calculations assume frictionless trading
- No Liquidity Risk: Assumes all positions can be liquidated instantly
- Single Currency: No explicit FX risk handling (assumes USD or local currency)
- Static Portfolio: No rebalancing logic; portfolio weights assumed constant over time
- Realistic, not toy: Implements commonly used techniques in professional risk management (vol/drawdown, Sharpe/Sortino, VaR variants, EWMA, Kupiec).
- Safe defaults: Caps Monte Carlo simulations, warns on small samples, and handles missing/failed symbols gracefully.
- Transparent: Rich metadata and warnings in API responses make it clear how numbers are computed and when they may be unstable.
- Extensible: Clear layering between routes, services, and schemas so new models/scenarios can be added with minimal friction.
This project is provided as-is for educational and research purposes.
Β© 2025 Tanishq Prabhu. All rights reserved.