You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
To retrieve historical data for futures contracts, the Contract fields for exchange and last_trade_date_or_contract_month need to be filled in, but Contract::futures(symbol) only accepts one argument for the symbol, so the exchange and last_trade_date_or_contract_month fields use the defaults empty strings.
A futures contract without an exchange and a contract month is a valid contract for a contract_details request. Based on my limited testing, running a contract_details request without an exchange or contract month returns a Iterator of all active contracts, whereas running the same request with a futures contract with the exchange and contract month specified returns and Iterator with just the details for that single contract. Each version has it's use case, so would be good to support both.
I didn't do thorough testing of what other requests work for a futures Contract without an exchange or contract month. At a glance, it looks like requesting the head_timestamp returns a value but it appears to be nonsense. I'm seeing 1970-01-01 for a contract that first existed just a couple years ago.
Steps to reproduce
Running the following program
fn main() {
let client = Client::connect("127.0.0.1:4001", 100).unwrap();
let symbol = "ES";
let contract = Contract::futures(symbol);
let start_date = Some(datetime!(2023-07-26 16:00 UTC));
let bid_ask_ticks = client
.historical_ticks_bid_ask(&contract, start_date, None, 1000, true, false)
.expect("Historical ticks request failed");
println!("Here are the bids and asks");
for tick in bid_ask_ticks {
let time = tick.timestamp;
let bid = tick.price_bid;
let ask = tick.price_ask;
println!("{time} | ${bid} | ${ask}");
}
}
Returns the following (i.e. the ticks returned is an empty Iterator):
Finished dev [unoptimized + debuginfo] target(s) in 0.24s
Running `target/debug/rust_ib_data`
Here are the bids and asks
[2104] Market data farm connection is OK:usfarm
[2106] HMDS data farm connection is OK:ushmds
[2158] Sec-def data farm connection is OK:secdefnj
The log from IB Gateway says:
22:36:57:756 -> ---54-2--1-2104-Market data farm connection is OK:usfarm-
22:36:57:756 -> ---34-2--1-2106-HMDS data farm connection is OK:ushmds-
22:36:57:756 -> ---84-2--1-2158-Sec-def data farm connection is OK:secdefnj-
22:36:57:799 <- 96-9000-0-ES-FUT--0-----USD---0-20230726 16:00:00 UTC--1000-BID_ASK-1-0--
22:36:57:799 -> ---Q4-2-9000-321-Error validating request.-'bV' : cause - Exchange must not be empty-
Environment
I'm using IB Gateway 10.19. These are my dependencies:
[dependencies]
time = "0.3.23"
ibapi = "0.3.0"
Working version
Switching the futures function to this results in a valid contract for historical data requests:
/// Creates futures contract from specified symbol
/// The contract's last trading day or contract month (for Options and Futures).
/// Strings with format YYYYMM will be interpreted as the Contract Month whereas YYYYMMDD will be interpreted as Last Trading Day.
pub fn futures(symbol: &str, exchange: &str, last_trade_date_or_contract_month: &str) -> Contract {
Contract {
symbol: symbol.to_string(),
security_type: SecurityType::Future,
currency: "USD".to_string(),
exchange: exchange.to_string(),
last_trade_date_or_contract_month: last_trade_date_or_contract_month.to_string(),
include_expired: true,
..Default::default()
}
}
Running this program
fn main() {
let client = Client::connect("127.0.0.1:4001", 100).unwrap();
let symbol = "ES";
let exchange = "CME";
let expiry = "202309";
let contract = Contract::futures(symbol, exchange, expiry);
let start_date = Some(datetime!(2023-07-26 16:00 UTC));
let bid_ask_ticks = client
.historical_ticks_bid_ask(&contract, start_date, None, 1000, true, false)
.expect("Historical ticks request failed");
println!("Here are the bids and asks");
for tick in bid_ask_ticks {
let time = tick.timestamp;
let bid = tick.price_bid;
let ask = tick.price_ask;
println!("{time} | ${bid} | ${ask}");
}
}
results in the expected output:
Here are the bids and asks
[2104] Market data farm connection is OK:usfarm
[2106] HMDS data farm connection is OK:ushmds
[2158] Sec-def data farm connection is OK:secdefnj
2023-07-26 15:59:59.0 +00:00:00 | $4589.75 | $4590
2023-07-26 16:00:00.0 +00:00:00 | $4589.75 | $4590
2023-07-26 16:00:00.0 +00:00:00 | $4589.75 | $4590
...
Proposal
Since there's a valid use for both a futures product (retrieving contract details for all active contracts) as well as an individual futures contract (retrieving historical data or contract details for a single contract), I think it makes sense to keep the current contstructor and add another Contract constructor function for an individual futures contract with an exchange and contract month. Also, I think include_expired be set to true for the individual contract constructor and perhaps be an argument for the current constructor.
I can put together a pull request for this.
The text was updated successfully, but these errors were encountered:
Summary
To retrieve historical data for futures contracts, the
Contract
fields forexchange
andlast_trade_date_or_contract_month
need to be filled in, butContract::futures(symbol)
only accepts one argument for the symbol, so theexchange
andlast_trade_date_or_contract_month
fields use the defaults empty strings.A futures contract without an exchange and a contract month is a valid contract for a
contract_details
request. Based on my limited testing, running acontract_details
request without an exchange or contract month returns a Iterator of all active contracts, whereas running the same request with a futures contract with the exchange and contract month specified returns and Iterator with just the details for that single contract. Each version has it's use case, so would be good to support both.I didn't do thorough testing of what other requests work for a futures Contract without an exchange or contract month. At a glance, it looks like requesting the
head_timestamp
returns a value but it appears to be nonsense. I'm seeing 1970-01-01 for a contract that first existed just a couple years ago.Steps to reproduce
Running the following program
Returns the following (i.e. the ticks returned is an empty Iterator):
The log from IB Gateway says:
Environment
I'm using IB Gateway 10.19. These are my dependencies:
Working version
Switching the
futures
function to this results in a valid contract for historical data requests:Running this program
results in the expected output:
Proposal
Since there's a valid use for both a futures product (retrieving contract details for all active contracts) as well as an individual futures contract (retrieving historical data or contract details for a single contract), I think it makes sense to keep the current contstructor and add another
Contract
constructor function for an individual futures contract with an exchange and contract month. Also, I thinkinclude_expired
be set to true for the individual contract constructor and perhaps be an argument for the current constructor.I can put together a pull request for this.
The text was updated successfully, but these errors were encountered: