Skip to main content

TwsApiClient

Struct TwsApiClient 

Source
pub struct TwsApiClient { /* private fields */ }
Expand description

Thin TWS/Gateway protocol client.

Implementations§

Source§

impl TwsApiClient

Source

pub fn into_event_pump<W: Wrapper>(self, wrapper: W) -> EventPump<W>

Moves this client into an owned asynchronous event pump.

Source

pub async fn connect(config: ClientConfig) -> TwsApiResult<Self>

Opens a TCP connection and performs the enhanced TWS API handshake.

Examples found in repository?
examples/twsapi/main.rs (line 517)
513async fn connect() -> Result<TwsApiClient, CliError> {
514    let host = env_string("TWS_HOST", "127.0.0.1");
515    let port = env_parse("TWS_PORT", 7497u16)?;
516    let client_id = env_parse("TWS_CLIENT_ID", 1002i32)?;
517    Ok(TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?)
518}
More examples
Hide additional examples
examples/request_current_time.rs (line 16)
5async fn main() -> truefix_twsapi_client::error::TwsApiResult<()> {
6    let host = std::env::var("TWS_HOST").unwrap_or_else(|_| "127.0.0.1".to_owned());
7    let port = std::env::var("TWS_PORT")
8        .ok()
9        .and_then(|value| value.parse::<u16>().ok())
10        .unwrap_or(7497);
11    let client_id = std::env::var("TWS_CLIENT_ID")
12        .ok()
13        .and_then(|value| value.parse::<i32>().ok())
14        .unwrap_or(1001);
15
16    let mut client = TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?;
17    client.req_current_time().await?;
18
19    loop {
20        match client.read_event().await? {
21            Event::CurrentTime { time } => {
22                println!("{time}");
23                break;
24            }
25            Event::Error { code, message, .. } => {
26                eprintln!("TWS error {code}: {message}");
27                break;
28            }
29            _ => {}
30        }
31    }
32
33    Ok(())
34}
examples/request_market_data.rs (line 28)
9async fn main() -> truefix_twsapi_client::error::TwsApiResult<()> {
10    let host = std::env::var("TWS_HOST").unwrap_or_else(|_| "127.0.0.1".to_owned());
11    let port = std::env::var("TWS_PORT")
12        .ok()
13        .and_then(|value| value.parse::<u16>().ok())
14        .unwrap_or(7497);
15    let client_id = std::env::var("TWS_CLIENT_ID")
16        .ok()
17        .and_then(|value| value.parse::<i32>().ok())
18        .unwrap_or(1002);
19    let symbol = std::env::var("TWS_SYMBOL").unwrap_or_else(|_| "AAPL".to_owned());
20    let exchange = std::env::var("TWS_EXCHANGE").unwrap_or_else(|_| "SMART".to_owned());
21    let currency = std::env::var("TWS_CURRENCY").unwrap_or_else(|_| "USD".to_owned());
22    let market_data_type = std::env::var("TWS_MARKET_DATA_TYPE")
23        .ok()
24        .and_then(|value| value.parse::<i32>().ok())
25        .unwrap_or(1);
26
27    let req_id = 9001;
28    let mut client = TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?;
29    wait_until_api_ready(&mut client).await?;
30    client.req_market_data_type(market_data_type).await?;
31    client
32        .req_mkt_data(MarketDataRequest {
33            req_id,
34            contract: Contract {
35                symbol,
36                sec_type: "STK".to_owned(),
37                exchange,
38                currency,
39                ..Contract::default()
40            },
41            generic_tick_list: String::new(),
42            snapshot: false,
43            regulatory_snapshot: false,
44            market_data_options: Vec::new(),
45        })
46        .await?;
47
48    let result = tokio::time::timeout(Duration::from_secs(30), async {
49        let should_cancel = loop {
50            match client.read_event().await? {
51                Event::TickPrice {
52                    req_id: event_req_id,
53                    tick_type,
54                    price,
55                    attrib,
56                } if event_req_id == req_id => {
57                    println!("price tick_type={tick_type} price={price} attrib={attrib}");
58                    break true;
59                }
60                Event::TickSize {
61                    req_id: event_req_id,
62                    tick_type,
63                    size,
64                } if event_req_id == req_id => {
65                    println!("size tick_type={tick_type} size={size}");
66                }
67                Event::Error {
68                    req_id: event_req_id,
69                    code,
70                    message,
71                    ..
72                } if event_req_id < 0 && is_market_data_status_code(code) => {
73                    eprintln!("TWS status {code}: {message}");
74                }
75                Event::Error {
76                    req_id: event_req_id,
77                    code,
78                    message,
79                    ..
80                } if event_req_id == req_id && is_delayed_market_data_notice(code) => {
81                    eprintln!("TWS notice {code}: {message}");
82                }
83                Event::Error {
84                    req_id: event_req_id,
85                    code,
86                    message,
87                    ..
88                } if event_req_id == req_id => {
89                    eprintln!("TWS error {code}: {message}");
90                    break false;
91                }
92                Event::Error { code, message, .. } => {
93                    eprintln!("TWS notice {code}: {message}");
94                }
95                _ => {}
96            }
97        };
98        truefix_twsapi_client::error::TwsApiResult::Ok(should_cancel)
99    })
100    .await;
101
102    let should_cancel = match &result {
103        Ok(Ok(should_cancel)) => *should_cancel,
104        Ok(Err(_)) | Err(_) => true,
105    };
106    if should_cancel && let Err(error) = client.cancel_mkt_data(req_id).await {
107        eprintln!("cancelMktData failed: {error}");
108    }
109    if should_cancel {
110        tokio::time::sleep(Duration::from_millis(250)).await;
111    }
112
113    match result {
114        Ok(result) => result.map(|_| ()),
115        Err(_) => {
116            eprintln!("timed out waiting for market data");
117            Ok(())
118        }
119    }
120}
Source

pub const fn server_version(&self) -> i32

Returns the negotiated server version.

Source

pub fn connection_time(&self) -> &str

Returns the connection time reported by TWS/Gateway.

Source

pub const fn state(&self) -> ConnectionState

Returns the current connection state.

Source

pub async fn disconnect(&mut self) -> TwsApiResult<()>

Closes the socket connection.

