Skip to main content

nautilus_backtest/
data_iterator.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//! Static backtest replay using the shared ordered batch iterator.
17
18use nautilus_data::replay::DataIterator;
19use nautilus_model::data::{Data, DataBatch, DataRef};
20
21/// Multi-stream, time-ordered data iterator used by the backtest engine.
22#[derive(Debug, Default)]
23pub struct BacktestDataIterator {
24    iterator: DataIterator,
25}
26
27impl BacktestDataIterator {
28    /// Creates a new empty [`BacktestDataIterator`].
29    #[must_use]
30    pub fn new() -> Self {
31        Self {
32            iterator: DataIterator::new(),
33        }
34    }
35
36    /// Adds (or replaces) a named data stream.
37    ///
38    /// When `append_data` is true the stream gets lower priority on equal replay keys;
39    /// when false (prepend) it wins ties. Named replacements retain their original priority.
40    pub fn add_data(&mut self, name: &str, data: Vec<Data>, append_data: bool) {
41        self.iterator.add_data(name, data, append_data);
42    }
43
44    /// Adds (or replaces) a named typed data stream.
45    ///
46    /// Items are ordered by replay key before insertion. A batch that arrives out of order while
47    /// sharing its backing allocation with another view is copied once, so the shared allocation
48    /// is never reordered.
49    pub fn add_data_batch(&mut self, name: &str, data: DataBatch, append_data: bool) {
50        self.iterator.add_data_batch(name, data, append_data);
51    }
52
53    /// Removes a named data stream.
54    pub fn remove_data(&mut self, name: &str, complete_remove: bool) {
55        self.iterator.remove_data(name, complete_remove);
56    }
57
58    /// Sets the cursor of a named stream to `index` (0-based).
59    pub fn set_index(&mut self, name: &str, index: usize) {
60        self.iterator.set_index(name, index);
61    }
62
63    /// Resets all stream cursors to the beginning.
64    pub fn reset_all_cursors(&mut self) {
65        self.iterator.reset_all_cursors();
66    }
67
68    pub(crate) fn peek(&self) -> Option<DataRef<'_>> {
69        self.iterator.peek()
70    }
71
72    pub(crate) fn advance(&mut self) {
73        self.iterator.advance();
74    }
75
76    /// Returns the next market [`Data`] element across all streams in chronological order.
77    #[expect(clippy::should_implement_trait)]
78    pub fn next(&mut self) -> Option<Data> {
79        self.iterator.next()
80    }
81
82    /// Returns whether all streams have been fully consumed.
83    #[must_use]
84    pub fn is_done(&self) -> bool {
85        self.iterator.is_done()
86    }
87}