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#[derive(Debug, Clone, PartialEq)]
14pub struct ScannerDataRow {
15 pub rank: i32,
17 pub contract: Box<Contract>,
19 pub market_name: String,
21 pub distance: String,
23 pub benchmark: String,
25 pub projection: String,
27 pub combo_key: String,
29}
30
31#[derive(Debug, Clone, PartialEq)]
33pub enum Event {
34 ConnectAck,
36 ConnectionClosed,
38 Error {
40 req_id: i32,
42 time: i64,
44 code: i32,
46 message: String,
48 advanced_order_reject_json: String,
50 },
51 NextValidId {
53 order_id: i32,
55 },
56 CurrentTime {
58 time: i64,
60 },
61 CurrentTimeInMillis {
63 time_in_millis: i64,
65 },
66 MarketDataType {
68 req_id: i32,
70 market_data_type: i32,
72 },
73 TickPrice {
75 req_id: i32,
77 tick_type: i32,
79 price: f64,
81 attrib: i32,
83 },
84 TickSize {
86 req_id: i32,
88 tick_type: i32,
90 size: Decimal,
92 },
93 TickGeneric {
95 req_id: i32,
97 tick_type: i32,
99 value: f64,
101 },
102 TickString {
104 req_id: i32,
106 tick_type: i32,
108 value: String,
110 },
111 TickEfp {
113 req_id: i32,
115 tick_type: i32,
117 basis_points: f64,
119 formatted_basis_points: String,
121 total_dividends: f64,
123 hold_days: i32,
125 future_last_trade_date: String,
127 dividend_impact: f64,
129 dividends_to_last_trade_date: f64,
131 },
132 TickSnapshotEnd {
134 req_id: i32,
136 },
137 TickOptionComputation {
139 req_id: i32,
141 tick_type: i32,
143 tick_attrib: i32,
145 implied_vol: f64,
147 delta: f64,
149 opt_price: f64,
151 pv_dividend: f64,
153 gamma: f64,
155 vega: f64,
157 theta: f64,
159 und_price: f64,
161 },
162 TickReqParams {
164 req_id: i32,
166 min_tick: String,
168 bbo_exchange: String,
170 snapshot_permissions: i32,
172 last_price_precision: String,
174 last_size_precision: String,
176 },
177 CommissionAndFeesReport {
179 report: CommissionAndFeesReport,
181 },
182 DeltaNeutralValidation {
184 req_id: i32,
186 delta_neutral_contract: DeltaNeutralContract,
188 },
189 OrderStatus {
191 order_id: i32,
193 status: String,
195 filled: Decimal,
197 remaining: Decimal,
199 avg_fill_price: f64,
201 perm_id: i64,
203 parent_id: i32,
205 last_fill_price: f64,
207 client_id: i32,
209 why_held: String,
211 market_cap_price: f64,
213 },
214 OpenOrder {
216 order_id: i32,
218 contract: Box<Contract>,
220 order: Box<Order>,
222 order_state: Box<OrderState>,
224 },
225 OpenOrderEnd,
227 ContractDetails {
229 req_id: i32,
231 details: Box<ContractDetails>,
233 },
234 BondContractDetails {
236 req_id: i32,
238 details: Box<ContractDetails>,
240 },
241 ContractDetailsEnd {
243 req_id: i32,
245 },
246 ExecutionDetails {
248 req_id: i32,
250 contract: Box<Contract>,
252 execution: Execution,
254 },
255 ExecutionDetailsEnd {
257 req_id: i32,
259 },
260 MarketDepth {
262 req_id: i32,
264 position: i32,
266 operation: i32,
268 side: i32,
270 price: f64,
272 size: Decimal,
274 market_maker: String,
276 is_smart_depth: bool,
278 },
279 MarketDepthExchanges {
281 descriptions: Vec<DepthMarketDataDescription>,
283 },
284 SmartComponents {
286 req_id: i32,
288 components: Vec<SmartComponent>,
290 },
291 RerouteMarketDataRequest {
293 req_id: i32,
295 con_id: i32,
297 exchange: String,
299 },
300 RerouteMarketDepthRequest {
302 req_id: i32,
304 con_id: i32,
306 exchange: String,
308 },
309 HistoricalData {
311 req_id: i32,
313 bar: BarData,
315 },
316 HistoricalDataBars {
318 req_id: i32,
320 bars: Vec<BarData>,
322 },
323 HistoricalDataUpdate {
325 req_id: i32,
327 bar: BarData,
329 },
330 HistoricalDataEnd {
332 req_id: i32,
334 start: String,
336 end: String,
338 },
339 HistoricalTicks {
341 req_id: i32,
343 ticks: Vec<HistoricalTick>,
345 done: bool,
347 },
348 HistoricalTicksBidAsk {
350 req_id: i32,
352 ticks: Vec<HistoricalTickBidAsk>,
354 done: bool,
356 },
357 HistoricalTicksLast {
359 req_id: i32,
361 ticks: Vec<HistoricalTickLast>,
363 done: bool,
365 },
366 TickByTick {
368 req_id: i32,
370 tick_type: i32,
372 tick: Option<TickByTick>,
374 },
375 HistoricalSchedule {
377 req_id: i32,
379 start_date_time: String,
381 end_date_time: String,
383 time_zone: String,
385 sessions: Vec<HistoricalSession>,
387 },
388 Position {
390 account: String,
392 contract: Box<Contract>,
394 position: Decimal,
396 avg_cost: f64,
398 },
399 PositionEnd,
401 PositionMulti {
403 req_id: i32,
405 account: String,
407 model_code: String,
409 contract: Box<Contract>,
411 position: Decimal,
413 avg_cost: f64,
415 },
416 PositionMultiEnd {
418 req_id: i32,
420 },
421 AccountValue {
423 key: String,
425 value: String,
427 currency: String,
429 account_name: String,
431 },
432 PortfolioValue {
434 contract: Box<Contract>,
436 position: Decimal,
438 market_price: f64,
440 market_value: f64,
442 average_cost: f64,
444 unrealized_pnl: f64,
446 realized_pnl: f64,
448 account_name: String,
450 },
451 AccountUpdateTime {
453 timestamp: String,
455 },
456 AccountDownloadEnd {
458 account_name: String,
460 },
461 AccountSummary {
463 req_id: i32,
465 account: String,
467 tag: String,
469 value: String,
471 currency: String,
473 },
474 AccountSummaryEnd {
476 req_id: i32,
478 },
479 AccountUpdateMulti {
481 req_id: i32,
483 account: String,
485 model_code: String,
487 key: String,
489 value: String,
491 currency: String,
493 },
494 AccountUpdateMultiEnd {
496 req_id: i32,
498 },
499 RealTimeBar {
501 req_id: i32,
503 time: i64,
505 bar: BarData,
507 },
508 HeadTimestamp {
510 req_id: i32,
512 head_timestamp: String,
514 },
515 HistogramData {
517 req_id: i32,
519 items: Vec<HistogramEntry>,
521 },
522 ScannerParameters {
524 xml: String,
526 },
527 ScannerData {
529 req_id: i32,
531 rows: Vec<ScannerDataRow>,
533 },
534 ScannerDataEnd {
536 req_id: i32,
538 },
539 SoftDollarTiers {
541 req_id: i32,
543 tiers: Vec<SoftDollarTier>,
545 },
546 FamilyCodes {
548 family_codes: Vec<FamilyCode>,
550 },
551 SymbolSamples {
553 req_id: i32,
555 descriptions: Vec<ContractDescription>,
557 },
558 SecurityDefinitionOptionParameter {
560 req_id: i32,
562 exchange: String,
564 underlying_con_id: i32,
566 trading_class: String,
568 multiplier: String,
570 expirations: Vec<String>,
572 strikes: Vec<f64>,
574 },
575 SecurityDefinitionOptionParameterEnd {
577 req_id: i32,
579 },
580 MarketRule {
582 market_rule_id: i32,
584 price_increments: Vec<PriceIncrement>,
586 },
587 Pnl {
589 req_id: i32,
591 daily_pnl: f64,
593 unrealized_pnl: f64,
595 realized_pnl: f64,
597 },
598 PnlSingle {
600 req_id: i32,
602 position: Decimal,
604 daily_pnl: f64,
606 unrealized_pnl: f64,
608 realized_pnl: f64,
610 value: f64,
612 },
613 NewsArticle {
615 req_id: i32,
617 article_type: i32,
619 article_text: String,
621 },
622 NewsBulletin {
624 news_msg_id: i32,
626 news_msg_type: i32,
628 news_message: String,
630 originating_exch: String,
632 },
633 NewsProviders {
635 providers: Vec<NewsProvider>,
637 },
638 HistoricalNews {
640 req_id: i32,
642 time: String,
644 provider_code: String,
646 article_id: String,
648 headline: String,
650 },
651 HistoricalNewsEnd {
653 req_id: i32,
655 has_more: bool,
657 },
658 TickNews {
660 req_id: i32,
662 timestamp: i64,
664 provider_code: String,
666 article_id: String,
668 headline: String,
670 extra_data: String,
672 },
673 WshMetaData {
675 req_id: i32,
677 data_json: String,
679 },
680 WshEventData {
682 req_id: i32,
684 data_json: String,
686 },
687 ReceiveFa {
689 fa_data_type: i32,
691 xml: String,
693 },
694 ReplaceFaEnd {
696 req_id: i32,
698 text: String,
700 },
701 DisplayGroupList {
703 req_id: i32,
705 groups: String,
707 },
708 DisplayGroupUpdated {
710 req_id: i32,
712 contract_info: String,
714 },
715 VerifyMessageApi {
717 api_data: String,
719 },
720 VerifyCompleted {
722 is_successful: bool,
724 error_text: String,
726 },
727 VerifyAndAuthMessageApi {
729 api_data: String,
731 challenge: String,
733 },
734 VerifyAndAuthCompleted {
736 is_successful: bool,
738 error_text: String,
740 },
741 ConfigResponse {
743 req_id: i32,
745 status: String,
747 message: String,
749 },
750 UpdateConfigResponse {
752 req_id: i32,
754 status: String,
756 message: String,
758 changed_fields: Vec<String>,
760 errors: Vec<String>,
762 },
763 OrderBound {
765 perm_id: i64,
767 client_id: i32,
769 order_id: i32,
771 },
772 CompletedOrder {
774 contract: Box<Contract>,
776 order: Box<Order>,
778 order_state: Box<OrderState>,
780 },
781 CompletedOrdersEnd,
783 UserInfo {
785 req_id: i32,
787 white_branding_id: String,
789 },
790 ManagedAccounts {
792 accounts: String,
794 },
795 Raw {
797 msg_id: i32,
799 fields: Vec<String>,
801 },
802 RawProtobuf {
804 msg_id: i32,
806 payload: Vec<u8>,
808 },
809}
810
811#[allow(clippy::too_many_arguments)]
815pub trait Wrapper: Send {
816 fn on_event(&mut self, _event: Event) {}
818
819 fn connect_ack(&mut self) {}
821
822 fn connection_closed(&mut self) {}
824
825 fn error(&mut self, _req_id: i32, _time: i64, _code: i32, _message: String) {}
827
828 fn next_valid_id(&mut self, _order_id: i32) {}
830
831 fn current_time(&mut self, _time: i64) {}
833
834 fn current_time_in_millis(&mut self, _time_in_millis: i64) {}
836
837 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 fn market_data_type(&mut self, _req_id: i32, _data_type: MarketDataType) {}
1311 fn tick_price(&mut self, _req_id: i32, _tick_type: TickType, _price: f64, _attrib: i32) {}
1313 fn tick_size(&mut self, _req_id: i32, _tick_type: TickType, _size: Decimal) {}
1315 fn tick_generic(&mut self, _req_id: i32, _tick_type: TickType, _value: f64) {}
1317 fn tick_string(&mut self, _req_id: i32, _tick_type: TickType, _value: String) {}
1319 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 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 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}