pub trait FillModel:
Debug
+ Send
+ Sync {
// Required method
fn fill_price(&self, fill: &FillContext<'_>) -> Option<Decimal>;
}Expand description
Prices a fill the venue has already decided will happen.
§Backtest-only
Only simulated execution consults a FillModel. Live execution clients receive real fill
prices from the venue.
§Called only for a taker
A market order, or a limit order that is marketable when it arrives. A resting order matched later fills at its own limit price and never reaches a fill model: a maker is paid the price it quoted, and price improvement accrues to the aggressor that crossed it.
§This model does not see the limit price, and must not
A limit constrains the result, not the pricing. The venue clamps whatever is returned to the order’s limit — never above a buy’s, never below a sell’s — so an implementation models slippage and spread and cannot produce a fill outside the order’s terms.
Reading the limit here is how two of the three models this crate ships came to return the limit itself for a marketable order: a buy limit of 51,000 arriving against an ask of 50,000 filled at 51,000 — a worse price than a market order got under the same configuration. The third returned the midpoint even when it sat above a buy’s limit. Removing the parameter is what makes that class of error unwritable rather than merely documented.
§Extensibility
Implement this to model market impact or other execution dynamics, and hand it to the venue
with SimulatedVenue::with_fill_model. The built-in models (LastPriceFillModel,
BidAskFillModel, MidpointFillModel) are baselines, and SimFillConfig selects one of
them from a serialisable configuration.
Adverse slippage, fixed or drawn at random, needs no model of its own: the venue applies its
SlippageConfig to whatever price the model returns, whichever model that is.
§It must be a pure function of its context
The venue may call fill_price more than once for one order, and for
orders that never fill: it asks, for instance, whether a short sale is priceable at all before
deciding to refuse it. So the same context must always give the same price, which is why this
takes &self. Randomness belongs in the venue’s SlippageConfig, whose seeded stream
advances exactly once per fill.
The price returned must be a real market price: the venue’s arithmetic on it, slippage and
settlement included, panics on Decimal overflow.
§It fills optimistically by default
The venue prices a taker at the market as it stands when the order arrives, which in a backtest on bars is the close of the bar the strategy has just seen. That is not look-ahead, since the close is known when deciding, but it is optimistic: it assumes trading at an observed price with no latency and, unless a model or slippage says otherwise, no cost of crossing.
§Returns
None when the context carries nothing this model can price from — no prices at all on the
first ticks of a backtest, say. The venue turns that into a rejection naming the instrument
rather than a panic.
Required Methods§
fn fill_price(&self, fill: &FillContext<'_>) -> Option<Decimal>
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".