Skip to main content

SimulatedVenue

Struct SimulatedVenue 

Source
pub struct SimulatedVenue {
    pub exchange: ExchangeId,
    pub fee_model: FeeModelConfig,
    pub spot_fee_asset: SpotFeeAsset,
    pub account: AccountState,
    /* private fields */
}
Expand description

Simulated venue state machine: synchronous, transport-free and latency-free.

Fills every market order immediately, rests limit orders that the market has not reached, and keeps its own balance ledger. It has no channels and never sleeps, so a driver decides when its output reaches a client while the venue decides what that output is and in which order it must arrive — see VenueOutcome.

§Which InstrumentKinds it accounts for

Spot and Cfd. A spot fill exchanges the two underlying assets; a CFD fill is cash-settled in the quote asset in both directions, since there is nothing to deliver and a short is a margin position rather than a stock loan — see # How a CFD is accounted. Both carry the instrument’s contract_size into the notional and the fee, so this ledger and the engine’s position accounting cannot disagree by that multiplier.

§How a spot fill is accounted

A spot fill exchanges the two assets. Which asset its fee is charged in is spot_fee_asset, a SpotFeeAsset rule; the amount comes from fee_model, priced in quote. Under the default, SpotFeeAsset::Quote, the fee is charged in quote on both sides:

  • A buy pays price × quantity plus the fee in quote, and receives quantity of base.
  • A sell delivers quantity of base, and receives price × quantity less the fee in quote.

Under SpotFeeAsset::Received, a sell is the same, and a buy pays price × quantity in quote and receives quantity less the fee in base, the quote fee divided by the price. A fill at a price that is not positive cannot be converted, so its fee is in quote.

A fill whose fee exceeds what it receives, which only a flat per-unit fee on a near-worthless fill can produce, takes the excess from the balance of the asset it receives, and is refused if that cannot cover it.

With MockExecutionConfig::fee_asset, a fill instead pays its fee, discounted, in a third asset such as BNB, out of that asset’s free balance and apart from what it exchanges: a buy pays price × quantity in quote and receives quantity of base, and a sell delivers quantity of base and receives price × quantity. It falls back to the rule above when that balance is short, the asset has no price, or the instrument trades the asset itself. See FeeAssetConfig. A fill paying in the fee asset restates that balance after the two it exchanged.

The fee the fill reports in Trade::fees is the one the ledger charged, in the asset it charged. So the base a fill moves is its quantity less any fee it reports in base, and the engine’s position, which nets a base fee from a spot quantity, agrees with this ledger’s base balance. A fill restates both balances it moved, the one it paid with first, before the Trade.

§Spot margin

By default this venue is a cash account: a spot order must be paid for with what the account holds, so a sell of base it lacks is refused. Configured with MockExecutionConfig::spot_margin, it is a cross margin account instead. An order’s MarginEffect (its request’s, else the configuration’s) decides what it does to the loans: a Borrow is lent the shortfall of the asset it pays with when the venue accepts it, or that asset’s configured minimum borrow if it is more, and the venue holds the loan against it and repays it if the order ends unfilled; a Repay repays loans, interest first, from what its fill delivers; a NoSideEffect does neither. Every balance then reports its loan in Balance::margin, and the account’s holding of an asset is its total less what it owes. See SpotMarginConfig for how much it lends and what it does not model.

A restatement whose loan differs from the one last reported for its asset is followed at once by an AccountEventKind::MarginDebt stating the new debt, at the restatement’s time, as a live margin venue streams one: MarginDebtKind::Borrow when principal rose, MarginDebtKind::Repay when principal or interest fell, and MarginDebtKind::Interest when only interest rose. The loans a configuration seeds are the debt it starts from, and are not reported.

