Multi-Method VaR Calculator for FX Portfolios
Production-ready REST API for Value-at-Risk calculations. Supports spot FX and options with two-tailed VaR, stress testing, and P&L distribution visualization.
Version: 2.1.0 Status: Production (AKS) Port: 8084 Namespace: gzc-risk
| Resource | URL |
|---|---|
| Swagger UI | http://localhost:8084/docs |
| ReDoc | http://localhost:8084/redoc |
| OpenAPI Spec | http://localhost:8084/openapi.json |
| Health Check | http://localhost:8084/health |
| Method | Description | Best For | Speed |
|---|---|---|---|
| Historical | 500-day empirical distribution | Regulatory reporting, fat tails | 0.1ms |
| Monte Carlo | 10K simulated paths (Cholesky) | Correlation modeling | 6-7ms |
| Parametric | Variance-covariance (normal) | Quick estimates | 0.1ms |
- Two-Tailed VaR: Upside (potential gain) and downside (potential loss)
- Confidence Levels: 95% and 99%
- CVaR (Expected Shortfall): Average loss beyond VaR
- Component VaR: Marginal risk contribution by position
- Method Comparison: Compare all three methods with convergence analysis
- Garman-Kohlhagen delta calculation
- RR/BF to Strike Vol conversion:
sigma_call = ATM + RR/2 + STR - Variance Interpolation for term structure
- Optimized Vol Surface: Only fetches needed tenor segments (6 tickers per option)
- Vega Approximation:
P&L = Vega x vol_shift
- 6 Predefined Scenarios: GFC 2008, COVID 2020, Fed +100bp, EUR Crisis, China Devalue, Risk-Off
- Custom Scenarios: Define your own currency shocks
- Impact Analysis: Per-currency and portfolio-level impacts
- P&L Distribution: Full histogram for visualization
- Gaussian Fit: Mean, std, skewness, kurtosis
- Per-Position Breakdown: Individual position distributions
- Method Comparison: Side-by-side distribution comparison
- Structured JSON Logging: Request/response with duration_ms
- CORS Enabled: Cross-origin requests supported
- Auto-Generated Docs: Swagger UI and ReDoc
| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check + available methods |
/var |
POST | Calculate VaR (select method) |
/var/compare |
POST | Compare all VaR methods |
/var/component |
POST | Component VaR breakdown |
/var/distribution |
POST | P&L distribution for visualization |
/var/option |
POST | Option VaR (sticky-delta) |
/var/stress |
POST | Stress test scenarios |
/var/scenarios |
GET | List predefined scenarios |
/docs |
GET | Swagger UI |
/redoc |
GET | ReDoc documentation |
/openapi.json |
GET | OpenAPI specification |
# Port-forward to local
kubectl port-forward svc/var-service 8084:8084 -n gzc-risk
# Test health
curl http://localhost:8084/health
# Open Swagger UI
open http://localhost:8084/docscd var-service
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cd app
uvicorn main:app --reload --port 8084# Build for AKS (linux/amd64)
docker buildx build --platform linux/amd64 -t gzcacr.azurecr.io/var-service:latest .
# Push to ACR
docker push gzcacr.azurecr.io/var-service:latest
# Deploy
kubectl rollout restart deployment/var-service -n gzc-riskcurl -X POST http://localhost:8084/var \
-H "Content-Type: application/json" \
-d '{
"positions": [
{"ticker": "EURUSD", "direction": "SHORT", "notional": 10000000},
{"ticker": "USDJPY", "direction": "SHORT", "notional": 10000000}
],
"portfolio_value": 50000000,
"method": "historical"
}'curl -X POST http://localhost:8084/var/compare \
-H "Content-Type: application/json" \
-d '{
"positions": [
{"ticker": "EURUSD", "direction": "SHORT", "notional": 10000000}
],
"portfolio_value": 50000000
}'curl -X POST http://localhost:8084/var/distribution \
-H "Content-Type: application/json" \
-d '{
"positions": [
{"ticker": "EURUSD", "direction": "SHORT", "notional": 10000000}
],
"portfolio_value": 50000000,
"include_positions": true,
"compare_methods": true
}'curl -X POST http://localhost:8084/var/option \
-H "Content-Type: application/json" \
-d '{
"options": [
{
"pair": "EURUSD",
"strike": 1.05,
"expiry_days": 90,
"notional": 10000000,
"is_call": true,
"spot": 1.0425,
"r_dom": 0.0435,
"r_for": 0.029
}
],
"vol_pillars": [
{"tenor": "1M", "atm": 0.068, "rr_25": -0.003, "str_25": 0.002},
{"tenor": "3M", "atm": 0.072, "rr_25": -0.004, "str_25": 0.003},
{"tenor": "6M", "atm": 0.075, "rr_25": -0.005, "str_25": 0.003}
],
"lookback_days": 500
}'curl -X POST http://localhost:8084/var/stress \
-H "Content-Type: application/json" \
-d '{
"positions": [
{"ticker": "EURUSD", "direction": "SHORT", "notional": 10000000}
],
"portfolio_value": 50000000,
"use_predefined": true
}'{
"var_95_down": 293472,
"var_99_down": 426762,
"var_95_up": 287654,
"var_99_up": 418923,
"cvar_95": 389179,
"cvar_99": 511304,
"var_95_down_pct": 0.0059,
"var_99_down_pct": 0.0085,
"var_95_up_pct": 0.0058,
"var_99_up_pct": 0.0084,
"portfolio_value": 50000000,
"scenarios_used": 500,
"calculation_date": "2025-12-26",
"methodology": "historical_simulation",
"computation_time_ms": 0.12
}{
"historical": { "var_99_down": 426762, "..." },
"monte_carlo": { "var_99_down": 403609, "..." },
"parametric": { "var_99_down": 406119, "..." },
"recommendation": "Methods converge well (<10% spread). Use historical for regulatory reporting."
}{
"pnl_scenarios": [-500000, -450000, "...", 480000, 520000],
"scenarios_count": 500,
"histogram_bins": [-600000, -500000, "..."],
"histogram_counts": [2, 5, 12, "..."],
"mean": -12500,
"std": 285000,
"skewness": -0.12,
"kurtosis": 0.45,
"var_95_down": 426762,
"var_99_down": 511304,
"var_95_up": 418923,
"var_99_up": 495000,
"percentiles": {"p1": -520000, "p5": -426762, "..."},
"position_distributions": ["..."],
"method_comparison": ["..."]
}| Scenario | Description | Key Impacts |
|---|---|---|
| GFC_2008 | Global Financial Crisis | USD +12%, MXN -25%, AUD -20% |
| COVID_2020 | March 2020 selloff | MXN -22%, JPY +5%, AUD -12% |
| FED_PLUS_100BP | Fed surprise hike | USD rally, EM weakness |
| EUR_CRISIS | Eurozone breakup fears | EUR -20%, safe haven bid |
| CHINA_DEVALUE | CNY devaluation | CNY -15%, EM contagion |
| RISK_OFF | General deleveraging | JPY +8%, EM -10-15% |
┌─────────────────────────────────────────────────────────────────┐
│ VaR Service v2.1.0 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ FastAPI (main.py) │
│ ├── Structured JSON Logging │
│ ├── CORS Middleware │
│ └── Auto-generated OpenAPI docs │
│ │
│ VaR Engine (var_engine.py) │
│ ├── Historical Simulation (500-day lookback) │
│ ├── Monte Carlo (10K paths, Cholesky correlation) │
│ ├── Parametric (variance-covariance) │
│ ├── Component VaR (marginal contributions) │
│ └── Two-Tailed VaR (upside + downside) │
│ │
│ FX Vol Surface (fx_vol_surface.py) │
│ ├── Garman-Kohlhagen (delta, vega) │
│ ├── RR/BF to Strike Vol conversion │
│ ├── Variance interpolation │
│ └── Optimized point interpolation (6 tickers/option) │
│ │
│ Data Sources: │
│ ├── Bloomberg API (production) │
│ └── Synthetic Returns (fallback) │
│ │
└─────────────────────────────────────────────────────────────────┘
Namespace: gzc-risk Replicas: 1-5 (HPA) Resources: 200m-1 CPU, 512Mi-1Gi RAM
# Apply manifests
kubectl apply -f k8s/production.yaml
# Check status
kubectl get pods -n gzc-risk -l app=var-service
# View logs
kubectl logs -n gzc-risk -l app=var-service --tail=50
# Port-forward
kubectl port-forward svc/var-service 8084:8084 -n gzc-riskStructured JSON logging for Azure Monitor / ELK integration:
{"time":"2025-12-26T09:34:20","level":"INFO","logger":"var-service",
"message":{"event":"request_complete","method":"POST","path":"/var/compare",
"status":200,"duration_ms":7.11}}| Env Var | Default | Description |
|---|---|---|
PORT |
8084 | Service port |
BLOOMBERG_API |
http://20.172.249.92:8081 | Bloomberg gateway |
| Operation | Time | Notes |
|---|---|---|
| Spot VaR (Historical) | 0.1-0.3ms | 7 positions |
| Spot VaR (Monte Carlo) | 6-7ms | 10K simulations |
| Spot VaR (Parametric) | 0.1ms | Fastest |
| Option VaR | 0.48s | Per option (optimized) |
| Method Compare | 7-11ms | All 3 methods |
| Stress Test | 2-3ms | 6 scenarios |
var-service/
├── app/
│ ├── main.py # FastAPI endpoints + logging
│ ├── var_engine.py # VaR calculations (3 methods)
│ ├── fx_vol_surface.py # Option VaR (GK, vol interpolation)
│ └── data_fetcher.py # Bloomberg data integration
├── k8s/
│ └── production.yaml # K8S deployment manifests
├── Dockerfile # Container build
├── requirements.txt # Python dependencies
├── PROJECT_MANIFEST.json # System registry
└── README.md # This file
Risk Agent (SENTINEL) - v2.1.0 - 2025-12-26