Skip to main content

UdCore

Struct UdCore 

Source
pub struct UdCore { /* private fields */ }
Expand description

Sans-io user data core: order statuses, fills and portfolio updates from the WebSocket channels.

It turns frames into Events (orders, executions, portfolio), delivers each fill once even if the broker repeats it (de-duplicated by executionId, the last 20 000 are remembered), and remembers which broker order id belongs to which client order id. It does no I/O.

§Examples

Feed one order event from the orders/events/ws channel and read the event it makes:

use std::time::Instant;
use brokapi_bcs_protocol::ws::client::BcsWsChannel;
use brokapi_bcs::UdCore;
use brokapi_core::{ClientOrderId, Event, OrderState, SubscriptionId};
use brokapi_sansio::{
    BrokerCore, DesiredSubscription, EventSink, SubscriptionKind, SubscriptionSet,
};

let mut core = UdCore::new();
let sub = SubscriptionId::new(1001);
core.apply(&SubscriptionSet::with_subscriptions(vec![DesiredSubscription {
    id: sub,
    kind: SubscriptionKind::OrderState,
}]));

let cid = ClientOrderId::new_v4();
let frame = format!(
    r#"{{"originalClientOrderId":"{cid}","clientOrderId":"{cid}","data":{{
        "messageType":"8","orderStatus":"0","executionType":"0","orderQuantity":10,
        "executedQuantity":0,"lastQuantity":0,"remainedQuantity":10,"ticker":"SBER",
        "classCode":"TQBR","side":"1","orderType":"2","averagePrice":0,"price":100,
        "orderId":"20261019-TQBR-1","currency":"RUB","transactionTime":"2026-10-19T10:00:00.000Z"}}}}"#
);
let mut out = EventSink::new();
core.feed_ws(BcsWsChannel::OrderEvents, &frame, Instant::now(), &mut out);

let events = out.drain();
assert_eq!(events.len(), 1);
assert_eq!(events[0].sub, Some(sub));
let Event::Order(order) = &events[0].payload else { panic!("an order event") };
assert!(matches!(order.state, OrderState::Acked { .. }));
// The core now knows which of our orders the broker's id is.
assert_eq!(core.cid_of_order_id("20261019-TQBR-1"), Some(cid));

Implementations§

Source§

impl UdCore

Source

pub fn new() -> Self

Creates a core with no subscriptions and no known orders. The answer timer for a registered place command is 30 seconds (see register_place).

Source

pub fn learn_order_id(&mut self, order_id: &str, cid: ClientOrderId)

Remembers that the broker’s order order_id is our cid.

Source

pub fn cid_of_order_id(&self, order_id: &str) -> Option<ClientOrderId>

Our cid of the broker’s order order_id, if this process has seen it.

Source

pub fn orders(&self) -> &OrderRegistry

The orders this core tracks (state machine per client order id).

Source

pub fn orders_mut(&mut self) -> &mut OrderRegistry

The same registry, for changes. Meant for tests and replays.

Source

pub fn register_place(&mut self, cid: ClientOrderId, now: Instant)

Registers a place command that was just sent, and starts the 30 second answer timer for it.

UserDataConnector does not call it (it tracks sent orders in its own runtime). It is here to drive the core by hand.

Source

pub fn on_incoming( &mut self, msg: IncomingMessage, now: Instant, out: &mut EventSink, )

Handles one message already parsed by the protocol layer.

This is what the pump calls. Order messages push Event::Order, and a message with a fill (lastQuantity above zero) also pushes Event::Execution once per executionId, but only while somebody is subscribed to executions. Portfolio messages push Event::Portfolio. Other messages are skipped.

Source

pub fn feed_ws( &mut self, channel: BcsWsChannel, text: &str, now: Instant, out: &mut EventSink, )

Parses one raw text frame of a WebSocket channel and handles it like on_incoming. A frame that cannot be parsed is skipped, there is no error to return.

Trait Implementations§

Source§

impl BrokerCore for UdCore

Source§

type Frame = UdFrame

The inbound frame type: for example String for WebSocket text, or a decoded message.
Source§

fn on_frame(&mut self, frame: Self::Frame, now: Instant, out: &mut EventSink)

Handles one inbound transport frame received at now. Read more
Source§

fn poll_transmit(&mut self) -> Option<Outbound>

Takes the next outbound wire message, if any. Call it until it returns None.
Source§

fn poll_timeout(&self) -> Option<Instant>

When the core wants on_timeout to be called next, or None if it has no timer pending. Read more
Source§

fn on_timeout(&mut self, now: Instant, out: &mut EventSink)

Handles a timer that fired. now is the time the timer was due.
Source§

fn apply(&mut self, desired: &SubscriptionSet)

Tells the core the full set of subscriptions the consumer wants now. Read more
Source§

impl Debug for UdCore

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for UdCore

Source§

fn default() -> Self

Returns the “default value” for a type. 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