# V12 — Momentum Taker con Confirmacion + Fix Verify Fill

## Resumen

V12 evoluciona V11 con tres cambios criticos:

1. **FIX: Eliminacion de trades fantasma (verify_fill reescrito)** — V11 usaba `data-api.polymarket.com/positions` para verificar fills, pero esta API tiene latencia de minutos y NUNCA mostraba las posiciones recientes. Todos los trades caian al path "FILL TRUST" (confiar ciegamente en el CLOB "matched"). Descubrimos que 1 de cada 3 trades era fantasma: el CLOB decia "matched" pero no habia ejecucion on-chain. V12 usa `client.get_trades()` que devuelve trades CONFIRMED con `transaction_hash` — la fuente de verdad. FILL TRUST eliminado.

2. **Confirmacion de momentum** — V11 entraba en el primer tick que cruzaba el threshold. Esto era vulnerable a "chop" (spikes transitorios donde el precio cruza brevemente el threshold y revierte dentro de la ventana). V12 requiere que el movimiento persista N ticks consecutivos (`CONFIRM_TICKS`, default 10s) en la misma direccion antes de generar senal.

3. **Aggressive bump reducido** — V11 pagaba ask+$0.02 para asegurar fill. En un share de ~$0.50, eso es 4% de overpay que destruye edge. V12 reduce a ask+$0.01 (`AGGRESSIVE_BUMP`, configurable).

## Por que estos cambios

### Problema 0: Trades fantasma (CRITICO)

**Descubierto 2026-06-01**: V11 reporto 3 trades ganadores (BTC, ETH, SOL) en la primera ventana despues del reset. El dashboard mostraba +$17.39 de PnL. Pero en Polymarket solo aparecian 2 trades, y el balance real subio solo +$10.88.

**Investigacion**: Los logs de tmux mostraban que los 3 trades cayeron al path `[FILL TRUST]`:
```
[verify retry 1/4] no position found yet...
[verify retry 2/4] no position found yet...
[verify retry 3/4] no position found yet...
[verify retry 4/4] no position found yet...
[FILL TRUST] YES — CLOB matched but verify failed, keeping aggressive price
```

La `data-api.polymarket.com/positions` retornaba 100+ posiciones viejas de V9/V10 pero NINGUNA posicion reciente. El verify_fill era inutil — siempre fallaba.

**Verificacion con CLOB get_trades API**: Usando `client.get_trades()` encontramos:
- ETH: 11.104 sh @ 0.47, 2 tx CONFIRMED on-chain
- SOL: 10.19 sh @ 0.51, 2 tx CONFIRMED on-chain
- BTC: **CERO fills** — trade fantasma

El CLOB respondio `status="matched"` para BTC pero la orden nunca se ejecuto on-chain. FILL TRUST la conto como win de +$6.60.

**Impacto historico**: Este bug existia desde el dia 1 de V11. TODAS las decisiones de thresholds, WR, y PnL estaban basadas en datos contaminados por trades fantasma. Esto explica por que el PnL reportado nunca cuadraba con el balance real de la wallet.

**Fix V12**:
1. `verify_fill` reescrito: usa `client.get_trades()` con filtro `after=order_ts`. Busca nuestra address en `maker_orders` con el `asset_id` correcto. Solo acepta trades con `status="CONFIRMED"`.
2. FILL TRUST eliminado completamente. Si get_trades no confirma → `[PHANTOM]`, orden cancelada, trade NO contado.
3. Balance delta check: compara balance antes/despues como sanity check adicional.
4. Settle ignora trades no verificados (no contamina CSV ni PnL).

### Problema 1: Chop (entrada en ruido)

