---
title: "Buying Power"
description: "Buying power models (also known as margin models) control how much buying power or leverage your portfolio has to make trades."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/buying-power
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/buying-power.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/24%20Reality%20Modeling/07%20Buying%20Power
modified: 2026-10-31
index: https://www.quantconnect.com/llms.txt
---

# Buying Power

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Reality Modeling > Buying Power

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

## Introduction

Buying power models (also known as margin models) control how much buying power or leverage your portfolio has to make trades. When you place an order, LEAN uses the buying power model to determine whether the order should be submitted so you avoid placing orders that would be rejected by the brokerage. Buying power calculations can be very complex and depend on many factors, including the brokerage or even the time of day.

## What is Buying Power?

Buying power is the total amount of money you can spend in your brokerage account. It depends on the security type and account type. On one hand, Option and Future contracts are leveraged securities with specific buying power rules. On the other hand, the buying power of cash accounts is just the cash in the account while the buying power of margin accounts is leveraged by the brokerage credit.

## What is Margin?

Margin is a credit loan from your brokerage you receive after you deposit collateral into your margin account. You need margin to place short-biased trades and you can use margin to increase your buying power, but you incur interest fees. **Margin** is the dollar value of the loan that the brokerage gives you. A **margin requirement** of 25% means that to purchase $10,000 worth of securities, you need at least $2,500 worth of collateral in your brokerage account to open the trade and you can borrow the rest on margin. **Maintenance margin** is the minimum equity (equity = total portfolio value - borrowed funds) you must have in your brokerage account to stay in your positions. If the value of your portfolio falls below the maintenance margin, you receive a [margin call](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/margin-calls.md). If you receive a margin call, you either need to add more capital to your brokerage account or the brokerage will liquidate some of your holdings to reduce your exposure and their risk.

Some securities have special margin rules. Derivatives are leveraged assets with a floating margin requirement. In particular, long Options have zero maintenance margin requirement and their initial margin requirement is only the premium that you pay upfront.

## What is Leverage?

Leverage is using borrowed money to increase your buying power. Leverage has an inverse relationship with your margin requirement and maintenance margin. If you have a margin requirement of 50%, you can use up to 1 / 50% = 2 leverage. Trading with leverage can be risky. It can boost your returns on profitable trades but can make your losing trades more expensive. If you have $10,000 in your brokerage margin account and purchase $20,000 worth of securities, you are trading with 2x leverage. If the value of the securities in your portfolio drops by 50% when you have a 2x leverage position, you lose all of your equity.

## What Are Position Groups?

A position group is the combination of holdings. It has lower margin requirement and maintenance margin than the sum of each position of the group. If you have a margin requirement of $29,150 to purchase an in-the-money call Option contract, and a margin requirement of $101,499 to sell an out-of-the money call Option contract, the total margin requirement is $130,649. However, these positions compose a [bull call spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bull-call-spread.md) with a margin requirement of $0.

## Set Models

The brokerage model of your algorithm automatically sets the buying power model for each security, but you can override it. To manually set the buying power model of a security, call the `set_buying_power_model` method on the `Security` object.

```python
def initialize(self) -> None:
    security = self.add_equity("SPY")
    # Use 3x leverage on the selected security, which mimic the actual buying power of your broker
    security.set_buying_power_model(BuyingPowerModel(3))
```

