@@ -107,7 +107,8 @@ pub struct CacheIndex {
107
107
venue_account : HashMap < Venue , AccountId > ,
108
108
venue_orders : HashMap < Venue , HashSet < ClientOrderId > > ,
109
109
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 > ,
111
112
order_position : HashMap < ClientOrderId , PositionId > ,
112
113
order_strategy : HashMap < ClientOrderId , StrategyId > ,
113
114
order_client : HashMap < ClientOrderId , ClientId > ,
@@ -139,7 +140,8 @@ impl CacheIndex {
139
140
self . venue_account . clear ( ) ;
140
141
self . venue_orders . clear ( ) ;
141
142
self . venue_positions . clear ( ) ;
142
- self . order_ids . clear ( ) ;
143
+ self . venue_order_ids . clear ( ) ;
144
+ self . client_order_ids . clear ( ) ;
143
145
self . order_position . clear ( ) ;
144
146
self . order_strategy . clear ( ) ;
145
147
self . order_client . clear ( ) ;
@@ -199,7 +201,8 @@ impl Cache {
199
201
venue_account : HashMap :: new ( ) ,
200
202
venue_orders : HashMap :: new ( ) ,
201
203
venue_positions : HashMap :: new ( ) ,
202
- order_ids : HashMap :: new ( ) ,
204
+ venue_order_ids : HashMap :: new ( ) ,
205
+ client_order_ids : HashMap :: new ( ) ,
203
206
order_position : HashMap :: new ( ) ,
204
207
order_strategy : HashMap :: new ( ) ,
205
208
order_client : HashMap :: new ( ) ,
@@ -362,7 +365,7 @@ impl Cache {
362
365
// 2: Build index.order_ids -> {VenueOrderId, ClientOrderId}
363
366
if let Some ( venue_order_id) = order. venue_order_id ( ) {
364
367
self . index
365
- . order_ids
368
+ . venue_order_ids
366
369
. insert ( venue_order_id, * client_order_id) ;
367
370
}
368
371
@@ -642,10 +645,20 @@ impl Cache {
642
645
}
643
646
}
644
647
645
- for client_order_id in self . index . order_ids . values ( ) {
648
+ for client_order_id in self . index . venue_order_ids . values ( ) {
646
649
if !self . orders . contains_key ( client_order_id) {
647
650
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`" ,
649
662
failure, client_order_id
650
663
) ;
651
664
error_count += 1 ;
@@ -1092,6 +1105,34 @@ impl Cache {
1092
1105
Ok ( ( ) )
1093
1106
}
1094
1107
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
+
1095
1136
/// Add the order to the cache indexed with any given identifiers.
1096
1137
///
1097
1138
/// # Parameters
@@ -1329,8 +1370,12 @@ impl Cache {
1329
1370
1330
1371
// Update venue order ID
1331
1372
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
+ } ;
1334
1379
}
1335
1380
1336
1381
// Update in-flight state
@@ -1719,14 +1764,12 @@ impl Cache {
1719
1764
1720
1765
#[ must_use]
1721
1766
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)
1723
1768
}
1724
1769
1725
1770
#[ 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)
1730
1773
}
1731
1774
1732
1775
#[ must_use]
@@ -2399,7 +2442,7 @@ mod tests {
2399
2442
orders:: { any:: OrderAny , stubs:: TestOrderStubs } ,
2400
2443
polymorphism:: {
2401
2444
ApplyOrderEventAny , GetAccountId , GetClientOrderId , GetInstrumentId , GetStrategyId ,
2402
- GetTraderId , IsOpen ,
2445
+ GetTraderId , GetVenueOrderId , IsOpen ,
2403
2446
} ,
2404
2447
types:: { price:: Price , quantity:: Quantity } ,
2405
2448
} ;
@@ -2528,6 +2571,7 @@ mod tests {
2528
2571
assert_eq ! ( cache. orders_emulated_count( None , None , None , None ) , 0 ) ;
2529
2572
assert_eq ! ( cache. orders_inflight_count( None , None , None , None ) , 0 ) ;
2530
2573
assert_eq ! ( cache. orders_total_count( None , None , None , None ) , 1 ) ;
2574
+ assert_eq ! ( cache. venue_order_id( & order. client_order_id( ) ) , None ) ;
2531
2575
}
2532
2576
2533
2577
#[ rstest]
@@ -2576,6 +2620,7 @@ mod tests {
2576
2620
assert_eq ! ( cache. orders_emulated_count( None , None , None , None ) , 0 ) ;
2577
2621
assert_eq ! ( cache. orders_inflight_count( None , None , None , None ) , 0 ) ;
2578
2622
assert_eq ! ( cache. orders_total_count( None , None , None , None ) , 1 ) ;
2623
+ assert_eq ! ( cache. venue_order_id( & order. client_order_id( ) ) , None ) ;
2579
2624
}
2580
2625
2581
2626
#[ rstest]
@@ -2641,6 +2686,14 @@ mod tests {
2641
2686
assert_eq ! ( cache. orders_emulated_count( None , None , None , None ) , 0 ) ;
2642
2687
assert_eq ! ( cache. orders_inflight_count( None , None , None , None ) , 0 ) ;
2643
2688
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
+ ) ;
2644
2697
}
2645
2698
2646
2699
#[ rstest]
0 commit comments