SPB Git

Repository Public

strategy.py 2.0 KB 58 lines python

1"""Long/short z-score mean reversion with a stop: fade large deviations from the short-term mean."""23import numpy as np45META = {6    "name": "zscore_reversion_perp",7    "version": "1",8    "kind": "perp",9    "universe": ["BTC", "ETH", "SOL", "HYPE"],10    "interval": "1h",11    "lookback": 300,12    "max_leverage": 2.0,13    "max_gross_exposure": 2.0,14    "params": {"window": 48, "entry_z": 2.0, "exit_z": 0.5, "stop_z": 4.0, "gross": 1.0},15}161718def _zscores(close, window):19    """z of each close against the mean and standard deviation of the `window` closes ending on it."""20    views = np.lib.stride_tricks.sliding_window_view(close, window)21    mean = views.mean(axis=1)22    std = views.std(axis=1, ddof=1)23    z = np.zeros(len(mean))24    ok = std > 025    z[ok] = (close[window - 1:][ok] - mean[ok]) / std[ok]26    return z272829def _state(z, entry_z, exit_z, stop_z):30    """Replay the rule over the window (the function keeps no memory): +1 long, -1 short, 0 flat."""31    state, blocked = 0, False32    for value in z:33        if blocked and abs(value) < exit_z:34            blocked = False35        if state == 0:36            if not blocked and entry_z < abs(value) < stop_z:37                state = -1 if value > 0 else 138        elif abs(value) > stop_z:                       # the deviation kept growing: stop, wait for a return39            state, blocked = 0, True40        elif (state == 1 and value > -exit_z) or (state == -1 and value < exit_z):41            state = 042    return state434445def target_weights(data, params):46    window = int(params["window"])47    entry_z, exit_z, stop_z = float(params["entry_z"]), float(params["exit_z"]), float(params["stop_z"])48    gross = float(params["gross"])49    n = len(data)50    weights = {}51    for symbol, df in data.items():52        close = df["close"].to_numpy()53        if window < 3 or len(close) < window + 1 or not exit_z < entry_z < stop_z:54            weights[symbol] = 0.055            continue56        weights[symbol] = _state(_zscores(close, window), entry_z, exit_z, stop_z) * gross / n57    return weights58
Files main
Menu

Theme