Skip to content

Repository files navigation

Quant Portfolio Risk Lab

A modular Python risk engine for equity portfolio VaR, Expected Shortfall, backtesting, stress testing, optimization, transaction costs, and automated HTML reporting.

The project is designed as a recruiter-facing quantitative engineering portfolio: notebook research has been extracted into reusable package modules, tested with deterministic unit and regression tests, and exposed through a reproducible portfolio-risk CLI.

Key Capabilities

  • Data validation for price, return, and portfolio-weight inputs.
  • Historical and Gaussian Value at Risk and Expected Shortfall.
  • Rolling VaR forecasts with Kupiec and Christoffersen validation tests.
  • GARCH volatility modeling and Monte Carlo portfolio simulation.
  • Deterministic market shocks, volatility shocks, covariance stress, and correlation stress.
  • Static portfolio optimization: equal weight, minimum variance, maximum Sharpe, and minimum ES.
  • Rolling portfolio backtesting with weight drift, turnover, gross/net returns, and cost drag.
  • Local HTML risk report generation with CSV, JSON, and PNG artifacts.
  • Unified CLI with typed YAML configuration, run manifests, logs, and overwrite protection.

Architecture

Market data snapshot
-> data validation
-> return calculation
-> risk estimation
-> VaR backtesting
-> stress testing
-> portfolio optimization
-> rolling portfolio backtesting
-> report generation

The package lives under src/portfolio_risk_engine and keeps quantitative domains separated:

  • risk/: scalar VaR and Expected Shortfall estimators.
  • backtesting/: rolling VaR forecasts, exceptions, Kupiec, and Christoffersen tests.
  • volatility/: GARCH fitting, forecasts, and residual diagnostics.
  • simulation/: multivariate and portfolio Monte Carlo simulation.
  • stress/: deterministic and covariance-based stress engines.
  • optimization/: constraints, objectives, solvers, and result summaries.
  • portfolio_backtesting/: rebalancing schedules, drift, turnover, costs, and performance.
  • reporting/: report payload builders, tables, figures, and HTML rendering.
  • cli/: reproducible command orchestration from YAML configs.

Quick Start

git clone https://github.com/FEDERICOLANCINI/Quant-Portfolio-Risk-Lab.git
cd Quant-Portfolio-Risk-Lab

python -m venv .venv
source .venv/bin/activate  # Windows: .\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"

Using uv:

uv sync --extra dev

CLI Example

portfolio-risk --help
portfolio-risk validate --config configs/base.yaml
portfolio-risk run --config configs/base.yaml
portfolio-risk backtest --config configs/backtest.yaml
portfolio-risk stress --config configs/stress.yaml
portfolio-risk optimize --config configs/optimization.yaml
portfolio-risk report --config configs/report.yaml

By default, CLI commands write to reports/runs/<UTC-run-id>/ and include:

  • config.yaml: exact config snapshot;
  • manifest.json: generated artifacts and command metadata;
  • portfolio-risk.log: command log;
  • command-specific CSV/JSON/HTML outputs.

report is intentionally separate from run, so report CSV exports do not overwrite pipeline artifacts in the same directory.

Example Report

View the example HTML risk report

GitHub may display the HTML source instead of rendering it. In that case, download the file and open it locally in a browser. The same example folder includes summary_metrics.json, CSV table exports, and figures under reports/example/figures/.

Quantitative Methodology

The repository uses a loss-positive convention:

loss = -portfolio_value * portfolio_return

VaR is computed as a loss quantile. Expected Shortfall is computed as the average loss beyond the VaR threshold. Core scalar risk functions do not impose a zero floor unless floor_at_zero=True is explicitly requested.

The saved equity universe is AAPL, MSFT, NVDA, AMZN, META, JPM, XOM, JNJ, UNH, and PG. SPY is used as a benchmark in reporting and validation, not as an optimized asset.

Portfolio optimization uses long-only full-investment constraints with bounded per-asset weights. Rolling backtests rebalance out of sample, apply pre-trade weight drift, measure half-turnover, and report transaction-cost drag separately from gross returns.

Stress tests are deterministic what-if scenarios, not forecasts. They are reported beside baseline VaR/ES metrics to make scenario sensitivity explicit.

Validation and Tests

Run the release checks locally:

uv run ruff check .
uv run ruff format --check .
uv run mypy src/portfolio_risk_engine
uv run pytest --cov=portfolio_risk_engine --cov-report=term-missing --cov-report=xml

The test suite covers validation, returns, VaR, Expected Shortfall, rolling VaR backtesting, Kupiec and Christoffersen tests, GARCH, Monte Carlo simulation, stress testing, optimization, rolling portfolio backtesting, reporting, and CLI orchestration.

Repository Structure

configs/                         # YAML configs for CLI workflows
data/
  raw/                           # committed market-data snapshot
  processed/                     # committed derived data used by tests/configs
notebooks/                       # research notebooks used to develop the methodology
reports/
  example/                       # lightweight committed demo report
  runs/                          # ignored local CLI outputs, keeps .gitkeep
scripts/
  generate_report.py             # backward-compatible wrapper for portfolio-risk report
src/portfolio_risk_engine/       # importable package
tests/unit/                      # deterministic unit and regression tests

Compatibility Shims

The following files are intentionally kept for notebook and legacy import compatibility:

  • src/portfolio_risk_engine/risk_metrics.py
  • src/portfolio_risk_engine/simulator.py
  • src/portfolio_risk_engine/volatility_model.py
  • scripts/generate_report.py

They delegate to the canonical package modules and should be removed only in a future breaking release after notebook imports are updated.

Development

Install pre-commit hooks:

uv run pre-commit install
uv run pre-commit run --all-files

Build the package:

uv build

Limitations

  • This is a research and educational project, not institutional production risk infrastructure.
  • The CLI uses saved local CSV artifacts and does not fetch live financial data.
  • Rerunning the notebooks can change the market-data snapshot because yfinance data evolves.
  • The portfolio universe is a small US equity sample and uses long-only bounded optimization.
  • GARCH forecasts use empirical correlations; DCC and copula dependence models are not implemented.
  • VaR backtesting uses sampled one-day-ahead observations with a configured step, not every trading day.
  • Stress scenarios are deterministic and should be interpreted as scenario analysis, not predictions.
  • No dashboard, API service, cloud deployment, or live-trading integration is included.

License and Disclaimer

This repository is released under the MIT License. See LICENSE.

The project is intended for research and educational purposes and does not constitute financial advice, investment advice, or a trading recommendation.

About

Portfolio risk modeling with GARCH, Monte Carlo simulation, VaR/ES backtesting, stress testing and optimization.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages