Skip to main content

UserDataConnector

Struct UserDataConnector 

Source
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§

Source§

impl UserDataConnector

Source

pub async fn start( cfg: UserDataConfig, limiter: Arc<BrokerLimiter>, out: Sender<Envelope>, ) -> Result<Self, 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.

Source

pub fn raw(&self) -> BybitRaw

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

Source

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.

Source

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.
Source

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§

Source§

impl Connector for UserDataConnector

Source§

type Caps = UserDataCaps

The type that describes what this connector can do.
Source§

fn caps(&self) -> UserDataCaps

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

fn shutdown<'async_trait>( self, mode: ShutdownMode, ) -> Pin<Box<dyn Future<Output = ShutdownReport> + Send + 'async_trait>>
where Self: '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.
Source§

impl ExecutionSource for UserDataConnector

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. Read more
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. Read more
Source§

impl OrderExecutor for UserDataConnector

Source§

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

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

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

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

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

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

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

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

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

Lists the working orders of the account. Read more
Source§

fn subscribe_order_state<'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 changes of your orders. Read more
Source§

fn reconcile<'life0, 'life1, 'async_trait>( &'life0 self, ledger: &'life1 [ClientOrderId], ) -> Pin<Box<dyn Future<Output = Result<ReconcileReport, Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

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

impl PortfolioSource for UserDataConnector

Source§

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

Reads money and positions at one moment. Read more
Source§

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

Reads the positions only. Read more
Source§

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

Reads the money balances only. Read more
Source§

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

Starts a stream of portfolio updates. Read more
Source§

impl StopOrderExecutor for UserDataConnector

Source§

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

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

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

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

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

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

fn subscribe_stop_orders<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<SubscriptionId, Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: '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> 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