Skip to main content

ExecutionSource

Trait ExecutionSource 

Source
pub trait ExecutionSource: Send + Sync {
    // Required methods
    fn executions<'life0, 'async_trait>(
        &'life0 self,
        range: TimeRange,
    ) -> Pin<Box<dyn Future<Output = Result<Vec<Execution>, Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
    fn subscribe_executions<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
}
Expand description

Your own fills: the history and the live stream.

An Execution is one fill of one of your orders. Public deals of the market are in MarketDataSource. The stream is Backpressure::Lossless: a fill must not be lost, so an overflow is announced with Event::Overflow and trading stops until OrderExecutor::reconcile.

§Examples

use std::time::Duration;
use brokapi_bcs::limits::default_limits;
use brokapi_bcs::{UserDataConfig, UserDataConnector};
use brokapi_core::{
    ClientOrderId, Event, ExecutionSource, InstrumentId, InstrumentKey, NativeId, OrderExecutor,
    OrderType, PlaceOrderRequest, Price, Qty, ShutdownMode, Side, TimeRange, UnixNanos,
};
use brokapi_runtime::BrokerLimiter;

let (events_tx, mut events) = tokio::sync::mpsc::channel(256);
let limiter = BrokerLimiter::new(&default_limits());
let ud = UserDataConnector::start(UserDataConfig::new(cfg, "bcs-ud"), limiter, events_tx).await?;
ud.reconcile(&[]).await?;

// Follow the fills as they happen.
let sub = ud.subscribe_executions().await?;

let cid = ClientOrderId::new_v4();
ud.place(PlaceOrderRequest {
    cid,
    instrument: InstrumentId::new(
        InstrumentKey::new("SBER", "TQBR"),
        NativeId::TickerClass { ticker: "SBER".into(), class_code: "TQBR".into() },
    ),
    side: Side::Buy,
    order_type: OrderType::Limit,
    qty: Qty::from(2),
    price: Some(Price::from(100)),
})
.await?;

let fill = tokio::time::timeout(Duration::from_secs(8), async {
    while let Some(env) = events.recv().await {
        if let Event::Execution(x) = env.payload {
            assert_eq!(env.sub, Some(sub));
            return Some(x);
        }
    }
    None
})
.await?
.expect("a fill arrived");
assert_eq!(fill.cid, Some(cid));
assert!(fill.qty.is_positive());

// The history of the day, the same fill with its trade id.
let everything = TimeRange::new(UnixNanos::ZERO, UnixNanos::from_nanos(i64::MAX / 2));
let history = ud.executions(everything).await?;
assert!(history.iter().any(|x| x.trade_id.len() > 0));

ud.shutdown(ShutdownMode::Immediate).await;

Required Methods§

Source

fn executions<'life0, 'async_trait>( &'life0 self, range: TimeRange, ) -> Pin<Box<dyn Future<Output = Result<Vec<Execution>, Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Reads your fills in range.

Use it to find what happened to an order after Error::Unknown, or to catch up after a gap. cid of an Execution is None when the broker does not echo it (the BCS history does not), match by broker_order_id then. commission is 0.0 where the broker gives none (BCS history). How far back it goes is decided by the broker.

§Contract
§Errors
§Examples
use brokapi_core::{ExecutionSource, TimeRange, UnixNanos};
let everything = TimeRange::new(UnixNanos::ZERO, UnixNanos::from_nanos(i64::MAX / 2));
let history = ud.executions(everything).await?;
// A fresh account has no fills. The call still works.
assert!(history.is_empty());
Source

fn subscribe_executions<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Starts the stream of your fills.

Each fill arrives once as Event::Execution, tagged with the returned id. The stream is lossless and has a buffer size from the connector config: keep draining your channel. Subscribe before you place: the call returns when the stream is open, so a fill after it cannot be missed, but fills that happened before are not delivered (read executions to catch up). There is no way to end this subscription except shutting the connector down.

§Contract
§Errors
§Examples

See the example of the trait, which receives a fill.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§