Skip to main content

nautilus_common/messages/data/
response.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
16use std::{any::Any, sync::Arc};
17
18use nautilus_core::{Params, UUID4, UnixNanos};
19use nautilus_model::{
20    data::{
21        Bar, BarType, DataType, ForwardPrice, FundingRateUpdate, HasTsInit, OrderBookDelta,
22        OrderBookDepth10, QuoteTick, TradeTick,
23    },
24    identifiers::{ClientId, InstrumentId, Venue},
25    instruments::InstrumentAny,
26    orderbook::OrderBook,
27};
28use serde::{Deserialize, Serialize};
29
30use super::Payload;
31
32/// Trims `data` to the inclusive `[start, end]` window on `ts_init`.
33///
34/// When `start` is set, drops leading entries with `ts_init < start`; when `end`
35/// is set, drops trailing entries with `ts_init > end`. Empty payloads and
36/// absent bounds short-circuit. When the bounds do not overlap the payload
37/// (e.g. `start` after the last entry, or `end` before the first), `data` is
38/// cleared.
39pub(crate) fn trim_data_to_bounds<T: HasTsInit>(
40    data: &mut Vec<T>,
41    start: Option<UnixNanos>,
42    end: Option<UnixNanos>,
43) {
44    let data_len = data.len();
45    if data_len == 0 {
46        return;
47    }
48
49    let first_index = if let Some(start) = start {
50        let Some(i) = data
51            .iter()
52            .position(|item| item.ts_init().as_u64() >= start.as_u64())
53        else {
54            data.clear();
55            return;
56        };
57        i
58    } else {
59        0
60    };
61
62    let last_index = if let Some(end) = end {
63        let Some(i) = data
64            .iter()
65            .rposition(|item| item.ts_init().as_u64() <= end.as_u64())
66        else {
67            data.clear();
68            return;
69        };
70        i
71    } else {
72        data_len - 1
73    };
74
75    if first_index <= last_index {
76        data.drain(..first_index);
77        data.truncate(last_index - first_index + 1);
78    } else {
79        data.clear();
80    }
81}
82
83#[derive(Clone, Debug)]
84pub struct CustomDataResponse {
85    pub correlation_id: UUID4,
86    pub client_id: ClientId,
87    pub venue: Option<Venue>,
88    pub data_type: DataType,
89    pub data: Payload,
90    pub start: Option<UnixNanos>,
91    pub end: Option<UnixNanos>,
92    pub ts_init: UnixNanos,
93    pub params: Option<Params>,
94}
95
96impl CustomDataResponse {
97    /// Creates a new [`CustomDataResponse`] instance.
98    #[expect(clippy::too_many_arguments)]
99    pub fn new<T: Any + Send + Sync>(
100        correlation_id: UUID4,
101        client_id: ClientId,
102        venue: Option<Venue>,
103        data_type: DataType,
104        data: T,
105        start: Option<UnixNanos>,
106        end: Option<UnixNanos>,
107        ts_init: UnixNanos,
108        params: Option<Params>,
109    ) -> Self {
110        Self {
111            correlation_id,
112            client_id,
113            venue,
114            data_type,
115            data: Arc::new(data),
116            start,
117            end,
118            ts_init,
119            params,
120        }
121    }
122
123    /// Converts the response to a dyn Any trait object for messaging.
124    pub fn as_any(&self) -> &dyn Any {
125        self
126    }
127}
128
129#[derive(Clone, Debug, Serialize, Deserialize)]
130pub struct InstrumentResponse {
131    pub correlation_id: UUID4,
132    pub client_id: ClientId,
133    pub instrument_id: InstrumentId,
134    pub data: InstrumentAny,
135    pub start: Option<UnixNanos>,
136    pub end: Option<UnixNanos>,
137    pub ts_init: UnixNanos,
138    pub params: Option<Params>,
139}
140
141impl InstrumentResponse {
142    /// Converts to a dyn Any trait object for messaging.
143    pub fn as_any(&self) -> &dyn Any {
144        self
145    }
146
147    /// Creates a new [`InstrumentResponse`] instance.
148    #[expect(clippy::too_many_arguments)]
149    pub fn new(
150        correlation_id: UUID4,
151        client_id: ClientId,
152        instrument_id: InstrumentId,
153        data: InstrumentAny,
154        start: Option<UnixNanos>,
155        end: Option<UnixNanos>,
156        ts_init: UnixNanos,
157        params: Option<Params>,
158    ) -> Self {
159        Self {
160            correlation_id,
161            client_id,
162            instrument_id,
163            data,
164            start,
165            end,
166            ts_init,
167            params,
168        }
169    }
170}
171
172#[derive(Clone, Debug, Serialize, Deserialize)]
173pub struct InstrumentsResponse {
174    pub correlation_id: UUID4,
175    pub client_id: ClientId,
176    pub venue: Venue,
177    pub data: Vec<InstrumentAny>,
178    pub start: Option<UnixNanos>,
179    pub end: Option<UnixNanos>,
180    pub ts_init: UnixNanos,
181    pub params: Option<Params>,
182}
183
184impl InstrumentsResponse {
185    /// Converts to a dyn Any trait object for messaging.
186    pub fn as_any(&self) -> &dyn Any {
187        self
188    }
189
190    /// Creates a new [`InstrumentsResponse`] instance.
191    #[expect(clippy::too_many_arguments)]
192    pub fn new(
193        correlation_id: UUID4,
194        client_id: ClientId,
195        venue: Venue,
196        data: Vec<InstrumentAny>,
197        start: Option<UnixNanos>,
198        end: Option<UnixNanos>,
199        ts_init: UnixNanos,
200        params: Option<Params>,
201    ) -> Self {
202        Self {
203            correlation_id,
204            client_id,
205            venue,
206            data,
207            start,
208            end,
209            ts_init,
210            params,
211        }
212    }
213}
214
215#[derive(Clone, Debug)]
216pub struct BookResponse {
217    pub correlation_id: UUID4,
218    pub client_id: ClientId,
219    pub instrument_id: InstrumentId,
220    pub data: OrderBook,
221    pub start: Option<UnixNanos>,
222    pub end: Option<UnixNanos>,
223    pub ts_init: UnixNanos,
224    pub params: Option<Params>,
225}
226
227impl BookResponse {
228    /// Converts to a dyn Any trait object for messaging.
229    pub fn as_any(&self) -> &dyn Any {
230        self
231    }
232
233    /// Creates a new [`BookResponse`] instance.
234    #[expect(clippy::too_many_arguments)]
235    pub fn new(
236        correlation_id: UUID4,
237        client_id: ClientId,
238        instrument_id: InstrumentId,
239        data: OrderBook,
240        start: Option<UnixNanos>,
241        end: Option<UnixNanos>,
242        ts_init: UnixNanos,
243        params: Option<Params>,
244    ) -> Self {
245        Self {
246            correlation_id,
247            client_id,
248            instrument_id,
249            data,
250            start,
251            end,
252            ts_init,
253            params,
254        }
255    }
256}
257
258#[derive(Clone, Debug, Serialize, Deserialize)]
259pub struct BookDeltasResponse {
260    pub correlation_id: UUID4,
261    pub client_id: ClientId,
262    pub instrument_id: InstrumentId,
263    pub data: Vec<OrderBookDelta>,
264    pub start: Option<UnixNanos>,
265    pub end: Option<UnixNanos>,
266    pub ts_init: UnixNanos,
267    pub params: Option<Params>,
268}
269
270impl BookDeltasResponse {
271    /// Converts to a dyn Any trait object for messaging.
272    pub fn as_any(&self) -> &dyn Any {
273        self
274    }
275
276    /// Creates a new [`BookDeltasResponse`] instance.
277    #[expect(clippy::too_many_arguments)]
278    pub fn new(
279        correlation_id: UUID4,
280        client_id: ClientId,
281        instrument_id: InstrumentId,
282        data: Vec<OrderBookDelta>,
283        start: Option<UnixNanos>,
284        end: Option<UnixNanos>,
285        ts_init: UnixNanos,
286        params: Option<Params>,
287    ) -> Self {
288        Self {
289            correlation_id,
290            client_id,
291            instrument_id,
292            data,
293            start,
294            end,
295            ts_init,
296            params,
297        }
298    }
299}
300
301#[derive(Clone, Debug, Serialize, Deserialize)]
302pub struct BookDepthResponse {
303    pub correlation_id: UUID4,
304    pub client_id: ClientId,
305    pub instrument_id: InstrumentId,
306    pub data: Vec<OrderBookDepth10>,
307    pub start: Option<UnixNanos>,
308    pub end: Option<UnixNanos>,
309    pub ts_init: UnixNanos,
310    pub params: Option<Params>,
311}
312
313impl BookDepthResponse {
314    /// Converts to a dyn Any trait object for messaging.
315    pub fn as_any(&self) -> &dyn Any {
316        self
317    }
318
319    /// Creates a new [`BookDepthResponse`] instance.
320    #[expect(clippy::too_many_arguments)]
321    pub fn new(
322        correlation_id: UUID4,
323        client_id: ClientId,
324        instrument_id: InstrumentId,
325        data: Vec<OrderBookDepth10>,
326        start: Option<UnixNanos>,
327        end: Option<UnixNanos>,
328        ts_init: UnixNanos,
329        params: Option<Params>,
330    ) -> Self {
331        Self {
332            correlation_id,
333            client_id,
334            instrument_id,
335            data,
336            start,
337            end,
338            ts_init,
339            params,
340        }
341    }
342}
343
344#[derive(Clone, Debug, Serialize, Deserialize)]
345pub struct QuotesResponse {
346    pub correlation_id: UUID4,
347    pub client_id: ClientId,
348    pub instrument_id: InstrumentId,
349    pub data: Vec<QuoteTick>,
350    pub start: Option<UnixNanos>,
351    pub end: Option<UnixNanos>,
352    pub ts_init: UnixNanos,
353    pub params: Option<Params>,
354}
355
356impl QuotesResponse {
357    /// Converts to a dyn Any trait object for messaging.
358    pub fn as_any(&self) -> &dyn Any {
359        self
360    }
361
362    /// Creates a new [`QuotesResponse`] instance.
363    #[expect(clippy::too_many_arguments)]
364    pub fn new(
365        correlation_id: UUID4,
366        client_id: ClientId,
367        instrument_id: InstrumentId,
368        data: Vec<QuoteTick>,
369        start: Option<UnixNanos>,
370        end: Option<UnixNanos>,
371        ts_init: UnixNanos,
372        params: Option<Params>,
373    ) -> Self {
374        Self {
375            correlation_id,
376            client_id,
377            instrument_id,
378            data,
379            start,
380            end,
381            ts_init,
382            params,
383        }
384    }
385}
386
387#[derive(Clone, Debug, Serialize, Deserialize)]
388pub struct TradesResponse {
389    pub correlation_id: UUID4,
390    pub client_id: ClientId,
391    pub instrument_id: InstrumentId,
392    pub data: Vec<TradeTick>,
393    pub start: Option<UnixNanos>,
394    pub end: Option<UnixNanos>,
395    pub ts_init: UnixNanos,
396    pub params: Option<Params>,
397}
398
399impl TradesResponse {
400    /// Converts to a dyn Any trait object for messaging.
401    pub fn as_any(&self) -> &dyn Any {
402        self
403    }
404
405    /// Creates a new [`TradesResponse`] instance.
406    #[expect(clippy::too_many_arguments)]
407    pub fn new(
408        correlation_id: UUID4,
409        client_id: ClientId,
410        instrument_id: InstrumentId,
411        data: Vec<TradeTick>,
412        start: Option<UnixNanos>,
413        end: Option<UnixNanos>,
414        ts_init: UnixNanos,
415        params: Option<Params>,
416    ) -> Self {
417        Self {
418            correlation_id,
419            client_id,
420            instrument_id,
421            data,
422            start,
423            end,
424            ts_init,
425            params,
426        }
427    }
428}
429
430#[derive(Clone, Debug, Serialize, Deserialize)]
431pub struct FundingRatesResponse {
432    pub correlation_id: UUID4,
433    pub client_id: ClientId,
434    pub instrument_id: InstrumentId,
435    pub data: Vec<FundingRateUpdate>,
436    pub start: Option<UnixNanos>,
437    pub end: Option<UnixNanos>,
438    pub ts_init: UnixNanos,
439    pub params: Option<Params>,
440}
441
442impl FundingRatesResponse {
443    /// Converts to a dyn Any trait object for messaging.
444    pub fn as_any(&self) -> &dyn Any {
445        self
446    }
447
448    /// Creates a new [`FundingRatesResponse`] instance.
449    #[expect(clippy::too_many_arguments)]
450    pub fn new(
451        correlation_id: UUID4,
452        client_id: ClientId,
453        instrument_id: InstrumentId,
454        data: Vec<FundingRateUpdate>,
455        start: Option<UnixNanos>,
456        end: Option<UnixNanos>,
457        ts_init: UnixNanos,
458        params: Option<Params>,
459    ) -> Self {
460        Self {
461            correlation_id,
462            client_id,
463            instrument_id,
464            data,
465            start,
466            end,
467            ts_init,
468            params,
469        }
470    }
471}
472
473#[derive(Clone, Debug, Serialize, Deserialize)]
474pub struct ForwardPricesResponse {
475    pub correlation_id: UUID4,
476    pub client_id: ClientId,
477    pub venue: Venue,
478    pub data: Vec<ForwardPrice>,
479    pub ts_init: UnixNanos,
480    pub params: Option<Params>,
481}
482
483impl ForwardPricesResponse {
484    /// Creates a new [`ForwardPricesResponse`] instance.
485    pub fn new(
486        correlation_id: UUID4,
487        client_id: ClientId,
488        venue: Venue,
489        data: Vec<ForwardPrice>,
490        ts_init: UnixNanos,
491        params: Option<Params>,
492    ) -> Self {
493        Self {
494            correlation_id,
495            client_id,
496            venue,
497            data,
498            ts_init,
499            params,
500        }
501    }
502}
503
504#[derive(Clone, Debug, Serialize, Deserialize)]
505pub struct BarsResponse {
506    pub correlation_id: UUID4,
507    pub client_id: ClientId,
508    pub bar_type: BarType,
509    pub data: Vec<Bar>,
510    pub ts_init: UnixNanos,
511    pub start: Option<UnixNanos>,
512    pub end: Option<UnixNanos>,
513    pub params: Option<Params>,
514}
515
516impl BarsResponse {
517    /// Converts to a dyn Any trait object for messaging.
518    pub fn as_any(&self) -> &dyn Any {
519        self
520    }
521
522    /// Creates a new [`BarsResponse`] instance.
523    #[expect(clippy::too_many_arguments)]
524    pub fn new(
525        correlation_id: UUID4,
526        client_id: ClientId,
527        bar_type: BarType,
528        data: Vec<Bar>,
529        start: Option<UnixNanos>,
530        end: Option<UnixNanos>,
531        ts_init: UnixNanos,
532        params: Option<Params>,
533    ) -> Self {
534        Self {
535            correlation_id,
536            client_id,
537            bar_type,
538            data,
539            ts_init,
540            start,
541            end,
542            params,
543        }
544    }
545}