I am currently creating an algorithm that is only in one asset at a time so I am currently manually checking if I'm invested in an asset, if so: liquidate and buy the new one, etc.
In my custom Portfolio Construction Model, I am handling this by only sending 1 PortfolioTarget.Percent object if I am currently invested in nothing and if currently invested in something, sending 2 PortfolioTarget.Percent objects: 1 with a 0% weighting (current asset in which I want to liquidate/get out of) and 1 with a 100% weighting (asset in which I want to switch into)
When handling this in my custom Execution Model class, I understand that self.SetHoldings() can automatically calculate the number of asset units that I would need to buy and it even has a funtion built in to liquidate other assets before starting (such as the example below).
EX:
# Allocate 50% of portfolio value to IBM, but liquidate other holdings before starting
self.SetHoldings("IBM", 0.5, True)
My question is: if I was to stop manually handling my orders and only use SetHoldings(), what would happen if SetHoldings is called with an asset in which I already own? Will it liquidate and re-buy the asset? Or would SetHoldings() ignore that call? Because liquidating and re-buying would harm me through fees and could harm me through other ways in which my algorithm can be scored.
Thank you in advance,
-Jamie
Adam W
You can see how SetHoldings is defined here:
public void SetHoldings(List<PortfolioTarget> targets, bool liquidateExistingHoldings = false) { foreach (var portfolioTarget in targets // we need to create targets with quantities for OrderTargetsByMarginImpact .Select(target => new PortfolioTarget(target.Symbol, CalculateOrderQuantity(target.Symbol, target.Quantity))) .OrderTargetsByMarginImpact(this, targetIsDelta:true)) { SetHoldingsImpl(portfolioTarget.Symbol, portfolioTarget.Quantity, liquidateExistingHoldings); } }
It uses CalculateOrderQuantity to determine the quantity to purchase here:
public decimal CalculateOrderQuantity(Symbol symbol, decimal target) { var percent = PortfolioTarget.Percent(this, symbol, target, true); if (percent == null) { return 0; } return percent.Quantity; }
Note in particular that PortfolioTarget.Percent() is called with returnDeltaQuantity=true, so that only the change in quantity to hit the target weight is returned. If you call SetHoldings('SPY',1) twice (and assuming portfolio value doesn't change at all), this should evaluate to a 0 change in quantity.
Adam W
Also if you did SetHoldings('SPY', 1, True) twice, should be the same 0 change result:
private void SetHoldingsImpl(Symbol symbol, decimal orderQuantity, bool liquidateExistingHoldings = false, string tag = "") { //If they triggered a liquidate if (liquidateExistingHoldings) { foreach (var kvp in Portfolio) { var holdingSymbol = kvp.Key; var holdings = kvp.Value; if (holdingSymbol != symbol && holdings.AbsoluteQuantity > 0) { //Go through all existing holdings [synchronously], market order the inverse quantity: var liquidationQuantity = CalculateOrderQuantity(holdingSymbol, 0m); Order(holdingSymbol, liquidationQuantity, false, tag); } } }
In particular, note the line:
if (holdingSymbol != symbol && holdings.AbsoluteQuantity > 0)
Jamie Dubauskas
Thank you so much for your response! You answered it perfectly!
Jamie Dubauskas
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!