You can also set the buying power model in a [security initializer](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#07-Set-Security-Initializer). If your algorithm has a universe, use the security initializer technique. In order to initialize single security subscriptions with the security initializer, call `add_security_initializer` before you create the subscriptions.

```python
class AddSecurityInitializerExampleAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        # In the Initialize method, set the security initializer to set models of assets.
        self.add_security_initializer(self._custom_security_initializer)

    def _custom_security_initializer(self, security: Security) -> None:
        # Overwrite some of the reality models
        security.set_buying_power_model(BuyingPowerModel(3))
```

You cannot change the position group buying power models.

## Supported Models

The following buying power models are available:

- [BuyingPowerModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/BuyingPowerModel.cs)
- [CashBuyingPowerModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/CashBuyingPowerModel.cs)
- [ConstantBuyingPowerModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/ConstantBuyingPowerModel.cs)
- [CryptoFutureMarginModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/CryptoFuture/CryptoFutureMarginModel.cs)
- [NullBuyingPowerModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/NullBuyingPowerModel.cs)
- [FutureMarginModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/Future/FutureMarginModel.cs)
- [FuturesOptionsMarginModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/FutureOption/FuturesOptionsMarginModel.cs)
- [OptionMarginModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/Option/OptionMarginModel.cs)
- [PatternDayTradingMarginModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/PatternDayTradingMarginModel.cs)

The following position group buying power models are available:

- [SecurityPositionGroupBuyingPowerModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/Positions/SecurityPositionGroupBuyingPowerModel.cs)
- [OptionStrategyPositionGroupBuyingPowerModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/Option/OptionStrategyPositionGroupBuyingPowerModel.cs)

The [SecurityMarginModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/SecurityMarginModel.cs) is an alias to the [BuyingPowerModel](https://github.com/QuantConnect/Lean/blob/master/Common/Securities/BuyingPowerModel.cs).

## Default Behavior

The [brokerage model](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/brokerages/key-concepts.md) of your algorithm automatically sets the buying power model of each security. The default brokerage model is the `DefaultBrokerageModel`, which sets the buying power model based on the asset class of the security. The following table shows the default buying power model of each asset class:

| Asset Class | Model |
| --- | --- |
| Equity Options | `OptionMarginModel` |
| Futures | `FutureMarginModel` |
| Future Options | `FuturesOptionsMarginModel` |
| Index Options | `OptionMarginModel` |
| Crypto | `CashBuyingPowerModel` for cash accounts or `BuyingPowerModel` for margin accounts |
| CryptoFuture | `CryptoFutureMarginModel` |
| Forex | `CashBuyingPowerModel` for cash accounts or `BuyingPowerModel` for margin accounts |
| Other | `BuyingPowerModel` |

## Model Structure

Buying power models should extend the `BuyingPowerModel` class. Extensions of the `BuyingPowerModel` class should implement the following methods:

```python
class CustomBuyingPowerModelExampleAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        security = self.add_equity("SPY")
        # Set the custom buying power model of the selected security to mimic its actual buying power in your used broker
        security.set_buying_power_model(MyBuyingPowerModel())

# Define the custom buying power model
class MyBuyingPowerModel(BuyingPowerModel):
    def __init__(self,
         leverage: float = 2,
         requiredFreeBuyingPowerPercent: float = 0):
        super().__init__(leverage, requiredFreeBuyingPowerPercent)

    def get_leverage(self, security: Security) -> float:
        return super().get_leverage(security)

    def set_leverage(self, security: Security, leverage: float) -> None:
        super().set_leverage(security, leverage)

    def get_initial_margin_required_for_order(self,
         parameters: InitialMarginRequiredForOrderParameters) -> InitialMargin:
        return super().get_initial_margin_required_for_order(parameters)

    def get_maintenance_margin(self,
         parameters: MaintenanceMarginParameters) -> MaintenanceMargin:
        return super().get_maintenance_margin(parameters)

    def get_margin_remaining(self,
         portfolio: SecurityPortfolioManager,
         security: Security,
         direction: OrderDirection) -> float:
        return super().get_margin_remaining(portfolio, security, direction)

    def get_initial_margin_requirement(self,
         parameters: InitialMarginParameters) -> InitialMargin:
        return super().get_initial_margin_requirement(parameters)

    def has_sufficient_buying_power_for_order(self,
         parameters: HasSufficientBuyingPowerForOrderParameters
        ) -> HasSufficientBuyingPowerForOrderResult:
        return super().has_sufficient_buying_power_for_order(parameters)

    def get_maximum_order_quantity_for_delta_buying_power(self,
         parameters: GetMaximumOrderQuantityForDeltaBuyingPowerParameters
        ) -> GetMaximumOrderQuantityResult:
        return super().get_maximum_order_quantity_for_delta_buying_power(parameters)

    def get_maximum_order_quantity_for_target_buying_power(self,
         parameters: GetMaximumOrderQuantityForTargetBuyingPowerParameters
        ) -> GetMaximumOrderQuantityResult:
        return super().get_maximum_order_quantity_for_target_buying_power(parameters)

    def get_reserved_buying_power_for_position(self,
         parameters: ReservedBuyingPowerForPositionParameters
        ) -> ReservedBuyingPowerForPosition:
        return super().get_reserved_buying_power_for_position(parameters)

    def get_buying_power(self,
         parameters: BuyingPowerParameters) -> BuyingPower:
        return super().get_buying_power(parameters)
```

## Disable Buying Power Models

You can disable order margin checks and opt to let your brokerage decide to accept or reject the trades. This is helpful in live trading if you have a more permissive brokerage margin allowance that what LEAN models. The [default position group buying power models](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/buying-power.md#08-Default-Behavior) are helpful for Option trading strategies. However, it can be counterproductive if it's not a [supported Option strategy](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies.md). To disable the validations of the default position group buying power model, use the `NullSecurityPositionGroupModel`. To set the `NullSecurityPositionGroupModel` for the portfolio, during [initialization](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md), call the `set_positions` method with the `SecurityPositionGroupModel. Null NULL` argument.

```python
self.portfolio.set_positions(SecurityPositionGroupModel.NULL)
```

To disable the validations of the [default buying power model](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/buying-power.md#08-Default-Behavior), use the `NullBuyingPowerModel`. To set the `NullBuyingPowerModel` for a security subscription, call the `set_buying_power_model` method with the `BuyingPowerModel. Null NULL` argument.

```python
def initialize(self) -> None:
    equity = self.add_equity("SPY")
    # To disable any buying power of the selected security
    equity.set_buying_power_model(BuyingPowerModel.NULL)
    # Alias:
    # equity.set_margin_model(SecurityMarginModel.NULL)
```

You can also set the `NullBuyingPowerModel` in a [security initializer](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#07-Set-Security-Initializer). If your algorithm has a universe, use the security initializer technique. To set the buying power of securities in the security initializer, [set the brokerage model](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#05-Set-Brokerage-and-Cash-Model), [set the security initializer](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#07-Set-Security-Initializer), and then create security subscriptions.

```python
class AddSecurityInitializerExampleAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        # In the Initialize method, set the security initializer to set models of assets.
        self.add_security_initializer(self._custom_security_initializer)

    def _custom_security_initializer(self, security: Security) -> None:
        # Overwrite the security buying power
        security.set_buying_power_model(BuyingPowerModel.NULL)
```

## Set Asset Leverage

The buying power model sets the leverage for each security in your algorithm, but you can override its leverage settings after the buying power model is set.

To set the leverage when you create a security subscription, pass in a `leverage` argument.

```python
def initialize(self) -> None:
	# Set the leverage to 3x manually subjected to specific need
	self.add_equity("SPY", leverage=3)
```

You can also set the asset leverage in a security initializer. In order to set the leverage of securities in the security initializer, call `add_security_initializer` before you create security subscriptions and after you call `set_brokerage_model`. If you pass in a `leverage` argument when you create the security subscription, the `leverage` argument takes precedence over the `set_leverage` call in the security initializer.

```python
class AddSecurityInitializerExampleAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        # In the Initialize method, set the security initializer to set models of assets.
        self.add_security_initializer(self._custom_security_initializer)

    def _custom_security_initializer(self, security: Security) -> None:
        # Overwrite the security leverage
        security.set_leverage(3)
```

To set the leverage for all securities in a universe, set the `universe_settings.leverage` property.

```python
def initialize(self) ->None:
	# Set the leverage to 3x to all securities, it should only be used for a very narrow spectrum of security universe with the same leverage
	# E.g. US Equities universe composed of only primary stocks in NYSE exchange
	self.universe_settings.leverage = 3
```

In live trading, LEAN doesn't ignore the leverage you set. However, if you set a different leverage from what your brokerage provides, it creates a mismatch between the buying power in your algorithm and the buying power the brokerage gives you. In this case, orders can pass the validations in LEAN but your brokerage may reject them.

## Get Initial Margin Requirements

The following sections explain how to check if you have enough buying power to cover the initial [margin requirements](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/buying-power.md#03-What-is-Margin3F) of an order before you place it.

### Check Requirements of Regular Orders

To check if you have enough buying power for a regular order, create an order request with the [order factory](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/order-management/order-factory.md) and convert it into an `Order` object. Then compare the absolute initial margin that the order requires with the buying power of your portfolio in the direction of the order. The initial margin is negative for sell orders and includes the modeled order fees. The buying power in the direction of the order includes the margin that the order frees when it reduces or reverses a position.

```python
security = self.securities[self._symbol]
request = self.order_factory.market_order(self._symbol, 100)
order = Order.create_order(request)
initial_margin = security.buying_power_model.get_initial_margin_required_for_order(
    InitialMarginRequiredForOrderParameters(self.portfolio.cash_book, security, order)).value
if abs(initial_margin) <= self.portfolio.get_buying_power(self._symbol, order.direction):
    self.order(request)
```

The `has_sufficient_buying_power_for_order` method of the security buying power model requires an order ticket, so it only works for orders that you already submitted. When you submit the order, LEAN runs its own buying power check.

### Check Requirements of Option Strategy Orders

To check if you have enough buying power for an [Option strategy](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies.md) order, follow these steps:

1. Create an `OptionStrategy` object with the strategy you want to trade.
   For example, create a [Bull Put Spread](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/option-strategies/bull-put-spread.md) strategy.
   ```python
   def initialize(self) -> None:
       # Subscribe to option data and cache the canonical symbol to obtain the option data
       self._symbol = self.add_option("SPY").symbol

   def on_data(self, slice: Slice) -> None:
       # Trade on updated option chain data
       chain = slice.option_chains.get(self._symbol)
       if not chain:
           return

       itm_strike = max(x.strike for x in chain)
       otm_strike = min(x.strike for x in chain)
       expiry = min(x.expiry for x in chain)

       option_strategy = OptionStrategies.bull_put_spread(self._symbol, itm_strike, otm_strike, expiry)
   ```
2. Create the order requests of the strategy legs with the [order factory](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/order-management/order-factory.md) and convert each request into an `Order` object.
   ```python
       requests = self.order_factory.option_strategy_order(option_strategy, 2)
       orders = [Order.create_order(request) for request in requests]
   ```
3. Call the `has_sufficient_buying_power_for_order` method of the portfolio with the list of orders.
   ```python
       result = self.portfolio.has_sufficient_buying_power_for_order(orders)
   ```
   The `has_sufficient_buying_power_for_order` method returns a `HasSufficientBuyingPowerForOrderResult` object, which has the following properties:
   *Members of `QuantConnect.Securities.HasSufficientBuyingPowerForOrderResult` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Securities.HasSufficientBuyingPowerForOrderResult&language=python*
4. If the result is sufficient, submit the order requests.
   ```python
       if result.is_sufficient:
           self.order(requests)
       else:
           self.debug(f"You don't have sufficient margin for this order: {result.reason}")
   ```

The method combines the orders with your current holdings into [position groups](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/buying-power.md#05-What-Are-Position-Groups3F), so it accounts for strategy orders that reduce or close a position. If the strategy has a single leg, such as a naked put, follow the steps in the preceding section.

## Live Trading Considerations

LEAN doesn't infer account type, leverage, or margin requirements from your brokerage account. For example, if you have a cash account, and your algorithm doesn't set `AccountType.``CASH`, LEAN will not automatically enforce cash account restrictions such as leverage of 1x or immediate settlement. You must manually configure your algorithm to adhere to these rules. If you set the leverage to 10x and you have a leverage of 2x, LEAN will place orders that can be rejected by your brokerage.

The default leverage of U.S. Equities is 2x. However, your brokerage can reduce the leverage of some securities based on market conditions. For example, leveraged ETFs such as TQQQ might have lower leverage during periods of high volatility. If your algorithm doesn't account for this, LEAN doesn't account for it and your orders can be rejected by your brokerage.

## Examples

The following examples demonstrate some common practices for implementing custom buying power models and checking buying power.

### Example 1: Always Sufficient Buying Power

The following algorithm trades a protective put strategy. Sometimes, the brokerage's margin requirement differs from the algorithm's default. To avoid errors on order submission at the algorithm level, we can use the `SecurityPositionGroupModel.NULL` and `NullBuyingPowerModel` to disable buying power limitation so the order is sent directly to the broker.

```python
class BuyingPowerModelAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.settings.seed_initial_prices = True
        self.add_security_initializer(self._custom_security_initializer)

        # Disable the validations of the default position group buying power model
        # that evaluates the buying power of multi-leg strategies
        self.portfolio.set_positions(SecurityPositionGroupModel.NULL)

        # Request SPY data for trading. Set the data normalization mode to raw to allow for a fair comparison in strike price.
        self.spy = self.add_equity("SPY", data_normalization_mode=DataNormalizationMode.RAW).symbol

        # Set a scheduled event to rebalance the protective put strategy.
        self.schedule.on(
            self.date_rules.week_start(self.spy),
            self.time_rules.after_market_open(self.spy, 0),
            self.rebalance
        )

    def rebalance(self) -> None:
        # Select the weekend expiring ATM put for the protective put strategy.
        chain = self.option_chain(self.spy)
        filtered = [x for x in chain if x.right == OptionRight.PUT and x.expiry <= self.time + timedelta(6)]
        if not filtered:
            return
        atm_put_contract = sorted(filtered,
            key=lambda x: (-abs(x.strike - x.underlying_last_price), x.expiry),
            reverse=True)[0]
        # Request the ATM put data for trading.
        atm_put = self.add_option_contract(atm_put_contract).symbol

        if self.portfolio[self.spy].invested:
            # If SPY is not assigned, we only need to buy the put.
            self.market_order(atm_put, 1, tag="Protective Put")
        else:
            # Order the protective put strategy by combo order.
            self.combo_market_order([
                    Leg.create(self.spy, 100),
                    Leg.create(atm_put, 1)
                ],
                1,
                tag="Protective Put"
            )

    def _custom_security_initializer(self, security: Security):
        # Do not allow buying power for options; only a hedging strategy with 0 margin is allowed.
        security.set_buying_power_model(NullBuyingPowerModel())
```

### Example 2: Default Model Wrapper

The following algorithm defines a subclass of the default `BuyingPowerModel` and overrides its built-in members so you can easily customize the parts you need.

```python
class CustomBuyingPowerModelAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100000)
        security = self.add_equity('SPY', Resolution.DAILY)
        security.set_buying_power_model(MyBuyingPowerModel())

    def on_data(self, data: Slice) -> None:
        if not self.portfolio.invested:
            self.set_holdings('SPY', 1)

class MyBuyingPowerModel(BuyingPowerModel):

    def __init__(self,
         leverage: float = 2,
         required_free_buying_power_percent: float = 0):
        super().__init__(leverage, required_free_buying_power_percent)

    def get_leverage(self, security: Security) -> float:
        return super().get_leverage(security)

    def set_leverage(self, security: Security, leverage: float) -> None:
        super().set_leverage(security, leverage)

    def get_initial_margin_required_for_order(self,
         parameters: InitialMarginRequiredForOrderParameters) -> InitialMargin:
        return super().get_initial_margin_required_for_order(parameters)

    def get_maintenance_margin(self,
         parameters: MaintenanceMarginParameters) -> MaintenanceMargin:
        return super().get_maintenance_margin(parameters)

    def get_margin_remaining(self,
         portfolio: SecurityPortfolioManager,
         security: Security,
         direction: OrderDirection) -> float:
        return super().get_margin_remaining(portfolio, security, direction)

    def get_initial_margin_requirement(self,
         parameters: InitialMarginParameters) -> InitialMargin:
        return super().get_initial_margin_requirement(parameters)

    def has_sufficient_buying_power_for_order(self,
         parameters: HasSufficientBuyingPowerForOrderParameters
        ) -> HasSufficientBuyingPowerForOrderResult:
        return super().has_sufficient_buying_power_for_order(parameters)

    def get_maximum_order_quantity_for_delta_buying_power(self,
         parameters: GetMaximumOrderQuantityForDeltaBuyingPowerParameters
        ) -> GetMaximumOrderQuantityResult:
        return super().get_maximum_order_quantity_for_delta_buying_power(parameters)

    def get_maximum_order_quantity_for_target_buying_power(self,
         parameters: GetMaximumOrderQuantityForTargetBuyingPowerParameters
        ) -> GetMaximumOrderQuantityResult:
        return super().get_maximum_order_quantity_for_target_buying_power(parameters)

    def get_reserved_buying_power_for_position(self,
         parameters: ReservedBuyingPowerForPositionParameters
        ) -> ReservedBuyingPowerForPosition:
        return super().get_reserved_buying_power_for_position(parameters)

    def get_buying_power(self,
         parameters: BuyingPowerParameters) -> BuyingPower:
        return super().get_buying_power(parameters)
```

### Example 3: Size Option Spreads to Buying Power

The following algorithm sells a weekly SPY bull put spread. Before it places the spread, it checks the buying power for quantities from 20 down to 1. It places the largest quantity that the portfolio can afford.

```python
class SizeOptionSpreadAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(10000)
        self._spy = self.add_equity("SPY", data_normalization_mode=DataNormalizationMode.RAW).symbol
        option = self.add_option("SPY")
        option.set_filter(lambda universe: universe.include_weeklys().puts_only().strikes(-10, 0).expiration(0, 7))
        self._option = option.symbol

    def on_data(self, slice: Slice) -> None:
        # Sell the shares of an assignment.
        if self.portfolio[self._spy].invested:
            self.liquidate(self._spy)
            return
        chain = slice.option_chains.get(self._option)
        if self.portfolio.invested or not chain:
            return
        expiry = max(x.expiry for x in chain)
        strikes = sorted({x.strike for x in chain if x.expiry == expiry}, reverse=True)
        if len(strikes) < 6:
            return
        strategy = OptionStrategies.bull_put_spread(self._option, strikes[0], strikes[5], expiry)
        for quantity in range(20, 0, -1):
            requests = self.order_factory.option_strategy_order(strategy, quantity)
            orders = [Order.create_order(request) for request in requests]
            if self.portfolio.has_sufficient_buying_power_for_order(orders).is_sufficient:
                self.order(requests)
                return
```

### Other Examples

For more examples, see the following algorithms:

**Demonstration Algorithms**

- [CustomBuyingPowerModelAlgorithm.py](https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/CustomBuyingPowerModelAlgorithm.py) (Python)
- [CustomModelsAlgorithm.py](https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/CustomModelsAlgorithm.py) (Python)
- [NullBuyingPowerOptionBullCallSpreadAlgorithm.py](https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/NullBuyingPowerOptionBullCallSpreadAlgorithm.py) (Python)