Examples found in repository?
examples/twsapi/main.rs (line 108)
92async fn main() -> Result<(), CliError> {
93    let args = env::args().skip(1).collect::<Vec<_>>();
94    let mut client = connect().await?;
95    wait_until_api_ready(&mut client).await?;
96
97    if args.is_empty() {
98        print_help();
99        run_interactive(&mut client).await?;
100    } else {
101        let (command, extra_args) = parse_command(args)?;
102        run_command(&mut client, command).await?;
103        if !extra_args.is_empty() {
104            eprintln!("unused args: {}", extra_args.join(" "));
105        }
106    }
107
108    let _ = client.disconnect().await;
109    Ok(())
110}
111
112async fn run_command(client: &mut TwsApiClient, command: Command) -> Result<(), CliError> {
113    match command {
114        Command::CurrentTime => run_current_time(client).await?,
115        Command::CurrentTimeMillis => run_current_time_millis(client).await?,
116        Command::RequestIds => run_request_ids(client).await?,
117        Command::SetServerLogLevel => run_set_server_log_level(client).await?,
118        Command::MarketData { symbol } => run_market_data(client, symbol).await?,
119        Command::MarketDepth => run_market_depth(client).await?,
120        Command::PlaceOrder => run_place_order(client).await?,
121        Command::CancelOrder => run_cancel_order(client).await?,
122        Command::OpenOrders => run_open_orders(client).await?,
123        Command::AutoOpenOrders => run_auto_open_orders(client).await?,
124        Command::AllOpenOrders => run_all_open_orders(client).await?,
125        Command::GlobalCancel => run_global_cancel(client).await?,
126        Command::CompletedOrders => run_completed_orders(client).await?,
127        Command::AccountSummary => run_account_summary(client).await?,
128        Command::Positions => run_positions(client).await?,
129        Command::PositionsMulti => run_positions_multi(client).await?,
130        Command::AccountUpdatesMulti => run_account_updates_multi(client).await?,
131        Command::HistoricalData => run_historical_data(client).await?,
132        Command::HistoricalTicks => run_historical_ticks(client).await?,
133        Command::HeadTimestamp => run_head_timestamp(client).await?,
134        Command::HistogramData => run_histogram_data(client).await?,
135        Command::ContractDetails => run_contract_details(client).await?,
136        Command::BondContractDetails => run_bond_contract_details(client).await?,
137        Command::Executions => run_executions(client).await?,
138        Command::Scanner => run_scanner(client).await?,
139        Command::ScannerParameters => run_scanner_parameters(client).await?,
140        Command::RealTimeBars => run_real_time_bars(client).await?,
141        Command::TickByTick => run_tick_by_tick(client).await?,
142        Command::SmartComponents => run_smart_components(client).await?,
143        Command::MarketRule => run_market_rule(client).await?,
144        Command::CalculateImpliedVolatility => run_calculate_implied_volatility(client).await?,
145        Command::CalculateOptionPrice => run_calculate_option_price(client).await?,
146        Command::ExerciseOptions => run_exercise_options(client).await?,
147        Command::Pnl => run_pnl(client).await?,
148        Command::PnlSingle => run_pnl_single(client).await?,
149        Command::NewsBulletins => run_news_bulletins(client).await?,
150        Command::NewsArticle => run_news_article(client).await?,
151        Command::HistoricalNews => run_historical_news(client).await?,
152        Command::ManagedAccounts => run_managed_accounts(client).await?,
153        Command::Disconnect => run_disconnect(client).await?,
154        Command::AccountUpdates => run_account_updates(client).await?,
155        Command::MarketDepthExchanges => run_market_depth_exchanges(client).await?,
156        Command::SecDefOptParams => run_sec_def_opt_params(client).await?,
157        Command::SoftDollarTiers => run_soft_dollar_tiers(client).await?,
158        Command::FamilyCodes => run_family_codes(client).await?,
159        Command::MatchingSymbols => run_matching_symbols(client).await?,
160        Command::QueryDisplayGroups => run_query_display_groups(client).await?,
161        Command::SubscribeToGroupEvents => run_subscribe_to_group_events(client).await?,
162        Command::UpdateDisplayGroup => run_update_display_group(client).await?,
163        Command::UnsubscribeFromGroupEvents => run_unsubscribe_from_group_events(client).await?,
164        Command::RequestFa => run_request_fa(client).await?,
165        Command::ReplaceFa => run_replace_fa(client).await?,
166        Command::WshMetaData => run_wsh_meta_data(client).await?,
167        Command::WshEventData => run_wsh_event_data(client).await?,
168        Command::UserInfo => run_user_info(client).await?,
169        Command::NewsProviders => run_news_providers(client).await?,
170    }
171    Ok(())
172}
173
174async fn run_interactive(client: &mut TwsApiClient) -> Result<(), CliError> {
175    let stdin = io::stdin();
176    let mut line = String::new();
177
178    loop {
179        print!("twsapi> ");
180        io::stdout().flush()?;
181        line.clear();
182
183        if stdin.read_line(&mut line)? == 0 {
184            println!();
185            break;
186        }
187
188        let input = line.trim();
189        if input.is_empty() {
190            continue;
191        }
192        if matches!(input, "quit" | "exit" | "q") {
193            break;
194        }
195        if matches!(input, "help" | "h" | "?") {
196            print_help();
197            continue;
198        }
199
200        let parts = input
201            .split_whitespace()
202            .map(str::to_owned)
203            .collect::<Vec<_>>();
204        let (command, extra_args) = match parse_command(parts) {
205            Ok(parsed) => parsed,
206            Err(err) => {
207                eprintln!("{err}");
208                continue;
209            }
210        };
211        if let Err(err) = run_command(client, command).await {
212            eprintln!("{err}");
213        }
214        if !extra_args.is_empty() {
215            eprintln!("unused args: {}", extra_args.join(" "));
216        }
217    }
218
219    Ok(())
220}
221
222fn parse_command(mut args: Vec<String>) -> Result<(Command, Vec<String>), CliError> {
223    if args.is_empty() {
224        return Err(CliError::Usage("missing command".to_owned()));
225    }
226
227    let command = match args.remove(0).as_str() {
228        "time" | "current-time" => Command::CurrentTime,
229        "current-time-ms" | "time-ms" => Command::CurrentTimeMillis,
230        "request-ids" | "req-ids" => Command::RequestIds,
231        "set-server-log-level" => Command::SetServerLogLevel,
232        "market-data" => {
233            let symbol = args.first().cloned();
234            if !args.is_empty() {
235                args.remove(0);
236            }
237            Command::MarketData { symbol }
238        }
239        "market-depth" => Command::MarketDepth,
240        "place-order" => Command::PlaceOrder,
241        "cancel-order" => Command::CancelOrder,
242        "open-orders" => Command::OpenOrders,
243        "auto-open-orders" => Command::AutoOpenOrders,
244        "all-open-orders" => Command::AllOpenOrders,
245        "global-cancel" => Command::GlobalCancel,
246        "completed-orders" => Command::CompletedOrders,
247        "account-summary" => Command::AccountSummary,
248        "positions" => Command::Positions,
249        "positions-multi" => Command::PositionsMulti,
250        "account-updates-multi" => Command::AccountUpdatesMulti,
251        "historical-data" => Command::HistoricalData,
252        "historical-ticks" => Command::HistoricalTicks,
253        "head-timestamp" => Command::HeadTimestamp,
254        "histogram-data" => Command::HistogramData,
255        "contract-details" => Command::ContractDetails,
256        "bond-contract-details" => Command::BondContractDetails,
257        "executions" => Command::Executions,
258        "scanner" => Command::Scanner,
259        "scanner-params" => Command::ScannerParameters,
260        "real-time-bars" => Command::RealTimeBars,
261        "tick-by-tick" => Command::TickByTick,
262        "smart-components" => Command::SmartComponents,
263        "market-rule" => Command::MarketRule,
264        "calc-iv" | "calculate-implied-volatility" => Command::CalculateImpliedVolatility,
265        "calc-option-price" | "calculate-option-price" => Command::CalculateOptionPrice,
266        "exercise-options" => Command::ExerciseOptions,
267        "pnl" => Command::Pnl,
268        "pnl-single" => Command::PnlSingle,
269        "news-bulletins" => Command::NewsBulletins,
270        "news-article" => Command::NewsArticle,
271        "historical-news" => Command::HistoricalNews,
272        "managed-accounts" => Command::ManagedAccounts,
273        "disconnect" => Command::Disconnect,
274        "account-updates" => Command::AccountUpdates,
275        "market-depth-exchanges" => Command::MarketDepthExchanges,
276        "sec-def-opt-params" => Command::SecDefOptParams,
277        "soft-dollar-tiers" => Command::SoftDollarTiers,
278        "family-codes" => Command::FamilyCodes,
279        "matching-symbols" => Command::MatchingSymbols,
280        "query-display-groups" => Command::QueryDisplayGroups,
281        "subscribe-group-events" => Command::SubscribeToGroupEvents,
282        "update-display-group" => Command::UpdateDisplayGroup,
283        "unsubscribe-group-events" => Command::UnsubscribeFromGroupEvents,
284        "request-fa" => Command::RequestFa,
285        "replace-fa" => Command::ReplaceFa,
286        "wsh-meta-data" => Command::WshMetaData,
287        "wsh-event-data" => Command::WshEventData,
288        "user-info" => Command::UserInfo,
289        "news-providers" => Command::NewsProviders,
290        "help" | "-h" | "--help" => {
291            return Err(CliError::Usage("use `help` inside the client".to_owned()));
292        }
293        other => return Err(CliError::Usage(format!("unknown command: {other}"))),
294    };
295
296    Ok((command, args))
297}
298
299fn print_help() {
300    eprintln!(
301        "usage:\n\
302         \x20\x20interactive: cargo run -p truefix-twsapi-client --example twsapi\n\
303         \x20\x20one-shot:    cargo run -p truefix-twsapi-client --example twsapi -- <command>\n\
304         \n\
305         commands:\n\
306         \x20\x20time | current-time\n\
307         \x20\x20current-time-ms | time-ms\n\
308         \x20\x20request-ids | req-ids\n\
309         \x20\x20set-server-log-level\n\
310         \x20\x20market-data\n\
311         \x20\x20market-depth\n\
312         \x20\x20place-order\n\
313         \x20\x20cancel-order\n\
314         \x20\x20open-orders\n\
315         \x20\x20auto-open-orders\n\
316         \x20\x20all-open-orders\n\
317         \x20\x20global-cancel\n\
318         \x20\x20completed-orders\n\
319         \x20\x20account-summary\n\
320         \x20\x20account-updates\n\
321         \x20\x20account-updates-multi\n\
322         \x20\x20positions\n\
323         \x20\x20positions-multi\n\
324         \x20\x20historical-data\n\
325         \x20\x20historical-ticks\n\
326         \x20\x20head-timestamp\n\
327         \x20\x20histogram-data\n\
328         \x20\x20contract-details\n\
329         \x20\x20bond-contract-details\n\
330         \x20\x20disconnect\n\
331         \x20\x20executions\n\
332         \x20\x20scanner\n\
333         \x20\x20scanner-params\n\
334         \x20\x20real-time-bars\n\
335         \x20\x20tick-by-tick\n\
336         \x20\x20smart-components\n\
337         \x20\x20market-rule\n\
338         \x20\x20calc-iv | calculate-implied-volatility\n\
339         \x20\x20calc-option-price | calculate-option-price\n\
340         \x20\x20exercise-options\n\
341         \x20\x20pnl\n\
342         \x20\x20pnl-single\n\
343         \x20\x20news-bulletins\n\
344         \x20\x20news-article\n\
345         \x20\x20historical-news\n\
346         \x20\x20managed-accounts\n\
347         \x20\x20market-depth-exchanges\n\
348         \x20\x20sec-def-opt-params\n\
349         \x20\x20soft-dollar-tiers\n\
350         \x20\x20family-codes\n\
351         \x20\x20matching-symbols\n\
352         \x20\x20query-display-groups\n\
353         \x20\x20subscribe-group-events\n\
354         \x20\x20update-display-group\n\
355         \x20\x20unsubscribe-group-events\n\
356         \x20\x20request-fa\n\
357         \x20\x20replace-fa\n\
358         \x20\x20wsh-meta-data\n\
359         \x20\x20wsh-event-data\n\
360         \x20\x20user-info\n\
361         \x20\x20news-providers\n\
362         \n\
363         common env:\n\
364         \x20\x20TWS_HOST=127.0.0.1 TWS_PORT=7497 TWS_CLIENT_ID=1002\n\
365         \x20\x20TWS_SYMBOL=AAPL TWS_SEC_TYPE=STK TWS_EXCHANGE=SMART TWS_CURRENCY=USD\n\
366         \x20\x20TWS_REQ_ID=9001 TWS_ACCOUNT=<acct> TWS_MODEL_CODE=<model>\n"
367    );
368}
369
370fn env_string(key: &str, default: &str) -> String {
371    env::var(key).unwrap_or_else(|_| default.to_owned())
372}
373
374fn env_opt_string(key: &str) -> Option<String> {
375    env::var(key).ok().filter(|value| !value.is_empty())
376}
377
378fn env_parse<T>(key: &str, default: T) -> Result<T, CliError>
379where
380    T: FromStr,
381    T::Err: std::fmt::Display,
382{
383    match env::var(key) {
384        Ok(value) if !value.is_empty() => value
385            .parse::<T>()
386            .map_err(|err| CliError::Usage(format!("{key}={value}: {err}"))),
387        _ => Ok(default),
388    }
389}
390
391fn env_bool(key: &str, default: bool) -> Result<bool, CliError> {
392    match env::var(key) {
393        Ok(value) if !value.is_empty() => match value.to_ascii_lowercase().as_str() {
394            "1" | "true" | "yes" | "y" => Ok(true),
395            "0" | "false" | "no" | "n" => Ok(false),
396            _ => Err(CliError::Usage(format!(
397                "{key} must be one of 1|0|true|false|yes|no|y|n"
398            ))),
399        },
400        _ => Ok(default),
401    }
402}
403
404fn env_decimal(key: &str) -> Result<Option<Decimal>, CliError> {
405    match env::var(key) {
406        Ok(value) if !value.is_empty() => value
407            .parse::<Decimal>()
408            .map(Some)
409            .map_err(|err| CliError::Usage(format!("{key}={value}: {err}"))),
410        _ => Ok(None),
411    }
412}
413
414fn env_tag_values(prefix: &str) -> Vec<TagValue> {
415    let mut values = Vec::new();
416    for idx in 1..=16 {
417        let tag_key = format!("{prefix}_{idx}_TAG");
418        let value_key = format!("{prefix}_{idx}_VALUE");
419        let Some(tag) = env_opt_string(&tag_key) else {
420            continue;
421        };
422        let value = env_opt_string(&value_key).unwrap_or_default();
423        values.push(TagValue { tag, value });
424    }
425    values
426}
427
428fn req_id(default: i32) -> Result<i32, CliError> {
429    env_parse("TWS_REQ_ID", default)
430}
431
432fn contract_from_env() -> Result<Contract, CliError> {
433    let mut contract = Contract::default();
434    contract.con_id = env_parse("TWS_CONID", 0i32)?;
435    contract.symbol = env_string("TWS_SYMBOL", "AAPL");
436    contract.sec_type = env_string("TWS_SEC_TYPE", "STK");
437    contract.last_trade_date_or_contract_month =
438        env_string("TWS_LAST_TRADE_DATE_OR_CONTRACT_MONTH", "");
439    contract.strike = env_parse("TWS_STRIKE", contract.strike)?;
440    contract.right = env_string("TWS_RIGHT", "");
441    contract.multiplier = env_string("TWS_MULTIPLIER", "");
442    contract.exchange = env_string("TWS_EXCHANGE", "SMART");
443    contract.primary_exchange = env_string("TWS_PRIMARY_EXCHANGE", "");
444    contract.currency = env_string("TWS_CURRENCY", "USD");
445    contract.local_symbol = env_string("TWS_LOCAL_SYMBOL", "");
446    contract.trading_class = env_string("TWS_TRADING_CLASS", "");
447    contract.include_expired = env_bool("TWS_INCLUDE_EXPIRED", false)?;
448    contract.sec_id_type = env_string("TWS_SEC_ID_TYPE", "");
449    contract.sec_id = env_string("TWS_SEC_ID", "");
450    contract.combo_legs_description = env_string("TWS_COMBO_LEGS_DESCRIPTION", "");
451    Ok(contract)
452}
453
454fn parse_order_kind() -> Result<String, CliError> {
455    Ok(env_string("TWS_ORDER_KIND", "limit").to_ascii_lowercase())
456}
457
458fn side(value: &str) -> Result<String, CliError> {
459    match value.to_ascii_uppercase().as_str() {
460        "BUY" | "SELL" => Ok(value.to_ascii_uppercase()),
461        other => Err(CliError::Usage(format!(
462            "TWS_ORDER_SIDE must be BUY or SELL, got {other}"
463        ))),
464    }
465}
466
467fn order_from_env() -> Result<Order, CliError> {
468    let mut order = Order::default();
469    order.order_id = req_id(5001)?;
470    order.action = side(&env_string("TWS_ORDER_SIDE", "BUY"))?;
471    order.total_quantity = env_decimal("TWS_ORDER_QTY")?.unwrap_or(Decimal::ONE);
472    order.account = env_string("TWS_ACCOUNT", "");
473    order.order_type = env_string("TWS_ORDER_TYPE", "");
474    order.tif = env_string("TWS_TIF", "DAY");
475    order.good_till_date = env_string("TWS_GOOD_TILL_DATE", "");
476    order.transmit = env_bool("TWS_TRANSMIT", true)?;
477    order.what_if = env_bool("TWS_WHAT_IF", false)?;
478    order.outside_rth = env_bool("TWS_OUTSIDE_RTH", false)?;
479    order.hidden = env_bool("TWS_HIDDEN", false)?;
480    order.solicited = env_bool("TWS_SOLICITED", false)?;
481    order.cash_qty = env_parse("TWS_CASH_QTY", order.cash_qty)?;
482    order.order_ref = env_string("TWS_ORDER_REF", "");
483    Ok(order)
484}
485
486fn order_kind_from_env(order: &mut Order) -> Result<(), CliError> {
487    match parse_order_kind()?.as_str() {
488        "market" => {
489            order.order_type = "MKT".to_owned();
490        }
491        "limit" => {
492            order.order_type = "LMT".to_owned();
493            order.limit_price = env_parse("TWS_LIMIT_PRICE", 0.0f64)?;
494        }
495        "stop" => {
496            order.order_type = "STP".to_owned();
497            order.trail_stop_price = env_parse("TWS_TRIGGER_PRICE", 0.0f64)?;
498        }
499        "stoplimit" => {
500            order.order_type = "STP LMT".to_owned();
501            order.limit_price = env_parse("TWS_LIMIT_PRICE", 0.0f64)?;
502            order.trail_stop_price = env_parse("TWS_TRIGGER_PRICE", 0.0f64)?;
503        }
504        other => {
505            return Err(CliError::Usage(format!(
506                "TWS_ORDER_KIND must be market|limit|stop|stoplimit, got {other}"
507            )));
508        }
509    }
510    Ok(())
511}
512
513async fn connect() -> Result<TwsApiClient, CliError> {
514    let host = env_string("TWS_HOST", "127.0.0.1");
515    let port = env_parse("TWS_PORT", 7497u16)?;
516    let client_id = env_parse("TWS_CLIENT_ID", 1002i32)?;
517    Ok(TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?)
518}
519
520async fn wait_until_api_ready(client: &mut TwsApiClient) -> Result<(), CliError> {
521    let result = tokio::time::timeout(Duration::from_secs(10), async {
522        while !client.api_ready() {
523            match client.read_event().await? {
524                Event::Error { code, message, .. } => {
525                    eprintln!("TWS notice {code}: {message}");
526                }
527                other => {
528                    print_event(&other);
529                }
530            }
531        }
532        truefix_twsapi_client::error::TwsApiResult::Ok(())
533    })
534    .await;
535
536    match result {
537        Ok(Ok(())) => Ok(()),
538        Ok(Err(err)) => Err(err.into()),
539        Err(_) => Err(CliError::Usage(
540            "timed out waiting for initial API callbacks".to_owned(),
541        )),
542    }
543}
544
545async fn read_until<F>(
546    client: &mut TwsApiClient,
547    timeout_secs: u64,
548    mut on_event: F,
549) -> Result<bool, CliError>
550where
551    F: FnMut(Event) -> bool,
552{
553    let result = tokio::time::timeout(Duration::from_secs(timeout_secs), async {
554        loop {
555            let event = client.read_event().await?;
556            if on_event(event) {
557                return truefix_twsapi_client::error::TwsApiResult::Ok(true);
558            }
559        }
560    })
561    .await;
562    match result {
563        Ok(Ok(done)) => Ok(done),
564        Ok(Err(err)) => Err(err.into()),
565        Err(_) => Ok(false),
566    }
567}
568
569fn print_event(event: &Event) {
570    match event {
571        Event::CurrentTime { time } => println!("current_time={time}"),
572        Event::CurrentTimeInMillis { time_in_millis } => {
573            println!("current_time_ms={time_in_millis}")
574        }
575        Event::MarketDataType {
576            req_id,
577            market_data_type,
578        } => println!("market_data_type req_id={req_id} type={market_data_type}"),
579        Event::TickPrice {
580            req_id,
581            tick_type,
582            price,
583            attrib,
584        } => println!(
585            "tick_price req_id={req_id} tick_type={tick_type} price={price} attrib={attrib}"
586        ),
587        Event::TickSize {
588            req_id,
589            tick_type,
590            size,
591        } => println!("tick_size req_id={req_id} tick_type={tick_type} size={size}"),
592        Event::TickString {
593            req_id,
594            tick_type,
595            value,
596        } => println!("tick_string req_id={req_id} tick_type={tick_type} value={value}"),
597        Event::TickOptionComputation {
598            req_id,
599            tick_type,
600            tick_attrib,
601            implied_vol,
602            delta,
603            opt_price,
604            pv_dividend,
605            gamma,
606            vega,
607            theta,
608            und_price,
609        } => println!(
610            "tick_option req_id={req_id} tick_type={tick_type} tick_attrib={tick_attrib} implied_vol={implied_vol} delta={delta} opt_price={opt_price} pv_dividend={pv_dividend} gamma={gamma} vega={vega} theta={theta} und_price={und_price}"
611        ),
612        Event::OrderStatus {
613            order_id,
614            status,
615            filled,
616            remaining,
617            avg_fill_price,
618            perm_id,
619            parent_id,
620            last_fill_price,
621            client_id,
622            why_held,
623            market_cap_price,
624        } => println!(
625            "order_status order_id={order_id} status={status} filled={filled} remaining={remaining} avg_fill_price={avg_fill_price} perm_id={perm_id} parent_id={parent_id} last_fill_price={last_fill_price} client_id={client_id} why_held={why_held} market_cap_price={market_cap_price}"
626        ),
627        Event::OpenOrder {
628            order_id,
629            contract,
630            order,
631            ..
632        } => println!(
633            "open_order order_id={order_id} symbol={} sec_type={} exchange={} action={} qty={} type={}",
634            contract.symbol,
635            contract.sec_type,
636            contract.exchange,
637            order.action,
638            order.total_quantity,
639            order.order_type
640        ),
641        Event::CompletedOrder {
642            contract,
643            order,
644            order_state,
645        } => println!(
646            "completed_order symbol={} sec_type={} exchange={} action={} qty={} status={} completed_status={}",
647            contract.symbol,
648            contract.sec_type,
649            contract.exchange,
650            order.action,
651            order.total_quantity,
652            order_state.status,
653            order_state.completed_status
654        ),
655        Event::ContractDetails { req_id, details } => println!(
656            "contract_details req_id={req_id} symbol={} sec_type={} exchange={} currency={}",
657            details.contract.symbol,
658            details.contract.sec_type,
659            details.contract.exchange,
660            details.contract.currency
661        ),
662        Event::BondContractDetails { req_id, details } => println!(
663            "bond_contract_details req_id={req_id} symbol={} sec_type={} exchange={} currency={}",
664            details.contract.symbol,
665            details.contract.sec_type,
666            details.contract.exchange,
667            details.contract.currency
668        ),
669        Event::ExecutionDetails {
670            req_id,
671            contract,
672            execution,
673        } => println!(
674            "execution req_id={req_id} symbol={} exec_id={} shares={} price={}",
675            contract.symbol, execution.exec_id, execution.shares, execution.price
676        ),
677        Event::HistoricalData { req_id, bar } => println!(
678            "historical_bar req_id={req_id} date={} open={} high={} low={} close={} volume={} wap={} count={}",
679            bar.date, bar.open, bar.high, bar.low, bar.close, bar.volume, bar.wap, bar.bar_count
680        ),
681        Event::HistoricalDataUpdate { req_id, bar } => println!(
682            "historical_update req_id={req_id} date={} open={} high={} low={} close={}",
683            bar.date, bar.open, bar.high, bar.low, bar.close
684        ),
685        Event::HistoricalDataEnd { req_id, start, end } => {
686            println!("historical_end req_id={req_id} start={start} end={end}")
687        }
688        Event::RealTimeBar { req_id, time, bar } => println!(
689            "real_time_bar req_id={req_id} time={time} open={} high={} low={} close={} volume={} wap={} count={}",
690            bar.open, bar.high, bar.low, bar.close, bar.volume, bar.wap, bar.bar_count
691        ),
692        Event::HeadTimestamp {
693            req_id,
694            head_timestamp,
695        } => println!("head_timestamp req_id={req_id} head_timestamp={head_timestamp}"),
696        Event::ScannerData { req_id, rows } => {
697            println!("scanner_data req_id={req_id} rows={}", rows.len());
698            for row in rows {
699                println!(
700                    "  rank={} symbol={} sec_type={} market={} distance={} benchmark={} projection={} combo_key={}",
701                    row.rank,
702                    row.contract.symbol,
703                    row.contract.sec_type,
704                    row.market_name,
705                    row.distance,
706                    row.benchmark,
707                    row.projection,
708                    row.combo_key
709                );
710            }
711        }
712        Event::ScannerDataEnd { req_id } => println!("scanner_data_end req_id={req_id}"),
713        Event::AccountSummary {
714            req_id,
715            account,
716            tag,
717            value,
718            currency,
719        } => println!(
720            "account_summary req_id={req_id} account={account} tag={tag} value={value} currency={currency}"
721        ),
722        Event::AccountValue {
723            key,
724            value,
725            currency,
726            account_name,
727        } => println!(
728            "account_value account={account_name} key={key} value={value} currency={currency}"
729        ),
730        Event::PortfolioValue {
731            contract,
732            position,
733            market_price,
734            market_value,
735            average_cost,
736            unrealized_pnl,
737            realized_pnl,
738            account_name,
739        } => println!(
740            "portfolio account={account_name} symbol={} position={} market_price={} market_value={} average_cost={} unrealized_pnl={} realized_pnl={}",
741            contract.symbol,
742            position,
743            market_price,
744            market_value,
745            average_cost,
746            unrealized_pnl,
747            realized_pnl
748        ),
749        Event::Position {
750            account,
751            contract,
752            position,
753            avg_cost,
754        } => println!(
755            "position account={account} symbol={} sec_type={} exchange={} position={} avg_cost={}",
756            contract.symbol, contract.sec_type, contract.exchange, position, avg_cost
757        ),
758        Event::PositionMulti {
759            req_id,
760            account,
761            model_code,
762            contract,
763            position,
764            avg_cost,
765        } => println!(
766            "position_multi req_id={req_id} account={account} model_code={model_code} symbol={} position={} avg_cost={}",
767            contract.symbol, position, avg_cost
768        ),
769        Event::Pnl {
770            req_id,
771            daily_pnl,
772            unrealized_pnl,
773            realized_pnl,
774        } => println!(
775            "pnl req_id={req_id} daily_pnl={daily_pnl} unrealized_pnl={unrealized_pnl} realized_pnl={realized_pnl}"
776        ),
777        Event::PnlSingle {
778            req_id,
779            position,
780            daily_pnl,
781            unrealized_pnl,
782            realized_pnl,
783            value,
784        } => println!(
785            "pnl_single req_id={req_id} position={position} daily_pnl={daily_pnl} unrealized_pnl={unrealized_pnl} realized_pnl={realized_pnl} value={value}"
786        ),
787        Event::ManagedAccounts { accounts } => println!("managed_accounts {accounts}"),
788        Event::MarketDepth {
789            req_id,
790            position,
791            operation,
792            side,
793            price,
794            size,
795            market_maker,
796            is_smart_depth,
797        } => println!(
798            "market_depth req_id={req_id} position={position} operation={operation} side={side} price={price} size={size} market_maker={market_maker} smart_depth={is_smart_depth}"
799        ),
800        Event::MarketDepthExchanges { descriptions } => {
801            println!("market_depth_exchanges count={}", descriptions.len());
802            for description in descriptions {
803                println!(
804                    "  {} {} {} {} {}",
805                    description.exchange,
806                    description.security_type,
807                    description.listing_exchange,
808                    description.service_data_type,
809                    description.aggregate_group
810                );
811            }
812        }
813        Event::NewsProviders { providers } => {
814            println!("news_providers count={}", providers.len());
815            for provider in providers {
816                println!("  {} {}", provider.code, provider.name);
817            }
818        }
819        Event::ScannerParameters { xml } => println!("{xml}"),
820        Event::OpenOrderEnd
821        | Event::CompletedOrdersEnd
822        | Event::ContractDetailsEnd { .. }
823        | Event::ExecutionDetailsEnd { .. }
824        | Event::PositionEnd
825        | Event::AccountSummaryEnd { .. }
826        | Event::AccountDownloadEnd { .. }
827        | Event::ConnectionClosed
828        | Event::ConnectAck => println!("{event:?}"),
829        Event::Error {
830            req_id,
831            code,
832            message,
833            advanced_order_reject_json,
834            ..
835        } => eprintln!(
836            "TWS error req_id={req_id} code={code} message={message} advanced={advanced_order_reject_json}"
837        ),
838        other => println!("{other:?}"),
839    }
840}
841
842async fn run_current_time(client: &mut TwsApiClient) -> Result<(), CliError> {
843    client.req_current_time().await?;
844    read_until(client, 5, |event| match event {
845        Event::CurrentTime { .. } | Event::CurrentTimeInMillis { .. } => {
846            print_event(&event);
847            true
848        }
849        Event::Error { .. } => {
850            print_event(&event);
851            true
852        }
853        other => {
854            print_event(&other);
855            false
856        }
857    })
858    .await?;
859    Ok(())
860}
861
862async fn run_current_time_millis(client: &mut TwsApiClient) -> Result<(), CliError> {
863    client.req_current_time_in_millis().await?;
864    read_until(client, 5, |event| match event {
865        Event::CurrentTimeInMillis { .. } => {
866            print_event(&event);
867            true
868        }
869        Event::Error { .. } => {
870            print_event(&event);
871            false
872        }
873        other => {
874            print_event(&other);
875            false
876        }
877    })
878    .await?;
879    Ok(())
880}
881
882async fn run_request_ids(client: &mut TwsApiClient) -> Result<(), CliError> {
883    let num_ids = env_parse("TWS_NUM_IDS", 1i32)?;
884    client.req_ids(num_ids).await?;
885    read_until(client, 5, |event| match event {
886        Event::NextValidId { order_id } => {
887            println!("next_valid_id order_id={order_id}");
888            true
889        }
890        Event::Error { .. } => {
891            print_event(&event);
892            false
893        }
894        other => {
895            print_event(&other);
896            false
897        }
898    })
899    .await?;
900    Ok(())
901}
902
903async fn run_set_server_log_level(client: &mut TwsApiClient) -> Result<(), CliError> {
904    let log_level = env_parse("TWS_LOG_LEVEL", 1i32)?;
905    client.set_server_log_level(log_level).await?;
906    println!("server_log_level={log_level}");
907    Ok(())
908}
909
910async fn run_market_data(
911    client: &mut TwsApiClient,
912    symbol: Option<String>,
913) -> Result<(), CliError> {
914    client
915        .req_market_data_type(env_parse("TWS_MARKET_DATA_TYPE", 1i32)?)
916        .await?;
917    let req_id = req_id(9001)?;
918    let symbol = symbol.unwrap_or_else(|| env_string("TWS_SYMBOL", "AAPL"));
919    let mut contract = contract_from_env()?;
920    contract.symbol = symbol;
921    client
922        .req_mkt_data(MarketDataRequest {
923            req_id,
924            contract,
925            generic_tick_list: env_string("TWS_GENERIC_TICK_LIST", ""),
926            snapshot: env_bool("TWS_SNAPSHOT", false)?,
927            regulatory_snapshot: env_bool("TWS_REGULATORY_SNAPSHOT", false)?,
928            market_data_options: env_tag_values("TWS_MARKET_DATA_OPTION"),
929        })
930        .await?;
931    let done = read_until(
932        client,
933        env_parse("TWS_WAIT_SECS", 30u64)?,
934        |event| match event {
935            Event::TickPrice {
936                req_id: event_req_id,
937                ..
938            }
939            | Event::TickSize {
940                req_id: event_req_id,
941                ..
942            }
943            | Event::TickString {
944                req_id: event_req_id,
945                ..
946            }
947            | Event::TickGeneric {
948                req_id: event_req_id,
949                ..
950            }
951            | Event::TickOptionComputation {
952                req_id: event_req_id,
953                ..
954            } if event_req_id == req_id => {
955                print_event(&event);
956                true
957            }
958            Event::Error {
959                req_id: event_req_id,
960                ..
961            } if event_req_id == req_id => {
962                print_event(&event);
963                true
964            }
965            Event::Error { code, message, .. } => {
966                eprintln!("TWS notice {code}: {message}");
967                false
968            }
969            other => {
970                print_event(&other);
971                false
972            }
973        },
974    )
975    .await?;
976    if !done {
977        let _ = client.cancel_mkt_data(req_id).await;
978    }
979    Ok(())
980}
981
982async fn run_market_depth(client: &mut TwsApiClient) -> Result<(), CliError> {
983    let req_id = req_id(9002)?;
984    client
985        .req_mkt_depth(MarketDepthRequest {
986            req_id,
987            contract: contract_from_env()?,
988            num_rows: env_parse("TWS_DEPTH_ROWS", 5i32)?,
989            is_smart_depth: env_bool("TWS_SMART_DEPTH", false)?,
990            market_depth_options: env_tag_values("TWS_DEPTH_OPTION"),
991        })
992        .await?;
993    read_until(
994        client,
995        env_parse("TWS_WAIT_SECS", 20u64)?,
996        |event| match event {
997            Event::MarketDepth {
998                req_id: event_req_id,
999                ..
1000            } if event_req_id == req_id => {
1001                print_event(&event);
1002                false
1003            }
1004            Event::Error {
1005                req_id: event_req_id,
1006                ..
1007            } if event_req_id == req_id => {
1008                print_event(&event);
1009                true
1010            }
1011            Event::Error { .. } => {
1012                print_event(&event);
1013                false
1014            }
1015            other => {
1016                print_event(&other);
1017                false
1018            }
1019        },
1020    )
1021    .await?;
1022    let _ = client
1023        .cancel_mkt_depth(req_id, env_bool("TWS_SMART_DEPTH", false)?)
1024        .await;
1025    Ok(())
1026}
1027
1028async fn run_place_order(client: &mut TwsApiClient) -> Result<(), CliError> {
1029    let mut order = order_from_env()?;
1030    order_kind_from_env(&mut order)?;
1031    let request = PlaceOrderRequest {
1032        order_id: order.order_id,
1033        contract: contract_from_env()?,
1034        order,
1035        extra_fields: env_string("TWS_ORDER_EXTRA_FIELDS", ""),
1036    };
1037    client.place_order(request).await?;
1038    read_until(
1039        client,
1040        env_parse("TWS_WAIT_SECS", 15u64)?,
1041        |event| match event {
1042            Event::OpenOrder { .. } | Event::OrderStatus { .. } | Event::Error { .. } => {
1043                print_event(&event);
1044                false
1045            }
1046            other => {
1047                print_event(&other);
1048                false
1049            }
1050        },
1051    )
1052    .await?;
1053    Ok(())
1054}
1055
1056async fn run_cancel_order(client: &mut TwsApiClient) -> Result<(), CliError> {
1057    client
1058        .cancel_order(
1059            req_id(5001)?,
1060            truefix_twsapi_client::types::OrderCancel::default(),
1061        )
1062        .await?;
1063    read_until(client, 10, |event| match event {
1064        Event::OrderStatus { .. } | Event::Error { .. } => {
1065            print_event(&event);
1066            false
1067        }
1068        other => {
1069            print_event(&other);
1070            false
1071        }
1072    })
1073    .await?;
1074    Ok(())
1075}
1076
1077async fn run_open_orders(client: &mut TwsApiClient) -> Result<(), CliError> {
1078    client.req_open_orders().await?;
1079    read_until(client, 20, |event| match event {
1080        Event::OpenOrder { .. } | Event::OpenOrderEnd => {
1081            print_event(&event);
1082            matches!(event, Event::OpenOrderEnd)
1083        }
1084        Event::Error { .. } => {
1085            print_event(&event);
1086            false
1087        }
1088        other => {
1089            print_event(&other);
1090            false
1091        }
1092    })
1093    .await?;
1094    Ok(())
1095}
1096
1097async fn run_auto_open_orders(client: &mut TwsApiClient) -> Result<(), CliError> {
1098    let auto_bind = env_bool("TWS_AUTO_BIND", true)?;
1099    client.req_auto_open_orders(auto_bind).await?;
1100    println!("auto_open_orders auto_bind={auto_bind}");
1101    Ok(())
1102}
1103
1104async fn run_all_open_orders(client: &mut TwsApiClient) -> Result<(), CliError> {
1105    client.req_all_open_orders().await?;
1106    read_until(client, 20, |event| match event {
1107        Event::OpenOrder { .. } | Event::OpenOrderEnd => {
1108            print_event(&event);
1109            matches!(event, Event::OpenOrderEnd)
1110        }
1111        Event::Error { .. } => {
1112            print_event(&event);
1113            false
1114        }
1115        other => {
1116            print_event(&other);
1117            false
1118        }
1119    })
1120    .await?;
1121    Ok(())
1122}
1123
1124async fn run_global_cancel(client: &mut TwsApiClient) -> Result<(), CliError> {
1125    client
1126        .req_global_cancel(truefix_twsapi_client::types::OrderCancel::default())
1127        .await?;
1128    println!("global_cancel sent");
1129    Ok(())
1130}
1131
1132async fn run_completed_orders(client: &mut TwsApiClient) -> Result<(), CliError> {
1133    client
1134        .req_completed_orders(env_bool("TWS_COMPLETED_API_ONLY", false)?)
1135        .await?;
1136    read_until(client, 20, |event| match event {
1137        Event::CompletedOrder { .. } | Event::CompletedOrdersEnd => {
1138            print_event(&event);
1139            matches!(event, Event::CompletedOrdersEnd)
1140        }
1141        Event::Error { .. } => {
1142            print_event(&event);
1143            false
1144        }
1145        other => {
1146            print_event(&other);
1147            false
1148        }
1149    })
1150    .await?;
1151    Ok(())
1152}
1153
1154async fn run_account_summary(client: &mut TwsApiClient) -> Result<(), CliError> {
1155    let req_id = req_id(9101)?;
1156    client
1157        .req_account_summary(
1158            req_id,
1159            &env_string("TWS_SUMMARY_GROUP", "All"),
1160            &env_string(
1161                "TWS_SUMMARY_TAGS",
1162                "NetLiquidation,TotalCashValue,BuyingPower,AvailableFunds",
1163            ),
1164        )
1165        .await?;
1166    read_until(client, 20, |event| match event {
1167        Event::AccountSummary {
1168            req_id: event_req_id,
1169            ..
1170        } if event_req_id == req_id => {
1171            print_event(&event);
1172            false
1173        }
1174        Event::AccountSummaryEnd {
1175            req_id: event_req_id,
1176        } if event_req_id == req_id => {
1177            print_event(&event);
1178            true
1179        }
1180        Event::Error { .. } => {
1181            print_event(&event);
1182            false
1183        }
1184        other => {
1185            print_event(&other);
1186            false
1187        }
1188    })
1189    .await?;
1190    let _ = client.cancel_account_summary(req_id).await;
1191    Ok(())
1192}
1193
1194async fn run_positions(client: &mut TwsApiClient) -> Result<(), CliError> {
1195    client.req_positions().await?;
1196    read_until(client, 20, |event| match event {
1197        Event::Position { .. } | Event::PositionEnd => {
1198            print_event(&event);
1199            matches!(event, Event::PositionEnd)
1200        }
1201        Event::Error { .. } => {
1202            print_event(&event);
1203            false
1204        }
1205        other => {
1206            print_event(&other);
1207            false
1208        }
1209    })
1210    .await?;
1211    let _ = client.cancel_positions().await;
1212    Ok(())
1213}
1214
1215async fn run_positions_multi(client: &mut TwsApiClient) -> Result<(), CliError> {
1216    let req_id = req_id(9102)?;
1217    client
1218        .req_positions_multi(
1219            req_id,
1220            &env_string("TWS_ACCOUNT", ""),
1221            &env_string("TWS_MODEL_CODE", ""),
1222        )
1223        .await?;
1224    read_until(client, 20, |event| match event {
1225        Event::PositionMulti {
1226            req_id: event_req_id,
1227            ..
1228        } if event_req_id == req_id => {
1229            print_event(&event);
1230            false
1231        }
1232        Event::PositionMultiEnd {
1233            req_id: event_req_id,
1234        } if event_req_id == req_id => {
1235            print_event(&event);
1236            true
1237        }
1238        Event::Error { .. } => {
1239            print_event(&event);
1240            false
1241        }
1242        other => {
1243            print_event(&other);
1244            false
1245        }
1246    })
1247    .await?;
1248    let _ = client.cancel_positions_multi(req_id).await;
1249    Ok(())
1250}
1251
1252async fn run_account_updates_multi(client: &mut TwsApiClient) -> Result<(), CliError> {
1253    let req_id = req_id(9103)?;
1254    client
1255        .req_account_updates_multi(
1256            req_id,
1257            &env_string("TWS_ACCOUNT", ""),
1258            &env_string("TWS_MODEL_CODE", ""),
1259            env_bool("TWS_LEDGER_AND_NLV", false)?,
1260        )
1261        .await?;
1262    let done = read_until(client, 20, |event| match event {
1263        Event::AccountUpdateMulti {
1264            req_id: event_req_id,
1265            ..
1266        } if event_req_id == req_id => {
1267            print_event(&event);
1268            false
1269        }
1270        Event::AccountUpdateMultiEnd {
1271            req_id: event_req_id,
1272        } if event_req_id == req_id => {
1273            print_event(&event);
1274            true
1275        }
1276        Event::Error { .. } => {
1277            print_event(&event);
1278            false
1279        }
1280        other => {
1281            print_event(&other);
1282            false
1283        }
1284    })
1285    .await?;
1286    if !done {
1287        let _ = client.cancel_account_updates_multi(req_id).await;
1288    }
1289    Ok(())
1290}
1291
1292async fn run_historical_data(client: &mut TwsApiClient) -> Result<(), CliError> {
1293    let req_id = req_id(9201)?;
1294    client
1295        .req_historical_data(HistoricalDataRequest {
1296            req_id,
1297            contract: contract_from_env()?,
1298            end_date_time: env_string("TWS_END_DATE_TIME", ""),
1299            duration_str: env_string("TWS_DURATION_STR", "1 D"),
1300            bar_size_setting: env_string("TWS_BAR_SIZE_SETTING", "1 day"),
1301            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1302            use_rth: env_parse("TWS_USE_RTH", 1i32)?,
1303            format_date: env_parse("TWS_FORMAT_DATE", 1i32)?,
1304            keep_up_to_date: env_bool("TWS_KEEP_UP_TO_DATE", false)?,
1305            chart_options: env_tag_values("TWS_HIST_OPTION"),
1306        })
1307        .await?;
1308    let done = read_until(
1309        client,
1310        env_parse("TWS_WAIT_SECS", 30u64)?,
1311        |event| match event {
1312            Event::HistoricalData {
1313                req_id: event_req_id,
1314                ..
1315            }
1316            | Event::HistoricalDataUpdate {
1317                req_id: event_req_id,
1318                ..
1319            }
1320            | Event::HistoricalDataEnd {
1321                req_id: event_req_id,
1322                ..
1323            } if event_req_id == req_id => {
1324                print_event(&event);
1325                matches!(event, Event::HistoricalDataEnd { .. })
1326            }
1327            Event::Error { .. } => {
1328                print_event(&event);
1329                false
1330            }
1331            other => {
1332                print_event(&other);
1333                false
1334            }
1335        },
1336    )
1337    .await?;
1338    if !done {
1339        let _ = client.cancel_historical_data(req_id).await;
1340    }
1341    Ok(())
1342}
1343
1344async fn run_historical_ticks(client: &mut TwsApiClient) -> Result<(), CliError> {
1345    let req_id = req_id(9202)?;
1346    client
1347        .req_historical_ticks(HistoricalTicksRequest {
1348            req_id,
1349            contract: contract_from_env()?,
1350            start_date_time: env_string("TWS_START_DATE_TIME", ""),
1351            end_date_time: env_string("TWS_END_DATE_TIME", ""),
1352            number_of_ticks: env_parse("TWS_NUMBER_OF_TICKS", 1000i32)?,
1353            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1354            use_rth: env_bool("TWS_USE_RTH", true)?,
1355            ignore_size: env_bool("TWS_IGNORE_SIZE", false)?,
1356            misc_options: env_tag_values("TWS_HIST_TICKS_OPTION"),
1357        })
1358        .await?;
1359    let done = read_until(
1360        client,
1361        env_parse("TWS_WAIT_SECS", 30u64)?,
1362        |event| match event {
1363            Event::HistoricalTicks {
1364                req_id: event_req_id,
1365                done,
1366                ..
1367            }
1368            | Event::HistoricalTicksBidAsk {
1369                req_id: event_req_id,
1370                done,
1371                ..
1372            }
1373            | Event::HistoricalTicksLast {
1374                req_id: event_req_id,
1375                done,
1376                ..
1377            } if event_req_id == req_id => {
1378                print_event(&event);
1379                done
1380            }
1381            Event::Error { .. } => {
1382                print_event(&event);
1383                false
1384            }
1385            other => {
1386                print_event(&other);
1387                false
1388            }
1389        },
1390    )
1391    .await?;
1392    if !done {
1393        let _ = client.cancel_historical_ticks(req_id).await;
1394    }
1395    Ok(())
1396}
1397
1398async fn run_head_timestamp(client: &mut TwsApiClient) -> Result<(), CliError> {
1399    let req_id = req_id(9301)?;
1400    client
1401        .req_head_timestamp(HeadTimestampRequest {
1402            req_id,
1403            contract: contract_from_env()?,
1404            use_rth: env_bool("TWS_USE_RTH", true)?,
1405            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1406            format_date: env_parse("TWS_FORMAT_DATE", 1i32)?,
1407        })
1408        .await?;
1409    read_until(client, 20, |event| match event {
1410        Event::HeadTimestamp {
1411            req_id: event_req_id,
1412            ..
1413        } if event_req_id == req_id => {
1414            print_event(&event);
1415            true
1416        }
1417        Event::Error { .. } => {
1418            print_event(&event);
1419            false
1420        }
1421        other => {
1422            print_event(&other);
1423            false
1424        }
1425    })
1426    .await?;
1427    let _ = client.cancel_head_timestamp(req_id).await;
1428    Ok(())
1429}
1430
1431async fn run_histogram_data(client: &mut TwsApiClient) -> Result<(), CliError> {
1432    let req_id = req_id(9302)?;
1433    client
1434        .req_histogram_data(HistogramDataRequest {
1435            req_id,
1436            contract: contract_from_env()?,
1437            use_rth: env_bool("TWS_USE_RTH", true)?,
1438            time_period: env_string("TWS_TIME_PERIOD", "1 D"),
1439        })
1440        .await?;
1441    read_until(client, 20, |event| match event {
1442        Event::HistogramData {
1443            req_id: event_req_id,
1444            ..
1445        } if event_req_id == req_id => {
1446            print_event(&event);
1447            true
1448        }
1449        Event::Error { .. } => {
1450            print_event(&event);
1451            false
1452        }
1453        other => {
1454            print_event(&other);
1455            false
1456        }
1457    })
1458    .await?;
1459    let _ = client.cancel_histogram_data(req_id).await;
1460    Ok(())
1461}
1462
1463async fn run_contract_details(client: &mut TwsApiClient) -> Result<(), CliError> {
1464    let req_id = req_id(9401)?;
1465    client
1466        .req_contract_details(ContractDetailsRequest {
1467            req_id,
1468            contract: contract_from_env()?,
1469        })
1470        .await?;
1471    read_until(client, 20, |event| match event {
1472        Event::ContractDetails {
1473            req_id: event_req_id,
1474            ..
1475        }
1476        | Event::ContractDetailsEnd {
1477            req_id: event_req_id,
1478        } if event_req_id == req_id => {
1479            print_event(&event);
1480            matches!(event, Event::ContractDetailsEnd { .. })
1481        }
1482        Event::Error { .. } => {
1483            print_event(&event);
1484            false
1485        }
1486        other => {
1487            print_event(&other);
1488            false
1489        }
1490    })
1491    .await?;
1492    let _ = client.cancel_contract_data(req_id).await;
1493    Ok(())
1494}
1495
1496async fn run_bond_contract_details(client: &mut TwsApiClient) -> Result<(), CliError> {
1497    let req_id = req_id(9401)?;
1498    let mut contract = contract_from_env()?;
1499    contract.sec_type = "BOND".to_owned();
1500    client
1501        .req_contract_details(ContractDetailsRequest { req_id, contract })
1502        .await?;
1503    read_until(client, 20, |event| match event {
1504        Event::BondContractDetails {
1505            req_id: event_req_id,
1506            ..
1507        }
1508        | Event::ContractDetailsEnd {
1509            req_id: event_req_id,
1510        } if event_req_id == req_id => {
1511            print_event(&event);
1512            matches!(event, Event::ContractDetailsEnd { .. })
1513        }
1514        Event::Error { .. } => {
1515            print_event(&event);
1516            false
1517        }
1518        other => {
1519            print_event(&other);
1520            false
1521        }
1522    })
1523    .await?;
1524    let _ = client.cancel_contract_data(req_id).await;
1525    Ok(())
1526}
1527
1528async fn run_smart_components(client: &mut TwsApiClient) -> Result<(), CliError> {
1529    let req_id = req_id(9402)?;
1530    client
1531        .req_smart_components(req_id, &env_string("TWS_BBO_EXCHANGE", "a6"))
1532        .await?;
1533    read_until(client, 10, |event| match event {
1534        Event::SmartComponents {
1535            req_id: event_req_id,
1536            ..
1537        } if event_req_id == req_id => {
1538            print_event(&event);
1539            true
1540        }
1541        Event::Error { .. } => {
1542            print_event(&event);
1543            false
1544        }
1545        other => {
1546            print_event(&other);
1547            false
1548        }
1549    })
1550    .await?;
1551    Ok(())
1552}
1553
1554async fn run_market_rule(client: &mut TwsApiClient) -> Result<(), CliError> {
1555    let market_rule_id = env_parse("TWS_MARKET_RULE_ID", 26i32)?;
1556    client.req_market_rule(market_rule_id).await?;
1557    read_until(client, 10, |event| match event {
1558        Event::MarketRule {
1559            market_rule_id: event_market_rule_id,
1560            ..
1561        } if event_market_rule_id == market_rule_id => {
1562            print_event(&event);
1563            true
1564        }
1565        Event::Error { .. } => {
1566            print_event(&event);
1567            false
1568        }
1569        other => {
1570            print_event(&other);
1571            false
1572        }
1573    })
1574    .await?;
1575    Ok(())
1576}
1577
1578async fn run_calculate_implied_volatility(client: &mut TwsApiClient) -> Result<(), CliError> {
1579    let req_id = req_id(9502)?;
1580    client
1581        .calculate_implied_volatility(CalculateImpliedVolatilityRequest {
1582            req_id,
1583            contract: contract_from_env()?,
1584            option_price: env_parse("TWS_OPTION_PRICE", 1.0f64)?,
1585            under_price: env_parse("TWS_UNDER_PRICE", 1.0f64)?,
1586            options: env_tag_values("TWS_IV_OPTION"),
1587        })
1588        .await?;
1589    let done = read_until(client, 10, |event| match event {
1590        Event::TickOptionComputation {
1591            req_id: event_req_id,
1592            ..
1593        } if event_req_id == req_id => {
1594            print_event(&event);
1595            true
1596        }
1597        Event::Error { .. } => {
1598            print_event(&event);
1599            false
1600        }
1601        other => {
1602            print_event(&other);
1603            false
1604        }
1605    })
1606    .await?;
1607    if !done {
1608        let _ = client.cancel_calculate_implied_volatility(req_id).await;
1609    }
1610    Ok(())
1611}
1612
1613async fn run_calculate_option_price(client: &mut TwsApiClient) -> Result<(), CliError> {
1614    let req_id = req_id(9503)?;
1615    client
1616        .calculate_option_price(CalculateOptionPriceRequest {
1617            req_id,
1618            contract: contract_from_env()?,
1619            volatility: env_parse("TWS_VOLATILITY", 0.2f64)?,
1620            under_price: env_parse("TWS_UNDER_PRICE", 1.0f64)?,
1621            options: env_tag_values("TWS_OPT_PRICE_OPTION"),
1622        })
1623        .await?;
1624    let done = read_until(client, 10, |event| match event {
1625        Event::TickOptionComputation {
1626            req_id: event_req_id,
1627            ..
1628        } if event_req_id == req_id => {
1629            print_event(&event);
1630            true
1631        }
1632        Event::Error { .. } => {
1633            print_event(&event);
1634            false
1635        }
1636        other => {
1637            print_event(&other);
1638            false
1639        }
1640    })
1641    .await?;
1642    if !done {
1643        let _ = client.cancel_calculate_option_price(req_id).await;
1644    }
1645    Ok(())
1646}
1647
1648async fn run_exercise_options(client: &mut TwsApiClient) -> Result<(), CliError> {
1649    let order_id = req_id(9602)?;
1650    client
1651        .exercise_options(ExerciseOptionsRequest {
1652            order_id,
1653            contract: contract_from_env()?,
1654            exercise_action: env_parse("TWS_EXERCISE_ACTION", 1i32)?,
1655            exercise_quantity: env_parse("TWS_EXERCISE_QTY", 1i32)?,
1656            account: env_string("TWS_ACCOUNT", ""),
1657            override_system_action: env_bool("TWS_EXERCISE_OVERRIDE", false)?,
1658            manual_order_time: env_string("TWS_MANUAL_ORDER_TIME", ""),
1659            customer_account: env_string("TWS_CUSTOMER_ACCOUNT", ""),
1660            professional_customer: env_bool("TWS_PROFESSIONAL_CUSTOMER", false)?,
1661        })
1662        .await?;
1663    read_until(client, 10, |event| match event {
1664        Event::OpenOrder { .. } | Event::OrderStatus { .. } | Event::Error { .. } => {
1665            print_event(&event);
1666            false
1667        }
1668        other => {
1669            print_event(&other);
1670            false
1671        }
1672    })
1673    .await?;
1674    Ok(())
1675}
1676
1677async fn run_executions(client: &mut TwsApiClient) -> Result<(), CliError> {
1678    let req_id = req_id(9501)?;
1679    client
1680        .req_executions(ExecutionRequest {
1681            req_id,
1682            filter: ExecutionFilter {
1683                client_id: env_parse("TWS_FILTER_CLIENT_ID", 0i32)?,
1684                acct_code: env_string("TWS_ACCOUNT", ""),
1685                time: env_string("TWS_EXEC_TIME", ""),
1686                symbol: env_string("TWS_SYMBOL", ""),
1687                sec_type: env_string("TWS_SEC_TYPE", ""),
1688                exchange: env_string("TWS_EXCHANGE", ""),
1689                side: env_string("TWS_EXEC_SIDE", ""),
1690                ..ExecutionFilter::default()
1691            },
1692        })
1693        .await?;
1694    read_until(client, 20, |event| match event {
1695        Event::ExecutionDetails {
1696            req_id: event_req_id,
1697            ..
1698        }
1699        | Event::ExecutionDetailsEnd {
1700            req_id: event_req_id,
1701        } if event_req_id == req_id => {
1702            print_event(&event);
1703            matches!(event, Event::ExecutionDetailsEnd { .. })
1704        }
1705        Event::Error { .. } => {
1706            print_event(&event);
1707            false
1708        }
1709        other => {
1710            print_event(&other);
1711            false
1712        }
1713    })
1714    .await?;
1715    Ok(())
1716}
1717
1718async fn run_news_bulletins(client: &mut TwsApiClient) -> Result<(), CliError> {
1719    let all_messages = env_bool("TWS_NEWS_ALL_MESSAGES", true)?;
1720    client.req_news_bulletins(all_messages).await?;
1721    let done = read_until(client, 15, |event| match event {
1722        Event::NewsBulletin { .. } => {
1723            print_event(&event);
1724            false
1725        }
1726        Event::Error { .. } => {
1727            print_event(&event);
1728            false
1729        }
1730        other => {
1731            print_event(&other);
1732            false
1733        }
1734    })
1735    .await?;
1736    if !done {
1737        let _ = client.cancel_news_bulletins().await;
1738    }
1739    Ok(())
1740}
1741
1742async fn run_news_article(client: &mut TwsApiClient) -> Result<(), CliError> {
1743    let req_id = req_id(9702)?;
1744    client
1745        .req_news_article(
1746            req_id,
1747            &env_string("TWS_NEWS_PROVIDER_CODE", "BZ"),
1748            &env_string("TWS_NEWS_ARTICLE_ID", ""),
1749            &env_tag_values("TWS_NEWS_OPTION"),
1750        )
1751        .await?;
1752    read_until(client, 10, |event| match event {
1753        Event::NewsArticle {
1754            req_id: event_req_id,
1755            ..
1756        } if event_req_id == req_id => {
1757            print_event(&event);
1758            true
1759        }
1760        Event::Error { .. } => {
1761            print_event(&event);
1762            false
1763        }
1764        other => {
1765            print_event(&other);
1766            false
1767        }
1768    })
1769    .await?;
1770    Ok(())
1771}
1772
1773async fn run_historical_news(client: &mut TwsApiClient) -> Result<(), CliError> {
1774    let req_id = req_id(9703)?;
1775    client
1776        .req_historical_news(HistoricalNewsRequest {
1777            req_id,
1778            con_id: env_parse("TWS_CONID", 0i32)?,
1779            provider_codes: env_string("TWS_NEWS_PROVIDER_CODES", ""),
1780            start_date_time: env_string("TWS_START_DATE_TIME", ""),
1781            end_date_time: env_string("TWS_END_DATE_TIME", ""),
1782            total_results: env_parse("TWS_TOTAL_RESULTS", 10i32)?,
1783            options: env_tag_values("TWS_HNEWS_OPTION"),
1784        })
1785        .await?;
1786    read_until(client, 15, |event| match event {
1787        Event::HistoricalNews {
1788            req_id: event_req_id,
1789            ..
1790        } if event_req_id == req_id => {
1791            print_event(&event);
1792            false
1793        }
1794        Event::HistoricalNewsEnd {
1795            req_id: event_req_id,
1796            ..
1797        } if event_req_id == req_id => {
1798            print_event(&event);
1799            true
1800        }
1801        Event::Error { .. } => {
1802            print_event(&event);
1803            false
1804        }
1805        other => {
1806            print_event(&other);
1807            false
1808        }
1809    })
1810    .await?;
1811    Ok(())
1812}
1813
1814async fn run_scanner(client: &mut TwsApiClient) -> Result<(), CliError> {
1815    let req_id = req_id(9601)?;
1816    client
1817        .req_scanner_subscription(ScannerSubscriptionRequest {
1818            req_id,
1819            subscription: ScannerSubscription {
1820                number_of_rows: env_parse("TWS_SCAN_ROWS", 10i32)?,
1821                instrument: env_string("TWS_SCAN_INSTRUMENT", "STK"),
1822                location_code: env_string("TWS_SCAN_LOCATION", "STK.US.MAJOR"),
1823                scan_code: env_string("TWS_SCAN_CODE", "TOP_PERC_GAIN"),
1824                above_price: env_parse("TWS_SCAN_ABOVE_PRICE", 0.0f64)?,
1825                below_price: env_parse("TWS_SCAN_BELOW_PRICE", 0.0f64)?,
1826                above_volume: env_parse("TWS_SCAN_ABOVE_VOLUME", 0i32)?,
1827                market_cap_above: env_parse("TWS_SCAN_MARKET_CAP_ABOVE", 0.0f64)?,
1828                market_cap_below: env_parse("TWS_SCAN_MARKET_CAP_BELOW", 0.0f64)?,
1829                moody_rating_above: env_string("TWS_SCAN_MOODY_ABOVE", ""),
1830                moody_rating_below: env_string("TWS_SCAN_MOODY_BELOW", ""),
1831                sp_rating_above: env_string("TWS_SCAN_SP_ABOVE", ""),
1832                sp_rating_below: env_string("TWS_SCAN_SP_BELOW", ""),
1833                maturity_date_above: env_string("TWS_SCAN_MATURITY_ABOVE", ""),
1834                maturity_date_below: env_string("TWS_SCAN_MATURITY_BELOW", ""),
1835                coupon_rate_above: env_parse("TWS_SCAN_COUPON_ABOVE", 0.0f64)?,
1836                coupon_rate_below: env_parse("TWS_SCAN_COUPON_BELOW", 0.0f64)?,
1837                exclude_convertible: env_bool("TWS_SCAN_EXCLUDE_CONVERTIBLE", false)?,
1838                average_option_volume_above: env_parse("TWS_SCAN_AVG_OPTION_VOLUME_ABOVE", 0i32)?,
1839                scanner_setting_pairs: env_string("TWS_SCAN_SETTING_PAIRS", ""),
1840                stock_type_filter: env_string("TWS_SCAN_STOCK_TYPE_FILTER", ""),
1841            },
1842            scanner_subscription_options: env_tag_values("TWS_SCAN_OPTION"),
1843            scanner_subscription_filter_options: env_tag_values("TWS_SCAN_FILTER"),
1844        })
1845        .await?;
1846    let done = read_until(
1847        client,
1848        env_parse("TWS_WAIT_SECS", 20u64)?,
1849        |event| match event {
1850            Event::ScannerData {
1851                req_id: event_req_id,
1852                ..
1853            }
1854            | Event::ScannerDataEnd {
1855                req_id: event_req_id,
1856            } if event_req_id == req_id => {
1857                print_event(&event);
1858                matches!(event, Event::ScannerDataEnd { .. })
1859            }
1860            Event::Error { .. } => {
1861                print_event(&event);
1862                false
1863            }
1864            other => {
1865                print_event(&other);
1866                false
1867            }
1868        },
1869    )
1870    .await?;
1871    if !done {
1872        let _ = client.cancel_scanner_subscription(req_id).await;
1873    }
1874    Ok(())
1875}
1876
1877async fn run_scanner_parameters(client: &mut TwsApiClient) -> Result<(), CliError> {
1878    client.req_scanner_parameters().await?;
1879    read_until(client, 10, |event| match event {
1880        Event::ScannerParameters { .. } | Event::Error { .. } => {
1881            print_event(&event);
1882            false
1883        }
1884        other => {
1885            print_event(&other);
1886            false
1887        }
1888    })
1889    .await?;
1890    Ok(())
1891}
1892
1893async fn run_sec_def_opt_params(client: &mut TwsApiClient) -> Result<(), CliError> {
1894    let req_id = req_id(9802)?;
1895    client
1896        .req_sec_def_opt_params(
1897            req_id,
1898            &env_string("TWS_UNDERLYING_SYMBOL", &env_string("TWS_SYMBOL", "AAPL")),
1899            &env_string("TWS_FUT_FOP_EXCHANGE", "SMART"),
1900            &env_string("TWS_UNDERLYING_SEC_TYPE", "STK"),
1901            env_parse("TWS_UNDERLYING_CON_ID", env_parse("TWS_CONID", 0i32)?)?,
1902        )
1903        .await?;
1904    read_until(client, 20, |event| match event {
1905        Event::SecurityDefinitionOptionParameter {
1906            req_id: event_req_id,
1907            ..
1908        }
1909        | Event::SecurityDefinitionOptionParameterEnd {
1910            req_id: event_req_id,
1911        } if event_req_id == req_id => {
1912            print_event(&event);
1913            matches!(event, Event::SecurityDefinitionOptionParameterEnd { .. })
1914        }
1915        Event::Error { .. } => {
1916            print_event(&event);
1917            false
1918        }
1919        other => {
1920            print_event(&other);
1921            false
1922        }
1923    })
1924    .await?;
1925    Ok(())
1926}
1927
1928async fn run_soft_dollar_tiers(client: &mut TwsApiClient) -> Result<(), CliError> {
1929    let req_id = req_id(9803)?;
1930    client.req_soft_dollar_tiers(req_id).await?;
1931    read_until(client, 10, |event| match event {
1932        Event::SoftDollarTiers {
1933            req_id: event_req_id,
1934            ..
1935        } if event_req_id == req_id => {
1936            print_event(&event);
1937            true
1938        }
1939        Event::Error { .. } => {
1940            print_event(&event);
1941            false
1942        }
1943        other => {
1944            print_event(&other);
1945            false
1946        }
1947    })
1948    .await?;
1949    Ok(())
1950}
1951
1952async fn run_family_codes(client: &mut TwsApiClient) -> Result<(), CliError> {
1953    client.req_family_codes().await?;
1954    read_until(client, 10, |event| match event {
1955        Event::FamilyCodes { .. } | Event::Error { .. } => {
1956            print_event(&event);
1957            true
1958        }
1959        other => {
1960            print_event(&other);
1961            false
1962        }
1963    })
1964    .await?;
1965    Ok(())
1966}
1967
1968async fn run_matching_symbols(client: &mut TwsApiClient) -> Result<(), CliError> {
1969    let req_id = req_id(9804)?;
1970    client
1971        .req_matching_symbols(req_id, &env_string("TWS_MATCH_PATTERN", "AAPL"))
1972        .await?;
1973    read_until(client, 10, |event| match event {
1974        Event::SymbolSamples {
1975            req_id: event_req_id,
1976            ..
1977        } if event_req_id == req_id => {
1978            print_event(&event);
1979            true
1980        }
1981        Event::Error { .. } => {
1982            print_event(&event);
1983            false
1984        }
1985        other => {
1986            print_event(&other);
1987            false
1988        }
1989    })
1990    .await?;
1991    Ok(())
1992}
1993
1994async fn run_query_display_groups(client: &mut TwsApiClient) -> Result<(), CliError> {
1995    let req_id = req_id(9805)?;
1996    client.query_display_groups(req_id).await?;
1997    read_until(client, 10, |event| match event {
1998        Event::DisplayGroupList {
1999            req_id: event_req_id,
2000            ..
2001        } if event_req_id == req_id => {
2002            print_event(&event);
2003            true
2004        }
2005        Event::Error { .. } => {
2006            print_event(&event);
2007            false
2008        }
2009        other => {
2010            print_event(&other);
2011            false
2012        }
2013    })
2014    .await?;
2015    Ok(())
2016}
2017
2018async fn run_subscribe_to_group_events(client: &mut TwsApiClient) -> Result<(), CliError> {
2019    let req_id = req_id(9806)?;
2020    let group_id = env_parse("TWS_GROUP_ID", 1i32)?;
2021    client.subscribe_to_group_events(req_id, group_id).await?;
2022    let done = read_until(client, 15, |event| match event {
2023        Event::DisplayGroupList {
2024            req_id: event_req_id,
2025            ..
2026        } if event_req_id == req_id => {
2027            print_event(&event);
2028            false
2029        }
2030        Event::DisplayGroupUpdated {
2031            req_id: event_req_id,
2032            ..
2033        } if event_req_id == req_id => {
2034            print_event(&event);
2035            false
2036        }
2037        Event::Error { .. } => {
2038            print_event(&event);
2039            false
2040        }
2041        other => {
2042            print_event(&other);
2043            false
2044        }
2045    })
2046    .await?;
2047    if !done {
2048        let _ = client.unsubscribe_from_group_events(req_id).await;
2049    }
2050    Ok(())
2051}
2052
2053async fn run_update_display_group(client: &mut TwsApiClient) -> Result<(), CliError> {
2054    let req_id = req_id(9807)?;
2055    client
2056        .update_display_group(req_id, &env_string("TWS_CONTRACT_INFO", ""))
2057        .await?;
2058    read_until(client, 10, |event| match event {
2059        Event::DisplayGroupUpdated {
2060            req_id: event_req_id,
2061            ..
2062        } if event_req_id == req_id => {
2063            print_event(&event);
2064            true
2065        }
2066        Event::Error { .. } => {
2067            print_event(&event);
2068            false
2069        }
2070        other => {
2071            print_event(&other);
2072            false
2073        }
2074    })
2075    .await?;
2076    Ok(())
2077}
2078
2079async fn run_unsubscribe_from_group_events(client: &mut TwsApiClient) -> Result<(), CliError> {
2080    let req_id = req_id(9806)?;
2081    client.unsubscribe_from_group_events(req_id).await?;
2082    println!("unsubscribe_from_group_events req_id={req_id}");
2083    Ok(())
2084}
2085
2086async fn run_request_fa(client: &mut TwsApiClient) -> Result<(), CliError> {
2087    let fa_data_type = env_parse("TWS_FA_DATA_TYPE", 1i32)?;
2088    client.request_fa(fa_data_type).await?;
2089    read_until(client, 10, |event| match event {
2090        Event::ReceiveFa {
2091            fa_data_type: event_type,
2092            ..
2093        } if event_type == fa_data_type => {
2094            print_event(&event);
2095            true
2096        }
2097        Event::Error { .. } => {
2098            print_event(&event);
2099            false
2100        }
2101        other => {
2102            print_event(&other);
2103            false
2104        }
2105    })
2106    .await?;
2107    Ok(())
2108}
2109
2110async fn run_replace_fa(client: &mut TwsApiClient) -> Result<(), CliError> {
2111    let req_id = req_id(9808)?;
2112    let fa_data_type = env_parse("TWS_FA_DATA_TYPE", 1i32)?;
2113    client
2114        .replace_fa(req_id, fa_data_type, &env_string("TWS_FA_XML", ""))
2115        .await?;
2116    read_until(client, 10, |event| match event {
2117        Event::ReplaceFaEnd {
2118            req_id: event_req_id,
2119            ..
2120        } if event_req_id == req_id => {
2121            print_event(&event);
2122            true
2123        }
2124        Event::Error { .. } => {
2125            print_event(&event);
2126            false
2127        }
2128        other => {
2129            print_event(&other);
2130            false
2131        }
2132    })
2133    .await?;
2134    Ok(())
2135}
2136
2137async fn run_wsh_meta_data(client: &mut TwsApiClient) -> Result<(), CliError> {
2138    let req_id = req_id(9809)?;
2139    client.req_wsh_meta_data(req_id).await?;
2140    read_until(client, 10, |event| match event {
2141        Event::WshMetaData {
2142            req_id: event_req_id,
2143            ..
2144        } if event_req_id == req_id => {
2145            print_event(&event);
2146            true
2147        }
2148        Event::Error { .. } => {
2149            print_event(&event);
2150            false
2151        }
2152        other => {
2153            print_event(&other);
2154            false
2155        }
2156    })
2157    .await?;
2158    let _ = client.cancel_wsh_meta_data(req_id).await;
2159    Ok(())
2160}
2161
2162async fn run_wsh_event_data(client: &mut TwsApiClient) -> Result<(), CliError> {
2163    let req_id = req_id(9810)?;
2164    client
2165        .req_wsh_event_data(WshEventDataRequest {
2166            req_id,
2167            con_id: env_parse("TWS_CONID", 0i32)?,
2168            filter: env_string("TWS_WSH_FILTER", ""),
2169            fill_watchlist: env_bool("TWS_WSH_FILL_WATCHLIST", false)?,
2170            fill_portfolio: env_bool("TWS_WSH_FILL_PORTFOLIO", false)?,
2171            fill_competitors: env_bool("TWS_WSH_FILL_COMPETITORS", false)?,
2172            start_date: env_string("TWS_START_DATE", ""),
2173            end_date: env_string("TWS_END_DATE", ""),
2174            total_limit: env_parse("TWS_TOTAL_LIMIT", 100i32)?,
2175        })
2176        .await?;
2177    let done = read_until(client, 10, |event| match event {
2178        Event::WshEventData {
2179            req_id: event_req_id,
2180            ..
2181        } if event_req_id == req_id => {
2182            print_event(&event);
2183            false
2184        }
2185        Event::Error { .. } => {
2186            print_event(&event);
2187            false
2188        }
2189        other => {
2190            print_event(&other);
2191            false
2192        }
2193    })
2194    .await?;
2195    if !done {
2196        let _ = client.cancel_wsh_event_data(req_id).await;
2197    }
2198    Ok(())
2199}
2200
2201async fn run_user_info(client: &mut TwsApiClient) -> Result<(), CliError> {
2202    let req_id = req_id(9811)?;
2203    client.req_user_info(req_id).await?;
2204    read_until(client, 10, |event| match event {
2205        Event::UserInfo {
2206            req_id: event_req_id,
2207            ..
2208        } if event_req_id == req_id => {
2209            print_event(&event);
2210            true
2211        }
2212        Event::Error { .. } => {
2213            print_event(&event);
2214            false
2215        }
2216        other => {
2217            print_event(&other);
2218            false
2219        }
2220    })
2221    .await?;
2222    Ok(())
2223}
2224async fn run_real_time_bars(client: &mut TwsApiClient) -> Result<(), CliError> {
2225    let req_id = req_id(9701)?;
2226    client
2227        .req_real_time_bars(RealTimeBarsRequest {
2228            req_id,
2229            contract: contract_from_env()?,
2230            bar_size: env_parse("TWS_BAR_SIZE", 5i32)?,
2231            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
2232            use_rth: env_bool("TWS_USE_RTH", true)?,
2233            options: env_tag_values("TWS_RTBAR_OPTION"),
2234        })
2235        .await?;
2236    let done = read_until(
2237        client,
2238        env_parse("TWS_WAIT_SECS", 20u64)?,
2239        |event| match event {
2240            Event::RealTimeBar {
2241                req_id: event_req_id,
2242                ..
2243            } if event_req_id == req_id => {
2244                print_event(&event);
2245                false
2246            }
2247            Event::Error { .. } => {
2248                print_event(&event);
2249                false
2250            }
2251            other => {
2252                print_event(&other);
2253                false
2254            }
2255        },
2256    )
2257    .await?;
2258    if !done {
2259        let _ = client.cancel_real_time_bars(req_id).await;
2260    }
2261    Ok(())
2262}
2263
2264async fn run_tick_by_tick(client: &mut TwsApiClient) -> Result<(), CliError> {
2265    let req_id = req_id(9801)?;
2266    client
2267        .req_tick_by_tick_data(TickByTickRequest {
2268            req_id,
2269            contract: contract_from_env()?,
2270            tick_type: env_string("TWS_TICK_TYPE", "Last"),
2271            number_of_ticks: env_parse("TWS_NUMBER_OF_TICKS", 0i32)?,
2272            ignore_size: env_bool("TWS_IGNORE_SIZE", false)?,
2273        })
2274        .await?;
2275    let done = read_until(
2276        client,
2277        env_parse("TWS_WAIT_SECS", 20u64)?,
2278        |event| match event {
2279            Event::TickByTick {
2280                req_id: event_req_id,
2281                ..
2282            } if event_req_id == req_id => {
2283                print_event(&event);
2284                false
2285            }
2286            Event::Error { .. } => {
2287                print_event(&event);
2288                false
2289            }
2290            other => {
2291                print_event(&other);
2292                false
2293            }
2294        },
2295    )
2296    .await?;
2297    if !done {
2298        let _ = client.cancel_tick_by_tick_data(req_id).await;
2299    }
2300    Ok(())
2301}
2302
2303async fn run_pnl(client: &mut TwsApiClient) -> Result<(), CliError> {
2304    let req_id = req_id(9901)?;
2305    client
2306        .req_pnl(
2307            req_id,
2308            &env_string("TWS_ACCOUNT", ""),
2309            &env_string("TWS_MODEL_CODE", ""),
2310        )
2311        .await?;
2312    read_until(client, 10, |event| match event {
2313        Event::Pnl {
2314            req_id: event_req_id,
2315            ..
2316        } if event_req_id == req_id => {
2317            print_event(&event);
2318            false
2319        }
2320        Event::Error { .. } => {
2321            print_event(&event);
2322            false
2323        }
2324        other => {
2325            print_event(&other);
2326            false
2327        }
2328    })
2329    .await?;
2330    let _ = client.cancel_pnl(req_id).await;
2331    Ok(())
2332}
2333
2334async fn run_pnl_single(client: &mut TwsApiClient) -> Result<(), CliError> {
2335    let req_id = req_id(9902)?;
2336    client
2337        .req_pnl_single(
2338            req_id,
2339            &env_string("TWS_ACCOUNT", ""),
2340            &env_string("TWS_MODEL_CODE", ""),
2341            env_parse("TWS_CONID", 0i32)?,
2342        )
2343        .await?;
2344    read_until(client, 10, |event| match event {
2345        Event::PnlSingle {
2346            req_id: event_req_id,
2347            ..
2348        } if event_req_id == req_id => {
2349            print_event(&event);
2350            false
2351        }
2352        Event::Error { .. } => {
2353            print_event(&event);
2354            false
2355        }
2356        other => {
2357            print_event(&other);
2358            false
2359        }
2360    })
2361    .await?;
2362    let _ = client.cancel_pnl_single(req_id).await;
2363    Ok(())
2364}
2365
2366async fn run_managed_accounts(client: &mut TwsApiClient) -> Result<(), CliError> {
2367    client.req_managed_accounts().await?;
2368    read_until(client, 5, |event| match event {
2369        Event::ManagedAccounts { .. } | Event::Error { .. } => {
2370            print_event(&event);
2371            false
2372        }
2373        other => {
2374            print_event(&other);
2375            false
2376        }
2377    })
2378    .await?;
2379    Ok(())
2380}
2381
2382async fn run_disconnect(client: &mut TwsApiClient) -> Result<(), CliError> {
2383    client.disconnect().await?;
2384    println!("disconnected");
2385    Ok(())
2386}
Source

