Trading and Orders
Position Sizing
Single Asset Targets
The SetHoldings
set_holdings
method calculates the number of asset units to purchase based on the portfolio weight you provide and then submits market orders. This method provides a quick way to set up a portfolio with a set of weights for assets. If you already have holdings, you may want to liquidate the existing holdings first to free up buying power.
// Allocate 50% of portfolio value to IBM SetHoldings("IBM", 0.5); // Allocate 50% of portfolio value to IBM, but liquidate other holdings first SetHoldings("IBM", 0.5, true); // Provide a tag and order properties to the SetHoldings method SetHoldings(symbol, weight, liquidateExistingHoldings, tag, orderProperties);
# Allocate 50% of buying power to IBM self.set_holdings("IBM", 0.5) # Allocate 50% of portfolio value to IBM, but liquidate other holdings first self.set_holdings("IBM", 0.5, True) # Provide a tag and order properties to the SetHoldings method self.set_holdings(symbol, weight, liquidate_existing_holdings, tag, order_properties)
If the percentage you provide translates to an order quantity of 0, the SetHoldings
set_holdings
method doesn’t place an order and doesn’t log anything.
Multiple Asset Targets
When you trade a weighted basket of assets, sometimes you must intelligently scale down existing positions before increasing allocations to other assets. If you call the SetHoldings
set_holdings
method with a list of PortfolioTarget
objects, LEAN sorts the orders based on your position delta and then places the orders that reduce your position size in an asset before it places orders that increase your position size in an asset. When you call the SetHoldings
set_holdings
method with a list of PortfolioTarget
objects, the decimal you pass to the PortfolioTarget
constructor represents the portfolio weight. In this situation, don't use the PortfolioTarget.Percent
PortfolioTarget.percent
method.
// Purchase a portfolio of targets, processing orders intelligently. var targets = new List<PortfolioTarget>() { new PortfolioTarget("SPY", 0.8m), new PortfolioTarget("IBM", 0.2m) }; SetHoldings(targets);
# Purchase a portfolio of targets, processing orders intelligently. self.set_holdings([PortfolioTarget("SPY", 0.8), PortfolioTarget("IBM", 0.2)]))
If you want the targets you pass to define the target portfolio state, enable the liquidateExistingHoldings
liquidate_existing_holdings
argument.
SetHoldings(targets, true);
self.set_holdings([PortfolioTarget("SPY", 0.8), PortfolioTarget("IBM", 0.2)], True)
The method also accepts tag and order properties arguments.
SetHoldings(targets, liquidateExistingHoldings, tag, orderProperties);
self.set_holdings(targets, liquidate_existing_holdings, tag, order_properties)
Calculate Order Quantities
The SetHoldings
set_holdings
method uses market order to reach the target portfolio weight you provide. If you want to use a different order type, you need to specify the quantity to trade. To calculate the number of units to trade based on a portfolio weight, call the CalculateOrderQuantity
calculate_order_quantity
method. The method calculates the quantity based on the current price of the asset and adjusts it for the fee model of the security. The target weight you provide is an unleveraged value. For instance, if you have 2x leverage and request a 100% weight, the method calculates the quantity that uses half of your available margin.
// Calculate the fee-adjusted quantity of shares with given buying power var quantity = CalculateOrderQuantity("IBM", 0.4);
# Calculate the fee-adjusted quantity of shares with given buying power quantity = self.calculate_order_quantity("IBM", 0.4)
Buying Power Buffer
If you place a market on open order near the market close, the market can gap overnight to a worse open price. If the gap is large enough against your trade direction, you may not have sufficient buying power at the open to fill your trade. To ensure a high probability of order fills through market gaps and discontinuities, the SetHoldings
set_holdings
method assumes a 2.5% cash buffer. If LEAN rejects your orders due to buying power, widen the cash buffer through the algorithm Settings
settings
property.
// Set the cash buffer to 5% Settings.FreePortfolioValuePercentage = 0.05m; // Set the cash buffer to $10,000 Settings.FreePortfolioValue = 10000m;
# Set the cash buffer to 5% self.settings.free_portfolio_value_percentage = 0.05 # Set the cash buffer to $10,000 self.settings.free_portfolio_value = 10000
If you use FreePortfolioValuePercentage
free_portfolio_value_percentage
, you must set it in the Initialize
initialize
or PostInitialize
post_initialize
event handler. If you use FreePortfolioValue
free_portfolio_value
, you must set it after the PostInitialize
post_initialize
event handler.