Skip to main content

UserDataConnector

Struct UserDataConnector 

pub struct UserDataConnector { /* private fields */ }
Expand description

The user data connector of Bybit for one account: implements [OrderExecutor], [StopOrderExecutor], [ExecutionSource] and [PortfolioSource].

Commands (place, cancel) go by HTTP, one request each, never repeated: a lost answer is [Error::Unknown]. The streams (own orders, fills, positions, wallet) come over one private WebSocket session that logs in with the key, reconnects on its own and restores its subscriptions. The account must be in one-way position mode (the default); the unified trading account is the only kind V5 knows.

Quantities are in units of the base coin (0.001 BTC). The connector reads the quantity step, the smallest order and the price step of a symbol once, and refuses an order off the grid before anything is sent.

The cid goes to the exchange as the orderLinkId of the order, which is how it comes back in the order list, the stream and the fills. A conditional order (a stop order) is an order with a trigger price: it is placed and cancelled through the same methods, and listed apart in [StopOrderExecutor::active_stop_orders].

§Examples

use brokapi_bybit::limits::default_limits;
use brokapi_bybit::util::instrument_id;
use brokapi_bybit::{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, "bybit-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("MOCKUSDT", "linear"),
        side: Side::Buy,
        order_type: OrderType::Limit,
        qty: Qty::from(10), // one step of the mock symbol
        price: Some(Price::new(dec!(1.00))),
    })
    .await?;
assert_eq!(ack.cid, cid);
ud.cancel(cid).await?;
ud.shutdown(ShutdownMode::Immediate).await;

Implementations§

§

impl UserDataConnector

pub async fn start( cfg: UserDataConfig, limiter: Arc<BrokerLimiter>, out: Sender<Envelope>, ) -> Result<UserDataConnector, Error>

Starts the connector: reads the clock of the exchange, checks the key pair with a read of the wallet, and opens the private WebSocket session in the background. Commands wait for the first reconcile.

§Errors

[Error::Config] when the client cannot be built or the exchange refuses the key pair (a key of the demo account used on the main host, a wrong secret, a missing right, an IP not on the list of the key); [Error::Transport] when the exchange cannot be reached.

pub fn raw(&self) -> BybitRaw

Direct access to any API method with this connector’s key and rate limiter. See BybitRaw.

pub fn price_grid(&self) -> &PriceGrid

The price steps and quantity steps the connector checks orders against, on top of the rules it reads from the exchange. Fill it with learn to be stricter.

pub fn caps(&self) -> UserDataCaps

What the connector can do.

  • place_idempotency: LabelOnly. The documentation says an orderLinkId is unique and a second order with the same one is refused (code 110072), but how long the exchange remembers a closed order’s id is not stated and not checked on a live account. The library never repeats a place whatever the value.
  • supports_replace: no. An amendment of the exchange keeps the client id of the order, and the shared replace promises a new order under a new cid. The amendment is available through raw and BybitHttpClient::amend_order. supports_stop_orders and streams_executions: yes.
  • ws_rpc and ordered_command_channel: no (commands go by HTTP; the exchange has a WebSocket trade channel that this connector does not use, and the demo contour has none). sandbox: yes on the demo contour (virtual money), no on the main one.

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

§

type Caps = UserDataCaps

The type that describes what this connector can do.
§

fn caps(&self) -> UserDataCaps

What this connector can do. Read it before you use a feature that not every broker has.
§

fn shutdown<'async_trait>( self, mode: ShutdownMode, ) -> Pin<Box<dyn Future<Output = ShutdownReport> + Send + 'async_trait>>
where UserDataConnector: 'async_trait,

Stops the connector: closes its streams, gives up commands that have no answer yet (they become [Error::Unknown], see [ShutdownReport]) and ends its tasks. Takes the connector by value, so it cannot be used afterwards.
§

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,

Reads your fills in 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,

Starts the stream of your fills. Read more
§

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,

Puts a new order and waits for the broker’s decision. Read more
§

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,

Cancels a working order and waits for the broker to confirm. Read more
§

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,

Changes the quantity or price of a working order. Read more
§

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,

Reads one order by its cid, as the broker shows it now. Read more
§

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,

Lists the working orders of the account. Read more
§

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,

Starts the stream of changes of your orders. Read more
§

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,

Compares your ledger with the broker and opens the trading gate. Read more
§

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,

Reads money and positions at one moment. Read more
§

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,

Reads the positions only. Read more
§

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,

Reads the money balances only. Read more
§

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,

Starts a stream of portfolio updates. Read more
§

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,

Puts a stop order and waits for the broker’s decision. Read more
§

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,

Cancels a stop order that has not triggered. Read more
§

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,

Lists the stop orders that wait for their trigger. Read more
§

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,

Stream of stop order statuses. Unsupported where the broker has no such stream. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> IntoRequest<T> for T

§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<L> LayerExt<L> for L

§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in [Layered].
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more