# BRIEF: Catching the Big Winners
## Steve Bot V2.0 — 15-Minute Gap Problem

**Author:** Kovac (Coordinator)  
**Date:** 23 Jun 2026  
**System:** LIVE ($454.81, 35-coin pool, BULL regime, gate OPEN)

---

## 1. The Problem in One Paragraph

Steve Bot V2.0 is a live Bitget futures bot trading both **LONG and SHORT** from structural support/resistance zones. For LONGs, it enters at the 15m candle open when price bounces off a support zone — achieving **69.6% win rate** — but the most profitable trades gap 0.5-3%+ above the zone top and **never look back**. For SHORTs, the identical problem exists in reverse: price gaps 0.5-3%+ below the resistance zone on a massive red candle and never retraces up to the zone entry window.

By the time the 15m candle closes and the engine detects the bounce/rejection, the optimal entry is gone. We tested 6 alternative approaches (limit orders at zone boundaries, pre-breakout signals, signal scoring) and **all failed** — each losing -89% to -99.7% of the baseline PnL.

We need a **fresh pair of eyes** — another AI — to analyse both sides of the problem and propose approaches we haven't considered.

---

## 2. How the Engine Works (Minimal — Just the Relevant Parts)

### 2.1 Entry Decision Chain (LONG)

```
Every 15m bar close:
  1. Fetch data (15m, 1H, 4H) from Bitget API for all 35 pool coins
  2. Detect 4H support zones for each coin
  3. Check: is current price within zone [zl_, zh]?
  4. Check: is 15m candle green? (close > open)
  5. Check: 1H conditions (RSI 30-70, EMA20 > EMA50, MACD)
  6. Check: BTC correlation filter (skip ETH/SOL/BNB if BTC down ≥1.5% today)
  7. ENTER at bar["o"] with SL = zl_ − 0.5 × ATR(4H)
  8. Trail activates at 0.80R profit, width = 0.50R
```

### 2.2 Zone Detection Algorithm (4H timeframe)

This is the **core** of the system — structural support detection:

```python
def find_zones_4h(bars, idx, cp, lookback=1200, cluster=0.05,
                   max_width=0.08, max_dist=0.35, min_zs=4):
    md = cp * max_dist   # max pivot distance from current price
    mw = cp * max_width  # max zone width
    lb = max(50, idx - lookback)
    highs = [b["h"] for b in bars]
    lows = [b["l"] for b in bars]
    pivots = []
    for i in range(2, len(bars) - 2):
        if i < lb or i >= idx - 1: continue
        if lows[i] >= cp: continue
        # 5-bar pivot detection
        if not (lows[i] < lows[i-1] and lows[i] < lows[i-2] and
                lows[i] < lows[i+1] and lows[i] < lows[i+2]): continue
        if (cp - lows[i]) > md: continue
        # Recaptured test
        recaptured = False
        for j in range(i+1, min(i+6, idx+1)):
            if bars[j]["c"] >= lows[i] * 1.02: recaptured = True; break
        if recaptured: pivots.append(lows[i])
    if not pivots: return []
    pivots.sort(reverse=True)
    cr = cp * cluster
    used = set()
    zones = []
    for pi, plv in enumerate(pivots):
        if pi in used: continue
        members = [plv]; used.add(pi)
        for pj in range(pi+1, min(pi+50, len(pivots))):
            if pj in used: continue
            if abs(pivots[pj] - plv) <= cr:
                members.append(pivots[pj]); used.add(pj)
        if len(members) < 2: continue
        zl = min(members); zh = max(members)
        if zh - zl > mw: continue
        zs = 2 + min(len(members)-1, 3)  # strength 2-5
        if zs >= min_zs: zones.append((round(zh,6), round(zl,6), zs, len(members)))
    zones.sort(key=lambda x: (x[2], -(cp - x[1])), reverse=True)
    return zones
```

