---
title: "Event Handlers"
description: "Event handlers pass information to your strategy during algorithm execution, aiding in debugging complex algorithms."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/event-handlers
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/event-handlers.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/01%20Key%20Concepts/07%20Event%20Handlers
modified: 2026-10-28
index: https://www.quantconnect.com/llms.txt
---

# Event Handlers

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Key Concepts > Event Handlers

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

## Introduction

Event handlers are called during an algorithm execution to pass information to your strategy. Most of the events are not needed for simple strategies, but can be helpful for debugging issues in more complex algorithms.

## Data Events

```python
# Get data for a specific symbol to analyze its price movements or trading signals.
def on_data(self, slice: Slice) -> None:
    my_data = slice.get(self._symbol)

# Get split information to adjust holdings and calculations for the symbol.
def on_splits(self, splits: Splits) -> None:
    split = splits.get(self._symbol)

# Capture dividend events to account for income or adjust the strategy based on the dividend payout.
def on_dividends(self, dividends: Dividends) -> None:
    dividend = dividends.get(self._symbol)

# Track events when a security changes its ticker, allowing the algorithm to adapt to these changes.
def on_symbol_changed_events(self, symbol_changed_events: SymbolChangedEvents) -> None:
    symbol_changed_event = symbol_changed_events.get(self._symbol)

# Handle delisting events to manage the position or adjust the strategy when the symbol is delisted.
def on_delistings(self, delistings: Delistings) -> None:
    delisting = delistings.get(self._symbol)
```

The `on_data` method is the primary event handler for receiving financial data events to your algorithm. It is triggered sequentially at the point in time the data is available; in backtesting and live. For daily data, this means the event is processed at market close. In this method, all data for a given moment of time is grouped in a single event, including custom data types. This data is passed with the [Slice](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/timeslices.md) object.

