| Overall Statistics |
|
Total Orders 320 Average Win 1.88% Average Loss -0.33% Compounding Annual Return 20.226% Drawdown 5.500% Expectancy 0.847 Start Equity 100000.00 End Equity 144688.04 Net Profit 44.688% Sharpe Ratio 1.343 Sortino Ratio 2.323 Probabilistic Sharpe Ratio 76.069% Loss Rate 73% Win Rate 27% Profit-Loss Ratio 5.76 Alpha 0.135 Beta 0.014 Annual Standard Deviation 0.102 Annual Variance 0.01 Information Ratio -0.176 Tracking Error 0.231 Treynor Ratio 9.522 Total Fees $0.00 Estimated Strategy Capacity $500000.00 Lowest Capacity Asset BTCUSD 2XR Portfolio Turnover 37.80% Drawdown Recovery 244 |
# region imports
from AlgorithmImports import *
# endregion
class MultiIndicatorStrategy(QCAlgorithm):
def Initialize(self):
self.set_start_date(2020,1,1)
self.set_end_date(2022, 1, 1)
self.set_cash(100000)
self.btc = self.add_crypto("BTCUSD", Resolution.MINUTE, Market.COINBASE)
fast_period = 50
slow_period = 200
rsi_period = 14
atr_period = 14
adx_period = 14
volume_period = 24
self.rsi_overbought = 85
self.atr_multiplier = 2.0
self.adx_strength_threshold = 37
self.fast_ema = self.ema(self.btc.Symbol, fast_period, Resolution.MINUTE)
self.slow_ema = self.ema(self.btc.Symbol, slow_period, Resolution.MINUTE)
self.RSI = self.rsi(self.btc.Symbol, rsi_period, MovingAverageType.EXPONENTIAL, Resolution.MINUTE)
self.ATR = self.atr(self.btc.Symbol, atr_period, MovingAverageType.EXPONENTIAL, Resolution.MINUTE)
self.ADX = self.adx(self.btc.symbol, adx_period, Resolution.MINUTE)
self.MACD = self.macd(self.btc.symbol, 12, 26, 9, MovingAverageType.EXPONENTIAL, Resolution.MINUTE)
self.volume_sma = self.sma(self.btc.symbol, volume_period, Resolution.MINUTE, Field.VOLUME)
self.previous_direction = 0
self.stop_loss_ticket = None
def OnData(self, data: Slice):
if not all([self.slow_ema.is_ready, self.RSI.is_ready, self.ATR.is_ready, self.ADX.is_ready, self.MACD.is_ready, self.volume_sma.is_ready]):
return
current_direction = 0
if self.fast_ema.Current.Value > self.slow_ema.Current.Value:
current_direction = 1 # Bullish
elif self.fast_ema.Current.Value < self.slow_ema.Current.Value:
current_direction = -1 # Bearish
is_strong_trend = self.ADX.current.value > self.adx_strength_threshold
is_momentum_confirmed = self.MACD.current.value > self.MACD.signal.current.value
is_volume_confirmed = self.securities[self.btc.symbol].volume > self.volume_sma.current.value
is_new_crossover = self.previous_direction != current_direction
if is_new_crossover and current_direction == 1:
if not self.portfolio.invested and self.RSI.Current.Value < self.rsi_overbought and is_strong_trend and is_momentum_confirmed and is_volume_confirmed:
self.log(f"Entry Signal: Strong Trend (ADX>{self.adx_strength_threshold}), MACD Bullish. Buying BTC.")
self.set_holdings(self.btc.Symbol, 1.0)
stop_price = self.securities[self.btc.Symbol].Close - (self.ATR.Current.Value * self.atr_multiplier)
self.stop_loss_ticket = self.stop_market_order(self.btc.Symbol, -self.portfolio[self.btc.Symbol].quantity, stop_price)
self.log(f"Stop-loss order placed at {stop_price:.2f}")
elif is_new_crossover and current_direction == -1:
if self.portfolio.invested:
self.log("Bearish Crossover: Liquidating BTC position.")
self.liquidate(self.btc.Symbol)
if self.stop_loss_ticket:
self.stop_loss_ticket.Cancel()
self.stop_loss_ticket = None
self.previous_direction = current_direction
def OnOrderEvent(self, orderEvent):
if orderEvent.Status == OrderStatus.FILLED:
self.log(f"Filled order: {orderEvent.Symbol} - Quantity: {orderEvent.FillQuantity} @ {orderEvent.FillPrice:.2f}")
if self.stop_loss_ticket and self.stop_loss_ticket.OrderId == orderEvent.OrderId:
self.log(f"Stop-loss triggered for {orderEvent.Symbol}.")
self.stop_loss_ticket = None
if orderEvent.Status == OrderStatus.CANCELED:
if self.stop_loss_ticket and self.stop_loss_ticket.OrderId == orderEvent.OrderId:
self.stop_loss_ticket = None