Files
momentum-system/deploy/docker/overrides.live.seed.env
T
momentum devandClaude Opus 5 45b0386347 feat: rank gappers by premarket range, the one measured predictor
Over 1,040 screened symbol-days (2026-08-01 on), asking which premarket
property predicts the session running >=50% open-to-high:

    premarket range   n     avg run   ran >=50%
    >= 30%           201     34.7%      15.9%
    15-30%           136     28.3%      14.7%
     5-15%           303     15.2%       5.9%
      < 5%           400     16.8%       4.3%

A name that already travelled >=15% premarket is 3.1x more likely to run
>=50% (15.4% vs 5.0%) -- the largest single lift in this dataset, and free:
it comes off minute bars the arm pass has already fetched.

Two findings constrain the shape:

  - It is a STEP at 15%, not a gradient (15-30% and >=30% are 14.7 vs 15.9;
    5-15% and <5% are 5.9 vs 4.3). So the multiplier is a threshold. A linear
    scale would invent precision the data does not support.

  - Premarket VOLUME carries NO signal (10.0/4.2/7.9/9.0% across participation
    buckets, non-monotonic) and raw premarket volume runs inversely to the
    outcome. scanner_snapshots.premarket_volume being NULL costs nothing;
    range is the field that mattered all along.

Do not expect 3x. Replaying armed-set selection over the same 29 sessions,
top-5 by mean/median run and >=50% runners captured out of 145 slots:

    gap x rvol (baseline)        39.77% / 10.97%   27
    x3.0 if PM range >= 15%      42.00% / 13.16%   32
    HARD FILTER >= 15%           37.27% / 12.67%   24   <- worse
    PM range alone               32.86% / 12.65%   20   <- much worse

gap x rvol already encodes much of the same information, so the marginal gain
is ~+2 points of mean run and 4-5 extra big runners per 145 slots. It is
BOOST-only for a reason: gating on this feature scored below baseline, and it
must never replace gap/rvol. Every threshold in 10-20% and gain in 1.5-5.0 beat
baseline -- a flat plateau, so not fitted. The shipped 15%/3.0x are the measured
step and the measured lift, not the sweep's peak cell.

Fail-open: an unknown range yields a neutral 1.0, never a penalty.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2LepdJfPCfK5Q8uznjFBM
2026-09-13 19:16:17 -05:00

119 lines
5.1 KiB
Bash