### 2.3 Resistance Zones (SHORT entries — C7/H6 config)

Mirrors `find_zones_4h` but detects HIGH pivots (resistance tops):
- `recaptured` test reversed — price must fall 2% BELOW pivot within 5 bars
- Pivots sorted by proximity ASCENDING (nearest to price first)
- Zones sorted by strength desc, then proximity DESC (far-to-near)
- SL = zone_top (zh) + 0.4×ATR (above the zone, structurally placed)

```python
def find_resistance_zones_4h(bars, idx, cp, lookback=1200, cluster=0.05,
                              max_width=0.08, max_dist=0.35, min_zs=4):
    md = cp * max_dist
    mw = cp * max_width
    lb = max(50, idx - lookback)
    highs = [b["h"] for b in bars]
    pivots = []
    for i in range(2, len(bars) - 2):
        if i < lb or i >= idx - 1: continue
        if highs[i] <= cp: continue
        # 5-bar HIGH pivot
        if not (highs[i] > highs[i-1] and highs[i] > highs[i-2] and
                highs[i] > highs[i+1] and highs[i] > highs[i+2]): continue
        if (highs[i] - cp) > md: continue
        # Recaptured test (reversed: price fell BELOW pivot)
        recaptured = False
        for j in range(i+1, min(i+6, idx+1)):
            if bars[j]["c"] <= highs[i] * 0.98: recaptured = True; break
        if not recaptured: pivots.append((i, highs[i]))
    if not pivots: return []
    pivots.sort(key=lambda x: x[1] - cp)  # NEAREST first (vs LONG's furthest-first)
    cr = cp * cluster
    zones = []
    used = set()
    for pi, (pidx, plv) in enumerate(pivots):
        if pidx in used: continue
        members = [(pidx, plv)]; used.add(pidx)
        for pj in range(pi+1, min(pi+50, len(pivots))):
            jdx, jlv = pivots[pj]
            if jdx in used: continue
            if any(abs(jlv - mv) <= cr for _, mv in members):
                members.append((jdx, jlv)); used.add(jdx)
        if len(members) < 2: continue
        ml = [m[1] for m in members]
        zl = min(ml); zh = max(ml)
        if zh - zl > mw: continue
        zs = 2 + min(len(members)-1, 3)
        if zs >= min_zs: zones.append((round(zh,6), round(zl,6), zs, len(members)))
    zones.sort(key=lambda x: (x[2], -(x[1] - cp)), reverse=True)
    return zones
```

### 2.3b SHORT Entry Decision Chain (C7/H6 Config)

The short system uses its own entry chain, entirely separate from LONGs:

```
Every 15m bar close (after LONG entries processed):
  1. Check margin gate: locked_margin > 60% of balance? → skip
  2. Check position limits: < 6 short positions, < 12 total positions
  3. Check cooldown: 96 bars (~24h) since last short on this symbol
  4. Fetch 4H resistance zones (find_resistance_zones_4h)
  5. CONDITION 1 (H6): 1H RSI > 40 (overbought/not oversold — bias to short)
  6. CONDITION 2 (H6): price near resistance zone top
     cp >= zbot AND cp <= ztop × 1.015
  7. NO volume exhaustion required (H6 — proven +$1,518 short PnL at 68.6% WR)
  8. ENTER at bar["o"] with SL = ztop + 0.4×ATR (above zone)
  9. Trail activates at 0.80R profit, width = 0.50R (trailing behind LOWEST price)
  10. Time exit: 288 bars (~3 days)
  11. Sizing: 5% of free balance, FLAT across ALL regimes (no regime multipliers)
      Regime short multipliers: just 5% across the board
```

### 2.3c SHORT Trailing Stop

