"""BRK03 — Keltner Channel Breakout
HYPOTHESIS: Long when close > EMA20 + k*ATR(20); flat when close < EMA20.
Try k in {1.5, 2.0, 2.5}. Vol-targeted continuous weights.
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt")
import altlib as al
import numpy as np


def keltner_breakout(df, k: float) -> np.ndarray:
    """Long (vol-targeted) when close > EMA20 + k*ATR(20); flat when close < EMA20.
    All values causal: EMA/ATR at i use data <= i. Decision at close[i] -> held during bar i+1.
    """
    c = df["close"].values.astype(float)
    ema20 = al.ema(c, span=20)
    atr20 = al.atr(df, win=20)

    upper_band = ema20 + k * atr20

    # Direction: +1 if close > upper_band (breakout above), else 0 (flat)
    # Exit: go flat when close < EMA20 (mean reversion back below center)
    n = len(c)
    direction = np.zeros(n, dtype=float)

    # Vectorized: long when above upper band; we then hold until close < EMA20
    # Implement as a state machine
    in_trade = False
    for i in range(n):
        if np.isnan(ema20[i]) or np.isnan(atr20[i]):
            direction[i] = 0.0
            continue
        if not in_trade:
            # Enter long on breakout above upper keltner band
            if c[i] > upper_band[i]:
                in_trade = True
                direction[i] = 1.0
        else:
            # Exit when price drops back below EMA
            if c[i] < ema20[i]:
                in_trade = False
                direction[i] = 0.0
            else:
                direction[i] = 1.0

    # Apply vol-targeting to scale position size
    pos = al.vol_target(direction, df, target_vol=0.20, vol_win_days=30, leverage_cap=2.0)
    return pos


# Grid: k in {1.5, 2.0, 2.5} — try all 3 param sets; pick best by min_asset_holdout_sharpe
best_rep = None
best_score = -999.0
best_k = None

for k_val in [1.5, 2.0, 2.5]:
    name = f"BRK03-k{k_val}"
    print(f"\n--- Running {name} ---")
    rep = al.study_weights(
        name,
        lambda df, k=k_val: keltner_breakout(df, k),
        tfs=("1d", "12h")
    )
    score = rep["verdict"].get("best_holdout_sharpe", -999.0) or -999.0
    print(al.fmt(rep))
    if score > best_score:
        best_score = score
        best_rep = rep
        best_k = k_val

print("\n" + "="*60)
print(f"BEST CONFIG: k={best_k}")
print("="*60)
print(al.fmt(best_rep))
print("JSON:", al.as_json(best_rep))
