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