This is a crypto-focused research and shadow paper trading bot using public OKX market data.
It is still research and paper trading first. Do not treat generated candidates as investment advice.
Crypto bars come from OKX public market data by default, so no API key is required for research candles:
python src/cache_okx_bars.py \
--symbols LINK-USDT,BTC-USDT,ETH-USDT,SOL-USDT,AVAX-USDT,NEAR-USDT,FARTCOIN-USDT-SWAP \
--timeframe 2Min \
--start 2024-06-22T00:00:00ZUseful timeframes:
2Minfor fast crypto scans.5Minor15Minif2Minis too noisy.1Hourfor slower swing-style research.
Cached files are written under:
data/okx/2Min/BTC_USDT.csv
OKX symbols use dash format, such as BTC-USDT. Filenames use underscores.
The default basket is:
LINK-USDT, BTC-USDT, ETH-USDT, SOL-USDT, AVAX-USDT, NEAR-USDT, FARTCOIN-USDT-SWAP
FARTCOIN-USDT-SWAP is a swap market on OKX, while the others are spot markets.
The broader research universe lives in:
config/okx_universe.txt
It includes larger names plus higher-beta coins such as SUI, APT, SEI, WIF, PEPE, BONK, HYPE, and FET.
For a quick pipeline test before the full two-year backfill:
python src/cache_okx_bars.py \
--symbols LINK-USDT,BTC-USDT \
--timeframe 2Min \
--start 2026-06-01T00:00:00Z \
--max-pages 20The default two-year research window is:
Full data: 2024-06-22 -> 2026-06-22
Training: 2024-06-22 -> 2025-12-22
Forward test: 2025-12-22 -> 2026-06-22
The pattern report favors setups that survive both the training period and the most recent six-month forward test.
The default acceptance rule is deliberately stricter than raw win rate:
training trades >= 30
forward-test trades >= 10
training win rate >= 50%
forward-test win rate >= 55%
forward-test profit factor >= 1.2
forward-test fixed-$10k PnL > $0
The report writes profitable_candidates.csv for setups that pass the forward-test money filters.
The forward-looking screen is:
python src/forward_watchlist.py \
--report-dir reports/pattern_lab_crypto_intraday \
--cache-dir data/okx/1Hour \
--out reports/forward_watchlist.csvIt uses strategies that survived the six-month forward test, then checks the latest candles for active or near-entry setups. It also includes recent BTC/ETH movement and a market_flush flag for altcoin support-reversal trades after BTC/ETH dumps.
Create .env from .env.example if you want to customize symbols or report settings, then run:
python3 -m venv venv
venv/bin/pip install -r requirements.txt
source venv/bin/activate
scripts/run_bot_cycle.shThe cycle:
- Caches recent
2Mincrypto bars. - Runs the pattern lab against the cached intraday bars.
- Writes candidates to
reports/pattern_lab_crypto_intraday/current_candidates.csv. - Posts a Discord scanner summary if
DISCORD_WEBHOOK_URLis configured.
For an unbiased forward test, freeze a strategy snapshot and only judge trades that happen after the freeze:
python src/freeze_optimizer_strategies.py \
--out config/frozen_strategies/candidate_v1.csvRun one local shadow cycle:
scripts/run_shadow_paper_cycle.shThis refreshes the required OKX 1Hour and 15Min caches, then updates:
reports/shadow_paper/candidate_v1/account_summary.csv
reports/shadow_paper/candidate_v1/open_positions.csv
reports/shadow_paper/candidate_v1/closed_trades.csv
reports/shadow_paper/candidate_v1/latest_actions.csv
The frozen candidate_v1 setup uses $100k starting cash, $20k max per position, and at most 5 open positions. It does not place real orders.
For scheduled runs on macOS, use the example plist:
scripts/com.tradingbot.shadow-paper.example.plist
The direct launchd job uses src/shadow_paper_cycle.py, which refreshes the required OKX candles first and then runs the frozen shadow trader. The scheduled setup uses closed-candle entry references for reliability, while signals are still based on confirmed candles.
If DISCORD_WEBHOOK_URL is set in the LaunchAgent environment, src/shadow_paper_trader.py posts alerts for paper opens/closes/partial targets and high-scoring near setups. Near setup alerts are de-duplicated by symbol, timeframe, strategy, and candle. Alerts include est_win, which is the strategy's historical win rate estimate, preferring recent validation when it has at least 5 trades, then validation, forward holdout, and training.
Live entry checks use a recent confirmed-candle window, currently --signal-lookback-bars 12, rather than only the latest candle. If a signal is older than the latest candle, the trader can still enter only when the current close has not chased more than --max-entry-chase-pct 0.015 above the signal close. Discord alerts include age, the number of confirmed bars since the signal candle.
Actual paper entries are forward-gated by default: the frozen strategy row must have at least --min-entry-forward-trades 3, --min-entry-forward-pf 1.05, and positive forward_fixed_pnl. Near alerts can still show weaker or unproven setups for manual review, but the paper account will not auto-enter them.
For the first historical research run, use:
scripts/run_research_backfill.shThat backfills from BACKTEST_START, then runs the 18-month training / 6-month forward-test report.
For frequent idea refreshes after the historical cache exists, use:
scripts/run_live_scan.shThat refreshes the last few days of OKX candles, reruns the scanner, and updates the candidate report.
Change symbols or timeframe without editing the script:
CRYPTO_SYMBOLS="LINK-USDT,BTC-USDT,ETH-USDT,SOL-USDT" CRYPTO_TIMEFRAME=5Min scripts/run_bot_cycle.shTo test the data path without doing the full two-year pull:
OKX_MAX_PAGES=20 scripts/run_research_backfill.shRemove OKX_MAX_PAGES or set it to 0 for the full backfill.
To backfill and test the broader universe on native 1-hour candles:
CRYPTO_TIMEFRAME=1Hour OKX_BAR=1H scripts/run_research_backfill.shTo test more responsive charts, use native 15-minute candles:
CRYPTO_TIMEFRAME=15Min OKX_BAR=15m scripts/run_research_backfill.shAfter cached bars exist, run local TP/SL/hold-time sweeps without printing every test to chat:
venv/bin/python src/strategy_optimizer.py \
--rounds 20 \
--population 220 \
--survivors 32 \
--out-dir reports/optimizer_runs/run_20_coreThe optimizer writes ranked candidates, round summaries, signal caches, and portfolio replays under the output folder. Reusing the same folder lets it reuse cached signal timestamps.
- Crypto trades 24/7, so cached crypto bars are not filtered to exchange sessions.
- The pattern lab still uses the argument name
--signal-timeframe hourly; in this project it means intraday cached bars, not necessarily one-hour bars. - Local paper trading supports fractional crypto units.