I have been struggling to find a way to allocate a set percentage of my assets to a particular portfolio so that SetHoldings will only apply to that particular percentage of my total portfolio. For example, I would like to have 90% of my money following a certain trend based strategy basewd on the overall market (lets say just moving average crossovers), and 10% of my money in another trend based strategy following Volatility instruments. Right now (since I am still a novice programmer) my portfolio continually rebalances as long as the condition for doing so is true, unless I have holdings set at absolutely nothing or 100% of one equity/instrument. Any type of solutions to these problems are appreciated - thanks in advance for any help! Let me know if you would like to see the underlying code that I am adding it to!
Derek Melchin
Hi Samuel,
I've attached a backtest which demonstrates how we can reserve portions of our portfolio for separate strategies. In this example, we limit strategy #1 to 10% of the portfolio and allocate the rest to strategy #2.
self.strategy_1_portion = 0.1 self.strategy_2_portion = 0.9
In OnData, we allow the strategies to enter/exit positions with respect to their portion of the portfolio.
def OnData(self, data): # Strategy #1 if random() > 0.5: if not self.Portfolio[self.spy].Invested: self.SetHoldings(self.spy, random() * self.strategy_1_portion) else: self.SetHoldings(self.spy, 0) # Strategy #2 if random() > 0.5: if not self.Portfolio[self.tsla].Invested: self.SetHoldings(self.tsla, random() * self.strategy_2_portion) else: self.SetHoldings(self.tsla, 0)
See the attached backtest for the full example algorithm. If this solution doesn't solve the issue you're facing, attach a backtest to this thread.
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.
Samuel Schoening
Thanks for the help so far Derek! Hopefully you can kind of see what I am attempting to do with this here. I might be trying to workaround something that I don't understand too, so please let me know if there is some way to more easily accomplish this! Thanks for any help and stay healthy!
Samuel Schoening
#Separated by page because I could not upload a working backtest yet. #I am trying to rebalance within multiple strategies which will themselves rebalance between each other #Randomly selected stocks, I am just looking for the syntax on how best to accomplish this! PAGE 1 [main.py] from random import random class ModulatedMultidimensionalContainmentField(QCAlgorithm): def Initialize(self): self.SetStartDate(2009, 6, 20) # Set Start Date self.SetCash(2500000000) # Set Strategy Cash / This is to account for the unadjusted prices of TVIX or UVXY over time #Do I need to add all equities here? #Do I need to list all strategy parameters here or can they be on their respective pages? self.strategy_1_portion = 0.45 self.strategy_2_portion = 0.45 self.strategy_3_portion = 0.1 #would like to do something like this if possible: self.Schedule.On( self.DateRules.WeekStart("SPY"), self.TimeRules.AfterMarketOpen("SPY", 120), self.AllocationStation ) def AllocationStation(self): self.SetHoldings(self.Strategy1.py,self.strategy_1_portion) self.SetHoldings(self.Strategy2.py,self.strategy_2_portion) self.SetHoldings(self.Strategy3.py,self.strategy_3_portion) #I want to set a regular rebalancing between multiple strategies referencing the same portfolio #If this is possible I would assume that my strategies would have to be rewritten to reference #the respective strategy's portion of the portfolio itself, rather than simply SetHoldings() PAGE 2 [my_custom_data.py] #This is a slightly modified volatility strategy from Sunny Nagam! from QuantConnect.Python import PythonQuandl # quandl data not CLOSE from QuantConnect.Python import PythonData # custom data from QuantConnect.Data import SubscriptionDataSource from datetime import datetime, timedelta import decimal class CboeVix(PythonData): '''CBOE Vix Download Custom Data Class''' def GetSource(self, config, date, isLiveMode): url_vix = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vixcurrent.csv" return SubscriptionDataSource(url_vix, SubscriptionTransportMedium.RemoteFile) def Reader(self, config, line, date, isLiveMode): if not (line.strip() and line[0].isdigit()): return None # New CboeVix object index = CboeVix(); index.Symbol = config.Symbol try: # Example File Format: # Date VIX Open VIX High VIX Low VIX Close # 01/02/2004 17.96 18.68 17.54 18.22 #print line data = line.split(',') date = data[0].split('/') index.Time = datetime(int(date[2]), int(date[0]), int(date[1])) index.Value = decimal.Decimal(data[4]) index["Open"] = float(data[1]) index["High"] = float(data[2]) index["Low"] = float(data[3]) index["Close"] = float(data[4]) except ValueError: # Do nothing return None # except KeyError, e: # print 'I got a KeyError - reason "%s"' % str(e) return index class CboeVixsm(PythonData): '''CBOE Vix Download Custom Data Class''' def GetSource(self, config, date, isLiveMode): url_vix = "https://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vix9ddailyprices.csv" return SubscriptionDataSource(url_vix, SubscriptionTransportMedium.RemoteFile) def Reader(self, config, line, date, isLiveMode): if not (line.strip() and line[0].isdigit()): return None # New CboeVix object index = CboeVixsm(); index.Symbol = config.Symbol try: # Example File Format: # Date VIX Open VIX High VIX Low VIX Close # 01/02/2004 17.96 18.68 17.54 18.22 #print line data = line.split(',') date = data[0].split('/') index.Time = datetime(int(date[2]), int(date[0]), int(date[1])) index.Value = decimal.Decimal(data[4]) index["Open"] = float(data[1]) index["High"] = float(data[2]) index["Low"] = float(data[3]) index["Close"] = float(data[4]) except ValueError: # Do nothing return None # except KeyError, e: # print 'I got a KeyError - reason "%s"' % str(e) return index # NB: CboeVxV class == CboeVix class, except for the URL class CboeVxv(PythonData): '''CBOE VXV Download Custom Data Class''' def GetSource(self, config, date, isLiveMode): url_vxv = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/vix3mdailyprices.csv" return SubscriptionDataSource(url_vxv, SubscriptionTransportMedium.RemoteFile) def Reader(self, config, line, date, isLiveMode): if not (line.strip() and line[0].isdigit()): return None index = CboeVxv(); index.Symbol = config.Symbol try: # Example File Format: # OPEN HIGH LOW CLOSE # 12/04/2007 24.8 25.01 24.15 24.65 data = line.split(',') date = data[0].split('/') index.Time = datetime(int(date[2]), int(date[0]), int(date[1])) index.Value = decimal.Decimal(data[4]) index["Open"] = float(data[1]) index["High"] = float(data[2]) index["Low"] = float(data[3]) index["Close"] = float(data[4]) except ValueError: # Do nothing return None return index PAGE 3 [Strategy1.py] class MultidimensionalTransdimensionalPrism(QCAlgorithm): def Initialize(self): self.SetStartDate(2009, 6, 20) # 2013/12/01 Earliest start date for all ETFs in universe 2/1/10 self.SetEndDate(2020, 6, 20) self.SetCash(250000000) self.SetBenchmark("SPY") self.SetWarmup(400) self.AddEquity("TSLA", Resolution.Minute) #Randomly selected tickers self.AddEquity("AAPL", Resolution.Minute) self.AddEquity("GOOG", Resolution.Minute) self.AddEquity("TXN", Resolution.Minute) self.AddEquity("SRTY", Resolution.Minute) self.AddEquity("IEF", Resolution.Minute) self._tkr = ["TSLA", "AAPL", "GOOG", "TXN", "SRTY", "IEF"] self._mothersma = self.SMA("SPY", 10, Resolution.Daily) self._othersma = self.SMA("SPY", 120, Resolution.Daily) self._sma = self.SMA("SPY", 200, Resolution.Daily) self.mompqqq = self.MOMP("SPY", 12, Resolution.Hour) self._mompqqqb = self.MOMP("SPY", 3, Resolution.Daily) self.vmaS = self.SMA("SPY", 10, Resolution.Daily, Field.Volume) self.vmaSS = self.SMA("SPY", 5, Resolution.Daily, Field.Volume) self.vmaL = self.SMA("SPY", 300, Resolution.Daily, Field.Volume) self.Schedule.On( self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 120), self.Rebalance ) #Implement a Pause to trading of 2-3 months after 10 crosses below 120 def Rebalance(self): if self.mompqqq.Current.Value <= -3: self.SetHoldings("TSLA", 0) self.SetHoldings("AAPL", 0) self.SetHoldings("GOOG", 0) self.SetHoldings("TXN", 0.25) self.SetHoldings("SRTY", 0.25) self.SetHoldings("IEF", 0) elif self.vmaS.Current.Value <= self.vmaL.Current.Value: self.SetHoldings("TSLA", 0) self.SetHoldings("AAPL", 1) self.SetHoldings("GOOG", 0) self.SetHoldings("TXN", 0) self.SetHoldings("SRTY", 0) self.SetHoldings("IEF", 0) elif self.vmaL.Current.Value <= (self.vmaSS.Current.Value)*1.16666: self.SetHoldings("TSLA", 0) self.SetHoldings("AAPL", 0) self.SetHoldings("GOOG", 0) self.SetHoldings("TXN", 0.5) self.SetHoldings("SRTY", 0.5) self.SetHoldings("IEF", 0) else: self.SetHoldings("TSLA", 0) self.SetHoldings("AAPL", 0) self.SetHoldings("GOOG", 0) self.SetHoldings("TXN", 0) self.SetHoldings("SRTY", 0) self.SetHoldings("IEF", 0) PAGE 4 [Strategy2.py] class MultidimensionalTransdimensionalPrism(QCAlgorithm): def Initialize(self): self.SetStartDate(2009, 6, 20) # 2013/12/01 Earliest start date for all ETFs in universe 2/1/10 self.SetEndDate(2020, 6, 20) self.SetCash(250000000) self.SetBenchmark("SPY") self.SetWarmup(400) self.AddEquity("TSLA", Resolution.Minute) #Randomly selected tickers self.AddEquity("AAPL", Resolution.Minute) self.AddEquity("GOOG", Resolution.Minute) self.AddEquity("TXN", Resolution.Minute) self.AddEquity("SRTY", Resolution.Minute) self.AddEquity("IEF", Resolution.Minute) self._tkr = ["TSLA", "AAPL", "GOOG", "TXN", "SRTY", "IEF"] self._mothersma = self.SMA("SPY", 10, Resolution.Daily) self._othersma = self.SMA("SPY", 120, Resolution.Daily) self._sma = self.SMA("SPY", 200, Resolution.Daily) self.mompqqq = self.MOMP("SPY", 12, Resolution.Hour) self._mompqqqb = self.MOMP("SPY", 3, Resolution.Daily) self.vmaS = self.SMA("SPY", 10, Resolution.Daily, Field.Volume) self.vmaSS = self.SMA("SPY", 5, Resolution.Daily, Field.Volume) self.vmaL = self.SMA("SPY", 300, Resolution.Daily, Field.Volume) self.Schedule.On( self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 120), self.Rebalance ) #Implement a Pause to trading of 2-3 months after 10 crosses below 120 def Rebalance(self): if self.mompqqq.Current.Value <= -3: self.SetHoldings("TSLA", 0) self.SetHoldings("AAPL", 0) self.SetHoldings("GOOG", 0) self.SetHoldings("TXN", 0.25) self.SetHoldings("SRTY", 0.25) self.SetHoldings("IEF", 0) elif self.vmaS.Current.Value <= self.vmaL.Current.Value: self.SetHoldings("TSLA", 0.5) self.SetHoldings("AAPL", 0.5) self.SetHoldings("GOOG", 0) self.SetHoldings("TXN", 0) self.SetHoldings("SRTY", 0) self.SetHoldings("IEF", 0) elif self.vmaL.Current.Value <= (self.vmaSS.Current.Value)*1.16666: self.SetHoldings("TSLA", 0) self.SetHoldings("AAPL", 0) self.SetHoldings("GOOG", 0) self.SetHoldings("TXN", 0.5) self.SetHoldings("SRTY", 0.5) self.SetHoldings("IEF", 0) else: self.SetHoldings("TSLA", 0) self.SetHoldings("AAPL", 0) self.SetHoldings("GOOG", 0) self.SetHoldings("TXN", 0) self.SetHoldings("SRTY", 0) self.SetHoldings("IEF", 0) PAGE 5 [Strategy3.py] from System import * from QuantConnect import * from QuantConnect.Algorithm import * from QuantConnect.Data.Custom.CBOE import * from QuantConnect.Python import PythonQuandl # quandl data not CLOSE from QuantConnect.Data import SubscriptionDataSource from QuantConnect.Python import PythonData import pandas as pd from my_custom_data import * # QuandlFuture, CboeVix, CboeVxV from QuantConnect.Python import PythonData # custom data from datetime import date, timedelta, datetime from decimal import Decimal import numpy as np from math import floor import json class QuandlFutures(PythonQuandl): def __init__(self): self.ValueColumnName = "open" class VentralTachyonAtmosphericScrubbers(QCAlgorithm): def Initialize(self): self.SetStartDate(2009, 6, 20) # Set Start Date self.SetEndDate(2020, 6, 25) self.SetCash(100000) # Set Strategy Cash self.perc_qnty = 1 self.selectedResolution = Resolution.Daily self.uvxy = self.AddEquity("UVXY", self.selectedResolution).Symbol self.svxy = self.AddEquity("SVXY", self.selectedResolution).Symbol self.spy = self.AddEquity("SPY", self.selectedResolution).Symbol self.tqqq = self.AddEquity("TQQQ", self.selectedResolution).Symbol self.spySma = self.SMA(self.spy, 25, self.selectedResolution, Field.Open) self.svxymomentum = self.MOMP("SVXY", 100) self.vixStr = "VIX" self.vxvStr = "VXV" self.vixsmStr = "VIX9D" self.AddData(CboeVix, "VIX") self.AddData(CboeVxv, "VXV") self.AddData(CboeVixsm, "VIX9D") self.macd = self.MACD("SPY", 12, 26, 6, MovingAverageType.Exponential, self.selectedResolution, Field.Open) self.yvixRatio = 0 self.yvixCrossUp = False self.yspy = 0 self.yspySma = 0 def OnData(self, data): if self.vixStr not in data or self.vxvStr not in data: return vixPrice = data[self.vixStr].Open vxvPrice = data[self.vxvStr].Open vixsmPrice = None if self.vixsmStr in data: vixsmPrice = data[self.vixsmStr].Open uvxy_qnty = self.Portfolio[self.uvxy].Quantity svxy_qnty = self.Portfolio[self.svxy].Quantity tqqq_qnty = self.Portfolio[self.tqqq].Quantity vixRatio = vixPrice/vxvPrice #self.Plot("Vix/Vix3M", "Vix/Vix3M", vixRatio) #self.Plot("SVXY", "SVXY", self.Securities["SVXY"].Price) #self.Plot("SPY", "SPY", self.Securities["SPY"].Open) #self.Plot("MACD", "Source", self.macd.Current.Value) #self.Plot("MACD", "Signal", self.macd.Signal.Current.Value) vixCrossUp = False if vixsmPrice: vixCrossUp = vixsmPrice > vixPrice macdLong = self.macd.Current.Value < self.macd.Signal.Current.Value inLong = uvxy_qnty != 0 inShort = svxy_qnty != 0 inRest = tqqq_qnty != 0 shortEntry = (vixRatio < 0.95) and not vixCrossUp and not (self.Securities["SPY"].Open <= self.spySma.Current.Value and self.yspy > self.yspySma) shortExit = inShort and (not shortEntry) longEntry = vixRatio > 1.05 and vixCrossUp and macdLong longExit = inLong and (not longEntry) if shortExit or longExit: self.Liquidate() if not inRest and longExit: self.SetHoldings(self.tqqq, self.perc_qnty) return if (shortEntry): if inLong: self.Liquidate(self.uvxy) if inRest: self.Liquidate(self.tqqq) if not inShort: self.SetHoldings(self.svxy, self.perc_qnty) if (longEntry): if inShort: self.Liquidate(self.svxy) if inRest: self.Liquidate(self.tqqq) if not inLong: self.SetHoldings(self.uvxy, self.perc_qnty) self.yvixRatio = vixRatio self.yvixCrossUp = vixCrossUp self.yspy = self.Securities["SPY"].Open self.yspySma = self.spySma.Current.Value
Samuel Schoening
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!