| Overall Statistics |
|
Total Orders 628 Average Win 1.47% Average Loss -0.39% Compounding Annual Return 7.664% Drawdown 13.000% Expectancy 0.158 Start Equity 100000.00 End Equity 115962.55 Net Profit 15.963% Sharpe Ratio 0.464 Sortino Ratio 0.924 Probabilistic Sharpe Ratio 16.985% Loss Rate 76% Win Rate 24% Profit-Loss Ratio 3.76 Alpha 0.052 Beta 0.016 Annual Standard Deviation 0.119 Annual Variance 0.014 Information Ratio -0.513 Tracking Error 0.239 Treynor Ratio 3.543 Total Fees $0.00 Estimated Strategy Capacity $530000.00 Lowest Capacity Asset BTCUSD 2XR Portfolio Turnover 73.82% Drawdown Recovery 382 |
# 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 = 20
self.rsi_overbought = 80
self.atr_multiplier = 3.0
self.adx_strength_threshold = 30
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