| Overall Statistics |
|
Total Trades 498 Average Win 0.00% Average Loss -0.01% Compounding Annual Return -0.975% Drawdown 3.400% Expectancy -0.995 Net Profit -3.390% Sharpe Ratio -2.166 Probabilistic Sharpe Ratio 0.000% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0.33 Alpha -0.007 Beta 0.004 Annual Standard Deviation 0.003 Annual Variance 0 Information Ratio -0.52 Tracking Error 0.196 Treynor Ratio -1.903 Total Fees $0.00 Estimated Strategy Capacity $1200000.00 Lowest Capacity Asset BTCUSD XJ Portfolio Turnover 38.67% |
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from QuantConnect.Orders import *
class MovingAverageCrossover(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 1, 1) # set start date
self.SetCash(10000) # set strategy cash
self.btc = self.AddCrypto("BTCUSD", Resolution.Daily) # Bitcoin data
self.fast = self.EMA("BTCUSD", 14, Resolution.Daily)
self.slow = self.EMA("BTCUSD", 28, Resolution.Daily)
self.long_term = self.EMA("BTCUSD", 50, Resolution.Daily)
self.volume = self.SMA("BTCUSD", 14, Resolution.Daily, Field.Volume)
self.atr = self.ATR("BTCUSD", 14, MovingAverageType.Simple, Resolution.Daily)
self.previous = None
self.stopMarketTicket = None
# Initialize the rolling window for the ATR values
self.atrWindow = RollingWindow[IndicatorDataPoint](14)
# Set maximum loss per trade
self.maxLossPerTrade = 0.01 # 1% of portfolio
def OnData(self, data):
if not self.fast.IsReady or not self.slow.IsReady or not self.long_term.IsReady or not self.volume.IsReady or not self.atr.IsReady:
return
if self.previous is not None and self.previous.date() == self.Time.date():
return
# Add the latest ATR value to the rolling window
self.atrWindow.Add(IndicatorDataPoint(self.btc.Symbol, self.Time, self.atr.Current.Value))
# Calculate the average ATR
if self.atrWindow.IsReady:
avg_atr = sum([ind.Value for ind in self.atrWindow]) / self.atrWindow.Count
else:
avg_atr = self.atr.Current.Value
holdings = self.Portfolio["BTCUSD"].Quantity
if self.fast.Current.Value > self.slow.Current.Value and self.Securities["BTCUSD"].Close > self.long_term.Current.Value and self.atr.Current.Value > avg_atr:
if holdings <= 0 and self.btc.Volume > self.volume.Current.Value:
self.SetHoldings("BTCUSD", 1.0)
self.stopMarketTicket = self.StopMarketOrder("BTCUSD",
-self.Portfolio["BTCUSD"].Quantity,
0.9 * self.Securities["BTCUSD"].Close)
elif self.fast.Current.Value < self.slow.Current.Value and self.Securities["BTCUSD"].Close < self.long_term.Current.Value and self.atr.Current.Value > avg_atr:
if holdings >= 0 and self.btc.Volume > self.volume.Current.Value:
self.SetHoldings("BTCUSD", -1.0)
self.stopMarketTicket = self.StopMarketOrder("BTCUSD",
self.Portfolio["BTCUSD"].Quantity,
1.1 * self.Securities["BTCUSD"].Close)
self.previous = self.Time
def OnOrderEvent(self, orderEvent):
order = self.Transactions.GetOrderById(orderEvent.OrderId)
if order.Type == OrderType.StopMarket and orderEvent.Status == OrderStatus.Filled:
self.stopMarketTicket = None
# Check for loss and close position if loss exceeds maximum
if self.Portfolio.Invested:
pnl = self.Portfolio.TotalPortfolioValue - self.Portfolio.TotalUnrealizedProfit
if pnl > self.maxLossPerTrade * self.Portfolio.TotalPortfolioValue:
self.Liquidate()