| Overall Statistics |
|
Total Trades 37 Average Win 5.34% Average Loss -4.31% Compounding Annual Return 11876.144% Drawdown 11.400% Expectancy 0.493 Net Profit 40.619% Sharpe Ratio 79.354 Probabilistic Sharpe Ratio 88.616% Loss Rate 33% Win Rate 67% Profit-Loss Ratio 1.24 Alpha 74.668 Beta 2.313 Annual Standard Deviation 0.942 Annual Variance 0.888 Information Ratio 83.068 Tracking Error 0.9 Treynor Ratio 32.336 Total Fees $53.04 Estimated Strategy Capacity $210000.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, 1, 31)
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 == 15) and (minute == 53):
self.allInvestments = []
if (hour == 15) 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 == "JMIA":
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 == 16):
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 == "SEAC"):
self.Debug("SEAC EMA: " + str(self.get7DayEMA(x)))
if (x.Value == "QS"):
self.Debug("QS Vol: " + str(self.getVolatilityScore(x)))
return
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)
if (x.Symbol.Value == "JMIA"):
self.Debug("JMIA is present before filter")
self.Debug("JMIA Volume: " + str(x.Volume))
self.Debug("JMIA Price: " + str(x.Price))
if(x.Volume > 500000):
if(x.Symbol.Value == "JMIA"):
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);
}
'''
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 = "SEAC"
boughtInstead = "AGFS"
highestPercentChange = 0
percentChange = 0
volScore = 0
bestVolScore = 0
posScore = 0
bestPosScore = 99
deal = None
skip = False
for ticker in self.stocks:
#self.Debug("I am on the ticker: " + ticker.Value)
#self.Debug(ticker.Value)
name = self.getStockName(ticker.Value)
if (name == "NULL"):
continue
#self.Debug(name)
if((("pharma" in name))
or (("Pharma" in name))
or (("Medical" in name))
or (("medical" in name))
or (("peutics" in name))
or (("Bio" in name))
or (("bio" in name))):
continue
#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("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.Portfolio.Cash / 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 < -40) or (percentChange > 0)):
if (ticker.Value == checking):
self.Debug("WTF " + checking + " IS BELOW -40?")
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 (percentChange < highestPercentChange):
if (volScore > 50):
continue
if ((volScore) > bestVolScore):
bestVolScore = volScore
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(deal != None):
if(deal.Value == checking):
self.Debug("WTF " + checking + " IS BEING OVERWRITTEN?")
if not (((deal is None) or (ticker is None))):
self.Debug("Ticker " + deal.Value + " overwritten by " + ticker.Value)
highestPercentChange = percentChange
deal = ticker
else:
if (ticker.Value == checking):
self.Debug("WTF " + checking + " IS NOT THE HIGHEST DECREASE?")
if deal != None:
self.Debug("\nCalculated Deal: " + deal.Value)
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 == 15) 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"
'''