Struct UserDataConnector
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§
§impl UserDataConnector
impl UserDataConnector
pub async fn start(
cfg: UserDataConfig,
limiter: Arc<BrokerLimiter>,
out: Sender<Envelope>,
) -> Result<UserDataConnector, Error>
pub async fn start( cfg: UserDataConfig, limiter: Arc<BrokerLimiter>, out: Sender<Envelope>, ) -> Result<UserDataConnector, 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.
pub 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.
pub fn portfolio_id(&self) -> &str
pub fn portfolio_id(&self) -> &str
The portfolio this connector works with.
pub 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.
pub 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).
pub async fn shutdown(self, mode: ShutdownMode) -> ShutdownReport
pub async fn shutdown(self, mode: ShutdownMode) -> ShutdownReport
Stops the connector. Unless the mode is Immediate it closes the trading gate first; Graceful also lets
the bot’s channel take what is still buffered. Orders at the exchange are not touched.
Trait Implementations§
§impl Connector for UserDataConnector
impl Connector for UserDataConnector
§fn caps(&self) -> UserDataCaps
fn caps(&self) -> UserDataCaps
§fn shutdown<'async_trait>(
self,
mode: ShutdownMode,
) -> Pin<Box<dyn Future<Output = ShutdownReport> + Send + 'async_trait>>where
UserDataConnector: 'async_trait,
fn shutdown<'async_trait>(
self,
mode: ShutdownMode,
) -> Pin<Box<dyn Future<Output = ShutdownReport> + Send + 'async_trait>>where
UserDataConnector: 'async_trait,
Error::Unknown], see [ShutdownReport]) and ends its tasks. Takes the connector by value, so it
cannot be used afterwards.§impl ExecutionSource for UserDataConnector
impl ExecutionSource for UserDataConnector
§fn executions<'life0, 'async_trait>(
&'life0 self,
range: TimeRange,
) -> Pin<Box<dyn Future<Output = Result<Vec<Execution>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn executions<'life0, 'async_trait>(
&'life0 self,
range: TimeRange,
) -> Pin<Box<dyn Future<Output = Result<Vec<Execution>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
range. Read more§fn subscribe_executions<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn subscribe_executions<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§impl OrderExecutor for UserDataConnector
impl OrderExecutor for UserDataConnector
§fn place<'life0, 'async_trait>(
&'life0 self,
req: PlaceOrderRequest,
) -> Pin<Box<dyn Future<Output = Result<OrderAck, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn place<'life0, 'async_trait>(
&'life0 self,
req: PlaceOrderRequest,
) -> Pin<Box<dyn Future<Output = Result<OrderAck, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn cancel<'life0, 'async_trait>(
&'life0 self,
cid: Uuid,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn cancel<'life0, 'async_trait>(
&'life0 self,
cid: Uuid,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn replace<'life0, 'async_trait>(
&'life0 self,
req: ReplaceOrderRequest,
) -> Pin<Box<dyn Future<Output = Result<OrderAck, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn replace<'life0, 'async_trait>(
&'life0 self,
req: ReplaceOrderRequest,
) -> Pin<Box<dyn Future<Output = Result<OrderAck, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn order_state<'life0, 'async_trait>(
&'life0 self,
cid: Uuid,
) -> Pin<Box<dyn Future<Output = Result<OrderSnapshot, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn order_state<'life0, 'async_trait>(
&'life0 self,
cid: Uuid,
) -> Pin<Box<dyn Future<Output = Result<OrderSnapshot, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn active_orders<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<OrderSnapshot>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn active_orders<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<OrderSnapshot>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn subscribe_order_state<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn subscribe_order_state<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn reconcile<'life0, 'life1, 'async_trait>(
&'life0 self,
ledger: &'life1 [Uuid],
) -> Pin<Box<dyn Future<Output = Result<ReconcileReport, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
UserDataConnector: 'async_trait,
fn reconcile<'life0, 'life1, 'async_trait>(
&'life0 self,
ledger: &'life1 [Uuid],
) -> Pin<Box<dyn Future<Output = Result<ReconcileReport, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
UserDataConnector: 'async_trait,
§impl PortfolioSource for UserDataConnector
impl PortfolioSource for UserDataConnector
§fn portfolio<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Portfolio, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn portfolio<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Portfolio, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn positions<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<Position>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn positions<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<Position>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn balances<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<Balance>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn balances<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<Balance>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn subscribe_portfolio<'life0, 'async_trait>(
&'life0 self,
opts: SubscribeOpts,
) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn subscribe_portfolio<'life0, 'async_trait>(
&'life0 self,
opts: SubscribeOpts,
) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§impl StopOrderExecutor for UserDataConnector
impl StopOrderExecutor for UserDataConnector
§fn place_stop<'life0, 'async_trait>(
&'life0 self,
req: PlaceStopOrderRequest,
) -> Pin<Box<dyn Future<Output = Result<OrderAck, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn place_stop<'life0, 'async_trait>(
&'life0 self,
req: PlaceStopOrderRequest,
) -> Pin<Box<dyn Future<Output = Result<OrderAck, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn cancel_stop<'life0, 'async_trait>(
&'life0 self,
stop: StopOrderRef,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn cancel_stop<'life0, 'async_trait>(
&'life0 self,
stop: StopOrderRef,
) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn active_stop_orders<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<StopOrderSnapshot>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn active_stop_orders<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<StopOrderSnapshot>, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
§fn subscribe_stop_orders<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
fn subscribe_stop_orders<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>where
'life0: 'async_trait,
UserDataConnector: 'async_trait,
Unsupported where the broker has no such stream. Read moreAuto Trait Implementations§
impl !Freeze for UserDataConnector
impl !RefUnwindSafe for UserDataConnector
impl !UnwindSafe for UserDataConnector
impl Send for UserDataConnector
impl Sync for UserDataConnector
impl Unpin for UserDataConnector
impl UnsafeUnpin for UserDataConnector
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].