#![allow(clippy::uninlined_format_args)]
use std::time::Duration;
use ibapi::prelude::*;
use ibapi::subscriptions::Subscription;
use tokio::time::{timeout_at, Instant};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let client = Client::connect("127.0.0.1:4002", 100).await?;
println!("Connected to IB Gateway");
let contract = Contract::stock("AAPL").build();
let subscription = client.market_data(&contract).subscribe().await?;
let deadline = Instant::now() + Duration::from_secs(10);
let printer = tokio::spawn(read("printer", subscription.clone(), deadline, Some(5)));
let counter = tokio::spawn(read("counter", subscription.clone(), deadline, None));
drop(subscription);
println!("printer read {} ticks", printer.await?);
println!("counter read {} ticks", counter.await?);
Ok(())
}
async fn read(name: &'static str, subscription: Subscription<TickTypes>, deadline: Instant, limit: Option<usize>) -> usize {
let mut ticks = subscription.filter_data();
let mut count = 0;
while limit.is_none_or(|limit| count < limit) {
match timeout_at(deadline, ticks.next()).await {
Ok(Some(Ok(tick))) => {
count += 1;
if limit.is_some() {
println!("[{name}] {tick:?}");
}
}
Ok(Some(Err(e))) => {
eprintln!("[{name}] error: {e}");
break;
}
Ok(None) | Err(_) => break,
}
}
count
}