Skip to main content

brokapi_bcs/
lib.rs

1//! BCS broker connectors: the market data connector and the user data connector.
2//!
3//! This crate is the connector layer for the BCS Trade API. It sits on top of the protocol crate
4//! `brokapi-bcs-protocol` (HTTP and WebSocket clients, wire models) and the runtime crates (`brokapi-runtime`,
5//! `brokapi-sansio`), and it implements the traits of `brokapi-core`:
6//!
7//! - [`MarketDataConnector`] implements `OrderBookSource`, `MarketDataSource` and `InstrumentSource`.
8//!   It is not tied to an account.
9//! - [`UserDataConnector`] implements `OrderExecutor`, `StopOrderExecutor`, `ExecutionSource` and
10//!   `PortfolioSource` for one account (the one the refresh token belongs to).
11//!
12//! Both connectors start with an `async fn start(config, limiter, out)`. Commands return their answer
13//! directly. Subscriptions deliver `Envelope`s into the channel `out`.
14//!
15//! Anything the shared traits cannot express is reachable through `connector.raw()` ([`BcsRaw`]):
16//! the same token, endpoint and rate limiter, one API method at a time.
17//! [`limits::default_limits`] gives the bundled rate limits. Give every connector of one BCS account
18//! the same limiter, because the limits belong to the token.
19//!
20//! The full guide is at <https://brokapi.ru/docs/>.
21//!
22//! # Examples
23//!
24//! The example runs against an in-process imitation of the broker, so it needs no network and no
25//! account. With a real account, `cfg` is built with `BcsConfig::from_env()` instead.
26//!
27//! ```
28//! use std::sync::Arc;
29//! use brokapi_bcs::limits::default_limits;
30//! use brokapi_bcs::{MarketDataConfig, MarketDataConnector, UserDataConfig, UserDataConnector};
31//! use brokapi_core::{PortfolioSource, ShutdownMode};
32//! use brokapi_runtime::BrokerLimiter;
33//! use tokio::sync::mpsc;
34//! # use brokapi_bcs_protocol::config::BcsConfig;
35//!
36//! # #[tokio::main(flavor = "current_thread")]
37//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
38//! # let server = brokapi_mocks::bcs::MockServer::start(Default::default()).await;
39//! # let cfg = BcsConfig::for_mock("mock-refresh-token", &server.http_base).with_write(true);
40//! // One limiter for the whole account.
41//! let limiter: Arc<BrokerLimiter> = BrokerLimiter::new(&default_limits());
42//! let (md_tx, _md_events) = mpsc::channel(256);
43//! let (ud_tx, _ud_events) = mpsc::channel(256);
44//!
45//! let md = MarketDataConnector::start(
46//!     MarketDataConfig::new(cfg.clone(), "bcs-md"),
47//!     Arc::clone(&limiter),
48//!     md_tx,
49//! )
50//! .await?;
51//! let ud = UserDataConnector::start(UserDataConfig::new(cfg, "bcs-ud"), limiter, ud_tx).await?;
52//!
53//! let portfolio = ud.portfolio().await?;
54//! println!("{} balances", portfolio.balances.len());
55//!
56//! md.shutdown(ShutdownMode::Immediate).await;
57//! ud.shutdown(ShutdownMode::Immediate).await;
58//! # Ok(())
59//! # }
60//! ```
61
62#![warn(missing_docs)]
63
64pub mod cid;
65pub mod config;
66pub mod core;
67pub mod error;
68pub mod limits;
69pub mod map;
70pub mod md;
71pub mod pump;
72pub mod raw;
73pub mod subs;
74pub mod ud;
75pub mod util;
76
77pub use cid::BcsCidCodec;
78pub use config::{MarketDataConfig, UserDataConfig};
79pub use core::{MdCore, UdCore, UdFrame, UdRestFrame};
80pub use md::MarketDataConnector;
81pub use raw::BcsRaw;
82pub use ud::UserDataConnector;