Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into sandbox
Browse files Browse the repository at this point in the history
  • Loading branch information
davidsblom committed Apr 27, 2024
2 parents 605c920 + 6fe3ae3 commit 23eb610
Show file tree
Hide file tree
Showing 12 changed files with 451 additions and 36 deletions.
20 changes: 10 additions & 10 deletions nautilus_core/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion nautilus_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ rand = "0.8.5"
rmp-serde = "1.2.0"
rust_decimal = "1.35.0"
rust_decimal_macros = "1.34.2"
serde = { version = "1.0.198", features = ["derive"] }
serde = { version = "1.0.199", features = ["derive"] }
serde_json = "1.0.116"
strum = { version = "0.26.2", features = ["derive"] }
thiserror = "1.0.59"
Expand Down
257 changes: 249 additions & 8 deletions nautilus_core/common/src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use nautilus_model::{
quote::QuoteTick,
trade::TradeTick,
},
enums::{AggregationSource, OrderSide, PositionSide, PriceType},
enums::{AggregationSource, OrderSide, PositionSide, PriceType, TriggerType},
identifiers::{
account_id::AccountId, client_id::ClientId, client_order_id::ClientOrderId,
component_id::ComponentId, exec_algorithm_id::ExecAlgorithmId, instrument_id::InstrumentId,
Expand All @@ -42,8 +42,9 @@ use nautilus_model::{
orderbook::book::OrderBook,
orders::{base::OrderAny, list::OrderList},
polymorphism::{
GetClientOrderId, GetExecAlgorithmId, GetExecSpawnId, GetInstrumentId, GetOrderFilledQty,
GetOrderLeavesQty, GetOrderQuantity, GetOrderSide, GetStrategyId, IsClosed,
GetClientOrderId, GetEmulationTrigger, GetExecAlgorithmId, GetExecSpawnId, GetInstrumentId,
GetOrderFilledQty, GetOrderLeavesQty, GetOrderQuantity, GetOrderSide, GetPositionId,
GetStrategyId, GetVenueOrderId, IsClosed, IsInflight, IsOpen,
},
position::Position,
types::{currency::Currency, price::Price, quantity::Quantity},
Expand Down Expand Up @@ -330,8 +331,212 @@ impl Cache {
Ok(())
}

pub fn build_index(&self) {
todo!() // Needs order query methods
pub fn build_index(&mut self) {
self.index.clear();
debug!("Building index");

// Index accounts
for account_id in self.accounts.keys() {
self.index
.venue_account
.insert(account_id.get_issuer(), *account_id);
}

// Index orders
for (client_order_id, order) in &self.orders {
let instrument_id = order.instrument_id();
let venue = instrument_id.venue;
let strategy_id = order.strategy_id();

// 1: Build _index_venue_orders -> {Venue, {ClientOrderId}}
if let Some(venue_orders) = self.index.venue_orders.get_mut(&venue) {
venue_orders.insert(*client_order_id);
} else {
let mut venue_orders = HashSet::new();
venue_orders.insert(*client_order_id);
self.index.venue_orders.insert(venue, venue_orders);
}

// 2: Build _index_order_ids -> {VenueOrderId, ClientOrderId}
if let Some(venue_order_id) = order.venue_order_id() {
self.index
.order_ids
.insert(venue_order_id, *client_order_id);
}

// 3: Build _index_order_position -> {ClientOrderId, PositionId}
if let Some(position_id) = order.position_id() {
self.index
.order_position
.insert(*client_order_id, position_id);
}

// 4: Build _index_order_strategy -> {ClientOrderId, StrategyId}
self.index
.order_strategy
.insert(*client_order_id, order.strategy_id());

// 5: Build _index_instrument_orders -> {InstrumentId, {ClientOrderId}}
if let Some(instrument_orders) = self.index.instrument_orders.get_mut(&instrument_id) {
instrument_orders.insert(*client_order_id);
} else {
let mut instrument_orders = HashSet::new();
instrument_orders.insert(*client_order_id);
self.index
.instrument_orders
.insert(instrument_id, instrument_orders);
}

// 6: Build _index_strategy_orders -> {StrategyId, {ClientOrderId}}
if let Some(strategy_orders) = self.index.strategy_orders.get_mut(&strategy_id) {
strategy_orders.insert(*client_order_id);
} else {
let mut strategy_orders = HashSet::new();
strategy_orders.insert(*client_order_id);
self.index
.strategy_orders
.insert(strategy_id, strategy_orders);
}

// 7: Build _index_exec_algorithm_orders -> {ExecAlgorithmId, {ClientOrderId}}
if let Some(exec_algorithm_id) = order.exec_algorithm_id() {
if let Some(exec_algorithm_orders) =
self.index.exec_algorithm_orders.get_mut(&exec_algorithm_id)
{
exec_algorithm_orders.insert(*client_order_id);
} else {
let mut exec_algorithm_orders = HashSet::new();
exec_algorithm_orders.insert(*client_order_id);
self.index
.exec_algorithm_orders
.insert(exec_algorithm_id, exec_algorithm_orders);
}
}

// 8: Build _index_exec_spawn_orders -> {ClientOrderId, {ClientOrderId}}
if let Some(exec_spawn_id) = order.exec_spawn_id() {
if let Some(exec_spawn_orders) =
self.index.exec_spawn_orders.get_mut(&exec_spawn_id)
{
exec_spawn_orders.insert(*client_order_id);
} else {
let mut exec_spawn_orders = HashSet::new();
exec_spawn_orders.insert(*client_order_id);
self.index
.exec_spawn_orders
.insert(exec_spawn_id, exec_spawn_orders);
}
}

// 9: Build _index_orders -> {ClientOrderId}
self.index.orders.insert(*client_order_id);

// 10: Build _index_orders_open -> {ClientOrderId}
if order.is_open() {
self.index.orders_open.insert(*client_order_id);
}

// 11: Build _index_orders_closed -> {ClientOrderId}
if order.is_closed() {
self.index.orders_closed.insert(*client_order_id);
}

// 12: Build _index_orders_emulated -> {ClientOrderId}
if let Some(emulation_trigger) = order.emulation_trigger() {
if emulation_trigger != TriggerType::NoTrigger && !order.is_closed() {
self.index.orders_emulated.insert(*client_order_id);
}
}

// 13: Build _index_orders_inflight -> {ClientOrderId}
if order.is_inflight() {
self.index.orders_inflight.insert(*client_order_id);
}

// 14: Build _index_strategies -> {StrategyId}
self.index.strategies.insert(strategy_id);

// 15: Build _index_strategies -> {ExecAlgorithmId}
if let Some(exec_algorithm_id) = order.exec_algorithm_id() {
self.index.exec_algorithms.insert(exec_algorithm_id);
}
}

// Index positions
for (position_id, position) in &self.positions {
let instrument_id = position.instrument_id;
let venue = instrument_id.venue;
let strategy_id = position.strategy_id;

// 1: Build _index_venue_positions -> {Venue, {PositionId}}
if let Some(venue_positions) = self.index.venue_positions.get_mut(&venue) {
venue_positions.insert(*position_id);
} else {
let mut venue_positions = HashSet::new();
venue_positions.insert(*position_id);
self.index.venue_positions.insert(venue, venue_positions);
}

// 2: Build _index_position_strategy -> {PositionId, StrategyId}
self.index
.position_strategy
.insert(*position_id, position.strategy_id);

// 3: Build _index_position_orders -> {PositionId, {ClientOrderId}}
if let Some(position_orders) = self.index.position_orders.get_mut(position_id) {
for client_order_id in position.client_order_ids() {
position_orders.insert(client_order_id);
}
} else {
let mut position_orders = HashSet::new();
for client_order_id in position.client_order_ids() {
position_orders.insert(client_order_id);
}
self.index
.position_orders
.insert(*position_id, position_orders);
}

// 4: Build _index_instrument_positions -> {InstrumentId, {PositionId}}
if let Some(instrument_positions) =
self.index.instrument_positions.get_mut(&instrument_id)
{
instrument_positions.insert(*position_id);
} else {
let mut instrument_positions = HashSet::new();
instrument_positions.insert(*position_id);
self.index
.instrument_positions
.insert(instrument_id, instrument_positions);
}

// 5: Build _index_strategy_positions -> {StrategyId, {PositionId}}
if let Some(strategy_positions) = self.index.strategy_positions.get_mut(&strategy_id) {
strategy_positions.insert(*position_id);
} else {
let mut strategy_positions = HashSet::new();
strategy_positions.insert(*position_id);
self.index
.strategy_positions
.insert(strategy_id, strategy_positions);
}

// 6: Build _index_positions -> {PositionId}
self.index.positions.insert(*position_id);

// 7: Build _index_positions_open -> {PositionId}
if position.is_open() {
self.index.positions_open.insert(*position_id);
}

// 8: Build _index_positions_closed -> {PositionId}
if position.is_closed() {
self.index.positions_closed.insert(*position_id);
}

// 9: Build _index_strategies -> {StrategyId}
self.index.strategies.insert(strategy_id);
}
}

#[must_use]
Expand Down Expand Up @@ -1196,7 +1401,7 @@ impl Cache {
let mut order_lists = self.order_lists.values().collect::<Vec<&OrderList>>();

if let Some(venue) = venue {
order_lists.retain(|ol| ol.instrument_id.venue == *venue);
order_lists.retain(|ol| &ol.instrument_id.venue == venue);
}

if let Some(instrument_id) = instrument_id {
Expand Down Expand Up @@ -1701,14 +1906,50 @@ mod tests {
}

#[rstest]
fn test_general_when_no_value() {
fn test_cache_general_load_when_no_database() {
let mut cache = Cache::default();
assert!(cache.cache_general().is_ok());
}

#[rstest]
fn test_cache_currencies_load_when_no_database() {
let mut cache = Cache::default();
assert!(cache.cache_currencies().is_ok());
}

#[rstest]
fn test_cache_instruments_load_when_no_database() {
let mut cache = Cache::default();
assert!(cache.cache_instruments().is_ok());
}

#[rstest]
fn test_cache_synthetics_when_no_database() {
let mut cache = Cache::default();
assert!(cache.cache_synthetics().is_ok());
}

#[rstest]
fn test_cache_orders_when_no_database() {
let mut cache = Cache::default();
assert!(cache.cache_orders().is_ok());
}

#[rstest]
fn test_cache_positions_when_no_database() {
let mut cache = Cache::default();
assert!(cache.cache_positions().is_ok());
}

#[rstest]
fn test_get_general_when_no_value() {
let cache = Cache::default();
let result = cache.get("A").unwrap();
assert_eq!(result, None);
}

#[rstest]
fn test_general_when_value() {
fn test_add_general_when_value() {
let mut cache = Cache::default();

let key = "A";
Expand Down
4 changes: 2 additions & 2 deletions nautilus_core/common/src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use std::{
use nautilus_core::{
correctness::{check_positive_u64, check_valid_string},
datetime::floor_to_nearest_microsecond,
nanos::{TimedeltaNanos, UnixNanos},
nanos::{DurationNanos, UnixNanos},
time::get_atomic_clock_realtime,
uuid::UUID4,
};
Expand Down Expand Up @@ -123,7 +123,7 @@ impl Ord for TimeEventHandler {
pub trait Timer {
fn new(
name: Ustr,
interval_ns: TimedeltaNanos,
interval_ns: DurationNanos,
start_time_ns: UnixNanos,
stop_time_ns: Option<UnixNanos>,
) -> Self;
Expand Down
Loading

0 comments on commit 23eb610

Please sign in to comment.