Skip to content

Commit ee1c9b2

Browse files
committed
Continue Cache in Rust
1 parent f169cce commit ee1c9b2

File tree

1 file changed

+67
-14
lines changed
  • nautilus_core/common/src/cache

1 file changed

+67
-14
lines changed

nautilus_core/common/src/cache/core.rs

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ pub struct CacheIndex {
107107
venue_account: HashMap<Venue, AccountId>,
108108
venue_orders: HashMap<Venue, HashSet<ClientOrderId>>,
109109
venue_positions: HashMap<Venue, HashSet<PositionId>>,
110-
order_ids: HashMap<VenueOrderId, ClientOrderId>,
110+
venue_order_ids: HashMap<VenueOrderId, ClientOrderId>,
111+
client_order_ids: HashMap<ClientOrderId, VenueOrderId>,
111112
order_position: HashMap<ClientOrderId, PositionId>,
112113
order_strategy: HashMap<ClientOrderId, StrategyId>,
113114
order_client: HashMap<ClientOrderId, ClientId>,
@@ -139,7 +140,8 @@ impl CacheIndex {
139140
self.venue_account.clear();
140141
self.venue_orders.clear();
141142
self.venue_positions.clear();
142-
self.order_ids.clear();
143+
self.venue_order_ids.clear();
144+
self.client_order_ids.clear();
143145
self.order_position.clear();
144146
self.order_strategy.clear();
145147
self.order_client.clear();
@@ -199,7 +201,8 @@ impl Cache {
199201
venue_account: HashMap::new(),
200202
venue_orders: HashMap::new(),
201203
venue_positions: HashMap::new(),
202-
order_ids: HashMap::new(),
204+
venue_order_ids: HashMap::new(),
205+
client_order_ids: HashMap::new(),
203206
order_position: HashMap::new(),
204207
order_strategy: HashMap::new(),
205208
order_client: HashMap::new(),
@@ -362,7 +365,7 @@ impl Cache {
362365
// 2: Build index.order_ids -> {VenueOrderId, ClientOrderId}
363366
if let Some(venue_order_id) = order.venue_order_id() {
364367
self.index
365-
.order_ids
368+
.venue_order_ids
366369
.insert(venue_order_id, *client_order_id);
367370
}
368371

@@ -642,10 +645,20 @@ impl Cache {
642645
}
643646
}
644647

645-
for client_order_id in self.index.order_ids.values() {
648+
for client_order_id in self.index.venue_order_ids.values() {
646649
if !self.orders.contains_key(client_order_id) {
647650
error!(
648-
"{} in `index.order_ids`: {} not found in `self.orders`",
651+
"{} in `index.venue_order_ids`: {} not found in `self.orders`",
652+
failure, client_order_id
653+
);
654+
error_count += 1;
655+
}
656+
}
657+
658+
for client_order_id in self.index.client_order_ids.keys() {
659+
if !self.orders.contains_key(client_order_id) {
660+
error!(
661+
"{} in `index.client_order_ids`: {} not found in `self.orders`",
649662
failure, client_order_id
650663
);
651664
error_count += 1;
@@ -1092,6 +1105,34 @@ impl Cache {
10921105
Ok(())
10931106
}
10941107

1108+
/// Index the given client order ID with the given venue order ID.
1109+
pub fn add_venue_order_id(
1110+
&mut self,
1111+
client_order_id: &ClientOrderId,
1112+
venue_order_id: &VenueOrderId,
1113+
overwrite: bool,
1114+
) -> anyhow::Result<()> {
1115+
if let Some(existing_venue_order_id) = self.index.client_order_ids.get(client_order_id) {
1116+
if !overwrite && existing_venue_order_id != venue_order_id {
1117+
anyhow::bail!(
1118+
"Existing {existing_venue_order_id} for {client_order_id}
1119+
did not match the given {venue_order_id}.
1120+
If you are writing a test then try a different `venue_order_id`,
1121+
otherwise this is probably a bug."
1122+
);
1123+
}
1124+
};
1125+
1126+
self.index
1127+
.client_order_ids
1128+
.insert(*client_order_id, *venue_order_id);
1129+
self.index
1130+
.venue_order_ids
1131+
.insert(*venue_order_id, *client_order_id);
1132+
1133+
Ok(())
1134+
}
1135+
10951136
/// Add the order to the cache indexed with any given identifiers.
10961137
///
10971138
/// # Parameters
@@ -1329,8 +1370,12 @@ impl Cache {
13291370

13301371
// Update venue order ID
13311372
if let Some(venue_order_id) = order.venue_order_id() {
1332-
// Assumes order_id does not change
1333-
self.index.order_ids.insert(venue_order_id, client_order_id);
1373+
// If the order is being modified then we allow a changing `VenueOrderId` to accommodate
1374+
// venues which use a cancel+replace update strategy.
1375+
if !self.index.venue_order_ids.contains_key(&venue_order_id) {
1376+
// TODO: If the last event was `OrderUpdated` then overwrite should be true
1377+
self.add_venue_order_id(&order.client_order_id(), &venue_order_id, false)?;
1378+
};
13341379
}
13351380

13361381
// Update in-flight state
@@ -1719,14 +1764,12 @@ impl Cache {
17191764

17201765
#[must_use]
17211766
pub fn client_order_id(&self, venue_order_id: &VenueOrderId) -> Option<&ClientOrderId> {
1722-
self.index.order_ids.get(venue_order_id)
1767+
self.index.venue_order_ids.get(venue_order_id)
17231768
}
17241769

17251770
#[must_use]
1726-
pub fn venue_order_id(&self, client_order_id: &ClientOrderId) -> Option<VenueOrderId> {
1727-
self.orders
1728-
.get(client_order_id)
1729-
.and_then(nautilus_model::polymorphism::GetVenueOrderId::venue_order_id)
1771+
pub fn venue_order_id(&self, client_order_id: &ClientOrderId) -> Option<&VenueOrderId> {
1772+
self.index.client_order_ids.get(client_order_id)
17301773
}
17311774

17321775
#[must_use]
@@ -2399,7 +2442,7 @@ mod tests {
23992442
orders::{any::OrderAny, stubs::TestOrderStubs},
24002443
polymorphism::{
24012444
ApplyOrderEventAny, GetAccountId, GetClientOrderId, GetInstrumentId, GetStrategyId,
2402-
GetTraderId, IsOpen,
2445+
GetTraderId, GetVenueOrderId, IsOpen,
24032446
},
24042447
types::{price::Price, quantity::Quantity},
24052448
};
@@ -2528,6 +2571,7 @@ mod tests {
25282571
assert_eq!(cache.orders_emulated_count(None, None, None, None), 0);
25292572
assert_eq!(cache.orders_inflight_count(None, None, None, None), 0);
25302573
assert_eq!(cache.orders_total_count(None, None, None, None), 1);
2574+
assert_eq!(cache.venue_order_id(&order.client_order_id()), None);
25312575
}
25322576

25332577
#[rstest]
@@ -2576,6 +2620,7 @@ mod tests {
25762620
assert_eq!(cache.orders_emulated_count(None, None, None, None), 0);
25772621
assert_eq!(cache.orders_inflight_count(None, None, None, None), 0);
25782622
assert_eq!(cache.orders_total_count(None, None, None, None), 1);
2623+
assert_eq!(cache.venue_order_id(&order.client_order_id()), None);
25792624
}
25802625

25812626
#[rstest]
@@ -2641,6 +2686,14 @@ mod tests {
26412686
assert_eq!(cache.orders_emulated_count(None, None, None, None), 0);
26422687
assert_eq!(cache.orders_inflight_count(None, None, None, None), 0);
26432688
assert_eq!(cache.orders_total_count(None, None, None, None), 1);
2689+
assert_eq!(
2690+
cache.client_order_id(&order.venue_order_id().unwrap()),
2691+
Some(&order.client_order_id())
2692+
);
2693+
assert_eq!(
2694+
cache.venue_order_id(&order.client_order_id()),
2695+
Some(&order.venue_order_id().unwrap())
2696+
);
26442697
}
26452698

26462699
#[rstest]

0 commit comments

Comments
 (0)