Overall Statistics
Total Trades
68
Average Win
21.18%
Average Loss
-3.93%
Compounding Annual Return
373.169%
Drawdown
26.300%
Expectancy
2.949
Net Profit
2175.334%
Sharpe Ratio
4.183
Probabilistic Sharpe Ratio
97.439%
Loss Rate
38%
Win Rate
62%
Profit-Loss Ratio
5.39
Alpha
1.053
Beta
0.415
Annual Standard Deviation
0.592
Annual Variance
0.35
Information Ratio
-1.403
Tracking Error
0.68
Treynor Ratio
5.969
Total Fees
$45230.45
Estimated Strategy Capacity
$44000000.00
Lowest Capacity Asset
ETHUSDT 18N
from datetime import timedelta
from AlgorithmImports import *
from SmartRollingWindow import *

class FocusedYellowGreenJellyfish(QCAlgorithm):

    def Initialize(self):
        self.InitAlgoParams()
        self.InitBacktestParams()
        self.InitAssets()
        self.InitIndicators()

    def InitAlgoParams(self):
        self.ticker       = "ETHUSDT"
        self.resolution = Resolution.Daily
        self.slowPeriod = int(self.GetParameter('slowPeriod'))
        self.fastPeriod = int(self.GetParameter('fastPeriod'))
        
    def InitBacktestParams(self):
        self.SetAccountCurrency("USDT")
        self.SetCash(100000)  
        self.SetStartDate(2020, 1, 1)
        
    def InitAssets(self):
        self.SetBrokerageModel(BrokerageName.Binance, AccountType.Cash);
        self.crypto = self.AddCrypto(self.ticker, self.resolution).Symbol
        self.SetBenchmark(self.ticker) 
        
    def InitIndicators(self):
        self.SetWarmUp(self.slowPeriod, self.resolution)
        self.fast = self.EMA(self.crypto, self.fastPeriod, self.resolution)
        self.slow = self.EMA(self.crypto, self.slowPeriod, self.resolution)
        self.slowWindow = SmartRollingWindow('float', 2)
        self.fastWindow = SmartRollingWindow('float', 2)
        self.priceWindow = SmartRollingWindow('float', 2)
        self.Consolidate(self.crypto, self.resolution, self.OnConsolidatedBarClose)
        
    def UpdateRollingWindows(self):
        self.slowWindow.Add(self.slow.Current.Value)
        self.fastWindow.Add(self.fast.Current.Value)
        self.priceWindow.Add(self.Securities[self.crypto].Price)
        
    def ShouldExit(self):
        return self.priceWindow.isBelow(self.slowWindow) or self.slowWindow.isAbove(self.fastWindow)
    def ShouldEnter(self):
        return self.fastWindow.isAbove(self.slowWindow) and self.priceWindow.isAbove(self.fastWindow)
    
    def OnEndOfDay(self):
        self.PlotCharts()
        self.UpdateRollingWindows()

    def OnConsolidatedBarClose(self, bar):
        if not self.slowWindow.IsReady():
            return
        if self.Portfolio[self.crypto].Invested and self.ShouldExit():
            self.Liquidate(tag="Slow crossed fast")
        elif not self.Portfolio[self.crypto].Invested and self.ShouldEnter():
            self.SetHoldings(self.crypto,  1);

    def PlotCharts(self):    
        self.Plot("charts", "Price", self.Securities[self.crypto].Price)        
        self.Plot("charts", "slow", self.slow.Current.Value)
        self.Plot("charts", "fast", self.fast.Current.Value)