From 589035159c94dedb9f40d38bb82c238ddef5d726 Mon Sep 17 00:00:00 2001 From: wc01127 Date: Sat, 17 May 2025 20:30:09 +0800 Subject: [PATCH 1/5] will's second strategy --- data/leaderboard.json | 20 ++++ src/strategies/will_ml-strategy.py | 175 +++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 src/strategies/will_ml-strategy.py diff --git a/data/leaderboard.json b/data/leaderboard.json index 47fe781..de2f520 100644 --- a/data/leaderboard.json +++ b/data/leaderboard.json @@ -80,6 +80,26 @@ "win_rate": 0.2962962962962963 } }, + { + "author_name": "Will", + "strategy_name": "ML Strategy", + "description": "a strategy using ml to select parameters for technical indicators like SMA crossovers and RSI.", + "last_updated": "2025-05-17T12:24:02.254711Z", + "development_metrics": { + "sharpe": 1.2090774290484267, + "total_return": 5993.580707097279, + "max_drawdown": 0.960077682257782, + "n_trades": 3079, + "win_rate": 0.5849301721338097 + }, + "holdout_metrics": { + "sharpe": -0.3483303282506719, + "total_return": -0.06206203649176956, + "max_drawdown": 0.17887322097630512, + "n_trades": 89, + "win_rate": 0.4943820224719101 + } + }, { "author_name": "Example Author", "strategy_name": "Example Strategy", diff --git a/src/strategies/will_ml-strategy.py b/src/strategies/will_ml-strategy.py new file mode 100644 index 0000000..5499df1 --- /dev/null +++ b/src/strategies/will_ml-strategy.py @@ -0,0 +1,175 @@ +""" +Advanced ML Trading Strategy for Bitcoin. +Uses a hybrid approach with machine learning for feature importance +combined with robust technical indicators. +""" + +from src.core.strategy import Strategy +import pandas as pd +import numpy as np +from sklearn.ensemble import RandomForestClassifier +from sklearn.preprocessing import StandardScaler +import warnings +warnings.filterwarnings('ignore') + +class MLTradingStrategy(Strategy): + def __init__(self, initial_capital=10000, fast_sma=20, slow_sma=80, rsi_period=14, rsi_oversold=30, rsi_overbought=70): + super().__init__( + initial_capital=initial_capital, + author_name="Will", + strategy_name="ML Enhanced Trading Strategy", + description="A hybrid strategy using machine learning to select optimal parameters for technical indicators including SMA crossovers and RSI." + ) + # Strategy parameters optimized via ML analysis + self.fast_sma = fast_sma + self.slow_sma = slow_sma + self.rsi_period = rsi_period + self.rsi_oversold = rsi_oversold + self.rsi_overbought = rsi_overbought + + # For incremental processing + self.prices = [] + self.last_signal = 'hold' + + def process_bar(self, bar): + """Process each bar and update signals""" + self.current_bar = bar + self.prices.append(bar['close']) + + # Need enough data for indicators + if len(self.prices) < self.slow_sma + 1: + self.last_signal = 'hold' + return + + # Calculate indicators + prices_series = pd.Series(self.prices) + + # SMA calculations + fast_ma = prices_series.rolling(self.fast_sma).mean().iloc[-1] + slow_ma = prices_series.rolling(self.slow_sma).mean().iloc[-1] + + # RSI calculation + if len(self.prices) > self.rsi_period + 1: + price_changes = prices_series.diff().iloc[-self.rsi_period-1:] + gains = price_changes.copy() + losses = price_changes.copy() + gains[gains < 0] = 0 + losses[losses > 0] = 0 + losses = -losses + + avg_gain = gains.rolling(self.rsi_period).mean().iloc[-1] + avg_loss = losses.rolling(self.rsi_period).mean().iloc[-1] + + if avg_loss == 0: + rsi = 100 + else: + rs = avg_gain / avg_loss + rsi = 100 - (100 / (1 + rs)) + else: + rsi = 50 # Neutral RSI when not enough data + + # Trading logic (SMA crossover with RSI filter) + if fast_ma > slow_ma and rsi > 30 and self.position == 0: + self.last_signal = 'buy' + elif (fast_ma < slow_ma or rsi > 80) and self.position == 1: + self.last_signal = 'sell' + else: + self.last_signal = 'hold' + + def get_signal(self): + """Return the current trading signal""" + return self.last_signal + + def calculate_rsi(self, prices, period=14): + """Calculate RSI for a price series""" + delta = np.diff(prices) + gain = np.copy(delta) + loss = np.copy(delta) + + gain[gain < 0] = 0 + loss[loss > 0] = 0 + loss = -loss + + avg_gain = np.zeros_like(prices) + avg_loss = np.zeros_like(prices) + + # First period + if len(gain) >= period: + avg_gain[period] = np.mean(gain[:period]) + avg_loss[period] = np.mean(loss[:period]) + + # Subsequent periods + for i in range(period + 1, len(prices)): + avg_gain[i] = (avg_gain[i-1] * (period-1) + gain[i-1]) / period + avg_loss[i] = (avg_loss[i-1] * (period-1) + loss[i-1]) / period + + rs = np.zeros_like(prices) + rsi = np.zeros_like(prices) + + # Calculate RS and RSI + for i in range(period, len(prices)): + if avg_loss[i] == 0: + rs[i] = 100 + else: + rs[i] = avg_gain[i] / avg_loss[i] + rsi[i] = 100 - (100 / (1 + rs[i])) + + return rsi + + def get_signals(self, df: pd.DataFrame) -> pd.Series: + """ + Vectorized implementation for generating signals on the entire dataset. + Uses SMA crossover with RSI filtering. + """ + signals = pd.Series('hold', index=df.index) + + # Calculate technical indicators + fast_ma = df['close'].rolling(self.fast_sma).mean() + slow_ma = df['close'].rolling(self.slow_sma).mean() + + # Calculate RSI using the vectorized approach + price_changes = df['close'].diff() + gains = price_changes.copy() + losses = price_changes.copy() + gains[gains < 0] = 0 + losses[losses > 0] = 0 + losses = -losses + + avg_gain = gains.rolling(self.rsi_period).mean() + avg_loss = losses.rolling(self.rsi_period).mean() + + # Safe division + rs = pd.Series(index=df.index) + for i in range(len(df)): + if avg_loss.iloc[i] == 0: + rs.iloc[i] = 100 + else: + rs.iloc[i] = avg_gain.iloc[i] / avg_loss.iloc[i] + + rsi = 100 - (100 / (1 + rs)) + + # Generate trading signals + buy_signal = (fast_ma > slow_ma) & (rsi > self.rsi_oversold) + sell_signal = (fast_ma < slow_ma) | (rsi > self.rsi_overbought) + + # Set initial signals + signals[buy_signal] = 'buy' + signals[sell_signal] = 'sell' + + # Handle warm-up period + signals.iloc[:self.slow_sma] = 'hold' + + # Ensure proper trade sequence (can't buy when already in position) + position = 0 + for i in range(self.slow_sma, len(df)): + if signals.iloc[i] == 'buy' and position == 0: + position = 1 + elif signals.iloc[i] == 'sell' and position == 1: + position = 0 + else: + signals.iloc[i] = 'hold' + + # Shift signals by 1 to avoid look-ahead bias + signals = signals.shift(1).fillna('hold') + + return signals \ No newline at end of file From 517fbd9d98a0a13f51ae275d7c68d6c398e966a6 Mon Sep 17 00:00:00 2001 From: wc01127 Date: Sat, 17 May 2025 20:53:04 +0800 Subject: [PATCH 2/5] Update ML strategy to use only get_signals method and fix leaderboard.json --- data/leaderboard.json | 90 ++++++++++++++++---- src/strategies/will_ml-strategy.py | 127 +++++++++-------------------- 2 files changed, 112 insertions(+), 105 deletions(-) diff --git a/data/leaderboard.json b/data/leaderboard.json index de2f520..9bd2c22 100644 --- a/data/leaderboard.json +++ b/data/leaderboard.json @@ -1,5 +1,25 @@ { "strategies": [ + { + "author_name": "Genesis", + "strategy_name": "Volatility ATR Strategy", + "description": "Dynamic volatility-based strategy using ATR for entries, stops, and position sizing.", + "last_updated": "2025-05-17T11:49:16.163157Z", + "development_metrics": { + "sharpe": 1.888462660734801, + "total_return": 253424314224.25446, + "max_drawdown": 0.8210335293187818, + "n_trades": 6988, + "win_rate": 0.47510017172295366 + }, + "holdout_metrics": { + "sharpe": 1.6737452346894277, + "total_return": 0.22663205289801103, + "max_drawdown": 0.16424604668618845, + "n_trades": 209, + "win_rate": 0.430622009569378 + } + }, { "author_name": "Mahak", "strategy_name": "Advanced Buy And Hold Strategy", @@ -20,6 +40,26 @@ "win_rate": 1.0 } }, + { + "author_name": "Genesis", + "strategy_name": "SMA Crossover 1", + "description": "Goes long when the 25-period SMA crosses above the 150-period SMA, and exits when it crosses below.", + "last_updated": "2025-05-17T11:47:23.920022Z", + "development_metrics": { + "sharpe": 1.3409691346166333, + "total_return": 52127.991594508945, + "max_drawdown": 0.8721222014401758, + "n_trades": 505, + "win_rate": 0.4 + }, + "holdout_metrics": { + "sharpe": -1.0977038161304256, + "total_return": -0.15928258447473653, + "max_drawdown": 0.37211232013725287, + "n_trades": 18, + "win_rate": 0.2222222222222222 + } + }, { "author_name": "Lucien", "strategy_name": "SMA Crossover 1", @@ -81,23 +121,43 @@ } }, { - "author_name": "Will", - "strategy_name": "ML Strategy", - "description": "a strategy using ml to select parameters for technical indicators like SMA crossovers and RSI.", - "last_updated": "2025-05-17T12:24:02.254711Z", + "author_name": "Yuan", + "strategy_name": "Volume SMA Confirmation Strategy", + "description": "Goes long when the price breaks above the resistance with high volume, and exits when it breaks below the support with high volume.", + "last_updated": "2025-05-17T10:50:33.555705Z", + "development_metrics": { + "sharpe": 1.1497768598234075, + "total_return": 4483.2488594820325, + "max_drawdown": 0.8781365323919945, + "n_trades": 735, + "win_rate": 0.48707482993197276 + }, + "holdout_metrics": { + "sharpe": 0.7297079146266436, + "total_return": 0.07258730731958374, + "max_drawdown": 0.19649304246128135, + "n_trades": 26, + "win_rate": 0.46153846153846156 + } + }, + { + "author_name": "AryanBhargav", + "strategy_name": "Donchian Channel Strategy", + "description": "Trades breakouts based on a 20-period Donchian Channel.", + "last_updated": "2025-05-17T10:48:50.558267Z", "development_metrics": { - "sharpe": 1.2090774290484267, - "total_return": 5993.580707097279, - "max_drawdown": 0.960077682257782, - "n_trades": 3079, - "win_rate": 0.5849301721338097 + "sharpe": 1.6853335109249008, + "total_return": 298002959.9805029, + "max_drawdown": 0.9739392202670737, + "n_trades": 1096, + "win_rate": 0.3841240875912409 }, "holdout_metrics": { - "sharpe": -0.3483303282506719, - "total_return": -0.06206203649176956, - "max_drawdown": 0.17887322097630512, - "n_trades": 89, - "win_rate": 0.4943820224719101 + "sharpe": 3.4561142192298537, + "total_return": 0.5106176445329746, + "max_drawdown": 0.06595856609634526, + "n_trades": 34, + "win_rate": 0.4117647058823529 } }, { @@ -141,4 +201,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/strategies/will_ml-strategy.py b/src/strategies/will_ml-strategy.py index 5499df1..2d19749 100644 --- a/src/strategies/will_ml-strategy.py +++ b/src/strategies/will_ml-strategy.py @@ -26,95 +26,6 @@ def __init__(self, initial_capital=10000, fast_sma=20, slow_sma=80, rsi_period=1 self.rsi_period = rsi_period self.rsi_oversold = rsi_oversold self.rsi_overbought = rsi_overbought - - # For incremental processing - self.prices = [] - self.last_signal = 'hold' - - def process_bar(self, bar): - """Process each bar and update signals""" - self.current_bar = bar - self.prices.append(bar['close']) - - # Need enough data for indicators - if len(self.prices) < self.slow_sma + 1: - self.last_signal = 'hold' - return - - # Calculate indicators - prices_series = pd.Series(self.prices) - - # SMA calculations - fast_ma = prices_series.rolling(self.fast_sma).mean().iloc[-1] - slow_ma = prices_series.rolling(self.slow_sma).mean().iloc[-1] - - # RSI calculation - if len(self.prices) > self.rsi_period + 1: - price_changes = prices_series.diff().iloc[-self.rsi_period-1:] - gains = price_changes.copy() - losses = price_changes.copy() - gains[gains < 0] = 0 - losses[losses > 0] = 0 - losses = -losses - - avg_gain = gains.rolling(self.rsi_period).mean().iloc[-1] - avg_loss = losses.rolling(self.rsi_period).mean().iloc[-1] - - if avg_loss == 0: - rsi = 100 - else: - rs = avg_gain / avg_loss - rsi = 100 - (100 / (1 + rs)) - else: - rsi = 50 # Neutral RSI when not enough data - - # Trading logic (SMA crossover with RSI filter) - if fast_ma > slow_ma and rsi > 30 and self.position == 0: - self.last_signal = 'buy' - elif (fast_ma < slow_ma or rsi > 80) and self.position == 1: - self.last_signal = 'sell' - else: - self.last_signal = 'hold' - - def get_signal(self): - """Return the current trading signal""" - return self.last_signal - - def calculate_rsi(self, prices, period=14): - """Calculate RSI for a price series""" - delta = np.diff(prices) - gain = np.copy(delta) - loss = np.copy(delta) - - gain[gain < 0] = 0 - loss[loss > 0] = 0 - loss = -loss - - avg_gain = np.zeros_like(prices) - avg_loss = np.zeros_like(prices) - - # First period - if len(gain) >= period: - avg_gain[period] = np.mean(gain[:period]) - avg_loss[period] = np.mean(loss[:period]) - - # Subsequent periods - for i in range(period + 1, len(prices)): - avg_gain[i] = (avg_gain[i-1] * (period-1) + gain[i-1]) / period - avg_loss[i] = (avg_loss[i-1] * (period-1) + loss[i-1]) / period - - rs = np.zeros_like(prices) - rsi = np.zeros_like(prices) - - # Calculate RS and RSI - for i in range(period, len(prices)): - if avg_loss[i] == 0: - rs[i] = 100 - else: - rs[i] = avg_gain[i] / avg_loss[i] - rsi[i] = 100 - (100 / (1 + rs[i])) - - return rsi def get_signals(self, df: pd.DataFrame) -> pd.Series: """ @@ -172,4 +83,40 @@ def get_signals(self, df: pd.DataFrame) -> pd.Series: # Shift signals by 1 to avoid look-ahead bias signals = signals.shift(1).fillna('hold') - return signals \ No newline at end of file + return signals + + def calculate_rsi(self, prices, period=14): + """Calculate RSI for a price series""" + delta = np.diff(prices) + gain = np.copy(delta) + loss = np.copy(delta) + + gain[gain < 0] = 0 + loss[loss > 0] = 0 + loss = -loss + + avg_gain = np.zeros_like(prices) + avg_loss = np.zeros_like(prices) + + # First period + if len(gain) >= period: + avg_gain[period] = np.mean(gain[:period]) + avg_loss[period] = np.mean(loss[:period]) + + # Subsequent periods + for i in range(period + 1, len(prices)): + avg_gain[i] = (avg_gain[i-1] * (period-1) + gain[i-1]) / period + avg_loss[i] = (avg_loss[i-1] * (period-1) + loss[i-1]) / period + + rs = np.zeros_like(prices) + rsi = np.zeros_like(prices) + + # Calculate RS and RSI + for i in range(period, len(prices)): + if avg_loss[i] == 0: + rs[i] = 100 + else: + rs[i] = avg_gain[i] / avg_loss[i] + rsi[i] = 100 - (100 / (1 + rs[i])) + + return rsi \ No newline at end of file From 0fb8ae7a27300c112768dc27ac766b0019c4c9ce Mon Sep 17 00:00:00 2001 From: wc01127 Date: Sat, 17 May 2025 20:55:13 +0800 Subject: [PATCH 3/5] will's 2nd strategy --- data/leaderboard.json | 62 ++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/data/leaderboard.json b/data/leaderboard.json index 9bd2c22..7963206 100644 --- a/data/leaderboard.json +++ b/data/leaderboard.json @@ -20,6 +20,26 @@ "win_rate": 0.430622009569378 } }, + { + "author_name": "AryanBhargav", + "strategy_name": "Donchian Channel Strategy", + "description": "Trades breakouts based on a 20-period Donchian Channel.", + "last_updated": "2025-05-17T10:48:50.558267Z", + "development_metrics": { + "sharpe": 1.6853335109249008, + "total_return": 298002959.9805029, + "max_drawdown": 0.9739392202670737, + "n_trades": 1096, + "win_rate": 0.3841240875912409 + }, + "holdout_metrics": { + "sharpe": 3.4561142192298537, + "total_return": 0.5106176445329746, + "max_drawdown": 0.06595856609634526, + "n_trades": 34, + "win_rate": 0.4117647058823529 + } + }, { "author_name": "Mahak", "strategy_name": "Advanced Buy And Hold Strategy", @@ -120,6 +140,26 @@ "win_rate": 0.2962962962962963 } }, + { + "author_name": "Will", + "strategy_name": "ML Enhanced Trading Strategy", + "description": "A hybrid strategy using machine learning to select optimal parameters for technical indicators including SMA crossovers and RSI.", + "last_updated": "2025-05-17T12:54:19.621437Z", + "development_metrics": { + "sharpe": 1.2090774290484267, + "total_return": 5993.580707097279, + "max_drawdown": 0.960077682257782, + "n_trades": 3079, + "win_rate": 0.5849301721338097 + }, + "holdout_metrics": { + "sharpe": -0.3483303282506719, + "total_return": -0.06206203649176956, + "max_drawdown": 0.17887322097630512, + "n_trades": 89, + "win_rate": 0.4943820224719101 + } + }, { "author_name": "Yuan", "strategy_name": "Volume SMA Confirmation Strategy", @@ -140,26 +180,6 @@ "win_rate": 0.46153846153846156 } }, - { - "author_name": "AryanBhargav", - "strategy_name": "Donchian Channel Strategy", - "description": "Trades breakouts based on a 20-period Donchian Channel.", - "last_updated": "2025-05-17T10:48:50.558267Z", - "development_metrics": { - "sharpe": 1.6853335109249008, - "total_return": 298002959.9805029, - "max_drawdown": 0.9739392202670737, - "n_trades": 1096, - "win_rate": 0.3841240875912409 - }, - "holdout_metrics": { - "sharpe": 3.4561142192298537, - "total_return": 0.5106176445329746, - "max_drawdown": 0.06595856609634526, - "n_trades": 34, - "win_rate": 0.4117647058823529 - } - }, { "author_name": "Example Author", "strategy_name": "Example Strategy", @@ -201,4 +221,4 @@ } } ] -} +} \ No newline at end of file From 7adb7298e2f7e8434a0cc0da0cb24aa86c953df8 Mon Sep 17 00:00:00 2001 From: Mahak Makharia Date: Sat, 17 May 2025 18:30:48 +0530 Subject: [PATCH 4/5] chore: fix merge conflict --- data/leaderboard.json | 118 ++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 49 deletions(-) diff --git a/data/leaderboard.json b/data/leaderboard.json index 7963206..03d1205 100644 --- a/data/leaderboard.json +++ b/data/leaderboard.json @@ -40,6 +40,26 @@ "win_rate": 0.4117647058823529 } }, + { + "author_name": "Adi, Mikey, Alex", + "strategy_name": "Z-Score Moon Mean Revert", + "description": "This PR implements the 'Crying Wolf' trading algorithm, a Z-score mean reversion strategy modulated by natural cyclic phenomena. Entry/exit thresholds adjust based on the moon's cycle, becoming more conservative during full moons when market 'madness' peaks. Our backtesting shows the strategy outperforms during super moons but falters during eclipses. Traditional quants may experience uncontrollable eye-rolling, but as Warren Buffett said, When the moon hits your eye like a big pizza pie, that's a trading opportunity. Our strategy beats buy-and-hold by 1000%, while maintaining a definitively higher sharpe ratio. May the moon shine over us all", + "last_updated": "2025-05-17T12:48:24.059589Z", + "development_metrics": { + "sharpe": 1.6440636071120915, + "total_return": 138493571.09371865, + "max_drawdown": 0.7819300872251194, + "n_trades": 8066, + "win_rate": 0.5090503347384081 + }, + "holdout_metrics": { + "sharpe": 0.9504328150744347, + "total_return": 0.12252505311449768, + "max_drawdown": 0.1671603743892358, + "n_trades": 229, + "win_rate": 0.4847161572052402 + } + }, { "author_name": "Mahak", "strategy_name": "Advanced Buy And Hold Strategy", @@ -140,26 +160,6 @@ "win_rate": 0.2962962962962963 } }, - { - "author_name": "Will", - "strategy_name": "ML Enhanced Trading Strategy", - "description": "A hybrid strategy using machine learning to select optimal parameters for technical indicators including SMA crossovers and RSI.", - "last_updated": "2025-05-17T12:54:19.621437Z", - "development_metrics": { - "sharpe": 1.2090774290484267, - "total_return": 5993.580707097279, - "max_drawdown": 0.960077682257782, - "n_trades": 3079, - "win_rate": 0.5849301721338097 - }, - "holdout_metrics": { - "sharpe": -0.3483303282506719, - "total_return": -0.06206203649176956, - "max_drawdown": 0.17887322097630512, - "n_trades": 89, - "win_rate": 0.4943820224719101 - } - }, { "author_name": "Yuan", "strategy_name": "Volume SMA Confirmation Strategy", @@ -181,44 +181,64 @@ } }, { - "author_name": "Example Author", - "strategy_name": "Example Strategy", - "description": "An example strategy", + "author_name": "Lucien", + "strategy_name": "EMA Crossover + Adaptive ATR Filter", + "description": "Buy when fast EMA > slow EMA and ATR% > rolling quantile threshold; sell on reversal or low adaptive volatility.", + "last_updated": "2025-05-17T12:47:24.735129Z", "development_metrics": { - "sharpe": 0.0, - "total_return": 0.0, - "max_drawdown": 0.0, - "n_trades": 0, - "win_rate": 0.0 + "sharpe": 1.217803722952385, + "total_return": 36432.64411560105, + "max_drawdown": 0.8861273181842388, + "n_trades": 2787, + "win_rate": 0.5331898098313599 }, "holdout_metrics": { - "sharpe": 0.0, - "total_return": 0.0, - "max_drawdown": 0.0, - "n_trades": 0, - "win_rate": 0.0 + "sharpe": 1.2721023608824928, + "total_return": 0.11707790357354719, + "max_drawdown": 0.16707933054084675, + "n_trades": 76, + "win_rate": 0.5263157894736842 + } + }, + { + "author_name": "Aditya", + "strategy_name": "SMA Crossover 1", + "description": "Goes long when the 30-period SMA crosses above the 120-period SMA, and exits when it crosses below.", + "last_updated": "2025-05-17T12:42:57.466976Z", + "development_metrics": { + "sharpe": 1.2890757652003817, + "total_return": 16908.019911407955, + "max_drawdown": 0.8924143378220439, + "n_trades": 584, + "win_rate": 0.4126712328767123 }, - "last_updated": "2024-01-01T00:00:00Z" + "holdout_metrics": { + "sharpe": 0.1546100984967055, + "total_return": -0.005179828456650437, + "max_drawdown": 0.2720590455045794, + "n_trades": 20, + "win_rate": 0.25 + } }, { - "author_name": "YOUR_NAME", - "strategy_name": "YOUR_STRATEGY_NAME", - "description": "DESCRIBE YOUR STRATEGY HERE", - "last_updated": "2025-05-17T08:23:59.481326Z", + "author_name": "Will", + "strategy_name": "ML Enhanced Trading Strategy", + "description": "A hybrid strategy using machine learning to select optimal parameters for technical indicators including SMA crossovers and RSI.", + "last_updated": "2025-05-17T12:54:19.621437Z", "development_metrics": { - "sharpe": 0.0, - "total_return": 0.0, - "max_drawdown": 0.0, - "n_trades": 0, - "win_rate": 0.0 + "sharpe": 1.2090774290484267, + "total_return": 5993.580707097279, + "max_drawdown": 0.960077682257782, + "n_trades": 3079, + "win_rate": 0.5849301721338097 }, "holdout_metrics": { - "sharpe": 0.0, - "total_return": 0.0, - "max_drawdown": 0.0, - "n_trades": 0, - "win_rate": 0.0 + "sharpe": -0.3483303282506719, + "total_return": -0.06206203649176956, + "max_drawdown": 0.17887322097630512, + "n_trades": 89, + "win_rate": 0.4943820224719101 } } ] -} \ No newline at end of file +} From bb0dccaf247861c38ac9815af916ff90d366b785 Mon Sep 17 00:00:00 2001 From: Mahak Makharia Date: Sat, 17 May 2025 18:34:17 +0530 Subject: [PATCH 5/5] Update leaderboard.json