ibapi 4.0.0

A Rust implementation of the Interactive Brokers TWS API, providing a reliable and user friendly interface for TWS and IB Gateway. Designed with a focus on simplicity and performance.
Documentation
//! Synchronous implementation of Wall Street Horizon functionality

use time::Date;

use crate::client::sync::Client;
use crate::subscriptions::sync::Subscription;
use crate::{
    common::request_helpers::{self, expect_proto},
    protocol::{check_version, Features},
    Error,
};

use super::builder::{WshEventDataBuilder, WshEventFilterBuilder};
use super::{common::decoders, encoders, AutoFill, WshEventData, WshMetadata};

impl Client {
    /// Requests metadata from the WSH calendar.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ibapi::client::blocking::Client;
    ///
    /// let client = Client::connect("127.0.0.1:4002", 100).expect("connection failed");
    ///
    /// let metadata = client.wsh_metadata().expect("request wsh metadata failed");
    /// println!("{metadata:?}");
    /// ```
    pub fn wsh_metadata(&self) -> Result<WshMetadata, Error> {
        check_version(self.server_version, Features::WSHE_CALENDAR)?;

        request_helpers::blocking::one_shot_by_request_id(
            self,
            encoders::encode_request_wsh_metadata,
            expect_proto(decoders::decode_wsh_metadata_proto),
        )
    }

    /// Build a request for Wall Street Horizon events on one contract.
    ///
    /// Terminal: [`WshEventDataBuilder::fetch`]. Optional narrowing via
    /// `.starting()` / `.ending()` / `.limit()` / `.auto_fill()`, each of which
    /// carries its own server-version requirement.
    ///
    /// # Arguments
    ///
    /// * `contract_id` - Contract identifier for the event request.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ibapi::client::blocking::Client;
    ///
    /// let client = Client::connect("127.0.0.1:4002", 100).expect("connection failed");
    ///
    /// let contract_id = 76792991; // TSLA
    /// let event_data = client.wsh_event_data_by_contract(contract_id).fetch().expect("request wsh event data failed");
    /// println!("{event_data:?}");
    /// ```
    pub fn wsh_event_data_by_contract(&self, contract_id: i32) -> WshEventDataBuilder<'_, Self> {
        WshEventDataBuilder::new(self, contract_id)
    }

    /// Build a request for Wall Street Horizon events matching a JSON filter.
    ///
    /// Terminal: [`WshEventFilterBuilder::subscribe`].
    ///
    /// # Arguments
    ///
    /// * `filter` - Json-formatted string containing all filter values.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use ibapi::client::blocking::Client;
    ///
    /// let client = Client::connect("127.0.0.1:4002", 100).expect("connection failed");
    ///
    /// let filter = "{}"; // see https://www.interactivebrokers.com/campus/ibkr-api-page/twsapi-doc/#wsheventdata-object
    /// let subscription = client.wsh_event_data_by_filter(filter).subscribe().expect("request wsh event data failed");
    /// for event in subscription.iter_data() {
    ///     println!("{:?}", event.expect("decode error"));
    /// }
    /// ```
    pub fn wsh_event_data_by_filter<'a>(&'a self, filter: &'a str) -> WshEventFilterBuilder<'a, Self> {
        WshEventFilterBuilder::new(self, filter)
    }
}

/// Request events for one contract. Reached through
/// [`WshEventDataBuilder::fetch`](super::builder::WshEventDataBuilder::fetch).
pub(crate) fn wsh_event_data_by_contract(
    client: &Client,
    contract_id: i32,
    start_date: Option<Date>,
    end_date: Option<Date>,
    limit: Option<i32>,
    auto_fill: Option<AutoFill>,
) -> Result<WshEventData, Error> {
    check_version(client.server_version, Features::WSHE_CALENDAR)?;

    if auto_fill.is_some() {
        check_version(client.server_version, Features::WSH_EVENT_DATA_FILTERS)?;
    }

    if start_date.is_some() || end_date.is_some() || limit.is_some() {
        check_version(client.server_version, Features::WSH_EVENT_DATA_FILTERS_DATE)?;
    }

    request_helpers::blocking::one_shot_by_request_id(
        client,
        |request_id| encoders::encode_request_wsh_event_data(request_id, Some(contract_id), None, start_date, end_date, limit, auto_fill),
        expect_proto(decoders::decode_wsh_event_data_proto),
    )
}

/// Request events matching a JSON filter. Reached through
/// [`WshEventFilterBuilder::subscribe`](super::builder::WshEventFilterBuilder::subscribe).
pub(crate) fn wsh_event_data_by_filter(
    client: &Client,
    filter: &str,
    limit: Option<i32>,
    auto_fill: Option<AutoFill>,
) -> Result<Subscription<WshEventData>, Error> {
    if limit.is_some() {
        check_version(client.server_version, Features::WSH_EVENT_DATA_FILTERS_DATE)?;
    }

    request_helpers::blocking::request_with_id(client, Features::WSH_EVENT_DATA_FILTERS, |request_id| {
        encoders::encode_request_wsh_event_data(
            request_id,
            None,
            Some(filter),
            None, // start_date
            None, // end_date
            limit,
            auto_fill,
        )
    })
}

#[cfg(test)]
#[path = "sync_tests.rs"]
mod tests;