Skip to content

Commit 4e61ca6

Browse files
authored
Merge pull request #12 from second-state/feat/backtest
feat: add backtest CLI for historical price simulation
2 parents a078129 + 1886e37 commit 4e61ca6

24 files changed

Lines changed: 2732 additions & 34 deletions

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ path = "src/bin/polymarket.rs"
3535
name = "okx"
3636
path = "src/bin/okx.rs"
3737

38+
[[bin]]
39+
name = "backtest"
40+
path = "src/bin/backtest.rs"
41+
3842
[dependencies]
3943
clap = { version = "4", features = ["derive"] }
4044
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }

README.md

Lines changed: 153 additions & 18 deletions
Large diffs are not rendered by default.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env bash
2+
#
3+
# COVID-19 Crash — Flight-to-Safety Hedge
4+
# ========================================
5+
#
6+
# Date: February 21, 2020 (Friday before the crash accelerated)
7+
#
8+
# Thesis: By late February 2020, COVID-19 had spread to Italy and South
9+
# Korea. The S&P 500 hit its all-time high on Feb 19. A pandemic-driven
10+
# selloff was imminent. The classic hedge: go long gold (safe haven) and
11+
# short equities. This is a dollar-neutral pair: ~$5,000 each side.
12+
#
13+
# Legs:
14+
# 1. Long GOLD — 3 oz at ~$1,645/oz ($4,934 notional)
15+
# 2. Short SP500 — 1.5 units at ~$3,337 ($5,006 notional)
16+
#
17+
# What happened: The S&P 500 fell ~12% over the next 7 trading days
18+
# (the fastest correction from ATH in history). Gold initially held
19+
# steady, then pulled back as margin calls hit.
20+
#
21+
# Result: The short equity leg dominates — this hedge captured the
22+
# crash while the gold leg acts as a stabilizer.
23+
#
24+
# Usage: ./examples/backtest/covid_crash_hedge.sh
25+
#
26+
set -uo pipefail
27+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
28+
BT="${BACKTEST:-$SCRIPT_DIR/../../target/release/backtest}"
29+
30+
echo ""
31+
echo "══════════════════════════════════════════════════════════════"
32+
echo " COVID-19 Crash Hedge — February 21, 2020"
33+
echo " Long GOLD + Short S&P 500 (dollar-neutral pair)"
34+
echo "══════════════════════════════════════════════════════════════"
35+
echo ""
36+
37+
# ── Reset portfolio ────────────────────────────────────────────────
38+
$BT --at 2020-02-21 reset 2>/dev/null
39+
40+
# ── Scout: get prices on Feb 21, 2020 ─────────────────────────────
41+
echo "── Scouting prices on 2020-02-21 ──"
42+
echo ""
43+
44+
GOLD_PRICE=$($BT --at 2020-02-21 --json '{"command":"quote","symbol":"GOLD"}' 2>/dev/null | jq -r '.price')
45+
SP_PRICE=$($BT --at 2020-02-21 --json '{"command":"quote","symbol":"SP500"}' 2>/dev/null | jq -r '.price')
46+
47+
echo " GOLD: \$$GOLD_PRICE / oz"
48+
echo " SP500: \$$SP_PRICE"
49+
echo ""
50+
51+
# ── Leg 1: Long gold — safe-haven bid ─────────────────────────────
52+
echo "── Leg 1: Long GOLD (flight to safety) ──"
53+
$BT --at 2020-02-21 buy GOLD --amount 3 --price "$GOLD_PRICE"
54+
55+
# ── Leg 2: Short S&P 500 — pandemic selloff ───────────────────────
56+
echo "── Leg 2: Short S&P 500 (equity crash) ──"
57+
$BT --at 2020-02-21 sell SP500 --amount 1.5 --price "$SP_PRICE"
58+
59+
# ── Portfolio snapshot ─────────────────────────────────────────────
60+
echo "══════════════════════════════════════════════════════════════"
61+
echo " Portfolio Summary"
62+
echo "══════════════════════════════════════════════════════════════"
63+
$BT --at 2020-02-21 balance
64+
$BT --at 2020-02-21 positions
65+
66+
# ── Cleanup ────────────────────────────────────────────────────────
67+
$BT --at 2020-02-21 reset > /dev/null 2>&1
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env bash
2+
#
3+
# FTX Collapse — Crypto Contagion Hedge
4+
# ========================================
5+
#
6+
# Date: November 8, 2022 (Binance announced it would sell its FTT holdings)
7+
#
8+
# Thesis: On Nov 6, CoinDesk reported Alameda's balance sheet was full
9+
# of FTT tokens. On Nov 8, Binance announced it would liquidate its
10+
# ~$530M in FTT, triggering a bank run on FTX. Crypto was about to
11+
# enter a contagion spiral — but it wasn't clear how far traditional
12+
# markets would follow. The trade: short crypto (BTC + ETH) and go
13+
# long gold as a safe-haven hedge in case the contagion spread.
14+
#
15+
# Legs:
16+
# 1. Short BTC — 0.15 BTC at ~$18,500 ($2,775 notional)
17+
# 2. Short ETH — 2.0 ETH at ~$1,340 ($2,680 notional)
18+
# 3. Long GOLD — 3 oz at ~$1,712/oz ($5,136 notional)
19+
#
20+
# Gold is the anchor — roughly sized to match the combined crypto short.
21+
# If crypto crashes and gold holds or rises, both sides win. If crypto
22+
# recovers, the gold leg limits the damage.
23+
#
24+
# What happened: BTC dropped from $18.5k to $15.7k (-15%) in 7 days.
25+
# ETH fell from $1,340 to $1,100 (-18%). Gold was roughly flat,
26+
# providing stability. The crypto short was the main profit driver.
27+
#
28+
# Usage: ./examples/backtest/ftx_crypto_contagion.sh
29+
#
30+
set -uo pipefail
31+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
32+
BT="${BACKTEST:-$SCRIPT_DIR/../../target/release/backtest}"
33+
34+
echo ""
35+
echo "══════════════════════════════════════════════════════════════"
36+
echo " FTX Collapse — November 8, 2022"
37+
echo " Short BTC + Short ETH + Long GOLD (contagion hedge)"
38+
echo "══════════════════════════════════════════════════════════════"
39+
echo ""
40+
41+
# ── Reset portfolio ────────────────────────────────────────────────
42+
$BT --at 2022-11-08 reset 2>/dev/null
43+
44+
# ── Scout: get prices on Nov 8, 2022 ──────────────────────────────
45+
echo "── Scouting prices on 2022-11-08 ──"
46+
echo ""
47+
48+
BTC_PRICE=$($BT --at 2022-11-08 --json '{"command":"quote","symbol":"BTC"}' 2>/dev/null | jq -r '.price')
49+
ETH_PRICE=$($BT --at 2022-11-08 --json '{"command":"quote","symbol":"ETH"}' 2>/dev/null | jq -r '.price')
50+
GOLD_PRICE=$($BT --at 2022-11-08 --json '{"command":"quote","symbol":"GOLD"}' 2>/dev/null | jq -r '.price')
51+
52+
echo " BTC: \$$BTC_PRICE"
53+
echo " ETH: \$$ETH_PRICE"
54+
echo " GOLD: \$$GOLD_PRICE"
55+
echo ""
56+
57+
# ── Leg 1: Short BTC — exchange contagion ─────────────────────────
58+
echo "── Leg 1: Short BTC (FTX contagion, forced selling) ──"
59+
$BT --at 2022-11-08 sell BTC --amount 0.15 --price "$BTC_PRICE"
60+
61+
# ── Leg 2: Short ETH — crypto-wide selloff ────────────────────────
62+
echo "── Leg 2: Short ETH (correlated crypto drawdown) ──"
63+
$BT --at 2022-11-08 sell ETH --amount 2.0 --price "$ETH_PRICE"
64+
65+
# ── Leg 3: Long gold — safe-haven anchor ──────────────────────────
66+
echo "── Leg 3: Long GOLD (safe haven, hedge against reversal) ──"
67+
$BT --at 2022-11-08 buy GOLD --amount 3 --price "$GOLD_PRICE"
68+
69+
# ── Portfolio snapshot ─────────────────────────────────────────────
70+
echo "══════════════════════════════════════════════════════════════"
71+
echo " Portfolio Summary"
72+
echo "══════════════════════════════════════════════════════════════"
73+
$BT --at 2022-11-08 balance
74+
$BT --at 2022-11-08 positions
75+
76+
# ── Cleanup ────────────────────────────────────────────────────────
77+
$BT --at 2022-11-08 reset > /dev/null 2>&1
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env bash
2+
#
3+
# NVIDIA Earnings Blowout — AI Sector Alpha
4+
# ============================================
5+
#
6+
# Date: May 25, 2023 (day after NVDA's historic Q1 FY24 earnings)
7+
#
8+
# Thesis: On May 24, 2023, NVIDIA reported revenue of $7.19B (vs
9+
# $6.52B expected) and guided Q2 to $11B — 50% above consensus.
10+
# The stock surged 25% after hours. This was the moment the market
11+
# realized AI infrastructure demand was real. The play: capture
12+
# NVDA's alpha while hedging broad market risk.
13+
#
14+
# Legs:
15+
# 1. Long NVDA — 13 shares at ~$379/share ($4,930 notional)
16+
# 2. Short SP500 — 1.2 units at ~$4,151 ($4,981 notional)
17+
#
18+
# This is a classic long/short equity pair: long the winner, short
19+
# the index. If the market rallies, NVDA should rally more. If the
20+
# market drops, NVDA's AI tailwind should cushion the loss.
21+
#
22+
# What happened: NVDA continued climbing from $379 to $400+ over
23+
# the next week as analysts rushed to upgrade. The S&P 500 was
24+
# roughly flat. Pure alpha.
25+
#
26+
# Usage: ./examples/backtest/nvda_earnings_alpha.sh
27+
#
28+
set -uo pipefail
29+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
30+
BT="${BACKTEST:-$SCRIPT_DIR/../../target/release/backtest}"
31+
32+
echo ""
33+
echo "══════════════════════════════════════════════════════════════"
34+
echo " NVIDIA AI Earnings — May 25, 2023"
35+
echo " Long NVDA + Short S&P 500 (sector alpha pair)"
36+
echo "══════════════════════════════════════════════════════════════"
37+
echo ""
38+
39+
# ── Reset portfolio ────────────────────────────────────────────────
40+
$BT --at 2023-05-25 reset 2>/dev/null
41+
42+
# ── Scout: get prices on May 25, 2023 ─────────────────────────────
43+
echo "── Scouting prices on 2023-05-25 ──"
44+
echo ""
45+
46+
NVDA_PRICE=$($BT --at 2023-05-25 --json '{"command":"quote","symbol":"NVDA"}' 2>/dev/null | jq -r '.price')
47+
SP_PRICE=$($BT --at 2023-05-25 --json '{"command":"quote","symbol":"SP500"}' 2>/dev/null | jq -r '.price')
48+
49+
echo " NVDA: \$$NVDA_PRICE"
50+
echo " SP500: \$$SP_PRICE"
51+
echo ""
52+
53+
# ── Leg 1: Long NVDA — AI momentum ───────────────────────────────
54+
echo "── Leg 1: Long NVDA (AI infrastructure demand) ──"
55+
$BT --at 2023-05-25 buy NVDA --amount 13 --price "$NVDA_PRICE"
56+
57+
# ── Leg 2: Short S&P 500 — market-neutral hedge ──────────────────
58+
echo "── Leg 2: Short S&P 500 (hedge broad market risk) ──"
59+
$BT --at 2023-05-25 sell SP500 --amount 1.2 --price "$SP_PRICE"
60+
61+
# ── Portfolio snapshot ─────────────────────────────────────────────
62+
echo "══════════════════════════════════════════════════════════════"
63+
echo " Portfolio Summary"
64+
echo "══════════════════════════════════════════════════════════════"
65+
$BT --at 2023-05-25 balance
66+
$BT --at 2023-05-25 positions
67+
68+
# ── Cleanup ────────────────────────────────────────────────────────
69+
$BT --at 2023-05-25 reset > /dev/null 2>&1
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Russia-Ukraine Invasion — Commodity Supply Shock
4+
# ==================================================
5+
#
6+
# Date: February 24, 2022 (the day Russia invaded Ukraine)
7+
#
8+
# Thesis: Russia is a top-3 global oil producer. A full-scale invasion
9+
# means sanctions, supply disruption, and an energy price spike. At the
10+
# same time, risk assets sell off on geopolitical uncertainty. This is
11+
# a classic macro shock trade: long commodities, short equities.
12+
#
13+
# Legs:
14+
# 1. Long OIL — 35 bbl at ~$92/bbl ($3,220 notional)
15+
# 2. Long GOLD — 2 oz at ~$1,909/oz ($3,818 notional) — war safe haven
16+
# 3. Short SP500 — 1.5 units at ~$4,225 ($6,338 notional)
17+
#
18+
# The short leg is sized larger to roughly balance the two long legs.
19+
# Oil is the directional bet; gold is the defensive anchor.
20+
#
21+
# What happened: Oil surged to $115+ within 2 weeks (eventually $130
22+
# in March). Gold rallied to $2,050. The S&P 500 dropped ~3% in the
23+
# first week before stabilizing.
24+
#
25+
# Result: Both commodity legs profit on the supply shock, while the
26+
# equity short captures the initial risk-off move.
27+
#
28+
# Usage: ./examples/backtest/ukraine_oil_shock.sh
29+
#
30+
set -uo pipefail
31+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
32+
BT="${BACKTEST:-$SCRIPT_DIR/../../target/release/backtest}"
33+
34+
echo ""
35+
echo "══════════════════════════════════════════════════════════════"
36+
echo " Russia-Ukraine Invasion — February 24, 2022"
37+
echo " Long OIL + Long GOLD + Short S&P 500"
38+
echo "══════════════════════════════════════════════════════════════"
39+
echo ""
40+
41+
# ── Reset portfolio ────────────────────────────────────────────────
42+
$BT --at 2022-02-24 reset 2>/dev/null
43+
44+
# ── Scout: get prices on Feb 24, 2022 ─────────────────────────────
45+
echo "── Scouting prices on 2022-02-24 ──"
46+
echo ""
47+
48+
OIL_PRICE=$($BT --at 2022-02-24 --json '{"command":"quote","symbol":"OIL"}' 2>/dev/null | jq -r '.price')
49+
GOLD_PRICE=$($BT --at 2022-02-24 --json '{"command":"quote","symbol":"GOLD"}' 2>/dev/null | jq -r '.price')
50+
SP_PRICE=$($BT --at 2022-02-24 --json '{"command":"quote","symbol":"SP500"}' 2>/dev/null | jq -r '.price')
51+
52+
echo " OIL: \$$OIL_PRICE / bbl"
53+
echo " GOLD: \$$GOLD_PRICE / oz"
54+
echo " SP500: \$$SP_PRICE"
55+
echo ""
56+
57+
# ── Leg 1: Long crude oil — supply disruption ─────────────────────
58+
echo "── Leg 1: Long OIL (supply shock from sanctions) ──"
59+
$BT --at 2022-02-24 buy OIL --amount 35 --price "$OIL_PRICE"
60+
61+
# ── Leg 2: Long gold — geopolitical safe haven ────────────────────
62+
echo "── Leg 2: Long GOLD (war premium + safe haven) ──"
63+
$BT --at 2022-02-24 buy GOLD --amount 2 --price "$GOLD_PRICE"
64+
65+
# ── Leg 3: Short S&P 500 — risk-off selloff ──────────────────────
66+
echo "── Leg 3: Short S&P 500 (risk-off) ──"
67+
$BT --at 2022-02-24 sell SP500 --amount 1.5 --price "$SP_PRICE"
68+
69+
# ── Portfolio snapshot ─────────────────────────────────────────────
70+
echo "══════════════════════════════════════════════════════════════"
71+
echo " Portfolio Summary"
72+
echo "══════════════════════════════════════════════════════════════"
73+
$BT --at 2022-02-24 balance
74+
$BT --at 2022-02-24 positions
75+
76+
# ── Cleanup ────────────────────────────────────────────────────────
77+
$BT --at 2022-02-24 reset > /dev/null 2>&1

0 commit comments

Comments
 (0)