# Seed for /app/data/overrides.env on the LIVE stack — the admin panel
# (port 8867.. n/a on live; edit via file or add admin service) manages this.
# Every service loads it at boot; overrides BEAT compose env.
ALPACA_DATA_FEED=sip
DISCOVER_INTERVAL_SECONDS=120
DISCOVER_THREAD_ENABLED=1
LIVE_BARS_INTERVAL_SECONDS=5
LIVE_BARS_REFRESH_MINUTES=20
NEWS_CATALYST_SCORE_ENABLED=1
NEWS_DILUTION_VETO_ENABLED=1
NEWS_ENRICH_BATCH_LIMIT=50
NEWS_ENRICH_ENABLED=1
NEWS_ENRICH_INTERVAL_SECONDS=120
NEWS_ENRICH_LOOKBACK_HOURS=12
NEWS_FEEDS=prnewswire=https://www.prnewswire.com/rss/news-releases-list.rss,businesswire=https://feed.businesswire.com/rss/home/?rss=G1QFDERJXkJeGVtRWQ==,globenewswire=https://www.globenewswire.com/RssFeed/orgclass/1/feedTitle/GlobeNewswire%20-%20News%20about%20Public%20Companies
NEWS_LOOKBACK_HOURS=8
NEWS_RANK_BOOST=2.0
# Ollama lives on 11434 (the standard port). The stack pointed at 30068/4000 with
# a model that was never pulled, so catalyst enrichment produced nothing from
# 2026-08-03 to 2026-09-13 — silently, because enrich_recent_news reports failure
# in its return value rather than raising. Smoke-tested 2026-09-13: tools:latest
# parses 8/8 headlines in ~2.8s each and classifies offering_dilution / fda_approval
# correctly. Verify the model is pulled before changing either line.
OLLAMA_ENABLED=true
OLLAMA_HOST=http://192.168.1.5:11434
OLLAMA_MODEL=tools:latest
OLLAMA_TEMPERATURE=0.1
OLLAMA_TIMEOUT_SECONDS=60
TRADING_AUTO_APPROVE=1
TRADING_BACKOUT_COOLDOWN_SECONDS=180
TRADING_BLOCK_REENTRY_AFTER_EXIT=1
TRADING_ENTRY_CONFIRM_BY_MINUTE=0
TRADING_ENTRY_FILL_MODEL=marketable
TRADING_ENTRY_INVALIDATE_PCT=0.015
TRADING_ENTRY_ORDER_TYPE=limit
TRADING_ENTRY_TIMEOUT_BARS=2
TRADING_EOD_FLATTEN_ENABLED=1
TRADING_EOD_FLATTEN_TIME=15:55
TRADING_EXECUTION_ENABLED=1
# EXIT MANAGEMENT — retuned 2026-09-13. The previous config stacked FOUR
# independent ratchets (BE@+5% from the env default, step-trail every 0.25R,
# prior-low trail, and profit-lock tiers). Together they capped every winner at
# ~1R: over 62 live + 172 paper trades the bot kept only 9.3% of the move on
# trades that ran >=20%, and held winners a median 10 min vs 19 min for losers.
# Replaced with a single percentage giveback that starts only after +1R. The
# 8/12/15/20% neighbourhood all beat the old config on BOTH stacks in BOTH
# train and test splits (mean R 0.20-0.25 vs 0.125), so 12% is a plateau pick,
# not a fitted one. Re-sweep with sweep_exits.py before changing.
TRADING_EXIT_BREAKEVEN_R=1.0
TRADING_EXIT_BREAKEVEN_PCT=0.0
TRADING_EXIT_MANAGE_INTERVAL_SECONDS=4
TRADING_EXIT_PROFIT_TIERS=
TRADING_EXIT_THREAD_ENABLED=1
TRADING_EXIT_THREAD_INTERVAL_SECONDS=1.0
TRADING_EXIT_TRAIL_AFTER_R=1.0
TRADING_EXIT_TRAIL_MODE=pct
TRADING_EXIT_TRAIL_PCT=0.12
TRADING_EXIT_TRAIL_R_STEP=0.0
TRADING_LIQUIDITY_MAX_VOLUME_PCT=0.025
TRADING_MAX_BACKOUTS_PER_SYMBOL=3
TRADING_MAX_CONCURRENT_POSITIONS=10
TRADING_MAX_DAILY_LOSS_PCT=0.05
TRADING_MAX_FRESH_ENTRIES_PER_DAY=10
TRADING_MAX_GROSS_NOTIONAL_PCT=0.60
TRADING_MAX_ORDERS_PER_TICK=1
TRADING_MAX_POSITION_PCT=0.16
# Boot-time sizing fallback. calculate_position_size falls back to this ONLY when
# equity was never readable; at the old 100000 a boot inside Tradier's ~01:06
# maintenance window (equity reads 0.0 there — 16 times in 14 days) would have
# sized 5% of 100k on a ~$250 account. Keep it BELOW real account equity so the
# fallback can only ever under-size (live equity 241.75 on 2026-09-13).
TRADING_DEFAULT_EQUITY=200
TRADING_MAX_RISK_DOLLARS=50000
TRADING_MIN_DAY_VOLUME=300000
TRADING_MIN_ENTRY_GAP_PCT=0.10
TRADING_MIN_QUALITY_SCORE=0.60
# PREMARKET-RANGE RANK BOOST (2026-09-13). A name that already travelled >=15%
# premarket ran >=50% on the day 15.4% of the time vs 5.0% for the rest -- a 3.1x
# lift, the largest single predictor measured over 1,040 screened symbol-days.
# Replaying the armed-set selection, the gain is real but modest (mean run of the
# top-5 armed 39.8% -> 42.0%, 27 -> 32 big runners per 145 slots) because gap x
# rvol already encodes much of it. BOOST only: a hard filter on the same feature
# scored WORSE than baseline. Set TRADING_PM_RANGE_BOOST=0 to disable.
TRADING_PM_RANGE_BOOST=1
TRADING_PM_RANGE_MIN_PCT=15.0
TRADING_PM_RANGE_GAIN=3.0
TRADING_PRICE_MAX=20.0
TRADING_PRICE_MIN=2.0
TRADING_REENTRY_MIN_LOSS_PCT=0.01
TRADING_REGIME_GATE_ENABLED=0
TRADING_REGIME_GATE_P_MIN=0.5
TRADING_REQUIRE_ABOVE_VWAP=1
TRADING_REWARD_MULTIPLE=10.0
TRADING_RISK_PER_TRADE_PCT=0.05
TRADING_SESSION_ONLY=1
TRADING_TRIGGER_SLIP_PCT=0.004
TRADING_UNIFIED_ENTRY=1
TRIGGER_ARM_INTERVAL_SECONDS=8
TRIGGER_ENABLED=1
TRIGGER_GAP_MAX=35
TRIGGER_GAP_MIN=10.0
TRIGGER_GAP_SQUEEZE_MIN=150
TRIGGER_GAP_SQUEEZE_RVOL=5.0
TRIGGER_INTERVAL_SECONDS=2
TRIGGER_MAX_ARMED=10
TRIGGER_MIN_DOLLAR_VOL=8000
TRIGGER_PRICE_MAX_AGE=12
TRIGGER_RVOL_MIN=2.0
# Apply the shared tradeable-population gate before the watcher scores anything.
# Without it the watcher wrote 191,458 criteria receipts across 57 symbols on
# 2026-09-10, 80.6% of them for names outside the gap band. Set 0 to restore the
# old evaluate-everything behaviour.
WATCHER_POPULATION_GATE=1
WATCHER_ENABLED=1
WATCHER_INTERVAL_SECONDS=8
WATCHER_PRICE_MAX=20
WATCHER_PRICE_MIN=2