from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Python import PythonQuandl
from datetime import timedelta, datetime
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
class SMAPairsTrading(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2000, 1, 1)
self.SetEndDate(2010,3,16)# Set Start Date
self.SetCash(100000) # Set Strategy Cash
self.SetUniverseSelection(AllUniverse())
self.UniverseSettings.Resolution = Resolution.Daily
self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw
self.AddAlpha(Smaalphamodel())
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.05))
self.SetExecution(ImmediateExecutionModel())
self.SetBenchmark("SPY")
self.SetSecurityInitializer(self.CustomSecurityInitializer)
def OnEndOfDay(self, symbol):
self.Log("Taking a position of " + str(self.Portfolio[symbol].Quantity) + " units of symbol " + str(symbol))
def CustomSecurityInitializer(self, security):
security.SetLeverage(1)
class Smaalphamodel(AlphaModel):
def __init__(self):
self.Symbols = [ ]
self.SMALT = SimpleMovingAverage(200)
self.SMAMT = SimpleMovingAverage(50)
self.SMAST = SimpleMovingAverage(20)
self.period = timedelta(days=2)
def Update(self, algorithm, data):
Appd = []
Prices={}
for i in range(len(List)):
Price[i] = self.Symbols[i].Price
List=[x.Symbol for x in self.Symbols]
self.SMALT.Update(algorithm.Time,[x for x in Prices])
self.SMAMT.Update(algorithm.Time,[x for x in Prices])
self.SMAST.Update(algorithm.Time,[x for x in Prices])
for i in List:
if self.Symbols[i].Price > self.SMAL[i].Current.Value > self.SMAMT[i].Current.Value>self.SMAST[i].Current.Value :
Appd.append(Insight.Price(i, self.period, InsightDirection.Up))
elif self.Symbols[i].Price < self.SMAL[i].Current.Value < self.SMAMT[i].Current.Value < self.SMAST[i].Current.Value :
Appd.append(Insight.Price(i, self.period, InsightDirection.Down))
else:
Appd.append(Insight.Price(i, self.period, InsightDirection.Flat))
return Insight.Group([ x for x in Appd])
def OnSecuritiesChanged(self, algorithm, changes):
self.Symbols = [x for x in changes.AddedSecurities]
#1. Call for 500 bars of history data for each symbol in the pair and save to the variable history
history = algorithm.History([x.Symbol for x in self.Symbols], 200)
#2. Unstack the Pandas data frame to reduce it to the history close price
history = history.close.unstack(level=0)
for tuple in history.itertuples():
self.SMALT.Update(tuple[0],[tuple[i] for i in range(len(self.Symbols))])
self.SMAMT.Update(tuple[0],[tuple[i] for i in range(len(self.Symbols))])
self.SMAST.Update(tuple[0],[tuple[i] for i in range(len(self.Symbols))])
class AllUniverse(FundamentalUniverseSelectionModel):
'''
This module selects the most liquid stocks listed on the New York Stock Exchange.
'''
def __init__(self, filterFineData = True, universeSettings = None, securityInitializer = None):
'''Initializes a new default instance of the TechnologyUniverseModule'''
super().__init__(filterFineData, universeSettings, securityInitializer)
self.numberOfSymbolsCoarse = 1000
self.numberOfSymbolsFine = 500
self.dollarVolumeBySymbol = {}
self.lastMonth = -1
def SelectCoarse(self, algorithm, coarse):
'''
Performs a coarse selection:
-The stock must have fundamental data
-The stock must have positive previous-day close price
-The stock must have positive volume on the previous trading day
'''
if algorithm.Time.month == self.lastMonth:
return Universe.Unchanged
sortedByDollarVolume = sorted([x for x in coarse if x.HasFundamentalData and x.Volume > 0 and x.Price > 5],
key = lambda x: x.DollarVolume, reverse=True)[:self.numberOfSymbolsCoarse]
self.dollarVolumeBySymbol = {x.Symbol:x.DollarVolume for x in sortedByDollarVolume}
# If no security has met the QC500 criteria, the universe is unchanged.
if len(self.dollarVolumeBySymbol) == 0:
return Universe.Unchanged
return list(self.dollarVolumeBySymbol.keys())
def SelectFine(self, algorithm, fine):
'''
Performs a fine selection:
-The company's headquarter must in the U.S.
-The stock must be traded on the NASDAQ stock exchange
-The stock must be in the Industry Template Code catagory N
-At least half a year since its initial public offering
'''
# Filter stocks and sort on dollar volume
sortedByDollarVolume = sorted([x for x in fine if x.CompanyReference.CountryId == "USA"
and x.CompanyReference.PrimaryExchangeID == "NYS"
and (algorithm.Time - x.SecurityReference.IPODate).days > 180],
key = lambda x: self.dollarVolumeBySymbol[x.Symbol], reverse=True)
if len(sortedByDollarVolume) == 0:
return Universe.Unchanged
self.lastMonth = algorithm.Time.month
return [x.Symbol for x in sortedByDollarVolume[:self.numberOfSymbolsFine]]
Hello , I want to create an alpha model using technical analysis but unfortunately I couldn't update the historical datas in the SimpleMovingAverage function.Does anyone know how to fix this problem?
Thank you
Derek Melchin
Hi Wawes23,
The issue here is that the algorithm is trying to pump historical data for a collection of securities into a single SimpleMovingAverage indicator. See the following snippet.
history = history.close.unstack(level=0) for tuple in history.itertuples(): self.SMALT.Update(tuple[0],[tuple[i] for i in range(len(self.Symbols))])
The Update method doesn't accept those arguments.
Instead, we should create an indicator for each symbol. Refer to this strategy in the Strategy Library for an example. Note how we create a SymbolData object for each symbol in the OnSecuritiesChanged method.
Best,
Derek Melchin
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Wawes23
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!