pub const fn api_ready(&self) -> bool

Returns whether initial API callbacks have been received after startApi.

Examples found in repository?
examples/twsapi/main.rs (line 522)
520async fn wait_until_api_ready(client: &mut TwsApiClient) -> Result<(), CliError> {
521    let result = tokio::time::timeout(Duration::from_secs(10), async {
522        while !client.api_ready() {
523            match client.read_event().await? {
524                Event::Error { code, message, .. } => {
525                    eprintln!("TWS notice {code}: {message}");
526                }
527                other => {
528                    print_event(&other);
529                }
530            }
531        }
532        truefix_twsapi_client::error::TwsApiResult::Ok(())
533    })
534    .await;
535
536    match result {
537        Ok(Ok(())) => Ok(()),
538        Ok(Err(err)) => Err(err.into()),
539        Err(_) => Err(CliError::Usage(
540            "timed out waiting for initial API callbacks".to_owned(),
541        )),
542    }
543}
More examples
Hide additional examples
examples/request_market_data.rs (line 134)
130async fn wait_until_api_ready(
131    client: &mut TwsApiClient,
132) -> truefix_twsapi_client::error::TwsApiResult<()> {
133    let result = tokio::time::timeout(Duration::from_secs(10), async {
134        while !client.api_ready() {
135            match client.read_event().await? {
136                Event::Error { code, message, .. } if is_market_data_status_code(code) => {
137                    eprintln!("TWS status {code}: {message}");
138                }
139                Event::Error { code, message, .. } => {
140                    eprintln!("TWS notice {code}: {message}");
141                }
142                _ => {}
143            }
144        }
145        truefix_twsapi_client::error::TwsApiResult::Ok(())
146    })
147    .await;
148
149    match result {
150        Ok(result) => result,
151        Err(_) => {
152            eprintln!("timed out waiting for initial API callbacks");
153            Ok(())
154        }
155    }
156}
Source

