nautilus_interactive_brokers/data_types.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//! Interactive Brokers subscription diagnostics delivered as custom data.
17
18use nautilus_core::UnixNanos;
19use nautilus_model::{
20 custom_data,
21 identifiers::{ClientId, InstrumentId},
22};
23
24/// A subscription receives no market data within its configured interval.
25///
26/// This is an inactivity signal, not evidence that the connection or market is closed.
27#[custom_data(pyo3, stub_module = "nautilus_trader.adapters.interactive_brokers")]
28pub struct InteractiveBrokersSubscriptionIdle {
29 /// The Nautilus data client identifier.
30 pub client_id: ClientId,
31 /// The subscribed instrument identifier.
32 pub instrument_id: InstrumentId,
33 /// The subscription kind, including the complete bar type for bar subscriptions.
34 pub subscription: String,
35 /// The configured interval without market data.
36 pub idle_timeout_secs: u64,
37 /// The last local receipt time, or `None` when no market data has arrived.
38 #[custom_data_field(serde)]
39 pub last_data_received_ns: Option<u64>,
40 /// The UNIX timestamp (nanoseconds) when inactivity is detected.
41 pub ts_event: UnixNanos,
42 /// The UNIX timestamp (nanoseconds) when the event is created.
43 pub ts_init: UnixNanos,
44}
45
46pub(crate) fn register_ib_custom_data() {
47 let _ = nautilus_model::data::ensure_custom_data_json_registered::<
48 InteractiveBrokersSubscriptionIdle,
49 >();
50}
51
52#[cfg(test)]
53mod tests {
54 use rstest::rstest;
55
56 use super::*;
57
58 #[rstest]
59 fn subscription_idle_round_trip_preserves_every_field() {
60 let event = InteractiveBrokersSubscriptionIdle {
61 client_id: ClientId::from("IB-DATA-17"),
62 instrument_id: InstrumentId::from("AAPL=STK.SMART"),
63 subscription: "trades".to_string(),
64 idle_timeout_secs: 17,
65 last_data_received_ns: Some(123),
66 ts_event: UnixNanos::from(456_u64),
67 ts_init: UnixNanos::from(789_u64),
68 };
69
70 let json = serde_json::to_string(&event).unwrap();
71 let restored: InteractiveBrokersSubscriptionIdle = serde_json::from_str(&json).unwrap();
72 assert_eq!(restored, event);
73 }
74}