---
title: "Key Concepts"
description: "Volatility models measure the historical volatility of an asset. The historical volatility need not be the standard deviation of the asset prices."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/volatility/key-concepts
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/volatility/key-concepts.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/24%20Reality%20Modeling/09%20Options%20Models/02%20Volatility/01%20Key%20Concepts
modified: 2026-10-31
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 > Options Models > Volatility > Key Concepts

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

## Introduction

Volatility models measure the historical volatility of an asset. They are mostly used to calculate the volatility of the underlying security of an Option because the implied volatility of an Option contract needs an initial guess. The historical volatility doesn't need to be the standard deviation of the asset prices. The various volatility models in LEAN each have a unique methodology to calculate volatility.

LEAN also provides an indicator implementation of implied volatility. It provides higher flexibility on Option price model selection, [volatility modeling](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/pricing.md#97-What-Is-Volatility-Smile3F), and allows [IV smoothing](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/pricing.md#98-What-Is-Volatility-Smoothing3F) through call-put pair. For details, see [Implied Volatility](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/equity-options/greeks-and-implied-volatility/indicators.md#03-Implied-Volatility).

## Set Models

To set the volatility model of the underlying security of an Option, set the `VolatilityModel` property of the `Security` object. The volatility model can have a different resolution than the underlying asset subscription.

```python
def initialize(self) -> None:
    underlying_security = self.add_equity("SPY")
    # Usually, the historical and implied volatility is calculated using 30-day standard deviation of return
    underlying_security.volatility_model = StandardDeviationOfReturnsVolatilityModel(30)
```

You can also set the volatility 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 of underlying assets, 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 the volatility model
        if security.Type == SecurityType.EQUITY:
            security.volatility_model = StandardDeviationOfReturnsVolatilityModel(30)
```

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

## Default Behavior

The default underlying volatility model for Equity Options and Index Options is the [StandardDeviationOfReturnsVolatilityModel](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/volatility/supported-models.md#03-Standard-Deviation-of-Returns-Model) based on 30 days of daily resolution data. The default underlying volatility model for Future Options is the [NullVolatilityModel](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/volatility/supported-models.md#02-Null-Model).

## Model Structure

Volatility models should extend the `BaseVolatilityModel` class. Extensions of the `BaseVolatilityModel` class must have `update` and `get_history_requirements` methods and a `volatility` property. The `update` method receives `Security` and `BaseData` objects and then updates the `volatility`. The `get_history_requirements` method receives `Security` and `datetime` objects and then returns a list of `HistoryRequest` objects that represent the history requests to warm up the model. Volatility models receive data at each time step in the algorithm to update their state.

```python
class CustomVolatilityModelExampleAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        underlying_security = self.add_index("VIX")
        # Apply custom volatility model for specific underlyings, often they are synthetic products or with different market calendar
        underlying_security.set_volatility_model(MyVolatilityModel())

# Define the custom volatility model outside of the algorithm
class MyVolatilityModel(BaseVolatilityModel):
    volatility: float = 0

    def set_subscription_data_config_provider(self,
        subscription_data_config_provider: ISubscriptionDataConfigProvider) -> None:
        super().set_subscription_data_config_provider(subscription_data_config_provider)

    def update(self, security: Security, data: BaseData) -> None:
        pass

    def get_history_requirements(
            self,
            security: Security,
            utc_time: datetime | date,
            resolution: Resolution | None = None,
            bar_count: int = 0) -> list[HistoryRequest]:
        return list(super().get_history_requirements(security, utc_time, resolution, bar_count))
```

## Warm Up Models

To use your volatility model as the [inital guess for the implied volatility](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/options-models/pricing.md#96-What-Is-Implied-Volatility3F), warm up the volatility model of the underlying security. If you subscribe to all the Options in the `initialize` method, set a [warm-up period](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/warm-up-periods.md) to warm up their volatility models. The warm-up period should provide the volatility models with enough data to compute their values.

```python
def initialize(self) -> None:
    # For default 30-day SD of return as volatility, you need 30+1 trading day to warm up
    self.set_warm_up(30, Resolution.DAILY)

def on_data(self, slice: Slice) -> None:
    # Only take the warmed-up volatility value into account for accuracy issue
    if self.is_warming_up:
        return
```

If you have a dynamic universe of underlying assets and add Option contracts to your algorithm with the `add_option_contract`, `add_index_option_contract`, or `add_future_option_contract` methods, warm up the volatility model when the underlying asset enters your universe. We recommend you do this inside a [security initializer](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md#07-Set-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 and warm up the volatility model
        if security.type == SecurityType.EQUITY:  # Underlying asset type
            security.volatility_model = StandardDeviationOfReturnsVolatilityModel(30)
            trade_bars = self.history[TradeBar](security.symbol, 30, Resolution.DAILY)
            for trade_bar in trade_bars:
                security.volatility_model.update(security, trade_bar)
```

## Examples

The following examples demonstrate common practices for implementing a custom volatility model.

### Example 1: Default Model Wrapper

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

```python
class CustomVolatilityModelAlgorithm(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.volatility_model = MyVolatilityModel()

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

class MyVolatilityModel(BaseVolatilityModel):
    volatility: float = 0

    def set_subscription_data_config_provider(self,
        subscription_data_config_provider: ISubscriptionDataConfigProvider) -> None:
        super().set_subscription_data_config_provider(subscription_data_config_provider)

    def update(self, security: Security, data: BaseData) -> None:
        pass

    def get_history_requirements(
            self,
            security: Security,
            utc_time: datetime | date,
            resolution: Resolution | None = None,
            bar_count: int = 0) -> Iterable[HistoryRequest]:
        return super().get_history_requirements(security, utc_time, resolution, bar_count)
```

### Other Examples

For more examples, see the following algorithms:

**Demonstration Algorithms**

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