pub async fn start_api(&mut self) -> TwsApiResult<()>

Sends startApi.

Source

pub async fn req_current_time(&mut self) -> TwsApiResult<()>

Sends reqCurrentTime.

Examples found in repository?
examples/twsapi/main.rs (line 843)
842async fn run_current_time(client: &mut TwsApiClient) -> Result<(), CliError> {
843    client.req_current_time().await?;
844    read_until(client, 5, |event| match event {
845        Event::CurrentTime { .. } | Event::CurrentTimeInMillis { .. } => {
846            print_event(&event);
847            true
848        }
849        Event::Error { .. } => {
850            print_event(&event);
851            true
852        }
853        other => {
854            print_event(&other);
855            false
856        }
857    })
858    .await?;
859    Ok(())
860}
More examples
Hide additional examples
examples/request_current_time.rs (line 17)
5async fn main() -> truefix_twsapi_client::error::TwsApiResult<()> {
6    let host = std::env::var("TWS_HOST").unwrap_or_else(|_| "127.0.0.1".to_owned());
7    let port = std::env::var("TWS_PORT")
8        .ok()
9        .and_then(|value| value.parse::<u16>().ok())
10        .unwrap_or(7497);
11    let client_id = std::env::var("TWS_CLIENT_ID")
12        .ok()
13        .and_then(|value| value.parse::<i32>().ok())
14        .unwrap_or(1001);
15
16    let mut client = TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?;
17    client.req_current_time().await?;
18
19    loop {
20        match client.read_event().await? {
21            Event::CurrentTime { time } => {
22                println!("{time}");
23                break;
24            }
25            Event::Error { code, message, .. } => {
26                eprintln!("TWS error {code}: {message}");
27                break;
28            }
29            _ => {}
30        }
31    }
32
33    Ok(())
34}
Source

pub async fn req_ids(&mut self, num_ids: i32) -> TwsApiResult<()>

Sends reqIds.

Examples found in repository?
examples/twsapi/main.rs (line 884)
882async fn run_request_ids(client: &mut TwsApiClient) -> Result<(), CliError> {
883    let num_ids = env_parse("TWS_NUM_IDS", 1i32)?;
884    client.req_ids(num_ids).await?;
885    read_until(client, 5, |event| match event {
886        Event::NextValidId { order_id } => {
887            println!("next_valid_id order_id={order_id}");
888            true
889        }
890        Event::Error { .. } => {
891            print_event(&event);
892            false
893        }
894        other => {
895            print_event(&other);
896            false
897        }
898    })
899    .await?;
900    Ok(())
901}
Source

pub async fn req_positions(&mut self) -> TwsApiResult<()>

Sends reqPositions.

Examples found in repository?
examples/twsapi/main.rs (line 1195)
1194async fn run_positions(client: &mut TwsApiClient) -> Result<(), CliError> {
1195    client.req_positions().await?;
1196    read_until(client, 20, |event| match event {
1197        Event::Position { .. } | Event::PositionEnd => {
1198            print_event(&event);
1199            matches!(event, Event::PositionEnd)
1200        }
1201        Event::Error { .. } => {
1202            print_event(&event);
1203            false
1204        }
1205        other => {
1206            print_event(&other);
1207            false
1208        }
1209    })
1210    .await?;
1211    let _ = client.cancel_positions().await;
1212    Ok(())
1213}
Source

pub async fn send_request<R>(&mut self, request: R) -> TwsApiResult<()>

Sends any field-encoded request.

Source

pub async fn raw_request( &mut self, message: Outgoing, fields: String, ) -> TwsApiResult<()>

Sends a raw field-encoded request. fields must contain only fields after the message id.

Source

pub async fn set_server_log_level(&mut self, log_level: i32) -> TwsApiResult<()>

Sends setServerLogLevel.

Examples found in repository?
examples/twsapi/main.rs (line 905)
903async fn run_set_server_log_level(client: &mut TwsApiClient) -> Result<(), CliError> {
904    let log_level = env_parse("TWS_LOG_LEVEL", 1i32)?;
905    client.set_server_log_level(log_level).await?;
906    println!("server_log_level={log_level}");
907    Ok(())
908}
Source

pub async fn req_mkt_data( &mut self, request: MarketDataRequest, ) -> TwsApiResult<()>

Sends reqMktData.

Examples found in repository?
examples/twsapi/main.rs (lines 922-929)
910async fn run_market_data(
911    client: &mut TwsApiClient,
912    symbol: Option<String>,
913) -> Result<(), CliError> {
914    client
915        .req_market_data_type(env_parse("TWS_MARKET_DATA_TYPE", 1i32)?)
916        .await?;
917    let req_id = req_id(9001)?;
918    let symbol = symbol.unwrap_or_else(|| env_string("TWS_SYMBOL", "AAPL"));
919    let mut contract = contract_from_env()?;
920    contract.symbol = symbol;
921    client
922        .req_mkt_data(MarketDataRequest {
923            req_id,
924            contract,
925            generic_tick_list: env_string("TWS_GENERIC_TICK_LIST", ""),
926            snapshot: env_bool("TWS_SNAPSHOT", false)?,
927            regulatory_snapshot: env_bool("TWS_REGULATORY_SNAPSHOT", false)?,
928            market_data_options: env_tag_values("TWS_MARKET_DATA_OPTION"),
929        })
930        .await?;
931    let done = read_until(
932        client,
933        env_parse("TWS_WAIT_SECS", 30u64)?,
934        |event| match event {
935            Event::TickPrice {
936                req_id: event_req_id,
937                ..
938            }
939            | Event::TickSize {
940                req_id: event_req_id,
941                ..
942            }
943            | Event::TickString {
944                req_id: event_req_id,
945                ..
946            }
947            | Event::TickGeneric {
948                req_id: event_req_id,
949                ..
950            }
951            | Event::TickOptionComputation {
952                req_id: event_req_id,
953                ..
954            } if event_req_id == req_id => {
955                print_event(&event);
956                true
957            }
958            Event::Error {
959                req_id: event_req_id,
960                ..
961            } if event_req_id == req_id => {
962                print_event(&event);
963                true
964            }
965            Event::Error { code, message, .. } => {
966                eprintln!("TWS notice {code}: {message}");
967                false
968            }
969            other => {
970                print_event(&other);
971                false
972            }
973        },
974    )
975    .await?;
976    if !done {
977        let _ = client.cancel_mkt_data(req_id).await;
978    }
979    Ok(())
980}
More examples
Hide additional examples
examples/request_market_data.rs (lines 32-45)
9async fn main() -> truefix_twsapi_client::error::TwsApiResult<()> {
10    let host = std::env::var("TWS_HOST").unwrap_or_else(|_| "127.0.0.1".to_owned());
11    let port = std::env::var("TWS_PORT")
12        .ok()
13        .and_then(|value| value.parse::<u16>().ok())
14        .unwrap_or(7497);
15    let client_id = std::env::var("TWS_CLIENT_ID")
16        .ok()
17        .and_then(|value| value.parse::<i32>().ok())
18        .unwrap_or(1002);
19    let symbol = std::env::var("TWS_SYMBOL").unwrap_or_else(|_| "AAPL".to_owned());
20    let exchange = std::env::var("TWS_EXCHANGE").unwrap_or_else(|_| "SMART".to_owned());
21    let currency = std::env::var("TWS_CURRENCY").unwrap_or_else(|_| "USD".to_owned());
22    let market_data_type = std::env::var("TWS_MARKET_DATA_TYPE")
23        .ok()
24        .and_then(|value| value.parse::<i32>().ok())
25        .unwrap_or(1);
26
27    let req_id = 9001;
28    let mut client = TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?;
29    wait_until_api_ready(&mut client).await?;
30    client.req_market_data_type(market_data_type).await?;
31    client
32        .req_mkt_data(MarketDataRequest {
33            req_id,
34            contract: Contract {
35                symbol,
36                sec_type: "STK".to_owned(),
37                exchange,
38                currency,
39                ..Contract::default()
40            },
41            generic_tick_list: String::new(),
42            snapshot: false,
43            regulatory_snapshot: false,
44            market_data_options: Vec::new(),
45        })
46        .await?;
47
48    let result = tokio::time::timeout(Duration::from_secs(30), async {
49        let should_cancel = loop {
50            match client.read_event().await? {
51                Event::TickPrice {
52                    req_id: event_req_id,
53                    tick_type,
54                    price,
55                    attrib,
56                } if event_req_id == req_id => {
57                    println!("price tick_type={tick_type} price={price} attrib={attrib}");
58                    break true;
59                }
60                Event::TickSize {
61                    req_id: event_req_id,
62                    tick_type,
63                    size,
64                } if event_req_id == req_id => {
65                    println!("size tick_type={tick_type} size={size}");
66                }
67                Event::Error {
68                    req_id: event_req_id,
69                    code,
70                    message,
71                    ..
72                } if event_req_id < 0 && is_market_data_status_code(code) => {
73                    eprintln!("TWS status {code}: {message}");
74                }
75                Event::Error {
76                    req_id: event_req_id,
77                    code,
78                    message,
79                    ..
80                } if event_req_id == req_id && is_delayed_market_data_notice(code) => {
81                    eprintln!("TWS notice {code}: {message}");
82                }
83                Event::Error {
84                    req_id: event_req_id,
85                    code,
86                    message,
87                    ..
88                } if event_req_id == req_id => {
89                    eprintln!("TWS error {code}: {message}");
90                    break false;
91                }
92                Event::Error { code, message, .. } => {
93                    eprintln!("TWS notice {code}: {message}");
94                }
95                _ => {}
96            }
97        };
98        truefix_twsapi_client::error::TwsApiResult::Ok(should_cancel)
99    })
100    .await;
101
102    let should_cancel = match &result {
103        Ok(Ok(should_cancel)) => *should_cancel,
104        Ok(Err(_)) | Err(_) => true,
105    };
106    if should_cancel && let Err(error) = client.cancel_mkt_data(req_id).await {
107        eprintln!("cancelMktData failed: {error}");
108    }
109    if should_cancel {
110        tokio::time::sleep(Duration::from_millis(250)).await;
111    }
112
113    match result {
114        Ok(result) => result.map(|_| ()),
115        Err(_) => {
116            eprintln!("timed out waiting for market data");
117            Ok(())
118        }
119    }
120}
Source