```python
def _update_short_trail_p4(entry, cur_sl, risk_dist, lo):
    profit = entry - lo  # positive when price drops
    if profit <= 0 or risk_dist <= 0: return cur_sl, False
    profit_r = profit / risk_dist
    if profit_r < SHORT_TRAIL_ACT_R: return cur_sl, False  # 0.80R
    trail_width = SHORT_TRAIL_WIDTH_R * risk_dist  # 0.50R
    new_sl = min(cur_sl, lo + trail_width)
    new_sl = max(new_sl, entry * 1.002)  # never tighten below entry
    return new_sl, True
```

### 2.3d The SHORT "Miss" Problem

The short engine has the same structural problem as LONGs in reverse. When a massive red 15m candle gaps FROM a resistance zone DOWN 2-3% in one bar, the engine skips because price has already blown past the resistance entry window:

```python
# H6 proximity check:
if cp < zbot or cp > ztop * SHORT_ZONE_PROXIMITY_PCT:  # 1.015×
    continue  # <-- BIG SHORT RUNNERS ARE MISSED HERE
```

A coin tests resistance at $100 for weeks. The 4H zone spans $98-$102. A news event drops a massive red candle opening at $100 and closing at $97. The engine sees cp=$97 < zbot=$98 → NOT IN ZONE → skip. Price never recovers to $100. The short runner is permanently missed.

**Known from backtesting:** S1 (resistance zones only, no RSI/volume gates) produced -$25.25 net PnL on 711 short trades. The H6 gates (RSI>40 + zone proximity) are essential — removing them floods in bad trades. Same constraint as LONG: you can't skip confirmation without eating WR.

### 2.4 Zone Properties (Shared by Both)

| Property | Value | Meaning |
|---|---|---|
| `min_zone_strength` | 4 | Zone needs ≥4 confluences (3+ pivot lows) |
| `max_width` | 8% of cp | Zone width capped at 8% of current price |
| `cluster` | 5% of cp | Pivots within 5% distance cluster together |
| `lookback` | 1200 bars | Scan up to 1200 4H bars (~200 days) |
| Sizing: zs≥5 + per-coin WR≥48% | 10% risk, 8x lev | High conviction tier |
| Sizing: default | 5% risk, 5x lev | Standard tier |
| Regime multiplier | 0.75-1.5× | BULL/SIDEWAYS/BEAR scaling |

### 2.5 The "Miss" Mechanism

```python
# p3_live.py entry gate:
col = zl_ + zhgt * (ZONE_UPPER_LIMIT_PCT / 100.0)  # 1% above zl_
if cp > col:
    # PRICE ABOVE ZONE — TRADE SKIPPED
    continue  # <-- THIS IS WHERE THE BIG WINNERS ARE LOST
```

When a massive green 15m candle gaps from zl_ to zh+2% in one bar, the engine skips it because cp > col (price is above zone entry limit). The candle never trades. And price never retraces to the zone — so the runner is permanently missed.

---

## 3. The Data We Can Prove (V65/V71 Analysis)

### 3.1 5,578 Near-Miss Signals (Full CSV Available)

Exported to: `dev_pipeline/code/v71_nearmiss_timestamps.csv`

| Column | Description |
|---|---|
| `symbol` | Trading pair (e.g. AAVEUSDT) |
| `bar_index` | 15m bar index |
| `timestamp_ms` | Epoch ms of the 15m bar |
| `zh` | Zone top price |
| `zl_` | Zone bottom price |
| `zone_width_pct` | (zh-zl)/zl × 100 |
| `gap_pct` | (entry_price − zh) / zh × 100 |
| `pnl_margin` | Simulated P&L margin |
| `is_winner` | 1 = winner, 0 = loser |

### 3.2 Key Metrics (V71 on 15 coins, 2023-2025)

| Metric | Value |
|---|---|
| V62 entered trades | 507 |
| V62 WR | 69.6% |
| Near-miss signals | 5,578 |
| Near-miss WR | 53.1% |
| Potential winners lost | ~2,960 |
| Top missed winners | AAVE +34.1%, INJ +19.1%, APT ×3 (+17-18%), QNT multiple (+13-16%) |

