1// -------------------------------------------------------------------------------------------------
2// Copyright (C) 2015-2025 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// -------------------------------------------------------------------------------------------------
1516//! An `InstrumentStatus` data type representing a change in an instrument market status.
1718use std::{collections::HashMap, fmt::Display, hash::Hash};
1920use derive_builder::Builder;
21use nautilus_core::{UnixNanos, serialization::Serializable};
22use serde::{Deserialize, Serialize};
23use ustr::Ustr;
2425use super::GetTsInit;
26use crate::{enums::MarketStatusAction, identifiers::InstrumentId};
2728/// Represents an event that indicates a change in an instrument market status.
29#[repr(C)]
30#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Builder)]
31#[serde(tag = "type")]
32#[cfg_attr(
33 feature = "python",
34 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.model")
35)]
36pub struct InstrumentStatus {
37/// The instrument ID for the status change.
38pub instrument_id: InstrumentId,
39/// The instrument market status action.
40pub action: MarketStatusAction,
41/// UNIX timestamp (nanoseconds) when the status event occurred.
42pub ts_event: UnixNanos,
43/// UNIX timestamp (nanoseconds) when the struct was initialized.
44pub ts_init: UnixNanos,
45/// Additional details about the cause of the status change.
46pub reason: Option<Ustr>,
47/// Further information about the status change (if provided).
48pub trading_event: Option<Ustr>,
49/// The state of trading in the instrument.
50pub is_trading: Option<bool>,
51/// The state of quoting in the instrument.
52pub is_quoting: Option<bool>,
53/// The state of short sell restrictions for the instrument (if applicable).
54pub is_short_sell_restricted: Option<bool>,
55}
5657impl InstrumentStatus {
58/// Creates a new [`InstrumentStatus`] instance.
59#[allow(clippy::too_many_arguments)]
60pub fn new(
61 instrument_id: InstrumentId,
62 action: MarketStatusAction,
63 ts_event: UnixNanos,
64 ts_init: UnixNanos,
65 reason: Option<Ustr>,
66 trading_event: Option<Ustr>,
67 is_trading: Option<bool>,
68 is_quoting: Option<bool>,
69 is_short_sell_restricted: Option<bool>,
70 ) -> Self {
71Self {
72 instrument_id,
73 action,
74 ts_event,
75 ts_init,
76 reason,
77 trading_event,
78 is_trading,
79 is_quoting,
80 is_short_sell_restricted,
81 }
82 }
8384/// Returns the metadata for the type, for use with serialization formats.
85#[must_use]
86pub fn get_metadata(instrument_id: &InstrumentId) -> HashMap<String, String> {
87let mut metadata = HashMap::new();
88 metadata.insert("instrument_id".to_string(), instrument_id.to_string());
89 metadata
90 }
91}
9293// TODO: Revisit this
94impl Display for InstrumentStatus {
95fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96write!(
97 f,
98"{},{},{},{}",
99self.instrument_id, self.action, self.ts_event, self.ts_init,
100 )
101 }
102}
103104impl Serializable for InstrumentStatus {}
105106impl GetTsInit for InstrumentStatus {
107fn ts_init(&self) -> UnixNanos {
108self.ts_init
109 }
110}
111112////////////////////////////////////////////////////////////////////////////////
113// Tests
114////////////////////////////////////////////////////////////////////////////////
115#[cfg(test)]
116mod tests {
117use nautilus_core::serialization::Serializable;
118use rstest::rstest;
119120use super::*;
121use crate::data::stubs::stub_instrument_status;
122123#[rstest]
124fn test_to_string(stub_instrument_status: InstrumentStatus) {
125assert_eq!(stub_instrument_status.to_string(), "MSFT.XNAS,TRADING,1,2");
126 }
127128#[rstest]
129fn test_json_serialization(stub_instrument_status: InstrumentStatus) {
130let serialized = stub_instrument_status.as_json_bytes().unwrap();
131let deserialized = InstrumentStatus::from_json_bytes(serialized.as_ref()).unwrap();
132assert_eq!(deserialized, stub_instrument_status);
133 }
134135#[rstest]
136fn test_msgpack_serialization(stub_instrument_status: InstrumentStatus) {
137let serialized = stub_instrument_status.as_msgpack_bytes().unwrap();
138let deserialized = InstrumentStatus::from_msgpack_bytes(serialized.as_ref()).unwrap();
139assert_eq!(deserialized, stub_instrument_status);
140 }
141}