"""TRD02 — EMA Cross Long-Short Strategy. HYPOTHESIS: Long when EMA(fast) > EMA(slow), SHORT when fast < slow. Compared to TRD01 (long-flat), this uses the full directional signal (+1/-1). Grid: (fast, slow) in {(10,50), (20,100), (50,200)}. Vol-targeted position (target_vol=20%, leverage cap 2x). Key question: does shorting add alpha vs long-flat in crypto (strong upward drift)? """ import sys sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt") import altlib as al import numpy as np # Grid: (fast, slow) pairs — 3 param sets, tested on 2 TFs = 6 total backtests max GRID = [ (10, 50), (20, 100), (50, 200), ] def make_target(fast: int, slow: int): """Returns a target_fn for the given EMA fast/slow parameters. Signal is decided with data <= close[i] (causal EMA), vol-targeted. Long (+1) when fast > slow, SHORT (-1) when fast < slow. """ def target_fn(df): c = df["close"].values.astype(float) e_fast = al.ema(c, fast) e_slow = al.ema(c, slow) # Direction: +1 when fast > slow, -1 otherwise (long-SHORT, not long-flat) direction = np.where(e_fast > e_slow, 1.0, -1.0) # Warmup: NaN-out until slow EMA has enough data (approx 3x slow period) warmup = slow * 3 direction[:warmup] = 0.0 # Vol-target the position tgt = al.vol_target(direction, df, target_vol=0.20, vol_win_days=30, leverage_cap=2.0) return tgt return target_fn def main(): best_rep = None best_score = -9999.0 best_params = None for (fast, slow) in GRID: name = f"TRD02_ema{fast}_{slow}" print(f"\n=== Testing {name} ===") rep = al.study_weights( name, make_target(fast, slow), tfs=("1d", "12h"), ) verdict = rep["verdict"] score = verdict.get("best_holdout_sharpe", -9999.0) or -9999.0 print(al.fmt(rep)) print("JSON:", al.as_json(rep)) if score > best_score: best_score = score best_rep = rep best_params = (fast, slow) print(f"\n\n=== BEST CONFIG: EMA({best_params[0]},{best_params[1]}) ===") print(al.fmt(best_rep)) print("JSON:", al.as_json(best_rep)) if __name__ == "__main__": main()