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
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/// An order book side.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Side {
    /// The bid (or buy) side.
    Bid,
    /// The ask (or sell) side.
    Ask,
}

impl std::ops::Not for Side {
    type Output = Side;

    fn not(self) -> Self::Output {
        match self {
            Side::Bid => Side::Ask,
            Side::Ask => Side::Bid,
        }
    }
}

/// An order to be executed by the order book.
#[derive(Debug, Copy, Clone)]
pub enum OrderType {
    /// A market order, which is either filled immediately (even partially), or
    /// canceled.
    Market {
        /// The unique ID of this order.
        id: u128,
        /// The order side. It will be matched against the resting orders on the
        /// other side of the order book.
        side: Side,
        /// The order quantity.
        qty: u64,
    },
    /// A limit order, which is either filled immediately, or added to the order
    /// book.
    Limit {
        /// The unique ID of this order.
        id: u128,
        /// The order side. It will be matched against the resting orders on the
        /// other side of the order book.
        side: Side,
        /// The order quantity.
        qty: u64,
        /// The limit price. The order book will only match this order with
        /// other orders at this price or better.
        price: u64,
    },
    /// A cancel order, which removes the order with the specified ID from the
    /// order book.
    Cancel {
        /// The unique ID of the order to be canceled.
        id: u128,
    },
}

/// An event resulting from the execution of an order.
#[derive(Debug, PartialEq, Clone)]
pub enum OrderEvent {
    /// Indicating that the corresponding order was not filled. It is only sent
    /// in response to market orders.
    Unfilled {
        /// The ID of the order this event is referring to.
        id: u128,
    },
    /// Indicating that the corresponding order was placed on the order book. It
    /// is only send in response to limit orders.
    Placed {
        /// The ID of the order this event is referring to.
        id: u128,
    },
    /// Indicating that the corresponding order was removed from the order book.
    /// It is only sent in response to cancel orders.
    Canceled {
        /// The ID of the order this event is referring to.
        id: u128,
    },
    /// Indicating that the corresponding order was only partially filled. It is
    /// sent in response to market or limit orders.
    PartiallyFilled {
        /// The ID of the order this event is referring to.
        id: u128,
        /// The filled quantity.
        filled_qty: u64,
        /// A vector with information on the order fills.
        fills: Vec<FillMetadata>,
    },
    /// Indicating that the corresponding order was filled completely. It is
    /// sent in response to market or limit orders.
    Filled {
        /// The ID of the order this event is referring to.
        id: u128,
        /// The filled quantity.
        filled_qty: u64,
        /// A vector with information on the order fills.
        fills: Vec<FillMetadata>,
    },
}

/// Information on a single order fill. When an order is matched with multiple
/// resting orders, it generates multiple `FillMetadata` values.
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct FillMetadata {
    /// The ID of the order that triggered the fill (taker).
    pub order_1: u128,
    /// The ID of the matching order.
    pub order_2: u128,
    /// The quantity that was traded.
    pub qty: u64,
    /// The price at which the trade happened.
    pub price: u64,
    /// The side of the taker order (order 1)
    pub taker_side: Side,
    /// Whether this order was a total (true) or partial (false) fill of the
    /// maker order.
    pub total_fill: bool,
}

/// A snapshot of the order book up to a certain depth level. Multiple orders at
/// the same price points are merged into a single [`BookLevel`] struct.
///
/// [`BookLevel`]: /struct.BookLevel.html
#[derive(Debug, Clone, PartialEq)]
pub struct BookDepth {
    /// The requested level. This field will always contain the level that was
    /// requested, even if some or all levels are empty.
    pub levels: usize,
    /// A vector of price points with the associated quantity on the ask side.
    pub asks: Vec<BookLevel>,
    /// A vector of price points with the associated quantity on the bid side.
    pub bids: Vec<BookLevel>,
}

/// A single level in the order book. This struct is used both for the bid and
/// ask side.
#[derive(Debug, Clone, PartialEq)]
pub struct BookLevel {
    /// The price point this level represents.
    pub price: u64,
    /// The total quantity of all orders resting at the specified price point.
    pub qty: u64,
}

/// A trade that happened as part of the matching process.
#[derive(Debug, Copy, Clone)]
pub struct Trade {
    /// The total quantity transacted as part of this trade.
    pub total_qty: u64,
    /// The volume-weighted average price computed from all the order fills
    /// within this trade.
    pub avg_price: f64,
    /// The price of the last fill that was part of this trade.
    pub last_price: u64,
    /// The quantity of the last fill that was part of this trade.
    pub last_qty: u64,
}

#[derive(Debug, PartialEq)]
pub struct LimitOrder {
    pub id: u128,
    pub qty: u64,
    pub price: u64,
}

#[cfg(test)]
mod test {
    use super::Side;

    #[test]
    fn side_negation() {
        assert_eq!(!Side::Ask, Side::Bid);
        assert_eq!(!Side::Bid, Side::Ask);
    }
}