---
title: "Key Concepts"
description: "To give your backtests the most accurate fees, LEAN contains transaction fee models that model the fee structure of many popular brokerages."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/transaction-fees/key-concepts
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/transaction-fees/key-concepts.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/24%20Reality%20Modeling/04%20Transaction%20Fees/01%20Key%20Concepts
modified: 2026-10-29
index: https://www.quantconnect.com/llms.txt
---

# Key Concepts

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Reality Modeling > Transaction Fees > Key Concepts

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

## Introduction

Your orders incur a transaction fee when a brokerage fills them in the market. LEAN uses transaction fee models in backtesting to model the live trading fees you would incur with the strategy. Transaction fee models make backtest results more realistic. To give your backtests the most accurate fees, LEAN contains transaction fee models that model the fee structure of many popular brokerages.

## Set Models

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

```python
def initialize(self):
    security = self.add_equity("SPY")
    # Set the fee model for the requested security to backtest with the most realistic scenario
    # Constant fee model of 0 dollar is accurate for the commission-free brokerage
    security.set_fee_model(ConstantFeeModel(0))
```

You can also set the fee model in a [security initializer](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#07-Set-Security-Initializer). If your algorithm has a dynamic 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_fee_model(ConstantFeeModel(0))
```

In live trading, the `set_fee_model` method isn't ignored. If we use order helper methods like `set_holdings`, the fee model helps to calculate the order quantity. However, the algorithm doesn't update the [cash book](https://www.quantconnect.com/docs/v2/writing-algorithms/portfolio/cashbook.md) with the fee from the fee model. The algorithm uses the actual fee from the brokerage to update the cash book.

To view all the pre-built fee models, see [Supported Models](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/transaction-fees/supported-models.md).

## Default Behavior

The brokerage model of your algorithm automatically sets the fill model for each security. The default brokerage model is the `DefaultBrokerageModel`, which set the [ConstantFeeModel](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/transaction-fees/supported-models.md#02-Constant-Model) with no fees for Forex, CFD, and Crypto assets and sets the [InteractiveBrokersFeeModel](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/transaction-fees/supported-models.md#13-Interactive-Brokers-Model) for the remaining asset classes.

## Model Structure

Fee models should extend the `FeeModel` class. Extensions of the `FeeModel` class must implement the `get_order_fee` method, which receives `OrderFeeParameters` and returns an `OrderFee` that represents a cash amount in a currency.

```python
class CustomFeeModelExampleAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        # In the Initialize method, set the custom fee model for an added security to use the custom model
        security = self.add_equity("SPY")
        security.set_fee_model(MyFeeModel())

# Define the custom fee model
class MyFeeModel(FeeModel):

    def get_order_fee(self, parameters: OrderFeeParameters) -> OrderFee:
        return OrderFee(CashAmount(0.5, 'USD'))
```

The `OrderFeeParameters` object has the following members:

*Members of `QuantConnect.Orders.Fees.OrderFeeParameters` (JSON): https://www.quantconnect.com/services/inspector?type=T:QuantConnect.Orders.Fees.OrderFeeParameters&language=python*

## Estimate Fees

To estimate the modeled fee of an order before you place it, 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 with the `Order.create_order` method. Then pass the order and its security to the fee model of the security. The conversion doesn't submit the order.

```python
security = self.securities[self._symbol]
request = self.order_factory.limit_order(self._symbol, 100, limit_price)
order = Order.create_order(request)
fee = security.fee_model.get_order_fee(OrderFeeParameters(security, order)).value
self.debug(f"Estimated fee: {fee.amount} {fee.currency}")
```

The estimate is a modeled fee. The fee model calculates it inside your algorithm with the current order and security values. In live trading, LEAN doesn't request the estimate from the brokerage. The fee that the brokerage charges can differ from the modeled fee, especially if the fee depends on the fill price or the fill quantity. To place the order after the estimate, pass the same request to the `order` method.

## Zero Transaction Fees

To model zero transaction fees, use the [ConstantFeeModel](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/transaction-fees/supported-models.md) with zero as `fee` and specify the `currency`.

```python
def initialize(self):
    security = self.add_equity("SPY")
    security.set_fee_model(ConstantFeeModel(fee=0, currency="USD"))
```

## Negative Transaction Fees

If you short a security and receive interest payments, they are negative transaction fees.

## Examples

The following examples demonstrate common practices for implementing custom fee models and estimating fees.

### Example 1: Fixed Fees

The following algorithm incurs a $0.50 fee for each order.

```python
class CustomFeeModelAlgorithm(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_fee_model(MyFeeModel())

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

class MyFeeModel(FeeModel):

    def get_order_fee(self, parameters: OrderFeeParameters) -> OrderFee:
        return OrderFee(CashAmount(0.5, 'USD'))
```

### Example 2: Buy When Fees Are Low

The following algorithm saves $100 each week to buy SPY. Interactive Brokers charges at least $1 for each order, so small orders are expensive. Each week, the algorithm estimates the fee of an order with its savings. It places the order only when the fee is 0.1% of the order value or less.

```python
class EstimateFeesAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2024, 1, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(5000)
        self.set_brokerage_model(BrokerageName.INTERACTIVE_BROKERS_BROKERAGE, AccountType.MARGIN)
        self._spy = self.add_equity("SPY", Resolution.DAILY).symbol
        self._weeks = 0
        self.schedule.on(self.date_rules.week_start(self._spy), self.time_rules.after_market_open(self._spy, 30), self._buy)

    def _buy(self) -> None:
        self._weeks += 1
        security = self.securities[self._spy]
        if not security.price:
            return
        quantity = int(self._weeks * 100 / security.price)
        if not quantity:
            return
        request = self.order_factory.market_order(self._spy, quantity)
        # Estimate the fee without submitting the order.
        fee = security.fee_model.get_order_fee(OrderFeeParameters(security, Order.create_order(request))).value.amount
        if fee <= 0.001 * quantity * security.price:
            self.order(request)
            self._weeks = 0
```

### Other Examples

For more examples, see the following algorithms:

**Demonstration Algorithms**

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