Skip to content

About

Portfolio Lab: an interactive Python app for portfolio optimisation, efficient frontiers, out-of-sample performance analysis and downloadable reports.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

106 Commits

Folders and files

Repository files navigation

Efficient Frontier Analysis for US Equities

A local Rust app for stock portfolio optimization and historical tests. It estimates returns and covariance from supplied prices, then finds stock weights within a volatility budget and holding limit.

The default universe combines the stocks held by SPY with current Nasdaq-100 constituents. You can also use your own stock symbols, a price CSV, or synthetic demo data. SPY and QQQ provide comparisons and do not enter the stock allocation.

Setup

Portfolio Lab is a desktop app. It opens in its own window and needs no browser, Python, or Docker. The pages come from inside the program, so the app opens no network port.

Ready-made programs

CI builds the programs for each change. Open the latest successful CI run, then download an artifact under Artifacts. GitHub asks you to sign in for artifacts and keeps them for 90 days.

System Artifact Start the app
Windows 10 or 11, 64-bit portfolio-lab-Windows Extract the ZIP. Double-click Portfolio Lab.exe.
Linux, 64-bit, with WebKitGTK 4.1 portfolio-lab-Linux Extract the ZIP, then portfolio-lab-linux-x86_64.tar.gz. Run ./portfolio-lab.

Each artifact also contains the command-line program efficient-frontier. The Windows app uses the Microsoft Edge WebView2 Runtime, which Windows 11 includes. The Linux app uses the system's WebKitGTK 4.1: on Debian or Ubuntu, install libwebkit2gtk-4.1-0; on Arch, install webkit2gtk-4.1. The programs have no code signature, so Windows SmartScreen can show a warning for a downloaded file. Select More info, then Run anyway.

Build from source

Install Rust 1.90 or newer with rustup. Rust also needs a C compiler and linker, and Linux needs the WebKitGTK 4.1 files for the window. The table gives the tools for each system. Then download and extract the repository.

System Install first Start the app
Windows Microsoft C++ build tools with "Desktop development with C++". The rustup installer offers them. Open Start Portfolio Lab.bat.
macOS Xcode Command Line Tools. Run xcode-select --install. Open Start Portfolio Lab.command.
Linux A C compiler and WebKitGTK 4.1. Debian or Ubuntu: sudo apt install build-essential libwebkit2gtk-4.1-dev. Arch: sudo pacman -S --needed base-devel webkit2gtk-4.1. Run bash run.sh from the project folder.

The first start compiles the app. It needs internet access and takes a few minutes. Later starts are fast. Close the window to stop the app. Demo and CSV studies work offline after the first build.

For a Git checkout:

git clone https://github.com/sammcentee/efficientfrontier.git
cd efficientfrontier
bash run.sh

See the user guide for setup errors and platform limits.

Run a study

  1. Read the model equations on the Efficient Frontier Analysis for US Equities opening page. Open Settings to choose stocks and history, or select the Demo stock source.
  2. Set Annual volatility budget and Holding limit in the two number fields. The holding limit defaults to 10%.
  3. Select Build portfolio.
  4. Inspect the latest stock holdings and their fitted frontier. Then compare in-sample and out-of-sample results, and the later replay with SPY and QQQ.
  5. Select Export, then choose where to save the offline report and exact input/result CSVs.

The app opens in a dark theme. The sun button beside Settings changes to the light theme, and the app keeps your choice. Exported reports use the light theme.

The app starts the volatility budget at QQQ's latest one-year annualized volatility, with its price date shown. This reference is separate from the stock fit window. Your edits take precedence. If the reference is unavailable, the app labels its 20% manual fallback.

A 10% holding limit needs at least ten eligible stocks. The six-asset synthetic demo uses a 20% limit. An infeasible budget or holding limit stops the calculation.

Model

The optimizer maximizes the estimated annual arithmetic mean return. Weights are long-only, sum to 100%, and obey the holding limit. The volatility budget limits the covariance-based estimate, not future volatility or losses. The objective is not CAGR or maximum Sharpe. The R comparison explains the original method, its return-formula error, and the corrected stock-only results.