pub async fn cancel_mkt_data(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelMktData.

Examples found in repository?
examples/twsapi/main.rs (line 977)
910async fn run_market_data(
911    client: &mut TwsApiClient,
912    symbol: Option<String>,
913) -> Result<(), CliError> {
914    client
915        .req_market_data_type(env_parse("TWS_MARKET_DATA_TYPE", 1i32)?)
916        .await?;
917    let req_id = req_id(9001)?;
918    let symbol = symbol.unwrap_or_else(|| env_string("TWS_SYMBOL", "AAPL"));
919    let mut contract = contract_from_env()?;
920    contract.symbol = symbol;
921    client
922        .req_mkt_data(MarketDataRequest {
923            req_id,
924            contract,
925            generic_tick_list: env_string("TWS_GENERIC_TICK_LIST", ""),
926            snapshot: env_bool("TWS_SNAPSHOT", false)?,
927            regulatory_snapshot: env_bool("TWS_REGULATORY_SNAPSHOT", false)?,
928            market_data_options: env_tag_values("TWS_MARKET_DATA_OPTION"),
929        })
930        .await?;
931    let done = read_until(
932        client,
933        env_parse("TWS_WAIT_SECS", 30u64)?,
934        |event| match event {
935            Event::TickPrice {
936                req_id: event_req_id,
937                ..
938            }
939            | Event::TickSize {
940                req_id: event_req_id,
941                ..
942            }
943            | Event::TickString {
944                req_id: event_req_id,
945                ..
946            }
947            | Event::TickGeneric {
948                req_id: event_req_id,
949                ..
950            }
951            | Event::TickOptionComputation {
952                req_id: event_req_id,
953                ..
954            } if event_req_id == req_id => {
955                print_event(&event);
956                true
957            }
958            Event::Error {
959                req_id: event_req_id,
960                ..
961            } if event_req_id == req_id => {
962                print_event(&event);
963                true
964            }
965            Event::Error { code, message, .. } => {
966                eprintln!("TWS notice {code}: {message}");
967                false
968            }
969            other => {
970                print_event(&other);
971                false
972            }
973        },
974    )
975    .await?;
976    if !done {
977        let _ = client.cancel_mkt_data(req_id).await;
978    }
979    Ok(())
980}
More examples
Hide additional examples
examples/request_market_data.rs (line 106)
9async fn main() -> truefix_twsapi_client::error::TwsApiResult<()> {
10    let host = std::env::var("TWS_HOST").unwrap_or_else(|_| "127.0.0.1".to_owned());
11    let port = std::env::var("TWS_PORT")
12        .ok()
13        .and_then(|value| value.parse::<u16>().ok())
14        .unwrap_or(7497);
15    let client_id = std::env::var("TWS_CLIENT_ID")
16        .ok()
17        .and_then(|value| value.parse::<i32>().ok())
18        .unwrap_or(1002);
19    let symbol = std::env::var("TWS_SYMBOL").unwrap_or_else(|_| "AAPL".to_owned());
20    let exchange = std::env::var("TWS_EXCHANGE").unwrap_or_else(|_| "SMART".to_owned());
21    let currency = std::env::var("TWS_CURRENCY").unwrap_or_else(|_| "USD".to_owned());
22    let market_data_type = std::env::var("TWS_MARKET_DATA_TYPE")
23        .ok()
24        .and_then(|value| value.parse::<i32>().ok())
25        .unwrap_or(1);
26
27    let req_id = 9001;
28    let mut client = TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?;
29    wait_until_api_ready(&mut client).await?;
30    client.req_market_data_type(market_data_type).await?;
31    client
32        .req_mkt_data(MarketDataRequest {
33            req_id,
34            contract: Contract {
35                symbol,
36                sec_type: "STK".to_owned(),
37                exchange,
38                currency,
39                ..Contract::default()
40            },
41            generic_tick_list: String::new(),
42            snapshot: false,
43            regulatory_snapshot: false,
44            market_data_options: Vec::new(),
45        })
46        .await?;
47
48    let result = tokio::time::timeout(Duration::from_secs(30), async {
49        let should_cancel = loop {
50            match client.read_event().await? {
51                Event::TickPrice {
52                    req_id: event_req_id,
53                    tick_type,
54                    price,
55                    attrib,
56                } if event_req_id == req_id => {
57                    println!("price tick_type={tick_type} price={price} attrib={attrib}");
58                    break true;
59                }
60                Event::TickSize {
61                    req_id: event_req_id,
62                    tick_type,
63                    size,
64                } if event_req_id == req_id => {
65                    println!("size tick_type={tick_type} size={size}");
66                }
67                Event::Error {
68                    req_id: event_req_id,
69                    code,
70                    message,
71                    ..
72                } if event_req_id < 0 && is_market_data_status_code(code) => {
73                    eprintln!("TWS status {code}: {message}");
74                }
75                Event::Error {
76                    req_id: event_req_id,
77                    code,
78                    message,
79                    ..
80                } if event_req_id == req_id && is_delayed_market_data_notice(code) => {
81                    eprintln!("TWS notice {code}: {message}");
82                }
83                Event::Error {
84                    req_id: event_req_id,
85                    code,
86                    message,
87                    ..
88                } if event_req_id == req_id => {
89                    eprintln!("TWS error {code}: {message}");
90                    break false;
91                }
92                Event::Error { code, message, .. } => {
93                    eprintln!("TWS notice {code}: {message}");
94                }
95                _ => {}
96            }
97        };
98        truefix_twsapi_client::error::TwsApiResult::Ok(should_cancel)
99    })
100    .await;
101
102    let should_cancel = match &result {
103        Ok(Ok(should_cancel)) => *should_cancel,
104        Ok(Err(_)) | Err(_) => true,
105    };
106    if should_cancel && let Err(error) = client.cancel_mkt_data(req_id).await {
107        eprintln!("cancelMktData failed: {error}");
108    }
109    if should_cancel {
110        tokio::time::sleep(Duration::from_millis(250)).await;
111    }
112
113    match result {
114        Ok(result) => result.map(|_| ()),
115        Err(_) => {
116            eprintln!("timed out waiting for market data");
117            Ok(())
118        }
119    }
120}
Source

pub async fn req_market_data_type( &mut self, market_data_type: i32, ) -> TwsApiResult<()>

Sends reqMarketDataType.

Examples found in repository?
examples/twsapi/main.rs (line 915)
910async fn run_market_data(
911    client: &mut TwsApiClient,
912    symbol: Option<String>,
913) -> Result<(), CliError> {
914    client
915        .req_market_data_type(env_parse("TWS_MARKET_DATA_TYPE", 1i32)?)
916        .await?;
917    let req_id = req_id(9001)?;
918    let symbol = symbol.unwrap_or_else(|| env_string("TWS_SYMBOL", "AAPL"));
919    let mut contract = contract_from_env()?;
920    contract.symbol = symbol;
921    client
922        .req_mkt_data(MarketDataRequest {
923            req_id,
924            contract,
925            generic_tick_list: env_string("TWS_GENERIC_TICK_LIST", ""),
926            snapshot: env_bool("TWS_SNAPSHOT", false)?,
927            regulatory_snapshot: env_bool("TWS_REGULATORY_SNAPSHOT", false)?,
928            market_data_options: env_tag_values("TWS_MARKET_DATA_OPTION"),
929        })
930        .await?;
931    let done = read_until(
932        client,
933        env_parse("TWS_WAIT_SECS", 30u64)?,
934        |event| match event {
935            Event::TickPrice {
936                req_id: event_req_id,
937                ..
938            }
939            | Event::TickSize {
940                req_id: event_req_id,
941                ..
942            }
943            | Event::TickString {
944                req_id: event_req_id,
945                ..
946            }
947            | Event::TickGeneric {
948                req_id: event_req_id,
949                ..
950            }
951            | Event::TickOptionComputation {
952                req_id: event_req_id,
953                ..
954            } if event_req_id == req_id => {
955                print_event(&event);
956                true
957            }
958            Event::Error {
959                req_id: event_req_id,
960                ..
961            } if event_req_id == req_id => {
962                print_event(&event);
963                true
964            }
965            Event::Error { code, message, .. } => {
966                eprintln!("TWS notice {code}: {message}");
967                false
968            }
969            other => {
970                print_event(&other);
971                false
972            }
973        },
974    )
975    .await?;
976    if !done {
977        let _ = client.cancel_mkt_data(req_id).await;
978    }
979    Ok(())
980}
More examples
Hide additional examples
examples/request_market_data.rs (line 30)
9async fn main() -> truefix_twsapi_client::error::TwsApiResult<()> {
10    let host = std::env::var("TWS_HOST").unwrap_or_else(|_| "127.0.0.1".to_owned());
11    let port = std::env::var("TWS_PORT")
12        .ok()
13        .and_then(|value| value.parse::<u16>().ok())
14        .unwrap_or(7497);
15    let client_id = std::env::var("TWS_CLIENT_ID")
16        .ok()
17        .and_then(|value| value.parse::<i32>().ok())
18        .unwrap_or(1002);
19    let symbol = std::env::var("TWS_SYMBOL").unwrap_or_else(|_| "AAPL".to_owned());
20    let exchange = std::env::var("TWS_EXCHANGE").unwrap_or_else(|_| "SMART".to_owned());
21    let currency = std::env::var("TWS_CURRENCY").unwrap_or_else(|_| "USD".to_owned());
22    let market_data_type = std::env::var("TWS_MARKET_DATA_TYPE")
23        .ok()
24        .and_then(|value| value.parse::<i32>().ok())
25        .unwrap_or(1);
26
27    let req_id = 9001;
28    let mut client = TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?;
29    wait_until_api_ready(&mut client).await?;
30    client.req_market_data_type(market_data_type).await?;
31    client
32        .req_mkt_data(MarketDataRequest {
33            req_id,
34            contract: Contract {
35                symbol,
36                sec_type: "STK".to_owned(),
37                exchange,
38                currency,
39                ..Contract::default()
40            },
41            generic_tick_list: String::new(),
42            snapshot: false,
43            regulatory_snapshot: false,
44            market_data_options: Vec::new(),
45        })
46        .await?;
47
48    let result = tokio::time::timeout(Duration::from_secs(30), async {
49        let should_cancel = loop {
50            match client.read_event().await? {
51                Event::TickPrice {
52                    req_id: event_req_id,
53                    tick_type,
54                    price,
55                    attrib,
56                } if event_req_id == req_id => {
57                    println!("price tick_type={tick_type} price={price} attrib={attrib}");
58                    break true;
59                }
60                Event::TickSize {
61                    req_id: event_req_id,
62                    tick_type,
63                    size,
64                } if event_req_id == req_id => {
65                    println!("size tick_type={tick_type} size={size}");
66                }
67                Event::Error {
68                    req_id: event_req_id,
69                    code,
70                    message,
71                    ..
72                } if event_req_id < 0 && is_market_data_status_code(code) => {
73                    eprintln!("TWS status {code}: {message}");
74                }
75                Event::Error {
76                    req_id: event_req_id,
77                    code,
78                    message,
79                    ..
80                } if event_req_id == req_id && is_delayed_market_data_notice(code) => {
81                    eprintln!("TWS notice {code}: {message}");
82                }
83                Event::Error {
84                    req_id: event_req_id,
85                    code,
86                    message,
87                    ..
88                } if event_req_id == req_id => {
89                    eprintln!("TWS error {code}: {message}");
90                    break false;
91                }
92                Event::Error { code, message, .. } => {
93                    eprintln!("TWS notice {code}: {message}");
94                }
95                _ => {}
96            }
97        };
98        truefix_twsapi_client::error::TwsApiResult::Ok(should_cancel)
99    })
100    .await;
101
102    let should_cancel = match &result {
103        Ok(Ok(should_cancel)) => *should_cancel,
104        Ok(Err(_)) | Err(_) => true,
105    };
106    if should_cancel && let Err(error) = client.cancel_mkt_data(req_id).await {
107        eprintln!("cancelMktData failed: {error}");
108    }
109    if should_cancel {
110        tokio::time::sleep(Duration::from_millis(250)).await;
111    }
112
113    match result {
114        Ok(result) => result.map(|_| ()),
115        Err(_) => {
116            eprintln!("timed out waiting for market data");
117            Ok(())
118        }
119    }
120}
Source

pub async fn req_smart_components( &mut self, req_id: i32, bbo_exchange: &str, ) -> TwsApiResult<()>

Sends reqSmartComponents.

Examples found in repository?
examples/twsapi/main.rs (line 1531)
1528async fn run_smart_components(client: &mut TwsApiClient) -> Result<(), CliError> {
1529    let req_id = req_id(9402)?;
1530    client
1531        .req_smart_components(req_id, &env_string("TWS_BBO_EXCHANGE", "a6"))
1532        .await?;
1533    read_until(client, 10, |event| match event {
1534        Event::SmartComponents {
1535            req_id: event_req_id,
1536            ..
1537        } if event_req_id == req_id => {
1538            print_event(&event);
1539            true
1540        }
1541        Event::Error { .. } => {
1542            print_event(&event);
1543            false
1544        }
1545        other => {
1546            print_event(&other);
1547            false
1548        }
1549    })
1550    .await?;
1551    Ok(())
1552}
Source

pub async fn req_market_rule(&mut self, market_rule_id: i32) -> TwsApiResult<()>

Sends reqMarketRule.

Examples found in repository?
examples/twsapi/main.rs (line 1556)
1554async fn run_market_rule(client: &mut TwsApiClient) -> Result<(), CliError> {
1555    let market_rule_id = env_parse("TWS_MARKET_RULE_ID", 26i32)?;
1556    client.req_market_rule(market_rule_id).await?;
1557    read_until(client, 10, |event| match event {
1558        Event::MarketRule {
1559            market_rule_id: event_market_rule_id,
1560            ..
1561        } if event_market_rule_id == market_rule_id => {
1562            print_event(&event);
1563            true
1564        }
1565        Event::Error { .. } => {
1566            print_event(&event);
1567            false
1568        }
1569        other => {
1570            print_event(&other);
1571            false
1572        }
1573    })
1574    .await?;
1575    Ok(())
1576}
Source

pub async fn req_mkt_depth( &mut self, request: MarketDepthRequest, ) -> TwsApiResult<()>

Sends reqMktDepth.

Examples found in repository?
examples/twsapi/main.rs (lines 985-991)
982async fn run_market_depth(client: &mut TwsApiClient) -> Result<(), CliError> {
983    let req_id = req_id(9002)?;
984    client
985        .req_mkt_depth(MarketDepthRequest {
986            req_id,
987            contract: contract_from_env()?,
988            num_rows: env_parse("TWS_DEPTH_ROWS", 5i32)?,
989            is_smart_depth: env_bool("TWS_SMART_DEPTH", false)?,
990            market_depth_options: env_tag_values("TWS_DEPTH_OPTION"),
991        })
992        .await?;
993    read_until(
994        client,
995        env_parse("TWS_WAIT_SECS", 20u64)?,
996        |event| match event {
997            Event::MarketDepth {
998                req_id: event_req_id,
999                ..
1000            } if event_req_id == req_id => {
1001                print_event(&event);
1002                false
1003            }
1004            Event::Error {
1005                req_id: event_req_id,
1006                ..
1007            } if event_req_id == req_id => {
1008                print_event(&event);
1009                true
1010            }
1011            Event::Error { .. } => {
1012                print_event(&event);
1013                false
1014            }
1015            other => {
1016                print_event(&other);
1017                false
1018            }
1019        },
1020    )
1021    .await?;
1022    let _ = client
1023        .cancel_mkt_depth(req_id, env_bool("TWS_SMART_DEPTH", false)?)
1024        .await;
1025    Ok(())
1026}
Source

pub async fn cancel_mkt_depth( &mut self, req_id: i32, is_smart_depth: bool, ) -> TwsApiResult<()>

Sends cancelMktDepth.

Examples found in repository?
examples/twsapi/main.rs (line 1023)
982async fn run_market_depth(client: &mut TwsApiClient) -> Result<(), CliError> {
983    let req_id = req_id(9002)?;
984    client
985        .req_mkt_depth(MarketDepthRequest {
986            req_id,
987            contract: contract_from_env()?,
988            num_rows: env_parse("TWS_DEPTH_ROWS", 5i32)?,
989            is_smart_depth: env_bool("TWS_SMART_DEPTH", false)?,
990            market_depth_options: env_tag_values("TWS_DEPTH_OPTION"),
991        })
992        .await?;
993    read_until(
994        client,
995        env_parse("TWS_WAIT_SECS", 20u64)?,
996        |event| match event {
997            Event::MarketDepth {
998                req_id: event_req_id,
999                ..
1000            } if event_req_id == req_id => {
1001                print_event(&event);
1002                false
1003            }
1004            Event::Error {
1005                req_id: event_req_id,
1006                ..
1007            } if event_req_id == req_id => {
1008                print_event(&event);
1009                true
1010            }
1011            Event::Error { .. } => {
1012                print_event(&event);
1013                false
1014            }
1015            other => {
1016                print_event(&other);
1017                false
1018            }
1019        },
1020    )
1021    .await?;
1022    let _ = client
1023        .cancel_mkt_depth(req_id, env_bool("TWS_SMART_DEPTH", false)?)
1024        .await;
1025    Ok(())
1026}
Source

pub async fn place_order( &mut self, request: PlaceOrderRequest, ) -> TwsApiResult<()>

Sends placeOrder.

Examples found in repository?
examples/twsapi/main.rs (line 1037)
1028async fn run_place_order(client: &mut TwsApiClient) -> Result<(), CliError> {
1029    let mut order = order_from_env()?;
1030    order_kind_from_env(&mut order)?;
1031    let request = PlaceOrderRequest {
1032        order_id: order.order_id,
1033        contract: contract_from_env()?,
1034        order,
1035        extra_fields: env_string("TWS_ORDER_EXTRA_FIELDS", ""),
1036    };
1037    client.place_order(request).await?;
1038    read_until(
1039        client,
1040        env_parse("TWS_WAIT_SECS", 15u64)?,
1041        |event| match event {
1042            Event::OpenOrder { .. } | Event::OrderStatus { .. } | Event::Error { .. } => {
1043                print_event(&event);
1044                false
1045            }
1046            other => {
1047                print_event(&other);
1048                false
1049            }
1050        },
1051    )
1052    .await?;
1053    Ok(())
1054}
Source

pub async fn cancel_order( &mut self, order_id: i32, order_cancel: OrderCancel, ) -> TwsApiResult<()>

Sends cancelOrder.

Examples found in repository?
examples/twsapi/main.rs (lines 1058-1061)
1056async fn run_cancel_order(client: &mut TwsApiClient) -> Result<(), CliError> {
1057    client
1058        .cancel_order(
1059            req_id(5001)?,
1060            truefix_twsapi_client::types::OrderCancel::default(),
1061        )
1062        .await?;
1063    read_until(client, 10, |event| match event {
1064        Event::OrderStatus { .. } | Event::Error { .. } => {
1065            print_event(&event);
1066            false
1067        }
1068        other => {
1069            print_event(&other);
1070            false
1071        }
1072    })
1073    .await?;
1074    Ok(())
1075}
Source

pub async fn req_open_orders(&mut self) -> TwsApiResult<()>

Sends reqOpenOrders.

Examples found in repository?
examples/twsapi/main.rs (line 1078)
1077async fn run_open_orders(client: &mut TwsApiClient) -> Result<(), CliError> {
1078    client.req_open_orders().await?;
1079    read_until(client, 20, |event| match event {
1080        Event::OpenOrder { .. } | Event::OpenOrderEnd => {
1081            print_event(&event);
1082            matches!(event, Event::OpenOrderEnd)
1083        }
1084        Event::Error { .. } => {
1085            print_event(&event);
1086            false
1087        }
1088        other => {
1089            print_event(&other);
1090            false
1091        }
1092    })
1093    .await?;
1094    Ok(())
1095}
Source

pub async fn req_auto_open_orders( &mut self, auto_bind: bool, ) -> TwsApiResult<()>

Sends reqAutoOpenOrders.

Examples found in repository?
examples/twsapi/main.rs (line 1099)
1097async fn run_auto_open_orders(client: &mut TwsApiClient) -> Result<(), CliError> {
1098    let auto_bind = env_bool("TWS_AUTO_BIND", true)?;
1099    client.req_auto_open_orders(auto_bind).await?;
1100    println!("auto_open_orders auto_bind={auto_bind}");
1101    Ok(())
1102}
Source

pub async fn req_all_open_orders(&mut self) -> TwsApiResult<()>

Sends reqAllOpenOrders.

Examples found in repository?
examples/twsapi/main.rs (line 1105)
1104async fn run_all_open_orders(client: &mut TwsApiClient) -> Result<(), CliError> {
1105    client.req_all_open_orders().await?;
1106    read_until(client, 20, |event| match event {
1107        Event::OpenOrder { .. } | Event::OpenOrderEnd => {
1108            print_event(&event);
1109            matches!(event, Event::OpenOrderEnd)
1110        }
1111        Event::Error { .. } => {
1112            print_event(&event);
1113            false
1114        }
1115        other => {
1116            print_event(&other);
1117            false
1118        }
1119    })
1120    .await?;
1121    Ok(())
1122}
Source

pub async fn req_global_cancel( &mut self, order_cancel: OrderCancel, ) -> TwsApiResult<()>

Sends reqGlobalCancel.

Examples found in repository?
examples/twsapi/main.rs (line 1126)
1124async fn run_global_cancel(client: &mut TwsApiClient) -> Result<(), CliError> {
1125    client
1126        .req_global_cancel(truefix_twsapi_client::types::OrderCancel::default())
1127        .await?;
1128    println!("global_cancel sent");
1129    Ok(())
1130}
Source

pub async fn req_account_updates( &mut self, subscribe: bool, account_code: &str, ) -> TwsApiResult<()>

Sends reqAccountUpdates.

Examples found in repository?
examples/twsapi/main.rs (lines 2390-2393)
2388async fn run_account_updates(client: &mut TwsApiClient) -> Result<(), CliError> {
2389    client
2390        .req_account_updates(
2391            env_bool("TWS_ACCOUNT_SUBSCRIBE", true)?,
2392            &env_string("TWS_ACCOUNT", ""),
2393        )
2394        .await?;
2395    read_until(client, 10, |event| match event {
2396        Event::AccountValue { .. }
2397        | Event::PortfolioValue { .. }
2398        | Event::AccountUpdateTime { .. }
2399        | Event::AccountDownloadEnd { .. }
2400        | Event::Error { .. } => {
2401            print_event(&event);
2402            false
2403        }
2404        other => {
2405            print_event(&other);
2406            false
2407        }
2408    })
2409    .await?;
2410    let _ = client
2411        .req_account_updates(false, &env_string("TWS_ACCOUNT", ""))
2412        .await;
2413    Ok(())
2414}
Source

pub async fn req_account_summary( &mut self, req_id: i32, group_name: &str, tags: &str, ) -> TwsApiResult<()>

Sends reqAccountSummary.

Examples found in repository?
examples/twsapi/main.rs (lines 1157-1164)
1154async fn run_account_summary(client: &mut TwsApiClient) -> Result<(), CliError> {
1155    let req_id = req_id(9101)?;
1156    client
1157        .req_account_summary(
1158            req_id,
1159            &env_string("TWS_SUMMARY_GROUP", "All"),
1160            &env_string(
1161                "TWS_SUMMARY_TAGS",
1162                "NetLiquidation,TotalCashValue,BuyingPower,AvailableFunds",
1163            ),
1164        )
1165        .await?;
1166    read_until(client, 20, |event| match event {
1167        Event::AccountSummary {
1168            req_id: event_req_id,
1169            ..
1170        } if event_req_id == req_id => {
1171            print_event(&event);
1172            false
1173        }
1174        Event::AccountSummaryEnd {
1175            req_id: event_req_id,
1176        } if event_req_id == req_id => {
1177            print_event(&event);
1178            true
1179        }
1180        Event::Error { .. } => {
1181            print_event(&event);
1182            false
1183        }
1184        other => {
1185            print_event(&other);
1186            false
1187        }
1188    })
1189    .await?;
1190    let _ = client.cancel_account_summary(req_id).await;
1191    Ok(())
1192}
Source

pub async fn cancel_account_summary(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelAccountSummary.

Examples found in repository?
examples/twsapi/main.rs (line 1190)
1154async fn run_account_summary(client: &mut TwsApiClient) -> Result<(), CliError> {
1155    let req_id = req_id(9101)?;
1156    client
1157        .req_account_summary(
1158            req_id,
1159            &env_string("TWS_SUMMARY_GROUP", "All"),
1160            &env_string(
1161                "TWS_SUMMARY_TAGS",
1162                "NetLiquidation,TotalCashValue,BuyingPower,AvailableFunds",
1163            ),
1164        )
1165        .await?;
1166    read_until(client, 20, |event| match event {
1167        Event::AccountSummary {
1168            req_id: event_req_id,
1169            ..
1170        } if event_req_id == req_id => {
1171            print_event(&event);
1172            false
1173        }
1174        Event::AccountSummaryEnd {
1175            req_id: event_req_id,
1176        } if event_req_id == req_id => {
1177            print_event(&event);
1178            true
1179        }
1180        Event::Error { .. } => {
1181            print_event(&event);
1182            false
1183        }
1184        other => {
1185            print_event(&other);
1186            false
1187        }
1188    })
1189    .await?;
1190    let _ = client.cancel_account_summary(req_id).await;
1191    Ok(())
1192}
Source

pub async fn cancel_positions(&mut self) -> TwsApiResult<()>

Sends cancelPositions.

Examples found in repository?
examples/twsapi/main.rs (line 1211)
1194async fn run_positions(client: &mut TwsApiClient) -> Result<(), CliError> {
1195    client.req_positions().await?;
1196    read_until(client, 20, |event| match event {
1197        Event::Position { .. } | Event::PositionEnd => {
1198            print_event(&event);
1199            matches!(event, Event::PositionEnd)
1200        }
1201        Event::Error { .. } => {
1202            print_event(&event);
1203            false
1204        }
1205        other => {
1206            print_event(&other);
1207            false
1208        }
1209    })
1210    .await?;
1211    let _ = client.cancel_positions().await;
1212    Ok(())
1213}
Source

pub async fn req_positions_multi( &mut self, req_id: i32, account: &str, model_code: &str, ) -> TwsApiResult<()>

Sends reqPositionsMulti.

Examples found in repository?
examples/twsapi/main.rs (lines 1218-1222)
1215async fn run_positions_multi(client: &mut TwsApiClient) -> Result<(), CliError> {
1216    let req_id = req_id(9102)?;
1217    client
1218        .req_positions_multi(
1219            req_id,
1220            &env_string("TWS_ACCOUNT", ""),
1221            &env_string("TWS_MODEL_CODE", ""),
1222        )
1223        .await?;
1224    read_until(client, 20, |event| match event {
1225        Event::PositionMulti {
1226            req_id: event_req_id,
1227            ..
1228        } if event_req_id == req_id => {
1229            print_event(&event);
1230            false
1231        }
1232        Event::PositionMultiEnd {
1233            req_id: event_req_id,
1234        } if event_req_id == req_id => {
1235            print_event(&event);
1236            true
1237        }
1238        Event::Error { .. } => {
1239            print_event(&event);
1240            false
1241        }
1242        other => {
1243            print_event(&other);
1244            false
1245        }
1246    })
1247    .await?;
1248    let _ = client.cancel_positions_multi(req_id).await;
1249    Ok(())
1250}
Source

pub async fn cancel_positions_multi(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelPositionsMulti.

Examples found in repository?
examples/twsapi/main.rs (line 1248)
1215async fn run_positions_multi(client: &mut TwsApiClient) -> Result<(), CliError> {
1216    let req_id = req_id(9102)?;
1217    client
1218        .req_positions_multi(
1219            req_id,
1220            &env_string("TWS_ACCOUNT", ""),
1221            &env_string("TWS_MODEL_CODE", ""),
1222        )
1223        .await?;
1224    read_until(client, 20, |event| match event {
1225        Event::PositionMulti {
1226            req_id: event_req_id,
1227            ..
1228        } if event_req_id == req_id => {
1229            print_event(&event);
1230            false
1231        }
1232        Event::PositionMultiEnd {
1233            req_id: event_req_id,
1234        } if event_req_id == req_id => {
1235            print_event(&event);
1236            true
1237        }
1238        Event::Error { .. } => {
1239            print_event(&event);
1240            false
1241        }
1242        other => {
1243            print_event(&other);
1244            false
1245        }
1246    })
1247    .await?;
1248    let _ = client.cancel_positions_multi(req_id).await;
1249    Ok(())
1250}
Source

pub async fn req_account_updates_multi( &mut self, req_id: i32, account: &str, model_code: &str, ledger_and_nlv: bool, ) -> TwsApiResult<()>

Sends reqAccountUpdatesMulti.

Examples found in repository?
examples/twsapi/main.rs (lines 1255-1260)
1252async fn run_account_updates_multi(client: &mut TwsApiClient) -> Result<(), CliError> {
1253    let req_id = req_id(9103)?;
1254    client
1255        .req_account_updates_multi(
1256            req_id,
1257            &env_string("TWS_ACCOUNT", ""),
1258            &env_string("TWS_MODEL_CODE", ""),
1259            env_bool("TWS_LEDGER_AND_NLV", false)?,
1260        )
1261        .await?;
1262    let done = read_until(client, 20, |event| match event {
1263        Event::AccountUpdateMulti {
1264            req_id: event_req_id,
1265            ..
1266        } if event_req_id == req_id => {
1267            print_event(&event);
1268            false
1269        }
1270        Event::AccountUpdateMultiEnd {
1271            req_id: event_req_id,
1272        } if event_req_id == req_id => {
1273            print_event(&event);
1274            true
1275        }
1276        Event::Error { .. } => {
1277            print_event(&event);
1278            false
1279        }
1280        other => {
1281            print_event(&other);
1282            false
1283        }
1284    })
1285    .await?;
1286    if !done {
1287        let _ = client.cancel_account_updates_multi(req_id).await;
1288    }
1289    Ok(())
1290}
Source

pub async fn cancel_account_updates_multi( &mut self, req_id: i32, ) -> TwsApiResult<()>

Sends cancelAccountUpdatesMulti.

Examples found in repository?
examples/twsapi/main.rs (line 1287)
1252async fn run_account_updates_multi(client: &mut TwsApiClient) -> Result<(), CliError> {
1253    let req_id = req_id(9103)?;
1254    client
1255        .req_account_updates_multi(
1256            req_id,
1257            &env_string("TWS_ACCOUNT", ""),
1258            &env_string("TWS_MODEL_CODE", ""),
1259            env_bool("TWS_LEDGER_AND_NLV", false)?,
1260        )
1261        .await?;
1262    let done = read_until(client, 20, |event| match event {
1263        Event::AccountUpdateMulti {
1264            req_id: event_req_id,
1265            ..
1266        } if event_req_id == req_id => {
1267            print_event(&event);
1268            false
1269        }
1270        Event::AccountUpdateMultiEnd {
1271            req_id: event_req_id,
1272        } if event_req_id == req_id => {
1273            print_event(&event);
1274            true
1275        }
1276        Event::Error { .. } => {
1277            print_event(&event);
1278            false
1279        }
1280        other => {
1281            print_event(&other);
1282            false
1283        }
1284    })
1285    .await?;
1286    if !done {
1287        let _ = client.cancel_account_updates_multi(req_id).await;
1288    }
1289    Ok(())
1290}
Source

pub async fn req_pnl( &mut self, req_id: i32, account: &str, model_code: &str, ) -> TwsApiResult<()>

Sends reqPnL.

Examples found in repository?
examples/twsapi/main.rs (lines 2306-2310)
2303async fn run_pnl(client: &mut TwsApiClient) -> Result<(), CliError> {
2304    let req_id = req_id(9901)?;
2305    client
2306        .req_pnl(
2307            req_id,
2308            &env_string("TWS_ACCOUNT", ""),
2309            &env_string("TWS_MODEL_CODE", ""),
2310        )
2311        .await?;
2312    read_until(client, 10, |event| match event {
2313        Event::Pnl {
2314            req_id: event_req_id,
2315            ..
2316        } if event_req_id == req_id => {
2317            print_event(&event);
2318            false
2319        }
2320        Event::Error { .. } => {
2321            print_event(&event);
2322            false
2323        }
2324        other => {
2325            print_event(&other);
2326            false
2327        }
2328    })
2329    .await?;
2330    let _ = client.cancel_pnl(req_id).await;
2331    Ok(())
2332}
Source

pub async fn cancel_pnl(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelPnL.

Examples found in repository?
examples/twsapi/main.rs (line 2330)
2303async fn run_pnl(client: &mut TwsApiClient) -> Result<(), CliError> {
2304    let req_id = req_id(9901)?;
2305    client
2306        .req_pnl(
2307            req_id,
2308            &env_string("TWS_ACCOUNT", ""),
2309            &env_string("TWS_MODEL_CODE", ""),
2310        )
2311        .await?;
2312    read_until(client, 10, |event| match event {
2313        Event::Pnl {
2314            req_id: event_req_id,
2315            ..
2316        } if event_req_id == req_id => {
2317            print_event(&event);
2318            false
2319        }
2320        Event::Error { .. } => {
2321            print_event(&event);
2322            false
2323        }
2324        other => {
2325            print_event(&other);
2326            false
2327        }
2328    })
2329    .await?;
2330    let _ = client.cancel_pnl(req_id).await;
2331    Ok(())
2332}
Source

pub async fn req_pnl_single( &mut self, req_id: i32, account: &str, model_code: &str, con_id: i32, ) -> TwsApiResult<()>

Sends reqPnLSingle.

Examples found in repository?
examples/twsapi/main.rs (lines 2337-2342)
2334async fn run_pnl_single(client: &mut TwsApiClient) -> Result<(), CliError> {
2335    let req_id = req_id(9902)?;
2336    client
2337        .req_pnl_single(
2338            req_id,
2339            &env_string("TWS_ACCOUNT", ""),
2340            &env_string("TWS_MODEL_CODE", ""),
2341            env_parse("TWS_CONID", 0i32)?,
2342        )
2343        .await?;
2344    read_until(client, 10, |event| match event {
2345        Event::PnlSingle {
2346            req_id: event_req_id,
2347            ..
2348        } if event_req_id == req_id => {
2349            print_event(&event);
2350            false
2351        }
2352        Event::Error { .. } => {
2353            print_event(&event);
2354            false
2355        }
2356        other => {
2357            print_event(&other);
2358            false
2359        }
2360    })
2361    .await?;
2362    let _ = client.cancel_pnl_single(req_id).await;
2363    Ok(())
2364}
Source

pub async fn cancel_pnl_single(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelPnLSingle.

Examples found in repository?
examples/twsapi/main.rs (line 2362)
2334async fn run_pnl_single(client: &mut TwsApiClient) -> Result<(), CliError> {
2335    let req_id = req_id(9902)?;
2336    client
2337        .req_pnl_single(
2338            req_id,
2339            &env_string("TWS_ACCOUNT", ""),
2340            &env_string("TWS_MODEL_CODE", ""),
2341            env_parse("TWS_CONID", 0i32)?,
2342        )
2343        .await?;
2344    read_until(client, 10, |event| match event {
2345        Event::PnlSingle {
2346            req_id: event_req_id,
2347            ..
2348        } if event_req_id == req_id => {
2349            print_event(&event);
2350            false
2351        }
2352        Event::Error { .. } => {
2353            print_event(&event);
2354            false
2355        }
2356        other => {
2357            print_event(&other);
2358            false
2359        }
2360    })
2361    .await?;
2362    let _ = client.cancel_pnl_single(req_id).await;
2363    Ok(())
2364}
Source

pub async fn req_executions( &mut self, request: ExecutionRequest, ) -> TwsApiResult<()>

Sends reqExecutions.

Examples found in repository?
examples/twsapi/main.rs (lines 1680-1692)
1677async fn run_executions(client: &mut TwsApiClient) -> Result<(), CliError> {
1678    let req_id = req_id(9501)?;
1679    client
1680        .req_executions(ExecutionRequest {
1681            req_id,
1682            filter: ExecutionFilter {
1683                client_id: env_parse("TWS_FILTER_CLIENT_ID", 0i32)?,
1684                acct_code: env_string("TWS_ACCOUNT", ""),
1685                time: env_string("TWS_EXEC_TIME", ""),
1686                symbol: env_string("TWS_SYMBOL", ""),
1687                sec_type: env_string("TWS_SEC_TYPE", ""),
1688                exchange: env_string("TWS_EXCHANGE", ""),
1689                side: env_string("TWS_EXEC_SIDE", ""),
1690                ..ExecutionFilter::default()
1691            },
1692        })
1693        .await?;
1694    read_until(client, 20, |event| match event {
1695        Event::ExecutionDetails {
1696            req_id: event_req_id,
1697            ..
1698        }
1699        | Event::ExecutionDetailsEnd {
1700            req_id: event_req_id,
1701        } if event_req_id == req_id => {
1702            print_event(&event);
1703            matches!(event, Event::ExecutionDetailsEnd { .. })
1704        }
1705        Event::Error { .. } => {
1706            print_event(&event);
1707            false
1708        }
1709        other => {
1710            print_event(&other);
1711            false
1712        }
1713    })
1714    .await?;
1715    Ok(())
1716}
Source

pub async fn req_contract_details( &mut self, request: ContractDetailsRequest, ) -> TwsApiResult<()>

Sends reqContractDetails.

Examples found in repository?
examples/twsapi/main.rs (lines 1466-1469)
1463async fn run_contract_details(client: &mut TwsApiClient) -> Result<(), CliError> {
1464    let req_id = req_id(9401)?;
1465    client
1466        .req_contract_details(ContractDetailsRequest {
1467            req_id,
1468            contract: contract_from_env()?,
1469        })
1470        .await?;
1471    read_until(client, 20, |event| match event {
1472        Event::ContractDetails {
1473            req_id: event_req_id,
1474            ..
1475        }
1476        | Event::ContractDetailsEnd {
1477            req_id: event_req_id,
1478        } if event_req_id == req_id => {
1479            print_event(&event);
1480            matches!(event, Event::ContractDetailsEnd { .. })
1481        }
1482        Event::Error { .. } => {
1483            print_event(&event);
1484            false
1485        }
1486        other => {
1487            print_event(&other);
1488            false
1489        }
1490    })
1491    .await?;
1492    let _ = client.cancel_contract_data(req_id).await;
1493    Ok(())
1494}
1495
1496async fn run_bond_contract_details(client: &mut TwsApiClient) -> Result<(), CliError> {
1497    let req_id = req_id(9401)?;
1498    let mut contract = contract_from_env()?;
1499    contract.sec_type = "BOND".to_owned();
1500    client
1501        .req_contract_details(ContractDetailsRequest { req_id, contract })
1502        .await?;
1503    read_until(client, 20, |event| match event {
1504        Event::BondContractDetails {
1505            req_id: event_req_id,
1506            ..
1507        }
1508        | Event::ContractDetailsEnd {
1509            req_id: event_req_id,
1510        } if event_req_id == req_id => {
1511            print_event(&event);
1512            matches!(event, Event::ContractDetailsEnd { .. })
1513        }
1514        Event::Error { .. } => {
1515            print_event(&event);
1516            false
1517        }
1518        other => {
1519            print_event(&other);
1520            false
1521        }
1522    })
1523    .await?;
1524    let _ = client.cancel_contract_data(req_id).await;
1525    Ok(())
1526}
Source

pub async fn cancel_contract_data(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelContractData.

Examples found in repository?
examples/twsapi/main.rs (line 1492)
1463async fn run_contract_details(client: &mut TwsApiClient) -> Result<(), CliError> {
1464    let req_id = req_id(9401)?;
1465    client
1466        .req_contract_details(ContractDetailsRequest {
1467            req_id,
1468            contract: contract_from_env()?,
1469        })
1470        .await?;
1471    read_until(client, 20, |event| match event {
1472        Event::ContractDetails {
1473            req_id: event_req_id,
1474            ..
1475        }
1476        | Event::ContractDetailsEnd {
1477            req_id: event_req_id,
1478        } if event_req_id == req_id => {
1479            print_event(&event);
1480            matches!(event, Event::ContractDetailsEnd { .. })
1481        }
1482        Event::Error { .. } => {
1483            print_event(&event);
1484            false
1485        }
1486        other => {
1487            print_event(&other);
1488            false
1489        }
1490    })
1491    .await?;
1492    let _ = client.cancel_contract_data(req_id).await;
1493    Ok(())
1494}
1495
1496async fn run_bond_contract_details(client: &mut TwsApiClient) -> Result<(), CliError> {
1497    let req_id = req_id(9401)?;
1498    let mut contract = contract_from_env()?;
1499    contract.sec_type = "BOND".to_owned();
1500    client
1501        .req_contract_details(ContractDetailsRequest { req_id, contract })
1502        .await?;
1503    read_until(client, 20, |event| match event {
1504        Event::BondContractDetails {
1505            req_id: event_req_id,
1506            ..
1507        }
1508        | Event::ContractDetailsEnd {
1509            req_id: event_req_id,
1510        } if event_req_id == req_id => {
1511            print_event(&event);
1512            matches!(event, Event::ContractDetailsEnd { .. })
1513        }
1514        Event::Error { .. } => {
1515            print_event(&event);
1516            false
1517        }
1518        other => {
1519            print_event(&other);
1520            false
1521        }
1522    })
1523    .await?;
1524    let _ = client.cancel_contract_data(req_id).await;
1525    Ok(())
1526}
Source

pub async fn req_mkt_depth_exchanges(&mut self) -> TwsApiResult<()>

Sends reqMktDepthExchanges.

Examples found in repository?
examples/twsapi/main.rs (line 2417)
2416async fn run_market_depth_exchanges(client: &mut TwsApiClient) -> Result<(), CliError> {
2417    client.req_mkt_depth_exchanges().await?;
2418    read_until(client, 5, |event| match event {
2419        Event::MarketDepthExchanges { .. } | Event::Error { .. } => {
2420            print_event(&event);
2421            false
2422        }
2423        other => {
2424            print_event(&other);
2425            false
2426        }
2427    })
2428    .await?;
2429    Ok(())
2430}
Source

pub async fn req_news_bulletins( &mut self, all_messages: bool, ) -> TwsApiResult<()>

Sends reqNewsBulletins.

Examples found in repository?
examples/twsapi/main.rs (line 1720)
1718async fn run_news_bulletins(client: &mut TwsApiClient) -> Result<(), CliError> {
1719    let all_messages = env_bool("TWS_NEWS_ALL_MESSAGES", true)?;
1720    client.req_news_bulletins(all_messages).await?;
1721    let done = read_until(client, 15, |event| match event {
1722        Event::NewsBulletin { .. } => {
1723            print_event(&event);
1724            false
1725        }
1726        Event::Error { .. } => {
1727            print_event(&event);
1728            false
1729        }
1730        other => {
1731            print_event(&other);
1732            false
1733        }
1734    })
1735    .await?;
1736    if !done {
1737        let _ = client.cancel_news_bulletins().await;
1738    }
1739    Ok(())
1740}
Source

pub async fn cancel_news_bulletins(&mut self) -> TwsApiResult<()>

Sends cancelNewsBulletins.

Examples found in repository?
examples/twsapi/main.rs (line 1737)
1718async fn run_news_bulletins(client: &mut TwsApiClient) -> Result<(), CliError> {
1719    let all_messages = env_bool("TWS_NEWS_ALL_MESSAGES", true)?;
1720    client.req_news_bulletins(all_messages).await?;
1721    let done = read_until(client, 15, |event| match event {
1722        Event::NewsBulletin { .. } => {
1723            print_event(&event);
1724            false
1725        }
1726        Event::Error { .. } => {
1727            print_event(&event);
1728            false
1729        }
1730        other => {
1731            print_event(&other);
1732            false
1733        }
1734    })
1735    .await?;
1736    if !done {
1737        let _ = client.cancel_news_bulletins().await;
1738    }
1739    Ok(())
1740}
Source

pub async fn req_managed_accounts(&mut self) -> TwsApiResult<()>

Sends reqManagedAccts.

Examples found in repository?
examples/twsapi/main.rs (line 2367)
2366async fn run_managed_accounts(client: &mut TwsApiClient) -> Result<(), CliError> {
2367    client.req_managed_accounts().await?;
2368    read_until(client, 5, |event| match event {
2369        Event::ManagedAccounts { .. } | Event::Error { .. } => {
2370            print_event(&event);
2371            false
2372        }
2373        other => {
2374            print_event(&other);
2375            false
2376        }
2377    })
2378    .await?;
2379    Ok(())
2380}
Source

pub async fn request_fa(&mut self, fa_data_type: i32) -> TwsApiResult<()>

Sends requestFA.

Examples found in repository?
examples/twsapi/main.rs (line 2088)
2086async fn run_request_fa(client: &mut TwsApiClient) -> Result<(), CliError> {
2087    let fa_data_type = env_parse("TWS_FA_DATA_TYPE", 1i32)?;
2088    client.request_fa(fa_data_type).await?;
2089    read_until(client, 10, |event| match event {
2090        Event::ReceiveFa {
2091            fa_data_type: event_type,
2092            ..
2093        } if event_type == fa_data_type => {
2094            print_event(&event);
2095            true
2096        }
2097        Event::Error { .. } => {
2098            print_event(&event);
2099            false
2100        }
2101        other => {
2102            print_event(&other);
2103            false
2104        }
2105    })
2106    .await?;
2107    Ok(())
2108}
Source

pub async fn replace_fa( &mut self, req_id: i32, fa_data_type: i32, xml: &str, ) -> TwsApiResult<()>

Sends replaceFA.

Examples found in repository?
examples/twsapi/main.rs (line 2114)
2110async fn run_replace_fa(client: &mut TwsApiClient) -> Result<(), CliError> {
2111    let req_id = req_id(9808)?;
2112    let fa_data_type = env_parse("TWS_FA_DATA_TYPE", 1i32)?;
2113    client
2114        .replace_fa(req_id, fa_data_type, &env_string("TWS_FA_XML", ""))
2115        .await?;
2116    read_until(client, 10, |event| match event {
2117        Event::ReplaceFaEnd {
2118            req_id: event_req_id,
2119            ..
2120        } if event_req_id == req_id => {
2121            print_event(&event);
2122            true
2123        }
2124        Event::Error { .. } => {
2125            print_event(&event);
2126            false
2127        }
2128        other => {
2129            print_event(&other);
2130            false
2131        }
2132    })
2133    .await?;
2134    Ok(())
2135}
Source

pub async fn req_historical_data( &mut self, request: HistoricalDataRequest, ) -> TwsApiResult<()>

Sends reqHistoricalData.

Examples found in repository?
examples/twsapi/main.rs (lines 1295-1306)
1292async fn run_historical_data(client: &mut TwsApiClient) -> Result<(), CliError> {
1293    let req_id = req_id(9201)?;
1294    client
1295        .req_historical_data(HistoricalDataRequest {
1296            req_id,
1297            contract: contract_from_env()?,
1298            end_date_time: env_string("TWS_END_DATE_TIME", ""),
1299            duration_str: env_string("TWS_DURATION_STR", "1 D"),
1300            bar_size_setting: env_string("TWS_BAR_SIZE_SETTING", "1 day"),
1301            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1302            use_rth: env_parse("TWS_USE_RTH", 1i32)?,
1303            format_date: env_parse("TWS_FORMAT_DATE", 1i32)?,
1304            keep_up_to_date: env_bool("TWS_KEEP_UP_TO_DATE", false)?,
1305            chart_options: env_tag_values("TWS_HIST_OPTION"),
1306        })
1307        .await?;
1308    let done = read_until(
1309        client,
1310        env_parse("TWS_WAIT_SECS", 30u64)?,
1311        |event| match event {
1312            Event::HistoricalData {
1313                req_id: event_req_id,
1314                ..
1315            }
1316            | Event::HistoricalDataUpdate {
1317                req_id: event_req_id,
1318                ..
1319            }
1320            | Event::HistoricalDataEnd {
1321                req_id: event_req_id,
1322                ..
1323            } if event_req_id == req_id => {
1324                print_event(&event);
1325                matches!(event, Event::HistoricalDataEnd { .. })
1326            }
1327            Event::Error { .. } => {
1328                print_event(&event);
1329                false
1330            }
1331            other => {
1332                print_event(&other);
1333                false
1334            }
1335        },
1336    )
1337    .await?;
1338    if !done {
1339        let _ = client.cancel_historical_data(req_id).await;
1340    }
1341    Ok(())
1342}
Source

pub async fn cancel_historical_data(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelHistoricalData.

Examples found in repository?
examples/twsapi/main.rs (line 1339)
1292async fn run_historical_data(client: &mut TwsApiClient) -> Result<(), CliError> {
1293    let req_id = req_id(9201)?;
1294    client
1295        .req_historical_data(HistoricalDataRequest {
1296            req_id,
1297            contract: contract_from_env()?,
1298            end_date_time: env_string("TWS_END_DATE_TIME", ""),
1299            duration_str: env_string("TWS_DURATION_STR", "1 D"),
1300            bar_size_setting: env_string("TWS_BAR_SIZE_SETTING", "1 day"),
1301            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1302            use_rth: env_parse("TWS_USE_RTH", 1i32)?,
1303            format_date: env_parse("TWS_FORMAT_DATE", 1i32)?,
1304            keep_up_to_date: env_bool("TWS_KEEP_UP_TO_DATE", false)?,
1305            chart_options: env_tag_values("TWS_HIST_OPTION"),
1306        })
1307        .await?;
1308    let done = read_until(
1309        client,
1310        env_parse("TWS_WAIT_SECS", 30u64)?,
1311        |event| match event {
1312            Event::HistoricalData {
1313                req_id: event_req_id,
1314                ..
1315            }
1316            | Event::HistoricalDataUpdate {
1317                req_id: event_req_id,
1318                ..
1319            }
1320            | Event::HistoricalDataEnd {
1321                req_id: event_req_id,
1322                ..
1323            } if event_req_id == req_id => {
1324                print_event(&event);
1325                matches!(event, Event::HistoricalDataEnd { .. })
1326            }
1327            Event::Error { .. } => {
1328                print_event(&event);
1329                false
1330            }
1331            other => {
1332                print_event(&other);
1333                false
1334            }
1335        },
1336    )
1337    .await?;
1338    if !done {
1339        let _ = client.cancel_historical_data(req_id).await;
1340    }
1341    Ok(())
1342}
Source

pub async fn req_scanner_parameters(&mut self) -> TwsApiResult<()>

Sends reqScannerParameters.

Examples found in repository?
examples/twsapi/main.rs (line 1878)
1877async fn run_scanner_parameters(client: &mut TwsApiClient) -> Result<(), CliError> {
1878    client.req_scanner_parameters().await?;
1879    read_until(client, 10, |event| match event {
1880        Event::ScannerParameters { .. } | Event::Error { .. } => {
1881            print_event(&event);
1882            false
1883        }
1884        other => {
1885            print_event(&other);
1886            false
1887        }
1888    })
1889    .await?;
1890    Ok(())
1891}
Source

pub async fn req_scanner_subscription( &mut self, request: ScannerSubscriptionRequest, ) -> TwsApiResult<()>

Sends reqScannerSubscription.

Examples found in repository?
examples/twsapi/main.rs (lines 1817-1844)
1814async fn run_scanner(client: &mut TwsApiClient) -> Result<(), CliError> {
1815    let req_id = req_id(9601)?;
1816    client
1817        .req_scanner_subscription(ScannerSubscriptionRequest {
1818            req_id,
1819            subscription: ScannerSubscription {
1820                number_of_rows: env_parse("TWS_SCAN_ROWS", 10i32)?,
1821                instrument: env_string("TWS_SCAN_INSTRUMENT", "STK"),
1822                location_code: env_string("TWS_SCAN_LOCATION", "STK.US.MAJOR"),
1823                scan_code: env_string("TWS_SCAN_CODE", "TOP_PERC_GAIN"),
1824                above_price: env_parse("TWS_SCAN_ABOVE_PRICE", 0.0f64)?,
1825                below_price: env_parse("TWS_SCAN_BELOW_PRICE", 0.0f64)?,
1826                above_volume: env_parse("TWS_SCAN_ABOVE_VOLUME", 0i32)?,
1827                market_cap_above: env_parse("TWS_SCAN_MARKET_CAP_ABOVE", 0.0f64)?,
1828                market_cap_below: env_parse("TWS_SCAN_MARKET_CAP_BELOW", 0.0f64)?,
1829                moody_rating_above: env_string("TWS_SCAN_MOODY_ABOVE", ""),
1830                moody_rating_below: env_string("TWS_SCAN_MOODY_BELOW", ""),
1831                sp_rating_above: env_string("TWS_SCAN_SP_ABOVE", ""),
1832                sp_rating_below: env_string("TWS_SCAN_SP_BELOW", ""),
1833                maturity_date_above: env_string("TWS_SCAN_MATURITY_ABOVE", ""),
1834                maturity_date_below: env_string("TWS_SCAN_MATURITY_BELOW", ""),
1835                coupon_rate_above: env_parse("TWS_SCAN_COUPON_ABOVE", 0.0f64)?,
1836                coupon_rate_below: env_parse("TWS_SCAN_COUPON_BELOW", 0.0f64)?,
1837                exclude_convertible: env_bool("TWS_SCAN_EXCLUDE_CONVERTIBLE", false)?,
1838                average_option_volume_above: env_parse("TWS_SCAN_AVG_OPTION_VOLUME_ABOVE", 0i32)?,
1839                scanner_setting_pairs: env_string("TWS_SCAN_SETTING_PAIRS", ""),
1840                stock_type_filter: env_string("TWS_SCAN_STOCK_TYPE_FILTER", ""),
1841            },
1842            scanner_subscription_options: env_tag_values("TWS_SCAN_OPTION"),
1843            scanner_subscription_filter_options: env_tag_values("TWS_SCAN_FILTER"),
1844        })
1845        .await?;
1846    let done = read_until(
1847        client,
1848        env_parse("TWS_WAIT_SECS", 20u64)?,
1849        |event| match event {
1850            Event::ScannerData {
1851                req_id: event_req_id,
1852                ..
1853            }
1854            | Event::ScannerDataEnd {
1855                req_id: event_req_id,
1856            } if event_req_id == req_id => {
1857                print_event(&event);
1858                matches!(event, Event::ScannerDataEnd { .. })
1859            }
1860            Event::Error { .. } => {
1861                print_event(&event);
1862                false
1863            }
1864            other => {
1865                print_event(&other);
1866                false
1867            }
1868        },
1869    )
1870    .await?;
1871    if !done {
1872        let _ = client.cancel_scanner_subscription(req_id).await;
1873    }
1874    Ok(())
1875}
Source

pub async fn cancel_scanner_subscription( &mut self, req_id: i32, ) -> TwsApiResult<()>

Sends cancelScannerSubscription.

Examples found in repository?
examples/twsapi/main.rs (line 1872)
1814async fn run_scanner(client: &mut TwsApiClient) -> Result<(), CliError> {
1815    let req_id = req_id(9601)?;
1816    client
1817        .req_scanner_subscription(ScannerSubscriptionRequest {
1818            req_id,
1819            subscription: ScannerSubscription {
1820                number_of_rows: env_parse("TWS_SCAN_ROWS", 10i32)?,
1821                instrument: env_string("TWS_SCAN_INSTRUMENT", "STK"),
1822                location_code: env_string("TWS_SCAN_LOCATION", "STK.US.MAJOR"),
1823                scan_code: env_string("TWS_SCAN_CODE", "TOP_PERC_GAIN"),
1824                above_price: env_parse("TWS_SCAN_ABOVE_PRICE", 0.0f64)?,
1825                below_price: env_parse("TWS_SCAN_BELOW_PRICE", 0.0f64)?,
1826                above_volume: env_parse("TWS_SCAN_ABOVE_VOLUME", 0i32)?,
1827                market_cap_above: env_parse("TWS_SCAN_MARKET_CAP_ABOVE", 0.0f64)?,
1828                market_cap_below: env_parse("TWS_SCAN_MARKET_CAP_BELOW", 0.0f64)?,
1829                moody_rating_above: env_string("TWS_SCAN_MOODY_ABOVE", ""),
1830                moody_rating_below: env_string("TWS_SCAN_MOODY_BELOW", ""),
1831                sp_rating_above: env_string("TWS_SCAN_SP_ABOVE", ""),
1832                sp_rating_below: env_string("TWS_SCAN_SP_BELOW", ""),
1833                maturity_date_above: env_string("TWS_SCAN_MATURITY_ABOVE", ""),
1834                maturity_date_below: env_string("TWS_SCAN_MATURITY_BELOW", ""),
1835                coupon_rate_above: env_parse("TWS_SCAN_COUPON_ABOVE", 0.0f64)?,
1836                coupon_rate_below: env_parse("TWS_SCAN_COUPON_BELOW", 0.0f64)?,
1837                exclude_convertible: env_bool("TWS_SCAN_EXCLUDE_CONVERTIBLE", false)?,
1838                average_option_volume_above: env_parse("TWS_SCAN_AVG_OPTION_VOLUME_ABOVE", 0i32)?,
1839                scanner_setting_pairs: env_string("TWS_SCAN_SETTING_PAIRS", ""),
1840                stock_type_filter: env_string("TWS_SCAN_STOCK_TYPE_FILTER", ""),
1841            },
1842            scanner_subscription_options: env_tag_values("TWS_SCAN_OPTION"),
1843            scanner_subscription_filter_options: env_tag_values("TWS_SCAN_FILTER"),
1844        })
1845        .await?;
1846    let done = read_until(
1847        client,
1848        env_parse("TWS_WAIT_SECS", 20u64)?,
1849        |event| match event {
1850            Event::ScannerData {
1851                req_id: event_req_id,
1852                ..
1853            }
1854            | Event::ScannerDataEnd {
1855                req_id: event_req_id,
1856            } if event_req_id == req_id => {
1857                print_event(&event);
1858                matches!(event, Event::ScannerDataEnd { .. })
1859            }
1860            Event::Error { .. } => {
1861                print_event(&event);
1862                false
1863            }
1864            other => {
1865                print_event(&other);
1866                false
1867            }
1868        },
1869    )
1870    .await?;
1871    if !done {
1872        let _ = client.cancel_scanner_subscription(req_id).await;
1873    }
1874    Ok(())
1875}
Source

pub async fn id_request_with_options( &mut self, message: Outgoing, req_id: i32, options: &[TagValue], ) -> TwsApiResult<()>

Sends a request id plus optional tag values.

Source

pub async fn req_tick_by_tick_data( &mut self, request: TickByTickRequest, ) -> TwsApiResult<()>

Sends reqTickByTickData.

Examples found in repository?
examples/twsapi/main.rs (lines 2267-2273)
2264async fn run_tick_by_tick(client: &mut TwsApiClient) -> Result<(), CliError> {
2265    let req_id = req_id(9801)?;
2266    client
2267        .req_tick_by_tick_data(TickByTickRequest {
2268            req_id,
2269            contract: contract_from_env()?,
2270            tick_type: env_string("TWS_TICK_TYPE", "Last"),
2271            number_of_ticks: env_parse("TWS_NUMBER_OF_TICKS", 0i32)?,
2272            ignore_size: env_bool("TWS_IGNORE_SIZE", false)?,
2273        })
2274        .await?;
2275    let done = read_until(
2276        client,
2277        env_parse("TWS_WAIT_SECS", 20u64)?,
2278        |event| match event {
2279            Event::TickByTick {
2280                req_id: event_req_id,
2281                ..
2282            } if event_req_id == req_id => {
2283                print_event(&event);
2284                false
2285            }
2286            Event::Error { .. } => {
2287                print_event(&event);
2288                false
2289            }
2290            other => {
2291                print_event(&other);
2292                false
2293            }
2294        },
2295    )
2296    .await?;
2297    if !done {
2298        let _ = client.cancel_tick_by_tick_data(req_id).await;
2299    }
2300    Ok(())
2301}
Source

pub async fn cancel_tick_by_tick_data( &mut self, req_id: i32, ) -> TwsApiResult<()>

Sends cancelTickByTickData.

Examples found in repository?
examples/twsapi/main.rs (line 2298)
2264async fn run_tick_by_tick(client: &mut TwsApiClient) -> Result<(), CliError> {
2265    let req_id = req_id(9801)?;
2266    client
2267        .req_tick_by_tick_data(TickByTickRequest {
2268            req_id,
2269            contract: contract_from_env()?,
2270            tick_type: env_string("TWS_TICK_TYPE", "Last"),
2271            number_of_ticks: env_parse("TWS_NUMBER_OF_TICKS", 0i32)?,
2272            ignore_size: env_bool("TWS_IGNORE_SIZE", false)?,
2273        })
2274        .await?;
2275    let done = read_until(
2276        client,
2277        env_parse("TWS_WAIT_SECS", 20u64)?,
2278        |event| match event {
2279            Event::TickByTick {
2280                req_id: event_req_id,
2281                ..
2282            } if event_req_id == req_id => {
2283                print_event(&event);
2284                false
2285            }
2286            Event::Error { .. } => {
2287                print_event(&event);
2288                false
2289            }
2290            other => {
2291                print_event(&other);
2292                false
2293            }
2294        },
2295    )
2296    .await?;
2297    if !done {
2298        let _ = client.cancel_tick_by_tick_data(req_id).await;
2299    }
2300    Ok(())
2301}
Source

pub async fn calculate_implied_volatility( &mut self, request: CalculateImpliedVolatilityRequest, ) -> TwsApiResult<()>

Sends calculateImpliedVolatility.

Examples found in repository?
examples/twsapi/main.rs (lines 1581-1587)
1578async fn run_calculate_implied_volatility(client: &mut TwsApiClient) -> Result<(), CliError> {
1579    let req_id = req_id(9502)?;
1580    client
1581        .calculate_implied_volatility(CalculateImpliedVolatilityRequest {
1582            req_id,
1583            contract: contract_from_env()?,
1584            option_price: env_parse("TWS_OPTION_PRICE", 1.0f64)?,
1585            under_price: env_parse("TWS_UNDER_PRICE", 1.0f64)?,
1586            options: env_tag_values("TWS_IV_OPTION"),
1587        })
1588        .await?;
1589    let done = read_until(client, 10, |event| match event {
1590        Event::TickOptionComputation {
1591            req_id: event_req_id,
1592            ..
1593        } if event_req_id == req_id => {
1594            print_event(&event);
1595            true
1596        }
1597        Event::Error { .. } => {
1598            print_event(&event);
1599            false
1600        }
1601        other => {
1602            print_event(&other);
1603            false
1604        }
1605    })
1606    .await?;
1607    if !done {
1608        let _ = client.cancel_calculate_implied_volatility(req_id).await;
1609    }
1610    Ok(())
1611}
Source

pub async fn cancel_calculate_implied_volatility( &mut self, req_id: i32, ) -> TwsApiResult<()>

Sends cancelCalculateImpliedVolatility.

Examples found in repository?
examples/twsapi/main.rs (line 1608)
1578async fn run_calculate_implied_volatility(client: &mut TwsApiClient) -> Result<(), CliError> {
1579    let req_id = req_id(9502)?;
1580    client
1581        .calculate_implied_volatility(CalculateImpliedVolatilityRequest {
1582            req_id,
1583            contract: contract_from_env()?,
1584            option_price: env_parse("TWS_OPTION_PRICE", 1.0f64)?,
1585            under_price: env_parse("TWS_UNDER_PRICE", 1.0f64)?,
1586            options: env_tag_values("TWS_IV_OPTION"),
1587        })
1588        .await?;
1589    let done = read_until(client, 10, |event| match event {
1590        Event::TickOptionComputation {
1591            req_id: event_req_id,
1592            ..
1593        } if event_req_id == req_id => {
1594            print_event(&event);
1595            true
1596        }
1597        Event::Error { .. } => {
1598            print_event(&event);
1599            false
1600        }
1601        other => {
1602            print_event(&other);
1603            false
1604        }
1605    })
1606    .await?;
1607    if !done {
1608        let _ = client.cancel_calculate_implied_volatility(req_id).await;
1609    }
1610    Ok(())
1611}
Source

pub async fn calculate_option_price( &mut self, request: CalculateOptionPriceRequest, ) -> TwsApiResult<()>

Sends calculateOptionPrice.

Examples found in repository?
examples/twsapi/main.rs (lines 1616-1622)
1613async fn run_calculate_option_price(client: &mut TwsApiClient) -> Result<(), CliError> {
1614    let req_id = req_id(9503)?;
1615    client
1616        .calculate_option_price(CalculateOptionPriceRequest {
1617            req_id,
1618            contract: contract_from_env()?,
1619            volatility: env_parse("TWS_VOLATILITY", 0.2f64)?,
1620            under_price: env_parse("TWS_UNDER_PRICE", 1.0f64)?,
1621            options: env_tag_values("TWS_OPT_PRICE_OPTION"),
1622        })
1623        .await?;
1624    let done = read_until(client, 10, |event| match event {
1625        Event::TickOptionComputation {
1626            req_id: event_req_id,
1627            ..
1628        } if event_req_id == req_id => {
1629            print_event(&event);
1630            true
1631        }
1632        Event::Error { .. } => {
1633            print_event(&event);
1634            false
1635        }
1636        other => {
1637            print_event(&other);
1638            false
1639        }
1640    })
1641    .await?;
1642    if !done {
1643        let _ = client.cancel_calculate_option_price(req_id).await;
1644    }
1645    Ok(())
1646}
Source

pub async fn cancel_calculate_option_price( &mut self, req_id: i32, ) -> TwsApiResult<()>

Sends cancelCalculateOptionPrice.

Examples found in repository?
examples/twsapi/main.rs (line 1643)
1613async fn run_calculate_option_price(client: &mut TwsApiClient) -> Result<(), CliError> {
1614    let req_id = req_id(9503)?;
1615    client
1616        .calculate_option_price(CalculateOptionPriceRequest {
1617            req_id,
1618            contract: contract_from_env()?,
1619            volatility: env_parse("TWS_VOLATILITY", 0.2f64)?,
1620            under_price: env_parse("TWS_UNDER_PRICE", 1.0f64)?,
1621            options: env_tag_values("TWS_OPT_PRICE_OPTION"),
1622        })
1623        .await?;
1624    let done = read_until(client, 10, |event| match event {
1625        Event::TickOptionComputation {
1626            req_id: event_req_id,
1627            ..
1628        } if event_req_id == req_id => {
1629            print_event(&event);
1630            true
1631        }
1632        Event::Error { .. } => {
1633            print_event(&event);
1634            false
1635        }
1636        other => {
1637            print_event(&other);
1638            false
1639        }
1640    })
1641    .await?;
1642    if !done {
1643        let _ = client.cancel_calculate_option_price(req_id).await;
1644    }
1645    Ok(())
1646}
Source

pub async fn exercise_options( &mut self, request: ExerciseOptionsRequest, ) -> TwsApiResult<()>

Sends exerciseOptions.

Examples found in repository?
examples/twsapi/main.rs (lines 1651-1661)
1648async fn run_exercise_options(client: &mut TwsApiClient) -> Result<(), CliError> {
1649    let order_id = req_id(9602)?;
1650    client
1651        .exercise_options(ExerciseOptionsRequest {
1652            order_id,
1653            contract: contract_from_env()?,
1654            exercise_action: env_parse("TWS_EXERCISE_ACTION", 1i32)?,
1655            exercise_quantity: env_parse("TWS_EXERCISE_QTY", 1i32)?,
1656            account: env_string("TWS_ACCOUNT", ""),
1657            override_system_action: env_bool("TWS_EXERCISE_OVERRIDE", false)?,
1658            manual_order_time: env_string("TWS_MANUAL_ORDER_TIME", ""),
1659            customer_account: env_string("TWS_CUSTOMER_ACCOUNT", ""),
1660            professional_customer: env_bool("TWS_PROFESSIONAL_CUSTOMER", false)?,
1661        })
1662        .await?;
1663    read_until(client, 10, |event| match event {
1664        Event::OpenOrder { .. } | Event::OrderStatus { .. } | Event::Error { .. } => {
1665            print_event(&event);
1666            false
1667        }
1668        other => {
1669            print_event(&other);
1670            false
1671        }
1672    })
1673    .await?;
1674    Ok(())
1675}
Source

pub async fn req_head_timestamp( &mut self, request: HeadTimestampRequest, ) -> TwsApiResult<()>

Sends reqHeadTimeStamp.

Examples found in repository?
examples/twsapi/main.rs (lines 1401-1407)
1398async fn run_head_timestamp(client: &mut TwsApiClient) -> Result<(), CliError> {
1399    let req_id = req_id(9301)?;
1400    client
1401        .req_head_timestamp(HeadTimestampRequest {
1402            req_id,
1403            contract: contract_from_env()?,
1404            use_rth: env_bool("TWS_USE_RTH", true)?,
1405            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1406            format_date: env_parse("TWS_FORMAT_DATE", 1i32)?,
1407        })
1408        .await?;
1409    read_until(client, 20, |event| match event {
1410        Event::HeadTimestamp {
1411            req_id: event_req_id,
1412            ..
1413        } if event_req_id == req_id => {
1414            print_event(&event);
1415            true
1416        }
1417        Event::Error { .. } => {
1418            print_event(&event);
1419            false
1420        }
1421        other => {
1422            print_event(&other);
1423            false
1424        }
1425    })
1426    .await?;
1427    let _ = client.cancel_head_timestamp(req_id).await;
1428    Ok(())
1429}
Source

pub async fn cancel_head_timestamp(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelHeadTimeStamp.

Examples found in repository?
examples/twsapi/main.rs (line 1427)
1398async fn run_head_timestamp(client: &mut TwsApiClient) -> Result<(), CliError> {
1399    let req_id = req_id(9301)?;
1400    client
1401        .req_head_timestamp(HeadTimestampRequest {
1402            req_id,
1403            contract: contract_from_env()?,
1404            use_rth: env_bool("TWS_USE_RTH", true)?,
1405            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1406            format_date: env_parse("TWS_FORMAT_DATE", 1i32)?,
1407        })
1408        .await?;
1409    read_until(client, 20, |event| match event {
1410        Event::HeadTimestamp {
1411            req_id: event_req_id,
1412            ..
1413        } if event_req_id == req_id => {
1414            print_event(&event);
1415            true
1416        }
1417        Event::Error { .. } => {
1418            print_event(&event);
1419            false
1420        }
1421        other => {
1422            print_event(&other);
1423            false
1424        }
1425    })
1426    .await?;
1427    let _ = client.cancel_head_timestamp(req_id).await;
1428    Ok(())
1429}
Source

pub async fn req_histogram_data( &mut self, request: HistogramDataRequest, ) -> TwsApiResult<()>

Sends reqHistogramData.

Examples found in repository?
examples/twsapi/main.rs (lines 1434-1439)
1431async fn run_histogram_data(client: &mut TwsApiClient) -> Result<(), CliError> {
1432    let req_id = req_id(9302)?;
1433    client
1434        .req_histogram_data(HistogramDataRequest {
1435            req_id,
1436            contract: contract_from_env()?,
1437            use_rth: env_bool("TWS_USE_RTH", true)?,
1438            time_period: env_string("TWS_TIME_PERIOD", "1 D"),
1439        })
1440        .await?;
1441    read_until(client, 20, |event| match event {
1442        Event::HistogramData {
1443            req_id: event_req_id,
1444            ..
1445        } if event_req_id == req_id => {
1446            print_event(&event);
1447            true
1448        }
1449        Event::Error { .. } => {
1450            print_event(&event);
1451            false
1452        }
1453        other => {
1454            print_event(&other);
1455            false
1456        }
1457    })
1458    .await?;
1459    let _ = client.cancel_histogram_data(req_id).await;
1460    Ok(())
1461}
Source

pub async fn cancel_histogram_data(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelHistogramData.

Examples found in repository?
examples/twsapi/main.rs (line 1459)
1431async fn run_histogram_data(client: &mut TwsApiClient) -> Result<(), CliError> {
1432    let req_id = req_id(9302)?;
1433    client
1434        .req_histogram_data(HistogramDataRequest {
1435            req_id,
1436            contract: contract_from_env()?,
1437            use_rth: env_bool("TWS_USE_RTH", true)?,
1438            time_period: env_string("TWS_TIME_PERIOD", "1 D"),
1439        })
1440        .await?;
1441    read_until(client, 20, |event| match event {
1442        Event::HistogramData {
1443            req_id: event_req_id,
1444            ..
1445        } if event_req_id == req_id => {
1446            print_event(&event);
1447            true
1448        }
1449        Event::Error { .. } => {
1450            print_event(&event);
1451            false
1452        }
1453        other => {
1454            print_event(&other);
1455            false
1456        }
1457    })
1458    .await?;
1459    let _ = client.cancel_histogram_data(req_id).await;
1460    Ok(())
1461}
Source

pub async fn req_historical_ticks( &mut self, request: HistoricalTicksRequest, ) -> TwsApiResult<()>

Sends reqHistoricalTicks.

Examples found in repository?
examples/twsapi/main.rs (lines 1347-1357)
1344async fn run_historical_ticks(client: &mut TwsApiClient) -> Result<(), CliError> {
1345    let req_id = req_id(9202)?;
1346    client
1347        .req_historical_ticks(HistoricalTicksRequest {
1348            req_id,
1349            contract: contract_from_env()?,
1350            start_date_time: env_string("TWS_START_DATE_TIME", ""),
1351            end_date_time: env_string("TWS_END_DATE_TIME", ""),
1352            number_of_ticks: env_parse("TWS_NUMBER_OF_TICKS", 1000i32)?,
1353            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1354            use_rth: env_bool("TWS_USE_RTH", true)?,
1355            ignore_size: env_bool("TWS_IGNORE_SIZE", false)?,
1356            misc_options: env_tag_values("TWS_HIST_TICKS_OPTION"),
1357        })
1358        .await?;
1359    let done = read_until(
1360        client,
1361        env_parse("TWS_WAIT_SECS", 30u64)?,
1362        |event| match event {
1363            Event::HistoricalTicks {
1364                req_id: event_req_id,
1365                done,
1366                ..
1367            }
1368            | Event::HistoricalTicksBidAsk {
1369                req_id: event_req_id,
1370                done,
1371                ..
1372            }
1373            | Event::HistoricalTicksLast {
1374                req_id: event_req_id,
1375                done,
1376                ..
1377            } if event_req_id == req_id => {
1378                print_event(&event);
1379                done
1380            }
1381            Event::Error { .. } => {
1382                print_event(&event);
1383                false
1384            }
1385            other => {
1386                print_event(&other);
1387                false
1388            }
1389        },
1390    )
1391    .await?;
1392    if !done {
1393        let _ = client.cancel_historical_ticks(req_id).await;
1394    }
1395    Ok(())
1396}
Source

pub async fn cancel_historical_ticks(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelHistoricalTicks.

Examples found in repository?
examples/twsapi/main.rs (line 1393)
1344async fn run_historical_ticks(client: &mut TwsApiClient) -> Result<(), CliError> {
1345    let req_id = req_id(9202)?;
1346    client
1347        .req_historical_ticks(HistoricalTicksRequest {
1348            req_id,
1349            contract: contract_from_env()?,
1350            start_date_time: env_string("TWS_START_DATE_TIME", ""),
1351            end_date_time: env_string("TWS_END_DATE_TIME", ""),
1352            number_of_ticks: env_parse("TWS_NUMBER_OF_TICKS", 1000i32)?,
1353            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
1354            use_rth: env_bool("TWS_USE_RTH", true)?,
1355            ignore_size: env_bool("TWS_IGNORE_SIZE", false)?,
1356            misc_options: env_tag_values("TWS_HIST_TICKS_OPTION"),
1357        })
1358        .await?;
1359    let done = read_until(
1360        client,
1361        env_parse("TWS_WAIT_SECS", 30u64)?,
1362        |event| match event {
1363            Event::HistoricalTicks {
1364                req_id: event_req_id,
1365                done,
1366                ..
1367            }
1368            | Event::HistoricalTicksBidAsk {
1369                req_id: event_req_id,
1370                done,
1371                ..
1372            }
1373            | Event::HistoricalTicksLast {
1374                req_id: event_req_id,
1375                done,
1376                ..
1377            } if event_req_id == req_id => {
1378                print_event(&event);
1379                done
1380            }
1381            Event::Error { .. } => {
1382                print_event(&event);
1383                false
1384            }
1385            other => {
1386                print_event(&other);
1387                false
1388            }
1389        },
1390    )
1391    .await?;
1392    if !done {
1393        let _ = client.cancel_historical_ticks(req_id).await;
1394    }
1395    Ok(())
1396}
Source

pub async fn req_real_time_bars( &mut self, request: RealTimeBarsRequest, ) -> TwsApiResult<()>

Sends reqRealTimeBars.

Examples found in repository?
examples/twsapi/main.rs (lines 2227-2234)
2224async fn run_real_time_bars(client: &mut TwsApiClient) -> Result<(), CliError> {
2225    let req_id = req_id(9701)?;
2226    client
2227        .req_real_time_bars(RealTimeBarsRequest {
2228            req_id,
2229            contract: contract_from_env()?,
2230            bar_size: env_parse("TWS_BAR_SIZE", 5i32)?,
2231            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
2232            use_rth: env_bool("TWS_USE_RTH", true)?,
2233            options: env_tag_values("TWS_RTBAR_OPTION"),
2234        })
2235        .await?;
2236    let done = read_until(
2237        client,
2238        env_parse("TWS_WAIT_SECS", 20u64)?,
2239        |event| match event {
2240            Event::RealTimeBar {
2241                req_id: event_req_id,
2242                ..
2243            } if event_req_id == req_id => {
2244                print_event(&event);
2245                false
2246            }
2247            Event::Error { .. } => {
2248                print_event(&event);
2249                false
2250            }
2251            other => {
2252                print_event(&other);
2253                false
2254            }
2255        },
2256    )
2257    .await?;
2258    if !done {
2259        let _ = client.cancel_real_time_bars(req_id).await;
2260    }
2261    Ok(())
2262}
Source

pub async fn cancel_real_time_bars(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelRealTimeBars.

Examples found in repository?
examples/twsapi/main.rs (line 2259)
2224async fn run_real_time_bars(client: &mut TwsApiClient) -> Result<(), CliError> {
2225    let req_id = req_id(9701)?;
2226    client
2227        .req_real_time_bars(RealTimeBarsRequest {
2228            req_id,
2229            contract: contract_from_env()?,
2230            bar_size: env_parse("TWS_BAR_SIZE", 5i32)?,
2231            what_to_show: env_string("TWS_WHAT_TO_SHOW", "TRADES"),
2232            use_rth: env_bool("TWS_USE_RTH", true)?,
2233            options: env_tag_values("TWS_RTBAR_OPTION"),
2234        })
2235        .await?;
2236    let done = read_until(
2237        client,
2238        env_parse("TWS_WAIT_SECS", 20u64)?,
2239        |event| match event {
2240            Event::RealTimeBar {
2241                req_id: event_req_id,
2242                ..
2243            } if event_req_id == req_id => {
2244                print_event(&event);
2245                false
2246            }
2247            Event::Error { .. } => {
2248                print_event(&event);
2249                false
2250            }
2251            other => {
2252                print_event(&other);
2253                false
2254            }
2255        },
2256    )
2257    .await?;
2258    if !done {
2259        let _ = client.cancel_real_time_bars(req_id).await;
2260    }
2261    Ok(())
2262}
Source

pub async fn req_news_providers(&mut self) -> TwsApiResult<()>

Sends reqNewsProviders.

Examples found in repository?
examples/twsapi/main.rs (line 2433)
2432async fn run_news_providers(client: &mut TwsApiClient) -> Result<(), CliError> {
2433    client.req_news_providers().await?;
2434    read_until(client, 5, |event| match event {
2435        Event::NewsProviders { .. } | Event::Error { .. } => {
2436            print_event(&event);
2437            false
2438        }
2439        other => {
2440            print_event(&other);
2441            false
2442        }
2443    })
2444    .await?;
2445    Ok(())
2446}
Source

pub async fn req_news_article( &mut self, req_id: i32, provider_code: &str, article_id: &str, options: &[TagValue], ) -> TwsApiResult<()>

Sends reqNewsArticle.

Examples found in repository?
examples/twsapi/main.rs (lines 1745-1750)
1742async fn run_news_article(client: &mut TwsApiClient) -> Result<(), CliError> {
1743    let req_id = req_id(9702)?;
1744    client
1745        .req_news_article(
1746            req_id,
1747            &env_string("TWS_NEWS_PROVIDER_CODE", "BZ"),
1748            &env_string("TWS_NEWS_ARTICLE_ID", ""),
1749            &env_tag_values("TWS_NEWS_OPTION"),
1750        )
1751        .await?;
1752    read_until(client, 10, |event| match event {
1753        Event::NewsArticle {
1754            req_id: event_req_id,
1755            ..
1756        } if event_req_id == req_id => {
1757            print_event(&event);
1758            true
1759        }
1760        Event::Error { .. } => {
1761            print_event(&event);
1762            false
1763        }
1764        other => {
1765            print_event(&other);
1766            false
1767        }
1768    })
1769    .await?;
1770    Ok(())
1771}
Source

pub async fn req_historical_news( &mut self, request: HistoricalNewsRequest, ) -> TwsApiResult<()>

Sends reqHistoricalNews.

Examples found in repository?
examples/twsapi/main.rs (lines 1776-1784)
1773async fn run_historical_news(client: &mut TwsApiClient) -> Result<(), CliError> {
1774    let req_id = req_id(9703)?;
1775    client
1776        .req_historical_news(HistoricalNewsRequest {
1777            req_id,
1778            con_id: env_parse("TWS_CONID", 0i32)?,
1779            provider_codes: env_string("TWS_NEWS_PROVIDER_CODES", ""),
1780            start_date_time: env_string("TWS_START_DATE_TIME", ""),
1781            end_date_time: env_string("TWS_END_DATE_TIME", ""),
1782            total_results: env_parse("TWS_TOTAL_RESULTS", 10i32)?,
1783            options: env_tag_values("TWS_HNEWS_OPTION"),
1784        })
1785        .await?;
1786    read_until(client, 15, |event| match event {
1787        Event::HistoricalNews {
1788            req_id: event_req_id,
1789            ..
1790        } if event_req_id == req_id => {
1791            print_event(&event);
1792            false
1793        }
1794        Event::HistoricalNewsEnd {
1795            req_id: event_req_id,
1796            ..
1797        } if event_req_id == req_id => {
1798            print_event(&event);
1799            true
1800        }
1801        Event::Error { .. } => {
1802            print_event(&event);
1803            false
1804        }
1805        other => {
1806            print_event(&other);
1807            false
1808        }
1809    })
1810    .await?;
1811    Ok(())
1812}
Source

pub async fn query_display_groups(&mut self, req_id: i32) -> TwsApiResult<()>

Sends queryDisplayGroups.

Examples found in repository?
examples/twsapi/main.rs (line 1996)
1994async fn run_query_display_groups(client: &mut TwsApiClient) -> Result<(), CliError> {
1995    let req_id = req_id(9805)?;
1996    client.query_display_groups(req_id).await?;
1997    read_until(client, 10, |event| match event {
1998        Event::DisplayGroupList {
1999            req_id: event_req_id,
2000            ..
2001        } if event_req_id == req_id => {
2002            print_event(&event);
2003            true
2004        }
2005        Event::Error { .. } => {
2006            print_event(&event);
2007            false
2008        }
2009        other => {
2010            print_event(&other);
2011            false
2012        }
2013    })
2014    .await?;
2015    Ok(())
2016}
Source

pub async fn subscribe_to_group_events( &mut self, req_id: i32, group_id: i32, ) -> TwsApiResult<()>

Sends subscribeToGroupEvents.

Examples found in repository?
examples/twsapi/main.rs (line 2021)
2018async fn run_subscribe_to_group_events(client: &mut TwsApiClient) -> Result<(), CliError> {
2019    let req_id = req_id(9806)?;
2020    let group_id = env_parse("TWS_GROUP_ID", 1i32)?;
2021    client.subscribe_to_group_events(req_id, group_id).await?;
2022    let done = read_until(client, 15, |event| match event {
2023        Event::DisplayGroupList {
2024            req_id: event_req_id,
2025            ..
2026        } if event_req_id == req_id => {
2027            print_event(&event);
2028            false
2029        }
2030        Event::DisplayGroupUpdated {
2031            req_id: event_req_id,
2032            ..
2033        } if event_req_id == req_id => {
2034            print_event(&event);
2035            false
2036        }
2037        Event::Error { .. } => {
2038            print_event(&event);
2039            false
2040        }
2041        other => {
2042            print_event(&other);
2043            false
2044        }
2045    })
2046    .await?;
2047    if !done {
2048        let _ = client.unsubscribe_from_group_events(req_id).await;
2049    }
2050    Ok(())
2051}
Source

pub async fn update_display_group( &mut self, req_id: i32, contract_info: &str, ) -> TwsApiResult<()>

Sends updateDisplayGroup.

Examples found in repository?
examples/twsapi/main.rs (line 2056)
2053async fn run_update_display_group(client: &mut TwsApiClient) -> Result<(), CliError> {
2054    let req_id = req_id(9807)?;
2055    client
2056        .update_display_group(req_id, &env_string("TWS_CONTRACT_INFO", ""))
2057        .await?;
2058    read_until(client, 10, |event| match event {
2059        Event::DisplayGroupUpdated {
2060            req_id: event_req_id,
2061            ..
2062        } if event_req_id == req_id => {
2063            print_event(&event);
2064            true
2065        }
2066        Event::Error { .. } => {
2067            print_event(&event);
2068            false
2069        }
2070        other => {
2071            print_event(&other);
2072            false
2073        }
2074    })
2075    .await?;
2076    Ok(())
2077}
Source

pub async fn unsubscribe_from_group_events( &mut self, req_id: i32, ) -> TwsApiResult<()>

Sends unsubscribeFromGroupEvents.

Examples found in repository?
examples/twsapi/main.rs (line 2048)
2018async fn run_subscribe_to_group_events(client: &mut TwsApiClient) -> Result<(), CliError> {
2019    let req_id = req_id(9806)?;
2020    let group_id = env_parse("TWS_GROUP_ID", 1i32)?;
2021    client.subscribe_to_group_events(req_id, group_id).await?;
2022    let done = read_until(client, 15, |event| match event {
2023        Event::DisplayGroupList {
2024            req_id: event_req_id,
2025            ..
2026        } if event_req_id == req_id => {
2027            print_event(&event);
2028            false
2029        }
2030        Event::DisplayGroupUpdated {
2031            req_id: event_req_id,
2032            ..
2033        } if event_req_id == req_id => {
2034            print_event(&event);
2035            false
2036        }
2037        Event::Error { .. } => {
2038            print_event(&event);
2039            false
2040        }
2041        other => {
2042            print_event(&other);
2043            false
2044        }
2045    })
2046    .await?;
2047    if !done {
2048        let _ = client.unsubscribe_from_group_events(req_id).await;
2049    }
2050    Ok(())
2051}
2052
2053async fn run_update_display_group(client: &mut TwsApiClient) -> Result<(), CliError> {
2054    let req_id = req_id(9807)?;
2055    client
2056        .update_display_group(req_id, &env_string("TWS_CONTRACT_INFO", ""))
2057        .await?;
2058    read_until(client, 10, |event| match event {
2059        Event::DisplayGroupUpdated {
2060            req_id: event_req_id,
2061            ..
2062        } if event_req_id == req_id => {
2063            print_event(&event);
2064            true
2065        }
2066        Event::Error { .. } => {
2067            print_event(&event);
2068            false
2069        }
2070        other => {
2071            print_event(&other);
2072            false
2073        }
2074    })
2075    .await?;
2076    Ok(())
2077}
2078
2079async fn run_unsubscribe_from_group_events(client: &mut TwsApiClient) -> Result<(), CliError> {
2080    let req_id = req_id(9806)?;
2081    client.unsubscribe_from_group_events(req_id).await?;
2082    println!("unsubscribe_from_group_events req_id={req_id}");
2083    Ok(())
2084}
Source

pub async fn verify_request( &mut self, api_name: &str, api_version: &str, ) -> TwsApiResult<()>

Sends verifyRequest.

Source

pub async fn verify_message(&mut self, api_data: &str) -> TwsApiResult<()>

Sends verifyMessage.

Source

pub async fn verify_and_auth_request( &mut self, api_name: &str, api_version: &str, opaque_isv_key: &str, ) -> TwsApiResult<()>

Sends verifyAndAuthRequest.

Source

pub async fn verify_and_auth_message( &mut self, api_data: &str, xyz_response: &str, ) -> TwsApiResult<()>

Sends verifyAndAuthMessage.

Source

pub async fn req_sec_def_opt_params( &mut self, req_id: i32, underlying_symbol: &str, fut_fop_exchange: &str, underlying_sec_type: &str, underlying_con_id: i32, ) -> TwsApiResult<()>

Sends reqSecDefOptParams.

Examples found in repository?
examples/twsapi/main.rs (lines 1896-1902)
1893async fn run_sec_def_opt_params(client: &mut TwsApiClient) -> Result<(), CliError> {
1894    let req_id = req_id(9802)?;
1895    client
1896        .req_sec_def_opt_params(
1897            req_id,
1898            &env_string("TWS_UNDERLYING_SYMBOL", &env_string("TWS_SYMBOL", "AAPL")),
1899            &env_string("TWS_FUT_FOP_EXCHANGE", "SMART"),
1900            &env_string("TWS_UNDERLYING_SEC_TYPE", "STK"),
1901            env_parse("TWS_UNDERLYING_CON_ID", env_parse("TWS_CONID", 0i32)?)?,
1902        )
1903        .await?;
1904    read_until(client, 20, |event| match event {
1905        Event::SecurityDefinitionOptionParameter {
1906            req_id: event_req_id,
1907            ..
1908        }
1909        | Event::SecurityDefinitionOptionParameterEnd {
1910            req_id: event_req_id,
1911        } if event_req_id == req_id => {
1912            print_event(&event);
1913            matches!(event, Event::SecurityDefinitionOptionParameterEnd { .. })
1914        }
1915        Event::Error { .. } => {
1916            print_event(&event);
1917            false
1918        }
1919        other => {
1920            print_event(&other);
1921            false
1922        }
1923    })
1924    .await?;
1925    Ok(())
1926}
Source

pub async fn req_soft_dollar_tiers(&mut self, req_id: i32) -> TwsApiResult<()>

Sends reqSoftDollarTiers.

Examples found in repository?
examples/twsapi/main.rs (line 1930)
1928async fn run_soft_dollar_tiers(client: &mut TwsApiClient) -> Result<(), CliError> {
1929    let req_id = req_id(9803)?;
1930    client.req_soft_dollar_tiers(req_id).await?;
1931    read_until(client, 10, |event| match event {
1932        Event::SoftDollarTiers {
1933            req_id: event_req_id,
1934            ..
1935        } if event_req_id == req_id => {
1936            print_event(&event);
1937            true
1938        }
1939        Event::Error { .. } => {
1940            print_event(&event);
1941            false
1942        }
1943        other => {
1944            print_event(&other);
1945            false
1946        }
1947    })
1948    .await?;
1949    Ok(())
1950}
Source

pub async fn req_family_codes(&mut self) -> TwsApiResult<()>

Sends reqFamilyCodes.

Examples found in repository?
examples/twsapi/main.rs (line 1953)
1952async fn run_family_codes(client: &mut TwsApiClient) -> Result<(), CliError> {
1953    client.req_family_codes().await?;
1954    read_until(client, 10, |event| match event {
1955        Event::FamilyCodes { .. } | Event::Error { .. } => {
1956            print_event(&event);
1957            true
1958        }
1959        other => {
1960            print_event(&other);
1961            false
1962        }
1963    })
1964    .await?;
1965    Ok(())
1966}
Source

pub async fn req_matching_symbols( &mut self, req_id: i32, pattern: &str, ) -> TwsApiResult<()>

Sends reqMatchingSymbols.

Examples found in repository?
examples/twsapi/main.rs (line 1971)
1968async fn run_matching_symbols(client: &mut TwsApiClient) -> Result<(), CliError> {
1969    let req_id = req_id(9804)?;
1970    client
1971        .req_matching_symbols(req_id, &env_string("TWS_MATCH_PATTERN", "AAPL"))
1972        .await?;
1973    read_until(client, 10, |event| match event {
1974        Event::SymbolSamples {
1975            req_id: event_req_id,
1976            ..
1977        } if event_req_id == req_id => {
1978            print_event(&event);
1979            true
1980        }
1981        Event::Error { .. } => {
1982            print_event(&event);
1983            false
1984        }
1985        other => {
1986            print_event(&other);
1987            false
1988        }
1989    })
1990    .await?;
1991    Ok(())
1992}
Source

pub async fn req_completed_orders(&mut self, api_only: bool) -> TwsApiResult<()>

Sends reqCompletedOrders.

Examples found in repository?
examples/twsapi/main.rs (line 1134)
1132async fn run_completed_orders(client: &mut TwsApiClient) -> Result<(), CliError> {
1133    client
1134        .req_completed_orders(env_bool("TWS_COMPLETED_API_ONLY", false)?)
1135        .await?;
1136    read_until(client, 20, |event| match event {
1137        Event::CompletedOrder { .. } | Event::CompletedOrdersEnd => {
1138            print_event(&event);
1139            matches!(event, Event::CompletedOrdersEnd)
1140        }
1141        Event::Error { .. } => {
1142            print_event(&event);
1143            false
1144        }
1145        other => {
1146            print_event(&other);
1147            false
1148        }
1149    })
1150    .await?;
1151    Ok(())
1152}
Source

pub async fn req_wsh_meta_data(&mut self, req_id: i32) -> TwsApiResult<()>

Sends reqWshMetaData.

Examples found in repository?
examples/twsapi/main.rs (line 2139)
2137async fn run_wsh_meta_data(client: &mut TwsApiClient) -> Result<(), CliError> {
2138    let req_id = req_id(9809)?;
2139    client.req_wsh_meta_data(req_id).await?;
2140    read_until(client, 10, |event| match event {
2141        Event::WshMetaData {
2142            req_id: event_req_id,
2143            ..
2144        } if event_req_id == req_id => {
2145            print_event(&event);
2146            true
2147        }
2148        Event::Error { .. } => {
2149            print_event(&event);
2150            false
2151        }
2152        other => {
2153            print_event(&other);
2154            false
2155        }
2156    })
2157    .await?;
2158    let _ = client.cancel_wsh_meta_data(req_id).await;
2159    Ok(())
2160}
Source

pub async fn cancel_wsh_meta_data(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelWshMetaData.

Examples found in repository?
examples/twsapi/main.rs (line 2158)
2137async fn run_wsh_meta_data(client: &mut TwsApiClient) -> Result<(), CliError> {
2138    let req_id = req_id(9809)?;
2139    client.req_wsh_meta_data(req_id).await?;
2140    read_until(client, 10, |event| match event {
2141        Event::WshMetaData {
2142            req_id: event_req_id,
2143            ..
2144        } if event_req_id == req_id => {
2145            print_event(&event);
2146            true
2147        }
2148        Event::Error { .. } => {
2149            print_event(&event);
2150            false
2151        }
2152        other => {
2153            print_event(&other);
2154            false
2155        }
2156    })
2157    .await?;
2158    let _ = client.cancel_wsh_meta_data(req_id).await;
2159    Ok(())
2160}
Source

pub async fn req_wsh_event_data( &mut self, request: WshEventDataRequest, ) -> TwsApiResult<()>

Sends reqWshEventData.

Examples found in repository?
examples/twsapi/main.rs (lines 2165-2175)
2162async fn run_wsh_event_data(client: &mut TwsApiClient) -> Result<(), CliError> {
2163    let req_id = req_id(9810)?;
2164    client
2165        .req_wsh_event_data(WshEventDataRequest {
2166            req_id,
2167            con_id: env_parse("TWS_CONID", 0i32)?,
2168            filter: env_string("TWS_WSH_FILTER", ""),
2169            fill_watchlist: env_bool("TWS_WSH_FILL_WATCHLIST", false)?,
2170            fill_portfolio: env_bool("TWS_WSH_FILL_PORTFOLIO", false)?,
2171            fill_competitors: env_bool("TWS_WSH_FILL_COMPETITORS", false)?,
2172            start_date: env_string("TWS_START_DATE", ""),
2173            end_date: env_string("TWS_END_DATE", ""),
2174            total_limit: env_parse("TWS_TOTAL_LIMIT", 100i32)?,
2175        })
2176        .await?;
2177    let done = read_until(client, 10, |event| match event {
2178        Event::WshEventData {
2179            req_id: event_req_id,
2180            ..
2181        } if event_req_id == req_id => {
2182            print_event(&event);
2183            false
2184        }
2185        Event::Error { .. } => {
2186            print_event(&event);
2187            false
2188        }
2189        other => {
2190            print_event(&other);
2191            false
2192        }
2193    })
2194    .await?;
2195    if !done {
2196        let _ = client.cancel_wsh_event_data(req_id).await;
2197    }
2198    Ok(())
2199}
Source

pub async fn cancel_wsh_event_data(&mut self, req_id: i32) -> TwsApiResult<()>

Sends cancelWshEventData.

Examples found in repository?
examples/twsapi/main.rs (line 2196)
2162async fn run_wsh_event_data(client: &mut TwsApiClient) -> Result<(), CliError> {
2163    let req_id = req_id(9810)?;
2164    client
2165        .req_wsh_event_data(WshEventDataRequest {
2166            req_id,
2167            con_id: env_parse("TWS_CONID", 0i32)?,
2168            filter: env_string("TWS_WSH_FILTER", ""),
2169            fill_watchlist: env_bool("TWS_WSH_FILL_WATCHLIST", false)?,
2170            fill_portfolio: env_bool("TWS_WSH_FILL_PORTFOLIO", false)?,
2171            fill_competitors: env_bool("TWS_WSH_FILL_COMPETITORS", false)?,
2172            start_date: env_string("TWS_START_DATE", ""),
2173            end_date: env_string("TWS_END_DATE", ""),
2174            total_limit: env_parse("TWS_TOTAL_LIMIT", 100i32)?,
2175        })
2176        .await?;
2177    let done = read_until(client, 10, |event| match event {
2178        Event::WshEventData {
2179            req_id: event_req_id,
2180            ..
2181        } if event_req_id == req_id => {
2182            print_event(&event);
2183            false
2184        }
2185        Event::Error { .. } => {
2186            print_event(&event);
2187            false
2188        }
2189        other => {
2190            print_event(&other);
2191            false
2192        }
2193    })
2194    .await?;
2195    if !done {
2196        let _ = client.cancel_wsh_event_data(req_id).await;
2197    }
2198    Ok(())
2199}
Source

pub async fn req_user_info(&mut self, req_id: i32) -> TwsApiResult<()>

Sends reqUserInfo.

Examples found in repository?
examples/twsapi/main.rs (line 2203)
2201async fn run_user_info(client: &mut TwsApiClient) -> Result<(), CliError> {
2202    let req_id = req_id(9811)?;
2203    client.req_user_info(req_id).await?;
2204    read_until(client, 10, |event| match event {
2205        Event::UserInfo {
2206            req_id: event_req_id,
2207            ..
2208        } if event_req_id == req_id => {
2209            print_event(&event);
2210            true
2211        }
2212        Event::Error { .. } => {
2213            print_event(&event);
2214            false
2215        }
2216        other => {
2217            print_event(&other);
2218            false
2219        }
2220    })
2221    .await?;
2222    Ok(())
2223}
Source

pub async fn req_current_time_in_millis(&mut self) -> TwsApiResult<()>

Sends reqCurrentTimeInMillis.

Examples found in repository?
examples/twsapi/main.rs (line 863)
862async fn run_current_time_millis(client: &mut TwsApiClient) -> Result<(), CliError> {
863    client.req_current_time_in_millis().await?;
864    read_until(client, 5, |event| match event {
865        Event::CurrentTimeInMillis { .. } => {
866            print_event(&event);
867            true
868        }
869        Event::Error { .. } => {
870            print_event(&event);
871            false
872        }
873        other => {
874            print_event(&other);
875            false
876        }
877    })
878    .await?;
879    Ok(())
880}
Source

pub async fn req_config_protobuf( &mut self, protobuf_data: &[u8], ) -> TwsApiResult<()>

Sends reqConfig protobuf payload.

Source

pub async fn update_config_protobuf( &mut self, protobuf_data: &[u8], ) -> TwsApiResult<()>

Sends updateConfig protobuf payload.

Source

pub async fn send_protobuf( &mut self, msg: Outgoing, protobuf_data: &[u8], ) -> TwsApiResult<()>

Sends an already-serialized protobuf payload with the protobuf-adjusted outgoing id.

Source

pub fn use_protobuf(&self, message: Outgoing) -> bool

Returns whether this server version supports protobuf for message.

Source

pub async fn send_protobuf_request( &mut self, message: Outgoing, protobuf_data: &[u8], ) -> TwsApiResult<()>

Sends protobuf for message only when the negotiated server version supports it.

Source

pub async fn read_payload(&mut self) -> TwsApiResult<Vec<u8>>

Reads one raw payload frame from the socket.

Source

pub async fn read_event(&mut self) -> TwsApiResult<Event>

Reads and decodes one incoming event.

Examples found in repository?
examples/twsapi/main.rs (line 523)
520async fn wait_until_api_ready(client: &mut TwsApiClient) -> Result<(), CliError> {
521    let result = tokio::time::timeout(Duration::from_secs(10), async {
522        while !client.api_ready() {
523            match client.read_event().await? {
524                Event::Error { code, message, .. } => {
525                    eprintln!("TWS notice {code}: {message}");
526                }
527                other => {
528                    print_event(&other);
529                }
530            }
531        }
532        truefix_twsapi_client::error::TwsApiResult::Ok(())
533    })
534    .await;
535
536    match result {
537        Ok(Ok(())) => Ok(()),
538        Ok(Err(err)) => Err(err.into()),
539        Err(_) => Err(CliError::Usage(
540            "timed out waiting for initial API callbacks".to_owned(),
541        )),
542    }
543}
544
545async fn read_until<F>(
546    client: &mut TwsApiClient,
547    timeout_secs: u64,
548    mut on_event: F,
549) -> Result<bool, CliError>
550where
551    F: FnMut(Event) -> bool,
552{
553    let result = tokio::time::timeout(Duration::from_secs(timeout_secs), async {
554        loop {
555            let event = client.read_event().await?;
556            if on_event(event) {
557                return truefix_twsapi_client::error::TwsApiResult::Ok(true);
558            }
559        }
560    })
561    .await;
562    match result {
563        Ok(Ok(done)) => Ok(done),
564        Ok(Err(err)) => Err(err.into()),
565        Err(_) => Ok(false),
566    }
567}
More examples
Hide additional examples
examples/request_current_time.rs (line 20)
5async fn main() -> truefix_twsapi_client::error::TwsApiResult<()> {
6    let host = std::env::var("TWS_HOST").unwrap_or_else(|_| "127.0.0.1".to_owned());
7    let port = std::env::var("TWS_PORT")
8        .ok()
9        .and_then(|value| value.parse::<u16>().ok())
10        .unwrap_or(7497);
11    let client_id = std::env::var("TWS_CLIENT_ID")
12        .ok()
13        .and_then(|value| value.parse::<i32>().ok())
14        .unwrap_or(1001);
15
16    let mut client = TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?;
17    client.req_current_time().await?;
18
19    loop {
20        match client.read_event().await? {
21            Event::CurrentTime { time } => {
22                println!("{time}");
23                break;
24            }
25            Event::Error { code, message, .. } => {
26                eprintln!("TWS error {code}: {message}");
27                break;
28            }
29            _ => {}
30        }
31    }
32
33    Ok(())
34}
examples/request_market_data.rs (line 50)
9async fn main() -> truefix_twsapi_client::error::TwsApiResult<()> {
10    let host = std::env::var("TWS_HOST").unwrap_or_else(|_| "127.0.0.1".to_owned());
11    let port = std::env::var("TWS_PORT")
12        .ok()
13        .and_then(|value| value.parse::<u16>().ok())
14        .unwrap_or(7497);
15    let client_id = std::env::var("TWS_CLIENT_ID")
16        .ok()
17        .and_then(|value| value.parse::<i32>().ok())
18        .unwrap_or(1002);
19    let symbol = std::env::var("TWS_SYMBOL").unwrap_or_else(|_| "AAPL".to_owned());
20    let exchange = std::env::var("TWS_EXCHANGE").unwrap_or_else(|_| "SMART".to_owned());
21    let currency = std::env::var("TWS_CURRENCY").unwrap_or_else(|_| "USD".to_owned());
22    let market_data_type = std::env::var("TWS_MARKET_DATA_TYPE")
23        .ok()
24        .and_then(|value| value.parse::<i32>().ok())
25        .unwrap_or(1);
26
27    let req_id = 9001;
28    let mut client = TwsApiClient::connect(ClientConfig::new(host, port, client_id)).await?;
29    wait_until_api_ready(&mut client).await?;
30    client.req_market_data_type(market_data_type).await?;
31    client
32        .req_mkt_data(MarketDataRequest {
33            req_id,
34            contract: Contract {
35                symbol,
36                sec_type: "STK".to_owned(),
37                exchange,
38                currency,
39                ..Contract::default()
40            },
41            generic_tick_list: String::new(),
42            snapshot: false,
43            regulatory_snapshot: false,
44            market_data_options: Vec::new(),
45        })
46        .await?;
47
48    let result = tokio::time::timeout(Duration::from_secs(30), async {
49        let should_cancel = loop {
50            match client.read_event().await? {
51                Event::TickPrice {
52                    req_id: event_req_id,
53                    tick_type,
54                    price,
55                    attrib,
56                } if event_req_id == req_id => {
57                    println!("price tick_type={tick_type} price={price} attrib={attrib}");
58                    break true;
59                }
60                Event::TickSize {
61                    req_id: event_req_id,
62                    tick_type,
63                    size,
64                } if event_req_id == req_id => {
65                    println!("size tick_type={tick_type} size={size}");
66                }
67                Event::Error {
68                    req_id: event_req_id,
69                    code,
70                    message,
71                    ..
72                } if event_req_id < 0 && is_market_data_status_code(code) => {
73                    eprintln!("TWS status {code}: {message}");
74                }
75                Event::Error {
76                    req_id: event_req_id,
77                    code,
78                    message,
79                    ..
80                } if event_req_id == req_id && is_delayed_market_data_notice(code) => {
81                    eprintln!("TWS notice {code}: {message}");
82                }
83                Event::Error {
84                    req_id: event_req_id,
85                    code,
86                    message,
87                    ..
88                } if event_req_id == req_id => {
89                    eprintln!("TWS error {code}: {message}");
90                    break false;
91                }
92                Event::Error { code, message, .. } => {
93                    eprintln!("TWS notice {code}: {message}");
94                }
95                _ => {}
96            }
97        };
98        truefix_twsapi_client::error::TwsApiResult::Ok(should_cancel)
99    })
100    .await;
101
102    let should_cancel = match &result {
103        Ok(Ok(should_cancel)) => *should_cancel,
104        Ok(Err(_)) | Err(_) => true,
105    };
106    if should_cancel && let Err(error) = client.cancel_mkt_data(req_id).await {
107        eprintln!("cancelMktData failed: {error}");
108    }
109    if should_cancel {
110        tokio::time::sleep(Duration::from_millis(250)).await;
111    }
112
113    match result {
114        Ok(result) => result.map(|_| ()),
115        Err(_) => {
116            eprintln!("timed out waiting for market data");
117            Ok(())
118        }
119    }
120}
121
122fn is_market_data_status_code(code: i32) -> bool {
123    matches!(code, 2103 | 2104 | 2106 | 2107 | 2108 | 2158)
124}
125
126fn is_delayed_market_data_notice(code: i32) -> bool {
127    code == 10167
128}
129
130async fn wait_until_api_ready(
131    client: &mut TwsApiClient,
132) -> truefix_twsapi_client::error::TwsApiResult<()> {
133    let result = tokio::time::timeout(Duration::from_secs(10), async {
134        while !client.api_ready() {
135            match client.read_event().await? {
136                Event::Error { code, message, .. } if is_market_data_status_code(code) => {
137                    eprintln!("TWS status {code}: {message}");
138                }
139                Event::Error { code, message, .. } => {
140                    eprintln!("TWS notice {code}: {message}");
141                }
142                _ => {}
143            }
144        }
145        truefix_twsapi_client::error::TwsApiResult::Ok(())
146    })
147    .await;
148
149    match result {
150        Ok(result) => result,
151        Err(_) => {
152            eprintln!("timed out waiting for initial API callbacks");
153            Ok(())
154        }
155    }
156}
Source

pub async fn read_event_with<W: Wrapper>( &mut self, wrapper: &mut W, ) -> TwsApiResult<Event>

Reads one event and dispatches it to typed Wrapper callbacks.

Source

pub async fn run_with<W: Wrapper>( &mut self, wrapper: &mut W, ) -> TwsApiResult<()>

Runs the event loop until the socket closes or a decoding error occurs.

Trait Implementations§

Source§

impl Debug for TwsApiClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.