Skip to content

Commit

Permalink
added options example. propagate error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Wil Boayue committed Jan 22, 2025
1 parent 4314bf6 commit d1f6c06
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 26 deletions.
42 changes: 19 additions & 23 deletions examples/historical_data_options.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
use clap::{arg, Command};
use time::macros::datetime;

use ibapi::contracts::Contract;
use ibapi::contracts::{Contract, SecurityType};
use ibapi::market_data::historical::{BarSize, ToDuration, WhatToShow};
use ibapi::Client;

// This example demonstrates how to request historical data for an options contract.
// Historical data is not available to expired options contracts.

fn main() {
env_logger::init();

let matches = Command::new("historical_data")
.about("Get last 30 days of daily data for given stock")
.arg(arg!(<STOCK_SYMBOL>).required(true))
.arg(arg!(--connection_string <VALUE>).default_value("127.0.0.1:4002"))
.get_matches();

let connection_string = matches.get_one::<String>("connection_string").expect("connection_string is required");
let stock_symbol = matches.get_one::<String>("STOCK_SYMBOL").expect("stock symbol is required");

let client = Client::connect(&connection_string, 100).expect("connection failed");
let client = Client::connect("127.0.0.1:4002", 100).expect("connection failed");

let contract = Contract::stock(stock_symbol);
let contract = build_contract();

let historical_data = client
.historical_data(
&contract,
Some(datetime!(2023-04-11 20:00 UTC)),
1.days(),
BarSize::Hour,
WhatToShow::Trades,
true,
)
.historical_data(&contract, None, 10.days(), BarSize::Hour, WhatToShow::AdjustedLast, true)
.expect("historical data request failed");

println!("start: {:?}, end: {:?}", historical_data.start, historical_data.end);
Expand All @@ -38,3 +22,15 @@ fn main() {
println!("{bar:?}");
}
}

fn build_contract() -> Contract {
Contract {
security_type: SecurityType::Option,
symbol: "AMZN".into(),
exchange: "SMART".into(),
last_trade_date_or_contract_month: "20250131".into(),
strike: 230.0,
right: "C".into(),
..Default::default()
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,6 @@ fn encode_option_field<T: ToField>(val: &Option<T>) -> String {
None => String::from(""),
}
}

// max attempts to retry failed tws requests
const MAX_RETRIES: i32 = 5;
11 changes: 8 additions & 3 deletions src/market_data/historical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use time::{Date, OffsetDateTime};
use crate::contracts::Contract;
use crate::messages::{IncomingMessages, RequestMessage, ResponseMessage};
use crate::transport::{InternalSubscription, Response};
use crate::{server_versions, Client, Error, ToField};
use crate::{server_versions, Client, Error, ToField, MAX_RETRIES};

mod decoders;
mod encoders;
Expand Down Expand Up @@ -342,10 +342,12 @@ pub(crate) fn historical_data(
}

if end_date.is_some() && what_to_show == Some(WhatToShow::AdjustedLast) {
return Err(Error::InvalidArgument("end_date must be None when requesting WhatToShow::AdjustedLast. You might have called Client::historical_data with WhatToShow::AdjustedLast".into()));
return Err(Error::InvalidArgument(
"end_date must be None when requesting WhatToShow::AdjustedLast.".into(),
));
}

loop {
for _ in 0..MAX_RETRIES {
let request_id = client.next_request_id();
let request = encoders::encode_request_historical_data(
client.server_version(),
Expand All @@ -366,12 +368,15 @@ pub(crate) fn historical_data(
Some(Ok(mut message)) if message.message_type() == IncomingMessages::HistoricalData => {
return decoders::decode_historical_data(client.server_version, time_zone(client), &mut message)
}
Some(Ok(message)) if message.message_type() == IncomingMessages::Error => return Err(Error::from(message)),
Some(Ok(message)) => return Err(Error::UnexpectedResponse(message)),
Some(Err(Error::ConnectionReset)) => continue,
Some(Err(e)) => return Err(e),
None => return Err(Error::UnexpectedEndOfStream),
}
}

Err(Error::ConnectionReset)
}

fn time_zone(client: &Client) -> &time_tz::Tz {
Expand Down

0 comments on commit d1f6c06

Please sign in to comment.