# TV Auto-Presets Plan

Auto-loads the correct optimizer-found weights and thresholds into TradingView
based on the current chart's asset and timeframe — no manual input required.

**Branch:** `feature/tv-presets`
**Status:** In progress

---

## Goal

One paste into TradingView. Change chart symbol or timeframe → weights and
thresholds update automatically. No manual editing or data entry ever.

## Design Summary

Pine Script exposes `syminfo.prefix`, `syminfo.ticker`, and `timeframe.period`
at runtime. We use these to build a preset key (`"COINBASE_BTCUSD 1D"`) which
drives a `switch` expression for every optimized parameter.

A Python script (`tools/generate_pine_presets.py`) reads all 20 winner CSVs and
rewrites a sentinel block inside the Pine file with the current best values.
After any optimization run, re-run the script and paste the Pine file into TV.

**Manual override:** `i_preset_override` input (blank = auto) lets the user
force a specific preset when on an unsupported symbol/TF.

**Scope (Option A):** All ~40 params from winner CSVs are preset-driven:
weights, thresholds, booleans, trailing stop, regime params, candlestick geometry.
Non-optimized params (MACD settings, GC settings, Stoch settings, M2 offsets,
date range) remain as manual `input.*`.

---

## Supported Combos (20 presets)

```
COINBASE_BTCUSD   4H  6H  8H  12H  1D
COINBASE_ETHUSD   4H  6H  8H  12H  1D
BINANCE_SOLUSD    4H  6H  8H  12H  1D
BINANCE_LINKUSD   4H  6H  8H  12H  1D
```

Fallback for unknown combos: COINBASE_BTCUSD 1D defaults.

## Timeframe mapping (Pine `timeframe.period` → label)

| `timeframe.period` | Label |
|--------------------|-------|
| `"D"`              | `1D`  |
| `"720"`            | `12H` |
| `"480"`            | `8H`  |
| `"360"`            | `6H`  |
| `"240"`            | `4H`  |

---

## Optimized Params List (~40 params, all preset-driven)

These params will be removed from `input.*` declarations and moved into the
auto-generated switch block. The variable names stay the same — only the
assignment mechanism changes.

**Thresholds (float):**
- `i_long_entry_activation_threshold`
- `i_long_exit_activation_threshold`
- `i_long_exit_activation_confirmation_threshold`
- `i_trailing_stop_threshold`
- `i_regime_entry_min_score`

**Flags (bool → converted from 0.0/1.0 float in CSV):**
- `i_use_long_entry_confirmation`
- `i_use_long_exit_confirmation`

**Integer:**
- `i_regime_window`

**Weights (float, 25 total):**
- `i_w_stoch`, `i_w_macd_pred`, `i_w_osc`, `i_w_macd_bullish`, `i_w_m3_momentum`
- `i_w_m2_tiny`, `i_w_rsid_osc`, `i_w_stoch_div_osc`, `i_w_vwap_div_osc`
- `i_w_stoch_peaking`, `i_w_stoch_bottoming`, `i_w_m3_div_osc`, `i_w_m2_div_osc`
- `i_w_bearish_engulfing`, `i_w_m2_div_osc_noOffset`
- `i_w_bullish_hammer`, `i_w_bullish_engulfing`, `i_w_shooting_star`
- `i_w_btc_spx_corr`, `i_w_dxy`, `i_w_vix`, `i_w_btc_dom`, `i_w_us10y`
- `i_w_spy`, `i_w_gold`, `i_w_mvrv`, `i_w_mvrv_cont`, `i_w_nupl`
- `i_w_fed_net_liq`, `i_w_gc_position`

**Candlestick geometry (float):**
- `i_w_bearish_engulfing` (weight, covered above)
- `i_cs_body_quality_ratio`
- `i_cs_confidence_scaling_factor`
- `i_cs_hammer_min_lower_shadow`, `i_cs_hammer_max_body_ratio`, `i_cs_hammer_max_upper_shadow`
- `i_cs_bull_eng_scaling_factor`
- `i_cs_star_min_upper_shadow`, `i_cs_star_max_body_ratio`, `i_cs_star_max_lower_shadow`

**Note:** `i_m3_momentum_period` appears in winner CSVs — include it.

---

## Sentinel Block Structure (in Pine file)

