Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

ShrishDhuria/bl-portfolio-optimiser

Repository files navigation

Black-Litterman Portfolio Optimiser

tests

A practitioner-grade implementation of the Black-Litterman model for European equity portfolio construction, applied to the SX5E top 15.

What it demonstrates

Black-Litterman starts from the market-cap–implied equilibrium return Π and tilts it only where you hold a view, sizing each tilt by your stated confidence (Idzorek). That fixes the central pathology of plain mean-variance — wild, corner-solution weights from tiny perturbations in the expected-return inputs. With no views the posterior reproduces the cap-weighted market exactly; with a 100%-confidence view the view is honoured exactly. The figure shows the efficient frontier on the EURO STOXX top 15 (left) and how a moderate view shifts the posterior expected returns away from the prior only on the names it touches (right).

Black-Litterman results — efficient frontier and prior-vs-posterior returns

Left: efficient frontier from the real covariance sweep, with the max-Sharpe point. Right: implied equilibrium Π vs the Black-Litterman posterior μ under one illustrative pair of views — the tilt is concentrated where the views apply. Regenerate with python make_figures.py.

Project goals

  • Combine market equilibrium (CAPM-implied returns) with investor views via Bayesian shrinkage to produce stable, intuitive portfolios.
  • Build parallel Python and Excel implementations to demonstrate both quantitative depth and tooling fluency.
  • Interactive Streamlit dashboard for live view-entry, sensitivity analysis, and efficient-frontier visualisation.

Methodology references

  • Black, F. & Litterman, R. (1992). "Global Portfolio Optimization." Financial Analysts Journal.
  • He, G. & Litterman, R. (1999). "The Intuition Behind Black-Litterman Model Portfolios." Goldman Sachs.
  • Idzorek, T. M. (2005). "A Step-by-Step Guide to the Black-Litterman Model." Working paper.

Project structure

bl-portfolio-optimiser/
├── market_data.py # Phase 1 — prices, returns, covariance, weights, rf
├── equilibrium.py # Phase 2 — reverse-optimisation → implied returns Π
├── views.py # Phase 3 — P, Q, Ω construction (Idzorek)
├── bl_model.py # Phase 4 — posterior μ and Σ computation
├── optimiser.py # Phase 5 — mean-variance, max Sharpe, efficient frontier
├── app.py # Phase 6 — Streamlit dashboard
├── sources.md # Data provenance
├── requirements.txt
└── README.md

Quick start

pip install -r requirements.txt
python market_data.py # builds the data layer and exports CSVs
streamlit run app.py # interactive dashboard

Build status

  • Phase 1 — Data layer
  • Phase 2 — Equilibrium implied returns
  • Phase 3 — Views (Idzorek confidence mapping)
  • Phase 4 — BL posterior
  • Phase 5 — Optimiser (with concentration caps)
  • Phase 6 — Streamlit dashboard

Limitations

Honest about what the model can and cannot do:

  • Inputs drive everything. Π depends on the covariance estimate (Ledoit-Wolf shrinkage is used here) and on the risk-aversion coefficient λ (anchored to an assumed 5% ERP); the output is only as good as those.
  • τ is set by convention, not estimated. The prior-scaling parameter (0.025) is a standard choice, and posterior weights are known to be sensitive to it — the dashboard's sensitivity view exists precisely because of this.
  • View confidence is judgment, not data. The Idzorek mapping turns a stated confidence into Ω; it does not calibrate that confidence from any track record.
  • Single-period and largely unconstrained. The objective is one-period mean-variance with a per-name cap; there are no transaction costs, turnover limits, or factor/sector constraints.
  • Covariance is estimated on ~3y of daily history and assumed stationary — regime shifts and time-varying correlation are not modelled.

Testing

A pytest suite under tests/ covers the model's mathematical contracts — the properties a reviewer is most likely to probe in an interview — rather than just checking that functions run. All fixtures are synthetic, so the suite is offline and fast.

  • No-views identity — with an empty view set the posterior mean collapses exactly onto the equilibrium prior Π.
  • Confidence limits — as Idzorek confidence → 0 the view is ignored (posterior → prior); at 100% confidence it is enforced exactly (P · μ_BL = Q).
  • Equilibrium round-trip(1/λ) Σ−1 Π = w_mkt to machine precision.
  • Two-form cross-check — the Theil and original Black-Litterman posteriors agree to ~1e-10.
  • Risk decomposition — Euler risk contributions sum to portfolio volatility.
  • Well-posedness — the posterior covariance stays symmetric and PSD; the optimisers respect the budget and per-name caps.
pip install -r requirements-dev.txt
pytest tests/ -q # 9 tests

Tests run automatically on every push via GitHub Actions (.github/workflows/tests.yml).

About

Black-Litterman portfolio construction on the EURO STOXX 50 top 15: reverse-optimised equilibrium, Idzorek view-confidence, Theil posterior, max-Sharpe / min-variance / efficient frontier, Streamlit dashboard.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /