Trading and Orders

Position Sizing

Introduction

LEAN provides several methods to help you set specific portfolio weights for assets. These methods account for lot size and pre-calculated order fees.

Single Asset Targets

The SetHoldings 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 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 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 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 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 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, liquidateExistingHoldings, tag, orderProperties)

Calculate Order Quantities

The SetHoldings 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 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 method assumes a 2.5% cash buffer. If LEAN rejects your orders due to buying power, widen the cash buffer through the algorithm 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 FreePortfolioValuePercentagefree_portfolio_value_percentage, you must set it in the Initialize or PostInitializepost_initialize event handler. If you use FreePortfolioValuefree_portfolio_value, you must set it after the PostInitializepost_initialize event handler.

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: