📉 Sub-$10 Pump SHORT — Strategy Honest Research

Дата: 28-04-2026 • Universe: $1-$10 prev_close, gap +10..+200% • 2y данных (Apr 2024 - Apr 2026)

⚠️ КРИТИЧЕСКИ ВАЖНО: Backtest grid врал

Оптимистичный grid (rr_grid_500k.json) показывал Sharpe 8-14 для $1-2.50. Honest данные с реальными exits (pump_short_moo_by_price): baseline Sharpe −2.15, потеря −212%/yr.

Разница из-за: (1) реальное моделирование стопов, (2) honest exits через bid в реальном времени, (3) включает halt-эффекты, (4) использует pm_close_vs_pc как proxy для open (более консервативно).

НО: с правильными фильтрами стратегия становится прибыльной. Найдено 2 рабочих стека.

🏆 Лучшие найденные стеки (HONEST)

Stack Sgap50 (главный)
Sh 13.64
$1-2.5, gap 50-100%, no halt • n=27 • WR 78% • +60%/yr
Stack S1_fading (backup)
Sh 5.05
$1-2.5, gap 20-50%, no halt, fading 09:00→09:25 • n=44 • WR 75-80% • +49%/yr
Без фильтров (baseline)
Sh −2.15
$1-10 universe, exit 11:00 — НЕ ТОРГОВАТЬ • WR 63% • −212%/yr
Универс: реальный N
71/yr
Combined 27 strong + 44 fading = ~71 trades/year

📖 Стратегия простыми словами

Что делаем: Шортим утренние пампы дешёвых стоков ($1-$2.50) которые УЖЕ начали разваливаться к открытию. Заходим через MOO в 09:30 ET, держим до 09:35-09:55 ET, выходим.

Какие пампы берём (3 правила обязательны):

Цена прев. закрытия $1-$2.50 — самая чистая зона. Дороже $2.50 — не работает (Sh negative). Дешевле $1 — нельзя зашортить (broker block).
Gap +20..+100% — слабые пампы (10-20%) не падают, экстрим (>100%) хайтит и locate fail.
Вчера НЕ было halt — has_halt=0 в pump_halt_history. Если был halt — фейдинг непредсказуемый.

Какие пампы НЕ берём (фильтры):

Цена <$1 — никогда. Locate <5%, broker block, спред 5-15%
Gap >100% — экстрим, halts spam. Это для отдельной pre-open стратегии
Вчера был halt — Sh −3.29 на этой группе
Высокая ликвидность Q4 (avg_vol >5M) — мега-pump событий, локально DD −127%/yr

Дополнительный сигнал-усилитель (опционально для S1):

Если в премаркете 09:00→09:25 цена УЖЕ ПАДАЕТ (direction_900_925 < 0) — «fading_pre» — это второй стек S1. Без падения = не входим.

Параметры исполнения:

Entry: SHORT через MOO ордер в 09:30 ET
Exit: 09:35 ET (если можно market) или 09:55 ET. Дальше держать НЕ выгодно.
BP per trade: $20-30K
Risk per trade: $150 (cap)
Max concurrent: 2-3 (события редкие, 71/yr ≈ 1-2 в неделю)

Ожидаемая прибыль (HONEST):

Stack S_gap50 (gap 50-100%): ~14 events/yr × +4% × $30K = $17K/yr
Stack S1_fading (gap 20-50, fading): ~22 events/yr × +2% × $30K = $13K/yr
Комбинированно: ~$25-30K/yr на $30K BP (ROI 80-100%, не 50% как грид показывал)

🗺️ Per-cell Heatmap (Sharpe by Price × Gap)

Зелёные — где работает SHORT MOO→11:00. Красные — теряют деньги. Только $1-2.50 даёт edge; зона $2.50-5 убыточна на любом gap'е.

⏱️ Exit Time Comparison — раньше выходить лучше

Все события (без фильтров)

Чем дольше держим, тем хуже. Эта эквити деградирует к 11:00. Пампы НЕ затухают — они ПРОДОЛЖАЮТСЯ к 11:00 ET (squeeze дальше).

На S_gap50 стеке (gap 50-100%, no halt)

На правильно отобранных событиях держать до 09:55 OK (Sh 13). Дальше тоже окей. Но 09:35 безопаснее — раньше exit меньше вариативность.

🎯 Pre-Open Direction — Главный фильтр

direction_900_925 — куда движется до open

Если в премаркете 09:00→09:25 цена ПАДАЕТ — отлично (fading_pre). Если РАСТЁТ — катастрофа (rallying_pre).

Логика сигнала

🟢 fading_pre (price 09:25 < price 09:00):
  Sh +0.45, WR 71%, +5%/yr
  = уже разворот, sellers активны
  = в SHORT с попутным ветром

🔴 rallying_pre (price 09:25 > price 09:00):
  Sh −5.07, WR 57%, −89%/yr
  = momentum жив до 09:25
  = обычно squeeze ещё 5-10% после open
  = SKIP не входим

