Skip to main content

truefix_twsapi_client/
events.rs

1use rust_decimal::Decimal;
2
3use crate::enums::{FaDataType, MarketDataType, TickType};
4use crate::types::{
5    BarData, CommissionAndFeesReport, Contract, ContractDescription, ContractDetails,
6    DeltaNeutralContract, Execution, FamilyCode, HistogramEntry, HistoricalSession, HistoricalTick,
7    HistoricalTickBidAsk, HistoricalTickLast, NewsProvider, Order, OrderState, PriceIncrement,
8    SmartComponent, SoftDollarTier, TickByTick,
9};
10use crate::types::{DepthMarketDataDescription, RealTimeBar, WshEventData};
11
12/// Scanner row data.
13#[derive(Debug, Clone, PartialEq)]
14pub struct ScannerDataRow {
15    /// Rank.
16    pub rank: i32,
17    /// Contract.
18    pub contract: Box<Contract>,
19    /// Market name.
20    pub market_name: String,
21    /// Distance.
22    pub distance: String,
23    /// Benchmark.
24    pub benchmark: String,
25    /// Projection.
26    pub projection: String,
27    /// Combo key.
28    pub combo_key: String,
29}
30
31/// A normalized TWS callback event.
32#[derive(Debug, Clone, PartialEq)]
33pub enum Event {
34    /// Connection completed.
35    ConnectAck,
36    /// Connection closed.
37    ConnectionClosed,
38    /// Error callback.
39    Error {
40        /// Request id.
41        req_id: i32,
42        /// Error time in milliseconds or server-provided timestamp.
43        time: i64,
44        /// Error code.
45        code: i32,
46        /// Error message.
47        message: String,
48        /// Advanced order reject payload.
49        advanced_order_reject_json: String,
50    },
51    /// Next valid order id.
52    NextValidId {
53        /// Order id.
54        order_id: i32,
55    },
56    /// Current time.
57    CurrentTime {
58        /// Unix timestamp seconds.
59        time: i64,
60    },
61    /// Current time in milliseconds.
62    CurrentTimeInMillis {
63        /// Unix timestamp milliseconds.
64        time_in_millis: i64,
65    },
66    /// Market data type.
67    MarketDataType {
68        /// Request id.
69        req_id: i32,
70        /// Market data type.
71        market_data_type: i32,
72    },
73    /// Tick price.
74    TickPrice {
75        /// Request id.
76        req_id: i32,
77        /// Tick type.
78        tick_type: i32,
79        /// Price.
80        price: f64,
81        /// Attributes as raw bitset.
82        attrib: i32,
83    },
84    /// Tick size.
85    TickSize {
86        /// Request id.
87        req_id: i32,
88        /// Tick type.
89        tick_type: i32,
90        /// Size.
91        size: Decimal,
92    },
93    /// Generic tick value.
94    TickGeneric {
95        /// Request id.
96        req_id: i32,
97        /// Tick type.
98        tick_type: i32,
99        /// Value.
100        value: f64,
101    },
102    /// Tick string.
103    TickString {
104        /// Request id.
105        req_id: i32,
106        /// Tick type.
107        tick_type: i32,
108        /// Value.
109        value: String,
110    },
111    /// Exchange-for-physical tick.
112    TickEfp {
113        /// Request id.
114        req_id: i32,
115        /// Tick type.
116        tick_type: i32,
117        /// Basis points.
118        basis_points: f64,
119        /// Formatted basis points.
120        formatted_basis_points: String,
121        /// Total dividends.
122        total_dividends: f64,
123        /// Hold days.
124        hold_days: i32,
125        /// Future last trade date.
126        future_last_trade_date: String,
127        /// Dividend impact.
128        dividend_impact: f64,
129        /// Dividends to last trade date.
130        dividends_to_last_trade_date: f64,
131    },
132    /// Tick snapshot end.
133    TickSnapshotEnd {
134        /// Request id.
135        req_id: i32,
136    },
137    /// Option computation tick.
138    TickOptionComputation {
139        /// Request id.
140        req_id: i32,
141        /// Tick type.
142        tick_type: i32,
143        /// Attribute bitset.
144        tick_attrib: i32,
145        /// Implied volatility.
146        implied_vol: f64,
147        /// Delta.
148        delta: f64,
149        /// Option price.
150        opt_price: f64,
151        /// Present value dividend.
152        pv_dividend: f64,
153        /// Gamma.
154        gamma: f64,
155        /// Vega.
156        vega: f64,
157        /// Theta.
158        theta: f64,
159        /// Underlying price.
160        und_price: f64,
161    },
162    /// Tick request parameters.
163    TickReqParams {
164        /// Request id.
165        req_id: i32,
166        /// Minimum tick.
167        min_tick: String,
168        /// BBO exchange.
169        bbo_exchange: String,
170        /// Snapshot permissions.
171        snapshot_permissions: i32,
172        /// Last price precision.
173        last_price_precision: String,
174        /// Last size precision.
175        last_size_precision: String,
176    },
177    /// Commission and fees report callback.
178    CommissionAndFeesReport {
179        /// Report.
180        report: CommissionAndFeesReport,
181    },
182    /// Delta-neutral validation callback.
183    DeltaNeutralValidation {
184        /// Request id.
185        req_id: i32,
186        /// Delta-neutral contract.
187        delta_neutral_contract: DeltaNeutralContract,
188    },
189    /// Order status.
190    OrderStatus {
191        /// Order id.
192        order_id: i32,
193        /// Status text.
194        status: String,
195        /// Filled quantity.
196        filled: Decimal,
197        /// Remaining quantity.
198        remaining: Decimal,
199        /// Average fill price.
200        avg_fill_price: f64,
201        /// Permanent id.
202        perm_id: i64,
203        /// Parent id.
204        parent_id: i32,
205        /// Last fill price.
206        last_fill_price: f64,
207        /// Client id.
208        client_id: i32,
209        /// Why held.
210        why_held: String,
211        /// Market cap price.
212        market_cap_price: f64,
213    },
214    /// Open order callback.
215    OpenOrder {
216        /// Order id.
217        order_id: i32,
218        /// Contract.
219        contract: Box<Contract>,
220        /// Order.
221        order: Box<Order>,
222        /// Order state.
223        order_state: Box<OrderState>,
224    },
225    /// Open order end.
226    OpenOrderEnd,
227    /// Contract details.
228    ContractDetails {
229        /// Request id.
230        req_id: i32,
231        /// Details.
232        details: Box<ContractDetails>,
233    },
234    /// Bond contract details.
235    BondContractDetails {
236        /// Request id.
237        req_id: i32,
238        /// Details.
239        details: Box<ContractDetails>,
240    },
241    /// Contract details end.
242    ContractDetailsEnd {
243        /// Request id.
244        req_id: i32,
245    },
246    /// Execution details.
247    ExecutionDetails {
248        /// Request id.
249        req_id: i32,
250        /// Contract.
251        contract: Box<Contract>,
252        /// Execution details.
253        execution: Execution,
254    },
255    /// Execution details end.
256    ExecutionDetailsEnd {
257        /// Request id.
258        req_id: i32,
259    },
260    /// Market depth update.
261    MarketDepth {
262        /// Request id.
263        req_id: i32,
264        /// Position.
265        position: i32,
266        /// Operation.
267        operation: i32,
268        /// Side.
269        side: i32,
270        /// Price.
271        price: f64,
272        /// Size.
273        size: Decimal,
274        /// Market maker.
275        market_maker: String,
276        /// Smart depth flag.
277        is_smart_depth: bool,
278    },
279    /// Market depth exchanges.
280    MarketDepthExchanges {
281        /// Exchange descriptions.
282        descriptions: Vec<DepthMarketDataDescription>,
283    },
284    /// Smart components callback.
285    SmartComponents {
286        /// Request id.
287        req_id: i32,
288        /// Components.
289        components: Vec<SmartComponent>,
290    },
291    /// Reroute market-data request.
292    RerouteMarketDataRequest {
293        /// Request id.
294        req_id: i32,
295        /// Contract id.
296        con_id: i32,
297        /// Exchange.
298        exchange: String,
299    },
300    /// Reroute market-depth request.
301    RerouteMarketDepthRequest {
302        /// Request id.
303        req_id: i32,
304        /// Contract id.
305        con_id: i32,
306        /// Exchange.
307        exchange: String,
308    },
309    /// Historical data bar.
310    HistoricalData {
311        /// Request id.
312        req_id: i32,
313        /// Bar.
314        bar: BarData,
315    },
316    /// Historical data batch.
317    HistoricalDataBars {
318        /// Request id.
319        req_id: i32,
320        /// Bars.
321        bars: Vec<BarData>,
322    },
323    /// Historical data update.
324    HistoricalDataUpdate {
325        /// Request id.
326        req_id: i32,
327        /// Bar.
328        bar: BarData,
329    },
330    /// Historical data end.
331    HistoricalDataEnd {
332        /// Request id.
333        req_id: i32,
334        /// Start marker.
335        start: String,
336        /// End marker.
337        end: String,
338    },
339    /// Historical midpoint/trade ticks callback.
340    HistoricalTicks {
341        /// Request id.
342        req_id: i32,
343        /// Ticks.
344        ticks: Vec<HistoricalTick>,
345        /// Done marker.
346        done: bool,
347    },
348    /// Historical bid/ask ticks callback.
349    HistoricalTicksBidAsk {
350        /// Request id.
351        req_id: i32,
352        /// Ticks.
353        ticks: Vec<HistoricalTickBidAsk>,
354        /// Done marker.
355        done: bool,
356    },
357    /// Historical last trade ticks callback.
358    HistoricalTicksLast {
359        /// Request id.
360        req_id: i32,
361        /// Ticks.
362        ticks: Vec<HistoricalTickLast>,
363        /// Done marker.
364        done: bool,
365    },
366    /// Tick-by-tick callback.
367    TickByTick {
368        /// Request id.
369        req_id: i32,
370        /// Tick type.
371        tick_type: i32,
372        /// Tick payload.
373        tick: Option<TickByTick>,
374    },
375    /// Historical schedule callback.
376    HistoricalSchedule {
377        /// Request id.
378        req_id: i32,
379        /// Schedule start.
380        start_date_time: String,
381        /// Schedule end.
382        end_date_time: String,
383        /// Time zone.
384        time_zone: String,
385        /// Sessions.
386        sessions: Vec<HistoricalSession>,
387    },
388    /// Position callback.
389    Position {
390        /// Account.
391        account: String,
392        /// Contract.
393        contract: Box<Contract>,
394        /// Position.
395        position: Decimal,
396        /// Average cost.
397        avg_cost: f64,
398    },
399    /// Position end.
400    PositionEnd,
401    /// Position multi callback.
402    PositionMulti {
403        /// Request id.
404        req_id: i32,
405        /// Account.
406        account: String,
407        /// Model code.
408        model_code: String,
409        /// Contract.
410        contract: Box<Contract>,
411        /// Position.
412        position: Decimal,
413        /// Average cost.
414        avg_cost: f64,
415    },
416    /// Position multi end.
417    PositionMultiEnd {
418        /// Request id.
419        req_id: i32,
420    },
421    /// Account value update.
422    AccountValue {
423        /// Key.
424        key: String,
425        /// Value.
426        value: String,
427        /// Currency.
428        currency: String,
429        /// Account name.
430        account_name: String,
431    },
432    /// Portfolio value update.
433    PortfolioValue {
434        /// Contract.
435        contract: Box<Contract>,
436        /// Position.
437        position: Decimal,
438        /// Market price.
439        market_price: f64,
440        /// Market value.
441        market_value: f64,
442        /// Average cost.
443        average_cost: f64,
444        /// Unrealized PnL.
445        unrealized_pnl: f64,
446        /// Realized PnL.
447        realized_pnl: f64,
448        /// Account name.
449        account_name: String,
450    },
451    /// Account update time.
452    AccountUpdateTime {
453        /// Timestamp.
454        timestamp: String,
455    },
456    /// Account download end.
457    AccountDownloadEnd {
458        /// Account name.
459        account_name: String,
460    },
461    /// Account summary.
462    AccountSummary {
463        /// Request id.
464        req_id: i32,
465        /// Account.
466        account: String,
467        /// Tag.
468        tag: String,
469        /// Value.
470        value: String,
471        /// Currency.
472        currency: String,
473    },
474    /// Account summary end.
475    AccountSummaryEnd {
476        /// Request id.
477        req_id: i32,
478    },
479    /// Account update multi.
480    AccountUpdateMulti {
481        /// Request id.
482        req_id: i32,
483        /// Account.
484        account: String,
485        /// Model code.
486        model_code: String,
487        /// Key.
488        key: String,
489        /// Value.
490        value: String,
491        /// Currency.
492        currency: String,
493    },
494    /// Account update multi end.
495    AccountUpdateMultiEnd {
496        /// Request id.
497        req_id: i32,
498    },
499    /// Real-time bar tick.
500    RealTimeBar {
501        /// Request id.
502        req_id: i32,
503        /// Unix timestamp seconds.
504        time: i64,
505        /// Bar.
506        bar: BarData,
507    },
508    /// Head timestamp.
509    HeadTimestamp {
510        /// Request id.
511        req_id: i32,
512        /// Head timestamp.
513        head_timestamp: String,
514    },
515    /// Histogram data.
516    HistogramData {
517        /// Request id.
518        req_id: i32,
519        /// Price/size entries.
520        items: Vec<HistogramEntry>,
521    },
522    /// Scanner parameters XML.
523    ScannerParameters {
524        /// XML payload.
525        xml: String,
526    },
527    /// Scanner data.
528    ScannerData {
529        /// Request id.
530        req_id: i32,
531        /// Rows.
532        rows: Vec<ScannerDataRow>,
533    },
534    /// Scanner data end.
535    ScannerDataEnd {
536        /// Request id.
537        req_id: i32,
538    },
539    /// Soft-dollar tiers.
540    SoftDollarTiers {
541        /// Request id.
542        req_id: i32,
543        /// Tiers.
544        tiers: Vec<SoftDollarTier>,
545    },
546    /// Family codes.
547    FamilyCodes {
548        /// Account family-code mappings.
549        family_codes: Vec<FamilyCode>,
550    },
551    /// Symbol samples callback.
552    SymbolSamples {
553        /// Request id.
554        req_id: i32,
555        /// Contract descriptions.
556        descriptions: Vec<ContractDescription>,
557    },
558    /// Security definition option parameter callback.
559    SecurityDefinitionOptionParameter {
560        /// Request id.
561        req_id: i32,
562        /// Exchange.
563        exchange: String,
564        /// Underlying contract id.
565        underlying_con_id: i32,
566        /// Trading class.
567        trading_class: String,
568        /// Multiplier.
569        multiplier: String,
570        /// Expirations.
571        expirations: Vec<String>,
572        /// Strikes.
573        strikes: Vec<f64>,
574    },
575    /// Security definition option parameter end.
576    SecurityDefinitionOptionParameterEnd {
577        /// Request id.
578        req_id: i32,
579    },
580    /// Market rule.
581    MarketRule {
582        /// Market rule id.
583        market_rule_id: i32,
584        /// Price increments.
585        price_increments: Vec<PriceIncrement>,
586    },
587    /// PnL update.
588    Pnl {
589        /// Request id.
590        req_id: i32,
591        /// Daily PnL.
592        daily_pnl: f64,
593        /// Unrealized PnL.
594        unrealized_pnl: f64,
595        /// Realized PnL.
596        realized_pnl: f64,
597    },
598    /// Single-contract PnL update.
599    PnlSingle {
600        /// Request id.
601        req_id: i32,
602        /// Position.
603        position: Decimal,
604        /// Daily PnL.
605        daily_pnl: f64,
606        /// Unrealized PnL.
607        unrealized_pnl: f64,
608        /// Realized PnL.
609        realized_pnl: f64,
610        /// Value.
611        value: f64,
612    },
613    /// News article body.
614    NewsArticle {
615        /// Request id.
616        req_id: i32,
617        /// Article type.
618        article_type: i32,
619        /// Article text.
620        article_text: String,
621    },
622    /// News bulletin.
623    NewsBulletin {
624        /// Message id.
625        news_msg_id: i32,
626        /// Message type.
627        news_msg_type: i32,
628        /// Message text.
629        news_message: String,
630        /// Originating exchange.
631        originating_exch: String,
632    },
633    /// News providers.
634    NewsProviders {
635        /// Provider metadata.
636        providers: Vec<NewsProvider>,
637    },
638    /// Historical news item.
639    HistoricalNews {
640        /// Request id.
641        req_id: i32,
642        /// Time.
643        time: String,
644        /// Provider code.
645        provider_code: String,
646        /// Article id.
647        article_id: String,
648        /// Headline.
649        headline: String,
650    },
651    /// Historical news end.
652    HistoricalNewsEnd {
653        /// Request id.
654        req_id: i32,
655        /// Whether more data is available.
656        has_more: bool,
657    },
658    /// Tick news item.
659    TickNews {
660        /// Request id.
661        req_id: i32,
662        /// Timestamp.
663        timestamp: i64,
664        /// Provider code.
665        provider_code: String,
666        /// Article id.
667        article_id: String,
668        /// Headline.
669        headline: String,
670        /// Extra data.
671        extra_data: String,
672    },
673    /// WSH metadata.
674    WshMetaData {
675        /// Request id.
676        req_id: i32,
677        /// JSON payload.
678        data_json: String,
679    },
680    /// WSH event data.
681    WshEventData {
682        /// Request id.
683        req_id: i32,
684        /// JSON payload.
685        data_json: String,
686    },
687    /// Receive FA data.
688    ReceiveFa {
689        /// FA data type.
690        fa_data_type: i32,
691        /// XML payload.
692        xml: String,
693    },
694    /// Replace FA end.
695    ReplaceFaEnd {
696        /// Request id.
697        req_id: i32,
698        /// Response text.
699        text: String,
700    },
701    /// Display group list.
702    DisplayGroupList {
703        /// Request id.
704        req_id: i32,
705        /// Groups.
706        groups: String,
707    },
708    /// Display group updated.
709    DisplayGroupUpdated {
710        /// Request id.
711        req_id: i32,
712        /// Contract info.
713        contract_info: String,
714    },
715    /// Verify message API.
716    VerifyMessageApi {
717        /// API data.
718        api_data: String,
719    },
720    /// Verify completed.
721    VerifyCompleted {
722        /// Success flag.
723        is_successful: bool,
724        /// Error text.
725        error_text: String,
726    },
727    /// Verify-and-auth message API.
728    VerifyAndAuthMessageApi {
729        /// API data.
730        api_data: String,
731        /// Challenge payload.
732        challenge: String,
733    },
734    /// Verify-and-auth completed.
735    VerifyAndAuthCompleted {
736        /// Success flag.
737        is_successful: bool,
738        /// Error text.
739        error_text: String,
740    },
741    /// Config response.
742    ConfigResponse {
743        /// Request id.
744        req_id: i32,
745        /// Status.
746        status: String,
747        /// Message.
748        message: String,
749    },
750    /// Update config response.
751    UpdateConfigResponse {
752        /// Request id.
753        req_id: i32,
754        /// Status.
755        status: String,
756        /// Message.
757        message: String,
758        /// Changed fields.
759        changed_fields: Vec<String>,
760        /// Errors.
761        errors: Vec<String>,
762    },
763    /// Order bound callback.
764    OrderBound {
765        /// Permanent id.
766        perm_id: i64,
767        /// Client id.
768        client_id: i32,
769        /// Order id.
770        order_id: i32,
771    },
772    /// Completed order callback.
773    CompletedOrder {
774        /// Contract.
775        contract: Box<Contract>,
776        /// Order.
777        order: Box<Order>,
778        /// Order state.
779        order_state: Box<OrderState>,
780    },
781    /// Completed orders end.
782    CompletedOrdersEnd,
783    /// User info callback.
784    UserInfo {
785        /// Request id.
786        req_id: i32,
787        /// White-branding id.
788        white_branding_id: String,
789    },
790    /// Managed account list.
791    ManagedAccounts {
792        /// Comma-separated accounts.
793        accounts: String,
794    },
795    /// Raw callback not decoded into a typed variant yet.
796    Raw {
797        /// Message id.
798        msg_id: i32,
799        /// Raw fields.
800        fields: Vec<String>,
801    },
802    /// Raw protobuf callback not decoded by this crate.
803    RawProtobuf {
804        /// Message id without protobuf offset.
805        msg_id: i32,
806        /// Raw payload.
807        payload: Vec<u8>,
808    },
809}
810
811/// Callback sink for TWS events.
812///
813/// Implementors can override either [`Wrapper::on_event`] or individual typed methods.
814#[allow(clippy::too_many_arguments)]
815pub trait Wrapper: Send {
816    /// Receives every event.
817    fn on_event(&mut self, _event: Event) {}
818
819    /// Connection completed.
820    fn connect_ack(&mut self) {}
821
822    /// Connection closed.
823    fn connection_closed(&mut self) {}
824
825    /// Error callback.
826    fn error(&mut self, _req_id: i32, _time: i64, _code: i32, _message: String) {}
827
828    /// Next valid id.
829    fn next_valid_id(&mut self, _order_id: i32) {}
830
831    /// Current time.
832    fn current_time(&mut self, _time: i64) {}
833
834    /// Current time in milliseconds.
835    fn current_time_in_millis(&mut self, _time_in_millis: i64) {}
836
837    /// Dispatches an event to its typed callback.
838    fn dispatch(&mut self, event: Event) {
839        self.on_event(event.clone());
840        match event {
841            Event::ConnectAck => self.connect_ack(),
842            Event::ConnectionClosed => self.connection_closed(),
843            Event::MarketDataType {
844                req_id,
845                market_data_type,
846            } => {
847                self.market_data_type(req_id, MarketDataType::from_i32(market_data_type));
848            }
849            Event::TickPrice {
850                req_id,
851                tick_type,
852                price,
853                attrib,
854            } => {
855                self.tick_price(req_id, TickType::from_i32(tick_type), price, attrib);
856            }
857            Event::TickSize {
858                req_id,
859                tick_type,
860                size,
861            } => {
862                self.tick_size(req_id, TickType::from_i32(tick_type), size);
863            }
864            Event::TickGeneric {
865                req_id,
866                tick_type,
867                value,
868            } => {
869                self.tick_generic(req_id, TickType::from_i32(tick_type), value);
870            }
871            Event::TickString {
872                req_id,
873                tick_type,
874                value,
875            } => {
876                self.tick_string(req_id, TickType::from_i32(tick_type), value);
877            }
878            Event::TickEfp {
879                req_id,
880                tick_type,
881                basis_points,
882                formatted_basis_points,
883                total_dividends,
884                hold_days,
885                future_last_trade_date,
886                dividend_impact,
887                dividends_to_last_trade_date,
888            } => self.tick_efp(
889                req_id,
890                TickType::from_i32(tick_type),
891                basis_points,
892                formatted_basis_points,
893                total_dividends,
894                hold_days,
895                future_last_trade_date,
896                dividend_impact,
897                dividends_to_last_trade_date,
898            ),
899            Event::TickSnapshotEnd { req_id } => self.tick_snapshot_end(req_id),
900            Event::TickOptionComputation {
901                req_id,
902                tick_type,
903                tick_attrib,
904                implied_vol,
905                delta,
906                opt_price,
907                pv_dividend,
908                gamma,
909                vega,
910                theta,
911                und_price,
912            } => self.tick_option_computation(
913                req_id,
914                TickType::from_i32(tick_type),
915                tick_attrib,
916                implied_vol,
917                delta,
918                opt_price,
919                pv_dividend,
920                gamma,
921                vega,
922                theta,
923                und_price,
924            ),
925            Event::TickReqParams {
926                req_id,
927                min_tick,
928                bbo_exchange,
929                snapshot_permissions,
930                last_price_precision,
931                last_size_precision,
932            } => self.tick_req_params(
933                req_id,
934                min_tick,
935                bbo_exchange,
936                snapshot_permissions,
937                last_price_precision,
938                last_size_precision,
939            ),
940            Event::CommissionAndFeesReport { report } => self.commission_and_fees_report(report),
941            Event::DeltaNeutralValidation {
942                req_id,
943                delta_neutral_contract,
944            } => self.delta_neutral_validation(req_id, delta_neutral_contract),
945            Event::NextValidId { order_id } => self.next_valid_id(order_id),
946            Event::CurrentTime { time } => self.current_time(time),
947            Event::CurrentTimeInMillis { time_in_millis } => {
948                self.current_time_in_millis(time_in_millis)
949            }
950            Event::Error {
951                req_id,
952                time,
953                code,
954                message,
955                advanced_order_reject_json,
956            } => {
957                self.error_with_advanced(req_id, time, code, message, advanced_order_reject_json);
958            }
959            Event::OrderStatus {
960                order_id,
961                status,
962                filled,
963                remaining,
964                avg_fill_price,
965                perm_id,
966                parent_id,
967                last_fill_price,
968                client_id,
969                why_held,
970                market_cap_price,
971            } => {
972                self.order_status(
973                    order_id,
974                    status,
975                    filled,
976                    remaining,
977                    avg_fill_price,
978                    perm_id,
979                    parent_id,
980                    last_fill_price,
981                    client_id,
982                    why_held,
983                    market_cap_price,
984                );
985            }
986            Event::OpenOrder {
987                order_id,
988                contract,
989                order,
990                order_state,
991            } => {
992                self.open_order(order_id, *contract, *order, *order_state);
993            }
994            Event::ContractDetails { req_id, details } => self.contract_details(req_id, *details),
995            Event::BondContractDetails { req_id, details } => {
996                self.bond_contract_details(req_id, *details)
997            }
998            Event::OpenOrderEnd => self.open_order_end(),
999            Event::ContractDetailsEnd { req_id } => self.contract_details_end(req_id),
1000            Event::ExecutionDetails {
1001                req_id,
1002                contract,
1003                execution,
1004            } => self.execution_details(req_id, *contract, execution),
1005            Event::ExecutionDetailsEnd { req_id } => self.execution_details_end(req_id),
1006            Event::MarketDepth {
1007                req_id,
1008                position,
1009                operation,
1010                side,
1011                price,
1012                size,
1013                market_maker,
1014                is_smart_depth,
1015            } => self.market_depth(
1016                req_id,
1017                position,
1018                operation,
1019                side,
1020                price,
1021                size,
1022                market_maker,
1023                is_smart_depth,
1024            ),
1025            Event::SmartComponents { req_id, components } => {
1026                self.smart_components(req_id, components)
1027            }
1028            Event::RerouteMarketDataRequest {
1029                req_id,
1030                con_id,
1031                exchange,
1032            } => self.reroute_market_data(req_id, con_id, exchange),
1033            Event::RerouteMarketDepthRequest {
1034                req_id,
1035                con_id,
1036                exchange,
1037            } => self.reroute_market_depth(req_id, con_id, exchange),
1038            Event::HistoricalData { req_id, bar } => self.historical_data(req_id, bar),
1039            Event::HistoricalDataBars { req_id, bars } => self.historical_data_bars(req_id, bars),
1040            Event::HistoricalDataUpdate { req_id, bar } => self.historical_data_update(req_id, bar),
1041            Event::HistoricalDataEnd { req_id, start, end } => {
1042                self.historical_data_end(req_id, start, end)
1043            }
1044            Event::HistoricalTicks {
1045                req_id,
1046                ticks,
1047                done,
1048            } => self.historical_ticks(req_id, ticks, done),
1049            Event::HistoricalTicksBidAsk {
1050                req_id,
1051                ticks,
1052                done,
1053            } => self.historical_ticks_bid_ask(req_id, ticks, done),
1054            Event::HistoricalTicksLast {
1055                req_id,
1056                ticks,
1057                done,
1058            } => self.historical_ticks_last(req_id, ticks, done),
1059            Event::TickByTick {
1060                req_id,
1061                tick_type,
1062                tick,
1063            } => self.tick_by_tick(req_id, TickType::from_i32(tick_type), tick),
1064            Event::HistoricalSchedule {
1065                req_id,
1066                start_date_time,
1067                end_date_time,
1068                time_zone,
1069                sessions,
1070            } => self.historical_schedule(
1071                req_id,
1072                start_date_time,
1073                end_date_time,
1074                time_zone,
1075                sessions,
1076            ),
1077            Event::RealTimeBar { req_id, time, bar } => self.real_time_bar(
1078                req_id,
1079                RealTimeBar {
1080                    time,
1081                    end_time: time + 5,
1082                    open: bar.open,
1083                    high: bar.high,
1084                    low: bar.low,
1085                    close: bar.close,
1086                    volume: bar.volume,
1087                    wap: bar.wap,
1088                    count: bar.bar_count,
1089                },
1090            ),
1091            Event::Position {
1092                account,
1093                contract,
1094                position,
1095                avg_cost,
1096            } => self.position(account, *contract, position, avg_cost),
1097            Event::PositionEnd => self.position_end(),
1098            Event::PositionMulti {
1099                req_id,
1100                account,
1101                model_code,
1102                contract,
1103                position,
1104                avg_cost,
1105            } => self.position_multi(req_id, account, model_code, *contract, position, avg_cost),
1106            Event::PositionMultiEnd { req_id } => self.position_multi_end(req_id),
1107            Event::AccountValue {
1108                key,
1109                value,
1110                currency,
1111                account_name,
1112            } => self.account_value(key, value, currency, account_name),
1113            Event::AccountSummary {
1114                req_id,
1115                account,
1116                tag,
1117                value,
1118                currency,
1119            } => self.account_summary(req_id, account, tag, value, currency),
1120            Event::PortfolioValue {
1121                contract,
1122                position,
1123                market_price,
1124                market_value,
1125                average_cost,
1126                unrealized_pnl,
1127                realized_pnl,
1128                account_name,
1129            } => self.portfolio_value(
1130                *contract,
1131                position,
1132                market_price,
1133                market_value,
1134                average_cost,
1135                unrealized_pnl,
1136                realized_pnl,
1137                account_name,
1138            ),
1139            Event::AccountUpdateTime { timestamp } => self.account_update_time(timestamp),
1140            Event::AccountDownloadEnd { account_name } => self.account_download_end(account_name),
1141            Event::AccountSummaryEnd { req_id } => self.account_summary_end(req_id),
1142            Event::AccountUpdateMulti {
1143                req_id,
1144                account,
1145                model_code,
1146                key,
1147                value,
1148                currency,
1149            } => self.account_update_multi(req_id, account, model_code, key, value, currency),
1150            Event::AccountUpdateMultiEnd { req_id } => self.account_update_multi_end(req_id),
1151            Event::FamilyCodes { family_codes } => self.family_codes(family_codes),
1152            Event::NewsProviders { providers } => self.news_providers(providers),
1153            Event::MarketDepthExchanges { descriptions } => {
1154                self.market_depth_exchanges(descriptions)
1155            }
1156            Event::MarketRule {
1157                market_rule_id,
1158                price_increments,
1159            } => self.market_rule(market_rule_id, price_increments),
1160            Event::ReceiveFa { fa_data_type, xml } => {
1161                self.receive_fa(FaDataType::from_i32(fa_data_type), xml)
1162            }
1163            Event::WshEventData { req_id, data_json } => {
1164                self.wsh_event_data(WshEventData::from_json(req_id, data_json))
1165            }
1166            Event::HeadTimestamp {
1167                req_id,
1168                head_timestamp,
1169            } => self.head_timestamp(req_id, head_timestamp),
1170            Event::HistogramData { req_id, items } => self.histogram_data(req_id, items),
1171            Event::ScannerParameters { xml } => self.scanner_parameters(xml),
1172            Event::ScannerData { req_id, rows } => self.scanner_data(req_id, rows),
1173            Event::ScannerDataEnd { req_id } => self.scanner_data_end(req_id),
1174            Event::SoftDollarTiers { req_id, tiers } => self.soft_dollar_tiers(req_id, tiers),
1175            Event::SymbolSamples {
1176                req_id,
1177                descriptions,
1178            } => self.symbol_samples(req_id, descriptions),
1179            Event::SecurityDefinitionOptionParameter {
1180                req_id,
1181                exchange,
1182                underlying_con_id,
1183                trading_class,
1184                multiplier,
1185                expirations,
1186                strikes,
1187            } => self.security_definition_option_parameter(
1188                req_id,
1189                exchange,
1190                underlying_con_id,
1191                trading_class,
1192                multiplier,
1193                expirations,
1194                strikes,
1195            ),
1196            Event::SecurityDefinitionOptionParameterEnd { req_id } => {
1197                self.security_definition_option_parameter_end(req_id)
1198            }
1199            Event::Pnl {
1200                req_id,
1201                daily_pnl,
1202                unrealized_pnl,
1203                realized_pnl,
1204            } => self.pnl(req_id, daily_pnl, unrealized_pnl, realized_pnl),
1205            Event::PnlSingle {
1206                req_id,
1207                position,
1208                daily_pnl,
1209                unrealized_pnl,
1210                realized_pnl,
1211                value,
1212            } => self.pnl_single(
1213                req_id,
1214                position,
1215                daily_pnl,
1216                unrealized_pnl,
1217                realized_pnl,
1218                value,
1219            ),
1220            Event::NewsArticle {
1221                req_id,
1222                article_type,
1223                article_text,
1224            } => self.news_article(req_id, article_type, article_text),
1225            Event::NewsBulletin {
1226                news_msg_id,
1227                news_msg_type,
1228                news_message,
1229                originating_exch,
1230            } => self.news_bulletin(news_msg_id, news_msg_type, news_message, originating_exch),
1231            Event::HistoricalNews {
1232                req_id,
1233                time,
1234                provider_code,
1235                article_id,
1236                headline,
1237            } => self.historical_news(req_id, time, provider_code, article_id, headline),
1238            Event::HistoricalNewsEnd { req_id, has_more } => {
1239                self.historical_news_end(req_id, has_more)
1240            }
1241            Event::TickNews {
1242                req_id,
1243                timestamp,
1244                provider_code,
1245                article_id,
1246                headline,
1247                extra_data,
1248            } => self.tick_news(
1249                req_id,
1250                timestamp,
1251                provider_code,
1252                article_id,
1253                headline,
1254                extra_data,
1255            ),
1256            Event::WshMetaData { req_id, data_json } => self.wsh_metadata(req_id, data_json),
1257            Event::ReplaceFaEnd { req_id, text } => self.replace_fa_end(req_id, text),
1258            Event::DisplayGroupList { req_id, groups } => self.display_group_list(req_id, groups),
1259            Event::DisplayGroupUpdated {
1260                req_id,
1261                contract_info,
1262            } => self.display_group_updated(req_id, contract_info),
1263            Event::ManagedAccounts { accounts } => self.managed_accounts(accounts),
1264            Event::VerifyMessageApi { api_data } => self.verify_message_api(api_data),
1265            Event::VerifyCompleted {
1266                is_successful,
1267                error_text,
1268            } => self.verify_completed(is_successful, error_text),
1269            Event::VerifyAndAuthMessageApi {
1270                api_data,
1271                challenge,
1272            } => self.verify_and_auth_message_api(api_data, challenge),
1273            Event::VerifyAndAuthCompleted {
1274                is_successful,
1275                error_text,
1276            } => self.verify_and_auth_completed(is_successful, error_text),
1277            Event::ConfigResponse {
1278                req_id,
1279                status,
1280                message,
1281            } => self.config_response(req_id, status, message),
1282            Event::UpdateConfigResponse {
1283                req_id,
1284                status,
1285                message,
1286                changed_fields,
1287                errors,
1288            } => self.update_config_response(req_id, status, message, changed_fields, errors),
1289            Event::OrderBound {
1290                perm_id,
1291                client_id,
1292                order_id,
1293            } => self.order_bound(perm_id, client_id, order_id),
1294            Event::CompletedOrder {
1295                contract,
1296                order,
1297                order_state,
1298            } => self.completed_order(*contract, *order, *order_state),
1299            Event::CompletedOrdersEnd => self.completed_orders_end(),
1300            Event::UserInfo {
1301                req_id,
1302                white_branding_id,
1303            } => self.user_info(req_id, white_branding_id),
1304            Event::Raw { msg_id, fields } => self.raw(msg_id, fields),
1305            Event::RawProtobuf { msg_id, payload } => self.raw_protobuf(msg_id, payload),
1306        }
1307    }
1308
1309    /// Typed market-data mode callback.
1310    fn market_data_type(&mut self, _req_id: i32, _data_type: MarketDataType) {}
1311    /// Typed price tick callback.
1312    fn tick_price(&mut self, _req_id: i32, _tick_type: TickType, _price: f64, _attrib: i32) {}
1313    /// Typed size tick callback.
1314    fn tick_size(&mut self, _req_id: i32, _tick_type: TickType, _size: Decimal) {}
1315    /// Typed generic tick callback.
1316    fn tick_generic(&mut self, _req_id: i32, _tick_type: TickType, _value: f64) {}
1317    /// Typed string tick callback.
1318    fn tick_string(&mut self, _req_id: i32, _tick_type: TickType, _value: String) {}
1319    /// Error callback including advanced reject details.
1320    fn error_with_advanced(
1321        &mut self,
1322        req_id: i32,
1323        time: i64,
1324        code: i32,
1325        message: String,
1326        _advanced: String,
1327    ) {
1328        self.error(req_id, time, code, message);
1329    }
1330    fn order_status(
1331        &mut self,
1332        _order_id: i32,
1333        _status: String,
1334        _filled: Decimal,
1335        _remaining: Decimal,
1336        _avg_fill_price: f64,
1337        _perm_id: i64,
1338        _parent_id: i32,
1339        _last_fill_price: f64,
1340        _client_id: i32,
1341        _why_held: String,
1342        _market_cap_price: f64,
1343    ) {
1344    }
1345    fn open_order(
1346        &mut self,
1347        _order_id: i32,
1348        _contract: Contract,
1349        _order: Order,
1350        _order_state: OrderState,
1351    ) {
1352    }
1353    fn contract_details(&mut self, _req_id: i32, _details: ContractDetails) {}
1354    fn bond_contract_details(&mut self, _req_id: i32, _details: ContractDetails) {}
1355    fn historical_data(&mut self, _req_id: i32, _bar: BarData) {}
1356    fn historical_data_bars(&mut self, _req_id: i32, _bars: Vec<BarData>) {}
1357    fn historical_data_update(&mut self, _req_id: i32, _bar: BarData) {}
1358    fn real_time_bar(&mut self, _req_id: i32, _bar: RealTimeBar) {}
1359    fn position(
1360        &mut self,
1361        _account: String,
1362        _contract: Contract,
1363        _position: Decimal,
1364        _avg_cost: f64,
1365    ) {
1366    }
1367    fn position_end(&mut self) {}
1368    fn account_value(
1369        &mut self,
1370        _key: String,
1371        _value: String,
1372        _currency: String,
1373        _account_name: String,
1374    ) {
1375    }
1376    fn account_summary(
1377        &mut self,
1378        _req_id: i32,
1379        _account: String,
1380        _tag: String,
1381        _value: String,
1382        _currency: String,
1383    ) {
1384    }
1385    fn family_codes(&mut self, _codes: Vec<FamilyCode>) {}
1386    fn news_providers(&mut self, _providers: Vec<NewsProvider>) {}
1387    fn market_depth_exchanges(&mut self, _descriptions: Vec<DepthMarketDataDescription>) {}
1388    fn market_rule(&mut self, _market_rule_id: i32, _increments: Vec<PriceIncrement>) {}
1389    fn receive_fa(&mut self, _data_type: FaDataType, _xml: String) {}
1390    fn wsh_event_data(&mut self, _data: WshEventData) {}
1391    fn tick_efp(
1392        &mut self,
1393        _req_id: i32,
1394        _tick_type: TickType,
1395        _basis_points: f64,
1396        _formatted_basis_points: String,
1397        _total_dividends: f64,
1398        _hold_days: i32,
1399        _future_last_trade_date: String,
1400        _dividend_impact: f64,
1401        _dividends_to_last_trade_date: f64,
1402    ) {
1403    }
1404    fn tick_snapshot_end(&mut self, _req_id: i32) {}
1405    fn tick_option_computation(
1406        &mut self,
1407        _req_id: i32,
1408        _tick_type: TickType,
1409        _tick_attrib: i32,
1410        _implied_vol: f64,
1411        _delta: f64,
1412        _opt_price: f64,
1413        _pv_dividend: f64,
1414        _gamma: f64,
1415        _vega: f64,
1416        _theta: f64,
1417        _und_price: f64,
1418    ) {
1419    }
1420    fn tick_req_params(
1421        &mut self,
1422        _req_id: i32,
1423        _min_tick: String,
1424        _bbo_exchange: String,
1425        _snapshot_permissions: i32,
1426        _last_price_precision: String,
1427        _last_size_precision: String,
1428    ) {
1429    }
1430    fn commission_and_fees_report(&mut self, _report: CommissionAndFeesReport) {}
1431    fn delta_neutral_validation(&mut self, _req_id: i32, _contract: DeltaNeutralContract) {}
1432    fn open_order_end(&mut self) {}
1433    fn contract_details_end(&mut self, _req_id: i32) {}
1434    fn execution_details(&mut self, _req_id: i32, _contract: Contract, _execution: Execution) {}
1435    fn execution_details_end(&mut self, _req_id: i32) {}
1436    fn market_depth(
1437        &mut self,
1438        _req_id: i32,
1439        _position: i32,
1440        _operation: i32,
1441        _side: i32,
1442        _price: f64,
1443        _size: Decimal,
1444        _market_maker: String,
1445        _is_smart_depth: bool,
1446    ) {
1447    }
1448    fn smart_components(&mut self, _req_id: i32, _components: Vec<SmartComponent>) {}
1449    fn reroute_market_data(&mut self, _req_id: i32, _con_id: i32, _exchange: String) {}
1450    fn reroute_market_depth(&mut self, _req_id: i32, _con_id: i32, _exchange: String) {}
1451    fn historical_data_end(&mut self, _req_id: i32, _start: String, _end: String) {}
1452    fn historical_ticks(&mut self, _req_id: i32, _ticks: Vec<HistoricalTick>, _done: bool) {}
1453    fn historical_ticks_bid_ask(
1454        &mut self,
1455        _req_id: i32,
1456        _ticks: Vec<HistoricalTickBidAsk>,
1457        _done: bool,
1458    ) {
1459    }
1460    fn historical_ticks_last(
1461        &mut self,
1462        _req_id: i32,
1463        _ticks: Vec<HistoricalTickLast>,
1464        _done: bool,
1465    ) {
1466    }
1467    fn tick_by_tick(&mut self, _req_id: i32, _tick_type: TickType, _tick: Option<TickByTick>) {}
1468    fn historical_schedule(
1469        &mut self,
1470        _req_id: i32,
1471        _start: String,
1472        _end: String,
1473        _time_zone: String,
1474        _sessions: Vec<HistoricalSession>,
1475    ) {
1476    }
1477    fn position_multi(
1478        &mut self,
1479        _req_id: i32,
1480        _account: String,
1481        _model_code: String,
1482        _contract: Contract,
1483        _position: Decimal,
1484        _avg_cost: f64,
1485    ) {
1486    }
1487    fn position_multi_end(&mut self, _req_id: i32) {}
1488    fn portfolio_value(
1489        &mut self,
1490        _contract: Contract,
1491        _position: Decimal,
1492        _market_price: f64,
1493        _market_value: f64,
1494        _average_cost: f64,
1495        _unrealized_pnl: f64,
1496        _realized_pnl: f64,
1497        _account_name: String,
1498    ) {
1499    }
1500    fn account_update_time(&mut self, _timestamp: String) {}
1501    fn account_download_end(&mut self, _account_name: String) {}
1502    fn account_summary_end(&mut self, _req_id: i32) {}
1503    fn account_update_multi(
1504        &mut self,
1505        _req_id: i32,
1506        _account: String,
1507        _model_code: String,
1508        _key: String,
1509        _value: String,
1510        _currency: String,
1511    ) {
1512    }
1513    fn account_update_multi_end(&mut self, _req_id: i32) {}
1514    fn head_timestamp(&mut self, _req_id: i32, _timestamp: String) {}
1515    fn histogram_data(&mut self, _req_id: i32, _items: Vec<HistogramEntry>) {}
1516    fn scanner_parameters(&mut self, _xml: String) {}
1517    fn scanner_data(&mut self, _req_id: i32, _rows: Vec<ScannerDataRow>) {}
1518    fn scanner_data_end(&mut self, _req_id: i32) {}
1519    fn soft_dollar_tiers(&mut self, _req_id: i32, _tiers: Vec<SoftDollarTier>) {}
1520    fn symbol_samples(&mut self, _req_id: i32, _descriptions: Vec<ContractDescription>) {}
1521    fn security_definition_option_parameter(
1522        &mut self,
1523        _req_id: i32,
1524        _exchange: String,
1525        _underlying_con_id: i32,
1526        _trading_class: String,
1527        _multiplier: String,
1528        _expirations: Vec<String>,
1529        _strikes: Vec<f64>,
1530    ) {
1531    }
1532    fn security_definition_option_parameter_end(&mut self, _req_id: i32) {}
1533    fn pnl(&mut self, _req_id: i32, _daily_pnl: f64, _unrealized_pnl: f64, _realized_pnl: f64) {}
1534    fn pnl_single(
1535        &mut self,
1536        _req_id: i32,
1537        _position: Decimal,
1538        _daily_pnl: f64,
1539        _unrealized_pnl: f64,
1540        _realized_pnl: f64,
1541        _value: f64,
1542    ) {
1543    }
1544    fn news_article(&mut self, _req_id: i32, _article_type: i32, _article_text: String) {}
1545    fn news_bulletin(&mut self, _msg_id: i32, _msg_type: i32, _message: String, _exchange: String) {
1546    }
1547    fn historical_news(
1548        &mut self,
1549        _req_id: i32,
1550        _time: String,
1551        _provider_code: String,
1552        _article_id: String,
1553        _headline: String,
1554    ) {
1555    }
1556    fn historical_news_end(&mut self, _req_id: i32, _has_more: bool) {}
1557    fn tick_news(
1558        &mut self,
1559        _req_id: i32,
1560        _timestamp: i64,
1561        _provider_code: String,
1562        _article_id: String,
1563        _headline: String,
1564        _extra_data: String,
1565    ) {
1566    }
1567    fn wsh_metadata(&mut self, _req_id: i32, _data_json: String) {}
1568    fn replace_fa_end(&mut self, _req_id: i32, _text: String) {}
1569    fn display_group_list(&mut self, _req_id: i32, _groups: String) {}
1570    fn display_group_updated(&mut self, _req_id: i32, _contract_info: String) {}
1571    fn managed_accounts(&mut self, _accounts: String) {}
1572    fn verify_message_api(&mut self, _api_data: String) {}
1573    fn verify_completed(&mut self, _is_successful: bool, _error_text: String) {}
1574    fn verify_and_auth_message_api(&mut self, _api_data: String, _challenge: String) {}
1575    fn verify_and_auth_completed(&mut self, _is_successful: bool, _error_text: String) {}
1576    fn config_response(&mut self, _req_id: i32, _status: String, _message: String) {}
1577    fn update_config_response(
1578        &mut self,
1579        _req_id: i32,
1580        _status: String,
1581        _message: String,
1582        _changed_fields: Vec<String>,
1583        _errors: Vec<String>,
1584    ) {
1585    }
1586    fn order_bound(&mut self, _perm_id: i64, _client_id: i32, _order_id: i32) {}
1587    fn completed_order(&mut self, _contract: Contract, _order: Order, _order_state: OrderState) {}
1588    fn completed_orders_end(&mut self) {}
1589    fn user_info(&mut self, _req_id: i32, _white_branding_id: String) {}
1590    fn raw(&mut self, _msg_id: i32, _fields: Vec<String>) {}
1591    fn raw_protobuf(&mut self, _msg_id: i32, _payload: Vec<u8>) {}
1592}
1593
1594impl Event {
1595    /// Returns a semantic tick type for tick events.
1596    pub fn tick_type(&self) -> Option<TickType> {
1597        match self {
1598            Self::TickPrice { tick_type, .. }
1599            | Self::TickSize { tick_type, .. }
1600            | Self::TickGeneric { tick_type, .. }
1601            | Self::TickString { tick_type, .. }
1602            | Self::TickOptionComputation { tick_type, .. }
1603            | Self::TickEfp { tick_type, .. }
1604            | Self::TickByTick { tick_type, .. } => Some(TickType::from_i32(*tick_type)),
1605            _ => None,
1606        }
1607    }
1608
1609    /// Returns a semantic market-data type for a market-data-mode event.
1610    pub fn market_data_type(&self) -> Option<MarketDataType> {
1611        match self {
1612            Self::MarketDataType {
1613                market_data_type, ..
1614            } => Some(MarketDataType::from_i32(*market_data_type)),
1615            _ => None,
1616        }
1617    }
1618}
1619
1620#[cfg(test)]
1621mod tests {
1622    use super::*;
1623
1624    #[derive(Default)]
1625    struct TestWrapper {
1626        tick: Option<TickType>,
1627        wsh_con_id: i32,
1628    }
1629
1630    impl Wrapper for TestWrapper {
1631        fn tick_price(&mut self, _req_id: i32, tick_type: TickType, _price: f64, _attrib: i32) {
1632            self.tick = Some(tick_type);
1633        }
1634
1635        fn wsh_event_data(&mut self, data: WshEventData) {
1636            self.wsh_con_id = data.con_id;
1637        }
1638    }
1639
1640    #[test]
1641    fn dispatches_typed_tick_and_wsh_callbacks() {
1642        let mut wrapper = TestWrapper::default();
1643        wrapper.dispatch(Event::TickPrice {
1644            req_id: 1,
1645            tick_type: 1,
1646            price: 100.0,
1647            attrib: 0,
1648        });
1649        wrapper.dispatch(Event::WshEventData {
1650            req_id: 2,
1651            data_json: r#"{"conId":42,"filter":"e"}"#.to_owned(),
1652        });
1653        assert_eq!(wrapper.tick, Some(TickType::Bid));
1654        assert_eq!(wrapper.wsh_con_id, 42);
1655    }
1656}