Hello,
I'm a C# guy, and brand new to Python. I am having difficulty with the posted ETF Dual Momentum code because I want to modify it to use the top 3 equities or bonds, not just the top 1.
I am getting an error that I understand but cannot solve in this code:
Would someone help me understand it please?
#region imports
from AlgorithmImports import *
#endregion
class VerticalNadionShield(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2016, 1, 1) # Set Start Date
self.SetEndDate(2022, 12, 31) # set end date
self.SetCash(100000) # Set Strategy Cash
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.leverage = 1
self.equities = ["XLV", "XLK", "XLI", "XLU", "XLF", "XLY", "XLP", "XLB", "XLE", "PSR", "IYZ", "USO", "SCZ", "SH", "PSQ", "QQQ"]
self.equityCombinedMomentum = {}
self.bonds = ["TLT", "TIP", "BIL", "AGG", "HYG"]
self.bondCombinedMomentum = {}
for equity in self.equities:
self.AddEquity(equity, Resolution.Hour)
self.Securities[equity].SetDataNormalizationMode(DataNormalizationMode.TotalReturn)
self.equityCombinedMomentum[equity] = CombinedMomentum(self, equity)
for bond in self.bonds:
self.AddEquity(bond, Resolution.Hour)
self.Securities[bond].SetDataNormalizationMode(DataNormalizationMode.TotalReturn)
self.bondCombinedMomentum[bond] = CombinedMomentum(self, bond)
self.SetWarmUp(125)
def shiftAssets(self, target):
for symbol in self.Portfolio:
if symbol not in target[0]:
self.Liquidate(symbol)
for x in target[x][0]:
if not (self.Portfolio[x].Invested):
self.MarketOnCloseOrder(target, self.CalculateOrderQuantity(target, 1 * self.leverage))
def getMonthLastTradingDay(self):
month_last_day = DateTime(self.Time.year, self.Time.month, DateTime.DaysInMonth(self.Time.year, self.Time.month))
tradingDays = self.TradingCalendar.GetDaysByType(TradingDayType.BusinessDay, DateTime(self.Time.year, self.Time.month, 1), month_last_day)
tradingDays = [day.Date.date() for day in tradingDays]
return tradingDays[-1]
def OnData(self, data):
if self.IsWarmingUp:
return
print(self.equities)
if (self.Time.date() == self.getMonthLastTradingDay()) and (self.Time.hour == 15):
topEquities = sorted(self.equityCombinedMomentum.items(), key=lambda x: x[1].getValue(), reverse=True)[:3]
topBonds = sorted(self.bondCombinedMomentum.items(), key=lambda x: x[1].getValue(), reverse=True)[:3]
if (topEquities[0][1].getValue() > 0):
self.shiftAssets(topEquities)
else:
self.shiftAssets(topBonds)
class CombinedMomentum():
def __init__(self, algo, symbol):
self.fst = algo.MOMP(symbol, 21, Resolution.Daily)
self.med = algo.MOMP(symbol, 63, Resolution.Daily)
self.slw = algo.MOMP(symbol, 126, Resolution.Daily)
def getValue(self):
value = (self.fst.Current.Value + self.med.Current.Value + self.slw.Current.Value) / 3
return value
Runtime Error: Trying to dynamically access a method that does not exist throws a TypeError exception. To prevent the exception, ensure each parameter type matches those required by the 'System.Collections.Generic.KeyValuePair[Symbol,SecurityHolding]'>) method. Please checkout the API documentation.
at shiftAssets
self.Liquidate(symbol)
in main.py: line 34
at OnData
self.shiftAssets(topEquities)
at Python.Runtime.PythonException.ThrowLastAsClrException()
at Python.Runtime.PyObject.Invoke(PyTuple args in main.py: line 57 (Open Stack Trace)
Simon David
I think you are not passing in the actual Symbol to Liquidate, you're passing in the ticker string in a variable called symbol.
you could change the code in lines 21 and 26 to store the Symbol from addEquity and keep a list of those or convert to a Symbol object from the ticker at line 35, e.g.
for security in self.Portfolio..items():
symbol = security.Symbol
self.Liquidate(symbol, “some tag")
Nico Xenox
Hey Craig McWilliams,
Simon is right, you have to change a few things in order to make it work. If you want all the keys you can loop trough them with ‘self.Portfolio.Keys’.
The code would look something like this:
Craig McWilliams
Thank you Guys very, very much.
Craig McWilliams
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!