Analisis de perdidas nocturnas (changelog V11 #24): 45 trades, WR=36%, PnL=-$76, hasta 9 perdidas consecutivas. Causa: en mercados laterales el precio oscila alrededor del strike. Cruza el threshold momentaneamente, el bot entra, y el precio revierte. La confirmacion temporal filtra estos spikes.

**Ejemplo concreto:**
- V11: precio cruza +0.08% del strike en tick 1 -> entra YES inmediatamente -> precio revierte a -0.03% -> LOSS
- V12: precio cruza +0.08% en tick 1 -> espera 10 ticks -> en tick 5 revierte a 0.02% -> counter reset -> NO ENTRA

**Trade-off:** La confirmacion reduce numero de trades (mas selectivo). Si el movimiento es genuino, entramos 10s mas tarde — el ask podria haber subido ligeramente. Pero eliminamos los trades de ruido que son la principal fuente de perdidas.

### Problema 2: Overpay en aggressive pricing

V11 sumaba $0.02 al ask para asegurar fill rapido. Impacto en EV:

| Ask | V11 paga | V12 paga | Ahorro/share |
|-----|----------|----------|-------------|
| $0.50 | $0.52 | $0.51 | $0.01 |
| $0.45 | $0.47 | $0.46 | $0.01 |
| $0.55 | $0.57 | $0.56 | $0.01 |

Con ~10 shares/trade, ahorro de ~$0.10/trade. En 20 trades/dia = $2/dia.

Breakeven WR con 2% fee (shares a $0.50):
- V11 (ask+0.02): paga 0.52 -> WR necesario ~54.2%
- V12 (ask+0.01): paga 0.51 -> WR necesario ~53.1%

Ese 1% de WR requerido menos es significativo cuando el edge real es marginal.

## Archivos modificados

| Archivo | Cambio |
|---------|--------|
| `config.py` | Nuevos params: `CONFIRM_TICKS=10`, `AGGRESSIVE_BUMP=0.01`. Per-asset override via `confirm_ticks`, `aggressive_bump` en ASSET_CONFIGS. Docstring actualizado a V12. |
| `strategy.py` | `MomentumStrategy` ahora es stateful: mantiene `_confirm_count` y `_confirm_side`. `check_signal()` incrementa counter cuando `abs_move > threshold`. Solo genera Signal cuando `count >= confirm_ticks`. Cambio de direccion o caida bajo threshold resetea counter. Nuevo metodo `reset()`. Propiedades `confirm_count`, `confirm_side` para dashboard. |
| `executor.py` | `place_taker_order()` usa `self.cfg.aggressive_bump` en vez de hardcoded `0.02`. **`verify_fill()` reescrito**: usa `client.get_trades(TradeParams(after=order_ts))` en vez de positions API rota. Busca fills CONFIRMED donde somos maker/taker para el token_id. Retorna `{size, avg_price, tx_hashes}` o None. Import de `TradeParams` agregado. FILL TRUST eliminado. |
| `bot.py` | Llama `strategy.reset()` en `_reset_window_state()`. Status line muestra `cfm=N/M` (progreso confirmacion). Dashboard state.json incluye seccion `confirm: {count, needed, side}`. **Verificacion reescrita**: 5 intentos (era 4), pasa `order_ts` a verify_fill. Si NO verifica → `[PHANTOM]`: cancela orden, decrementa trades, NO loguea a CSV. FILL TRUST eliminado completamente. Settle ignora trades no verificados (`_fill_verified` flag). Prints y labels actualizados a V12. |
| `feeds.py` | Sin cambios. |
| `market.py` | Sin cambios. |
| `logger.py` | Sin cambios. |
| `main.py` | Sin cambios (ya usa import relativo, funciona con v12). |

## Parametros nuevos en config.py

```python
# V12: Confirmacion de momentum
CONFIRM_TICKS   = 10    # ticks consecutivos (1 tick = 1s) con |move| > threshold
                        # en la misma direccion antes de generar senal

# V12: Bump agresivo reducido
AGGRESSIVE_BUMP = 0.01  # centavos sobre ask (V11 era 0.02)
```

Ambos son override-ables per-asset en ASSET_CONFIGS:
```python
"btc": {
    ...
    "confirm_ticks": 8,       # BTC es menos ruidoso, confirmar mas rapido
    "aggressive_bump": 0.01,
},
```

## Parametros actuales

| Parametro | BTC | ETH | SOL |
|-----------|-----|-----|-----|
| momentum_threshold | 0.08% | 0.10% | 0.10% |
| confirm_ticks | 3 | 3 | 3 |
| aggressive_bump | $0.01 | $0.01 | $0.01 |
| entry_size_usd | $5 | $5 | $5 |
| max_entry_price | 0.55 | 0.53 | 0.53 |
| min_ask_confirm | 0.38 | 0.40 | 0.48 |

Defensas (sin cambios):
- Global cooldown: 3 losses -> 15min pausa (cross-asset)
- Filtro horario: DESACTIVADO (test limpio)
- Loss streak per-asset: 3 losses -> 3 windows cooldown

## Como ejecutar

```bash
# Paper (test sin dinero real)
cd /var/www/html/MetaHedge/POLYBOT1
python3 -m v12.main --asset btc --window 5

# Live
python3 -m v12.main --asset btc --window 5 --live
```

## Como revertir a V11

```bash
# Simplemente ejecutar desde v11/ en vez de v12/
python3 -m v11.main --asset btc --window 5 --live
```

Los logs son compartidos (misma carpeta `logs/`), no hay conflicto.

## Riesgos y monitorizacion

1. **Menos trades**: La confirmacion filtra trades. Esto es intencional — menos trades de peor calidad. Monitorizar que no filtre DEMASIADO (si 0 trades en 4h, considerar bajar CONFIRM_TICKS a 7-8).

2. **Entry price ligeramente peor**: Al esperar 10s, el ask puede subir 1-2c en movimientos fuertes. Pero esto se compensa con creces al evitar los trades de chop.

3. **Bump reducido puede causar mas pending**: Con +$0.01 en vez de +$0.02, alguna orden podria no llenarse inmediatamente. El verify_fill + cancel flow ya maneja esto.

---

## Historial de cambios post-lanzamiento

### 2026-06-01: Lanzamiento V12 live (BTC, ETH, SOL)

- Arrancados bots live BTC, ETH, SOL con CONFIRM_TICKS=10
- Dashboard (`v11_multi_dashboard.html`) actualizado: titulo V12, indicador CFM count/needed

### 2026-06-01 (noche): CONFIRM_TICKS 10 → 3

**Problema:** CONFIRM_TICKS=10 demasiado alto. Los market makers del CLOB reprecian asks a $0.90+ en 3-5 segundos tras un movimiento de Binance. Con 10 ticks de confirmacion, el ask siempre superaba max_entry_price antes de completar la confirmacion → 0 trades en 14 ventanas.

**Evidencia:** SOL seq#18 empezo con ask NO=$0.33 (viable) pero llego a $0.70 en tick 9. V11 paper entro en esa ventana a $0.53 NO y gano +$4.47.

**Fix:** `CONFIRM_TICKS = 3` en config.py (linea 55). Filtra spikes de 1 tick sin perder edge vs CLOB.

### 2026-06-01 (noche): Bug fix — counter no reseteaba tras rechazo de filtros

**Problema:** Cuando la confirmacion alcanzaba N ticks pero el ask era rechazado por filtros de precio (max_entry_price, min_ask_confirm, MIN_ENTRY_PRICE), el counter seguia incrementando en vez de resetearse. Dashboard mostraba cfm=45/10, cfm=60/10.

**Fix en strategy.py:** Añadido `self._confirm_count = 0; self._confirm_side = ""` en las 3 ramas de rechazo por precio (lineas 127-143).

### 2026-06-02: BNB añadida a live

Añadida basandose en resultados paper prometedores (WR 68.8%, +$29.47). Config: min_ask_confirm=0.45, max_entry_price=0.53, momentum_threshold=0.0007.

### 2026-06-03: BNB eliminada de live

**Resultado tras 2 dias:** 21 trades, WR 38.1%, PnL -$18.56, **10 trades fantasma (32% phantom rate)**. La tasa de phantoms indica que el CLOB de BNB en Polymarket no tiene liquidez real suficiente.

**Por que paper engañaba:** Paper no tiene phantoms (fills simulados al 100%), no tiene delay de ejecucion, y no requiere liquidez real en el CLOB. BNB paper seguia reportando WR~70% y PnL positivo, pero esos resultados no son replicables en live.

**Impacto en portfolio:**
- Con BNB: WR 62.1%, PnL +$119.07
- Sin BNB: WR 69.7%, PnL +$137.63
- BNB arrastraba -$18.56 al resultado global

**Decision:** Eliminar BNB de live. Mantener solo BTC, ETH, SOL.

### Resultados acumulados V12 live (2026-06-01 a 2026-06-03)

Balance: $212.34 (inicio $96.68, **+119.6% ROI en 2 dias**)

| Asset | Trades | WR | PnL | Phantoms |
|-------|--------|----|-----|----------|
| ETH | 20 | 80.0% | +$76.24 | 0 |
| SOL | 26 | 69.2% | +$43.88 | 0 |
| BTC | 20 | 60.0% | +$17.51 | 0 |
| ~~BNB~~ | ~~21~~ | ~~38.1%~~ | ~~-$18.56~~ | ~~10~~ |
| **Total (sin BNB)** | **66** | **69.7%** | **+$137.63** | **0** |

**V12 vs V11 (conclusion):** V12 es mas rentable en la realidad. V11 paper reporta mas trades y mayor PnL, pero esos numeros estan inflados por trades fantasma contados como wins (FILL TRUST). V12 solo cuenta trades verificados on-chain.

### Configuracion activa (2026-06-03)

Bots live: BTC, ETH, SOL (3 bots en tmux)
CONFIRM_TICKS: 3 (global default, sin override per-asset)
AGGRESSIVE_BUMP: $0.01
Filtro horario: DESACTIVADO (test limpio)
Balance: $212.34
