Skip to content

research: accumulation policy after fees -- no arm beats static DCA (#831) - #835

Merged
eaitbrahim merged 3 commits into
mainfrom
feat/accumulation-policy
Sep 27, 2026
Merged

eaitbrahim merged 3 commits into
mainfrom
feat/accumulation-policy

Conversation

@eaitbrahim

Copy link
Copy Markdown
Contributor

Closes #831. Implements the approved design (#834, revision 2).

Three commits, in the order that matters:

  1. 7a1e900 feat(sim): keel/sim/accumulation_policy.py. Four allocators; an account with allowance-aware fees and average-cost lots; a joint stationary bootstrap; the D6 decision rule.
    • 47 tests, each seen failing first. 15 of 15 mutants killed; a 16th was equivalent, and its redundant code was removed.
    • Arm A reproduces dca_into_allowlist to the cent under zero fees on gapless candles. It fills at the next open where the benchmark fills at the close, as the design requires, and a second test pins that difference.
  2. 4113ed0 The pre-registration. The driver's docstring is the design's §3–§8, frozen. It was pushed at 02:04 UTC before the run. git diff 4113ed0 -- docs/experiments/2026-09-27-accumulation-policy.py is empty: the driver hasn't changed since.
  3. bd18cae The record, data and 16 ledger rows (ablation, a_priori, diagnostic_only; chain verified, 114 rows).

Result (headline: 5 years without PAXG, allowance-aware fees, $30,500 deposited)

Arm Terminal Sortino Max DD P(ΔSortino > 0), 20 / 60-day blocks Verdict
A static DCA $46,629 0.523 79.5% — baseline
B value averaging $48,840 0.542 78.5% 0.583 / 0.599 not better
C steered deposits $47,967 0.564 79.1% 0.365 / 0.407 not better
D selective trimming $52,919 0.611 79.3% 0.363 / 0.434 not better

No arm is better than static DCA after fees, in either run or fee model.

  • Trimming (D) wins the historical path by 13.5% but improves Sortino in only 36–43% of 2,000 resampled paths. That's a path-specific result, and the record declines to call it a win.
  • Value averaging (B) is the most consistent arm: 58–61% of paths, and about 2 points less drawdown. It is still far from the 0.95 bar.
  • Prediction misses are recorded. D was expected to do best on the with-PAXG run and was instead the weakest alternative there. PAXG's slippage is about 100 bp per leg.

Verification

  • Full suite: 6832 passed, 3 skipped.
  • mypy and ruff are clean.
  • verify_chain on the ledger: no problems.
  • The record's computed claims were re-checked against the data. Three were corrected before committing, and a causal story I hadn't tested was removed.

🤖 Generated with Claude Code

eaitbrahim and others added 3 commits September 26, 2026 21:59
…aware account, joint stationary bootstrap, D6 rule (#831)

Implements the approved design (docs/superpowers/specs/2026-09-27-accumulation-policy-design.md,
revision 2) as a pure module, apart from portfolio_sim: static DCA, bounded buy-only value
averaging, shortfall-steered DCA and DCA with selective upper-band trimming; an account loop with
next-open fills, the monthly fee-free buy allowance (sells always taxed; a flat-taker mode),
per-asset slippage and average-cost lots; a deposit-neutral TWR index; a stationary block
bootstrap of joint daily rows; and the D6 verdict over both block lengths.

Arm A reproduces benchmark.dca_into_allowlist to the cent under zero fees on gapless candles;
the one divergence (next open vs same-day close) is pinned by its own test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… driver written, NOT yet run (#831)

The driver's docstring is the pre-registration: spec §3-§8 frozen with D1-D6 settled, the
expectation recorded, both runs (5-year PAXG-free primary to now_ts=1790455996; ~1.4-year
with-PAXG secondary from PAXG's first cached daily bar), both fee modes, both bootstrap block
lengths (20, 60; 2,000 paths; seed 831) and the D6 decision rule. No real candle has been run
through it; it was smoke-tested only on synthetic candles in a throwaway database.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tic DCA (#831)

Pre-registered (design #834; driver 4113ed0 pushed before the run, and
unchanged since). On equal $500 monthly deposits with allowance-aware
fees, over 5 years without PAXG and 1.4 years with it: no arm clears
P(dSortino>0) >= 0.95 under both bootstrap block lengths. Band trimming
leads the historical path by 13.5% but improves Sortino in only 36-43% of
paths; value averaging is the most consistent at 58-61%. 16 ablation rows
appended to the trials ledger.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@eaitbrahim eaitbrahim added feature New capability (groups under Features) research Measurement, validation or KB work (Research & validation) experiment A pre-declared experiment and its result (Research & validation) labels Sep 27, 2026
@eaitbrahim
eaitbrahim merged commit b8ce169 into main Sep 27, 2026
4 checks passed
@eaitbrahim
eaitbrahim deleted the feat/accumulation-policy branch September 27, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

experiment A pre-declared experiment and its result (Research & validation) feature New capability (groups under Features) research Measurement, validation or KB work (Research & validation)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Research: value averaging and band rebalancing vs static DCA for accumulation (pre-registration)

1 participant