nautilus_backtest/modules/mod.rs
1// -------------------------------------------------------------------------------------------------
2// Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3// https://nautechsystems.io
4//
5// Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6// You may not use this file except in compliance with the License.
7// You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Simulation module trait for extending backtesting with custom venue behaviors.
17
18pub mod fx_rollover;
19
20use ahash::AHashMap;
21pub use fx_rollover::FXRolloverInterestModule;
22use nautilus_common::cache::Cache;
23use nautilus_core::UnixNanos;
24use nautilus_execution::matching_engine::engine::OrderMatchingEngine;
25use nautilus_model::{
26 data::Data,
27 identifiers::{InstrumentId, Venue},
28 instruments::InstrumentAny,
29 types::{Currency, Money},
30};
31
32/// Read-only view of exchange state passed to simulation modules during processing.
33#[derive(Debug)]
34pub struct ExchangeContext<'a> {
35 /// The venue identifier.
36 pub venue: Venue,
37 /// The optional base currency for single-currency accounts.
38 pub base_currency: Option<Currency>,
39 /// All instruments registered on the exchange.
40 pub instruments: &'a AHashMap<InstrumentId, InstrumentAny>,
41 /// All matching engines, providing order book access.
42 pub matching_engines: &'a AHashMap<InstrumentId, OrderMatchingEngine>,
43 /// Read-only cache access for querying positions and other state.
44 pub cache: &'a Cache,
45}
46
47#[derive(Debug, Clone)]
48pub enum SimulationModuleAny {
49 FXRolloverInterest(FXRolloverInterestModule),
50}
51
52impl SimulationModule for SimulationModuleAny {
53 fn pre_process(&self, data: &Data) {
54 match self {
55 Self::FXRolloverInterest(module) => module.pre_process(data),
56 }
57 }
58
59 fn process(&self, ts_now: UnixNanos, ctx: &ExchangeContext) -> Vec<Money> {
60 match self {
61 Self::FXRolloverInterest(module) => module.process(ts_now, ctx),
62 }
63 }
64
65 fn log_diagnostics(&self) {
66 match self {
67 Self::FXRolloverInterest(module) => module.log_diagnostics(),
68 }
69 }
70
71 fn reset(&self) {
72 match self {
73 Self::FXRolloverInterest(module) => module.reset(),
74 }
75 }
76}
77
78impl From<SimulationModuleAny> for Box<dyn SimulationModule> {
79 fn from(value: SimulationModuleAny) -> Self {
80 match value {
81 SimulationModuleAny::FXRolloverInterest(module) => Box::new(module),
82 }
83 }
84}
85
86/// Trait for custom simulation modules that extend backtesting functionality.
87///
88/// Implementations can add specialized behavior such as rollover interest,
89/// market makers, price impact models, or other venue-specific simulation
90/// logic that runs alongside the core backtesting engine.
91///
92/// Modules use interior mutability (`Cell`/`RefCell`) for state since they
93/// are stored inside `SimulatedExchange` and invoked through shared references.
94pub trait SimulationModule {
95 /// Pre-processes market data before matching engine processing.
96 fn pre_process(&self, data: &Data);
97
98 /// Processes simulation logic at the given timestamp.
99 ///
100 /// Returns account balance adjustments to be applied by the exchange.
101 fn process(&self, ts_now: UnixNanos, ctx: &ExchangeContext) -> Vec<Money>;
102
103 /// Logs diagnostic information about the module's state.
104 fn log_diagnostics(&self);
105
106 /// Resets the module to its initial state.
107 fn reset(&self);
108}