Repository Public
1"""Volatility-targeted trend: trend-following position, scaled down when realised volatility is high.23Universe-generic (version 3): the symbols are whatever the agent trades; same rule and parameters as version 1.4"""56import numpy as np78META = {9 "name": "vol_target_trend",10 "version": "3",11 "universe": ["*"],12 "interval": "1h",13 "lookback": 1000,14 "params": {"fast": 72, "slow": 480, "vol_window": 168, "target_vol": 0.4},15}1617SECONDS_PER_YEAR = 365.0 * 86400.0181920def target_weights(data, params):21 fast, slow = int(params["fast"]), int(params["slow"])22 vol_window, target_vol = int(params["vol_window"]), float(params["target_vol"])23 n = len(data)24 weights = {}25 for symbol, df in data.items():26 close = df["close"].to_numpy()27 if len(close) < max(fast, slow, vol_window + 1) or fast >= slow or vol_window < 2:28 weights[symbol] = 0.029 continue30 if not close[-fast:].mean() > close[-slow:].mean():31 weights[symbol] = 0.032 continue33 bar_seconds = (df.index[-1] - df.index[-2]).total_seconds()34 log_returns = np.diff(np.log(close[-(vol_window + 1):]))35 realised = log_returns.std(ddof=1) * np.sqrt(SECONDS_PER_YEAR / bar_seconds)36 scale = min(1.0, target_vol / realised) if realised > 0 else 0.037 weights[symbol] = scale / n38 return weights39