|
|
# ORB (Opening Range Breakout) Strategy — Default Configuration
|
|
|
# Strategy: Buy breakout of first 5-min candle high (bullish candles only).
|
|
|
# Uses ATR-based stops, risk-based position sizing, 15:55 ET time exit.
|
|
|
# Based on ORB academic research adapted for available data infrastructure.
|
|
|
|
|
|
strategy_mode: orb
|
|
|
|
|
|
orb_strategy:
|
|
|
# ORB window
|
|
|
orb_minutes: 5 # 9:30–9:35 ET opening range
|
|
|
sim_bar_minutes: 30 # 30-min bars for breakout/stop management (ORB candle stays 5-min)
|
|
|
|
|
|
# Entry
|
|
|
entry_direction: long_only # bullish candle only (V1; 'candle' for both directions)
|
|
|
order_timeout_minutes: 45 # cancel if no fill by 10:15 ET
|
|
|
|
|
|
# Universe quality filters (applied during pre-screening)
|
|
|
min_price: 10.0 # $10+ stocks only
|
|
|
min_avg_dollar_volume: 25000000 # $25M 30-day avg daily dollar volume
|
|
|
min_atr_14: 0.50 # ATR(14) > $0.50 (sufficient range to trade)
|
|
|
|
|
|
# RVOL-based candidate selection
|
|
|
min_rvol: 1.0 # minimum approx RVOL at open (see note in features.py)
|
|
|
max_candidates: 20 # top N candidates per day
|
|
|
min_candidates_to_trade: 3 # skip day if fewer qualify
|
|
|
|
|
|
# Composite ranking weights (must sum to 1.0)
|
|
|
weight_rvol: 0.60 # relative volume (main signal)
|
|
|
weight_gap: 0.25 # gap% (proxy for premarket activity)
|
|
|
weight_dollar_vol: 0.15 # first-bar dollar volume
|
|
|
|
|
|
# ATR-based stop management
|
|
|
atr_stop_multiplier: 0.50 # initial stop = ATR(14) × 50% from entry
|
|
|
breakeven_at_r: 1.0 # move stop to entry at +1R
|
|
|
trailing_at_r: 2.0 # activate trailing stop (3-bar swing low) at +2R
|
|
|
|
|
|
# Risk-based position sizing
|
|
|
risk_per_trade_pct: 0.0025 # 0.25% of equity per trade
|
|
|
max_position_pct: 0.20 # cap at 20% of equity per position
|
|
|
daily_max_loss_pct: 0.0125 # stop trading at -1.25% daily loss
|
|
|
max_stops_per_day: 3 # stop trading after 3 full-R stops
|
|
|
|
|
|
# Exit
|
|
|
exit_minutes_before_close: 5 # time exit at 15:55 ET
|
|
|
|
|
|
# Execution
|
|
|
slippage_bps: 5.0 # 0.05% one-way slippage (both entry and exit)
|
|
|
initial_capital: 10000 # $10,000 starting capital
|
|
|
ticker_cooldown_days: 0 # no cooldown (ORB trades daily runners)
|
|
|
|
|
|
# Cash account GFV (Good Faith Violation) constraint
|
|
|
# Unsettled proceeds can buy but not same-day sell → ORB always exits same day
|
|
|
# → only settled cash is usable. 0=disabled, 1=T+1 (US since May 2024), 2=T+2
|
|
|
settlement_days: 1
|
|
|
|
|
|
# Max opening gap filter: exclude stocks that gapped up more than this at open.
|
|
|
# Stocks with large gaps are over-extended and show low breakout continuation rate.
|
|
|
# Sweep result: 3% >> 5% >> 10% in Sharpe (5.59 vs 4.50 vs 3.74).
|
|
|
max_gap_pct: 0.03
|
|
|
|
|
|
# Market regime: skip days when index gaps down > threshold at open
|
|
|
# Sweep result: SPY -0.5% filter hurts absolute return with minimal Sharpe gain.
|
|
|
# Individual ORB candidates can surge even on weak-SPY days (e.g. sector rotation).
|
|
|
market_regime_spy_threshold: null # disabled — breadth filter below is superior
|
|
|
|
|
|
# Candidate breadth filter: skip day if <N% of candidates opened above prev close.
|
|
|
# Sweep: Breadth≥30% → Sharpe 19.86 but return +520% vs +676% with no filter.
|
|
|
# Existing per-trade risk controls (ATR stop, daily loss limit) are sufficient.
|
|
|
min_candidate_breadth: null
|
|
|
|
|
|
universe:
|
|
|
source: midlarge # 971-ticker mid+large cap universe
|
|
|
min_price: 10.0 # redundant with orb_strategy.min_price but explicit
|
|
|
|
|
|
backtest:
|
|
|
start_date: null # null = auto (today - lookback_trading_days)
|
|
|
end_date: null
|
|
|
lookback_trading_days: 200 # ~10 months
|
|
|
pre_screen_threshold: 0.01 # not used by ORB mode (kept for config compatibility)
|
|
|
|
|
|
cache:
|
|
|
enabled: true
|
|
|
dir: data/cache/intraday
|
|
|
|
|
|
output:
|
|
|
dir: runs/intraday_orb
|
|
|
verbose: false
|