Overall Statistics
Total Trades
13
Average Win
7.65%
Average Loss
-5.16%
Compounding Annual Return
4.297%
Drawdown
21.100%
Expectancy
-0.173
Net Profit
23.883%
Sharpe Ratio
0.409
Probabilistic Sharpe Ratio
6.933%
Loss Rate
67%
Win Rate
33%
Profit-Loss Ratio
1.48
Alpha
0.041
Beta
-0.012
Annual Standard Deviation
0.099
Annual Variance
0.01
Information Ratio
0.078
Tracking Error
0.236
Treynor Ratio
-3.255
Total Fees
$13.00
from System.Drawing import Color

class SMA_trading(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2005, 1, 1)                       # the starting date for our backtest
        self.SetEndDate(2010, 2, 1)                        # the ending date for our backtest (if no date, then it will test up until today)
        self.start_value = 5000                             # define the amount of starting cash
        self.SetCash(self.start_value)                      # initialize our wallet
        self.EQY = "SPY"                                    # define the stock ticker
        self.AddEquity(self.EQY, Resolution.Daily)          # add a stock to the list of those we want to trade, and how often to pull data
        self.starting_price = None
        self.spy_portfolio = None
        self.period = 20
        
        # create a consolidator for weekly data
        self.Consolidate(self.EQY, Calendar.Weekly, self.OnWeeklyBar)
    
        # set up an SMA20 indicator
        #var sma = SMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
        self.sma = SimpleMovingAverage(self.period)
        

        # need to give the indicators data before running the algorithm
        self.SetWarmUp(timedelta(self.period * 7))
    
        # set up a chart to display our buy and sell dates
        self.stockPlot = Chart('Equity')
        self.SPY_candles  = Series(self.EQY, SeriesType.Candle)
        self.stockPlot.AddSeries(self.SPY_candles)
        self.stockPlot.AddSeries(Series('Buy', SeriesType.Scatter, '$', Color.Green, ScatterMarkerSymbol.Triangle))
        self.stockPlot.AddSeries(Series('Sell', SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.TriangleDown))
        self.AddChart(self.stockPlot)
   
   
        
    # this is for plotting the relative change of each stock and our portfolio value   
    def OnEndOfDay(self):
        current_portfolio = self.Portfolio.TotalPortfolioValue
        change_portfolio = (current_portfolio - self.start_value )/ self.start_value
        self.Plot("Percent Change","Portfolio Change", change_portfolio)
        
        # # if we haven't gotten the starting price, then get it
        if self.starting_price == None:
            self.starting_price = self.Securities[self.EQY].Price
        
        start_price = self.starting_price
        price = self.Securities[self.EQY].Price
        change_in_price = (price - start_price)/ start_price
        self.Plot("Percent Change", self.EQY + " Change", change_in_price)
        
        # price = self.Securities[self.EQY].Price
        # change_in_price = (price - start_price)/ start_price
        # self.Plot("Strategy Equity", self.EQY + " Change", change_in_price * self.start_value)
        
        
        
    def OnWeeklyBar(self, weeklyBar):
        
        # self.Log(weeklyBar)
        
        self.currentBar = weeklyBar
        
        self.sma.Update(weeklyBar.Time, weeklyBar.Close)
        
        # # if the indicators aren't ready, don't do anything
        if (not self.sma.IsReady): return
        
        low_price  = self.currentBar.Low
        high_price = self.currentBar.High
        
        # # extract the current value of each indicator
        sma = self.sma.Current.Value
        
        # # determine where the price is relative to the sma20
        upSMA = low_price > sma
        downSMA = high_price < sma
        
        
        if (upSMA):
            if not self.Portfolio[self.EQY].Invested:
                self.SetHoldings(self.EQY, 1)       # if the price is above the 20-day moving average, buy the stock
                self.Plot("Equity", 'Buy', self.Securities[self.EQY].Price)
        elif (downSMA):
            if self.Portfolio[self.EQY].Invested:
                self.SetHoldings(self.EQY, 0)        # otherwise exit the position
                self.Plot("Equity", 'Sell', self.Securities[self.EQY].Price)
        
        
        # plotting stuff
        self.SPY_candles.AddPoint(self.Time + timedelta(minutes=1), weeklyBar.Open)
        self.SPY_candles.AddPoint(self.Time + timedelta(minutes=2), weeklyBar.High)
        self.SPY_candles.AddPoint(self.Time + timedelta(minutes=3), weeklyBar.Low)
        self.SPY_candles.AddPoint(self.Time + timedelta(minutes=4), weeklyBar.Close)
        
        #self.Plot("Equity",self.EQY + " HIGH", weeklyBar.High)
        #self.Plot("Equity",self.EQY + " LOW", weeklyBar.Low)
        #self.Plot("Equity",self.EQY, weeklyBar.High)
        #self.Plot("Equity",self.EQY, weeklyBar.Low)
        #self.Plot("Equity",self.EQY, weeklyBar.Close)
        #self.Plot("Equity",self.EQY+' Price',self.Securities[self.EQY].Close)
        self.Plot("Equity","SMA", sma)
        
        
    def OnOrderEvent(self, orderEvent):
        
        if orderEvent.Status != OrderStatus.Filled:
            return
        
        self.Log(f"Order Executed! Open Time: {self.currentBar.Time}, Close Time: {self.currentBar.EndTime} -- Bar: {self.currentBar}, SMA: {self.sma.Current.Value}")