### 3.3 Why Limit Orders at Zone Failed (LONG)

| Approach | Fill Rate | PnL vs Baseline | Verdict |
|---|---|---|---|
| Limit at zl_ (zone bottom) | 7.0% | -99.7% | Dead |
| Limit at zh (zone top) | 17% | -407pp | Dead |
| Pre-breakout (L2, 2-3 bars before) | — | -89% to -96.5% | Dead |
| Signal score filtering | — | 85% false positive | Dead |

**Root cause:** The V62 confirmation filters (green candle + volume surge + RSI 30-70 + EMA conditions) do essential work. Entering before confirmation catches too many weak bounces.

### 3.3b SHORT Research History (Proven Config)

Shorts went through their own optimisation journey, separate from LONGs:

| Version | Entry Logic | Short WR | Short PnL | Notes |
|---|---|---|---|---|
| S0 (V58 baseline) | LONG only | — | $0 | No short system |
| S1 (zones only) | Resistance zones only | — | -$25.25 | Bad — no confirmation |
| S2 (triple confluence) | Vol exhaust + RSI>70 + zone | 64.9% | +$113 | First positive |
| H7 (V59 winner) | RSI>60 + vol exhaust + zone proximity | 67.6% | +$254 | 124% improvement |
| P4 (V60 winner) | H7 + 2.0% risk | 70.6% | +$792 | +37% over H7 |
| V61 A/B final | P4 on full 31x engine | 66.1% | +$759 | Pure additive |
| **C7 (V2.0 live)** | **H6: RSI>40 + zone proximity, 5% risk** | **68.6%** | **+$1,518** | **+80% over P4** |

**Key C7 finding:** Removing the vol exhaustion gate (H7→H6) increased short trades from 74 to 139 while maintaining 68.6% WR. The 5% flat risk was the biggest performance lever (no regime multipliers).

### 3.4 What DID Work (Three Living Paths)

**Path A: bar[i-1] Quality Filter** — skip trades where the 15m bar BEFORE the entry has low ATR percentile (< 30), low volume rank (< 40), or narrow BB width (< 40). These are "squeeze" bounces that stall and exit by TIME. This is a **negative quality filter**, not a runner predictor.

**Path B: 1m Microstructure V-Bounce + DCA** — use 1m candles between 15m bars to detect a wick to zl_ + immediate reversal + volume spike, then enter incrementally (1% probe → 1% add on confirmation → 3% V62 confirmation). **Needs real 1m data.** Partial data downloaded from Binance (AAVE, APT, ATOM, BAT, BTC complete; 10 more symbols pending).

**Path C: Zone Width Refinement** — narrowing max zone width from 8% to 6% increases WR by +2.2pp (56.8% vs 54.6%). Testable on existing 15m data.

---

## 4. Data Available via Bitget API

The live engine connects to Bitget v2 REST API. The following data can be fetched in real-time for any USDT-M futures symbol in the pool:

### 4.1 OHLCV Klines

**Endpoint:** `GET /api/v2/mix/market/candles`

| Timeframe | Granularity String | Bars Per Request | Notes |
|---|---|---|---|
| 1 minute | `1m` | Up to 1000 | Available via Bitget v2 but NOT used by current engine |
| 5 minute | `5m` | Up to 1000 | Available |
| 15 minute | `15m` | Up to 1000 | **Primary timeframe** — entry signals, trailing stops |
| 1 hour | `1H` | Up to 1000 | Regime detection, RSI, MACD, EMA cross checks |
| 4 hour | `4H` | Up to 1000 | **Zone detection timeframe** — pivot scanning, ATR |
| 1 day | `1D` | Up to 1000 | Available via API but not currently used by engine |
| 1 week | `1W` | Up to 1000 | Available via API |

**Parameter:** `productType=USDT-FUTURES` for futures data.

