nautilus_model/python/identifiers/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//! Identifiers for the trading domain model.
17
18pub mod instrument_id;
19pub mod option_series_id;
20pub mod symbol;
21pub mod trade_id;
22
23use nautilus_core::python::to_pyvalue_err;
24use pyo3::{
25 prelude::*,
26 pyclass::CompareOp,
27 types::{PyString, PyTuple},
28};
29
30use crate::{
31 identifier_for_python,
32 identifiers::{InstrumentId, new_generic_spread_id, parse_generic_spread_id_legs},
33};
34
35identifier_for_python!(crate::identifiers::ActorId);
36identifier_for_python!(crate::identifiers::AccountId);
37identifier_for_python!(crate::identifiers::ClientId);
38identifier_for_python!(crate::identifiers::ClientOrderId);
39identifier_for_python!(crate::identifiers::ComponentId);
40identifier_for_python!(crate::identifiers::ExecAlgorithmId);
41identifier_for_python!(crate::identifiers::OrderListId);
42identifier_for_python!(crate::identifiers::PositionId);
43identifier_for_python!(crate::identifiers::StrategyId);
44identifier_for_python!(crate::identifiers::TraderId);
45identifier_for_python!(crate::identifiers::Venue);
46identifier_for_python!(crate::identifiers::VenueOrderId);
47
48/// Creates a generic spread instrument ID from `(instrument_id, ratio)` legs.
49///
50/// Sorts the legs by symbol and joins them with `GENERIC_SPREAD_ID_SEPARATOR`, formatting a
51/// positive ratio as `(ratio)symbol` and a negative ratio as `((ratio))symbol`. For example,
52/// `MSFT.NASDAQ` with ratio 1 and `AAPL.NASDAQ` with ratio -2 produce
53/// `((2))AAPL___(1)MSFT.NASDAQ`.
54///
55/// A leg symbol that contains the separator or ends with `_` produces an ID that does not parse
56/// back into the same legs.
57///
58/// # Errors
59///
60/// Returns an error if:
61/// - Fewer than two legs are given.
62/// - A ratio is zero or `i64::MIN`.
63/// - The legs have different venues.
64#[pyfunction]
65#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.model")]
66#[pyo3(name = "new_generic_spread_id")]
67#[expect(clippy::needless_pass_by_value)]
68pub fn py_new_generic_spread_id(
69 instrument_ratios: Vec<(InstrumentId, i64)>,
70) -> PyResult<InstrumentId> {
71 new_generic_spread_id(&instrument_ratios).map_err(to_pyvalue_err)
72}
73
74/// Parses a generic spread instrument ID into `(instrument_id, ratio)` legs.
75///
76/// Returns the legs in the order they appear in the symbol, with a negative ratio for each
77/// `((ratio))symbol` leg.
78///
79/// # Errors
80///
81/// Returns an error if `instrument_id` is not in the format `new_generic_spread_id` produces.
82#[pyfunction]
83#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.model")]
84#[pyo3(name = "generic_spread_id_to_list")]
85pub fn py_generic_spread_id_to_list(
86 instrument_id: InstrumentId,
87) -> PyResult<Vec<(InstrumentId, i64)>> {
88 parse_generic_spread_id_legs(&instrument_id).map_err(to_pyvalue_err)
89}