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