# Implementing Custom Fee Models in Backtesting Frameworks: A QuantConnect Guide

> Learn to implement custom fee models in QuantConnect backtesting. Inherit FeeModel, override GetOrderFee, and calculate transaction costs for accurate simulation. Enhance your trading strategies today.

- Repository: [Papers With Backtest/awesome-systematic-trading](https://github.com/paperswithbacktest/awesome-systematic-trading)
- Tags: how-to-guide
- Published: 2026-08-01

---

**Implement custom fee models in QuantConnect by inheriting from the `FeeModel` base class and overriding the `GetOrderFee` method to return calculated transaction costs wrapped in a `CashAmount` object.**

Implementing custom fee models in backtesting frameworks is essential for realistic performance attribution, as transaction costs can significantly erode strategy returns in live trading. The `paperswithbacktest/awesome-systematic-trading` repository demonstrates production-tested patterns for modeling commissions within QuantConnect's algorithm framework. This guide extracts the implementation details from the repository's systematic strategies to show you how to build parameterizable, currency-aware fee models that integrate seamlessly with your backtesting workflow.

## Understanding the FeeModel Abstraction

QuantConnect exposes transaction cost calculation through the abstract `FeeModel` base class, which requires a single method implementation to customize commission logic. The `GetOrderFee` method receives an `OrderFeeParameters` object containing the security instance and order details, and must return an `OrderFee` object wrapping a `CashAmount`. This architecture isolates fee calculation from strategy logic, allowing you to swap commission structures without modifying algorithm code. According to the repository source code, all custom implementations should inherit from `FeeModel` and override this specific method signature to ensure compatibility with the backtesting engine.

## Building a Reusable Custom Fee Model

### Create the Fee Model Class

Encapsulate your commission logic in a dedicated class that derives from `FeeModel`, implementing the required `GetOrderFee` method to calculate costs based on price, quantity, and your specific rate structure.

```python
from AlgorithmImports import *

class FixedCommissionFeeModel(FeeModel):
    """Applies a fixed commission rate (in basis points) to every order."""
    def __init__(self, rate_bps: float = 5.0):
        # Convert basis points to a decimal proportion (e.g., 5 bps → 0.00005)

        self._rate = rate_bps / 1_00_000

    def GetOrderFee(self, parameters: OrderFeeParameters) -> OrderFee:
        # fee = price × quantity × rate

        fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * self._rate
        return OrderFee(CashAmount(fee, "USD"))

```

### Parameterize Commission Rates

Store fee rates as class attributes or constructor parameters rather than hard-coding values, enabling you to test different commission structures without touching algorithm logic. The example above accepts `rate_bps` as a configurable parameter, converting basis points to decimal form for calculation. This pattern appears consistently throughout the repository, allowing strategies to specify different rates for various security types or broker assumptions.

### Handle Currency Correctly

Always return fees wrapped in a `CashAmount` object specifying the correct currency—typically `"USD"` for US equities or the security's quote currency for international assets. This prevents accounting errors where fees might be calculated in one currency but applied to an account denominated in another. The repository implementations consistently use `CashAmount(fee, "USD")` to ensure currency alignment with the security's pricing context.

## Attaching Fee Models to Securities

Attach your custom model to each security during the `Initialize` method using `SetFeeModel()`, ensuring every order execution uses your custom logic. This attachment must occur after adding the security to the algorithm but before any orders are placed.

```python
class MyStrategy(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2020, 1, 1)
        self.SetCash(1_000_000)
        
        # Add an equity and attach the custom fee model

        equity = self.AddEquity("SPY", Resolution.Daily)
        equity.SetFeeModel(FixedCommissionFeeModel(rate_bps=4.0))   # 4 bps

        
        # Add another security with the default 5 bps fee model

        another = self.AddEquity("EWJ", Resolution.Daily)
        another.SetFeeModel(FixedCommissionFeeModel())             # uses default 5 bps

```

## Real-World Examples from the Repository

The `awesome-systematic-trading` repository demonstrates these patterns across multiple strategy implementations. In [`static/strategies/value-factor-effect-within-countries.py`](https://github.com/paperswithbacktest/awesome-systematic-trading/blob/main/static/strategies/value-factor-effect-within-countries.py) (lines 42-46), a minimal custom fee model multiplies security price by order quantity and a fixed rate of 0.00005 (5 basis points), illustrating the essential pattern for simple commission structures.

Similarly, [`static/strategies/momentum-factor-effect-in-stocks.py`](https://github.com/paperswithbacktest/awesome-systematic-trading/blob/main/static/strategies/momentum-factor-effect-in-stocks.py) (lines 17-21) reuses the same `CustomFeeModel` pattern, reinforcing the repository's consistent approach to fee modeling. The implementation in [`static/strategies/short-term-reversal-in-stocks.py`](https://github.com/paperswithbacktest/awesome-systematic-trading/blob/main/static/strategies/short-term-reversal-in-stocks.py) shows how fee models integrate with different factor-based strategies, while [`static/strategies/fx-carry-trade.py`](https://github.com/paperswithbacktest/awesome-systematic-trading/blob/main/static/strategies/fx-carry-trade.py) demonstrates currency-agnostic usage for foreign exchange equities.

These examples collectively illustrate a modular approach where fee logic remains stateless aside from rate parameters, making models safe for parallel backtests and easy to tune for different broker fee schedules.

## Summary

- **Encapsulate fee logic** in a dedicated class inheriting from `FeeModel` with a deterministic `GetOrderFee` implementation to isolate transaction costs from strategy code.
- **Parameterize rates** via constructor arguments rather than hard-coding values, allowing flexible commission testing across different broker scenarios.
- **Use `CashAmount`** with the correct currency code to prevent accounting mismatches and ensure proper fee deduction from portfolio value.
- **Attach models early** by calling `SetFeeModel()` immediately after adding securities in `Initialize()` to ensure all orders use custom fee calculations.
- **Maintain consistency** across strategies by following the patterns demonstrated in the repository's Value Factor and Momentum Factor implementations.

## Frequently Asked Questions

### How do I implement a custom fee model in QuantConnect?

Create a class that inherits from `FeeModel` and override the `GetOrderFee` method to calculate your commission based on the `OrderFeeParameters` provided, then return an `OrderFee` object containing a `CashAmount`. Attach this model to individual securities using `security.SetFeeModel(CustomFeeModel())` within your algorithm's `Initialize` method.

### What parameters does the GetOrderFee method receive?

The `GetOrderFee` method receives an `OrderFeeParameters` object that includes the `Security` instance (providing access to current price) and the `Order` object (providing `AbsoluteQuantity` and other order details). You use these to calculate the notional value and apply your commission rate.

### Can I use different fee models for different securities in the same algorithm?

Yes, you can instantiate different fee model classes or the same class with different parameters for each security. Call `SetFeeModel()` on each security individually after adding it to the algorithm, as demonstrated in the repository's examples where SPY might use a 4 bps model while EWJ uses 5 bps.

### Why should I avoid random components in fee calculations?

Deterministic fees ensure your backtest results remain reproducible across multiple runs, which is critical for debugging strategy logic and comparing performance across different parameter sets. Only introduce stochastic cost elements if you are explicitly modeling variable costs like slippage or market impact, and even then, use seeded random generators for reproducibility.