1use crate::{
2 folio::FolioMessage,
3 orderflow::{
4 AberrantFill, Ack, Cancel, CancelAll, Fill, Order, OrderType, OrderflowMessage,
5 Out, Reject, TimeInForce,
6 },
7 symbology::market::{MinOrderQuantityUnit, NormalizedMarketInfo},
8 Amount, Dir, OrderId,
9};
10use chrono::{DateTime, Utc};
11use derive::FromStrJson;
12#[cfg(feature = "netidx")]
13use derive::FromValue;
14#[cfg(feature = "netidx")]
15use netidx_derive::Pack;
16use rust_decimal::{prelude::FromPrimitive, Decimal};
17use schemars::JsonSchema;
18use serde::{Deserialize, Serialize};
19use std::ops::{Deref, DerefMut};
20use zeroize::Zeroize;
21
22#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
23#[cfg_attr(feature = "netidx", derive(Pack))]
24pub enum Status {
25 #[serde(alias = "online")]
26 Online,
27 #[serde(alias = "cancel_only")]
28 CancelOnly,
29 #[serde(alias = "post_only")]
30 PostOnly,
31 #[serde(alias = "limit_only")]
32 LimitOnly,
33 #[serde(alias = "reduce_only")]
34 ReduceOnly,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
38#[cfg_attr(feature = "netidx", derive(Pack))]
39pub struct KrakenMarketInfo {
40 pub altname: String,
41 pub wsname: String,
42 pub aclass_base: String,
43 pub base: String,
44 pub aclass_quote: String,
45 pub quote: String,
46 pub pair_decimals: u64,
47 pub cost_decimals: u64,
48 pub lot_decimals: u64,
49 pub lot_multiplier: u64,
50 pub margin_call: u64,
51 pub margin_stop: u64,
52 pub fee_volume_currency: String,
53 pub ordermin: Decimal,
54 pub costmin: Decimal,
55 pub tick_size: Decimal,
56 pub status: Status,
57 pub long_position_limit: Option<u64>,
58 pub short_position_limit: Option<u64>,
59}
60
61impl NormalizedMarketInfo for KrakenMarketInfo {
62 fn tick_size(&self) -> Decimal {
63 self.tick_size
64 }
65
66 fn step_size(&self) -> Decimal {
67 Decimal::from_f64(10f64.powi(-(self.lot_decimals as i32)))
68 .expect(&format!("could not compute step_size: {:?}", self))
69 }
70
71 fn min_order_quantity(&self) -> Amount<Decimal, MinOrderQuantityUnit> {
72 return Amount::new(self.ordermin, MinOrderQuantityUnit::Base);
73 }
74
75 fn is_delisted(&self) -> bool {
76 false
77 }
78}
79
80impl std::fmt::Display for KrakenMarketInfo {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 write!(f, "{}", serde_json::to_string_pretty(self).unwrap())?;
83 Ok(())
84 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
88#[cfg_attr(feature = "netidx", derive(Pack))]
89#[cfg_attr(feature = "netidx", derive(FromValue))]
90pub enum KrakenMessage {
91 Initialize,
92 Order(KrakenOrder),
93 Cancel(Cancel),
94 CancelAll(CancelAll),
95 Reject(Reject),
96 Ack(Ack),
97 Fill(KrakenFill),
98 Out(Out),
99 ExchangeOrderUpdate(
100 KrakenUserRef,
101 KrakenExchangeId,
102 Option<(OrderId, KrakenExternalOrder)>,
103 bool, ),
105 ExchangeAck(OrderId, KrakenExchangeId),
106 ExchangeFill(KrakenExternalFill),
107 ExchangeExternalOrderNew(OrderId, KrakenExternalOrder),
108 ExchangeExternalOrderOut(KrakenExchangeId),
109 ExchangeExternalFill(KrakenExternalFill),
110 Folio(FolioMessage),
111}
112
113impl TryInto<OrderflowMessage> for &KrakenMessage {
114 type Error = ();
115
116 fn try_into(self) -> Result<OrderflowMessage, ()> {
117 match self {
118 KrakenMessage::Order(o) => Ok(OrderflowMessage::Order(**o)),
119 KrakenMessage::Cancel(c) => Ok(OrderflowMessage::Cancel(*c)),
120 KrakenMessage::CancelAll(ca) => Ok(OrderflowMessage::CancelAll(ca.clone())),
121 KrakenMessage::Reject(r) => Ok(OrderflowMessage::Reject(r.clone())),
122 KrakenMessage::Ack(a) => Ok(OrderflowMessage::Ack(*a)),
123 KrakenMessage::Fill(f) => Ok(OrderflowMessage::Fill(**f)),
124 KrakenMessage::Out(o) => Ok(OrderflowMessage::Out(*o)),
125 KrakenMessage::ExchangeOrderUpdate(..)
126 | KrakenMessage::Initialize
127 | KrakenMessage::ExchangeAck(..)
128 | KrakenMessage::ExchangeFill(..)
129 | KrakenMessage::ExchangeExternalOrderNew(..)
130 | KrakenMessage::ExchangeExternalFill(..)
131 | KrakenMessage::ExchangeExternalOrderOut(..)
132 | KrakenMessage::Folio(..) => Err(()),
133 }
134 }
135}
136
137impl TryInto<KrakenMessage> for &OrderflowMessage {
138 type Error = ();
139
140 fn try_into(self) -> Result<KrakenMessage, ()> {
141 match self {
142 OrderflowMessage::Order(o) => {
143 Ok(KrakenMessage::Order(KrakenOrder { order: *o }))
144 }
145 OrderflowMessage::Cancel(c) => Ok(KrakenMessage::Cancel(*c)),
146 OrderflowMessage::Reject(r) => Ok(KrakenMessage::Reject(r.clone())),
147 OrderflowMessage::Ack(a) => Ok(KrakenMessage::Ack(*a)),
148 OrderflowMessage::Fill(_) => Err(()),
149 OrderflowMessage::CancelAll(ca) => Ok(KrakenMessage::CancelAll(ca.clone())),
150 OrderflowMessage::Out(o) => Ok(KrakenMessage::Out(*o)),
151 }
152 }
153}
154
155impl TryInto<FolioMessage> for &KrakenMessage {
156 type Error = ();
157
158 fn try_into(self) -> Result<FolioMessage, ()> {
159 match self {
160 KrakenMessage::Folio(f) => Ok(f.clone()),
161 _ => Err(()),
162 }
163 }
164}
165
166impl TryFrom<&FolioMessage> for KrakenMessage {
167 type Error = ();
168
169 fn try_from(f: &FolioMessage) -> Result<Self, ()> {
170 Ok(Self::Folio(f.clone()))
171 }
172}
173
174pub type KrakenExchangeId = String;
175pub type KrakenUserRef = i32;
176
177#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
178#[cfg_attr(feature = "netidx", derive(Pack))]
179pub struct KrakenOrder {
180 #[serde(flatten)]
181 pub order: Order,
182}
183
184impl From<Order> for KrakenOrder {
185 fn from(order: Order) -> Self {
186 Self { order }
187 }
188}
189
190impl Deref for KrakenOrder {
191 type Target = Order;
192
193 fn deref(&self) -> &Self::Target {
194 &self.order
195 }
196}
197
198impl DerefMut for KrakenOrder {
199 fn deref_mut(&mut self) -> &mut Self::Target {
200 &mut self.order
201 }
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
205#[cfg_attr(feature = "netidx", derive(Pack))]
206pub struct KrakenFill {
207 #[serde(flatten)]
208 pub fill: Result<Fill, AberrantFill>,
209 pub exchange_trade_id: KrakenExchangeId,
210 pub exchange_order_id: KrakenExchangeId,
211}
212
213impl Deref for KrakenFill {
214 type Target = Result<Fill, AberrantFill>;
215
216 fn deref(&self) -> &Self::Target {
217 &self.fill
218 }
219}
220
221#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
222#[cfg_attr(feature = "netidx", derive(Pack))]
223pub struct KrakenExternalOrder {
224 pub exchange_symbol: String,
225 pub exchange_order_id: KrakenExchangeId,
226 pub user_reference_id: KrakenUserRef,
227 pub quantity: Decimal,
228 pub trigger_price: Option<Decimal>,
229 pub dir: Dir,
230 pub expiration: Option<DateTime<Utc>>,
231 pub order_type: OrderType,
232 pub time_in_force: TimeInForce,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
236#[cfg_attr(feature = "netidx", derive(Pack))]
237pub struct KrakenExternalFill {
238 pub exchange_order_id: KrakenExchangeId,
239 pub exchange_trade_id: KrakenExchangeId,
240 pub user_reference_id: Option<KrakenUserRef>,
241 pub time: DateTime<Utc>,
242 pub quantity: Decimal,
243 pub price: Decimal,
244 pub dir: Dir,
245}
246
247#[derive(Debug, Clone, FromStrJson, Serialize, Deserialize, Zeroize, JsonSchema)]
248#[cfg_attr(feature = "netidx", derive(Pack))]
249#[cfg_attr(feature = "netidx", derive(FromValue))]
250pub struct KrakenCredentials {
251 #[serde(default)]
255 pub account_name: Option<String>,
256 pub api_key: String,
257 pub api_secret: String,
258}