> For the complete documentation index, see [llms.txt](https://quantinfra.gitbook.io/quantinfra-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://quantinfra.gitbook.io/quantinfra-docs/strategies/implementing-strategies.md).

# Implementing strategies

## Basic principles

Strategies Service (during the live execution) or the backtesting engine hosts one or several strategies. Strategies have three inputs:

* Market data state (candles and indicators, order books)
* Account state (current orders, positions, and balances)
* Strategy state (an arbitrary state that must persist between the service restarts)

All states are initialized at startup and are later updated automatically, upon receiving certain events from other components (e.g., a tick from the Market Data Service or an execution report from the Accounts Service). All events are processed in a single thread.

When processing an event, the strategy issues orders that are forwarded for execution. When the order status changes or a trade is booked, the strategy will receive the corresponding event.

For the sake of throughput and low latency, strategies cannot request any historical data during the execution. All data must be pre-calculated and kept in one of the states. Strategies Service ensures that the required historical data is hydrated upon startup.

### Market data

The current version supports only time-aggregated candles (referred to as bars or bar storages) as market data. The next version will add support for ticks and order books.

#### Candles

Upon initialization, strategies must use ClaimBarStorage method to tell Strategies Service that it needs certain candles (usually, defined in the strategy config). AbstractSingleBarHostedStrategy and AbstractMultipleBarsHostedStrategy do this automatically for every bar storage defined in the config. Bar storages and indicators are shared among strategies.

Next, strategies derived from all classes need to call RegisterIndicator to define which indicators they use. Strategies Service then defines how much historical data is required for every bar storage, loads it, and hydrates the candles and indicators.

#### Best bid and offer (BBO)

Upon initialization, strategies must use ClaimBestBidOffer method. All changes to the BBO received from Market Data Service will invoke the strategy's callback named OnBestBidOfferUpdated.

#### Order books (L2)

Upon initialization, strategies must use ClaimOrderBook method. The current state of the order book will be retrieved from Market Data Service. Subsequent updates will be automatically applied to the state; the strategy's callback, named OnOrderBookUpdated, will be called.

### Account and strategy state

Every strategy runs on its own subaccount and does not see orders and positions from other strategies (even if several subaccounts run on a single broker account). The account and the strategy states are loaded on startup and later maintained by the Strategies Service. When a strategy callback is called (e.g., OnExecutionReport), the state is already updated.

A strategy state contains two properties:

* LastCalculationTs that may be used for deduplication (e.g., if after the restart of the Strategies Service the same historical market data is replayed).
* InternalState provides a persistent storage for the custom state (any POCO object)

## Base classes for the strategies

Every custom strategy must implement one of these base classes:

| AbstractHostedStrategy             | The most generic base class allowing you to control all aspects of a strategy                            |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------- |
| AbstractSingleBarHostedStrategy    | Simplified base class for strategies that trade only one contract and use one series of candles as input |
| AbstractMultipleBarsHostedStrategy | Simplified base class for strategies that use several inputs and trade one or multiple contracts         |

## Lifecycle of the strategy object

Generally, it is not guaranteed that the strategy object will not be recreated during execution. Hence, all internal fields within the class may be used only to store information that can be restored during hydration. Use the Internal State for the information that needs to be persisted.

1. When the Strategies Service starts, it instantiates all active strategies it will handle. At this moment, the constructor is called. You can instantiate indicators you need inside the constructor.
2. Immediately after that, OnInitialize method is called. Here, you can claim market data that your strategy needs.
3. Strategies Service loads the market data (candles) required by all strategies it hosts and hydrates the history automatically. Additionally, it loads the account and the strategy state. When this is done, the strategy’s OnDeployed method is called.
   1. Note, that during the hydration, market data callbacks of the strategy may be called. The hydration can be detected by the IsHistory flag of the StrategyCalculationContext set to true.
4. Upon receiving market data or account updates, Strategies Service will call the respective method of the strategy. See the section Callbacks for the list of available methods.

## Constructor

The only parameter passed to the constructor of all three classes is the strategy config.

Use the constructor to instantiate indicators that your strategy will use:

```csharp
public MoMacdExample(StrategyConfig config): base(config)
{
    _close = new Close();
    var momentum = new Momentum(_close, Params.MomentumPeriod);
    _acceleration = new Momentum(momentum, Params.MomentumPeriod);
    _emaSlow = new EMA(momentum, Params.EmaPeriod);
    _emaFast = new EMA(momentum, Params.EmaPeriod / 3);
}
```

### Strategy parameters

All base classes for strategies are generic types, and the type argument must be a POCO class that defines the strategy's parameters. The parameters parsed from the strategy config are available for the strategy in the Params property.

## Initialization

Override the method OnInitialize for strategies deriving from AbstractHostedStrategies, and OnInitialized for other base classes.

```csharp
protected override void OnInitialized(StrategyInitializationContext context)
{
    RegisterIndicator(_close, 1);
    RegisterIndicator(_emaSlow, 1);
    RegisterIndicator(_emaFast, 1);            
    RegisterIndicator(_acceleration);
}
```

During initialization, the following methods are available:

| Method                               | Description                                                                                                                                                                                                                                                                        |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| RequireAccountingMode                | Validate that the accounting mode (Hedged or Netted) is configured correctly for the account. Will throw an InvalidOperationException on Strategies Service startup otherwise.                                                                                                     |
| ClaimHeartbeats                      | OnHeartbeat callback will be invoked once a second during the execution.                                                                                                                                                                                                           |
| ClaimBarStorage                      | <p>Registers a shared bar storage.<br>If called, the callback OnBarClosed will be call once the respective bar closes.</p>                                                                                                                                                         |
| BarStoragesProvider.CreateBarStorage | Creates a new bar storage that is not shared with other strategies and is not hydrated or maintained automatically. The strategy must subscribe to minute bars or ticks via ClaimExchangeBars/ClaimTicks and add each bar to created storage in the OnExchangeBar/OnTick callback. |
| ClaimExchangeBars                    | If called, the OnExchangeBar callback will be invoked once a 1-minute bar for the specified contract or stream closes.                                                                                                                                                             |
| ClaimContract                        | For strategies implementing AbstractHostedStrategy, this must be called for every contract the strategy trades. For strategies deriving from other classes, this is done automatically for every symbol from the strategy config.                                                  |
| RegisterIndicator                    | <p>Apply some indicator the shared bar storage. Requires bar storage to be initialized by ClaimBarStorage first.<br><br>For non-shared bar storages, register required indicators by calling the respective method of the bar storage object, returned by CreateBarStorage.</p>    |
| ClaimOrderBook                       | Subscribe to the L2 order book of the provided contract. OnOrderBookUpdated callback will be invoked during the execution.                                                                                                                                                         |
| ClaimBestBidOffer                    | Subscribe to the updates of BBO of the provided contract. OnBestBidOfferUpdated callback will be invoked during the execution.                                                                                                                                                     |

### Bar storages

Bar storage provides access to the time- and volume-aggregated candles for a stream or a contract.

The capacity of the bar storage (i.e., how many historical bars are available) is defined by the corresponding parameter in ClaimBarStorage/CreateBarStorage. When using shared bar storage created by ClaimBarStorage, the actual capacity may be larger (if requested by another strategy or indicator).

The bars in the bar storage are sorted in descending order: BarStorage\[0] (or BarStorage.CurrentBar) is the last bar, BarStorage\[1] is the second, and so on.

Bar storage configuration: [described here](/quantinfra-docs/strategies/strategy-configuration.md#bar-storage-candles-configuration).

### Indicators

A strategy may use predefined or custom indicators.

Indicators can be nested:

```csharp
public MoMacdExample(StrategyConfig config): base(config)
{
    _close = new Close();  // Use the close price of the bar as base
    var momentum = new Momentum(_close, Params.MomentumPeriod); // Apply momentum on the close price
    _acceleration = new Momentum(momentum, Params.MomentumPeriod); // Apply momentum on the momentum
    _emaSlow = new EMA(momentum, Params.EmaPeriod); // Apply exponential moving average on the momentum
    _emaFast = new EMA(momentum, Params.EmaPeriod / 3);
}
```

The Lookback parameter specifies how many historical bars the strategy requires for this indicator. For instance, if you need to know the average only of the current bar, call RegisterIndicator(\_avg, 0). If you need the average from 5 bars ago, call RegisterIndicator(\_avg, 5).

Note that this is different from the number of bars required to calculate the indicator itself. In the example above, the rolling window for \_avg may be any value. The current bar (with the index 0) will contain the average calculated for the defined window (Bar\[0] — Bar\[N]), and the 5th bar (with the index 5) will contain the average calculated over the window (Bar\[5] — Bar\[5 + N]).

If during execution you try to access a value of an indicator outside the lookback window, an exception will be thrown. |

Later, the indicator’s value can be retrieved as follows:

```csharp
var currentBarClose = _close.GetValue(BarStorages[0]); // Get close value of the last bar
var prevHigh = _high.GetValue(BarStorages[1]); // Get close value of the previous bar. Note this requires setting lookback to 1 when registering the indicator.
```

Strategies Service (and the backtester) hydrates the bar storages so that as of the moment of deploying the strategies (or starting the backtest), all requested indicators have initialized values. For instance, if you use EMA(EMA(5), 5), 9 bars will be automatically hydrated at startup.

### Initialization context

When OnInitialize / OnInitialized methods are called, an instance of StrategyInitializationContext is passed as an argument. It gives access to the base information about the account and to the static data provider.

## Hydration of historical data

Once all strategies have requested market data, Strategies Service automatically loads it. During hydration, the market data callbacks for strategies will be invoked. Unless your strategy uses its own bar storages (created by calling BarStoragesProvider.CreateBarStorage), the processing can be omitted:

```csharp
protected override bool OnBarClosed(string barQualifier, StrategyCalculationContext context)
{
	if (context.IsHistory) return;

	// Logic goes here
}
```

## Available properties and methods

AbstractHostedStrategy\<T> provides the following helper properties and methods:

<table><thead><tr><th width="254.24609375">Name</th><th>Description</th></tr></thead><tbody><tr><td>StrategyConfig</td><td>Configuration parameters for this strategy object instance</td></tr><tr><td>StrategyId</td><td></td></tr><tr><td>BestBidOfferProvider</td><td>Gives access to the current state of BBOs</td></tr><tr><td>Logger</td><td>Default strategy logger (named "Strategy.{StrategyId}"</td></tr><tr><td>LoggerFactory</td><td>Logger factory that can be used to instantiate custom loggers</td></tr><tr><td>UsedContractIds</td><td>Hash set of contract IDs that are available for the strategy</td></tr><tr><td>BarStoragesByName</td><td>A dictionary that provides access to the shared bar storages.<br><br>For strategies deriving from AbstractSingleBarHostedStrategy / AbstractMultipleBarsHostedStrategy, the name corresponds to the friendly name of the contract in the strategy config:<br><br>StrategyConfig: { ..., Symbols: { "main": 10000 }, ... }<br>Strategy code: BarStoragesByName["main"].CurrentBar</td></tr><tr><td>GetOrderBook()</td><td>Get the current state of the order book by contract id or by the friendly name</td></tr><tr><td>GetBestBidOffer()</td><td>Get the last BBO by contract id or by the friendly name</td></tr></tbody></table>

## Callbacks

### Strategy Calculation Context

When any of the callbacks mentioned below are called, an instance of StrategyCalculationContext is passed as an argument. It gives access to the current strategy and account state and must be used for placing orders:

| Property       | Description                                                                                                                                         |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| StrategyRecord | Strategy config and status                                                                                                                          |
| StrategyState  | Contains LastCalculationTs and the persistent strategy state. Use the extension method StrategyState.GetInternalState to retrieve the parsed state. |
| Strategy       | Use it to update LastCalculationTs or the persistent state.                                                                                         |
| AccountRecord  | Basic account configuration                                                                                                                         |
| AccountState   | Account balances, orders, and positions                                                                                                             |
| Account        | May be used for placing orders, though using the strategy base class helpers is recommended                                                         |
| ReferenceDt    | The timestamp of the currently processed event (e.g., the close time of a closed bar)                                                               |
| GetContract()  | Used to retrieve the contract configuration                                                                                                         |
| IsHistory      | Set to true during the hydration of historical data                                                                                                 |

### OnDeployed

Called upon the start of the Strategies Service, when all market data is hydrated, and the account and the strategy states are retrieved.

### OnHeartbeat

Called once a second. Requires a subscription to be made during initialization by calling ClaimHeartbeats().

### Market data callbacks

If your strategy needs to process market data, implement these callbacks:

| Method                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OnExchangeBar         | When 1-minute bar for some contract closes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| OnBarClosed           | When one of the aggregated bars requested by the strategy has closed. Use only inside the strategies derived directly from AbstractHostedStrategy.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| Calculate             | <p>This method is available only for strategies deriving AbstractSingleBarHostedStrategy and AbstractMultipleBarsHostedStrategy.<br><br>For the former, it is called once the aggregated bar used by the strategy is closed. <br><br>For the latter, it is called once all aggregated bars used by the strategy are closed at the same moment. For example, if your strategy uses 2 time series: 30 minutes and 2 hours, the method will be called once every 2 hours. If the strategy uses 1-hour candles for several contracts, the method is called once an hour, when all aggregates are calculated. <br><br>Remember that all events are processed sequentially in a single thread, so closing several aggregates requires several sequential events.</p> |
| OnOrderBookUpdated    | On every update of the L2 order book. The order book state available through GetOrderBook() contains the updated state.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| OnBestBidOfferUpdated | On every BBO update                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |

### Execution callbacks

| Method              | Description                                                                                                          |
| ------------------- | -------------------------------------------------------------------------------------------------------------------- |
| OnExecutionReport   | When the status of an order changes                                                                                  |
| OnTrade             | When a trade is booked                                                                                               |
| OnEndOfDay          | When the account is marked to market at the end of day                                                               |
| OnInvestmentChanged | When the [investment](/quantinfra-docs/balances-and-investment.md#investment-and-share-count) of the account changes |

## Methods and helpers

| Method        | Description                                                                                                                              |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| NewOrder      | <p>Places a new order to the account.<br><br>May throw an <code>ArgumentException</code> or <code>NewOrderException</code> .</p>         |
| CancelOrder   | <p>Requests cancellation of an existing order.<br><br>Throws <code>InvalidOperationException</code> in case the order doesn’t exist.</p> |
| ReplaceOrder  | <p>Requests a replace of an existing order.<br><br>Throws <code>InvalidOperationException</code> in case the order doesn’t exist.</p>    |
| OpenPosition  | Places a new order of the specified type to open the position. Additionally, may place a stop-loss and a take-profit.                    |
| ClosePosition | Places a new market order to close the position.                                                                                         |
| GetContractId | Returns the ID of the contract by its internal name (the key in StrategyConfig.Symbols)                                                  |
| GetVolume     | Returns the trade volume for the contract calculated based on the current price and the account investment                               |

### Extension methods

StrategyCalculationContext.AccountState.Orders and AccountState.Positions provide the following extension methods to search for orders and positions:

| Method                   | Description                               |
| ------------------------ | ----------------------------------------- |
| GetOrder                 | Search for an order by ClOrdId or OrderId |
| GetOrdersByContractId    | Get all active orders for a contract      |
| GetPosition              | Search for an existing position           |
| GetPositionsByContractId | Get all positions for a contract          |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://quantinfra.gitbook.io/quantinfra-docs/strategies/implementing-strategies.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