When [fill-forward](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/requesting-data.md#05-Fill-Forward) is enabled for your asset, the OnData event handler will be called regularly even if there was no new data. This is the default behavior.

In backtesting, if your algorithm takes a long time to process a slice, the following slice objects queue up and the next event triggers when your algorithm finishes processing the current slice. In live trading, if your algorithm takes longer to process the current slice than the [time period](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/periods.md) that the slice spans, the next event triggers when your algorithm finishes processing the current slice, but the slice of the following event is the most recent slice. For example, say your algorithm consumes second resolution Crypto data but it takes your algorithm 3.5 seconds to process each slice. In backtesting, you'll get every slice. In live trading, if you deploy at 12:00:00 AM Coordinated Universal Time (UTC), you'll get the first slice at 12:00:01 AM UTC (spanning 12:00:00 AM UTC to 12:00:01 AM UTC) and you'll get the second slice at 12:00:04.5 AM UTC (roughly spanning 12:00:03 AM UTC to 12:00:04 AM UTC).

The `on_splits`, `on_dividends`, `on_symbol_changed_events`, and `on_delistings` event handlers provide data for their respective types in an isolated way. However, all of the data for these corporate actions is also available in the `Slice` in `on_data`.

To perform intensive computation before the market opens, use a [Scheduled Event](https://www.quantconnect.com/docs/v2/writing-algorithms/scheduled-events.md) or the [train](https://www.quantconnect.com/docs/v2/writing-algorithms/machine-learning/training-models.md#02-Train-Models) method.

For more information on the `Slice` object and OnData event, see [Handling Data](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/handling-data.md#03-Data-Events).

## Securities Changed Event

```python
# Log the universe changes.
def on_securities_changed(self, changes: SecurityChanges) -> None:
    for security in changes.added_securities:
        self.debug(f"{self.time}: Added {security.symbol}")

    for security in changes.removed_securities:
        self.debug(f"{self.time}: Removed {security.symbol}")

        if security.invested:
            self.liquidate(security.symbol, "Removed from Universe")
```

The `on_securities_changed` event notifies the algorithm when assets are added or removed from the universe. This can be due to changes in the [Universe constituents](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/key-concepts.md#06-Security-Changed-Events), [delisting](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/us-equity/corporate-actions.md#05-Delistings), contract expiration, or an explicit call to the [remove_security](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/requesting-data.md#07-Remove-Subscriptions) method.

The event is triggered immediately when the asset is removed from the universe; however the data feed for the asset may remain active if the algorithm has open orders.

For more information, see how to use [Security Changed Events](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/key-concepts.md#06-Security-Changed-Events).

## Order Events

```python
# Track filled orders and get the details of each fill.
def on_order_event(self, order_event: OrderEvent) -> None:
    order = self.transactions.get_order_by_id(order_event.order_id)
    if order_event.status == OrderStatus.FILLED:
        self.debug(f"{self.time}: {order.type}: {order_event}")

# Track Option assignment events to handle assigned Equity holdings.
def on_assignment_order_event(self, assignment_event: OrderEvent) -> None:
    self.log(str(assignment_event))
```

The `on_order_event` method notifies the algorithm of new orders, and changes in the order status such as fill events and cancelations. For options assignment events there is a dedicated event handler `on_assignment_order_event`.

In backtesting order events are triggered synchronously after the main data events. In live trading, order events are asynchronously as they occur. To avoid infinite loops, we recommend not to place orders in the OnOrderEvent.

For more information, see how to use [Order Events](https://www.quantconnect.com/docs/v2/writing-algorithms/trading-and-orders/order-events.md#02-Track-Order-Events).

## Brokerage Events

```python
# Track brokerage messages.
def on_brokerage_message(self, message: BrokerageMessageEvent) -> None:
    if message.type == BrokerageMessageType.RECONNECT:
        self.log(f"{self.time}: {message.type}: Message: {message.message}")

# Track brokerage disconnections and respond to connectivity interruptions.
def on_brokerage_disconnect(self) -> None:
    self.log(f"Brokerage disconnection detected at {self.time}")

 # Track brokerage reconnections to resume trading operations.
def on_brokerage_reconnect(self) -> None:
    self.log(f"Brokerage reconnected at {self.time}")
```

The `on_brokerage_disconnect` and `on_brokerage_reconnect` event handlers pass information to the algorithm about the brokerage connection status. This can be helpful for considering when to place a trade when a brokerage API is unreliable or under maintenance. The `on_brokerage_message` event handler provides information from the brokerages, including the disconnect and reconnect messages. Message content varies with each brokerage.

Brokerage events are triggered asynchronously in live trading, and are not created in backtesting.

## Margin Call Events

```python
# Track when remaining margin is low.
def on_margin_call_warning(self) -> None:
    self.log("Margin call warning, 5% margin remaining")

# Review and adjust liquidation orders in response to a margin call.
def on_margin_call(self, requests): -> List[SubmitOrderRequest]:
    # Modify order requests to choose what to liquidate.
    return requests
```

The `on_margin_call_warning` and `on_margin_call` event handlers provide information and control over how to reduce algorithm leverage when performance is poor.

The `on_margin_call_warning` method is called when there is less than 5% margin remaining to give you an opportunity to reduce leverage before an official margin call is performed by the brokerage. The `on_margin_call` event handler is passed a list of `SubmitOrderRequest` objects which will be executed on exiting the method.

Margin events are called before the data events are processed.

The following [demonstration](https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/MarginCallEventsAlgorithm.py) processes suggested orders and modifies the qualities to liquidate more than necessary and prevent a second margin call. For more information, see how to handle [Margin Calls](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/margin-calls.md).

## Warmup Finished Event

```python
# This event handler runs when the algorithm is done warming up.
def on_warmup_finished(self) -> None:
    pass # Done warming up.
```

The `on_warmup_finished` event handler runs once [initialization](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md) and [warm up](https://www.quantconnect.com/docs/v2/writing-algorithms/historical-data/warm-up-periods.md) is complete.

## Command Events

```python
# An event handler for receiving external commands.
def on_command(self, data):
    self.log(f'Got command at {self.time} with data: {data}')
    return True
```

The `on_command` event handler runs when you send external [commands](https://www.quantconnect.com/docs/v2/writing-algorithms/live-trading/commands.md) to your algorithm.

## End Of Algorithm Events

```python
# The final step after algorithm execution.
def on_end_of_algorithm(self) -> None:
    self.debug("Algorithm done")
```

The `on_end_of_algorithm` event handler is when the algorithm has finished executing as its final step. This event handler is helpful for performing final analysis, or saving algorithm state.

## Event Flow

When you deploy an algorithm, LEAN first calls the [initialize](https://www.quantconnect.com/docs/v2/writing-algorithms/initialization.md) method. In live mode, the engine loads your holdings and open orders from your brokerage account to add data subscriptions and populate the `securities`, `portfolio`, and `transactions` objects. LEAN receives the data from the subscriptions, synchronizes the data to create a [timeslice](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/timeslices.md), and then performs the following steps. Your algorithm can spend up to 10 minutes on each timeslice unless you call the [train](https://www.quantconnect.com/docs/v2/writing-algorithms/machine-learning/training-models.md) method.

1. If it's a backtest, check if there are [Scheduled Events](https://www.quantconnect.com/docs/v2/writing-algorithms/scheduled-events.md) in the past that didn't fire because there was no data between the previous [slice](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/time-modeling/timeslices.md) and the current slice. LEAN automatically creates a Scheduled Event to call the `on_end_of_day` method at the end of each day.
   In live mode, Scheduled Events occur in a separate thread from the algorithm manager, so they run at the correct time.
2. Update the algorithm time.
3. Update the `current_slice`.
4. Pass the `SymbolChangedEvents` to the `on_symbol_changed_events` method.
5. Cancel all open orders for securities that [changed their ticker](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/us-equity/corporate-actions.md#04-Symbol-Changes).
6. Add a `Security` object to the `securities` collection for each new security in the universe.
7. Update the `Security` objects with the latest data.
8. Update the `Cash` objects in the [CashBook](https://www.quantconnect.com/docs/v2/writing-algorithms/portfolio/cashbook.md) with the latest data.
9. Process [fill models](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/trade-fills/key-concepts.md) for non-market orders.
10. Submit market on open orders to liquidate Equity Option contracts if the underlying Equity has a [split warning](https://www.quantconnect.com/docs/v2/writing-algorithms/securities/asset-classes/us-equity/corporate-actions.md#02-Splits).
11. Process [margin calls](https://www.quantconnect.com/docs/v2/writing-algorithms/reality-modeling/margin-calls.md).
12. If it's time to settle [unsettled cash](https://www.quantconnect.com/docs/v2/writing-algorithms/portfolio/cashbook.md#03-Settled-vs-Unsettled-Cash), perform settlement.
13. Call the [on_securities_changed](https://www.quantconnect.com/docs/v2/writing-algorithms/universes/key-concepts.md#06-Security-Changed-Events) method with the latest security changes.
14. Apply dividends to the portfolio.
15. For securities that have a split warning, update their portfolio holdings and adjust their open orders to account for the split.
16. Update [consolidators](https://www.quantconnect.com/docs/v2/writing-algorithms/consolidating-data/getting-started.md) with the latest data.
17. Pass the `Dividends` to the `on_dividends` method.
18. Pass the `Splits` to the `on_splits` method.
19. Pass the `Delistings` to the `on_delistings` method.
20. Pass the `Slice` to the `on_data` method.
21. Perform [universe selection](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/universe-selection/key-concepts.md).
22. Pass the `Slice` to the `update` method of each [Alpha model](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/alpha/key-concepts.md).
23. Pass the `Insight` objects from the Alpha model to the [Portfolio Construction model](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/portfolio-construction/key-concepts.md).
24. Pass the `PortfolioTarget` objects from the Portfolio Construction model to each [Risk Management model](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/risk-management/key-concepts.md).
25. Pass the risk-adjusted `PortfolioTarget` objects from the Risk Management models to the [Execution model](https://www.quantconnect.com/docs/v2/writing-algorithms/algorithm-framework/execution/key-concepts.md).

When your algorithm stops executing, LEAN calls the `on_end_of_algorithm` [method](https://www.quantconnect.com/docs/v2/writing-algorithms/key-concepts/event-handlers.md#15-End-Of-Algorithm-Events).
