pub struct UserDataConnector { /* private fields */ }Expand description
The user data connector of ALOR for one portfolio: implements [OrderExecutor], [StopOrderExecutor],
[ExecutionSource] and [PortfolioSource].
Commands (place, cancel, replace) go by HTTP, one request each, never repeated: a lost answer is
[Error::Unknown]. The streams (own orders, fills, positions) come over one WebSocket session that
reconnects on its own. Quantities of the shared interface are pieces; the broker counts in lots, so the
connector reads the lot size of an instrument once and converts both ways.
The portfolio and the exchange come from the config (ALOR_PORTFOLIO, ALOR_EXCHANGE). An order for an
instrument of another exchange is refused with [Error::Config]: start a second connector for it.
The cid goes to the broker twice: as X-REQID of the command, and as the comment of the order. The comment
is how it comes back in the order list, the stream and the trades.
§Examples
use brokapi_alor::limits::default_limits;
use brokapi_alor::util::instrument_id;
use brokapi_alor::{UserDataConfig, UserDataConnector};
use brokapi_core::{
ClientOrderId, Decimal, OrderExecutor, OrderType, PlaceOrderRequest, Price, Qty, ShutdownMode, Side, dec,
};
use brokapi_runtime::BrokerLimiter;
use tokio::sync::mpsc;
let (tx, _events) = mpsc::channel(256);
let ud = UserDataConnector::start(UserDataConfig::new(cfg, "alor-ud"), BrokerLimiter::new(&default_limits()), tx).await?;
// Commands wait for the first reconcile.
ud.reconcile(&[]).await?;
let cid = ClientOrderId::new_v4();
let ack = ud
.place(PlaceOrderRequest {
cid,
instrument: instrument_id("SBER", "TQBR"),
side: Side::Buy,
order_type: OrderType::Limit,
qty: Qty::from(10), // one lot of SBER: 10 shares
price: Some(Price::new(dec!(100.0))),
})
.await?;
assert_eq!(ack.cid, cid);
ud.cancel(cid).await?;
ud.shutdown(ShutdownMode::Immediate).await;Implementations§
Source§impl UserDataConnector
impl UserDataConnector
Sourcepub async fn start(
cfg: UserDataConfig,
limiter: Arc<BrokerLimiter>,
out: Sender<Envelope>,
) -> Result<Self, Error>
pub async fn start( cfg: UserDataConfig, limiter: Arc<BrokerLimiter>, out: Sender<Envelope>, ) -> Result<Self, Error>
Starts the connector: gets the first access token, finds the portfolio, and opens the WebSocket session in
the background. Commands wait for the first reconcile.
§Errors
[Error::Config] when the client cannot be built, the broker refuses the token, or no single portfolio
can be told (the config names none and the token names several or none); [Error::Transport] when the
authorization server cannot be reached.
Sourcepub fn raw(&self) -> AlorRaw
pub fn raw(&self) -> AlorRaw
Direct access to any API method with this connector’s token and rate limiter. See AlorRaw.
Sourcepub fn portfolio_id(&self) -> &str
pub fn portfolio_id(&self) -> &str
The portfolio this connector works with.
Sourcepub fn price_grid(&self) -> &PriceGrid
pub fn price_grid(&self) -> &PriceGrid
The price steps and lot sizes the connector checks orders against. Fill it with learn before you trade.
Sourcepub fn caps(&self) -> UserDataCaps
pub fn caps(&self) -> UserDataCaps
What the connector can do.
place_idempotency:LabelOnly. The broker’s documentation says a repeatedX-REQIDgets a copy of the first answer instead of a second order, but that is not checked on a live account and the window is unknown. The library never repeats a place whatever the value.supports_replaceandsupports_stop_orders: yes.streams_executions: yes.ws_rpcandordered_command_channel: no (commands go by HTTP).sandbox: no (the test contour is a contour of its own, chosen in the config).
Trait Implementations§
Source§impl Connector for UserDataConnector
impl Connector for UserDataConnector
Source§fn caps(&self) -> UserDataCaps
fn caps(&self) -> UserDataCaps
Source§fn shutdown<'async_trait>(
self,
mode: ShutdownMode,
) -> Pin<Box<dyn Future<Output = ShutdownReport> + Send + 'async_trait>>where
Self: 'async_trait,
fn shutdown<'async_trait>(
self,
mode: ShutdownMode,
) -> Pin<Box<dyn Future<Output = ShutdownReport> + Send + 'async_trait>>where
Self: 'async_trait,
Error::Unknown], see [ShutdownReport]) and ends its tasks. Takes the connector by value, so it
cannot be used afterwards.