---
title: "Position Sizing"
description: "LEAN provides several methods to help you set specific portfolio weights for assets."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/position-sizing
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/position-sizing.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/22%20Trading%20and%20Orders/05%20Position%20Sizing
modified: 2026-10-30
index: https://www.quantconnect.com/llms.txt
---

# Position Sizing

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Trading and Orders > Position Sizing

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## 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 `set_holdings` method calculates the number of asset units to purchase based on the portfolio weight you provide and then [submits market orders](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/order-types/market-orders.md#02-Place-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.

```python
 # 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, liquidate_existing_holdings=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 or to a small quantity that doesn't exceed the `minimum_order_margin_portfolio_percentage` [algorithm setting](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#10-Set-Algorithm-Settings), then the `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 `set_holdings` method with a list of `PortfolioTarget` objects, LEAN sorts the orders based on your position delta and then [places the orders](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/order-types/market-orders.md#02-Place-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 `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` method.

```python
# Purchase a portfolio of targets, processing orders intelligently.
# PortfolioTarget accepts a Symbol and decimal percent of buying power.
targets = [PortfolioTarget("SPY", 0.8), PortfolioTarget("IBM", 0.2)]
self.set_holdings(targets)
```

If you want the targets you pass to define the target portfolio state, enable the `liquidate_existing_holdings` argument.

```python
self.set_holdings([PortfolioTarget("SPY", 0.8), PortfolioTarget("IBM", 0.2)], liquidate_existing_holdings=True)
```

The method also accepts [tag](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/order-properties.md#17-Tags) and [order properties](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/order-properties.md) arguments.

```python
self.set_holdings(targets, liquidate_existing_holdings, tag, order_properties)
```

If the percentage you provide translates to an order quantity of 0 or to a small quantity that doesn't exceed the `minimum_order_margin_portfolio_percentage` [algorithm setting](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#10-Set-Algorithm-Settings), then the `set_holdings` method doesn’t place an order and doesn’t log anything.

## Asynchronous Orders

When you trade a large portfolio of assets, you may want to send orders in batches and not wait for the response of each one. To send [asynchronous orders](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/key-concepts.md#09-Asynchronous-Execution), set the `asynchronous` argument to `True`.

```python
self.set_holdings("IBM", 0.5, asynchronous=True);
```

The `asynchronous` parameter comes before the `tag` parameter, so pass the tag as a named argument, such as `tag="Entry"`. If you pass the tag by position, it fills the `asynchronous` parameter and the method call fails.

When you set multiple asset targets, you likely want to send asynchronous orders.

```python
targets = [PortfolioTarget("SPY", 0.8), PortfolioTarget("IBM", 0.2)]
self.set_holdings(targets, asynchronous=True)
```

## Calculate Order Quantities

The `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 `calculate_order_quantity` method. The method calculates the quantity based on the current price of the asset and adjusts it for the [fee model](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/transaction-fees/key-concepts.md) 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.

```python
 # 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 `set_holdings` method assumes a 0.25% cash buffer. If LEAN rejects your orders due to buying power, widen the cash buffer through the algorithm `settings` property.

```python
# 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 `free_portfolio_value_percentage`, you must set it in the `initialize` or `post_initialize` event handler. If you use `free_portfolio_value`, you must set it after the `post_initialize` event handler.

## Examples

The following examples demonstrate some common practices for position sizing.

### Example 1: Covered Call

```python
class PositionSizingAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(10_000_000)

        # Seed the price to ensure securities have information for margin calculations.
        self.settings.seed_initial_prices = True

        # Request SPY data for trading. We use raw price data to compare the strike price fairly for ATM contract selection.
        self.spy = self.add_equity("SPY", data_normalization_mode=DataNormalizationMode.RAW).symbol

        # Set a scheduled event to rebalance the covered call positions.
        self.schedule.on(
            self.date_rules.week_start(self.spy),
            self.time_rules.after_market_open(self.spy, 1),
            self.rebalance
        )

    def rebalance(self) -> None:
        option_chain = self.option_chain(self.spy)
        # Filter for the calls within 1-week expiry.
        expiry = max(x.expiry for x in option_chain if x.expiry <= self.time + timedelta(6))
        filtered = [x for x in option_chain if x.right == OptionRight.CALL and x.expiry == expiry]
        # Select the ATM call.
        atm_call = sorted(filtered, key=lambda x: abs(x.strike - self.securities[self.spy].price))[0]
        atm_call = self.add_option_contract(atm_call).symbol

        # Calculate the order size for the covered call.
        quantity = int(self.calculate_order_quantity(self.spy, 0.5) // 100)
        # Covered call involves 100 shares of SPY and -1 ATM call contract.
        if quantity > 0:
            self.combo_market_order(
                [Leg.create(self.spy, 100), Leg.create(atm_call, -1)],
                quantity,
                asynchronous=True
            )
```