The app fixes these assumptions:

Assumption Value
Initial training / later test First 70% / final 30% of return observations
Walk-forward tests Fits on the first 50%, 60%, 70%, 80%, and 90% of returns. Each holds through the next tenth only
Holding rule Fit once on the initial sample, buy once, then let weights drift
Execution Close after the last price used in the fit
Trading fees 0.10% of the initial purchase. No later trades or terminal sale
Covariance Ordinary sample covariance, without shrinkage

The first test interval stays in cash at zero interest. All replay paths then buy once and hold. The model omits taxes, currency conversion, and market impact. The method reference gives the equations and accounting.

Read the results

Overview starts with the latest stock holdings, followed by their fitted frontier, then an in-sample and out-of-sample comparison. Company cards show names, weights, and a short business description from current Yahoo Finance profiles when available. CSV and demo studies stay offline. Five walk-forward tests fit the model on earlier stock prices only, then hold that allocation through a later window that the fit did not see. Each window shows the same allocation on its own fit dates (in sample) and on the later dates (out of sample). The growth chart, replay metrics, and exact return reconciliation follow. Open Settings from the results navigation, or Data & method for coverage and trades.

The latest fit includes the replay dates. The replay did not use the latest holdings. The fit chooses one allocation using all supplied history. The replay buys one allocation from the initial training sample, then holds it through the later prices without rebalancing. The two panels use different dates, weights, and fee treatment.

Result Meaning
Fitted annual mean Average return from a fit's history, using its target weights, before fees
Fitted volatility Sample volatility from the fit's dates and target weights; the budget applies to this estimate
Fitted frontier Best estimated stock returns across risk levels, with SPY/QQQ as separate reference points
In sample Buy-and-hold result of an allocation on the same dates that chose it, measured from the purchase close
Out of sample Buy-and-hold result of an allocation on later dates that its fit did not use, measured from the purchase close
Historical replay Net performance of the initial allocation, bought once and held through later prices
Latest holdings A new fit using all supplied history; these weights did not produce the earlier test

Equal-weight stocks, SPY, and QQQ also buy once and hold. The equal-weight reference starts with equal weights but lets them drift. Within the replay, all comparisons use the same dates and fee rate, but their risks can differ. A benchmark with higher mean return and lower volatility beat the stock rule in that replay, even if the latest fitted portfolio sits above it on the fitted frontier chart.

The app displays typeset equations for the optimizer, volatility budget, buy-and-hold accounting, and performance metrics. The introduction appears beside the controls. Fitted moments describe the starting weights. They do not describe a historical buy-and-hold path.

The test status describes coverage, realized risk, and comparison results. It is not proof of future outperformance. Current member lists and complete-history requirements favor survivors. Prior review of the test dates also limits their value as new evidence.

Command line

Run the app's model without the window:

# Offline demo
cargo run --release --bin efficient-frontier -- --target-volatility .20 --max-weight .20

# Supplied stock prices, with at least ten eligible stocks
cargo run --release --bin efficient-frontier -- --csv data/prices.csv --target-volatility .20

The first run compiles the CLI. You can also build it one time with cargo build --release. Then run ./target/release/efficient-frontier with the same flags. On Windows, the program is target\release\efficient-frontier.exe.

Output goes to results/latest/. Use --output to preserve separate studies. Reports contain the input prices. Keep private data in ignored data/ or private/ folders.

Reference

The original Efficient Frontier v1.12.R and spy_holdings.ods remain historical files. R is not required. The Rust version replaced the Python release. Git history keeps the last Python release at commit 2e5f21c. Earlier findings remain in the stock study and research archive.

Code and documentation use the MIT License. Third-party terms still apply. The software license does not grant rights to download or redistribute market data.

About

Portfolio Lab: an interactive Python app for portfolio optimisation, efficient frontiers, out-of-sample performance analysis and downloadable reports.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages