nautilus_model/ffi/instruments/
synthetic.rs1use std::{
17 ffi::c_char,
18 ops::{Deref, DerefMut},
19};
20
21use nautilus_core::{
22 ffi::{
23 cvec::CVec,
24 parsing::{bytes_to_string_vec, string_vec_to_bytes},
25 string::{cstr_as_str, str_to_cstr},
26 },
27 UnixNanos,
28};
29
30use crate::{
31 identifiers::{InstrumentId, Symbol},
32 instruments::synthetic::SyntheticInstrument,
33 types::{Price, ERROR_PRICE},
34};
35
36#[repr(C)]
46#[allow(non_camel_case_types)]
47pub struct SyntheticInstrument_API(Box<SyntheticInstrument>);
48
49impl Deref for SyntheticInstrument_API {
50 type Target = SyntheticInstrument;
51
52 fn deref(&self) -> &Self::Target {
53 &self.0
54 }
55}
56
57impl DerefMut for SyntheticInstrument_API {
58 fn deref_mut(&mut self) -> &mut Self::Target {
59 &mut self.0
60 }
61}
62
63#[no_mangle]
68pub unsafe extern "C" fn synthetic_instrument_new(
69 symbol: Symbol,
70 price_precision: u8,
71 components_ptr: *const c_char,
72 formula_ptr: *const c_char,
73 ts_event: u64,
74 ts_init: u64,
75) -> SyntheticInstrument_API {
76 let components = bytes_to_string_vec(components_ptr)
78 .into_iter()
79 .map(|s| InstrumentId::from(s.as_str()))
80 .collect::<Vec<InstrumentId>>();
81 let formula = cstr_as_str(formula_ptr).to_string();
82 let synth = SyntheticInstrument::new(
83 symbol,
84 price_precision,
85 components,
86 formula,
87 ts_event.into(),
88 ts_init.into(),
89 );
90
91 SyntheticInstrument_API(Box::new(synth))
92}
93
94#[no_mangle]
95pub extern "C" fn synthetic_instrument_drop(synth: SyntheticInstrument_API) {
96 drop(synth); }
98
99#[no_mangle]
100pub extern "C" fn synthetic_instrument_id(synth: &SyntheticInstrument_API) -> InstrumentId {
101 synth.id
102}
103
104#[no_mangle]
105pub extern "C" fn synthetic_instrument_price_precision(synth: &SyntheticInstrument_API) -> u8 {
106 synth.price_precision
107}
108
109#[no_mangle]
110#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
111pub extern "C" fn synthetic_instrument_price_increment(synth: &SyntheticInstrument_API) -> Price {
112 synth.price_increment
113}
114
115#[no_mangle]
116pub extern "C" fn synthetic_instrument_formula_to_cstr(
117 synth: &SyntheticInstrument_API,
118) -> *const c_char {
119 str_to_cstr(&synth.formula)
120}
121
122#[no_mangle]
123pub extern "C" fn synthetic_instrument_components_to_cstr(
124 synth: &SyntheticInstrument_API,
125) -> *const c_char {
126 let components_vec = synth
127 .components
128 .iter()
129 .map(std::string::ToString::to_string)
130 .collect::<Vec<String>>();
131
132 string_vec_to_bytes(components_vec)
133}
134
135#[no_mangle]
136pub extern "C" fn synthetic_instrument_components_count(synth: &SyntheticInstrument_API) -> usize {
137 synth.components.len()
138}
139
140#[no_mangle]
141pub extern "C" fn synthetic_instrument_ts_event(synth: &SyntheticInstrument_API) -> UnixNanos {
142 synth.ts_event
143}
144
145#[no_mangle]
146pub extern "C" fn synthetic_instrument_ts_init(synth: &SyntheticInstrument_API) -> UnixNanos {
147 synth.ts_init
148}
149
150#[no_mangle]
154pub unsafe extern "C" fn synthetic_instrument_is_valid_formula(
155 synth: &SyntheticInstrument_API,
156 formula_ptr: *const c_char,
157) -> u8 {
158 if formula_ptr.is_null() {
159 return u8::from(false);
160 }
161 let formula = cstr_as_str(formula_ptr);
162 u8::from(synth.is_valid_formula(formula))
163}
164
165#[no_mangle]
169pub unsafe extern "C" fn synthetic_instrument_change_formula(
170 synth: &mut SyntheticInstrument_API,
171 formula_ptr: *const c_char,
172) {
173 let formula = cstr_as_str(formula_ptr);
174 synth.change_formula(formula.to_string()).unwrap();
175}
176
177#[no_mangle]
178#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
179pub extern "C" fn synthetic_instrument_calculate(
180 synth: &mut SyntheticInstrument_API,
181 inputs_ptr: &CVec,
182) -> Price {
183 let CVec { ptr, len, .. } = inputs_ptr;
184 let inputs: &[f64] = unsafe { std::slice::from_raw_parts((*ptr).cast::<f64>(), *len) };
185
186 match synth.calculate(inputs) {
187 Ok(price) => price,
188 Err(_) => ERROR_PRICE,
189 }
190}