pub struct Sink { /* private fields */ }Expand description
Live updates for one subscription. Cheap to clone and usable from any thread; pushes never wait for the chart to catch up.
use chrono::Utc;
use egui_charts::data::{Datafeed, HistoryPage, HistoryRequest, Reply, Subscription};
use egui_charts::model::{OrderBook, OrderBookLevel, Tick, OrderSide};
struct Exchange;
impl Datafeed for Exchange {
fn history(&self, _: HistoryRequest, reply: Reply<HistoryPage>) {
reply.send(Ok(HistoryPage::default()));
}
/// A real feed pushes from its connection's thread or task.
fn subscribe(&self, subscription: Subscription) {
let sink = subscription.sink;
let level = |price, size| OrderBookLevel { price, size, order_cnt: None };
let symbol = subscription.symbol;
let book = |bids, asks| OrderBook { ts: Utc::now(), symbol: symbol.clone(), bids, asks };
sink.push_depth_snapshot(7, book(vec![level(99.75, 3.0)], vec![level(100.0, 2.0)]));
let side = Some(OrderSide::Buy);
sink.push_tick(Tick::new(Utc::now(), 100.0, 2.0, side).with_id(41_207));
// The buy took the whole offer at 100.
sink.push_depth_delta(8, &book(vec![], vec![level(100.0, 0.0)]));
}
}Pending bars are capped at 100,000 slots independently of raw trades. Overflow discards
the oldest slots and reports FeedError::InvalidData on the next drain; the host reloads
history to recover the missing bars.
Implementations§
Source§impl Sink
impl Sink
Sourcepub fn reset_replay(&self, time: DateTime<Utc>)
pub fn reset_replay(&self, time: DateTime<Utc>)
Starts a new replay position on this subscription. The next chart drain clears prior
bars, trades, depth, quote and sampled history before applying subsequent pushes. Resets
trade ids and partial event bars too, so rewinding cannot double-count or retain future
state. Hosts coordinate outstanding history replies and call this on every symbol’s sink
before dispatching ReplayClock::seek. Keep using the same subscription and sampler grid.
Sourcepub fn push_bar(&self, bar: Bar)
pub fn push_bar(&self, bar: Bar)
A bar of the subscribed timeframe, stamped with its open or any instant inside it:
replaces the bar it shares a slot with, appends a newer one, corrects an older one. A bar
of a day or longer is stamped inside its calendar period, as HistoryPage::bars describes. A
bar stamped too far ahead of the feed’s current time is rejected, as
Sink::set_server_time describes.
Sourcepub fn push_tick(&self, tick: Tick)
pub fn push_tick(&self, tick: Tick)
A trade, folded into the bar of its slot and kept for order flow, the oldest trades making
room for new ones. Its size is added to that bar’s volume, also when the bar came from a
history page. Trades that arrive before history extend only the page’s newest bar, which
must count only trades the stream did not send, or the feed must hold those trades until
the page is answered. Completed page bars replace bars built from ticks. A feed that cannot
tell pushes bars instead. Trades older than the last
accepted execution or forming bar are dropped, and so is a trade whose id is among those
of the last trades the subscription folded, as many as its trade store holds. A trade
stamped too far ahead of the feed’s current time is rejected, as Sink::set_server_time
describes.
Repeated ids can complete missing aggressor and resting order ids without adding volume.
Trade-based intervals start at the first accepted execution of the subscription. Replay the retained executions on resubscription to rebuild a partial bar. Count bars use the first trade’s time; if that would duplicate a bar time, it advances by one nanosecond. Original execution times remain unchanged. Volume and delta fills split exactly at the threshold; range bars need the instrument tick size and close at the first real fill reaching it. A fill producing more than 100,000 bars is rejected atomically. A pushed trade-based bar must be complete: the next trade starts a fresh bar. History pages should contain complete trade-based bars only.
Sourcepub fn advance_time(&self, now: DateTime<Utc>)
pub fn advance_time(&self, now: DateTime<Utc>)
Advances a time-based stream through now, opening an empty forming candle at the
current clock boundary when there has been no execution. Empty candles have zero volume
and carry the close of the newest bar before them that is not whitespace, whether this
stream or a history page delivered it, before or after the heartbeat; their first trade
sets the real open, high and low. Count bars never advance without trades. A clock with a
session opens a candle only inside the windows the subscription selected: a heartbeat
outside them only advances the stream’s time, and the first one inside the next session
opens that session’s slot at the last close. Call from a trusted feed heartbeat, after
seeding a bar or execution; invalid or future clock values obey the same rule as trade
timestamps. Heartbeats also close due depth-history periods, including on count intervals.
Sourcepub fn push_depth_snapshot(&self, sequence: u64, book: OrderBook)
pub fn push_depth_snapshot(&self, sequence: u64, book: OrderBook)
The whole order book, numbered sequence, at most 10,000 levels per side: a deeper book is
rejected. It replaces the book; the next delta carries sequence + 1. Levels are keyed by
the nearest integer tick of the instrument’s tick_size,
when it has one, so prices that differ by a rounding error are one level and the latest
size pushed for it holds. A crossed book is kept as pushed.
Sourcepub fn push_depth_delta(&self, sequence: u64, changes: &OrderBook)
pub fn push_depth_delta(&self, sequence: u64, changes: &OrderBook)
The levels that changed since the update numbered sequence - 1, each with its new size; a
size of 0 removes the level. The symbol of changes is ignored. Taken by reference, so a
feed can clear and refill one OrderBook for every delta instead of allocating its levels
per message. Changes are sorted by price and merged in one pass, with the last entry for
each price winning. A delta numbered at or below the last one applied is ignored. After a
gap, before the first snapshot, or when a side would exceed 10,000 levels, the book is
cleared and the chart calls Datafeed::request_depth_snapshot once; a snapshot pushed
before the chart sees the loss cancels the call. Keep pushing deltas while the snapshot is
fetched: those pushed while the book waits are held, the oldest dropped beyond 10,000
levels in all, and the snapshot applies the ones numbered above its own sequence.
Sourcepub fn push_order_snapshot(
&self,
sequence: u64,
time: DateTime<Utc>,
orders: Vec<RestingOrder>,
)
pub fn push_order_snapshot( &self, sequence: u64, time: DateTime<Utc>, orders: Vec<RestingOrder>, )
Replaces the per-order book, at most 10,000 orders per side, listed in queue order.
The next event has sequence + 1; events buffered during resync above the snapshot’s
sequence apply afterwards. Gaps and invalid events clear both books and ask the feed for
a new snapshot once through Datafeed::request_depth_snapshot. Use either order events
or aggregated deltas for a subscription; an aggregated push discards the order queues.
Sourcepub fn push_order_event(
&self,
sequence: u64,
time: DateTime<Utc>,
event: OrderEvent,
)
pub fn push_order_event( &self, sequence: u64, time: DateTime<Utc>, event: OrderEvent, )
Applies one order event with consecutive sequencing. Repeated sequences are ignored; while waiting for a snapshot at most 10,000 consecutive events are kept. Unknown cancels, duplicate adds, invalid sizes and oversized executions lose the book. An execution’s optional trade enters the raw trade store and carries the resting order id it filled.
Sourcepub fn push_quote(&self, quote: Level1Quote)
pub fn push_quote(&self, quote: Level1Quote)
Latest best bid and ask. Bursts coalesce to the newest timestamp (last arrival on a tie).
Non-finite prices and negative or non-finite sizes are rejected without replacing the
pending quote. A crossed quote, its bid above its ask, is kept, as the top of a crossed
book (see OrderBook::is_crossed). Times obey the feed-clock rule of Self::set_server_time.
The subscription supplies the instrument identity; the
sink ignores a quote whose symbol differs from its subscribed symbol.
Sourcepub fn set_server_time(&self, now: DateTime<Utc>)
pub fn set_server_time(&self, now: DateTime<Utc>)
The feed’s current time, from a clock other than the times it pushes, such as its server’s heartbeat or time message: reporting the time of the trade or bar about to be pushed would let a wrong time through. The time runs on with the system clock until the next call; until the first, the system clock stands in.
A bar or trade is rejected when its slot opens more than one slot after the slot of this time and more than a minute after this time, or more than two weeks for bars of a day or longer, which a feed stamps on their trading date. A time in the wrong unit, such as milliseconds read as seconds, therefore cannot make every later trade late, while a system clock a few seconds slow rejects nothing. A replay or simulation calls this before its first push, whenever its clock jumps, and at least once per bar while its clock runs at another speed.
Sourcepub fn set_status(&self, status: FeedStatus)
pub fn set_status(&self, status: FeedStatus)
The connection status. The latest one wins.
Sourcepub fn report_error(&self, error: FeedError)
pub fn report_error(&self, error: FeedError)
An error of the live stream. The latest one wins.
Sourcepub fn symbols_changed(&self)
pub fn symbols_changed(&self)
Notifies the host that its symbol search catalog should be refreshed. Coalesces within
a frame; the chart exposes arrivals through FeedState::symbol_catalog_revision.
Source§impl Sink
impl Sink
Sourcepub fn push_metric(&self, point: MetricPoint)
pub fn push_metric(&self, point: MetricPoint)
Publish or correct a metric point. Its value is held until the next point;
an inactive subscription ignores pushes, like Self::push_bar.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for Sink
impl !UnwindSafe for Sink
impl Freeze for Sink
impl Send for Sink
impl Sync for Sink
impl Unpin for Sink
impl UnsafeUnpin for Sink
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more