Overall Statistics |
Total Trades 1128 Average Win 1.11% Average Loss -0.62% Compounding Annual Return 173.305% Drawdown 17.400% Expectancy 0.321 Net Profit 196.849% Sharpe Ratio 3.976 Probabilistic Sharpe Ratio 95.385% Loss Rate 53% Win Rate 47% Profit-Loss Ratio 1.79 Alpha 1.195 Beta 1.318 Annual Standard Deviation 0.365 Annual Variance 0.133 Information Ratio 3.893 Tracking Error 0.323 Treynor Ratio 1.102 Total Fees $0.00 Estimated Strategy Capacity $52000.00 Lowest Capacity Asset KVSB XMWYVA1XG4MD |
import pandas as pd from io import StringIO class CathieWoods1YearBacktest1Kcapital(QCAlgorithm): def Initialize(self): #BackTest start date one year self.SetStartDate(2020, 9, 1) # Target market self.SetCash(100000) #Universe selection self.AddUniverse(self.Coarse) #using Hourly resolution for more data points. self.UniverseSettings.Resolution = Resolution.Hour self.run = False self.tickers = [] self.tickers_value = [] self.tickers_list = [] self.date_list = [] self.direction_list = [] self.buying_stocks = [] self.invested_stocks = [] self.is_downloaded = False #Run everyday at midnight to scrape the daily updates self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(0, 0), self.DownloadTickers) # Set Fee Model to No trading fees to mimic new fee model self.SetSecurityInitializer(lambda x: x.SetFeeModel(ConstantFeeModel(0))) def DownloadTickers(self): #Reset self.run = False self.buying_stocks = [] self.invested_stocks = [] #Check if downloaded if self.is_downloaded == False: csv = self.Download("https://www.dropbox.com/s/sqjb76w2faer76l/Trade_Log.csv?dl=1") df = pd.read_csv(StringIO(csv)) self.tickers_list = df["Ticker"].to_list() self.date_list = df["Date"].to_list() self.direction_list = df["Direction"].to_list() self.is_downloaded = True #once downloaded mark as downloaded def Coarse(self, coarse): filtered = [x for x in coarse if x.Symbol.Value in self.tickers_list and x.HasFundamentalData] return [x.Symbol for x in filtered] # Filter for stocks in the universe def OnSecuritiesChanged(self, changes): for stock in changes.RemovedSecurities: pass history = self.History([stock.Symbol for stock in changes.AddedSecurities], 50, Resolution.Hour) for stock in changes.AddedSecurities: symbol = stock.Symbol if symbol in history.index: self.tickers.append(symbol) self.tickers_value.append(symbol.Value) # make list of symbols and value def OnData(self, data): #Reset invested stocks list self.invested_stocks = [] #Check order fills for kvp in self.Portfolio: security_holding = kvp.Value if security_holding.Invested: symbol = security_holding.Symbol self.invested_stocks.append(symbol.Value) average_price = security_holding.AveragePrice current_price = self.Securities[symbol].Price change = current_price / average_price #Check if invested stock's current price greater than or less than average price by 10% 0r 5%, if so, sell if change > 1.1 or change < 0.95: self.Liquidate(symbol) #Check if logic ran today if self.run == False: today_date = (str(self.Time.month) + "/" + str(self.Time.day) + "/" + str(self.Time.year)) for i in range(len(self.date_list)): if self.date_list[i] == today_date: ticker = self.tickers_list[i] direction = self.direction_list[i] if ticker in self.tickers_value: index = self.tickers_value.index(ticker) if direction == "Buy" and ticker not in self.buying_stocks and ticker not in self.invested_stocks: # if self.Portfolio.Cash > 1000: self.SetHoldings(str(self.tickers[index]), 0.1) self.buying_stocks.append(ticker) # Code is front heavy, not true reflection of strategy # set entry_price. Not yet code. If need to code, for change of strategy will change data.Pls ignore. #Only run logic once per day self.run = True