🚦 Halt Filter

has_halt — был ли вчера/сегодня LULD halt

Влияние

ГруппаnSharpeWR$/yr%
no_halt274−1.8863%−150%
had_halt44−3.2964%−68%

Вывод: halt-events хуже даже несмотря на одинаковый WR. Слишком волатильно — большие losers съедают winners. SKIP if has_halt=1

💧 Liquidity (avg_vol_20d)

4 квартиля по средне-дневному объёму

Что показывает

Quartilevol range (20d avg)nShWR
Q1 low0 — 1.6M80−2.5156%
Q2 mid-low1.6M — 2.7M79−0.4367%
Q3 mid-high2.7M — 5.2M79−0.6068%
Q4 high>5.2M80−3.6661%

Surprise: Q4 high-volume = ХУДШИЙ. Это мега-pump события (e.g. squeeze candidates). Q2-Q3 mid-volume — спокойные затухания.

Соотношение к BP: Q1-Q3 = 1.5-5M shares avg = comfortable для $30K BP (поток в 1 минуту PM ≈ $50-200K, наш ордер <30%).

Soft filter: avg_vol_20d < 5M (skip Q4)

🕐 Теория «памп до 6:00 → шортить ближе к open» — РЕЗУЛЬТАТ

Что показали данные (vol_early_share)

Использовали как proxy: vol_early_share = доля PM объёма который произошёл в 04:00-07:00. Высокая = памп был "ранний", "stale" к 09:30.

Теория частично НЕ подтвердилась

Классvol_early доляnShWR
fresh0-20%163−2.8960%
mid_early20-40%69−1.4665%
early_majority40-60%52−0.8769%
stale>60%21−4.2357%

Парадокс: "early_majority" (40-60% объёма в раннем PM) — лучшая группа. Но "stale" (≥60%) — худшая.

Интерпретация: "stale" пампы (всё в early PM, ничего после 07:00) часто = sustained bid, реальный catalyst → в RTH продолжает расти. Это НЕ затухающий памп.

Вывод: Идея "ранний памп лучше шортить" работает только для "early_majority", не для extreme stale. Это выборочный фильтр, не основной.

Для production: добавить как мягкий boost (×1.2 size если early_majority), не hard-filter.

📋 Все проверенные факторы — Summary

ФакторЧто делатьЭффектConfidence
Цена <$1SKIP всегдаLocate <5%, broker blockHigh
Цена $1-$2.50PRIMARY zoneSingle positive cellHigh
Цена $2.50-$5SKIPAll cells negativeHigh
Цена $5-$10SKIPВсе strategies underperformMed
Gap <20%SKIPSh −5.01 на $1-2.5×10-20High
Gap 20-50%REQUIRE fading_pre filterSh 0.52 base, Sh 5.05 with filterHigh
Gap 50-100%CORE TRADES (best)Sh 13.64, WR 88%High
Gap >100%SKIP (для pre-open module)n <30, halt riskMed
has_halt = 1SKIP всегдаSh −3.29High
direction_900_925 < 0Сильный сигнал ENTERSh +0.45 baseline → Sh 5+ stackHigh
direction_900_925 > 0SKIPSh −5.07High
avg_vol_20d >5MSOFT skipSh −3.66 в Q4Med
vol_early_share 40-60%BOOST sizeLowest negative classLow
vol_early_share >60%SKIP"sustained bid" pumps continueMed
exit_935 / exit_955USEШире окно после = деградацияHigh
exit_1100AVOID на baselineХорошо ТОЛЬКО на правильно отобранныхHigh

🚀 Action Plan

✅ Phase 1 — DEPLOY: stack S_gap50 + S1_fading

Что: Запустить paper-trading на 1 месяц с обоими стеками одновременно. Цель — подтвердить Sh ≥ 3 на live данных.

Universe фильтр:

def is_eligible(event):
    # HARD SKIPs
    if event.prev_close < 1.0: return False, "sub_1$"
    if event.prev_close >= 2.5: return False, "above_2.5$"
    if event.gap_pct < 20: return False, "gap_too_small"
    if event.gap_pct >= 100: return False, "extreme_pump_skip"
    if event.has_halt == 1: return False, "halt_yesterday"
    if event.avg_vol_20d > 5_000_000: return False, "high_volume_squeeze_risk"

    # STACK selection
    if event.gap_pct >= 50:
        return True, "S_gap50"  # primary stack — gap 50-100
    if event.direction_900_925 < 0:
        return True, "S1_fading"  # gap 20-50 + fading pre
    return False, "gap_2050_no_fading"

Параметры:

ParamValueReason
EntrySHORT MOO 09:30 ETBacktested base
Primary exit09:35 ET marketSh max в обоих stacks
Backup exit09:55 ET если 09:35 missedSh ≈ same
Hard cutoff11:00 ETRisk control
BP / trade$20-30KLiquidity safe
Risk / trade$150Cap
Max concurrent2-3~71 events/yr ≈ 1-2/week
SL / TP0.5% / 2%From original grid (still valid for $1-2.5)

