nautilus_model/ffi/data/
bar.rs

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// -------------------------------------------------------------------------------------------------
15
16use std::{
17    collections::hash_map::DefaultHasher,
18    ffi::c_char,
19    hash::{Hash, Hasher},
20    str::FromStr,
21};
22
23use nautilus_core::{
24    ffi::string::{cstr_as_str, str_to_cstr},
25    UnixNanos,
26};
27
28use crate::{
29    data::bar::{Bar, BarSpecification, BarType},
30    enums::{AggregationSource, BarAggregation, PriceType},
31    identifiers::InstrumentId,
32    types::{Price, Quantity},
33};
34
35#[no_mangle]
36pub extern "C" fn bar_specification_new(
37    step: usize,
38    aggregation: u8,
39    price_type: u8,
40) -> BarSpecification {
41    let aggregation =
42        BarAggregation::from_repr(aggregation as usize).expect("Error converting enum");
43    let price_type = PriceType::from_repr(price_type as usize).expect("Error converting enum");
44    BarSpecification::new(step, aggregation, price_type)
45}
46
47/// Returns a [`BarSpecification`] as a C string pointer.
48#[no_mangle]
49pub extern "C" fn bar_specification_to_cstr(bar_spec: &BarSpecification) -> *const c_char {
50    str_to_cstr(&bar_spec.to_string())
51}
52
53#[no_mangle]
54pub extern "C" fn bar_specification_hash(bar_spec: &BarSpecification) -> u64 {
55    let mut h = DefaultHasher::new();
56    bar_spec.hash(&mut h);
57    h.finish()
58}
59
60#[no_mangle]
61pub extern "C" fn bar_specification_eq(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
62    u8::from(lhs == rhs)
63}
64
65#[no_mangle]
66pub extern "C" fn bar_specification_lt(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
67    u8::from(lhs < rhs)
68}
69
70#[no_mangle]
71pub extern "C" fn bar_specification_le(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
72    u8::from(lhs <= rhs)
73}
74
75#[no_mangle]
76pub extern "C" fn bar_specification_gt(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
77    u8::from(lhs > rhs)
78}
79
80#[no_mangle]
81pub extern "C" fn bar_specification_ge(lhs: &BarSpecification, rhs: &BarSpecification) -> u8 {
82    u8::from(lhs >= rhs)
83}
84
85#[no_mangle]
86pub extern "C" fn bar_type_new(
87    instrument_id: InstrumentId,
88    spec: BarSpecification,
89    aggregation_source: u8,
90) -> BarType {
91    let aggregation_source =
92        AggregationSource::from_repr(aggregation_source as usize).expect("Error converting enum");
93
94    BarType::Standard {
95        instrument_id,
96        spec,
97        aggregation_source,
98    }
99}
100
101#[no_mangle]
102pub extern "C" fn bar_type_new_composite(
103    instrument_id: InstrumentId,
104    spec: BarSpecification,
105    aggregation_source: AggregationSource,
106
107    composite_step: usize,
108    composite_aggregation: BarAggregation,
109    composite_aggregation_source: AggregationSource,
110) -> BarType {
111    BarType::new_composite(
112        instrument_id,
113        spec,
114        aggregation_source,
115        composite_step,
116        composite_aggregation,
117        composite_aggregation_source,
118    )
119}
120
121#[no_mangle]
122pub extern "C" fn bar_type_is_standard(bar_type: &BarType) -> u8 {
123    bar_type.is_standard() as u8
124}
125
126#[no_mangle]
127pub extern "C" fn bar_type_is_composite(bar_type: &BarType) -> u8 {
128    bar_type.is_composite() as u8
129}
130
131#[no_mangle]
132pub extern "C" fn bar_type_standard(bar_type: &BarType) -> BarType {
133    bar_type.standard()
134}
135
136#[no_mangle]
137pub extern "C" fn bar_type_composite(bar_type: &BarType) -> BarType {
138    bar_type.composite()
139}
140
141#[no_mangle]
142pub extern "C" fn bar_type_instrument_id(bar_type: &BarType) -> InstrumentId {
143    bar_type.instrument_id()
144}
145
146#[no_mangle]
147pub extern "C" fn bar_type_spec(bar_type: &BarType) -> BarSpecification {
148    bar_type.spec()
149}
150
151#[no_mangle]
152pub extern "C" fn bar_type_aggregation_source(bar_type: &BarType) -> AggregationSource {
153    bar_type.aggregation_source()
154}
155
156/// Returns any [`BarType`] parsing error from the provided C string pointer.
157///
158/// # Safety
159///
160/// - Assumes `ptr` is a valid C string pointer.
161#[no_mangle]
162pub unsafe extern "C" fn bar_type_check_parsing(ptr: *const c_char) -> *const c_char {
163    match BarType::from_str(cstr_as_str(ptr)) {
164        Ok(_) => str_to_cstr(""),
165        Err(e) => str_to_cstr(&e.to_string()),
166    }
167}
168
169/// Returns a [`BarType`] from a C string pointer.
170///
171/// # Safety
172///
173/// - Assumes `ptr` is a valid C string pointer.
174#[no_mangle]
175pub unsafe extern "C" fn bar_type_from_cstr(ptr: *const c_char) -> BarType {
176    BarType::from(cstr_as_str(ptr))
177}
178
179#[no_mangle]
180pub extern "C" fn bar_type_eq(lhs: &BarType, rhs: &BarType) -> u8 {
181    u8::from(lhs == rhs)
182}
183
184#[no_mangle]
185pub extern "C" fn bar_type_lt(lhs: &BarType, rhs: &BarType) -> u8 {
186    u8::from(lhs < rhs)
187}
188
189#[no_mangle]
190pub extern "C" fn bar_type_le(lhs: &BarType, rhs: &BarType) -> u8 {
191    u8::from(lhs <= rhs)
192}
193
194#[no_mangle]
195pub extern "C" fn bar_type_gt(lhs: &BarType, rhs: &BarType) -> u8 {
196    u8::from(lhs > rhs)
197}
198
199#[no_mangle]
200pub extern "C" fn bar_type_ge(lhs: &BarType, rhs: &BarType) -> u8 {
201    u8::from(lhs >= rhs)
202}
203
204#[no_mangle]
205pub extern "C" fn bar_type_hash(bar_type: &BarType) -> u64 {
206    let mut h = DefaultHasher::new();
207    bar_type.hash(&mut h);
208    h.finish()
209}
210
211/// Returns a [`BarType`] as a C string pointer.
212#[no_mangle]
213pub extern "C" fn bar_type_to_cstr(bar_type: &BarType) -> *const c_char {
214    str_to_cstr(&bar_type.to_string())
215}
216
217#[no_mangle]
218#[cfg_attr(feature = "high-precision", allow(improper_ctypes_definitions))]
219pub extern "C" fn bar_new(
220    bar_type: BarType,
221    open: Price,
222    high: Price,
223    low: Price,
224    close: Price,
225    volume: Quantity,
226    ts_event: UnixNanos,
227    ts_init: UnixNanos,
228) -> Bar {
229    Bar {
230        bar_type,
231        open,
232        high,
233        low,
234        close,
235        volume,
236        ts_event,
237        ts_init,
238    }
239}
240
241#[no_mangle]
242pub extern "C" fn bar_eq(lhs: &Bar, rhs: &Bar) -> u8 {
243    u8::from(lhs == rhs)
244}
245
246#[no_mangle]
247pub extern "C" fn bar_hash(bar: &Bar) -> u64 {
248    let mut h = DefaultHasher::new();
249    bar.hash(&mut h);
250    h.finish()
251}
252
253/// Returns a [`Bar`] as a C string.
254#[no_mangle]
255pub extern "C" fn bar_to_cstr(bar: &Bar) -> *const c_char {
256    str_to_cstr(&bar.to_string())
257}