Overall Statistics
Total Trades
246
Average Win
1.12%
Average Loss
-1.24%
Compounding Annual Return
3.293%
Drawdown
19.200%
Expectancy
0.037
Net Profit
3.311%
Sharpe Ratio
0.265
Probabilistic Sharpe Ratio
22.861%
Loss Rate
46%
Win Rate
54%
Profit-Loss Ratio
0.90
Alpha
0.083
Beta
-0.355
Annual Standard Deviation
0.212
Annual Variance
0.045
Information Ratio
-0.065
Tracking Error
0.279
Treynor Ratio
-0.159
Total Fees
$3844.50
Estimated Strategy Capacity
$1200000.00
from datetime import timedelta, datetime
class FocusedYellowLemur(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2015, 12, 1)  # Set Start Date
        self.SetEndDate(2016, 12, 1)
        self.SetCash(100000)  # Set Strategy Cash
       
        self.Data = {}

        for ticker in ["TSLA","AAPL"]:
            symbol = self.AddEquity(ticker, Resolution.Hour, Market.USA).Symbol
            self.Data[symbol] = SymbolData(self, symbol)
            
            
            
        self.stopLossLevel = -0.05 # stop loss percentage 
        self.stopProfitLevel = 0.01# stop profit percentage
        self.tolerance = 1.01
            
        self.SetWarmUp(100, Resolution.Hour)


    def OnData(self, data):
        
        if self.IsWarmingUp:
            return
            
        for symbol, symbolData in self.Data.items():
            if not (data.ContainsKey(symbol) and data[symbol] is not None and symbolData.IsReady):
                continue
            
            fast = symbolData.fast.Current.Value
            slow = symbolData.slow.Current.Value
            current_price = symbolData.closeWindow[0]
            #current_price = data[symbol].Close
            self.is_uptrend = fast > slow * self.tolerance
            self.is_downtrend = slow > fast * self.tolerance
            
            
            if self.Portfolio[symbol].Invested:
                
                if self.isLong:
                    condStopProfit = (current_price - self.buyInPrice)/self.buyInPrice > self.stopProfitLevel
                    condStopLoss = (current_price - self.buyInPrice)/self.buyInPrice < self.stopLossLevel
                    if condStopProfit:
                        self.Liquidate(symbol)
                        self.Log(f"{self.Time} Long Position Stop Profit at {current_price}")
                        
                    if condStopLoss:
                        self.Liquidate(symbol)
                        self.Log(f"{self.Time} Long Position Stop Loss at {current_price}")
                  
                else:
                    condStopProfit = (self.sellInPrice - current_price)/self.sellInPrice > self.stopProfitLevel
                    condStopLoss = (self.sellInPrice - current_price)/self.sellInPrice < self.stopLossLevel
                    if condStopProfit:
                        self.Liquidate(symbol)
                        self.Log(f"{self.Time} Short Position Stop Profit at {current_price}")
                        
                    if condStopLoss:
                        self.Liquidate(symbol)
                        self.Log(f"{self.Time} Short Position Stop Profit at {current_price}")
                        
    
            
            if not self.Portfolio[symbol].Invested:
                uptrend = self.is_uptrend
                downtrend = self.is_downtrend
                
                if downtrend and current_price < fast:
                    self.SetHoldings(symbol, 0)
                    # get buy-in price for trailing stop loss/profit
                    self.buyInPrice = current_price
                    # entered long position
                    self.isLong = True
                    #Timebought = self.Time
                    self.Log(f"{self.Time} Entered Long Position at {current_price}")
                        
                if uptrend and current_price > fast:
                    self.SetHoldings(symbol, -1)
                    # get sell-in price for trailing stop loss/profit
                    self.sellInPrice = current_price
                    # entered short position
                    self.isLong = False
                    #Timesold = self.Time
                    self.Log(f"{self.Time} Entered Short Position at {current_price}")
                        
                    
class SymbolData:
    def __init__(self, algorithm, symbol):
        self.fast = SimpleMovingAverage(5) #Resolution.Hour
        self.fastWindow = RollingWindow[IndicatorDataPoint](2)
        
        #Generating 5-period SMA values of 4 hours Resolution
        algorithm.RegisterIndicator(symbol, self.fast, timedelta(hours=4))
        self.fast.Updated += self.FastUpdated 
        
        self.slow = SimpleMovingAverage(10) #Resolution.Hour
        self.slowWindow = RollingWindow[IndicatorDataPoint](2)
        
        #Generating 10-period SMA values of 4 hours Resolution.
        algorithm.RegisterIndicator(symbol, self.slow, timedelta(hours=4))
        self.slow.Updated += self.SlowUpdated 

        self.closeWindow = RollingWindow[float](10)
        
        # Add consolidator to track rolling close prices
        self.consolidator = TradeBarConsolidator(timedelta(hours=4))
        self.consolidator.DataConsolidated += self.CloseUpdated
        algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator)
        

    def FastUpdated(self, sender, updated):
        '''Event holder to update the fast SMA Rolling Window values'''
        if self.fast.IsReady:
            self.fastWindow.Add(updated)

    def SlowUpdated(self, sender, updated):
        '''Event holder to update the slow SMA Rolling Window values'''
        if self.slow.IsReady:
            self.slowWindow.Add(updated)
            
            
    def CloseUpdated(self, sender, bar):
        '''Event holder to update the close Rolling Window values'''
        self.closeWindow.Add(bar.Close)
       
    @property 
    def IsReady(self):
        return self.fast.IsReady  and self.slow.IsReady and self.closeWindow.IsReady