1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use serde::{Deserialize, Serialize};

use crate::market::{Price, Quantity};
use crate::misc::DateTimeUTC;

/// Type alias for an order ID.
pub type OrderID = String;

/// Type alias for symbol.
pub type Symbol = String;

/// Represents an order content.
#[derive(Clone, Serialize)]
pub enum OrderContent {
    /// Represents a new direct order.
    /// Negative `quantity` means sell order.
    NewDirect { price: Price, quantity: Quantity },

    /// Represents a market order.
    /// Negative `quantity` means sell order.
    NewMarket { quantity: Quantity },

    /// Represents a cancel order.
    Cancel { original_client_order_id: OrderID },
}

/// Represents a TIF.
#[derive(Clone, Serialize)]
pub enum TimeInForce {
    /// Good Til Cancel (with provided `expiration_time`)
    GTC { expiration_time: DateTimeUTC },
    /// Immediate or cancel
    IoC,
    /// Fill or Kill = IoC + AoN (All or None)
    FoK,
}

/// Represents an order request.
#[derive(Clone, Serialize)]
pub struct OrderRequest {
    /// Main content of this order request.
    pub content: OrderContent,
    /// Target symbol.
    pub symbol: Symbol,
    /// Order request ID from client's side.
    pub client_order_id: OrderID,
}

/// Represents an order response status.
#[derive(Clone, Deserialize)]
pub enum OrderResponseStatus {
    Ok,
    Filled {
        executed_price: Price,
        executed_quantity: Quantity,
    },
    Rejected {
        code: Option<i32>,
        message: Option<String>,
    },
}

/// Represents an order response.
#[derive(Clone, Deserialize)]
pub struct OrderResponse {
    pub status: OrderResponseStatus,
    /// Same as `OrderRequest::client_order_id`.
    pub client_order_id: OrderID,
}

impl OrderResponse {
    /// Get notional value of this execution.
    pub fn notional_value(&self) -> Quantity {
        match self.status {
            OrderResponseStatus::Filled {
                executed_price,
                executed_quantity,
            } => executed_price * executed_quantity,
            _ => Quantity::ZERO,
        }
    }
}