Adding a Strategy
Every strategy in Gordon follows a strict promotion flow from initial research to live trading. No shortcuts. A strategy that skips validation steps will eventually fail in production.
Promotion flow
Research idea (gordon-lab, Python)
|
v
Level 1 — Signal quality gate
| Sharpe > 0.5, walk-forward consistency > 50%
v
Level 2 — Realistic simulation
| Max DD < 30%, positive CAGR, 1-bar delay enforced
v
Walk-forward validation (rolling windows, no random splits)
v
Ablation analysis (every component must prove lift)
v
Multi-asset validation (BTC, ETH, SOL minimum)
v
Rust implementation in gordon-strategy
v
Backtest via gordon-manager BFF (byte-parity gate)
v
Binance testnet validation (30+ trades minimum)
v
Micro live allocation (progressive)
v
Full live allocationFile layout (mandatory)
The gordon-strategy CLAUDE.md mandates a specific directory structure. Every strategy must follow it, no exceptions:
gordon-strategy/
└── src/
└── engines/
└── <name>/
├── mod.rs # Strategy implementation (required)
├── tests.rs # Unit + parity tests (required)
└── fixtures.rs # Golden-file fixtures (if needed)No flat <name>.rs peers at the parent level. No orphan fixture files outside the strategy folder.
Implement the Strategy trait
use gordon_strategy::{Strategy, MarketContext, Signal, SizeHint, StrategyError, StrategyParams};
pub struct MyStrategy {
params: MyStrategyParams,
// internal state
}
impl Strategy for MyStrategy {
fn name(&self) -> &'static str { "my_strategy" }
fn params_schema() -> serde_json::Value { /* JSON schema */ }
fn evaluate(
&mut self,
ctx: &MarketContext,
) -> Result<Option<Signal>, StrategyError> {
// pure math over ctx.klines, ctx.funding_rates, ctx.open_interest
// emit Signal only on entry/flip, not every bar
// SizeHint::VolatilityTarget or SizeHint::Fixed
}
}Key constraints from gordon-strategy invariants:
- No I/O, no HTTP, no exchange dependency, no
tokio::spawn - No
#[allow(...)]— fix the warning - Deterministic: same candles + same params must produce byte-identical
Signalsequences - No
SystemTime::now(), norand::*, no non-deterministic iteration on the evaluation path
Register in StrategyRegistry
Add the strategy to gordon-strategy/src/engines/registry.rs:
registry.register("my_strategy", || Box::new(MyStrategy::new(Default::default())));Both gordon-bot (live loop) and gordon-manager (backtest replay) share this registry at startup.
Walk-forward validation pipeline (gordon-lab)
Research and validation happen in gordon-lab (Python). Provide gordon-lab with:
- Strategy parameters — the tuned values from research
- Signal logic — a Python reference implementation of the entry/exit conditions
- Risk parameters — stop loss formula, position sizing rules
gordon-lab runs:
- Level 1: signal quality test (no risk management, full allocation, measure Sharpe + WF consistency)
- Level 2: realistic simulation with the risk management system (stop loss, ATR-based sizing, 1-bar delay)
- Walk-forward: rolling windows, never random splits
- Ablation: test each overlay and filter independently
Pass criteria before proceeding to Rust implementation:
- Sharpe > 0.5
- Walk-forward consistency > 50%
- Max drawdown < 30%
- Positive CAGR
- Multi-asset validation (BTC, ETH, SOL at minimum)
Backtest via gordon-manager BFF
After implementing in Rust, verify the backtest output matches gordon-lab's Python output:
curl -X POST http://localhost:8083/backtest \
-H "Authorization: Bearer dev-operator-token" \
-H "Content-Type: application/json" \
-d '{
"strategy": "my_strategy",
"symbol": "BTCUSDT",
"timeframe": "1d",
"from_ts": 1704067200000,
"to_ts": 1735689600000,
"params": { ... }
}'The BacktestExecution engine uses the same Strategy::evaluate path as the live bot. If the backtest output differs from gordon-lab's Python output, fix the Rust implementation — not the Python reference.
Binance testnet validation
Before any live capital:
- Deploy the strategy to a testnet gordon-bot container (configure
BINANCE_TESTNET=true) - Run for at least 30 trades
- Compare fill behavior, SL triggering, and PnL to backtest expectations
- Review logs for anomalies via gordon-console or Grafana
There is no paper-trading mode in v7. Binance testnet is the forward-test gate.
Promote to live
After testnet validation is clean:
- Start with a micro allocation (1% of account)
- Monitor for 2–4 weeks against testnet behavior
- Scale to full allocation once live behavior matches expectations
Checklist
Before submitting a strategy for production promotion:
- [ ] Level 1 test passed (Sharpe > 0.5, WF consistency > 50%)
- [ ] Level 2 test passed (max DD < 30%, positive CAGR, 1-bar delay)
- [ ] Walk-forward validated with rolling windows (not random splits)
- [ ] Ablation analysis completed (every component justified)
- [ ] Multi-asset validation (BTC, ETH, SOL minimum)
- [ ] Strategy contract documented (parameters, signal logic, risk params)
- [ ] Results net-of-fees (all results include transaction costs and funding)
- [ ] Rust implementation follows mandatory directory layout
- [ ] Registered in
StrategyRegistry - [ ] Byte-parity test passes (
cargo testin gordon-strategy) - [ ] Binance testnet validation complete (30+ trades)