Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 74 additions & 54 deletions data/leaderboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@
"win_rate": 0.4847161572052402
}
},
{
"author_name": "Jim",
"strategy_name": "Enhanced Price Momentum",
"description": "Enhanced momentum strategy with trend confirmation, volatility-based position sizing, and risk management.",
"last_updated": "2025-05-17T12:50:15.376811Z",
"development_metrics": {
"sharpe": 1.5028615712789264,
"total_return": 83691.01305699791,
"max_drawdown": 0.8047181682279175,
"n_trades": 175,
"win_rate": 0.4685714285714286
},
"holdout_metrics": {
"sharpe": 2.3589800460822663,
"total_return": 0.25319737220833005,
"max_drawdown": 0.09536946074759874,
"n_trades": 8,
"win_rate": 0.75
}
},
{
"author_name": "Mahak",
"strategy_name": "Advanced Buy And Hold Strategy",
Expand Down Expand Up @@ -140,6 +160,26 @@
"win_rate": 0.25
}
},
{
"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
},
"holdout_metrics": {
"sharpe": 0.1546100984967055,
"total_return": -0.005179828456650437,
"max_drawdown": 0.2720590455045794,
"n_trades": 20,
"win_rate": 0.25
}
},
{
"author_name": "Will",
"strategy_name": "SMA Crossover 1",
Expand All @@ -160,26 +200,6 @@
"win_rate": 0.2962962962962963
}
},
{
"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": "Lucien",
"strategy_name": "EMA Crossover + Adaptive ATR Filter",
Expand All @@ -200,26 +220,6 @@
"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
},
"holdout_metrics": {
"sharpe": 0.1546100984967055,
"total_return": -0.005179828456650437,
"max_drawdown": 0.2720590455045794,
"n_trades": 20,
"win_rate": 0.25
}
},
{
"author_name": "Will",
"strategy_name": "ML Enhanced Trading Strategy",
Expand All @@ -241,23 +241,43 @@
}
},
{
"author_name": "Jim",
"strategy_name": "Enhanced Price Momentum",
"description": "Enhanced momentum strategy with trend confirmation, volatility-based position sizing, and risk management.",
"last_updated": "2025-05-17T12:50:15.376811Z",
"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.5028615712789264,
"total_return": 83691.01305699791,
"max_drawdown": 0.8047181682279175,
"n_trades": 175,
"win_rate": 0.4685714285714286
"sharpe": 1.1497768598234075,
"total_return": 4483.2488594820325,
"max_drawdown": 0.8781365323919945,
"n_trades": 735,
"win_rate": 0.48707482993197276
},
"holdout_metrics": {
"sharpe": 2.3589800460822663,
"total_return": 0.25319737220833005,
"max_drawdown": 0.09536946074759874,
"n_trades": 8,
"win_rate": 0.75
"sharpe": 0.7297079146266436,
"total_return": 0.07258730731958374,
"max_drawdown": 0.19649304246128135,
"n_trades": 26,
"win_rate": 0.46153846153846156
}
},
{
"author_name": "Barnabas",
"strategy_name": "Multi EWMA Crossover (Choppy)",
"description": "Goes long when the fast EWMA crosses above the slow EWMA, and exits when it crosses below. Prevents trades when the market is choppy.",
"last_updated": "2025-05-17T17:57:56.951056Z",
"development_metrics": {
"sharpe": 1.1292850486779653,
"total_return": 4629.7711500823425,
"max_drawdown": 0.911266631874821,
"n_trades": 328,
"win_rate": 0.34146341463414637
},
"holdout_metrics": {
"sharpe": 0.5300982500415287,
"total_return": 0.04090393135053816,
"max_drawdown": 0.15072754709598601,
"n_trades": 7,
"win_rate": 0.2857142857142857
}
},
{
Expand Down
94 changes: 94 additions & 0 deletions src/strategies/barnabas-ewma.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import pandas as pd
import numpy as np

from src.core.strategy import Strategy

def choppiness(high: pd.Series,
low: pd.Series,
close: pd.Series,
length: int = 14) -> pd.Series:
"""
Choppiness Index (CHOP)

Parameters
----------
high, low, close : pd.Series
length : look-back period (default 14)

Returns
-------
pd.Series of CHOP values in the 0-100 range
"""
# True Range (vectorised)
tr = pd.concat([
high - low,
(high - close.shift(1)).abs(),
(low - close.shift(1)).abs()
], axis=1).max(axis=1)

sum_tr = tr.rolling(length).sum()
price_range = high.rolling(length).max() - low.rolling(length).min()

# Avoid divide-by-zero if range is zero
chop = 100 * np.log10(sum_tr / price_range.replace(0, np.nan)) / np.log10(length)
return chop

class BarnabasEWMA(Strategy):
def __init__(self, initial_capital=10000, fast=20, slow=200):
super().__init__(
initial_capital=initial_capital,
author_name="Barnabas",
strategy_name="Multi EWMA Crossover (Choppy)",
description="Goes long when the fast EWMA crosses above the slow EWMA, and exits when it crosses below. Prevents trades when the market is choppy."
)
self.prices = []
self.fast = fast
self.slow = slow
self.fast2 = fast * 2
self.slow2 = slow * 2
self.last_signal = 'hold'

def process_bar(self, bar):
"""
Process each bar of data.
This is where you implement your strategy logic.

Args:
bar: Dictionary containing 'time', 'close', and 'volume' data
"""
self.current_bar = bar

# Add your strategy logic here
# For example:
# if self.current_bar['close'] > self.previous_close * (1 + self.threshold):
# self.last_signal = 'buy'
# elif self.current_bar['close'] < self.previous_close * (1 - self.threshold):
# self.last_signal = 'sell'
# else:
# self.last_signal = 'hold'

def get_signal(self):
"""
Return the current trading signal.
Must return one of: 'buy', 'sell', 'hold'
"""
# Add your signal generation logic here
return 'hold'

def get_signals(self, df: pd.DataFrame) -> pd.Series:
"""
Vectorized version of signal generation.
Override this if you want to implement a more efficient vectorized version.
"""
fast_ma = df['close'].ewm(span=self.fast).mean()
slow_ma = df['close'].ewm(span=self.slow).mean()
fast2_ma = df['close'].ewm(span=self.fast2).mean()
slow2_ma = df['close'].ewm(span=self.slow2).mean()
signals = pd.Series('hold', index=df.index)
choppy = choppiness(df['high'], df['low'], df['close'], length=self.slow2)
signals[(fast_ma > slow_ma) & (fast2_ma > slow2_ma) & (choppy < 60)] = 'buy'
signals[(fast_ma < slow_ma)] = 'sell'
signals.iloc[:self.slow-1] = 'hold'

signals = signals.shift(1).fillna('hold')
return signals