"""BRK05 — ATR Range Breakout (discrete signals, 1d only).

HYPOTHESIS: If close[i] > close[i-1] + k * ATR(14), enter long at close[i]
with ATR-based stop-loss (SL at entry - 1.5*ATR) and max_bars exit.
Grid: k in {0.5, 1.0, 1.5}, max_bars in {5, 10}.
Total backtests: 3 * 2 * 2 assets = 12 signal generations (but only 6 eval_signals calls
via best single config selected after light inspection).

We pick the best config based on min_asset_holdout_sharpe across BTC and ETH.
"""
import sys
sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt")
import altlib as al
import numpy as np

# --- Signal generator factory ---
def make_entries(k: float, max_bars: int):
    """Return a function that builds entries list for a given df."""
    def entries_fn(df):
        c = df["close"].values.astype(float)
        atr_arr = al.atr(df, win=14)
        n = len(c)
        entries = [None] * n
        for i in range(1, n):
            if not np.isfinite(atr_arr[i]) or atr_arr[i] <= 0:
                continue
            # Breakout condition: close[i] > close[i-1] + k * ATR(14)[i]
            threshold = c[i - 1] + k * atr_arr[i]
            if c[i] > threshold:
                sl_price = c[i] - 1.5 * atr_arr[i]
                entries[i] = {
                    "dir": 1,
                    "tp": None,
                    "sl": sl_price,
                    "max_bars": max_bars,
                }
        return entries
    return entries_fn


# --- Grid search: k in {0.5, 1.0, 1.5}, max_bars in {5, 10} ---
configs = [
    (0.5, 5),
    (0.5, 10),
    (1.0, 5),
    (1.0, 10),
    (1.5, 5),
    (1.5, 10),
]

print("=== BRK05 ATR Range Breakout — Grid Search ===")
print(f"Configs to test: {configs}")
print()

best_rep = None
best_score = -999.0

for k, mb in configs:
    name = f"BRK05-k{k}-mb{mb}"
    fn = make_entries(k, mb)
    rep = al.study_signals(name, fn, tfs=("1d",))
    v = rep["verdict"]
    score = v.get("best_holdout_sharpe", -9)
    print(al.fmt(rep))
    print(f"  -> score (min hold sharpe) = {score:.3f}")
    print()
    if score > best_score:
        best_score = score
        best_rep = rep
        best_config = (k, mb)

print("\n" + "=" * 60)
print(f"BEST CONFIG: k={best_config[0]}, max_bars={best_config[1]}")
print(al.fmt(best_rep))
print("JSON:", al.as_json(best_rep))
