Back

Requesting help with making separate portfolios within the same algorithm

  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!

Update Backtest







0

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.


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

1

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.


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!

0

#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

 

0

Update Backtest





0

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.


Loading...

This discussion is closed