Its loans are free unless it is given a MarginInterestModel through with_margin_interest. Then each loan is charged when it is taken, and at each of the model’s boundaries while principal is owed in its asset:

  • At borrow, on the amount lent, when the order that borrows is accepted. The balance the order restates includes the interest. The AccountEventKind::CashFlow reporting it comes after the trade the loan pays for, once the position it funds exists, so that a consumer attributing the charge to that position (see CashFlowAttributionStrategy in the rustrade crate) finds it: [balance.., trade, cash flow]. An order that borrows when it rests on the book, or is held for a later bar or a fresh market, has traded nothing yet, so its cash flow waits: it is reported after the order’s first fill, or with the order’s end if it never fills (a cancel, an expiry, or a release it cannot afford). It is stamped at that instant, not at the charge, since a consumer applies no flow stamped before the position it belongs to.
  • At a boundary, on the principal owed when it falls, as [balance, cash flow] stamped at the boundary, when a driver moves the clock to or past it, as for holding costs (see # Holding costs). A loan taken at a boundary’s instant is charged at borrow, not again at that boundary.

The interest is added to the loan, so total and free are unchanged and what a fill delivers repays it first. Each cash flow is a CashFlowKind::MarginInterest, in the borrowed asset, negative, with no instrument, since a cross margin loan belongs to the account rather than to a position. A charge on a new loan carries InterestTiming::OnBorrow and one at a boundary InterestTiming::Periodic. A venue that books such interest at the start of its hour stamps it earlier than this venue does.

It liquidates the account only when the configuration says so, with SpotMarginConfig::with_liquidation: then, after each input, an account whose margin level has fallen to the configured level has its open orders cancelled and every debt closed by forced trades, reported as TradeOrigin::Liquidation fills, and is charged a fee. See SpotMarginLiquidation.

§How a CFD is accounted

This venue keeps one net position per CFD instrument, in contracts, and splits every fill against it: the part that opposes the position closes it, and the rest opens one. A single fill can do both, flipping a long into a short.

  • Opening posts the full notional, price × quantity × contract_size, as margin. This venue models no leverage, so that is the conservative reading, and the requirement a spot buy already carries.
  • Closing pays back the margin of the quantity closed at its average entry, together with the realised PnL: closed × contract_size × (price − entry) for a long, and the negative of that for a short. The proceeds count towards what the same fill must pay, so a flip is funded by the position it closes, and an account that opened with its whole balance can close.
  • The fee is charged on the whole quantity.

Over a round trip the balance therefore moves by the realised PnL less the fees, as the engine’s own Position books it. The entry averages as the engine’s does: an increase moves it to the volume-weighted average, a reduction keeps it, and a flip enters at the fill price. The position is reported by account_snapshot, and a position that a configured initial_state reports for a CFD is where this venue starts.

Not modelled: liquidation of a CFD position, even on a venue that liquidates its spot margin account. A short closed at more than twice its entry has lost more than its margin, and pays the shortfall as a debit. Carry is charged only when configured: see # Holding costs.

Perpetual, Future and Option need funding, margin and expiry settlement, none of which this venue models. They are rejected at open_order with ApiError::InstrumentInvalid rather than filled. The check lives here, not only in the rustrade builder, because this type and its constructors are public: a consumer that constructs one directly bypasses every upstream gate, and the alternative to rejecting is filling a derivative as if it were deliverable stock.

§Holding costs

By default this venue charges no carrying cost, so a CFD position is held for free and the balances and PnL of a run leave carry out. Configured with with_holding_costs, it charges each CFD position what its HoldingCostModels say holding it costs: funding, a borrow fee, overnight financing.

  • When. At each model’s boundaries, as the clock reaches them. This venue has no timer, so a boundary is charged when a driver next moves the clock to or past it, through advance_time or apply_market. Several boundaries passed at once are each charged once, in time order, however far the clock jumped, and a clock moved back charges nothing (see advance_time). A driver that moves the clock to next_deadline charges each one when it falls, as SimRunner does. Charging starts at the instant the clock first moves, so a position a configured initial_state seeds is charged from there, and never for the time before the run.
  • What. The position held across the boundary, valued at the mid of this venue’s market, else its last price, else its entry price where there is no market, which is warned of once. A position opened at a boundary’s instant is not charged for it; one closed at that instant is. Nothing is charged for part of a period: a position opened and closed between two boundaries pays nothing, as one held past no venue cutoff would.
  • How. Each charge moves the instrument’s quote asset and is reported as [balance, cash flow]: the restated balance, then an AccountEventKind::CashFlow attributed to the instrument, both stamped at the boundary, with a CashFlowId from this venue’s own sequence. The engine adds the flow to the position’s carry, as it does a live venue’s. A charge the account cannot cover is still made, and takes free below zero, with a WARN on the charge that does so, since this venue liquidates no CFD position.

§Locates and the short-sale restriction

This venue lends no stock: a spot sell delivers base the account must hold, so a short sale of a spot instrument is refused with ApiError::BalanceInsufficient.

A CFD short is allowed without limit by default. Configured with with_shortability, this venue asks its ShortabilityProvider about every order that would open or increase one, at the venue’s clock, and refuses it with ApiError::BorrowRejected for the first of these that applies:

  • NotShortable: the provider says the instrument is not shortable, or that it is delisted at or before the venue’s clock (Shortability::delisting_at).
  • InventoryUnavailable: the short would exceed what the provider says is available. That is the lender’s total, so the account’s own short counts against it, and so does every resting sell, as if it had filled. The refusal carries what is left in BorrowReject::available.
  • ShortSaleRestricted: a short-sale restriction is in effect and the order is marketable: a market order, or a sell limit at or below the best bid (the last price, on a feed with no book). A limit above the bid rests, and so does any sell limit when there is neither a bid nor a last price. A market order the FillModel cannot price, such as one against a bid-only book under MidpointFillModel, is refused as unpriceable, as it would be unrestricted.

Only the short part of an order is gated: a flip from a long is measured by the short it opens, and a buy, or a sell that only reduces a long once every resting sell has filled, is never refused. Unknown values allow the short. An order is checked once, on arrival: a resting order fills whatever the provider says later, and the easy-to-borrow flag and fee rate are not read here, since a borrow fee is charged by a HoldingCostModel.

§⚠️ Caller obligations and known limitations

  • Fund the quote asset of every instrument traded. Every debit is quote-denominated except a spot sell, which debits base, and the excess fee of a fill whose fee exceeds what it receives (see # How a spot fill is accounted). A missing balance to debit is a panic, not an error: the balances are this venue’s own fixture, so an absent one is a mis-specified test rather than a runtime condition. A margin account that lends the debit is the exception: it opens the balance with the loan (see # Spot margin). A CFD settling in an account currency that is not the quote asset still needs the quote asset funded — see below.
  • CfdContract::settlement_asset is not settled in. A CFD routinely cash-settles in an account currency that is not the quote asset (a GBP account trading a USD-quoted index), which requires a quote→settlement conversion rate. This venue has no rate source and will not invent one, so it debits and credits the quote asset and leaves the currency dimension unmodelled. The field is carried on the instrument so its description stays faithful, and the engine’s own InstrumentKind — not this copy — drives PnL. A backtest whose result depends on the settlement currency needs a real execution client.
  • The asset a spot fill receives is created at zero if the account never held it, so only the paying asset of a first order needs funding. A sell of base the account holds none of is still a missing balance, since it is a debit.
  • Which order kinds are accepted depends on the VenueRegime. OrderKind::Market always; OrderKind::Limit only on a MarketDriven venue; every other kind never.
  • A resting order seeded by initial_state reserves nothing, because this venue never took it. An account snapshot says an order is resting and says what the balances are, but not which order any held portion belongs to. Such an order still matches, and its fill debits the ledger then — so the seeded balances must cover it, exactly as they must cover a market order. They cannot? For spot that is a mis-specified fixture, and it panics, in the same class as an absent balance; a CFD order is instead cancelled at fill, as described under the reserved balances below. Cancelling one releases nothing and restates no balance, and neither does retiring one at its deadline. Such an order may also arrive part-filled, carrying an Open::filled_quantity this venue did not produce: only the remainder ever trades here, and a fill that completes it reports no avg_price, because the price of the part that traded elsewhere is not something this venue can know. An order this venue part-filled before resting is the same shape, and reports no avg_price for the same reason — the two fills were struck at different prices and this state carries one of them.
  • A CFD position seeded by initial_state is where the venue’s ledger starts, and must carry an entry price. Closing it credits the margin and realised PnL measured from that price, so a position with entry_price: None is a mis-specified fixture, and construction panics.

§How an order is priced

Every fill is priced from one market, and which market that is depends only on the VenueRegime: this venue’s own on a MarketDriven one, and the snapshot the request carried (RequestOpen::market) on a RequestPriced one. A limit order is only ever accepted on a MarketDriven venue, so it is always priced from the venue’s own market; a market order follows the regime.

That a MarketDriven venue prices a market order from its own book — rather than from the sender’s view at decision time — is what makes a driver’s request latency price-relevant instead of a pure delivery delay. The market may move between an order being decided and arriving, and a fill is struck against the book it arrives to. RequestOpen::market is then decision-time provenance and nothing else, which is what it is documented to be, and the difference between it and the fill is implementation shortfall — a quantity that is identically zero when the two are the same snapshot.

A MarketDriven venue that has not been fed an instrument rejects a market order in it as unpriceable rather than falling back to the requester’s snapshot: a venue with no market for an instrument cannot fill a market order in it, and saying so is the observable failure. Silently pricing from the requester’s view would make the fill depend on which of the two happened to hold a price, and would re-admit the very RequestPriced behaviour the regime exists to distinguish.

Given that market, the three cases are:

  • A market order, and a limit order marketable on arrival — priced by the FillModel, then moved against the order by the configured slippage. A limit order is then clamped to its own limit: a buy never fills above it, a sell never below. Both are charged Liquidity::Taker.
  • A resting limit order — fills at its own limit price exactly, and never reaches the FillModel or the slippage. Deriving a better price from the book would credit price improvement no resting order can obtain: a maker is paid the price it quoted, and improvement accrues to the aggressor that crossed it. Charged Liquidity::Maker.
  • A market order held for the next bar, under MarketOrderTiming::NextBar — priced like a market order, but from the next bar’s reference price rather than the market it arrived to: the FillModel is handed that price as the only one there is, and the slippage moves it. Charged Liquidity::Taker.
  • An order held on a stale market, under StaleMarketPolicy::Wait — priced as if it arrived just after the fresh observation that releases it, by the rules above: a market order as a market order, a limit order as one marketable on arrival if that market crosses it and as a resting one if not.

The marketable and resting rules agree exactly at the crossing point — an order arriving when best_ask == limit fills at the limit either way — and diverge only where the order genuinely is, or is not, marketable. Marketability is judged on best_ask/best_bid, falling back to last_price when the feed supplies no book: with the default LastPriceFillModel and a trades-only feed there is no book at all, so a book-only rule would never match anything.

§What matching does not model

  • No queue position. Nothing rests ahead of this account’s orders. OpenOrders ranks them by price then arrival, so which of them fills first is reproducible, but they are matched against a book with no other participants in it — an order that crosses is never waiting behind anyone.
  • Only a taker is capped by size. An order aggressing on arrival fills at most what VenueInstrumentMarket::depth says is on offer, and draws that down as it takes it. A resting order is not capped: when the market reaches it, it fills its whole remaining quantity at its limit however little traded there. Capping it honestly would need the volume that actually printed through the limit, which this venue’s feed does not carry — a MarketSnapshot is a view of the market, not a record of what traded — and capping it by the size on the opposite side would be a number shaped like a cap that measures nothing a cap should.
  • A capped taker’s remainder is a maker, and makers are not capped. So an order the book could only partly fill rests the rest, and the very next tick that still crosses it fills that remainder in full. The cap bounds what one order takes from one observation; it does not make liquidity scarce for longer than that.
  • Absent size means unlimited, not unfillable. A feed with no sizes — trades only, candles, a price-only export, or a RequestPriced venue, which has no market at all — caps nothing. See MarketDepth.
  • Depth is this account’s own bound, not the market’s. It is reset by each apply_market rather than accumulated, so it stops two of this account’s orders double-spending one observation’s size and claims nothing about anyone else’s.

§Which TimeInForce this venue honours

An unsupported one is rejected, never quietly treated as good-until-cancelled: that would leave an order working that its sender asked to have cancelled.

TimeInForceOrderKind::LimitOrderKind::Market
GoodUntilCancelled { post_only: false }rests, or fills if marketablefills
GoodUntilCancelled { post_only: true }rests, or cancels if marketablerejected
ImmediateOrCancel / FillOrKillfills if marketable, else cancelsfills
GoodTillDate { expiry }rests until expiry, then expiresfills
GoodUntilEndOfDayrejectedfills
AtOpen / AtCloserejectedrejected

A market order works only on arrival, which honours every time in force that bounds how long an order works — so most of the table is moot for one. (It fills in full wherever the book has the size; what it cannot fill is cancelled, since it has no limit price to rest at.) The two exceptions are real: post_only on a market order is a promise never to take liquidity, which is all a market order does; and AtOpen/AtClose say when an order executes rather than how long it lasts, so honouring them needs a session calendar this venue has not got. Filling one on arrival would be a wrong fill rather than an ignored flag.

§A deadline is swept, not scheduled

This venue has no timer. A GoodTillDate order is retired when a driver next calls advance_time or apply_market, whichever comes first, and the sweep spans every instrument rather than only the one that ticked. A deadline falling after the last such call is never reached at all — see advance_time for what that means for a caller. A driver that keeps a timeline of its own can advance the clock to each next_deadline as it falls, as SimRunner does, so that a deadline is reached at its own instant.

A deadline is an unconditional cutoff. An order reaching it is retired even if the very tick that reached it would have crossed it, and an order that arrives already past its deadline is retired without resting and without trading — otherwise whether an expired order traded would depend on where the book happened to be.

§A client order id names one working order at a time

An open request whose ClientOrderId already names an order resting here is rejected with ApiError::DuplicateClientOrderId, whatever its kind, and the resting order is untouched: its price, queue position, deadline and reservation stay as they were. Only an order that rests holds its id; one that fills or is cancelled on arrival never does.

Once an order has ended its id is free, and the next order under it replaces what this venue remembers of the earlier one. orders_ended, the rejection of a cancel and account_snapshot therefore report the latest order under each id.

The check follows the static ones on kind, time in force and instrument, so a malformed request is reported as malformed, and comes before anything that touches the ledger.

§Reserved balances

The ledger distinguishes held from spendable: free is what an order may draw on, total is what the account holds, and the difference is held against something. An initial_state copied from a live account with margin reserved is therefore usable as configured — it was rejected outright while every order filled on arrival and the ledger could not represent the state.

Every arrival is one commitment against the ledger (AccountState::commit) and therefore one balance restatement, whichever of the three shapes it has: an order that fills outright settles and holds nothing; one that rests holds and settles nothing; one the book fills in part does both at once, settling what traded and holding against the remainder it leaves resting. An order that rests emits one more restatement later, when the market reaches it and the hold is settled — never an intermediate balance the account did not hold. A configured reservation is carried through untouched: settling lowers total by the settled amount and leaves the rest held.

An order is funded whole or refused whole. The two legs of a part-filled arrival are asked for together, so an account that cannot cover both has the order rejected with nothing moved. It is not filled for the part it could afford: choosing that would be this venue substituting a disposition for the one the sender asked for. Note the consequence, which is easy to be surprised by — a capped order costs more than the same order filling outright, because its remainder is held at the order’s own limit while the fill struck a better price, so an order can be refused for a size the book was willing to sell it.

For spot, the reservation is exactly what the fill will settle, not a conservative over-estimate: both come from one computation at the order’s own limit and its own liquidity side. A conservative reservation would have to be released and re-debited on the fill, producing two or three restatements for one fill and reporting balances the account never held, while Balance::used misreported for the order’s whole life.

A resting CFD order holds only what its fill would cost net of what the fill pays back, computed against the position when it rests. An order that only reduces a position therefore holds nothing. The position can move before the order fills — another order may close what this one was going to — so a CFD fill is costed again when it fills: its hold is released and the fill settled afresh, still as one balance restatement. If the account can no longer afford it, the order is cancelled rather than filled, as a venue re-checking margin at fill time would cancel it. That includes an order a configured initial_state seeded, which for an ordinary spot order would be a panic.

A resting spot order holds what it pays with, and nothing for a fee that comes out of what it receives. A fill whose fee exceeds what it receives takes the excess from the asset it receives, so it is costed afresh when it fills, as a CFD order is, and cancelled, seeded or not, if that asset cannot cover the excess.

Fields§

§exchange: ExchangeId§fee_model: FeeModelConfig§spot_fee_asset: SpotFeeAsset

Which asset a spot fill’s fee is charged in. See # How a spot fill is accounted.

§account: AccountState

Implementations§

Source§

impl SimulatedVenue

Source

pub fn new( config: &MockExecutionConfig, instruments: FnvHashMap<InstrumentNameExchange, Instrument<ExchangeId, AssetNameExchange>>, ) -> Self

A venue with no market feed, which prices each market order from the snapshot its own request carries and accepts no OrderKind::Limit.

See VenueRegime::RequestPriced, and new_market_driven for the regime that accepts limits.

§Panics
  • If initial_state holds an open CFD position with no entry price: see the caller obligations on SimulatedVenue.
  • If initial_state lists one client order id more than once among its open and cancelled orders: see DuplicateSeededOrder.
Source

pub fn new_market_driven( config: &MockExecutionConfig, instruments: FnvHashMap<InstrumentNameExchange, Instrument<ExchangeId, AssetNameExchange>>, ) -> Self

A venue whose driver feeds apply_market, so limit orders are accepted and a resting one is matched against that feed.

Constructing one and then never calling apply_market produces a venue that accepts limit orders and can never match them, which is the state the regime exists to prevent — so this constructor is a driver’s assertion that it will feed the venue, not a configuration knob.

See VenueRegime::MarketDriven.

§Panics
  • If initial_state holds an open CFD position with no entry price: see the caller obligations on SimulatedVenue.
  • If initial_state lists one client order id more than once among its open and cancelled orders: see DuplicateSeededOrder.
Source

pub fn with_holding_costs(self, models: Vec<Arc<dyn HoldingCostModel>>) -> Self

This venue, charging each open position what models say holding it costs.

Each model is asked for its boundaries on every instrument this venue holds a position in, and charges the position held across each one, as described on HoldingCostModel. Only a cash-settled position is charged: a spot holding is a balance on this venue, not a position. See the type’s # Holding costs for when a charge is made and how it is reported.

Source

pub fn with_margin_interest(self, model: Arc<dyn MarginInterestModel>) -> Self

This venue, charging interest on its spot margin loans as model says.

Each loan is charged when it is taken, on the amount lent, and at each of the model’s boundaries while the account owes principal in its asset, on that principal, as described on MarginInterestModel. See the type’s # Spot margin for how a charge is reported.

§Panics

If this venue has no MockExecutionConfig::spot_margin: a cash account takes no loans, so a model given to one would silently charge nothing. Or if model breaks its contract with a boundary not after the instant it was asked from, for a loan the account already owes.

Source

pub fn with_fill_model(self, model: Arc<dyn FillModel>) -> Self

This venue, pricing each taker fill with model rather than the configured fill_model.

The way to plug in a model of your own, such as a size-aware impact model reading FillContext::quantity. The configured slippage still applies to whatever price it returns. See FillModel for what an implementation must uphold.

The model is not part of the configuration, so a serialised configuration no longer says what priced the fills: its fill_model is unused. A venue that MockExchange::new drives is built from its configuration alone, so it takes no custom model.

Source

pub fn with_shortability(self, provider: Arc<dyn ShortabilityProvider>) -> Self

This venue, refusing a CFD short that provider does not allow.

Asked on the arrival of every order that would open or increase a short, as described in the type’s # Locates and the short-sale restriction.

Source

pub fn next_deadline(&self) -> Option<DateTime<Utc>>

The next instant at which this venue has something to do of its own accord: an open order reaching its deadline, a holding-cost boundary of a position it holds, or an interest boundary of a loan it made.

For a driver with a timeline of its own, such as SimRunner, which moves the clock to this instant so that an expiry or a charge happens when it is due rather than when the next market event or request happens to arrive. None when nothing is due.

Recompute it after anything that moves this venue: an order, a fill, or the clock. A holding-cost or interest boundary is reported only once the venue’s clock has first moved, since that is where charging starts.

Source

pub fn regime(&self) -> VenueRegime

Which price source this venue has, and so which order kinds it accepts.

Source

pub fn advance_time( &mut self, time_exchange: DateTime<Utc>, ) -> Vec<UnindexedAccountEvent> ⓘ

Sets the instant this venue stamps on everything it produces from now on, retiring any order whose deadline that instant has reached.

The caller owns the latency model: a driver simulating a network delay passes an instant already offset by it. The venue itself models no delay.

§Deadlines are swept from here and from apply_market, never on a

clock of their own A TimeInForce::GoodTillDate order must stop working at the instant it says, not at whenever the next market tick happens to arrive – otherwise a cancel sent after the nominal deadline would succeed against an order that should already have been retired, and an instrument that stops ticking would hold its expired orders open indefinitely. So both of this venue’s inputs sweep.

The sweep is not scoped to any instrument: a deadline is a property of the clock, not of a book. An order on a quiet instrument is retired by activity anywhere on the venue.

§The residual limitation, stated plainly

This venue has no timer. Nothing retires an order until a driver next advances the clock or feeds a market, so a deadline falling after the last such call is never reached at all. A driver that stops driving leaves orders working past their deadline, and that is a property of the simulation rather than something a caller can configure away. A driver that wants each deadline reached at its own instant advances the clock to next_deadline.

§Returns the expiries it caused, which a driver must deliver

Per retired order the events are [balance, order] – the released reservation, then the terminal Expired snapshot – or [order] alone for an order this venue never took a reservation for, exactly as cancel_order reports one.

#[must_use] because a driver that advances the clock and drops the result has silently eaten the expiries, leaving its client holding orders the venue no longer has and a balance it has already released.

§And the holding costs and interest it reached

Every holding-cost and interest boundary between the previous instant and this one is charged first, in time order, each as [balance, cash flow] stamped at its boundary — see the type’s # Holding costs and # Spot margin. They precede the expiries, which are stamped at time_exchange.

§And the liquidation it caused

Last, a spot margin account configured with a SpotMarginLiquidation is checked at time_exchange, and the notices, cancels, forced trades and fee that check causes follow everything else, stamped there too.

§The clock never moves back

An instant earlier than the latest this venue has reached, through this call or through apply_market, is taken as that latest instant. It charges nothing again, and the balances it restamps and whatever a request after it produces are stamped no earlier than what this venue has already reported. A consumer keeping the latest stamp of each balance would otherwise drop such a restatement as older than one it holds.

The venue clamps the instant itself, so this holds whichever driver calls it, including one stamping requests from a wall clock that stepped back. A request that arrives behind a later market tick is therefore stamped at that tick. apply_market clamps its tick the same way.

§A forward jump charges every boundary it crosses

However far one call moves the clock, each boundary in between is charged once, at its own stamp, on what was held and owed across it: a live paper venue whose host resumes after hours asleep charges every hour it slept through. That is what a venue that kept running would have charged, since funding and interest fall due at a boundary whether or not anyone is watching. Each is valued at the market as it stood before the jump, since this venue saw none in between.

§Panics

If a configured HoldingCostModel or MarginInterestModel breaks its contract: a boundary not after the instant it was asked from, or a negative interest.

Source

pub fn time_exchange(&self) -> DateTime<Utc>

The instant advance_time last set, which stamps what a request produces. The Unix epoch until advance_time is first called.

Source

pub fn apply_market( &mut self, instrument: &InstrumentNameExchange, observation: MarketObservation, time_exchange: DateTime<Utc>, ) -> Vec<UnindexedAccountEvent> ⓘ

Records this venue’s own view of instrument as of time_exchange, from observation.

Its snapshot replaces whatever was held: it is a complete view of the instrument, not a partial update, so a field that is None means the feed supplies no such price rather than “unchanged”. Whoever calls this owns the state machine that folds a stream of market events into that view.

§The depth replaces what is left, it does not add to it

MarketDepth is the size on offer as of this observation, and it is stored as the size still available — drawn down by every taker fill struck against it until the next call replaces it. That is the only thing that stops two market orders arriving between two observations from each taking the whole of a size that was displayed once: reading a stored size does not consume it, so without the draw-down both would see it undiminished.

It bounds this account’s own aggression within one observation and claims nothing more. It is not queue position against the rest of the market, which stays unmodelled — see the type’s # What matching does not model.

A feed with no sizes passes MarketDepth::UNKNOWN, which caps nothing. See MarketDepth for why that, and not “nothing is available”, is what absent size means.

§Not every driver supplies this

A venue only has market state if something feeds it one. SimRunner does, routing each source market event to the venues trading that instrument before the Engine sees it, and so does MockExchange::new_market_driven, from a live feed. A request-priced venue, which MockExchange::new drives, is fed nothing, since a backtest feeding it the market alongside requests would re-create the look-ahead hazard that motivated the split, so it reports market as None forever. That difference is a property of the regime, not an accident of wiring.

§What it prices

Everything this venue fills. It is the market a resting order is matched against, the one a limit order’s marketability is judged on, and — on a MarketDriven venue, which is the only kind that has one — the one a market order is priced from. See the type’s # How an order is priced.

So feeding this is not optional for a MarketDriven venue: an instrument it has never been fed cannot fill a market order, and says so rather than reaching for the requester’s snapshot.

§Returns the fills it caused, which a driver must deliver

Applying a market is what makes a resting order fill, so this returns every account event those fills produced, in the order they must be delivered — the same obligation VenueOutcome carries for a request. Per filled order the events are [balance, trade, order]: the trade precedes the terminal order snapshot, because a consumer routing a fill to a position needs the order still to be live when the trade arrives.

They are preceded by the holding costs of every boundary since the clock last moved and the expiries this tick reached, exactly as advance_time reports them. The costs are valued at the market as it stood before this tick replaced it. They are followed by what the margin check at the end of the tick causes, as for advance_time, valued at the market this tick set.

§A bar releases the orders held for it

Under MarketOrderTiming::NextBar, an observation carrying a bar releases every order held on instrument, earliest first, stamped time_exchange: each market order filled at the bar’s reference price as a taker, and each limit order held on a stale market decided as if it arrived to that price. Their events follow the expiries and precede the resting fills, since a held order trades at the start of the bar and a resting one is crossed during it. fills_ahead_of says beforehand whether an observation will release anything this way.

Under StaleMarketPolicy::Wait, a bar that is not fresh releases nothing, and cancels the immediate-or-cancel and fill-or-kill orders held for it.

§A fresh observation releases the orders waiting for one

Under StaleMarketPolicy::Wait with MarketOrderTiming::OnArrival, a fresh observation releases every order that arrived on a stale instrument, earliest first, each decided as if it had arrived just after this observation, stamped time_exchange: a market order fills, and a limit order trades what the market crosses and rests the rest at its limit. Their events follow the resting fills, which the observation crossed first, so a limit order resting on release is not crossed by the observation that released it.

§An observation that is not fresh crosses no resting order

Under StaleMarketPolicy::Wait, an observation that is not fresh still moves the price the venue holds, but fills no resting order, however far it moves: it is not evidence that anything traded there.

#[must_use] because a driver that applies the market and drops the result has silently eaten the fills, leaving its client holding an order the venue no longer has.

§The clock never moves back

A time_exchange earlier than the latest instant this venue has reached, through this call or through advance_time, is taken as that latest instant, as advance_time takes one. It charges nothing again, and everything the tick stamps is stamped no earlier than what this venue has already reported: the market it stores, the instant it counts as fresh from, the expiries it sweeps, and the fills it causes with the balances they restate. A consumer keeping the latest stamp of each balance would otherwise drop a fill’s restatement as older than one it holds.

The venue clamps the instant itself, so this holds whichever driver calls it. A driver that feeds its ticks in order, never behind an instant it has already advanced to, sees no difference.

§Panics

If a configured HoldingCostModel or MarginInterestModel breaks its contract: a boundary not after the instant it was asked from, or a negative interest.

Source

pub fn fills_ahead_of( &self, instrument: &InstrumentNameExchange, observation: &MarketObservation, ) -> bool

Whether applying observation to instrument releases orders held for its bar, whose fills a driver must deliver ahead of the observation itself — see MarketOrderTiming::NextBar.

Asked before apply_market, since applying the observation is what empties the hold. false for a fill released by a fresh observation under StaleMarketPolicy::Wait alone, which follows its observation as a resting fill does.

Source

pub fn expire_held( &mut self, time_exchange: DateTime<Utc>, ) -> Vec<UnindexedAccountEvent> ⓘ

Retires every order still held as expired, filled nothing, stamped time_exchange: the data has ended before the bar or the fresh observation it was waiting for.

For a driver at the end of its data, so that no order it accepted is left unanswered. Per order the events are [balance, order], the released hold then the terminal Expired snapshot, as advance_time reports a deadline it reached. Pass the last instant of the run: this moves no clock and charges no holding cost.

§Panics

If the configured MarginInterestModel breaks its contract with a boundary not after the instant it was asked from, when the venue next looks for one after a loan is repaid.

Source

pub fn instruments( &self, ) -> &FnvHashMap<InstrumentNameExchange, Instrument<ExchangeId, AssetNameExchange>>

Every instrument this venue trades, keyed by its exchange name, exactly as it was constructed with.

Read only: the set of instruments is fixed for the venue’s life. To trade a different set, construct a new venue.

Source

pub fn instrument( &self, name: &InstrumentNameExchange, ) -> Option<&Instrument<ExchangeId, AssetNameExchange>>

The instrument this venue trades under name, or None if it trades none by that name.

Source

pub fn market( &self, instrument: &InstrumentNameExchange, ) -> Option<&VenueInstrumentMarket>

This venue’s view of instrument, or None if nothing has fed it one.

Source

pub fn order_sequence(&self) -> u64

Number of orders this venue has booked.

Also how far the next OrderId is past the first one this venue minted, which is 0 unless the seeded account state carried a decimal id: then the first is one past the highest such id, so a minted id never repeats a seeded one.

Counts every order it gave an id to, including those that retired without ever trading. It is not a count of trades — one order can print more than once, and trade ids are minted from a sequence of their own.

Source

pub fn balances( &self, assets: &[AssetNameExchange], ) -> Vec<AssetBalance<AssetNameExchange>>

Source

pub fn borrow_capacity( &self, instrument: &InstrumentNameExchange, side: Side, ) -> Result<BorrowCapacity, UnindexedApiError>

How much more this account can borrow now for an order on instrument on side: what BorrowCapacityClient::fetch_borrow_capacity asks a simulated venue.

A sell borrows instrument’s base asset, a buy its quote asset, which the result names. borrowable_now is the lesser of what the leverage limit and the asset’s borrow cap leave, as SpotMarginConfig’s # How much it lends says. It is zero when that is below the asset’s minimum borrow, which no loan may be under, and while a liquidation is under way, when this venue lends nothing. account_limit is the asset’s cap, unset when it has none.

It is the room to borrow alone. The account’s free balance of the asset is not added, though an order spends that before it borrows. Resting orders need no adjustment: what they borrowed when placed is in the debt, and what they hold is still in the equity.

§Valued without an order’s market

The query carries no market snapshot, so only the markets this venue holds value the account. When they cannot value the asset, or any balance the account holds or owes, borrowable_now is None, unknown, where an order, which brings its own market, may still be lent. A cap that leaves nothing, or less than the minimum borrow, still makes it zero. A RequestPriced venue holds no market, so it can answer only for an account holding nothing but its valuation asset, asked about that asset.

§Errors

ApiError::InstrumentInvalid for an instrument this venue does not trade, and for one it never lends against: every instrument on a cash account (no spot margin configuration), and a cash-settled one on a margin account.

Source

pub fn orders_open( &self, instruments: &[InstrumentNameExchange], ) -> Vec<Order<ExchangeId, InstrumentNameExchange, Open>>

Source

pub fn orders_ended( &self, orders: &[UnindexedOrderKey], ) -> Vec<UnindexedInactiveOrder> ⓘ

How each of orders ended, for those that have: filled, cancelled (including the unfilled remainder of a market order) or expired at its own deadline.

An order still open is omitted, and so is one this venue never held, including one it rejected on arrival, whose rejection was the answer to its open request. An empty orders returns nothing, not every ended order.

Each order is found by its client order id, which this venue keys every order on, and is returned under the key it was asked for. A key naming a different instrument from the one the order traded is treated as unknown, and an id asked about more than once is reported once, under the first key that finds it.

Source

pub fn trades( &self, time_since: DateTime<Utc>, ) -> Vec<Trade<AssetNameExchange, InstrumentNameExchange>>

Source

pub fn open_order( &mut self, request: OrderRequestOpen<ExchangeId, InstrumentNameExchange>, ) -> OpenOutcome

Books an open against the ledger and reports everything it owes the client.

The venue books its own fill: the Trade is acknowledged into the ledger here, so a driver cannot forget to. A filled open reports [balance, trade] – [paid, received, trade] for spot, which moves two assets – mirroring a real venue where the trade is booked before the order can be reported FullyFilled; an open that rests reports [balance] alone – the reservation now held against it – and no trade, because nothing traded.

A Market order has no limit price, and any price it carries is ignored, so the venue prices it from whichever market its VenueRegime gives it – its own on a MarketDriven venue, and RequestOpen::market on a RequestPriced one. A Limit order is always judged and priced against this venue’s own market; see the type’s # How an order is priced.

An order whose quantity is zero or negative is rejected, moving nothing, whatever the market: with an ApiError::OrderRejected naming the quantity, unless its kind or time in force is refused first.

§Panics

If a configured HoldingCostModel or MarginInterestModel breaks its contract: a boundary not after the instant it was asked from, or a negative interest.

Source

pub fn cancel_order( &mut self, request: OrderRequestCancel<ExchangeId, InstrumentNameExchange>, ) -> CancelOutcome

Takes a resting order off the book, releasing whatever is held against it.

Returns [balance] and a Cancelled carrying the quantity filled before the cancel arrived – which is whatever the order had done: nothing for one that rested untouched, the taker part for one the book could only partly fill on arrival, and whatever a configured initial_state seeded, carried through rather than added to. An order the venue holds nothing against releases nothing and reports no balance; see this type’s note on initial_state.

§A cancel that finds nothing says which nothing it found

A cancel racing its own order’s fill is the reason this distinguishes three cases rather than rejecting flatly. With a non-zero to_venue latency the fill can win, and ApiError::OrderAlreadyFullyFilled is what tells the caller to reconcile against the fill rather than retry. An order cancelled twice gets ApiError::OrderAlreadyCancelled, and only an id this venue has never booked is rejected as unknown.

§Panics

If the configured MarginInterestModel breaks its contract with a boundary not after the instant it was asked from, when the venue next looks for one after a loan is repaid.

Source

pub fn account_snapshot(&self) -> UnindexedAccountSnapshot

Source

pub fn validate_order_kind_supported( &self, order_kind: OrderKind, ) -> Result<(), UnindexedOrderError>

Whether this venue accepts order_kind, which depends on its VenueRegime.

OrderKind::Market is always accepted. OrderKind::Limit needs somewhere to rest and something to be matched against, so it is accepted only by a MarketDriven venue. Every other kind is rejected outright.

§Errors

Returns ApiError::OrderRejected naming the kind, and – for a limit order refused by the regime – why the venue cannot hold one.

Source

pub fn find_instrument_data( &self, instrument: &InstrumentNameExchange, ) -> Result<&Instrument<ExchangeId, AssetNameExchange>, UnindexedApiError>

Trait Implementations§

Source§

impl Debug for SimulatedVenue

Source§

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

Formats the value using the given formatter. 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
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

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.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

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

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

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

impl<T> JsonSchemaMaybe for T

Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows 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
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows 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
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

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

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

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .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
where Self: BorrowMut<B>, B: ?Sized,

Calls .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
where Self: AsRef<R>, R: ?Sized,

Calls .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
where Self: AsMut<R>, R: ?Sized,

Calls .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
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

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

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more