Overall Statistics
Total Trades
6
Average Win
94.07%
Average Loss
0%
Compounding Annual Return
264.637%
Drawdown
25.200%
Expectancy
0
Net Profit
306.747%
Sharpe Ratio
3.475
Probabilistic Sharpe Ratio
90.107%
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
1.384
Beta
0.031
Annual Standard Deviation
0.514
Annual Variance
0.264
Information Ratio
-4.334
Tracking Error
2.599
Treynor Ratio
57.953
Total Fees
$1007.06
Estimated Strategy Capacity
$11000000.00
Lowest Capacity Asset
BTCUSD XJ
class SimpleTurtleTrading(QCAlgorithm):

    def Initialize(self):
        # indicate whether or not logging is allowed
        self.LOGGING = True
        
        # set our start and end dates
        self.SetStartDate(2020, 11, 1)
        self.SetEndDate(2021, 12, 1)
        
        # set our amount of initial cash
        self.SetCash(10_000)

        # set the crypto brokerage mode
        self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)
        
        # initialize our assets and set our benchmark so we can compare our
        # results to it
        self.coin = self.AddCrypto("BTCUSD", Resolution.Daily, Market.GDAX)
        self.SetBenchmark(self.coin.Symbol)
        
        # initialize our rolling window size
        self.WINDOW_SIZE = 55
        
        # create our Donchian channel indicator and our simple moving average
        # indicator
        self.donchian = self.DCH(self.coin.Symbol, self.WINDOW_SIZE,
            self.WINDOW_SIZE, Resolution.Daily)
        self.sma = self.SMA(self.coin.Symbol, self.WINDOW_SIZE,
            Resolution.Daily)

        # create a plot for the price, max, average, and buy/sell events
        self.plot_title = "Turtle Trading"
        plot = Chart(self.plot_title)
        plot.AddSeries(Series("Price", SeriesType.Line, 0))
        plot.AddSeries(Series(f"{self.WINDOW_SIZE} Day Max",
            SeriesType.Line, 0))
        plot.AddSeries(Series(f"{self.WINDOW_SIZE} Day Avg",
            SeriesType.Line, 0))
        plot.AddSeries(Series("Buy", SeriesType.Scatter, 1))
        plot.AddSeries(Series("Sell", SeriesType.Scatter, 1))
        self.AddChart(plot)

        # set our warmup time
        self.SetWarmUp(self.WINDOW_SIZE, Resolution.Daily)

    def OnData(self, data):
        # if neither of our indicators are ready, return
        if not all([self.donchian.IsReady, self.sma.IsReady]):
            self._log("WARMING UP - {}".format(self.Time))
            return
        
        # grab the current price of our asset, then grab the upper band
        # value from our donchian indicator and the average price from
        # our SMA indicator
        price = data[self.coin.Symbol].Close
        window_max = self.donchian.UpperBand.Current.Value
        window_avg = self.sma.Current.Value
        
        # set our buying conditions
        buy = all([
            not self.Portfolio.Invested,
            price > window_max
        ])
        
        # set our sell conditions
        sell = all([
            self.Portfolio.Invested,
            price < window_avg
        ])
        
        # check to see if we are buying
        if buy:
            # purchase our assets
            self._log("PURCHASE - price: {}, max: {}".format(price, window_max))
            self.SetHoldings(self.coin.Symbol, 1.0)
            self.Plot(self.plot_title, "Buy", price)
        
        # check to seel if we are selling
        elif sell:
            # sell our assets
            self._log("SELL - price: {}, avg: {}".format( price, window_avg))
            self.Liquidate()
            self.Plot(self.plot_title, "Sell", price)
        
        # otherwise, no action is to be taken (but log it anyway so we can
        # track our algorithm's progress)
        else:
            self._log("NO ACTION - price: {}, max: {}, avg: {}".format(
                price, window_max, window_avg))

        # plot the price, max, and average
        self.Plot(self.plot_title, "Price", price)
        self.Plot(self.plot_title, f"{self.WINDOW_SIZE} Day Max",
            window_max)
        self.Plot(self.plot_title, f"{self.WINDOW_SIZE} Day Avg",
            window_avg)
    
    def _log(self, s):
        # check to see if logging is enabled, and if so, log the string
        if self.LOGGING:
            self.Log(s)