| Overall Statistics |
|
Total Trades 621 Average Win 0.57% Average Loss -0.73% Compounding Annual Return 43.899% Drawdown 21.200% Expectancy 0.575 Net Profit 168.097% Sharpe Ratio 1.429 Loss Rate 12% Win Rate 88% Profit-Loss Ratio 0.78 Alpha 0.265 Beta 4.43 Annual Standard Deviation 0.239 Annual Variance 0.057 Information Ratio 1.357 Tracking Error 0.239 Treynor Ratio 0.077 Total Fees $967.76 |
import numpy as np
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Common")
import math as mt
from System import *
from QuantConnect import *
from QuantConnect.Data import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from System.Collections.Generic import List
import decimal as d
from datetime import timedelta
### <summary>
### Basic template algorithm simply initializes the date range and cash. This is a skeleton
### framework you can use for designing an algorithm.
### </summary>
def make_div_by_05(s, buy=False):
s *= 20.00
s = mt.floor(s) if buy else mt.ceil(s)
s /= 20.00
return s
class theMAs(object):
def __init__(self,symbol):
self.dv = 0
price = 0
self.symbol = symbol
self.Short = SimpleMovingAverage(3)
self.Long = SimpleMovingAverage(42)
self.percent_diff = 0
def update(self,time,value):
if self.Short.Update(time,value) and self.Long.Update(time,value):
short = self.Short.Current.Value
Long = self.Long.Current.Value
class BasicTemplateAlgorithm(QCAlgorithm):
def __init__(self):
self.Age = {}
def Initialize(self):
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)
self.SetWarmUp(200)
self.firstbuy = 1
self.days = 0
self.Tobuy = 0
self.filtered_stocks = []
self.averages = {}
self.MaxCandidates=50
self.MaxBuyOrdersAtOnce=20
self.MyLeastPrice=0.40
self.MyMostPrice=1.40
self.MyFireSalePrice=self.MyLeastPrice
self.MyFireSaleAge=3
self.SetStartDate(2016,1,07) #Set Start Date
self.SetEndDate(2017,12,07) #Set End Date
self.SetCash(2500) #Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Daily
self.AddEquity("SPY", Resolution.Daily)
self.AddUniverse(self.CoarseSelectionFunction,self.FineSelectionFunction)
self.Schedule.On(self.DateRules.EveryDay(),self.TimeRules.Every(timedelta(minutes=10)),Action(self.rebalance))
self.Schedule.On(self.DateRules.EveryDay(),self.TimeRules.At(9,37),Action(self.before_trading_start))
def CoarseSelectionFunction(self, coarse):
stocks_To_buy = filter(lambda x: x.Price >=self.MyLeastPrice,coarse)
stocks_To_buy = filter(lambda x: x.Price <=self.MyMostPrice,stocks_To_buy)
stocks_To_buy = filter(lambda x: x.HasFundamentalData,stocks_To_buy)
#for stock in stocks_To_buy[:10]:
#self.Log("The market of the stock is {}".format(stock.StandardName))
#Symbols with more than 5 letters are usually not common stocks and otc's have 5 letters
#Check here for more info https://www.investopedia.com/ask/answers/06/nasdaqfifthletter.asp(could take off)
return [x.Symbol for x in stocks_To_buy[:60] if len(str(x.Symbol.Value)) < 5 and x.Symbol.Value != 'SPY' ]
def FineSelectionFunction(self, fine):
#Making sure not mlp
stocks_To_buy = filter(lambda x: 'lp' not in str(x.CompanyReference.ShortName).lower(),fine)
#Making sure not adr
stocks_To_buy = filter(lambda x: int(x.SecurityReference.IsDepositaryReceipt) ==0,stocks_To_buy)
#Making sure is primary adr
stocks_To_buy = filter(lambda x: x.SecurityReference.IsPrimaryShare,stocks_To_buy)
#Making sure not otc
stocks_To_buy = filter(lambda x: str(x.SecurityReference.ExchangeId) != "OTC",stocks_To_buy)
#get moving averages and dollar volume
for stock in stocks_To_buy:
self.AddEquity(str(stock.Symbol.Value))
hist = self.History([stock.Symbol.Value],20,Resolution.Daily)
if 'volume' in hist:
dv = (hist['volume'].mean()*hist['close'].mean())/len(hist)
#self.dvolume[stock.Symbol.Value] = dvolume(stock.Symbol.Value,dv)
#self.Log(("Volume for stock {} is {}".format(self.dvolume[stock.Symbol.Value].symbol,self.dvolume[stock.Symbol.Value].dvolAvg)))
if stock.Symbol not in self.averages:
self.averages[stock.Symbol] = theMAs(stock.Symbol)
avg = self.averages[stock.Symbol]
avg.dv=dv
avg.price = self.Securities[stock.Symbol.Value].Price
avg.update(stock.EndTime,self.Securities[stock.Symbol.Value].Price)
if float(str(avg.Long)) >0 :
avg.percent_diff = (float(str(avg.Short)) - float(str(avg.Long))) / float(str(avg.Long))
#self.Log("The long ma for {} is {}".format(stock.Symbol.Value,avg.dv))
values = self.averages.values()
values.sort(key=lambda x: x.dv)
minmum_range = int(round(len(values) * 0.06))
maximum_range = int(round(len(values) * 0.40))
if minmum_range < 1:
minmum_range =0
if maximum_range < 1:
maximum_range = 1
values = values[minmum_range:maximum_range]
values.sort(key=lambda x: x.percent_diff)
values = values[:10]
#self.Log(str(values[0].dv))
#for stock in values:
#self.Log("{0} {1}".format(str(stock.symbol),str(stock.percent_diff)))
#self.Log("--------")
#for stock in stocks_To_buy:
#self.Log("here is the stock{}".format(str(stock.SecurityReference.ExchangeId)))
return [ x.symbol for x in values]
def before_trading_start(self):
day = str(self.UtcTime).split("-")[-1]
day = day.split(" ")[0]
#self.Log(str(day))
MyLeastPrice=0.40
MyMostPrice=1.40
for stock in self.Portfolio.Values:
if stock.Invested:
if str(stock.Symbol) not in self.Age:
self.Age[str(stock.Symbol)] = 0
else:
self.Age[str(stock.Symbol)]+=1
#self.Log(str(self.Age[stock.Symbol]))
"""for stock.Symbol in self.Age:
if stock.Symbol not in self.Portfolio.Values:
self.Age.pop(stock.Symbol)
#self.Log(str(self.Age[stock.Symbol]))
lowestprice = MyLeastPrice
if len(self.Portfolio.Transactions) > 0:
for stock in self.Portfolio.Transactions:
self.Log(str(stock))
if stock.Invested:
#theid = self.Transactions.LastOrderId(str(stock.Symbol))
#self.Log(str(self.Transactions.GetOrderById(theid)))
curr_price = float(self.Securities[stock.Symbol].Price)
if curr_price < lowestprice:
lowestprice = curr_price
else:
self.Log(str(self.Portfolio.Transactions))"""
def OnSecuritiesChanged(self, changes):
time = str(self.Time).split(' ')[1]
hour = time.split(':')[0]
m = time.split(':')[1]
self.filtered_stocks = [stock for stock in changes.AddedSecurities]
#self.Log("amount of stocks in universe {}".format(len(self.filtered_stocks)))
def rebalance(self):
cash = float(self.Portfolio.Cash)
self.Tobuy = float(len(self.filtered_stocks))
if self.Tobuy > 0:
weight = float(1/self.Tobuy)
self.days+=1
BuyFactor=0.96
SellFactor=1.05
for stock in self.Portfolio.Values:
if stock.Invested:
if len(self.Transactions.GetOpenOrders(stock.Symbol)) == 0:
curr_price = float(self.Securities[stock.Symbol].Price)
cost_basis = float(self.Portfolio[stock.Symbol].AveragePrice)
shares_held = self.Portfolio[stock.Symbol].Quantity
sell_price = make_div_by_05(curr_price*SellFactor,buy = False)
if (sell_price)== 0 and shares_held > 0:
pass
if stock.Symbol in self.Age:
if(self.Age[str(stock.Symbol)] % 3 == 0) and self.Age[str(stock.Symbol)] >= self.MyFireSaleAge \
and self.MyLeastPrice > curr_price or cost_basis >curr_price:
stop_price = float(make_div_by_05(0.96*curr_price,buy=False))
self.LimitOrder(stock.Symbol,-shares_held,stop_price)
else:
self.LimitOrder(stock.Symbol,-shares_held,sell_price)
if len(self.filtered_stocks) > 0 and cash > 0:
self.Log(str(cash))
for stock in self.filtered_stocks:
shares_held = self.Portfolio[stock.Symbol].Quantity
oo = len(self.Transactions.GetOpenOrders(stock.Symbol))
if shares_held == 0 and oo == 0:
hist = self.History([stock.Symbol],20,Resolution.Daily)
if 'close' in hist.columns:
avg_price = float(hist['close'].mean())
curr_price = float(self.Securities[stock.Symbol].Price)
if curr_price == None or curr_price == 0:
pass
else:
if curr_price > (1.2* avg_price):
buy_price = curr_price*0.99
else:
buy_price=float(make_div_by_05(BuyFactor*curr_price, buy=True))
#self.Log("The cash{} The weight{} the curr_price{} the buy_price{}".format(cash,weight,curr_price,buy_price))
StockShares = int(cash*0.25/buy_price)
self.LimitOrder(stock.Symbol,StockShares,buy_price)
self.filtered_stocks.pop(self.filtered_stocks.index(stock))
self.Notify.Sms("5105011500", "Stock Watched:\n" + str(stock.Symbol) + "\n Resistance: $" + str(buy_price) + "\nFuego Financial")
self.Notify.Sms("7073190735", "Stock Watched:\n" + str(stock.Symbol) + "\n Resistance: $" + str(buy_price) + "\nFuego Financial")
self.Notify.Sms("5105989476", "Stock Watched:\n" + str(stock.Symbol) + "\n Resistance: $" + str(buy_price) + "\nFuego Financial")