**Response format per candle:** `[timestamp_ms, open, high, low, close, volume, timestamp_ms_close]`

The engine wraps this in `get_klines(symbol, granularity, limit)` returning `[{ts, o, h, l, c, vol}]`.

For historical data, the same endpoint can be called repeatedly with different `startTime`/`endTime` params to build large datasets — the current engine doesn't do this but the API supports it.

### 4.2 Account & Position Data

| Endpoint | Data Returned |
|---|---|
| `GET /api/v2/mix/account/accounts` | Equity, locked margin, available balance |
| `GET /api/v2/mix/position/all-position` | Open positions (size, entry, margin, P&L, leverage) |
| `GET /api/v2/mix/order/detail` | Individual order status |

### 4.3 1m Data Already Downloaded

The following real 1m Binance futures data is already on disk (or being fetched for):

| Symbol | Status | Date Range | Candles |
|---|---|---|---|
| AAVE | ✅ Complete | 2023-02-11 → 2025-04-08 | 1,133,281 |
| APT | ✅ Complete | 2023-04-22 → 2025-03-31 | 1,020,842 |
| ATOM | ✅ Complete | 2023-03-12 → 2024-08-29 | 772,141 |
| BAT | ✅ Complete | Range confirmed | ~500K+ |
| BTC | ✅ Complete | 2023-03-27 → 2025-03-11 | 1,030,081 |
| DOT | ⏳ Fetching | 2023-03-06 → 2025-04-15 | — |
| FIL | ⏳ Fetching | 2023-02-20 → 2025-03-11 | — |
| GALA | ⏳ Fetching | 2023-05-11 → 2025-04-20 | — |
| INJ | ⏳ Fetching | 2023-02-10 → 2025-04-19 | — |
| IOTA | ⏳ Fetching | 2023-03-07 → 2025-04-21 | — |
| LTC | ⏳ Fetching | 2023-03-16 → 2024-12-18 | — |
| NEO | ⏳ Fetching | 2023-03-03 → 2025-05-01 | — |
| OM | ⏳ Fetching | 2024-07-20 → 2026-02-20 | — |
| QNT | ⏳ Fetching | 2023-02-27 → 2025-02-12 | — |
| VET | ⏳ Fetching | 2023-02-28 → 2025-04-18 | — |

**Format:** `research_engine/data/raw/1m_{SYMBOLSHORT}.csv` → `ts,o,h,l,c,v`

---

## 5. Questions for the AI

### 5.1 LONG-Specific

1. **The core constraint:** We confirmed that entering BEFORE the V62 confirmation (at zone boundary with limit orders, or 2-3 bars earlier with pattern recognition) destroys profitability. The confirmation filters are essential. Given this constraint, what **new approach** could capture LONG runners that gap past the support zone?

2. **1m microstructure:** We have real 1m data for 5 symbols and fetching the rest. The theory is that between 15m bars, 1m micro-patterns (wick to zl_ → immediate reversal → volume spike) could signal the bounce before the 15m candle confirms. Can you design a robust micro-pattern detector that **doesn't degenerate into a limit-order-at-zone** (which we proved fails)?

3. **Regime-aware acceleration:** In strong BULL regimes (score ≥ 40), the engine sizes at 150%. Could we also **widen the zone entry limit** in strong BULL? E.g., `ZONE_UPPER_LIMIT_PCT = 2%` instead of 1% when BTC is ripping? Or is this just another form of "skip confirmation = lose money"?

4. **DCA architecture:** The planned DCA overlay is: 1% probe at zl_ → 1% add on V-bounce → 3% full V62. What flaws do you see in this model? Is the V-bounce signal real or will it also degenerate into noise like limit-at-zone did?

### 5.2 SHORT-Specific

