@@ -281,3 +281,269 @@ impl PartialEq for StopOrderAny {
281
281
}
282
282
}
283
283
}
284
+
285
+ ////////////////////////////////////////////////////////////////////////////////
286
+ // Tests
287
+ ////////////////////////////////////////////////////////////////////////////////
288
+ #[ cfg( test) ]
289
+ mod tests {
290
+ use rust_decimal:: Decimal ;
291
+
292
+ use super :: * ;
293
+ use crate :: {
294
+ enums:: { OrderType , TrailingOffsetType } ,
295
+ events:: { OrderEventAny , OrderUpdated , order:: initialized:: OrderInitializedBuilder } ,
296
+ identifiers:: { ClientOrderId , InstrumentId , StrategyId } ,
297
+ orders:: builder:: OrderTestBuilder ,
298
+ types:: { Price , Quantity } ,
299
+ } ;
300
+
301
+ #[ test]
302
+ fn test_order_any_equality ( ) {
303
+ // Create two orders with different types but same client_order_id
304
+ let client_order_id = ClientOrderId :: from ( "ORDER-001" ) ;
305
+
306
+ let market_order = OrderTestBuilder :: new ( OrderType :: Market )
307
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
308
+ . quantity ( Quantity :: from ( 10 ) )
309
+ . client_order_id ( client_order_id. clone ( ) )
310
+ . build ( ) ;
311
+
312
+ let limit_order = OrderTestBuilder :: new ( OrderType :: Limit )
313
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
314
+ . quantity ( Quantity :: from ( 10 ) )
315
+ . price ( Price :: new ( 100.0 , 2 ) )
316
+ . client_order_id ( client_order_id)
317
+ . build ( ) ;
318
+
319
+ // They should be equal because they have the same client_order_id
320
+ assert_eq ! ( market_order, limit_order) ;
321
+ }
322
+
323
+ #[ test]
324
+ fn test_order_any_conversion_from_events ( ) {
325
+ // Create an OrderInitialized event
326
+ let init_event = OrderInitializedBuilder :: default ( )
327
+ . order_type ( OrderType :: Market )
328
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
329
+ . quantity ( Quantity :: from ( 10 ) )
330
+ . build ( )
331
+ . unwrap ( ) ;
332
+
333
+ // Create a vector of events
334
+ let events = vec ! [ OrderEventAny :: Initialized ( init_event. clone( ) ) ] ;
335
+
336
+ // Create OrderAny from events
337
+ let order = OrderAny :: from_events ( events) . unwrap ( ) ;
338
+
339
+ // Verify the order was created properly
340
+ assert_eq ! ( order. order_type( ) , OrderType :: Market ) ;
341
+ assert_eq ! ( order. instrument_id( ) , init_event. instrument_id) ;
342
+ assert_eq ! ( order. quantity( ) , init_event. quantity) ;
343
+ }
344
+
345
+ #[ test]
346
+ fn test_order_any_from_events_empty_error ( ) {
347
+ let events: Vec < OrderEventAny > = vec ! [ ] ;
348
+ let result = OrderAny :: from_events ( events) ;
349
+
350
+ assert ! ( result. is_err( ) ) ;
351
+ assert_eq ! (
352
+ result. unwrap_err( ) . to_string( ) ,
353
+ "No order events provided to create OrderAny"
354
+ ) ;
355
+ }
356
+
357
+ #[ test]
358
+ fn test_order_any_from_events_wrong_first_event ( ) {
359
+ // Create an event that is not OrderInitialized
360
+ let client_order_id = ClientOrderId :: from ( "ORDER-001" ) ;
361
+ let strategy_id = StrategyId :: from ( "STRATEGY-001" ) ;
362
+
363
+ let update_event = OrderUpdated {
364
+ client_order_id,
365
+ strategy_id,
366
+ quantity : Quantity :: from ( 20 ) ,
367
+ ..Default :: default ( )
368
+ } ;
369
+
370
+ // Create a vector with a non-initialization event first
371
+ let events = vec ! [ OrderEventAny :: Updated ( update_event) ] ;
372
+
373
+ // Attempt to create order should fail
374
+ let result = OrderAny :: from_events ( events) ;
375
+ assert ! ( result. is_err( ) ) ;
376
+ assert_eq ! (
377
+ result. unwrap_err( ) . to_string( ) ,
378
+ "First event must be `OrderInitialized`"
379
+ ) ;
380
+ }
381
+
382
+ #[ test]
383
+ fn test_passive_order_any_conversion ( ) {
384
+ // Create a limit order
385
+ let limit_order = OrderTestBuilder :: new ( OrderType :: Limit )
386
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
387
+ . quantity ( Quantity :: from ( 10 ) )
388
+ . price ( Price :: new ( 100.0 , 2 ) )
389
+ . build ( ) ;
390
+
391
+ // Convert to PassiveOrderAny and back
392
+ let passive_order: PassiveOrderAny = limit_order. clone ( ) . into ( ) ;
393
+ let order_any: OrderAny = passive_order. into ( ) ;
394
+
395
+ // Verify it maintained its properties
396
+ assert_eq ! ( order_any. order_type( ) , OrderType :: Limit ) ;
397
+ assert_eq ! ( order_any. quantity( ) , Quantity :: from( 10 ) ) ;
398
+ }
399
+
400
+ #[ test]
401
+ fn test_stop_order_any_conversion ( ) {
402
+ // Create a stop market order
403
+ let stop_order = OrderTestBuilder :: new ( OrderType :: StopMarket )
404
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
405
+ . quantity ( Quantity :: from ( 10 ) )
406
+ . trigger_price ( Price :: new ( 100.0 , 2 ) )
407
+ . build ( ) ;
408
+
409
+ // Convert to StopOrderAny and back
410
+ let stop_order_any: StopOrderAny = stop_order. into ( ) ;
411
+ let order_any: OrderAny = stop_order_any. into ( ) ;
412
+
413
+ // Verify it maintained its properties
414
+ assert_eq ! ( order_any. order_type( ) , OrderType :: StopMarket ) ;
415
+ assert_eq ! ( order_any. quantity( ) , Quantity :: from( 10 ) ) ;
416
+ assert_eq ! ( order_any. trigger_price( ) , Some ( Price :: new( 100.0 , 2 ) ) ) ;
417
+ }
418
+
419
+ #[ test]
420
+ fn test_limit_order_any_conversion ( ) {
421
+ // Create a limit order
422
+ let limit_order = OrderTestBuilder :: new ( OrderType :: Limit )
423
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
424
+ . quantity ( Quantity :: from ( 10 ) )
425
+ . price ( Price :: new ( 100.0 , 2 ) )
426
+ . build ( ) ;
427
+
428
+ // Convert to LimitOrderAny and back
429
+ let limit_order_any: LimitOrderAny = limit_order. into ( ) ;
430
+ let order_any: OrderAny = limit_order_any. into ( ) ;
431
+
432
+ // Verify it maintained its properties
433
+ assert_eq ! ( order_any. order_type( ) , OrderType :: Limit ) ;
434
+ assert_eq ! ( order_any. quantity( ) , Quantity :: from( 10 ) ) ;
435
+ }
436
+
437
+ #[ test]
438
+ fn test_limit_order_any_limit_price ( ) {
439
+ // Create a limit order
440
+ let limit_order = OrderTestBuilder :: new ( OrderType :: Limit )
441
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
442
+ . quantity ( Quantity :: from ( 10 ) )
443
+ . price ( Price :: new ( 100.0 , 2 ) )
444
+ . build ( ) ;
445
+
446
+ // Convert to LimitOrderAny
447
+ let limit_order_any: LimitOrderAny = limit_order. into ( ) ;
448
+
449
+ // Check limit price accessor
450
+ let limit_px = limit_order_any. limit_px ( ) ;
451
+ assert_eq ! ( limit_px, Price :: new( 100.0 , 2 ) ) ;
452
+ }
453
+
454
+ #[ test]
455
+ fn test_stop_order_any_stop_price ( ) {
456
+ // Create a stop market order
457
+ let stop_order = OrderTestBuilder :: new ( OrderType :: StopMarket )
458
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
459
+ . quantity ( Quantity :: from ( 10 ) )
460
+ . trigger_price ( Price :: new ( 100.0 , 2 ) )
461
+ . build ( ) ;
462
+
463
+ // Convert to StopOrderAny
464
+ let stop_order_any: StopOrderAny = stop_order. into ( ) ;
465
+
466
+ // Check stop price accessor
467
+ let stop_px = stop_order_any. stop_px ( ) ;
468
+ assert_eq ! ( stop_px, Price :: new( 100.0 , 2 ) ) ;
469
+ }
470
+
471
+ #[ test]
472
+ fn test_trailing_stop_market_order_conversion ( ) {
473
+ // Create a trailing stop market order
474
+ let trailing_stop_order = OrderTestBuilder :: new ( OrderType :: TrailingStopMarket )
475
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
476
+ . quantity ( Quantity :: from ( 10 ) )
477
+ . trigger_price ( Price :: new ( 100.0 , 2 ) )
478
+ . trailing_offset ( Decimal :: new ( 5 , 1 ) ) // 0.5
479
+ . trailing_offset_type ( TrailingOffsetType :: NoTrailingOffset )
480
+ . build ( ) ;
481
+
482
+ // Convert to StopOrderAny
483
+ let stop_order_any: StopOrderAny = trailing_stop_order. clone ( ) . into ( ) ;
484
+
485
+ // And back to OrderAny
486
+ let order_any: OrderAny = stop_order_any. into ( ) ;
487
+
488
+ // Verify properties are preserved
489
+ assert_eq ! ( order_any. order_type( ) , OrderType :: TrailingStopMarket ) ;
490
+ assert_eq ! ( order_any. quantity( ) , Quantity :: from( 10 ) ) ;
491
+ assert_eq ! ( order_any. trigger_price( ) , Some ( Price :: new( 100.0 , 2 ) ) ) ;
492
+ assert_eq ! ( order_any. trailing_offset( ) , Some ( Decimal :: new( 5 , 1 ) ) ) ;
493
+ assert_eq ! (
494
+ order_any. trailing_offset_type( ) ,
495
+ Some ( TrailingOffsetType :: NoTrailingOffset )
496
+ ) ;
497
+ }
498
+
499
+ #[ test]
500
+ fn test_trailing_stop_limit_order_conversion ( ) {
501
+ // Create a trailing stop limit order
502
+ let trailing_stop_limit = OrderTestBuilder :: new ( OrderType :: TrailingStopLimit )
503
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
504
+ . quantity ( Quantity :: from ( 10 ) )
505
+ . price ( Price :: new ( 99.0 , 2 ) )
506
+ . trigger_price ( Price :: new ( 100.0 , 2 ) )
507
+ . limit_offset ( Decimal :: new ( 10 , 1 ) ) // 1.0
508
+ . trailing_offset ( Decimal :: new ( 5 , 1 ) ) // 0.5
509
+ . trailing_offset_type ( TrailingOffsetType :: NoTrailingOffset )
510
+ . build ( ) ;
511
+
512
+ // Convert to LimitOrderAny
513
+ let limit_order_any: LimitOrderAny = trailing_stop_limit. clone ( ) . into ( ) ;
514
+
515
+ // Check limit price
516
+ assert_eq ! ( limit_order_any. limit_px( ) , Price :: new( 99.0 , 2 ) ) ;
517
+
518
+ // Convert back to OrderAny
519
+ let order_any: OrderAny = limit_order_any. into ( ) ;
520
+
521
+ // Verify properties are preserved
522
+ assert_eq ! ( order_any. order_type( ) , OrderType :: TrailingStopLimit ) ;
523
+ assert_eq ! ( order_any. quantity( ) , Quantity :: from( 10 ) ) ;
524
+ assert_eq ! ( order_any. price( ) , Some ( Price :: new( 99.0 , 2 ) ) ) ;
525
+ assert_eq ! ( order_any. trigger_price( ) , Some ( Price :: new( 100.0 , 2 ) ) ) ;
526
+ assert_eq ! ( order_any. trailing_offset( ) , Some ( Decimal :: new( 5 , 1 ) ) ) ;
527
+ }
528
+
529
+ #[ test]
530
+ fn test_passive_order_any_to_any ( ) {
531
+ // Create a limit order
532
+ let limit_order = OrderTestBuilder :: new ( OrderType :: Limit )
533
+ . instrument_id ( InstrumentId :: from ( "BTC-USDT.BINANCE" ) )
534
+ . quantity ( Quantity :: from ( 10 ) )
535
+ . price ( Price :: new ( 100.0 , 2 ) )
536
+ . build ( ) ;
537
+
538
+ // Convert to PassiveOrderAny
539
+ let passive_order: PassiveOrderAny = limit_order. into ( ) ;
540
+
541
+ // Use to_any method
542
+ let order_any = passive_order. to_any ( ) ;
543
+
544
+ // Verify it maintained its properties
545
+ assert_eq ! ( order_any. order_type( ) , OrderType :: Limit ) ;
546
+ assert_eq ! ( order_any. quantity( ) , Quantity :: from( 10 ) ) ;
547
+ assert_eq ! ( order_any. price( ) , Some ( Price :: new( 100.0 , 2 ) ) ) ;
548
+ }
549
+ }
0 commit comments