Skip to content

Add cash-deploy backtest that buys drawdowns from a cash reserve - #2

Merged
valuecodes merged 3 commits into
mainfrom
feat/cash-deploy-backtest
Jul 13, 2026
Merged

Add cash-deploy backtest that buys drawdowns from a cash reserve#2
valuecodes merged 3 commits into
mainfrom
feat/cash-deploy-backtest

Conversation

@valuecodes

Copy link
Copy Markdown
Owner

What

  • Adds a tactical cash-deployment backtest: hold part of the portfolio in a
    cash reserve (money-market at the fed funds rate), deploy it into stocks in
    tranches as the S&P 500 draws down from its all-time high, then drip it back
    toward the target reserve at new highs. The question it answers: does buying
    drawdowns from a reserve beat a plain static stock/cash split?
  • Ships four named deploy rules from the research brief — Käyttäjän sääntö,
    Kasvuoptimi, Riskioptimi, Suositus
    — plus a custom-rule builder.
  • New dedicated stateful engine (cash_deploy.py) with a tranche base locked
    per drawdown episode; the existing fixed-weight run_simulation is reused for
    the 100% stocks and static split comparison baselines.
  • New Streamlit Cash Deploy page (multipage): metrics table (incl. a Sharpe
    vs. cash), equity curve, stock/cash composition chart, drawdown, and a
    deploy/refill event log. The stocks+cash loader is shared into
    data.load_stocks_cash so Home.py and the new page use one implementation.
  • Note: the bundled S&P 500 series is price-return only (no dividends),
    which understates equity returns and mildly favours cash — surfaced as a
    caveat on the page.

How to test

uv run poe check
uv run poe cov
uv run poe dev   # open the "Cash Deploy" page; try Suositus @ 30% reserve

Verified on real data (1954–2026): the reserve deploys progressively through the
2008 and 2020 drawdowns and refills on recovery; cash stays ≥ 0 and equity > 0
across all 18,127 days. 89 tests pass; lint + typecheck green.

Security review

No security-impacting changes.

Add a tactical cash-deployment strategy: hold a cash reserve at the fed
funds rate, deploy it into stocks in tranches as the S&P draws down from
its all-time high, and drip it back toward the target reserve at new
highs. Includes named deploy rules (Käyttäjän sääntö, Kasvuoptimi,
Riskioptimi, Suositus), a dedicated stateful engine, a Streamlit page,
and comparison baselines (100% stocks, static split) via the existing
simulator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 13, 2026 19:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “tactical cash-deployment” backtest path to the Portfolio Research Lab: maintaining a cash reserve that deploys into equities in tranches on drawdowns from ATH, then refills back toward a target reserve at new highs, with UI + shared data-loading support and expanded tests.

Changes:

  • Introduces a stateful cash-deploy simulation engine (run_cash_deploy) plus result object and event log.
  • Adds new Pydantic models for deploy rules/config and ships four named preset rules.
  • Adds a Sharpe ratio metric (including vs-cash usage), a shared load_stocks_cash loader, a new Streamlit “Cash Deploy” page, and comprehensive tests.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/test_models.py Adds validation coverage for DeployRule, CashDeployConfig, and preset rules.
tests/test_metrics.py Adds unit tests for the new Sharpe ratio metric.
tests/test_data.py Adds tests for the shared load_stocks_cash loader behavior and validation.
tests/test_cash_deploy.py Adds end-to-end tests for deploy/refill mechanics and event schema.
tests/conftest.py Adds a reusable hand-checkable stocks+cash fixture for cash-deploy tests.
src/portfolio_research_lab/models.py Adds DeployRule, CashDeployConfig, and preset deploy rules.
src/portfolio_research_lab/metrics.py Adds sharpe_ratio metric used by the new UI.
src/portfolio_research_lab/data.py Adds load_stocks_cash to centralize construction of the stocks+cash price frame.
src/portfolio_research_lab/cash_deploy.py New path-dependent cash-deployment engine with deploy/refill event logging.
app/pages/1_Cash_Deploy.py New Streamlit multipage UI for the cash-deploy strategy + baselines and event log.
app/Home.py Refactors existing stocks+cash loading to reuse data.load_stocks_cash.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/portfolio_research_lab/cash_deploy.py Outdated
Comment on lines +69 to +79
if len(returns) < 2:
return 0.0
if isinstance(risk_free, pd.Series):
rf: pd.Series | float = risk_free.reindex(returns.index).fillna(0.0)
else:
rf = risk_free
excess = returns - rf
vol = annualized_volatility(excess, periods_per_year)
if vol == 0.0:
return 0.0
return float(excess.mean() * periods_per_year / vol)
valuecodes and others added 2 commits July 13, 2026 22:23
Rename the four preset deploy rules from Finnish to English: User rule,
Growth optimum, Risk optimum, Recommended.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@valuecodes
valuecodes merged commit a19a2e6 into main Jul 13, 2026
8 checks passed
@valuecodes
valuecodes deleted the feat/cash-deploy-backtest branch July 14, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants