#[non_exhaustive]pub enum StaleMarketPolicy {
Off,
Wait {
max_age: Duration,
},
}Expand description
What a simulated venue does with an order when the instrument’s market is stale, as
MockExecutionConfig::stale_market selects. Defaults to Off.
§The problem it addresses
A venue fed a market keeps the last one it saw for each instrument, and by default fills an order against it however old it is. On a bar feed, a market order on an instrument with no bar at the current instant therefore fills at the close of its last bar, which may be minutes, hours or a weekend old, and so does a limit order that close crosses. A real order would not get that price: in a quiet market it trades against the book, and in an outage, a halt or a closed market it is refused or waits for the reopen, filling at a price that may have gapped. A bar that only carries the previous close forward, with zero volume, makes this worse: it looks recent, but nothing traded.
A venue cannot tell a quiet market from a dead feed or a halt by looking at bars, and this policy does not try to. It treats an old market as one nobody can trade in yet.
§When to turn it on, and why it is off by default
Turn it on for bar feeds, with a max_age a little over the bar interval, so that only a
market with a missing bar counts as stale. It stays off by default because a venue cannot know
a feed’s bar interval, and because on a quote or tick feed the book stays valid until it is
replaced: a quiet book is still a book an order can trade against.
#[non_exhaustive]: other actions on a stale market may be added.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Off
Fill an order against the market the venue holds, however old.
Wait
An order arriving when the instrument’s last fresh observation is more than max_age old
waits for the next one, and an observation that is not fresh fills no resting order.
§What is fresh
An observation the driver marks fresh: a
trade, a quote, or a bar something traded in. A bar reported with zero volume still moves
the price the venue holds, but not the instant the market’s age is measured from. An
observation exactly max_age old is still fresh, so a max_age of zero accepts an order
only at the instant of a fresh observation.
An instrument whose venue has no price at all is not stale but unpriced: its market orders are rejected and its limit orders rest, as they do without this policy.
§What waits
Every order arriving on a stale market, market and limit alike: whether the old market
crosses a limit order says nothing about whether the market it will trade in does. The
order is accepted as Open and held as MarketOrderTiming::NextBar holds a market
order: a cancel takes it back, and the venue holds what it would cost arriving now. That
is the current price for a market order, capped at the limit for a limit order that price
crosses, and the limit for one it does not cross. An order the account cannot cover is
refused on arrival. While it is held, nothing fills it: not even an observation that
crosses its limit, until that observation is fresh.
An immediate-or-cancel or fill-or-kill order is rejected instead, with a reason naming this policy: it asked to trade now or not at all. That includes the immediate-or-cancel orders an engine sends to close positions, so a strategy closing out on a stale instrument has to try again once its market is fresh. An order already past its own deadline expires, as it would on a fresh market.
§When it fills
On the instrument’s next fresh observation, as if it had arrived just after it, to the market that observation leaves: a trade’s or quote’s price, or a bar’s close.
- A market order is priced by the venue’s
FillModelfrom that market, moved by its slippage, and costed afresh, as any taker fill is. - A limit order that market crosses trades the same way, capped at its limit, up to the size the market has, and the rest of it joins the book at its limit. One that market does not cross joins the book whole, at its limit. A post-only one that market crosses is cancelled, as it would have been on arrival.
A fill is stamped at the observation’s instant and follows the fills of orders already resting, which the observation crossed first; a limit order joining the book then is not crossed by the observation that released it. An order the account can no longer afford, or a market order that the market cannot price, is cancelled and reported.
Only an observation of that instrument releases a held order: a clock moving, or a fresh observation of another instrument, never does. A deadline the order carries still retires it, and an order still waiting when its driver runs out of data is retired as expired, filled nothing.
§Resting orders
A limit order already resting is filled at its limit when a fresh observation crosses it, as without this policy. An observation that is not fresh, such as a bar reported with zero volume, still moves the price the venue holds but fills no resting order, however far it moves: it is not evidence that anything traded there.
§With MarketOrderTiming::NextBar
Every market order already waits for its instrument’s next bar and fills at that bar’s price, so a fresh market changes nothing for one. A limit order arriving on a stale market waits for the next bar too, and is decided against that bar’s price as a market order is priced from it. What it does not trade there rests at its limit, where the rest of that bar can cross it as it crosses any resting order. On a fresh market a limit order is decided on arrival, as without this policy. A bar reported with zero volume releases nothing: the orders held for it wait for the next bar something traded in, except an immediate-or-cancel or fill-or-kill order, which the bar cancels, since it had nothing to trade. An immediate-or-cancel or fill-or-kill order arriving on a stale market is rejected, as above.
§Needs a market feed
A RequestPriced venue, the
kind MockExchange drives, has no market feed to measure an age from, so it rejects every
market order, naming this policy (it accepts no limit order at all). On a venue that is fed
a market, an instrument it has never been fed has no price at all, and its market orders are
rejected as unpriced, as above.
§Serialised
max_age is a Duration, so it serialises as seconds and nanoseconds:
{"Wait":{"max_age":{"secs":90,"nanos":0}}}.
Trait Implementations§
Source§impl Clone for StaleMarketPolicy
impl Clone for StaleMarketPolicy
impl Copy for StaleMarketPolicy
Source§impl Debug for StaleMarketPolicy
impl Debug for StaleMarketPolicy
Source§impl Default for StaleMarketPolicy
impl Default for StaleMarketPolicy
Source§impl<'de> Deserialize<'de> for StaleMarketPolicy
impl<'de> Deserialize<'de> for StaleMarketPolicy
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for StaleMarketPolicy
Source§impl Hash for StaleMarketPolicy
impl Hash for StaleMarketPolicy
Source§impl Ord for StaleMarketPolicy
impl Ord for StaleMarketPolicy
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialEq for StaleMarketPolicy
impl PartialEq for StaleMarketPolicy
Source§impl PartialOrd for StaleMarketPolicy
impl PartialOrd for StaleMarketPolicy
Source§impl Serialize for StaleMarketPolicy
impl Serialize for StaleMarketPolicy
impl StructuralPartialEq for StaleMarketPolicy
Auto Trait Implementations§
impl Freeze for StaleMarketPolicy
impl RefUnwindSafe for StaleMarketPolicy
impl Send for StaleMarketPolicy
impl Sync for StaleMarketPolicy
impl Unpin for StaleMarketPolicy
impl UnsafeUnpin for StaleMarketPolicy
impl UnwindSafe for StaleMarketPolicy
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
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 moreimpl<T> JsonSchemaMaybe for T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.