| Overall Statistics |
|
Total Trades 39 Average Win 5.83% Average Loss -2.29% Compounding Annual Return 28887.268% Drawdown 13.600% Expectancy 1.050 Net Profit 56.902% Sharpe Ratio 153.121 Probabilistic Sharpe Ratio 95.125% Loss Rate 42% Win Rate 58% Profit-Loss Ratio 2.54 Alpha 138.984 Beta 2.105 Annual Standard Deviation 0.911 Annual Variance 0.83 Information Ratio 160.03 Tracking Error 0.87 Treynor Ratio 66.265 Total Fees $53.03 Estimated Strategy Capacity $170000.00 |
import math
from io import StringIO
import pandas as pd
class FocusedYellowGreenGaur(QCAlgorithm):
# Order ticket for our stop order, Datetime when stop order was last hit
universeOpenPrice = {}
universeClosePrice = {}
boughtInPrice = {}
peakPrices = {}
orderTickets = {}
stocks = []
tradingEnabled = False
allInvestments = []
df = [2]*2
startingCash = 0
numDiversify = 0
tickerNames = {}
def Initialize(self):
self.SetStartDate(2021, 1, 4)
self.SetEndDate(2021, 2, 1)
self.SetCash(1000)
#universe = self.AddUniverse(self.MyCoarseFilterFunction, self.MyFineFilterFunction)
self.SetSecurityInitializer(self.CustomSecurityInitializer)
universe = self.AddUniverse(self.MyCoarseFilterFunction)
self.UniverseSettings.Resolution = Resolution.Minute
self.SetTimeZone("America/New_York")
self.numDiversify = 1
csv = self.Download("https://www.dropbox.com/s/owfplskyiwuc70a/companyNames.csv?dl=1")
#sep='\t',
self.tickerNames = pd.read_csv(StringIO(csv), header = 0, index_col = 0, squeeze = True).to_dict()
self.Debug(self.tickerNames)
def OnData(self, data):
self.tradingManager(data)
#for x in allInvestments:
# self.Plot("Data Chart", "Asset Price", self.Securities[x].Close)
def CustomSecurityInitializer(self, security):
'''Initialize the security with raw prices'''
security.SetDataNormalizationMode(DataNormalizationMode.Adjusted)
def tradingManager(self, data):
hour = self.Time.hour
minute = self.Time.minute
self.Log("Current Hour: " + str(hour))
self.Log("Current Minute: " + str(minute))
self.tradingHours()
if (hour == 9) and (minute == 31):
self.updateStocks(data)
self.onMarketOpen()
if (hour == 13) and (minute == 53):
self.allInvestments = []
if (hour == 13) and (minute == 59):
self.beforeMarketClose()
self.startingCash = self.Portfolio.Cash
buying = self.calculateDeals(self.numDiversify)
for toBuy in buying:
self.buy(toBuy)
if self.Portfolio.Invested:
for x in self.allInvestments:
self.Debug("Trying to sell: " + x.Value)
self.sell(x)
else:
self.Debug("Successfully sold stock\n")
def getStockName(self, ticker):
if (ticker in self.tickerNames):
return self.tickerNames[ticker]
else:
return "NULL"
def updateStocks(self, data):
self.stocks = []
tempTickers = []
tempStocks = []
for universe in self.UniverseManager.Values:
#for x in data:
self.Debug("Number of Keys: " + str(len(universe.Members.Keys)))
#if (universe is self.UniverseManager.UserDefinedUniverse):
# continue
for key in universe.Members.Keys:
if key.Value == "WNW":
self.Debug(key.Value + " is in the dataset")
self.stocks.append(key)
self.stocks = sorted(self.stocks, key=lambda x: x.Value, reverse=False)
#Sort alphabetically
#self.stocks = []
#for x in symbol:
# self.Log("\nI am on the ticker: " + x.Value)
# self.stocks.append(x)
def tradingHours(self):
minute = self.Time.minute
hour = self.Time.hour
day = self.Time.day
if (hour == 9) and (minute == 31):
self.tradingEnabled = True
self.Debug("\nI am enabling trading")
if (hour == 14):
self.tradingEnabled = False
self.Debug("\nI am disabling trading")
return
def onMarketOpen(self):
self.universeOpenPrice = {}
self.universeClosePrice = {}
self.Debug("\nSize of stocks: " + str(len(self.stocks)))
self.startingCash = self.Portfolio.Cash
for owned in self.allInvestments:
if ((not owned.Value in self.boughtInPrice)):
#or (not owned in self.Portfolio)):
continue
self.orderTickets[owned] = self.StopMarketOrder(owned, ( -1) * self.Portfolio[owned].Quantity, self.boughtInPrice[owned.Value] * 0.95)
#if ((self.Portfolio[owned].Price) > (self.boughtInPrice[owned.Value] * 1.02)):
# self.Debug("Attemping to liquidate")
# self.Liquidate(owned)
#else:
# self.Debug("Attemping to put limit sell")
# self.orderTickets[owned] = self.LimitOrder(owned, (-1) * self.Portfolio[owned].Quantity, self.boughtInPrice[owned.Value] * 1.02)
self.UniverseSettings.Resolution = Resolution.Daily
for x in self.stocks:
#self.Log("\nI am on the ticker: " + x.Value)
#self.Log("\nOpen Price: " + str(self.Securities[x].Price))
self.df = self.History(self.Symbol(x), 1)
#for row in self.df:
# self.Debug(str(row))
if (len(self.df) > 0):
openPrices = self.df["open"]
openPrices.unstack('symbol')
if (len(openPrices) > 0):
for prices in openPrices:
self.universeOpenPrice[x] = prices
else:
self.stocks.remove(x)
self.UniverseSettings.Resolution = Resolution.Minute
return
def beforeMarketClose(self):
self.universeClosePrice = {}
for x in self.stocks:
self.Log("\nClose Price: " + str(self.Securities[x].Price))
self.universeClosePrice[x] = self.Securities[x].Price
for x in self.stocks:
if (x.Value == "CD"):
self.Debug("CD Vol: " + str(self.getVolatilityScore(x)))
if (x.Value == "METX"):
self.Debug("METX Vol: " + str(self.getVolatilityScore(x)))
return
def getVolume(self, stock):
self.df = self.History(self.Symbol(stock), 1, Resolution.Daily)
key = 'volume'
if (not key in self.df):
return 0
allVolume = self.df['volume']
volume = []
allVolume.unstack('symbol')
for vol in allVolume:
volume.append(vol)
return volume[0]
def MyCoarseFilterFunction(self, coarse):
sortedByName = sorted(coarse, key=lambda x: x.Symbol.Value, reverse=False)
filtered = []
for x in sortedByName:
#self.Debug("I am on the ticker: " + x.Symbol.Value)
name = self.getStockName(x.Symbol.Value)
if (name == "NULL"):
continue
#self.Debug(name)
if((("pharma" in str(name)))
or (("Pharma" in str(name)))
or (("Medical" in str(name)))
or (("medical" in str(name)))
or (("peutics" in str(name)))
or (("Bio" in str(name)))
or (("bio" in str(name)))):
continue
if (x.Symbol.Value == "SEAC"):
self.Debug("SEAC is present before filter")
self.Debug("SEAC Volume: " + str(x.Volume))
self.Debug("SEAC Price: " + str(x.Price))
if(x.Volume > 1000000):
if(x.Symbol.Value == "SEAC"):
self.Debug("Passed Volume test")
if x.Price > 1:
# if(x.Symbol.Value == "JMIA"):
# self.Debug("Passed the price test. Adding to universe")
filtered.append(x.Symbol)
#self.Debug("VoLScore: " + str(self.getVolatilityScore(x.Symbol)))
#self.Debug("isBelow7DayEMA: " + str(self.isBelow7DayEMA(x.Symbol)))
#self.Debug("is trending down: " + str(self.trendingDown(x.Symbol)))
'''
filtered = [ x.Symbol for x in sortedByName
if x.Volume > 500000 and
x.Price > 10
]
'''
return filtered
def MyFineFilterFunction(self, fine):
filtered = []
self.Debug("I printed this before I shat myself")
for x in fine:
if x.Symbol.Value == "JMIA":
self.Debug("JMIA present in fine")
if((not ("pharma" in x.CompanyReference.LegalName))
and (not ("Pharma" in x.CompanyReference.LegalName))
and (not ("Medical" in x.CompanyReference.LegalName))
and (not ("medical" in x.CompanyReference.LegalName))
and (not ("peutics" in x.CompanyReference.LegalName))
and (not ("Bio" in x.CompanyReference.LegalName))
and (not ("bio" in x.CompanyReference.LegalName))):
filtered.append(x.Symbol)
return filtered
def passTests(self, stock):
return True
def OnOrderEvent(self, orderEvent):
if orderEvent.Status != OrderStatus.Filled:
return
def getHistory(self, ticker):
self.Debug("On ticker: " + ticker)
return
def getAllHistory(self):
for ticker in self.Securities.keys:
self.getHistory(ticker)
return
def getPremarketScore(self, stock):
self.df = self.History(self.Symbol(stock), 6, Resolution.Daily)
openPrices = self.df["open"]
closePrices = self.df["close"]
open = []
close = []
openPrices.unstack('symbol')
closePrices.unstack('symbol')
for prices in openPrices:
open.append(prices)
for prices in closePrices:
close.append(prices)
percentChange = 0
tempOpen = 0
tempClose = 0
percentChange = 0;
numPositives = 0
if (len(open) < 6) or (len(close) < 6):
return 0
for x in range(5):
tempOpen = open[x + 1]
tempClose = close[x]
percentChange = abs(((tempOpen - tempClose) / tempClose) * 100)
if (percentChange > 0):
numPositives = numPositives + 1
return numPositives
def getAvgPremarketIncrease(self, stock):
self.df = self.History(self.Symbol(stock), 6, Resolution.Daily)
openPrices = self.df["open"]
closePrices = self.df["close"]
open = []
close = []
openPrices.unstack('symbol')
closePrices.unstack('symbol')
posSum = 0
for prices in openPrices:
open.append(prices)
for prices in closePrices:
close.append(prices)
percentChange = 0
tempOpen = 0
tempClose = 0
percentChange = 0;
numPositives = 0
if (len(open) < 6) or (len(close) < 6):
return 0
for x in range(5):
tempOpen = open[x + 1]
tempClose = close[x]
percentChange = abs(((tempOpen - tempClose) / tempClose) * 100)
if (percentChange > 0):
numPositives = numPositives + 1
posSum = posSum + percentChange
return posSum / numPositives
def getVolatilityScore(self, stock):
self.df = self.History(self.Symbol(stock), 7, Resolution.Daily)
openPrices = self.df["open"]
closePrices = self.df["close"]
open = []
close = []
openPrices.unstack('symbol')
closePrices.unstack('symbol')
for prices in openPrices:
open.append(prices)
for prices in closePrices:
close.append(prices)
percentChange = 0
tempOpen = 0
tempClose = 0
percentSum = 0;
if (len(open) < 7) or (len(close) < 7):
return 0
for x in range(7):
tempOpen = open[x]
tempClose = close[x]
percentChange = abs(((tempOpen - tempClose) / tempClose) * 100)
percentSum = percentSum + percentChange
return percentSum
#for col in self.df.iterrows():
# + str(row)
#self.Debug(str(self.df[col]['close']) + "\n")
def trendingDown(self, stock):
self.df = self.History(self.Symbol(stock), 6, Resolution.Daily)
closePrices = self.df["close"]
close = []
closePrices.unstack('symbol')
for prices in closePrices:
close.append(prices)
if (len(close) < 6):
if(stock.Value == "SEAC"):
self.Debug("WTF SEAC DOESNT HAVE ENOUGH PRICES?")
return False
sum = 0
for i in range(6):
#if(stock.Value == "AHT"):
#self.Debug("Current Close Price: " + str(close[i]))
if (((i + 1) % 2) == 0):
sum = sum + close[5 - i]
else:
sum = sum - close[5 - i]
#self.Debug("Trending Down Sum: " + str(sum))
return (sum > 0)
def get7DayMovingAverage(self, stock):
self.df = self.History(self.Symbol(stock), 7, Resolution.Daily)
closePrices = self.df["close"]
close = []
closePrices.unstack('symbol')
for prices in closePrices:
close.append(prices)
sum = 0
if (len(close) < 7):
return 0
for i in range(7):
sum = sum + close[i]
return (sum / 7)
def EMAHelper(self, stock, close, numDays, daysLeft):
sevenAvg = self.get7DayMovingAverage(stock)
if (sevenAvg == 0):
return 0
if daysLeft == 0:
value = (((close[numDays - 1]) - sevenAvg) * (2/(numDays + 1))) + sevenAvg
else:
prevEMA = self.EMAHelper(stock, close, numDays, (daysLeft - 1))
value = ((close[numDays - daysLeft - 1] - prevEMA)) * (2/(numDays + 1)) + prevEMA
return value
'''
double value;
if (daysRemaining == 0)
{
double sevenAvg = get7DayMovingAverage(stock);
value = ((stock.getClosePrice() - sevenAvg) * (2/(numDays + 1))) + sevenAvg;
}
else
{
value = ((stock.getClosePrice() - EMAHelper(getPreviousDayStock(stock), daysRemaining - 1)) * (2/(numDays + 1))) + EMAHelper(getPreviousDayStock(stock), daysRemaining - 1);
}
return value;
'''
def get7DayEMA(self, stock):
self.df = self.History(self.Symbol(stock), 14, Resolution.Daily)
closePrices = self.df["close"]
close = []
closePrices.unstack('symbol')
for prices in closePrices:
close.append(prices)
sum = 0
if (len(close) < 14):
return 0
for i in range(7):
sum = sum + close[i]
average = sum / 7
tempEMA = average
value = ((self.universeClosePrice[stock] - tempEMA) * (2/8)) + tempEMA
if (stock.Value == "SEAC"):
self.Debug("SEAC 7 DAY EMA: " + str(average))
return average
def isBelow7DayEMA(self, stock):
sevenEMA = self.get7DayEMA(stock)
currentPrice = self.universeClosePrice[stock]
if (sevenEMA == 0):
return True
return (currentPrice < sevenEMA)
'''
double value;
if (daysRemaining == 0)
{
double sevenAvg = get7DayMovingAverage(stock);
value = ((stock.getClosePrice() - sevenAvg) * (2/(numDays + 1))) + sevenAvg;
}
else
{
value = ((stock.getClosePrice() - EMAHelper(getPreviousDayStock(stock), daysRemaining - 1)) * (2/(numDays + 1))) + EMAHelper(getPreviousDayStock(stock), daysRemaining - 1);
}
'''
'''
I have a theory that the stock which rose the most today
is related to the volatility score. My theory is the true golden volscore is impossible
to know for the day; however, is relatively close to the golden volscore of yesterday.
'''
def getGoldenVolScore(self):
#First, find the stock which has risen the most today
percentChange = 0
highestPercentChange = 0
highestGain = None
for stock in self.stocks:
if ((not (stock in self.universeOpenPrice)) or (not (stock in self.universeClosePrice))):
continue
openPrice = self.universeOpenPrice[stock]
closePrice = self.universeClosePrice[stock]
percentChange = ((openPrice - closePrice / (openPrice))) * 100
if (percentChange > 100):
continue
if percentChange > highestPercentChange:
highestPercentChange = percentChange
highestGain = stock
'''
Now that we have found the stock which has gained the most, we must find its volscore.
To do this, we must get its history 8 days in the past (we are not including the day before
in the math)
'''
self.df = self.History(self.Symbol(highestGain), 8, Resolution.Daily)
openPrices = self.df["open"]
closePrices = self.df["close"]
open = []
close = []
openPrices.unstack('symbol')
closePrices.unstack('symbol')
for prices in openPrices:
open.append(prices)
for prices in closePrices:
close.append(prices)
percentSum = 0
for i in range(7):
percentChange = abs(((open[i] - close[i]) / close[i]) * 100)
percentSum = percentSum + percentChange
#Return the golden volscore
self.Debug("Calcuated highest increase was " + str(highestPercentChange) + " from the ticker " + highestGain.Value + " and a volScore of " + str(percentSum))
return percentSum
def calculateDeals(self, numDeals):
alreadyBuying = []
for i in range(numDeals):
toAdd = self.calculateDeal(alreadyBuying)
if toAdd != None:
alreadyBuying.append(toAdd)
return alreadyBuying
def calculateDeal(self, alreadyBuying):
#self.Debug("\nI am calculating the deals!")
checking = "WNW"
boughtInstead = "METX"
highestPercentChange = 0
percentChange = 0
volScore = 0
bestVolScore = 0
posScore = 0
bestPosScore = 99
deal = None
skip = False
goldenVolScore = self.getGoldenVolScore()
for ticker in self.stocks:
#self.Debug("I am on the ticker: " + ticker.Value)
#self.Debug(ticker.Value)
#if (ticker.Value == "QS"):
# self.Debug("QS thrown out in deal method")
if len(ticker.Value) > 4:
continue
if not ((ticker in self.universeOpenPrice) and (ticker in self.universeClosePrice)):
continue
openPrice = self.universeOpenPrice[ticker]
closePrice = self.universeClosePrice[ticker]
if ticker.Value == checking:
self.Debug(checking + " is now being evaluated")
self.Debug("Volume: " + str(self.getVolume(ticker)))
self.Debug("Open Price: " + str(openPrice))
self.Debug("Close Price: " + str(closePrice))
#if ticker.Value == boughtInstead:
# self.Debug(boughtInstead + " is now being evaluated")
# self.Debug("Open Price: " + str(openPrice))
# self.Debug("Close Price: " + str(closePrice))
if (len(alreadyBuying) > 0):
for buying in alreadyBuying:
if buying.Value == ticker.Value:
skip = True
if skip:
continue
if ((((self.startingCash / self.numDiversify) * 0.9) < closePrice)):
continue
if ((openPrice == 0) or (closePrice == 0)):
continue
percentChange = ((closePrice - openPrice) / (closePrice)) * 100
if (ticker.Value == checking):
self.Debug(checking + " percentChange: " + str(percentChange))
if (ticker.Value == boughtInstead):
self.Debug(boughtInstead + " percentChange: " + str(percentChange))
if ((percentChange > 0)):
if (ticker.Value == checking):
self.Debug("WTF " + checking + " IS BELOW -40?")
continue
oldAvg = self.get7DayEMA(ticker)
newAvg = self.get7DayMovingAverage(ticker)
if (((oldAvg * 0.95) < newAvg)):
continue
if (((oldAvg) > (newAvg * 1.3))):
continue
if (self.get7DayEMA(ticker) < self.get7DayMovingAverage(ticker)):
continue
if (not self.isBelow7DayEMA(ticker)):
if (ticker.Value == checking):
self.Debug("WTF " + checking +" is below 7 day ema!?")
continue
#if (not self.trendingDown(ticker)):
# if (ticker.Value == checking):
# self.Debug("Wtf " + checking + " is trending down?")
# continue
volScore = self.getVolatilityScore(ticker)
if (volScore > goldenVolScore):
continue
if ((volScore) > bestVolScore):
bestVolScore = volScore
deal = ticker
else:
if (ticker.Value == checking):
self.Debug("Best Score: " + str(bestVolScore))
self.Debug("Current Score: "+ str(volScore))
continue
'''
posScore = self.getPremarketScore(ticker)
if (posScore < bestPosScore):
posIncrease = self.getAvgPremarketIncrease(ticker)
if (posIncrease > 2):
bestPosScore = posScore
self.Debug("I am overridding best pos score")
else:
#bestVolScore = volScore
#self.Debug("Not the best volScore")
if (ticker.Value == checking):
self.Debug("WTF " + checking + " DOESNT HAVE THE BEST VOLSCORE?")
self.Debug(checking + "'s Volscore is: " + str(volScore))
self.Debug(deal.Value + " has a volscore of: " + str(self.getVolatilityScore(deal)))
continue
'''
#if not (((deal is None) or (ticker is None))):
# self.Debug("Ticker " + deal.Value + " overwritten by " + ticker.Value)
#deal = ticker
if deal != None:
self.Debug("\nCalculated Deal: " + deal.Value)
else:
self.Debug("Deal was none?")
return deal
#for ticker in self.Securities.keys:
def buy(self, toBuy):
if (not toBuy in self.universeClosePrice):
return
price = self.universeClosePrice[toBuy]
self.Debug("Price: " + str(price))
purchasingPower = (self.startingCash / self.numDiversify) * 0.95
numShares = math.floor((purchasingPower)/ price)
self.Debug("Number of Shares: " + str(numShares))
self.MarketOrder(toBuy, numShares)
self.boughtInPrice[toBuy.Value] = self.Portfolio[toBuy].Price
self.peakPrices[toBuy] = price
self.Debug("I am buying " + toBuy.Value)
self.allInvestments.append(toBuy)
self.tradingEnabled = False
return numShares
def sell(self, toSell):
if (not self.tradingEnabled):
return
if (( not toSell.Value in self.boughtInPrice )
or ( not toSell in self.Portfolio )
or ( not toSell in self.orderTickets )
or (not toSell in self.peakPrices)
or (not toSell in self.universeOpenPrice)):
return
self.Debug ("I have made it past the tests")
currentPrice = self.Portfolio[toSell].Price
boughtIn = self.boughtInPrice[toSell.Value]
numShares = self.Portfolio[toSell].Quantity
ticket = self.orderTickets[toSell]
delta = ((self.peakPrices[toSell] - boughtIn) / boughtIn) * 100
#if ((self.boughtInPrice[toSell.Value] * (0.98)) > self.universeOpenPrice[toSell]):
# ticket.Cancel("The Stock " + toSell.Value + " opened below purchase price")
# self.Liquidate(toSell)
if (currentPrice > self.peakPrices[toSell]):
self.peakPrices[toSell] = currentPrice
updateSettings = UpdateOrderFields()
self.Debug("Delta: " + str(delta))
if ((delta > 5) and (delta < 10)):
updateSettings.StopPrice = self.peakPrices[toSell] * 0.97
updateSettings.Tag = "\nChanging the trailing stop"
#ticket.Cancel("Updating StopMarketOrder")
#self.orderTickers[toSell] = self.StopMarketOrder(toSell, ( -1) * self.Portfolio[toSell].Quantity, self.peakPrices[toSell] * 0.97)
if (delta > 10):
updateSettings.StopPrice = self.peakPrices[toSell] * 0.98
updateSettings.Tag = "\nChanging the trailing stop"
#ticket.Cancel("Updating StopMarketOrder")
#self.orderTickers[toSell] = self.StopMarketOrder(toSell, ( -1) * self.Portfolio[toSell].Quantity, self.peakPrices[toSell] * 0.98)
hour = self.Time.hour
minute = self.Time.minute
if (hour == 13) and (minute == 50):
self.Debug("\nMarket is about to close")
ticket.Cancel("Buying new stocks")
self.Liquidate(toSell)
response = ticket.Update(updateSettings)
if (response.IsSuccess):
self.Debug("Updated Successfully")
return
'''
def getAllHistory():
allQuandlData = self.History(QuandlFuture, self.Securities.Keys, timedelta(365))
self.AssertHistoryCount("History(QuandlFuture, self.Securities.Keys, timedelta(365))", allQuandlData, 250)
'''
#def AssertHistoryCount(self, methodCall, tradeBarHistory, expected):
# count = len(tradeBarHistory.index)
# if count != expected:
# raise Exception("{} expected {}, but received {}".format(methodCall, expected, count))
'''class QuandlFuture(PythonQuandl):
def __init__(self):
# Define ValueColumnName: cannot be None, Empty or non-existant column name
# If ValueColumnName is "Close", do not use PythonQuandl, use Quandl:
# self.AddData[QuandlFuture](self.crude, Resolution.Daily)
self.ValueColumnName = "Settle"
'''