Skip to content

Commit

Permalink
Implement event OrderSubmitted in Rust (#1383)
Browse files Browse the repository at this point in the history
  • Loading branch information
filipmacek authored Dec 1, 2023
1 parent fbeb07f commit 829ab95
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 11 deletions.
44 changes: 33 additions & 11 deletions nautilus_core/model/src/events/order/stubs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
enums::{ContingencyType, LiquiditySide, OrderSide, OrderType, TimeInForce, TriggerType},
events::order::{
denied::OrderDenied, filled::OrderFilled, initialized::OrderInitialized,
rejected::OrderRejected, triggered::OrderTriggered,
rejected::OrderRejected, submitted::OrderSubmitted, triggered::OrderTriggered,
},
identifiers::{
account_id::AccountId, client_order_id::ClientOrderId, instrument_id::InstrumentId,
Expand All @@ -39,8 +39,8 @@ pub fn order_filled(
strategy_id_ema_cross: StrategyId,
instrument_id_btc_usdt: InstrumentId,
client_order_id: ClientOrderId,
uuid4: UUID4,
) -> OrderFilled {
let event_id = UUID4::new();
OrderFilled::new(
trader_id,
strategy_id_ema_cross,
Expand All @@ -55,7 +55,7 @@ pub fn order_filled(
Price::from_str("22000").unwrap(),
Currency::from_str("USDT").unwrap(),
LiquiditySide::Taker,
event_id,
uuid4,
0,
0,
false,
Expand All @@ -71,15 +71,15 @@ pub fn order_denied_max_submitted_rate(
strategy_id_ema_cross: StrategyId,
instrument_id_btc_usdt: InstrumentId,
client_order_id: ClientOrderId,
uuid4: UUID4,
) -> OrderDenied {
let event_id = UUID4::new();
OrderDenied::new(
trader_id,
strategy_id_ema_cross,
instrument_id_btc_usdt,
client_order_id,
Ustr::from("Exceeded MAX_ORDER_SUBMIT_RATE"),
event_id,
uuid4,
0,
0,
)
Expand All @@ -93,16 +93,16 @@ pub fn order_rejected_insufficient_margin(
strategy_id_ema_cross: StrategyId,
instrument_id_btc_usdt: InstrumentId,
client_order_id: ClientOrderId,
uuid4: UUID4,
) -> OrderRejected {
let event_id = UUID4::new();
OrderRejected::new(
trader_id,
strategy_id_ema_cross,
instrument_id_btc_usdt,
client_order_id,
account_id,
Ustr::from("INSUFFICIENT_MARGIN"),
event_id,
uuid4,
0,
0,
false,
Expand All @@ -116,8 +116,8 @@ pub fn order_initialized_buy_limit(
strategy_id_ema_cross: StrategyId,
instrument_id_btc_usdt: InstrumentId,
client_order_id: ClientOrderId,
uuid4: UUID4,
) -> OrderInitialized {
let event_id = UUID4::new();
let order_list_id = OrderListId::new("1").unwrap();
let linked_order_ids = vec![ClientOrderId::new("O-2020872378424").unwrap()];
OrderInitialized::new(
Expand All @@ -133,7 +133,7 @@ pub fn order_initialized_buy_limit(
true,
false,
false,
event_id,
uuid4,
0,
0,
Some(Price::from_str("22000").unwrap()),
Expand All @@ -158,6 +158,28 @@ pub fn order_initialized_buy_limit(
.unwrap()
}

#[fixture]
pub fn order_submitted(
trader_id: TraderId,
strategy_id_ema_cross: StrategyId,
instrument_id_btc_usdt: InstrumentId,
client_order_id: ClientOrderId,
account_id: AccountId,
uuid4: UUID4,
) -> OrderSubmitted {
OrderSubmitted::new(
trader_id,
strategy_id_ema_cross,
instrument_id_btc_usdt,
client_order_id,
account_id,
uuid4,
0,
0,
)
.unwrap()
}

#[fixture]
pub fn order_triggered(
trader_id: TraderId,
Expand All @@ -166,14 +188,14 @@ pub fn order_triggered(
client_order_id: ClientOrderId,
venue_order_id: VenueOrderId,
account_id: AccountId,
uuid4: UUID4,
) -> OrderTriggered {
let event_id = UUID4::new();
OrderTriggered::new(
trader_id,
strategy_id_ema_cross,
instrument_id_btc_usdt,
client_order_id,
event_id,
uuid4,
0,
0,
false,
Expand Down
64 changes: 64 additions & 0 deletions nautilus_core/model/src/events/order/submitted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
// limitations under the License.
// -------------------------------------------------------------------------------------------------

use std::fmt::{Display, Formatter};

use anyhow::Result;
use derive_builder::{self, Builder};
use nautilus_core::{time::UnixNanos, uuid::UUID4};
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};

use crate::identifiers::{
Expand All @@ -26,6 +30,10 @@ use crate::identifiers::{
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize, Builder)]
#[builder(default)]
#[serde(tag = "type")]
#[cfg_attr(
feature = "python",
pyclass(module = "nautilus_trader.core.nautilus_pyo3.model")
)]
pub struct OrderSubmitted {
pub trader_id: TraderId,
pub strategy_id: StrategyId,
Expand All @@ -36,3 +44,59 @@ pub struct OrderSubmitted {
pub ts_event: UnixNanos,
pub ts_init: UnixNanos,
}

impl OrderSubmitted {
#[allow(clippy::too_many_arguments)]
pub fn new(
trader_id: TraderId,
strategy_id: StrategyId,
instrument_id: InstrumentId,
client_order_id: ClientOrderId,
account_id: AccountId,
event_id: UUID4,
ts_event: UnixNanos,
ts_init: UnixNanos,
) -> Result<OrderSubmitted> {
Ok(OrderSubmitted {
trader_id,
strategy_id,
instrument_id,
client_order_id,
account_id,
event_id,
ts_event,
ts_init,
})
}
}

impl Display for OrderSubmitted {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"OrderSubmitted(instrument_id={}, client_order_id={}, account_id={}, ts_event={})",
self.instrument_id, self.client_order_id, self.account_id, self.ts_event
)
}
}

////////////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
use rstest::rstest;

use super::*;
use crate::events::order::stubs::*;

#[rstest]
fn test_order_rejected_display(order_submitted: OrderSubmitted) {
let display = format!("{}", order_submitted);
assert_eq!(
display,
"OrderSubmitted(instrument_id=BTCUSDT.COINBASE, client_order_id=O-20200814-102234-001-001-1, account_id=SIM-001, ts_event=0)"
);
}
}
7 changes: 7 additions & 0 deletions nautilus_core/model/src/identifiers/stubs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.
// -------------------------------------------------------------------------------------------------

use nautilus_core::uuid::UUID4;
use rstest::fixture;

use crate::identifiers::{
Expand Down Expand Up @@ -142,3 +143,9 @@ pub fn venue_sim() -> Venue {
pub fn venue_order_id() -> VenueOrderId {
VenueOrderId::from("001")
}

// ---- UUID ----
#[fixture]
pub fn uuid4() -> UUID4 {
UUID4::from("16578139-a945-4b65-b46c-bc131a15d8e7")
}
1 change: 1 addition & 0 deletions nautilus_core/model/src/python/events/order/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ pub mod denied;
pub mod filled;
pub mod initialized;
pub mod rejected;
pub mod submitted;
pub mod triggered;
112 changes: 112 additions & 0 deletions nautilus_core/model/src/python/events/order/submitted.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// -------------------------------------------------------------------------------------------------
// Copyright (C) 2015-2023 Nautech Systems Pty Ltd. All rights reserved.
// https://nautechsystems.io
//
// Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
// You may not use this file except in compliance with the License.
// You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// -------------------------------------------------------------------------------------------------

use nautilus_core::{
python::{serialization::from_dict_pyo3, to_pyvalue_err},
time::UnixNanos,
uuid::UUID4,
};
use pyo3::{basic::CompareOp, prelude::*, types::PyDict};
use rust_decimal::prelude::ToPrimitive;

use crate::{
events::order::submitted::OrderSubmitted,
identifiers::{
account_id::AccountId, client_order_id::ClientOrderId, instrument_id::InstrumentId,
strategy_id::StrategyId, trader_id::TraderId,
},
};

#[pymethods]
impl OrderSubmitted {
#[allow(clippy::too_many_arguments)]
#[new]
fn py_new(
trader_id: TraderId,
strategy_id: StrategyId,
instrument_id: InstrumentId,
client_order_id: ClientOrderId,
account_id: AccountId,
event_id: UUID4,
ts_event: UnixNanos,
ts_init: UnixNanos,
) -> PyResult<Self> {
Self::new(
trader_id,
strategy_id,
instrument_id,
client_order_id,
account_id,
event_id,
ts_event,
ts_init,
)
.map_err(to_pyvalue_err)
}

fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
match op {
CompareOp::Eq => self.eq(other).into_py(py),
CompareOp::Ne => self.ne(other).into_py(py),
_ => py.NotImplemented(),
}
}

fn __repr__(&self) -> String {
format!(
"{}(trader_id={}, strategy_id={}, instrument_id={}, client_order_id={}, account_id={}, event_id={}, ts_event={}, ts_init={})",
stringify!(OrderSubmitted),
self.trader_id,
self.strategy_id,
self.instrument_id,
self.client_order_id,
self.account_id,
self.event_id,
self.ts_event,
self.ts_init
)
}

fn __str__(&self) -> String {
format!(
"{}(instrument_id={}, client_order_id={}, account_id={}, ts_event={})",
stringify!(OrderSubmitted),
self.instrument_id,
self.client_order_id,
self.account_id,
self.ts_event,
)
}

#[staticmethod]
#[pyo3(name = "from_dict")]
fn py_from_dict(py: Python<'_>, values: Py<PyDict>) -> PyResult<Self> {
from_dict_pyo3(py, values)
}

#[pyo3(name = "to_dict")]
fn py_to_dict(&self, py: Python<'_>) -> PyResult<PyObject> {
let dict = PyDict::new(py);
dict.set_item("trader_id", self.trader_id.to_string())?;
dict.set_item("strategy_id", self.strategy_id.to_string())?;
dict.set_item("instrument_id", self.instrument_id.to_string())?;
dict.set_item("client_order_id", self.client_order_id.to_string())?;
dict.set_item("account_id", self.account_id.to_string())?;
dict.set_item("event_id", self.event_id.to_string())?;
dict.set_item("ts_event", self.ts_event.to_u64())?;
dict.set_item("ts_init", self.ts_init.to_u64())?;
Ok(dict.into())
}
}
1 change: 1 addition & 0 deletions nautilus_core/model/src/python/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,5 +298,6 @@ pub fn model(_: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<crate::events::order::initialized::OrderInitialized>()?;
m.add_class::<crate::events::order::rejected::OrderRejected>()?;
m.add_class::<crate::events::order::triggered::OrderTriggered>()?;
m.add_class::<crate::events::order::submitted::OrderSubmitted>()?;
Ok(())
}
16 changes: 16 additions & 0 deletions nautilus_trader/core/nautilus_pyo3.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,22 @@ class OrderInitialized:
def from_dict(cls, values: dict[str, str]) -> OrderInitialized: ...
def to_dict(self) -> dict[str, str]: ...

class OrderSubmitted:
def __init__(
self,
trader_id: TraderId,
strategy_id: StrategyId,
instrument_id: InstrumentId,
client_order_id: ClientOrderId,
account_id: AccountId,
event_id: UUID4,
ts_event: int,
ts_init: int,
) -> None: ...
@classmethod
def from_dict(cls, values: dict[str, str]) -> OrderSubmitted: ...
def to_dict(self) -> dict[str, str]: ...


###################################################################################################
# Infrastructure
Expand Down
Loading

0 comments on commit 829ab95

Please sign in to comment.