🟡 Phase 2 — RESEARCH: Pre-open SHORT для gap >100%

Текущий dataset имеет 26 событий gap 100-200% в $1-10 (n меньше 30 порога). Эти extreme пампы исключены из текущей стратегии. Открываем отдельный pipeline:

Universe: $1-10, gap >100%, vol_early ≥ 0.5
Entry: SHORT в премаркете 08:00-09:00 (когда ясно, что HOD позади)
Exit: 09:30 при open OR при достижении +5% TP
Локационный заранее: через broker API проверить locate в 07:30
Need data: pump_pre_open_entries (есть!) + halt_history + locate_check

🟡 Phase 3 — RESEARCH: Day-2 fade ($1-10)

Идея с прошлого обсуждения: вчера +50% pump, сегодня open флет/-10%. Не в текущем dataset напрямую (need prev_day_high enrichment).

Build: events_day2_fade.parquet через merge с прошлым днём pump_events
Expected: 150 events/yr, Sh 4-6, +$15-25K/yr на $20K BP
Преимущество: locate clears overnight, лучше execution чем fresh pumps

🟡 Phase 4 — API control layer

КонтрольПокрывает
Locate-check pre-tradeCancel SKIP if no locate available (prevent failed orders)
Halt-aware exitForce close on resume after halt (don't wait for stop)
Spread blowout cancelCancel MOO if spread >1% at 09:29:55
PM stop-loss ordersPlace STOP-LIMIT в PM for late-entered shorts (Day-2 fade)
Real-time P&L circuitAlready in adaptive_risk_gates.py — wire to new module
Telegram /overrideManual kill switch via existing TG bot

📅 По годам — стабильность

Stack S1 fading per year

YearnMean exit_1100WR
2024 (Apr-Dec)10+7.00%100%
2025 (full)27−0.73%70%
2026 (Jan-Apr)7+5.96%86%

2025 — слабый год. Возможно regime shift. 2024 и 2026 сильны. Need watch — если 2026 H2 деградирует, переоценить.

Honest expected forward

Conservative: применяем 2025 weak year как baseline → ~$10-15K/yr

Balanced: 3y average → $25-30K/yr

Aggressive: 2026 trend → $35-40K/yr (вряд ли устойчиво)

Capital allocation:

$30K dedicated BP (1-2 concurrent позиции одновременно)
ROI honest: 30-50%/yr
DD expected: −$1.5K to −$3K на стек

💻 Reference Code

Минимальный scorer для production

# broker/strategies/moo_1100_sub10/scorer.py
from typing import Optional, Tuple

HARD_PRICE_FLOOR = 1.0
HARD_PRICE_CEIL = 2.5  # exclusive
GAP_MIN = 20.0
GAP_MAX = 100.0  # exclusive
GAP_STRONG = 50.0  # gap_pct >= 50 → automatic eligible
HIGH_VOL_FLOOR = 5_000_000

def score_sub10_pump(event) -> Tuple[bool, str, dict]:
    """Returns (eligible, stack_name, params)"""
    # Hard skips
    if event.prev_close < HARD_PRICE_FLOOR:
        return False, "skip_below_floor", {}
    if event.prev_close >= HARD_PRICE_CEIL:
        return False, "skip_above_ceiling", {}
    if event.gap_pct < GAP_MIN or event.gap_pct >= GAP_MAX:
        return False, "skip_gap_oob", {}
    if event.has_halt:
        return False, "skip_halt", {}
    if event.avg_vol_20d and event.avg_vol_20d > HIGH_VOL_FLOOR:
        return False, "skip_high_vol", {}

    # Stack selection
    if event.gap_pct >= GAP_STRONG:
        return True, "S_gap50", {
            "tp_pct": 0.02, "sl_pct": 0.005,
            "primary_exit": "09:35", "hard_cutoff": "11:00",
            "bp": 30_000, "size_mult": 1.0,
        }
    if event.direction_900_925 is not None and event.direction_900_925 < 0:
        return True, "S1_fading", {
            "tp_pct": 0.02, "sl_pct": 0.005,
            "primary_exit": "09:35", "hard_cutoff": "09:55",
            "bp": 25_000, "size_mult": 0.8,
        }
    return False, "skip_no_signal", {}

📁 Источники данных

ФайлЧто использовали
pump_short_moo_by_price.parquet4234 SHORT MOO trades с реальными exits 09:35-11:00 — основной honest источник
pump_pm_accumulation_long.parquet858 events с timing breakdown (vol_early/mid/late share)
pump_halt_history.parquet4359 events with has_halt, n_luld_pause
pump_pre_open_entries.parquet2575 events с p_900, p_925, direction_900_925
events_v2.parquet (asym v2)3200 events для общего grid (сравнить с honest)

Output files:

research_results/engine_v1_rerun_apr27/sub10_full_results.json
research_results/engine_v1_rerun_apr27/sub10_master.parquet
research_results/engine_v1_rerun_apr27/sub10_grid.json