Class LastLookExecution
- All Implemented Interfaces:
ExecutionModel
Bar-level model of the hold window: the order arrives at the bar open and the LP watches the intra-bar move.
Signal-bar handling: when worked through
ExecutionAwareBacktester, the parent is created at the signal
bar's CLOSE — so on that first bar there is no hold window left to
observe, and filling at that bar's open would credit a price from
before the signal existed (intrabar time travel). The model therefore
HOLDS on the parent's signal bar (no fill, no reject counted — it is
pure latency, the LP has seen nothing yet); the first real attempt is
the next bar, whose open is the price standing when the order actually
arrived. Direct calls without onParentOrder(com.quantfinlib.orderbook.Side, long, int) keep the plain
arrives-at-the-open semantics.
- Move in the taker's favor beyond
rejectThresholdBps(price rising on a buy — adverse to the LP who would sell) → reject; the parent quantity carries to the next bar, exactly like real requote-and-chase. - Otherwise → full fill at the open plus the taker pays
spreadBpshalf-spread (all-in price).
The asymmetry here is deliberate as a taker's worst-case model:
it simulates the adverse LP behavior the FX Global Code prohibits but a
taker must still budget for. The Code-compliant maker-side mechanism —
symmetric rejection in both directions — is
com.quantfinlib.trading.LastLookGate; when calibrating this
model's threshold from an LP's published (symmetric) disclosures, note
those statistics count rejects in both directions while this model
rejects only one. Rejection statistics are exposed for TCA — a live desk
watches its reject rate per LP for exactly this pattern.
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionExecutes up torequestedQtyon this bar.longAccepted fills (parent-bar attempts, not shares).voidonParentOrder(Side side, long totalQuantity, int signalIndex) Notification that a new parent order has been created (entry or exit).doublereferencePrice(BarSeries series, int index) The price this model's fills are anchored to on the given bar — the engine budgets entry requests ascash / (referencePrice * (1 + worstCaseCostFraction())).longLast-look rejections — the number a real desk tracks per LP.doubleReject rate across all attempts, 0 when nothing was attempted.doubleUpper bound on this model's all-in cost as a fraction ofExecutionModel.referencePrice(com.quantfinlib.core.BarSeries, int)(spread + fees + slippage).
-
Constructor Details
-
LastLookExecution
public LastLookExecution(double spreadBps, double rejectThresholdBps) - Parameters:
spreadBps- half-spread paid on accepted fillsrejectThresholdBps- intra-bar move (bps, in the taker's favor) beyond which the LP rejects
-
-
Method Details
-
onParentOrder
Description copied from interface:ExecutionModelNotification that a new parent order has been created (entry or exit). Stateful models (e.g.IcebergExecution) reset per-parent state here.- Specified by:
onParentOrderin interfaceExecutionModel
-
referencePrice
Description copied from interface:ExecutionModelThe price this model's fills are anchored to on the given bar — the engine budgets entry requests ascash / (referencePrice * (1 + worstCaseCostFraction())). Default: the bar close. A model that fills off a different price point (e.g.LastLookExecutionfills at the OPEN) must override this, or a gap between close and its actual anchor lets a fully-filled request overdraw cash.- Specified by:
referencePricein interfaceExecutionModel
-
worstCaseCostFraction
public double worstCaseCostFraction()Description copied from interface:ExecutionModelUpper bound on this model's all-in cost as a fraction ofExecutionModel.referencePrice(com.quantfinlib.core.BarSeries, int)(spread + fees + slippage). The engine uses it to size entries so that a fully-filled parent can never overdraw cash — a model whose fills can cost more thanreferencePrice * (1 + worstCaseCostFraction())MUST override one or both methods, or the backtest silently trades on margin it doesn't have. Wrappers must DELEGATE both to the model that actually prices the fills. Default 1%.- Specified by:
worstCaseCostFractionin interfaceExecutionModel
-
execute
Description copied from interface:ExecutionModelExecutes up torequestedQtyon this bar. Must never fill more than requested; may fill less (or nothing) — the remainder is retried on subsequent bars.- Specified by:
executein interfaceExecutionModel
-
fillCount
public long fillCount()Accepted fills (parent-bar attempts, not shares). -
rejectCount
public long rejectCount()Last-look rejections — the number a real desk tracks per LP. -
rejectRate
public double rejectRate()Reject rate across all attempts, 0 when nothing was attempted.
-