Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0.217
Tracking Error
0.086
Treynor Ratio
0
Total Fees
$0.00
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Data import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from System.Collections.Generic import List


class main(QCAlgorithm):

    def Initialize(self):
        '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''

        self.SetStartDate(2020, 12, 20)
        #self.SetEndDate(2015,1,1)    #Set End Date
        
        self.initialcash=10000000 #Set Strategy Cash
        self.totalPortfolioProfitTarget=self.initialcash/2   #means a take profit after 50% rise in portfolio value
        self.SetCash(self.initialcash)         
        self.PercentageOfPortfolioToAllocateToEachSecurity= 0.02 # 1 means 100%
        self.numOfCoarseSymbols = 10 #max number of symbols that are returned by our universe selection function
        
        self.SetBrokerageModel(BrokerageName.Alpaca)
        self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
        
        self.UniverseSettings.Resolution = Resolution.Hour # Timeframe to trade
        self.UniverseSettings.Leverage = 1
        
        self.benchmark="SPY"
        self.benchmark= self.AddEquity(self.benchmark, self.UniverseSettings.Resolution)
        self.SPY_EMA = self.EMA("SPY", 20, Resolution.Daily)

        self.SymbolDataDictionary = {}
        self.AddUniverse(self.CoarseSelectionFunction)

        # schedule an event to fire on a single day of the week
        #self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(15, 50), self.buy_time)
        
        #schedule an event to Liquidate (exit all positions at the day and hours specified)
        #self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(9, 10), self.sell_time)
        
    def buy_time(self):
        for kvp in self.SymbolDataDictionary:
            symbol=self.SymbolDataDictionary[kvp]
            if self.benchmark.Price > self.SPY_EMA.Current.Value :
                self.SetHoldings(kvp, self.PercentageOfPortfolioToAllocateToEachSecurity) #here the actual positions are initiated, in this case the symbols are 10, so every symbol receives 10% of the Portfolio. In this case being the cash 100000$ every stock gets an allocation of 10000$.
                #The three lines below are used to Debug
                #self.Log(" Symbol "+ str(symbol.symbol))
                #self.Log(" % Performance of the symbol "+ str(symbol.get_percentage_change()))
                #self.Log(" Volume of the symbol "+ str(symbol.get_relative_volume()))
            
    def sell_time(self):
        self.Liquidate()
        
    
    def CoarseSelectionFunction(self, coarse):
        
        CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData and x.Price > 1 and x.Price<50]
        sortedByVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=True)
        # We are going to use a dictionary to refer the object that will keep the moving averages
        for kvp in sortedByVolume:
            if kvp.Symbol not in self.SymbolDataDictionary:
                self.SymbolDataDictionary[kvp.Symbol]=SymbolData(kvp.Symbol)
        
        for cf in coarse:
            if cf.Symbol in self.SymbolDataDictionary:
                self.SymbolDataDictionary[cf.Symbol].update(cf.EndTime, cf.AdjustedPrice, kvp.DollarVolume)
           
        
        #values = list(filter(lambda x: x.EMAS_ARE_OK and x.RSI_IS_OK and x.percentage_change and x.relative_volume, self.SymbolDataDictionary.values()))
        #values = list(filter(lambda x: x.percentage_change,self.SymbolDataDictionary.values()))
        values = list(self.SymbolDataDictionary.values())
        values = sorted(values, key=lambda x: x.percentage_change and x.percentage_change>0.2, reverse=True)
        
        
        #used to output instruments in the universe
        for x in values:
            self.Debug(str(self.Time)+' symbol: ' + str(x.symbol.Value)+" "+str(x.percentage_change))
         
        
        # we need to return only the symbol objects
        return [ x.symbol for x in values ]   # return [ x.symbol for x in values[:self.numOfCoarseSymbols] ]
        
    
    def OnData(self, data):
        if self.Portfolio.Invested:
            if self.Portfolio.TotalProfit > self.totalPortfolioProfitTarget:    
                self.Liquidate()
        
    
        
class SymbolData(object):
    def __init__(self, symbol):
        self.symbol = symbol
        self.EMA1 = ExponentialMovingAverage (5)
        self.EMA2 = ExponentialMovingAverage (20)
        self.RSI = RelativeStrengthIndex(70)
        self.PriceHistory = RollingWindow[float](2)
        self.DollarVolumeHistory = RollingWindow[float](30)
        #self.EMAS_ARE_OK = False
        #self.RSI_IS_OK = False
        self.percentage_change=0
        #self.relative_volume=False


    def update(self, time, value, volume):
        if self.EMA1.Update(time, value) and self.EMA2.Update(time, value):
            EMA1 = self.EMA1.Current.Value
            EMA2 = self.EMA2.Current.Value
            self.EMAS_ARE_OK = value > EMA1 and value > EMA2
        
        if self.RSI.Update(time, value):
            RSI = self.RSI.Current.Value
            self.RSI_IS_OK = value > RSI
            
            
        self.PriceHistory.Add(value)
        self.DollarVolumeHistory.Add(volume)
        
       
        if self.PriceHistory.Count>1:
            self.percentage_change = (self.PriceHistory[0]-self.PriceHistory[1])/self.PriceHistory[1]

            
        if self.DollarVolumeHistory.Count>29:
            todays_volume=self.DollarVolumeHistory[0]
            thirtydaysvolume=0
            for i in range(0,self.DollarVolumeHistory.Count-1):
                thirtydaysvolume=self.DollarVolumeHistory[i]+thirtydaysvolume
            averagethirtydaysvolume=thirtydaysvolume/30   #let's divide by 30

            relative_volume=(todays_volume-averagethirtydaysvolume)/averagethirtydaysvolume
            if relative_volume > 2: #in this case I followed your Excel Spreadsheet example, >2
                self.relative_volume=True