use clap::{ArgAction, Parser};
use ibapi::{Client, contracts::Contract, market_data::MarketDataType};
use std::error::Error;
use tokio::time::{self, Duration, MissedTickBehavior};
const SYMBOL: &str = "AAPL";
const SNAPSHOT_TIMEOUT: Duration = Duration::from_secs(5);
const SNAPSHOT_INTERVAL: Duration = Duration::from_mins(1);
#[derive(Parser)]
#[command(
about = concat!(
env!("CARGO_PKG_DESCRIPTION"),
"\n\n",
"More information can be found at: ",
env!("CARGO_PKG_HOMEPAGE"),
),
version,
disable_version_flag = true
)]
struct Cli {
#[arg(short, long, help = "Print version", action = ArgAction::Version)]
_version: Option<bool>,
#[arg(long, default_value = "127.0.0.1:4001")]
address: String,
#[arg(long, default_value_t = 100)]
client_id: i32,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let cli = Cli::parse();
let client = Client::connect(&cli.address, cli.client_id).await?;
client
.switch_market_data_type(MarketDataType::Realtime)
.await?;
let contract = Contract::stock(SYMBOL).build();
let mut interval = time::interval(SNAPSHOT_INTERVAL);
interval.set_missed_tick_behavior(MissedTickBehavior::Delay);
loop {
interval.tick().await;
println!("Requesting {SYMBOL} market data snapshot…\n");
let ticks = match client
.market_data(&contract)
.snapshot_once(SNAPSHOT_TIMEOUT)
.await
{
Ok(ticks) => ticks,
Err(error) => {
eprintln!("Failed to request {SYMBOL} market data snapshot: {error}");
continue;
}
};
for tick in ticks {
println!("{tick:?}");
}
println!();
}
}
#[cfg(test)]
mod tests {
use super::Cli;
use clap::CommandFactory;
#[test]
fn verify_cli() {
Cli::command().debug_assert();
}
}