```pine
// ── PRESET AUTO-DETECT ────────────────────────────────────────────────────────
_tf_label = switch timeframe.period
    "D"   => "1D"
    "720" => "12H"
    "480" => "8H"
    "360" => "6H"
    "240" => "4H"
    => ""
i_preset_override = input.string("", "Force preset (blank = auto)",
    options=["", "COINBASE_BTCUSD 1D", "COINBASE_BTCUSD 12H", ...all 20...],
    group=group_neural_activation_thresholds)
_auto_key  = syminfo.prefix + "_" + syminfo.ticker + " " + _tf_label
_preset    = i_preset_override != "" ? i_preset_override : _auto_key
// ── END PRESET AUTO-DETECT ───────────────────────────────────────────────────

// ── AUTO-GENERATED PRESET VALUES — do not edit manually ──────────────────────
// Run tools/generate_pine_presets.py to regenerate from latest winner CSVs.
// Last generated: <TIMESTAMP>
i_long_entry_activation_threshold = switch _preset
    "COINBASE_BTCUSD 1D"  => 185.0
    "COINBASE_BTCUSD 12H" => 240.0
    // ... all 20 ...
    => 185.0

// ... repeat for all ~40 params ...
// ── END AUTO-GENERATED ────────────────────────────────────────────────────────
```

---

## Punchlist

### P1 — Create plan document ✅
This document. Written before any code changes.

### P2 — Write `tools/generate_pine_presets.py`
**Status:** ✅

Script that:
1. Reads all 20 `results/winners/optimization_winner_activation_scores_<ASSET>_<TF>.csv`
2. Builds `preset_key → {param: value}` map for all optimized params
3. Generates the switch block for each param (float, bool, int handled appropriately)
4. Reads `strategies/strategy_activation_scores.pine`
5. Locates `// ── AUTO-GENERATED PRESET VALUES` and `// ── END AUTO-GENERATED` sentinels
6. Replaces content between sentinels with freshly generated block
7. Writes updated Pine file in-place
8. Prints summary: N presets written, timestamp, any missing winner files warned

**Float formatting:** Round to 4 sig figs, strip trailing zeros.
**Bool handling:** Winner CSVs store `1.0`/`0.0` — emit `true`/`false` in Pine.
**Int handling:** `i_regime_window`, `i_m3_momentum_period` — emit `int(value)`.
**Missing files:** If a winner CSV doesn't exist, emit `na` for that preset and warn.

### P3 — Add sentinel block + auto-detect logic to Pine file
**Status:** ✅ (combined with P4 as single atomic edit)

### P4 — Remove `input.*` declarations for optimized params from Pine file
**Status:** ✅ (combined with P3)

### P5 — Run `generate_pine_presets.py`, paste into TV, verify
**Status:** Script runs ✅ (20/20 presets written). TV paste + verification pending user action.

Test checklist:
- [x] Script runs without errors, reports 20 presets written
- [ ] Paste Pine into TV on BTC 1D → score and thresholds match winner CSV values
- [ ] Change to ETH 4H → different weights auto-load (confirm in TV data window)
- [ ] Change to BTC 12H → 12H weights load
- [ ] Override input to "BINANCE_SOLUSD 6H" while on AAPL chart → SOL 6H weights load
- [ ] Unsupported symbol (e.g. AAPL) with no override → falls back to BTC 1D defaults
- [ ] Unsupported TF (e.g. 2H) → falls back gracefully

### P6 — Auto-call from `run_all_crypto.py`
**Status:** ✅

At the end of `run_all_crypto.py`, after the final combo completes, add:
```python
subprocess.run([sys.executable, "tools/generate_pine_presets.py"])
print("[PRESETS] Pine file updated with latest winner params.")
```

### P7 — Update CLAUDE.md
**Status:** ✅

Add to Architecture section:
- Description of `tools/generate_pine_presets.py`
- Workflow: "after running `run_all_crypto.py`, the Pine file is auto-updated; paste into TV for latest params"
- Note about auto-detection and manual override

---

## File Changes Summary

| File | Change |
|------|--------|
| `strategies/strategy_activation_scores.pine` | Add sentinel block (P3), remove optimized `input.*` (P4) |
| `tools/generate_pine_presets.py` | New file (P2) |
| `run_all_crypto.py` | Auto-call generate_pine_presets.py at end (P6) |
| `CLAUDE.md` | Document new tool (P7) |

---

## How to Resume If Interrupted

1. Check git log on `feature/tv-presets` to see last completed step
2. Read this document — check off which punchlist items have `✅`
3. Continue from first incomplete item
4. The sentinel block in the Pine file acts as a clear marker for P3/P4 status:
   - Sentinels present but old `input.*` still there → P3 done, P4 not started
   - Sentinels present AND old `input.*` removed → P4 done
5. `tools/generate_pine_presets.py` existence → P2 done

## Key Invariant

At no point should the Pine file be left in a broken/un-pasteable state.
After each punchlist step, the Pine file must be valid Pine v6 that compiles in TV.
