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