architect_api/algo/
mod.rs

1use crate::{OrderId, TraderIdOrEmail, UserId};
2use anyhow::Result;
3use chrono::{DateTime, Utc};
4use derive::grpc;
5use derive_more::{Display, FromStr};
6use schemars::{JsonSchema, JsonSchema_repr};
7use serde::{de::DeserializeOwned, Deserialize, Serialize};
8use serde_json::value::RawValue;
9use serde_repr::{Deserialize_repr, Serialize_repr};
10use strum::FromRepr;
11pub mod builder;
12pub mod common_params;
13pub mod quote_one_side;
14pub mod release_at_time;
15pub mod spreader;
16pub mod twap;
17
18pub trait Algo {
19    const NAME: &'static str;
20
21    type Params: std::fmt::Debug
22        + Clone
23        + Validate
24        + DisplaySymbols
25        + Serialize
26        + DeserializeOwned
27        + JsonSchema
28        + Send
29        + 'static;
30
31    type Status: std::fmt::Debug
32        + Clone
33        + Default
34        + Serialize
35        + DeserializeOwned
36        + JsonSchema;
37}
38
39pub trait DisplaySymbols {
40    fn display_symbols(&self) -> Option<Vec<String>> {
41        None
42    }
43}
44
45impl DisplaySymbols for () {}
46
47#[grpc(package = "json.architect")]
48#[grpc(service = "Algo", name = "create_algo_order", response = "AlgoOrder")]
49#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
50pub struct CreateAlgoOrderRequest {
51    pub algo: String,
52    pub id: Option<OrderId>,
53    pub parent_id: Option<OrderId>,
54    pub trader: Option<TraderIdOrEmail>,
55    pub params: Box<RawValue>,
56}
57
58#[grpc(package = "json.architect")]
59#[grpc(service = "AlgoHelper", name = "_algo_param_types", response = "AlgoParamTypes")]
60#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
61/// this is used to coerce creation of the params in the schema.json
62pub struct AlgoParamTypes {
63    pub spreader: (spreader::SpreaderParams, spreader::SpreaderStatus),
64    pub quote_one_side:
65        (quote_one_side::QuoteOneSideParams, quote_one_side::QuoteOneSideStatus),
66}
67
68impl CreateAlgoOrderRequest {
69    pub fn builder(algo: impl AsRef<str>) -> builder::CreateAlgoOrderRequestBuilder {
70        builder::CreateAlgoOrderRequestBuilder::new(algo)
71    }
72}
73
74#[grpc(package = "json.architect")]
75#[grpc(service = "Algo", name = "modify_algo_order", response = "AlgoOrder")]
76#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
77pub struct ModifyAlgoOrderRequest {
78    pub algo_order_id: OrderId,
79    pub params: Box<RawValue>,
80}
81
82#[grpc(package = "json.architect")]
83#[grpc(service = "Algo", name = "start_algo", response = "StartAlgoResponse")]
84#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
85pub struct StartAlgoRequest {
86    pub algo_order_id: OrderId,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
90pub struct StartAlgoResponse {}
91
92#[grpc(package = "json.architect")]
93#[grpc(service = "Algo", name = "pause_algo", response = "PauseAlgoResponse")]
94#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
95pub struct PauseAlgoRequest {
96    pub algo_order_id: OrderId,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
100pub struct PauseAlgoResponse {}
101
102#[grpc(package = "json.architect")]
103#[grpc(service = "Algo", name = "stop_algo", response = "StopAlgoResponse")]
104#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
105pub struct StopAlgoRequest {
106    pub algo_order_id: OrderId,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
110pub struct StopAlgoResponse {}
111
112/// Get generic algo run status
113#[grpc(package = "json.architect")]
114#[grpc(service = "Algo", name = "algo_order", response = "AlgoOrder")]
115#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
116pub struct AlgoOrderRequest {
117    pub algo_order_id: OrderId,
118}
119
120/// Find all algo orders matching the given criteria.
121///
122/// If limit is not specified, it will default to 100.
123#[grpc(package = "json.architect")]
124#[grpc(service = "Algo", name = "algo_orders", response = "AlgoOrdersResponse")]
125#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
126pub struct AlgoOrdersRequest {
127    pub algo: Option<String>,
128    pub parent_order_id: Option<OrderId>,
129    pub trader: Option<TraderIdOrEmail>,
130    pub display_symbol: Option<String>,
131    pub status: Option<Vec<AlgoOrderStatus>>,
132    pub from_inclusive: Option<DateTime<Utc>>,
133    pub to_exclusive: Option<DateTime<Utc>>,
134    pub limit: Option<u32>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
138pub struct AlgoOrdersResponse {
139    pub algo_orders: Vec<AlgoOrder>,
140}
141
142impl Algo for () {
143    const NAME: &'static str = "UNKNOWN";
144
145    type Params = ();
146    type Status = ();
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
150pub struct AlgoOrder {
151    pub algo: String,
152    pub id: OrderId,
153    pub parent_id: Option<OrderId>,
154    pub create_time: DateTime<Utc>,
155    /// If the algo order is stopped, the time at which it was stopped.
156    pub finish_time: Option<DateTime<Utc>>,
157    /// If the algo order is stopped, whether the stop was successful.
158    pub finish_success: Option<bool>,
159    pub status: AlgoOrderStatus,
160    pub status_details: Box<RawValue>,
161    /// If algo order status is rejected, contains the reject reason;
162    /// for algo orders that finished unsuccessfully, contains the error reason.
163    pub reject_or_error_reason: Option<String>,
164    pub display_symbols: Option<Vec<String>>,
165    pub trader: UserId,
166    pub params: Box<RawValue>,
167    /// Progress of the algo, 0.0 to 1.0, if computable
168    pub working_progress: Option<f64>,
169    pub num_sent_orders: u32,
170    pub num_open_orders: u32,
171    pub num_rejects: u32,
172    pub num_errors: u32,
173}
174
175#[derive(
176    Debug,
177    Display,
178    FromStr,
179    FromRepr,
180    Clone,
181    Copy,
182    PartialEq,
183    Eq,
184    Serialize_repr,
185    Deserialize_repr,
186    JsonSchema_repr,
187)]
188#[cfg_attr(feature = "graphql", derive(juniper::GraphQLEnum))]
189#[serde(rename_all = "snake_case")]
190#[repr(u8)]
191pub enum AlgoOrderStatus {
192    // Pending = 0,
193    Working = 1,
194    Rejected = 2,
195    Paused = 63,
196    // Pausing = 64,
197    Stopping = 128,
198    Stopped = 127, // same as paused but final
199}
200
201impl AlgoOrderStatus {
202    pub fn is_alive(&self) -> bool {
203        matches!(
204            self,
205            AlgoOrderStatus::Working
206                | AlgoOrderStatus::Paused
207                | AlgoOrderStatus::Stopping
208        )
209    }
210}
211
212// CR-someday alee: use something more akin to the validator crate
213pub trait Validate {
214    fn validate(&self) -> Result<()> {
215        Ok(())
216    }
217}
218
219impl Validate for () {}
220
221#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
222pub struct AlgoLog {}