Retired Experiments
Swing Trader and Astro Lite are retired, in full — full logs, frozen final state, and an honest retirement note. Nothing here is deleted.
Swing Trader
late May 2026 (exact start unrecorded) – Jun 19, 2026 · died in the June outage
unrecorded final NAV · 0 trades
Astro Lite
late May 2026 (exact start unrecorded) – Jul 6, 2026 · retired: ablation superseded by pillar scoring
unrecorded final NAV · 2 trades
# Experiment Archive — Retirement Notes
PredictMyGold originally ran a three-bot ablation (Swing Trader, Astro Lite,
Astro Heavy) to test whether Vedic astrology signals add anything over pure
technical/regime trading. The owner has retired that ablation in favor of a
weighted, Brier-scored, four-pillar intelligence Ledger: every pillar
(including astrology) now files pre-registered, dated calls that are scored
against actual price outcomes, and its "earned weight" is published at
`/api/weights`. That per-call scoring is a more direct and continuously-updated
answer to "does astrology add anything?" than comparing three separate paper
accounts ever was.
Astro Heavy remains live — for gamification and an unbroken long-term track
record — under `bot_astro_heavy.py`. Swing Trader and Astro Lite are retired
here, in full, with their last known state and trade logs. **Nothing here is
deleted; wrong or unflattering results are kept, not hidden.**
---
## Swing Trader (`bot_swing.py`)
- **Strategy:** weekly-regime-gated swing trades (15-min check cycle), daily
regime + astro bias as an entry filter, technical trailing/hard stops.
- **Start:** operational since late May 2026. The exact first-cycle timestamp
was not preserved in any surviving log (no dated CSV row or state snapshot
from before June 1 survives in this repo).
- **End:** June 19, 2026 — `run_bots.py` had no restart logic; when the Swing
process died it was never restarted (see `README_UPGRADE.md`, "Silent
death, June 19"). Nothing detected or alerted on the outage.
- **Last recorded state:** cycle 58, updated 2026-06-01T18:11:37Z — see
`swing_final_state.json`. At that point: `balance_usdt=$50.00`,
`balance_paxg=0`, `portfolio_val=$50.00`, `pnl=$0.00` per the bot's own
state write.
- **Trade log:** `trades_swing.csv` does not exist anywhere in this repo —
no trade was ever appended to it, and `swing_trades.csv` is intentionally
**not** included here since there is nothing real to freeze. The state
file's `balance_usdt` ($50) does not match its own starting `CAPITAL`
($100) despite zero logged trades and zero PAXG held — that inconsistency
predates this retirement, was not introduced by it, and is not resolved by
this document. It is presented as-recorded, not corrected or explained away.
- **Trades executed:** 0 (per the missing CSV and `position_pct: 0` /
`balance_paxg: 0` in the last state).
- **Reason for retirement:** superseded by per-call Brier scoring of the
astrology pillar; one bot (Astro Heavy) remains for the live track record.
Swing's silent death on June 19 — and the fact that its own state hadn't
been refreshed since June 1, well before that death — was itself a symptom
of the monitoring gaps this rework closes (loud staleness badges, a
supervisor that actually restarts crashed bots, ops alerts to Telegram).
## Astro Lite (`bot_astro_lite.py`)
- **Strategy:** the same regime/astro framework as Swing but on an hourly
cycle, with a simplified position-sizing rule and Claude-authored planetary
briefs.
- **Start:** operational since late May 2026 (same caveat as above — exact
first cycle not preserved).
- **End:** July 6, 2026 (today) — retired as part of this rework, not a crash.
- **Last recorded state:** cycle 15, updated 2026-06-01T17:47:48Z — see
`lite_final_state.json`. `balance_usdt=$50.00`, `balance_paxg=0`,
`portfolio_val=$50.00`, `pnl=$0.00`. Like Swing, state hadn't refreshed
since June 1 even though the bot was nominally "live" until today — the
same silent-staleness pattern, undetected until this audit.
- **Trade log:** `trades_astro_lite.csv` does not exist in this repo either —
0 trades were ever logged, so `lite_trades.csv` is not fabricated here.
- **Trades executed:** 0.
- **Reason for retirement:** the three-bot ablation is superseded by per-call
Brier scoring of the astrology pillar; one bot remains for the live track
record.
---
## What's in this folder
| File | Contents |
|---|---|
| `swing_final_state.json` | Frozen copy of Swing's last `state_swing.json` (cycle 58, 2026-06-01). |
| `lite_final_state.json` | Frozen copy of Lite's last `state_lite.json` (cycle 15, 2026-06-01). |
| `code/bot_swing.py` | The exact code that produced Swing's trade history. No longer imported anywhere live. |
| `code/bot_astro_lite.py` | The exact code that produced Lite's trade history. No longer imported anywhere live. |
No `swing_trades.csv` / `lite_trades.csv` are included — both bots logged zero
trades before retirement, so there is no trade log to freeze. If this changes
(e.g. an older trade CSV turns up elsewhere), it should be added here rather
than reconstructed.
# Honest Backtest Re-Run (2026-07-06)
`backtest_macro_v2.py` re-runs the same three-pass macro/astro backtest as
the archived `backtest_macro.py` (see `archive/experiments/code/`), over the
same 730-day PAXG/USDT window (2024-07-07 → 2026-07-06), with the two bugs
the audit found actually fixed:
1. **Weekly-candle look-ahead.** The old backtest's weekly slice was
`ww = [c for c in weekly if c["time"] <= wd[-1]["time"]]` — this includes
the *current, still-forming* weekly bar as soon as its **open** time is on
or before today, which leaks that week's not-yet-known final close into
mid-week decisions. `backtest_macro_v2.py` requires a full 7 days to have
elapsed since the bar opened (`c["time"] + timedelta(days=7) <=
wd[-1]["time"]`) before that bar is visible — the same `closed()`
discipline now used live in `bot_astro_heavy.py` via `signal_policy.py`.
2. **Zero trading costs.** The old backtest had no fee variable at all —
every rebalance was free. `backtest_macro_v2.py` applies `FEE = 0.0012`
(12bps per side) on every fill, the same `COST_BPS` used live.
## Old claim vs honest re-run
`bot_astro_heavy.py`'s docstring (and the dashboard's `backtest_pnl` /
`backtest_dd` fields) claimed **Pass C — Dynamic sizing + Vedic astro**
achieved:
| | Old claim (look-ahead, no fees) | Honest re-run (closed candles, 12bps fees) |
|---|---|---|
| Net P&L | +62.88% | **+38.42%** |
| Max drawdown | 14.40% | **17.42%** |
| Win rate | 69.1% | **57.4%** |
The gap is not noise — it's the two bugs. Removing the look-ahead alone
lets the strategy react to real, already-closed information instead of a
sneak preview of the current week's close; adding realistic fees on top of
102–113 rebalances per pass (vs. free trading before) compounds directly
into the P&L. **The honest number is meaningfully worse than advertised on
every metric**, and the archived `bot_astro_lite.py`'s own claimed
+57.94% is presumed to carry the same bugs (it was backtested with the
same pre-fix harness) — that file is left untouched as the frozen,
inspectable historical record of what the retired bot's authors believed
at the time (see `archive/experiments/RETIREMENT.md`); it is not re-run or
re-published as a current claim anywhere live.
## Full honest re-run — all three passes
Period: **2024-07-07 → 2026-07-06** (730 days) · Capital: $50 · Fee: 12bps/side
| Metric | A: Buy & Hold | B: Dynamic, no astro | C: Dynamic + astro |
|---|---|---|---|
| Net P&L % | **+65.67%** | +37.73% | +38.42% |
| Final value | $82.83 | $68.87 | $69.21 |
| Alpha vs Buy & Hold | +0.00% | **−27.94%** | **−27.25%** |
| Max drawdown | 27.74% | 15.48% | 17.42% |
| Win rate | n/a (0 trades) | 52.2% | 57.4% |
| Rebalances | 0 | 192 (102 buy / 90 sell) | 207 (113 buy / 94 sell) |
**The uncomfortable headline: over this exact 2-year window, simply buying
and holding PAXG beat both managed passes by roughly 27 points**, even
after the managed passes' real drawdown-reduction benefit (27.74% → 15.48%,
a genuine ~12-point improvement) is accounted for. Astro adds a modest
+0.7pp of P&L and +5.2pp of win rate over the no-astro pass in this window,
at the cost of ~1.9pp more drawdown and 15 more rebalances (more fee drag)
— a wash at best, not the standalone edge the old docstring implied.
This is exactly the question `compare_baselines.py` (below) is built to
keep asking on a rolling basis, not just as a one-time backtest: **did the
live bot beat just holding gold?** Publish the answer every week — including
when it's no.
## Single source of truth
Every published performance number now traces to `backtest_claims.py`,
populated directly from this re-run. Nothing else in the codebase should
hardcode a backtest number — import from `backtest_claims.py` instead.