nautilus_model/ffi/instruments/
synthetic.rsuse std::{
ffi::c_char,
ops::{Deref, DerefMut},
};
use nautilus_core::{
ffi::{
cvec::CVec,
parsing::{bytes_to_string_vec, string_vec_to_bytes},
string::{cstr_as_str, str_to_cstr},
},
nanos::UnixNanos,
};
use crate::{
identifiers::{InstrumentId, Symbol},
instruments::synthetic::SyntheticInstrument,
types::price::{Price, ERROR_PRICE},
};
#[repr(C)]
#[allow(non_camel_case_types)]
pub struct SyntheticInstrument_API(Box<SyntheticInstrument>);
impl Deref for SyntheticInstrument_API {
type Target = SyntheticInstrument;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for SyntheticInstrument_API {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[no_mangle]
pub unsafe extern "C" fn synthetic_instrument_new(
symbol: Symbol,
price_precision: u8,
components_ptr: *const c_char,
formula_ptr: *const c_char,
ts_event: u64,
ts_init: u64,
) -> SyntheticInstrument_API {
let components = bytes_to_string_vec(components_ptr)
.into_iter()
.map(|s| InstrumentId::from(s.as_str()))
.collect::<Vec<InstrumentId>>();
let formula = cstr_as_str(formula_ptr).to_string();
let synth = SyntheticInstrument::new(
symbol,
price_precision,
components,
formula,
ts_event.into(),
ts_init.into(),
);
SyntheticInstrument_API(Box::new(synth))
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_drop(synth: SyntheticInstrument_API) {
drop(synth); }
#[no_mangle]
pub extern "C" fn synthetic_instrument_id(synth: &SyntheticInstrument_API) -> InstrumentId {
synth.id
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_price_precision(synth: &SyntheticInstrument_API) -> u8 {
synth.price_precision
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_price_increment(synth: &SyntheticInstrument_API) -> Price {
synth.price_increment
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_formula_to_cstr(
synth: &SyntheticInstrument_API,
) -> *const c_char {
str_to_cstr(&synth.formula)
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_components_to_cstr(
synth: &SyntheticInstrument_API,
) -> *const c_char {
let components_vec = synth
.components
.iter()
.map(std::string::ToString::to_string)
.collect::<Vec<String>>();
string_vec_to_bytes(components_vec)
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_components_count(synth: &SyntheticInstrument_API) -> usize {
synth.components.len()
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_ts_event(synth: &SyntheticInstrument_API) -> UnixNanos {
synth.ts_event
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_ts_init(synth: &SyntheticInstrument_API) -> UnixNanos {
synth.ts_init
}
#[no_mangle]
pub unsafe extern "C" fn synthetic_instrument_is_valid_formula(
synth: &SyntheticInstrument_API,
formula_ptr: *const c_char,
) -> u8 {
if formula_ptr.is_null() {
return u8::from(false);
}
let formula = cstr_as_str(formula_ptr);
u8::from(synth.is_valid_formula(formula))
}
#[no_mangle]
pub unsafe extern "C" fn synthetic_instrument_change_formula(
synth: &mut SyntheticInstrument_API,
formula_ptr: *const c_char,
) {
let formula = cstr_as_str(formula_ptr);
synth.change_formula(formula.to_string()).unwrap();
}
#[no_mangle]
pub extern "C" fn synthetic_instrument_calculate(
synth: &mut SyntheticInstrument_API,
inputs_ptr: &CVec,
) -> Price {
let CVec { ptr, len, .. } = inputs_ptr;
let inputs: &[f64] = unsafe { std::slice::from_raw_parts((*ptr).cast::<f64>(), *len) };
match synth.calculate(inputs) {
Ok(price) => price,
Err(_) => ERROR_PRICE,
}
}