5. **SHORT near-miss data doesn't exist yet** — we haven't run the same analysis. Do you expect the same pattern (big losers missed, limit orders at zone top fail)? Or is SHORT different because resistance breaks are usually sharper than support bounces? Would the H6 gate conditions suffer the same pre-confirmation penalty?

6. **H6 entry vs H7 (with vol exhaustion):** The current H6 (no vol exhaustion) produces more short trades but at lower WR than H7 (with vol exhaustion). Could relaxing the zone proximity check (widening from 1.5% to 3% above zone top) capture more short runners without destroying WR? Is there a short analogue of the bar[i-1] quality filter?

7. **SHORT regime sizing is flat (5% everywhere):** Longs have regime multipliers (75%-150%). Should shorts also? The BEAR regime short PnL was +$157 in v60 — is there room to size up in BEAR, or would that cause overfitting?

### 5.3 Cross-Cutting

8. **What data would you need?** The Bitget API can supply any timeframe (1m to 1D) for all pool symbols. The near-miss CSV is 5,578 LONG signals. If you want the same analysis run for SHORT near-misses, we can produce a parallel CSV. What specific historical analysis or live data stream would help you crack this?

9. **Liquidity analysis:** The near-miss CSV has 5,578 signals — can you analyse whether the **blocked** trades (cp > col by 0.5-3%) would have been fillable at all? Could we model slippage between 15m bar open and the limit zone to estimate real-world fill viability for both LONG and SHORT?

---

## 6. How to Help

**You have:**
- The full zone detection algorithm (code above)
- The entry decision chain (Section 2.1)
- All config constants
- A CSV of 5,578 near-miss signals with exact timestamps
- 1m Binance data on disk for 5+ symbols
- Bitget API capable of any timeframe from 1m to 1D

**What we need from you:**
1. **Fresh ideas** — approaches we haven't considered that respect the constraint that pre-confirmation entry kills WR
2. **Analysis of the near-miss CSV** — pattern mining across the 5,578 signals
3. **1m microstructure design** — if the V-bounce approach has merit, design the detector logic
4. **Test plan** — a concrete, coded testable on our existing data

---

## 7. Key Files

| File | Content |
|---|---|
| `dev_pipeline/BRIEF_BIG_WINNER_DETECTION.md` | This document |
| `dev_pipeline/code/v71_nearmiss_timestamps.csv` | 5,578 LONG near-miss signals with timestamps, prices, P&L |
| `dev_pipeline/deployment/p3_live.py` | Complete live engine (2,422 lines — ALL entry/exit code for both LONG & SHORT) |
| `dev_pipeline/deployment/p3_config.yaml` | Config (risk, leverage, pool, timeframes) |
| `dev_pipeline/specs/entry_sl_doctrine.md` | Entry / SL doctrine |
| `research_engine/data/raw/1m_{SHORT}.csv` | 1m Binance data (5+ symbols complete, rest downloading) |
| `dev_pipeline/code/v62_entry_method_test.py` | Baseline LONG backtest (+10,467%) |
| `dev_pipeline/reports/v65_entry_retracement_report.md` | Never-look-back analysis (LONG) |
| `dev_pipeline/reports/v71_big_miss_1m_analysis.md` | Full near-miss + V-bounce analysis (LONG) |
| `dev_pipeline/code/v70_prev_bar_analysis.py` | bar[i-1] predictor analysis (LONG) |
| `dev_pipeline/reports/v70_prev_bar_analysis.md` | bar[i-1] report with statistical tests (LONG) |
| `dev_pipeline/code/v59_short_opt.py` | SHORT H7 optimisation (all 8 experiments) |
| `dev_pipeline/reports/v59_short_opt_results.md` | SHORT optimisation full report |
| `dev_pipeline/reports/v60_short_params_results.md` | SHORT P4 parameter optimisation report |
| `dev_pipeline/reports/v61_full_range_ab_results.md` | Final SHORT A/B verification (pure additive) |

<!-- deploy-1782234539 -->
