@@ -1616,6 +1616,8 @@ mod tests {
16161616 use nautilus_model:: defi:: {
16171617 AmmType , Chain , Dex , DexType , PoolIdentifier , PoolLiquidityUpdateType , Token ,
16181618 } ;
1619+ #[ cfg( any( feature = "sbe" , feature = "capnp" ) ) ]
1620+ use nautilus_model:: { data:: OptionGreekValues , enums:: GreeksConvention } ;
16191621 use nautilus_model:: {
16201622 data:: {
16211623 Bar , FundingRateUpdate , IndexPriceUpdate , MarkPriceUpdate , OptionGreeks ,
@@ -1949,6 +1951,28 @@ mod tests {
19491951 )
19501952 }
19511953
1954+ #[ cfg( any( feature = "sbe" , feature = "capnp" ) ) ]
1955+ fn option_greeks ( ) -> OptionGreeks {
1956+ OptionGreeks {
1957+ instrument_id : InstrumentId :: from ( "BTC-30JUN23-40000-C.DERIBIT" ) ,
1958+ convention : GreeksConvention :: PriceAdjusted ,
1959+ greeks : OptionGreekValues {
1960+ delta : 0.525 ,
1961+ gamma : 0.00032 ,
1962+ vega : 12.25 ,
1963+ theta : -0.72 ,
1964+ rho : 0.18 ,
1965+ } ,
1966+ mark_iv : Some ( 0.0 ) ,
1967+ bid_iv : None ,
1968+ ask_iv : Some ( 0.54 ) ,
1969+ underlying_price : Some ( 41_500.25 ) ,
1970+ open_interest : Some ( 0.0 ) ,
1971+ ts_event : UnixNanos :: from ( 20 ) ,
1972+ ts_init : UnixNanos :: from ( 21 ) ,
1973+ }
1974+ }
1975+
19521976 fn portfolio_snapshot ( ) -> PortfolioSnapshot {
19531977 PortfolioSnapshot :: new (
19541978 AccountId :: from ( "SIM-001" ) ,
@@ -2529,6 +2553,15 @@ mod tests {
25292553 subscribe_funding_rates,
25302554 assert_eq_ref,
25312555 ) ;
2556+ assert_typed_external_round_trips (
2557+ encoding,
2558+ BusPayloadType :: OptionGreeks ,
2559+ "data.option_greeks.BTC-30JUN23-40000-C.DERIBIT" ,
2560+ option_greeks ( ) ,
2561+ publish_option_greeks,
2562+ subscribe_option_greeks,
2563+ assert_eq_ref,
2564+ ) ;
25322565 }
25332566
25342567 #[ cfg( feature = "sbe" ) ]
@@ -2545,7 +2578,6 @@ mod tests {
25452578
25462579 #[ rstest]
25472580 #[ case( BusPayloadType :: AccountState ) ]
2548- #[ case( BusPayloadType :: OptionGreeks ) ]
25492581 fn republish_external_message_skips_unsupported_binary_payload (
25502582 #[ case] payload_type : BusPayloadType ,
25512583 ) {
@@ -2560,16 +2592,6 @@ mod tests {
25602592 } ) ,
25612593 None ,
25622594 ) ;
2563- let greeks_received = received. clone ( ) ;
2564- subscribe_option_greeks (
2565- "events.unsupported.*" . into ( ) ,
2566- TypedHandler :: from ( move |greeks : & OptionGreeks | {
2567- greeks_received
2568- . borrow_mut ( )
2569- . push ( serde_json:: to_value ( greeks) . unwrap ( ) ) ;
2570- } ) ,
2571- None ,
2572- ) ;
25732595
25742596 for encoding in [ SerializationEncoding :: Sbe , SerializationEncoding :: Capnp ] {
25752597 let message = BusMessage :: with_str_topic (
@@ -2631,6 +2653,26 @@ mod tests {
26312653 reset_message_bus ( ) ;
26322654 }
26332655
2656+ #[ cfg( feature = "sbe" ) ]
2657+ #[ rstest]
2658+ fn publish_option_greeks_sbe_forwards_decodable_payload_to_external_egress ( ) {
2659+ let publications = install_capturing_external_egress ( SerializationEncoding :: Sbe ) ;
2660+ let greeks = option_greeks ( ) ;
2661+
2662+ publish_option_greeks ( "data.option_greeks.TEST" . into ( ) , & greeks) ;
2663+
2664+ let publications = publications. borrow ( ) ;
2665+ assert_eq ! ( publications. len( ) , 1 ) ;
2666+ assert_eq ! ( publications[ 0 ] . topic, "data.option_greeks.TEST" ) ;
2667+ assert_eq ! (
2668+ OptionGreeks :: from_sbe( & publications[ 0 ] . payload)
2669+ . expect( "SBE payload must decode as OptionGreeks" ) ,
2670+ greeks
2671+ ) ;
2672+ drop ( publications) ;
2673+ reset_message_bus ( ) ;
2674+ }
2675+
26342676 #[ cfg( not( feature = "sbe" ) ) ]
26352677 #[ rstest]
26362678 fn publish_quote_sbe_without_feature_drops_payload ( ) {
@@ -2669,6 +2711,32 @@ mod tests {
26692711 reset_message_bus ( ) ;
26702712 }
26712713
2714+ #[ cfg( feature = "capnp" ) ]
2715+ #[ rstest]
2716+ fn publish_option_greeks_capnp_forwards_decodable_payload_to_external_egress ( ) {
2717+ let publications = install_capturing_external_egress ( SerializationEncoding :: Capnp ) ;
2718+ let greeks = option_greeks ( ) ;
2719+
2720+ publish_option_greeks ( "data.option_greeks.TEST" . into ( ) , & greeks) ;
2721+
2722+ let publications = publications. borrow ( ) ;
2723+ assert_eq ! ( publications. len( ) , 1 ) ;
2724+ assert_eq ! ( publications[ 0 ] . topic, "data.option_greeks.TEST" ) ;
2725+ let reader = capnp:: serialize:: read_message (
2726+ & mut & publications[ 0 ] . payload [ ..] ,
2727+ capnp:: message:: ReaderOptions :: new ( ) ,
2728+ )
2729+ . expect ( "Cap'n Proto payload must be readable" ) ;
2730+ let root = reader
2731+ . get_root :: < market_capnp:: option_greeks:: Reader > ( )
2732+ . expect ( "Cap'n Proto payload must have an OptionGreeks root" ) ;
2733+ let decoded = OptionGreeks :: from_capnp ( root)
2734+ . expect ( "Cap'n Proto payload must decode as OptionGreeks" ) ;
2735+ assert_eq ! ( decoded, greeks) ;
2736+ drop ( publications) ;
2737+ reset_message_bus ( ) ;
2738+ }
2739+
26722740 #[ cfg( not( feature = "capnp" ) ) ]
26732741 #[ rstest]
26742742 fn publish_quote_capnp_without_feature_drops_payload ( ) {
0 commit comments