Overall Statistics |
Total Trades 25 Average Win 0% Average Loss -1.16% Compounding Annual Return -81.842% Drawdown 13.500% Expectancy -1 Net Profit -13.489% Sharpe Ratio -2.753 Probabilistic Sharpe Ratio 0.321% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.107 Beta 0.008 Annual Standard Deviation 0.041 Annual Variance 0.002 Information Ratio 1.736 Tracking Error 0.381 Treynor Ratio -14.348 Total Fees $18603.56 Estimated Strategy Capacity $150000.00 Lowest Capacity Asset BTCUSD XJ |
#region imports from AlgorithmImports import * #endregion # EMA Cross over strategy 9-13-21-55 # ------------------------------------------------------------------- CRYPTO = "BTCUSD"; EMA_C1 = 9; EMA_C2 = 13; EMA_F = 21; EMA_S = 55; # ------------------------------------------------------------------- class MovingAverageCrossAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2022, 4, 1) self.SetEndDate(2022, 5, 1) self.SetCash("USDT", 100000) self.SetBrokerageModel(BrokerageName.FTXUS, AccountType.Margin) res = Resolution.Hour self.crypto = self.AddCrypto(CRYPTO, res, Market.GDAX).Symbol self.ema_c1 = self.EMA(self.crypto, EMA_C1, res) self.ema_c2 = self.EMA(self.crypto, EMA_C2, res) self.ema_f = self.EMA(self.crypto, EMA_F, res) self.ema_s = self.EMA(self.crypto, EMA_S, res) self.SetWarmUp(5*EMA_S, res) self.sell_Ticket = False self.buy_Ticket = False self.position_close_long = False self.position_close_short = False def OnData(self, data): if self.IsWarmingUp: return if not self.ema_s.IsReady: return ema_c1 = self.ema_c1.Current.Value ema_c2 = self.ema_c2.Current.Value ema_f = self.ema_f.Current.Value ema_s = self.ema_s.Current.Value self.Plot(self.crypto, "Price", self.Securities[self.crypto].Price) self.Plot(self.crypto, "ema_c1", ema_c1) self.Plot(self.crypto, "ema_c2", ema_c2) self.Plot(self.crypto, "ema_f", ema_f) self.Plot(self.crypto, "ema_s", ema_s ) # open initial long when ema ribbon crosses to the upside if not self.Portfolio[self.crypto].IsLong: if not self.sell_Ticket: if not self.position_close_long: if self.ema_c1 > self.ema_c2 > self.ema_f > self.ema_s: self.SetHoldings(self.crypto, 0.95) self.sell_Ticket = True # close long when the two fastest emas cross, create a boolan to keep track if self.Portfolio[self.crypto].IsLong: if self.sell_Ticket: if ema_c1 < ema_c2: self.Liquidate(self.crypto) self.position_close_long = True # reopen position if it was closed and it was a fake out if not self.Portfolio[self.crypto].IsLong: if self.sell_Ticket and self.position_close_long: if ema_f < ema_c2 < ema_c1: self.SetHoldings(self.crypto, 0.95) self.position_close_long = False # reset all boolans when ribbon flips if not self.Portfolio[self.crypto].IsLong: if self.position_close_long: if ema_f < ema_s: self.position_close_long = False self.sell_ticket = False ## open initial short when ema ribbon crosses to the upside if not self.Portfolio[self.crypto].IsShort: if not self.buy_Ticket: if not self.position_close_short: if ema_c1 < ema_c2 < ema_f < ema_s: self.SetHoldings(self.crypto, -0.95) self.buy_Ticket = True ## close short when the two fastest emas cross, create a boolan to keep track if self.Portfolio[self.crypto].IsShort: if self.buy_Ticket: if ema_c2 > ema_c1: self.Liquidate(self.crypto) self.position_close_short = True ## reopen short position if it was closed and it was a fake out if not self.Portfolio[self.crypto].IsShort: if self.buy_Ticket and self.position_close_short: if self.ema_f > self.ema_c2 > self.ema_c1 : self.SetHoldings(self.crypto, -0.95) self.position_close_short = False ## reset all boolans when ribbon flips if not self.Portfolio[self.crypto].IsShort: if self.buy_Ticket and self.position_close_short: if ema_s < ema_f: self.position_close_short = False self.buy_ticket = False