Strategy Classes
A strategy class encapsulates one trading strategy as an object with well-defined lifecycle methods (such as on_data, on_signal and on_fill) and its own state, so the strategy logic is isolated from data handling, risk and execution, and can be tested and reused independently.
Quick Answer
A strategy class packages one system's state and rules behind lifecycle hooks the engine calls on each event, such as on_data and on_fill. Because it only decides and never places raw orders, you can unit-test it with scripted events and no broker. The same object then runs a backtest and live unchanged.
Definition: Strategy Classes
Strategy Classes are objects that package one trading system's state and decision logic behind lifecycle methods such as on_data and on_fill, isolating decisions from execution.
Key takeaways: Strategy Classes
- A strategy class bundles one strategy's state and logic behind lifecycle methods like on_data, on_signal and on_fill
- Separate the strategy's decisions from data, sizing, risk and execution concerns
- The engine calls the lifecycle methods; the strategy only implements reactions (inversion of control)
- This structure makes strategies unit-testable with synthetic events and no broker
- One strategy class driven identically in backtest and live removes a whole class of discrepancies
Strategy Classes at a glance
| Subject | One strategy encapsulated as an object |
|---|---|
| Lifecycle hooks | on_data, on_signal, on_fill, on_stop |
| Owns | Decision logic and its own state |
| Delegates | Sizing, risk and execution to shared engines |
| Payoff | Same object runs backtest and live |
| Testability | Feed scripted events, assert intentions |
| Failure mode | Placing broker orders inside the class |
Strategy Classes in simple words
A strategy class is a way to package one trading strategy as a self-contained object, with methods that get called at key moments: when new data arrives, when a signal fires, and when an order is filled. Keeping the strategy's decision logic separate from the plumbing that fetches data and sends orders makes the code easier to understand, test and reuse. It mirrors how event-driven backtesters and live engines are built, so the same strategy can run in both.
What Strategy Classes is for
Strategy classes exist to separate the concern of deciding what to trade from the concerns of data, risk and execution, giving a testable, reusable unit that behaves identically in backtesting and live trading.
Strategy Classes — professional explanation
Why a class, not a script
A trading strategy has state (current position, indicators, pending orders, parameters) and behaviour (how it reacts to each new piece of information). A class is the natural way to bundle that state and behaviour together, so each strategy instance carries its own configuration and running state without leaking global variables. This makes it trivial to run several strategies or several parameter sets side by side, each an independent object, and it prevents the tangled global state that plagues strategy code written as a flat script. The class becomes a clean unit you can instantiate, configure, test and drop into either a backtester or a live engine.
Lifecycle methods: the event interface
The core design is a small, well-defined set of lifecycle methods that the surrounding engine calls as events occur. A typical set is: an initialise or on_start hook to set up indicators and state; on_data (or on_bar/on_tick) called for each new market data event, where the strategy updates indicators and may decide to act; on_signal where a raw signal is turned into an intended order (often after sizing and risk checks elsewhere); on_fill (or on_order) called when an order is acknowledged, partially or fully filled, so the strategy can update its position and pending state; and an on_stop or finalise hook for end-of-session cleanup. The engine owns the loop and calls these methods; the strategy only implements the reactions. This inversion of control is what lets the identical strategy object run in a backtest (events replayed from history) and live (events from a real feed).
Separation of concerns
The strategy class should decide, not execute. It answers what and when, and hands off the how to other components: a data layer provides clean, aligned bars; a position-sizing and risk engine translate an intention into a permitted order size and veto anything that breaches limits; an execution or order-management component actually routes the order and reports back fills. Keeping these responsibilities out of the strategy class means the strategy contains only trading logic, which is what you want to test and reason about, while sizing, risk and execution are shared, hardened components reused across all strategies. A strategy that places raw broker orders directly, or that hard-codes its position size, has entangled concerns and is far harder to test and to keep safe.
State management and idempotency
Because lifecycle methods are called repeatedly, state discipline is critical. The class must track its position and pending orders accurately, avoid acting twice on the same signal, and remain consistent when a fill arrives out of order or an order is rejected. A common pattern is to keep an explicit state machine (flat, entering, long, exiting) and to make signal handling idempotent so a duplicate on_data call cannot double the position. Storing all mutable state on the instance (not in module globals) also makes the strategy resettable between backtest runs and safe to run in multiple instances.
Testability
The payoff of this structure is testability. Because the strategy is a class with a defined event interface and no hidden dependencies, you can unit-test it by constructing an instance and feeding it a scripted sequence of synthetic data and fill events, then asserting on the intentions it emits, with no broker, no network and no real data required. You can replay a deterministic historical sequence and check the exact orders produced (a form of golden-master or replay test), and you can inject a fake execution component to verify how the strategy reacts to partial fills or rejections. This is only possible because concerns are separated; a strategy tangled with live API calls cannot be tested this way.
Reuse across backtest and live
The strongest argument for the pattern is a single code path. If backtesting and live trading both drive the same strategy class through the same lifecycle methods, differing only in where events come from (replayed history versus a live feed) and where orders go (a simulator versus a broker), then what you tested is what you run. This eliminates a whole category of discrepancies where a strategy behaves differently in backtest and live because it was re-implemented for each. Frameworks like Backtrader and Zipline are built exactly this way, with a base Strategy class and next/handle_data style hooks that users override.
How Strategy Classes looks visually
Worked example: Strategy Classes
Illustrative example (Indian market)
Consider a Nifty mean-reversion strategy written as a class. In initialise it sets its parameters (lookback, entry z-score, one lot of 65) and creates a rolling window. Its on_data method is called for each one-minute bar, updates the window, computes a z-score, and if the score crosses the entry threshold while the strategy is flat, it emits an intended entry signal, it does not place a broker order directly. The engine passes that intention through the shared position-sizing and risk engine, which may cut or veto it, then to execution. When the order fills, on_fill is called and the class updates its position from flat to long. To test it, you instantiate the class, feed a hand-built sequence of bars that should trigger exactly one entry, and assert that precisely one entry intention was emitted and the position state is correct, with no broker involved. This is an illustrative structure, not a strategy recommendation.
In an NSE F&O context, the same strategy class can be replayed over historical Bank Nifty minute bars in a backtest and then run live during the 09:15 to 15:30 session, with only the event source and order sink swapped. Keeping lot-size (say 30 or 65 depending on the contract), STT/brokerage cost modelling and daily-loss limits in the shared risk layer, not in the strategy class, means one hardened risk component protects every strategy.
Advantages of Strategy Classes
- Encapsulates strategy state and logic in a clean, reusable, instantiable unit
- Lifecycle methods give a clear event interface shared by backtest and live engines
- Separation of concerns keeps strategy code focused on decisions, not plumbing
- Highly testable: feed synthetic events and assert on emitted intentions
- Multiple strategies or parameter sets run as independent objects without shared globals
Limitations of Strategy Classes
- Requires disciplined design; a poorly structured class re-tangles concerns
- The lifecycle abstraction adds a learning curve over a simple script
- State and idempotency bugs are easy to introduce if the state machine is sloppy
- Over-abstraction (too many hooks and layers) can obscure simple logic
- The pattern helps structure but does not by itself make a strategy profitable or correct
How professionals treat Strategy Classes
Professional and framework-grade systems universally structure strategies as classes with a lifecycle interface. A base Strategy class defines hooks (initialise, on_data/next, on_order, on_fill, on_stop) and the engine, whether backtest or live, drives instances through them, guaranteeing a single code path. Sizing, risk and execution are separate, shared, heavily tested components, so the strategy class contains only trading logic. Teams keep all mutable state on the instance, model the position as an explicit state machine, make signal handling idempotent, and unit-test each strategy by replaying scripted event sequences before it ever sees capital.
Common misconceptions about Strategy Classes
Misconception: A strategy class is the same as a backtesting framework.
Reality: But frameworks like Backtrader and Zipline are built around the strategy-class pattern: they provide a base Strategy class with lifecycle hooks you override. The pattern is the design idea; a framework is one implementation of an engine that drives such classes.
Misconception: A good strategy class makes a strategy profitable.
Reality: Good structure makes a strategy testable, maintainable and safe to run, but it says nothing about whether the underlying trading idea has an edge. Structure is necessary engineering discipline, not a source of profit.
Common mistakes with Strategy Classes
- Placing raw broker orders directly inside the strategy class, entangling execution with decision logic and breaking testability
- Hard-coding position size in the strategy instead of delegating to a shared sizing and risk engine
- Storing strategy state in module-level globals, so instances interfere and backtests cannot reset cleanly
- Acting on the same signal twice because signal handling is not idempotent, doubling the intended position
- Mishandling out-of-order or partial fills in on_fill, leaving the tracked position out of sync with reality
- Re-implementing the strategy separately for backtest and live, so the two behave differently
Strategy Classes: frequently asked questions
What is a strategy class in trading?
It is an object-oriented way to package one trading strategy, bundling its state (position, indicators, parameters) with behaviour exposed as lifecycle methods that an engine calls as events occur. It isolates trading logic from data, risk and execution, making the strategy reusable and testable.
What are lifecycle methods in a trading strategy?
They are the hooks the engine calls at defined moments: an initialise step, on_data (or on_bar/on_tick) for each market event, on_signal to turn a signal into an intended order, on_fill when an order is executed, and a finalise step. The strategy implements these reactions while the engine owns the loop.
Why should strategy logic be separated from execution?
So the strategy contains only decisions (what and when) while shared, hardened components handle sizing, risk and order routing (the how). This separation makes the strategy testable in isolation, lets one risk engine protect every strategy, and prevents dangerous entanglement of trading logic with live API calls.
How does structuring a strategy as a class improve testability?
Because the class exposes a clear event interface and has no hidden dependencies, you can construct an instance, feed it scripted synthetic data and fill events, and assert on the intentions it emits, with no broker or network. A strategy tangled with live API calls cannot be tested this way.
Why use the same strategy class for backtesting and live trading?
So that what you tested is what you run. If both modes drive the identical class through the same lifecycle methods, differing only in the event source and order sink, you eliminate discrepancies caused by re-implementing the strategy separately for each mode.
What is inversion of control in a strategy engine?
It means the engine, not the strategy, owns the main loop and calls the strategy's lifecycle methods when events occur, rather than the strategy calling the engine. This lets the same strategy object be driven by a backtest engine or a live engine without changing the strategy code.
Voice search: how people ask about Strategy Classes
Natural-language questions people ask about Strategy Classes.
What is a strategy class?
It is a way to package one trading strategy as an object, with methods that run when new data arrives, when a signal fires, and when an order fills, keeping the trading logic separate from the plumbing.
Why put a trading strategy in a class?
Because it bundles the strategy's state and logic in one reusable, testable unit and keeps it separate from data handling, risk and order placement, which makes the code easier to trust.
What are the main methods in a strategy class?
Usually an initialise step, an on-data method for each new bar or tick, an on-signal step, and an on-fill method for when orders execute, plus a cleanup step at the end.
Sources & references
- Ernest P. Chan, “Quantitative Trading: How to Build Your Own Algorithmic Trading Business”, 2nd ed., Wiley, 2021
- Robert Kissell, “The Science of Algorithmic Trading and Portfolio Management”, Academic Press (Elsevier), 2013
Published 10 July 2026. Educational content only — not investment advice. Markets and rules change; verify current conventions with SEBI, NSE/BSE and your broker.