_meta:
  id: 109
  name: "ORB Gainers V41 OBV Filter"
  status: candidate
  live_readiness: experimental
  parent: orb_gainers_v24_quality_overlay
  description: >
    V24 → V41: converts the OBV-slope weight into a HARD FILTER.

    V24 uses OBV-slope as a continuous scoring weight (weight_obv_slope: 0.05).
    V41 keeps the weight AND adds min_obv_slope_20d: 0.0 to filter out candidates
    in active distribution (negative OBV slope = institutions selling net).

    Hypothesis: stocks with OBV_slope_20 < 0 represent institutional distribution.
    Even if they rank well on rvol/gap/premarket, entering a distributing stock on
    a gap-up is a lower-quality setup. Filtering them out improves trade quality
    at the cost of some volume reduction.

    The filter is additive to (not replacing) the weight.
    All other V24 params unchanged.

    Gates (200d): Return ≥ +98.8% (V24 +94.8% + 4pp), DD ≥ -11.79%, Sharpe ≥ 2.93
    Gates (400d): Return ≥ +166.1% (V24 +162.1% + 4pp), DD ≥ -14.20%, Sharpe ≥ 2.52

strategy_mode: orb

orb_strategy:
  engine_family: gainers_leader
  live_readiness: experimental
  orb_minutes: 5
  sim_bar_minutes: 5

  entry_direction: long_only
  order_timeout_minutes: 45

  allow_doji_breakout: true
  allow_red_to_green_breakout: true

  min_price: 10.0
  min_avg_dollar_volume: 25000000
  min_atr_14: 0.50
  min_atr_pct: 0.04

  min_rvol: 1.5
  min_abs_gap_pct: 0.02
  min_premarket_dollar_vol: 1500000
  max_candidates: 20
  max_candidates_per_sector: 3
  min_candidates_to_trade: 1
  ticker_cooldown_days: 0
  max_gap_pct: 0.04

  min_candidate_breadth: 0.60
  market_regime_spy_threshold: 0.0015
  market_regime_ticker: QQQ
  rolling_loss_days: 7
  rolling_loss_threshold: -0.07
  max_simultaneous_entries: 3
  min_breakout_rel_vol: 1.2

  weight_rvol: 0.35
  weight_gap: 0.20
  weight_dollar_vol: 0.05
  weight_premarket_dollar_vol: 0.25
  weight_body_ratio: 0.0
  weight_momentum: 0.15
  weight_obv_slope: 0.05

  # V41 change: hard filter — only trade stocks in accumulation (positive OBV slope)
  min_obv_slope_20d: 0.0

  atr_stop_multiplier: 0.75
  breakeven_at_r: 1.0
  trailing_at_r: 1.0
  trailing_stop_atr_multiplier: 0.8
  trailing_tighten_at_r: 2.0
  trailing_stop_atr_multiplier_tight: 0.3

  partial_exit_at_r: 99.0
  partial_exit_pct: 0.50

  risk_per_trade_pct: 0.05
  max_position_pct: 0.70
  daily_max_loss_pct: 0.05
  max_stops_per_day: 5
  exit_minutes_before_close: 5

  slippage_bps: 5.0
  initial_capital: 10000

  compound_returns: false
  daily_budget_reset: true
  settlement_days: 1

  drawdown_governor_threshold: 0.025
  drawdown_governor_min_scale: 0.30

  streak_sizing_win_bonus: 0.70
  streak_sizing_max: 2.5

universe:
  source: midlarge

backtest:
  start_date: null
  end_date: null
  lookback_trading_days: 200

cache:
  enabled: true
  dir: data/cache/intraday

output:
  dir: runs/intraday_orb
  verbose: false
