Skip to main content

nautilus_coinapi/http/
models.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//! Raw CoinAPI responses, decoded directly from JSON bytes to preserve decimal tokens.
17
18use jiff::Timestamp;
19use nautilus_core::serialization::decimal;
20use rust_decimal::Decimal;
21use serde::Deserialize;
22use ustr::Ustr;
23
24use crate::common::enums::{SymbolType, TakerSide};
25
26/// Exchange identity and metadata.
27#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
28pub struct Exchange {
29    pub exchange_id: Ustr,
30    pub name: String,
31    pub website: Option<String>,
32    pub data_start: Option<String>,
33    pub data_end: Option<String>,
34    pub data_symbols_count: Option<u64>,
35    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
36    pub volume_1hrs_usd: Option<Decimal>,
37    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
38    pub volume_1day_usd: Option<Decimal>,
39    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
40    pub volume_1mth_usd: Option<Decimal>,
41}
42
43/// Provider symbol identity and data resolution, without trading-increment inference.
44#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
45pub struct Symbol {
46    pub symbol_id: Ustr,
47    pub exchange_id: Ustr,
48    pub symbol_type: SymbolType,
49    pub asset_id_base: Option<Ustr>,
50    pub asset_id_quote: Option<Ustr>,
51    pub asset_id_unit: Option<Ustr>,
52    pub symbol_id_exchange: Option<Ustr>,
53    pub asset_id_base_exchange: Option<Ustr>,
54    pub asset_id_quote_exchange: Option<Ustr>,
55    pub future_contract_unit_asset: Option<Ustr>,
56    pub data_start: Option<String>,
57    pub data_end: Option<String>,
58    pub future_delivery_time: Option<Timestamp>,
59    pub data_quote_start: Option<Timestamp>,
60    pub data_quote_end: Option<Timestamp>,
61    pub data_trade_start: Option<Timestamp>,
62    pub data_trade_end: Option<Timestamp>,
63    pub data_orderbook_start: Option<Timestamp>,
64    pub data_orderbook_end: Option<Timestamp>,
65    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
66    pub future_contract_unit: Option<Decimal>,
67    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
68    pub price_precision: Option<Decimal>,
69    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
70    pub size_precision: Option<Decimal>,
71    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
72    pub price: Option<Decimal>,
73    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
74    pub volume_1hrs: Option<Decimal>,
75    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
76    pub volume_1hrs_usd: Option<Decimal>,
77    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
78    pub volume_1day: Option<Decimal>,
79    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
80    pub volume_1day_usd: Option<Decimal>,
81    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
82    pub volume_1mth: Option<Decimal>,
83    #[serde(default, deserialize_with = "decimal::deserialize_optional_json")]
84    pub volume_1mth_usd: Option<Decimal>,
85    pub symbol_id_int: Option<u64>,
86    pub raw_kvp: Option<SymbolRawKvp>,
87}
88
89/// Venue metadata that CoinAPI forwards as string key-value pairs, limited to product
90/// classification keys.
91#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
92#[serde(rename_all = "camelCase")]
93pub struct SymbolRawKvp {
94    pub contract_type: Option<Ustr>,
95    pub underlying_type: Option<Ustr>,
96}
97
98/// A current provider order-book snapshot.
99#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
100pub struct Book {
101    pub symbol_id: Ustr,
102    pub time_exchange: Timestamp,
103    pub time_coinapi: Timestamp,
104    pub asks: Vec<BookLevel>,
105    pub bids: Vec<BookLevel>,
106}
107
108/// A book entry, retaining an order identifier when supplied.
109#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
110pub struct BookLevel {
111    pub id: Option<String>,
112    #[serde(deserialize_with = "decimal::deserialize_json")]
113    pub price: Decimal,
114    #[serde(deserialize_with = "decimal::deserialize_json")]
115    pub size: Decimal,
116}
117
118/// A historical best bid and ask update.
119#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
120pub struct Quote {
121    pub symbol_id: Option<Ustr>,
122    pub time_exchange: Timestamp,
123    pub time_coinapi: Timestamp,
124    #[serde(deserialize_with = "decimal::deserialize_json")]
125    pub ask_price: Decimal,
126    #[serde(deserialize_with = "decimal::deserialize_json")]
127    pub ask_size: Decimal,
128    #[serde(deserialize_with = "decimal::deserialize_json")]
129    pub bid_price: Decimal,
130    #[serde(deserialize_with = "decimal::deserialize_json")]
131    pub bid_size: Decimal,
132}
133
134/// An executed trade in provider wire terms.
135#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
136pub struct Trade {
137    pub symbol_id: Option<Ustr>,
138    pub time_exchange: Timestamp,
139    pub time_coinapi: Timestamp,
140    pub uuid: String,
141    #[serde(deserialize_with = "decimal::deserialize_json")]
142    pub price: Decimal,
143    #[serde(deserialize_with = "decimal::deserialize_json")]
144    pub size: Decimal,
145    pub taker_side: TakerSide,
146    pub id_trade: Option<String>,
147}
148
149/// A provider OHLCV period.
150#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
151pub struct Ohlcv {
152    pub time_period_start: Timestamp,
153    pub time_period_end: Timestamp,
154    pub time_open: Timestamp,
155    pub time_close: Timestamp,
156    #[serde(deserialize_with = "decimal::deserialize_json")]
157    pub price_open: Decimal,
158    #[serde(deserialize_with = "decimal::deserialize_json")]
159    pub price_high: Decimal,
160    #[serde(deserialize_with = "decimal::deserialize_json")]
161    pub price_low: Decimal,
162    #[serde(deserialize_with = "decimal::deserialize_json")]
163    pub price_close: Decimal,
164    #[serde(deserialize_with = "decimal::deserialize_json")]
165    pub volume_traded: Decimal,
166    pub trades_count: u64,
167}