Overall Statistics
Total Trades
425
Average Win
0.70%
Average Loss
-0.57%
Compounding Annual Return
3.924%
Drawdown
20.800%
Expectancy
0.177
Net Profit
21.248%
Sharpe Ratio
0.31
Probabilistic Sharpe Ratio
3.947%
Loss Rate
47%
Win Rate
53%
Profit-Loss Ratio
1.22
Alpha
0.046
Beta
-0.034
Annual Standard Deviation
0.133
Annual Variance
0.018
Information Ratio
-0.442
Tracking Error
0.222
Treynor Ratio
-1.204
Total Fees
$936.90
Estimated Strategy Capacity
$25000000.00
Lowest Capacity Asset
TLRY WWAWWB4P01GL
import pandas as pd
import numpy as np
from io import StringIO

class RedditStockSentiment(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2016,1, 1)  # Set Start Date
        self.SetEndDate(2020, 12, 31) #Set End Date
        self.SetCash(100000)  # Set Strategy Cash
        self.tickers = ["TSLA", "AAPL", "SPCE", "CLOV","LULU","PLTR","TLRY","FB","MARA", "AMD"] 
        self.investP = 1/len(self.tickers) #Equal weight portfolio

        for stock in self.tickers:
            self.AddEquity(stock, Resolution.Daily) 
        
        # self.AddRiskManagement(TrailingStopRiskManagementModel(0.08)) #Risk management
        
        self.trade = True #OnData will run when the program when the program is first executed
        
        csv = self.Download("https://www.dropbox.com/s/vovg893xfc0berw/Reddit_Sentiment_Equity.csv?dl=1") #Downloads data
        self.df = pd.read_csv(StringIO(csv)) #Read into a dataframe
        
        self.Schedule.On(self.DateRules.EveryDay(), 
                 self.TimeRules.At(8, 30),        
                 self.runDaily) 
        
    def OnData(self, data):
        
        if self.trade != True: 
            return
        
        #Assigns three variables with the current time(year, month, day)
        algYear = self.Time.year
        algMonth = self.Time.month
        algDay = self.Time.day 
        algHour = self.Time.hour
        
        #Iterates through the dataframe tuples
        for row in self.df.itertuples():
            try: #If there is an error with dates a tuple(row) then continue to the next row
                date = row[-1] #Date is the index of the tuple(final colum in the dataframe)
                
                #Date is parsed as a string and assigned to three variables
                year = date[0:4]
                month = date[5:7]
                day = date[8:10]
                hour = date[11:13]
            except:
                continue
            
            #Compares current date with the date from the tuple
            if ((int(year) != algYear) or (int(month) != algMonth) or (int(day) != algDay)):
                continue
            
            '''
            averageSentiment is calculated by averaging the sentiment of the submission title, body text, and all comments.
            This process can be very time consuming. 
            '''
            
            #Assigns several variables with data from the tuple
            stock = str(row[1])
            averageSentiment = float(row[4]) 
            numberOfComments = int(row[3])
            score = int(row[7])

            adjust = 1
            
            #If score is low, allocate a smaller percentage to the position taken for the underlying equity
            if score <= 20: 
                adjust = 0.5
        
            if(averageSentiment >= 0.1) and not self.Portfolio[stock].IsLong:
                self.SetHoldings(stock, self.investP*adjust, True)
            if(averageSentiment <= -0.1) and not self.Portfolio[stock].IsShort:
                self.SetHoldings(stock, - (self.investP*0.5)*adjust, True) 
            if (-0.1 < averageSentiment < 0.1):
                self.Liquidate(stock)
                
            self.trade = False
                
    def runDaily(self):
        self.trade = True