PineForge v0.13.1-379-g9b50973
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
native_host.hpp
Go to the documentation of this file.
1#pragma once
2
8
9#include <cstddef>
10#include <cstdint>
11#include <limits>
12#include <optional>
13#include <string>
14#include <string_view>
15#include <type_traits>
16#include <variant>
17#include <vector>
18
19namespace pineforge {
20inline namespace engine_script_run_v18 {
21
22/// Where a host stands. Read it off native_state().kind; nothing else reports it.
23/// Unconfigured is a fresh host, Ready a staged spec, Running a consumed begin
24/// (with NativeRunPhase saying which driving), Completed a finished run whose
25/// lots and live requests stay visible but not actionable, and Failed a durable
26/// first failure: discard the host, replay on a fresh instance, never reconfigure
27/// in place. Pinned by tests/test_native_host_repairs.cpp.
28enum class NativeLifecycleKind : std::uint8_t {
30 Ready = 1,
33 Failed = 4,
34};
35
36/// Which driving is Running: a batch run(), a stream's internal warmup, or its
37/// realtime leg. Folded into native_continuation_hash() on purpose — a consumer
38/// mid-warmup and one mid-realtime are not interchangeable continuations — which
39/// is why a batch and a stream over identical bars record different per-bar
40/// broker-state hashes while booking identical trades.
41enum class NativeRunPhase : std::uint8_t {
42 Batch = 0,
43 Warmup = 1,
45};
46
47/// How a Completed run ended: a batch reached the last bar, or a stream was
48/// ended. Reporting only; the book, the report and every hash are what the run
49/// left.
50enum class NativeCompletion : std::uint8_t {
53};
54
55/// The durable first failure of a run, in NativeFailure::code. InvalidSpecification
56/// is a refused spec at configure, Contract a lifecycle misuse (a second
57/// configure, a run number at or under the high water), Preflight a bar array the
58/// driver refused, UnsupportedSource a source-only setter or command on a bare
59/// host, CallbackException a host callback that threw or a C callback that
60/// returned non-zero, and Aborted a cooperative abort. The rest are internal
61/// exhaustion states with no rollback promise. Set once and latched: later run /
62/// stream_* / configure_native calls refuse.
78
79/// Which operation was in flight when the failure latched — the second half of
80/// "what went wrong", beside NativeFailureCode. Presentation only; the kernel
81/// takes no decision on it.
82enum class NativeFailureOperation : std::uint16_t {
83 None = 0,
85 Begin = 2,
87 Input = 4,
91 Stream = 8,
92};
93
94/// In-run failure references. Identifiers belong to NativeFailed.spec->identity;
95/// they never carry a second RunIdentity string. Kind is a bit-union of the
96/// typed alternatives below (Cause=1, Recipient=2, Cursor=4).
107
108/// The event ordinal a failure was caused by, 0 when absent. Populated only when
109/// native_failure_has_cause() is true for the context's kind.
111 std::uint64_t ordinal = 0; // 0 = absent
112};
113
114/// The request incarnation a failure was addressed to, 0 when absent. Populated
115/// only when native_failure_has_recipient() is true.
117 std::uint64_t incarnation = 0; // 0 = absent
118};
119
120/// Where on the modeled path a failure happened: the driver point's coordinate and
121/// its interpolation position t. Populated only when native_failure_has_cursor()
122/// is true.
125 double t = 0.0;
126};
127
128/// The three in-run facts a failure may carry, tagged by kind. Copy and move are
129/// allocation-free — this is what a failed host reports from inside a callback —
130/// and the predicates below say which alternatives are populated rather than
131/// asking a caller to decode the bit-union itself.
138
139/// The bit-union under NativeFailureContextKind: Cause=1, Recipient=2, Cursor=4.
140/// Prefer the three predicates below to testing these bits by hand.
141constexpr std::uint8_t native_failure_context_bits(NativeFailureContextKind kind) noexcept {
142 return static_cast<std::uint8_t>(kind);
143}
144/// Whether a context of this kind populates its NativeInRunCause.
146 return (native_failure_context_bits(kind) & 1u) != 0;
147}
148/// Whether a context of this kind populates its NativeInRunRecipient.
150 return (native_failure_context_bits(kind) & 2u) != 0;
151}
152/// Whether a context of this kind populates its NativeInRunCursor.
154 return (native_failure_context_bits(kind) & 4u) != 0;
155}
156/// Whether this context populates its NativeInRunCause. The overload a reader of
157/// native_state().failure.context wants.
158constexpr bool native_failure_has_cause(const NativeFailureContext& context) noexcept {
159 return native_failure_has_cause(context.kind);
160}
161/// Whether this context populates its NativeInRunRecipient.
162constexpr bool native_failure_has_recipient(const NativeFailureContext& context) noexcept {
163 return native_failure_has_recipient(context.kind);
164}
165/// Whether this context populates its NativeInRunCursor.
166constexpr bool native_failure_has_cursor(const NativeFailureContext& context) noexcept {
167 return native_failure_has_cursor(context.kind);
168}
169
170/// The kind that says exactly these three alternatives are populated.
172 bool cause, bool recipient, bool cursor) noexcept {
173 return static_cast<NativeFailureContextKind>(
174 (cause ? 1u : 0u) | (recipient ? 2u : 0u) | (cursor ? 4u : 0u));
175}
176
177/// A context carrying one causing event ordinal. A zero ordinal is "absent" and
178/// yields the None kind rather than a Cause with nothing in it.
179inline NativeFailureContext native_failure_cause(std::uint64_t ordinal) noexcept {
180 NativeFailureContext context;
181 if (ordinal == 0) return context;
183 context.cause.ordinal = ordinal;
184 return context;
185}
186/// A context carrying one addressed request incarnation. A zero incarnation is
187/// "absent", as above.
188inline NativeFailureContext native_failure_recipient(std::uint64_t incarnation) noexcept {
189 NativeFailureContext context;
190 if (incarnation == 0) return context;
192 context.recipient.incarnation = incarnation;
193 return context;
194}
195/// A context carrying one path cursor. A cursor is always meaningful, so there is
196/// no absent spelling.
197inline NativeFailureContext native_failure_cursor(NativeCoordinate point, double t = 0.0) noexcept {
198 NativeFailureContext context;
200 context.cursor.point = point;
201 context.cursor.t = t;
202 return context;
203}
204
205/// Copies only ordinals/incarnation/cursor scalars. Foreign run identities are
206/// dropped rather than stored under the failed spec's identity.
208 const native_order::RunIdentity& run,
209 const native_order::EventId* cause,
210 const native_order::RequestHandle* recipient,
211 const native_order::MatchCursor* cursor) noexcept {
212 NativeFailureContext context;
213 bool has_cause = false;
214 bool has_recipient = false;
215 bool has_cursor = false;
216 if (cause != nullptr && cause->ordinal != 0 && cause->run == run) {
217 has_cause = true;
218 context.cause.ordinal = cause->ordinal;
219 }
220 if (recipient != nullptr && recipient->incarnation != 0 && recipient->run == run) {
221 has_recipient = true;
222 context.recipient.incarnation = recipient->incarnation;
223 }
224 if (cursor != nullptr) {
225 has_cursor = true;
226 context.cursor.point = cursor->point;
227 context.cursor.t = cursor->t;
228 }
229 context.kind = native_failure_context_kind(has_cause, has_recipient, has_cursor);
230 return context;
231}
232
233/// The durable record native_state().failure answers: the code, the operation it
234/// happened in, an optional event ordinal and discriminator, and the
235/// allocation-free context. last_error() is presentation text beside it and is
236/// never the authority. Copy and move do not allocate.
244
245/// The NativeLifecycle alternatives, one per NativeLifecycleKind. Ready, Running
246/// and Completed own a copy of the staged spec; Failed owns it only when configure
247/// got that far. NativeStateView is the flattened read a host uses; this variant is
248/// the consumer's own storage.
253struct NativeFailed { std::optional<NativeRunSpec> spec; NativeFailure failure; };
254
255/// The lifecycle as one value. Exhaustive over the five alternatives above.
258
259/// The RunIdentity the failed spec carried, or nullptr when configure failed
260/// before staging one. This is how a caller names the run a failure belongs to
261/// without the failure carrying a second identity string of its own.
263 const NativeFailed& failed) noexcept {
264 return failed.spec ? &failed.spec->identity : nullptr;
265}
266
267static_assert(std::is_trivially_copyable_v<NativeInRunCause>);
268static_assert(std::is_trivially_copyable_v<NativeInRunRecipient>);
269static_assert(std::is_trivially_copyable_v<NativeInRunCursor>);
270static_assert(std::is_trivially_copyable_v<NativeFailureContext>);
271static_assert(std::is_trivially_copyable_v<NativeFailure>);
272static_assert(std::is_nothrow_copy_constructible_v<NativeFailure>);
273static_assert(std::is_nothrow_copy_assignable_v<NativeFailure>);
274static_assert(std::is_nothrow_move_constructible_v<NativeFailed>);
275static_assert(std::is_nothrow_move_assignable_v<NativeFailed>);
276
277/// The flattened run state native_state() answers: the lifecycle kind, a borrowed
278/// pointer to the staged spec (nullptr when Unconfigured), the phase, how a
279/// Completed run ended, the durable failure, the consumed run-number high water
280/// and the monotonic decision floor. The spec pointer is valid until the next
281/// configure or begin. C spelling: strategy_native_state_v1.
291
292/// The book as one aggregate: signed units, the volume-weighted average entry
293/// price and the number of open physical lots. physical_position() answers it;
294/// native_open_lots(mark) is the same book lot by lot. C spelling:
295/// strategy_native_position_v1.
297 double signed_units = 0.0;
298 double average_price = 0.0;
299 std::size_t lot_count = 0;
300};
301
302/// Owning value row for one open physical lot, copied at query time by
303/// native_open_lots(mark) — the lot-by-lot view of the same book
304/// physical_position() aggregates. Every field is what the book already
305/// holds; nothing is computed that the kernel does not already keep.
306///
307/// Identity: `ordinal` is the lot's position in the book (oldest first),
308/// `entry_incarnation` the request record whose fill opened it (never
309/// reused; 0 only for a legacy synthetic lot) and `cycle` the position cycle
310/// the lot belongs to (the value BindOpening / BindOpenings name).
311///
312/// Booking: `entry_label` / `entry_comment` are the opening request's own,
313/// `entry_time_ms` / `entry_bar_index` its fill point, `entry_price` the
314/// booked price, `signed_units` the lot's remaining units (> 0 long, < 0
315/// short) and `entry_commission` the entry fee still on the lot in account
316/// currency — a partial realization takes its share with it.
317///
318/// Marked: `unrealized_pnl` is the lot's own term of native_marked_equity(mark)
319/// — the move from `entry_price` to `mark`, in account currency, less
320/// `entry_commission` — so the marked equity is the realized balance plus the
321/// sum of these rows. `favorable_excursion` / `adverse_excursion` are the
322/// largest moves for and against the lot the kernel has sampled along the
323/// delivered path, in account currency, with `mark` itself folded in; both
324/// are gross of fees and never negative. A host that owns lot excursions
325/// (owns_lot_excursions) keeps its own sampler, so for that run the kernel's
326/// two fields fold `mark` alone. A NaN `mark` keeps every booking fact,
327/// leaves `unrealized_pnl` NaN and folds nothing into the excursions.
329 std::size_t ordinal = 0;
330 std::uint64_t entry_incarnation = 0;
331 std::int64_t cycle = 0;
332 native_order::Side side = native_order::Side::Long;
333 std::string entry_label;
334 std::string entry_comment;
335 std::int64_t entry_time_ms = 0;
337 double entry_price = 0.0;
338 double signed_units = 0.0;
339 double entry_commission = 0.0;
340 double mark = std::numeric_limits<double>::quiet_NaN();
341 double unrealized_pnl = std::numeric_limits<double>::quiet_NaN();
343 double adverse_excursion = 0.0;
344};
345
346/// The account row that follows an applied execution in the event history: the
347/// shared ordinal, the effective time, the marked equity, the realized balance and
348/// the signed book after it. One per applied execution, so an applied event and
349/// its observation share an ordinal — advance an event cursor by the last returned
350/// ordinal, never mid-group.
352 uint64_t ordinal = 0;
353 int64_t effective_time_ms = 0;
354 double marked_equity = 0.0;
355 double realized_balance = 0.0;
356 double signed_units = 0.0;
357};
358
359/// Which of NativeMarketEvent's three alternatives is populated.
360enum class NativeEventKind : std::uint8_t {
364};
365
366/// One owning row of native_events(after_ordinal): a command event, a driver point
367/// or an account observation, tagged by kind. Later commands and the next run's
368/// reset do not invalidate a row already returned. C spelling:
369/// strategy_native_events_v1, which flattens the same rows into one tagged POD.
372 uint64_t ordinal = 0;
373 std::optional<native_order::CommandEvent> command;
374 std::optional<NativeDriverPoint> driver;
375 std::optional<NativeAccountObservation> account;
376};
377
378/// Whether a setup call applied its value or refused it. Failed leaves engine
379/// storage untouched.
380enum class NativeSetupStatus : std::uint8_t { Applied = 0, Failed = 1 };
381
382/// What configure_native answers: the status and, on refusal, the first error
383/// field validate_native_run_spec found. A refusal changes nothing — there is no
384/// partial apply.
389
390/// What configure_native_fx_curve answers: the status and, on refusal, the curve
391/// validation with the index of the first bad point. A refusal leaves the staged
392/// curve as it was.
397
398/// Which price a current execution settles at: the active callback's quote as
399/// presented, or that quote on the instrument's nearest tick. Configured
400/// directional slippage applies once either way.
401enum class NativeCurrentPriceRule : std::uint8_t { AsPresented = 0, NearestTick = 1 };
402/// Where a price came from: the callback's own market decision point, or the
403/// execution it is anchored to. A current execution inherits its cause's quote, so
404/// a chain does not compound slippage.
405enum class NativeCurrentQuoteKind : std::uint8_t { MarketDecision = 0, ExecutionAnchor = 1 };
406
407/// Read-only owning-value facts for one candidate. The host is already the
408/// engine, so no engine handle or prepared execution token is exposed here.
436
437/// Ephemeral factual view of one prepared execution before any physical effect.
454
455/// The host is consulted before generic opening-margin admission. Admit keeps
456/// the native default gate; AdmitWithHostMargin lets a host that owns the
457/// source-compatible margin rule take responsibility for that one check.
458/// Proceed remains an alias for the v7 spelling used by existing C++ callers.
459enum class NativePrecommitVerdict : std::uint8_t {
460 Admit = 0,
464};
465
466/// Ephemeral factual view of one kernel-issued liquidation before its units
467/// are fixed. `position` is the physical book being liquidated, `mark` the
468/// sizing price the kernel measured the breach at, `equity` the marked equity
469/// there and `required` the maintenance requirement of the whole position at
470/// that same mark. A host that answers with a value owns the slice quantity.
478
479/// Which kernel check point is about to test the maintenance requirement.
480/// BarOpen is the script bar's open, after on_native_bar_open and before the
481/// bar's own matching; AfterApplied is the re-arm that follows a point's
482/// applied fills, which is the kernel's only mid-path check; Calculation is
483/// the script calculation of a CalculationOnly model; FxRoll is a step of the
484/// run's declared NativeFxCurve: the first driver point the account converts
485/// at a different rate than the point before it, offered immediately before
486/// that point is matched, with the price where the walk left it -- the
487/// requirement moved though no price did. A run that declares no curve has no
488/// such point, and a CalculationOnly model, which measures at its calculation
489/// alone, is not offered it. These are the kernel's own points: a broker model
490/// that checks somewhere else is a host policy, expressed by suppressing the
491/// points it does not share.
492enum class NativeMarginCheckKind : std::uint32_t {
497};
498
499/// Ephemeral factual view of one kernel check point, offered to the host
500/// before the check runs. `mark` is the price the kernel would measure the
501/// breach at; the modeled path phase is `cursor.point.path_phase`.
505 double mark = 0.0;
507 /// Whether the model already holds a liquidation resting from an earlier
508 /// admitted point. A host that suppresses points -- and therefore owns
509 /// when a slice sized on a book that has since shrunk is re-sized -- needs
510 /// to tell "re-size the live slice" from "take a new one" apart. The
511 /// default host admits every point and never reads this.
513};
514
515/// Ephemeral factual view of the numbers the kernel is about to compare, at
516/// one check point, BEFORE the breach test. `equity` is the marked equity on
517/// the model's own basis and `required` the kernel's maintenance requirement
518/// of the whole position at `mark`; both are exactly what the kernel would
519/// compare if the host answered nullopt.
528
529/// The host's answer to one requirement view. `required` and `equity` replace
530/// the kernel's two numbers for this check point only -- they are a broker's
531/// money rule (a rounded requirement, a fee-adjusted equity), never a second
532/// account. `force_breach` makes the kernel proceed past `required > equity`
533/// even when the answered numbers do not meet it; the sizing policy and
534/// resolve_margin_call_units then decide the slice as usual.
536 double required = 0.0;
537 double equity = 0.0;
538 bool force_breach = false;
539};
540
541/// Which trigger of an anchored leg the owner's fill is about to supply.
542enum class NativeAnchoredTrigger : std::uint8_t {
543 Limit = 0,
544 Stop = 1,
546};
547
548/// Ephemeral read-only facts of one anchored-leg materialization (L7b),
549/// offered to the host exactly once, before the ArmedEvent is built. `owner`
550/// is the request whose fill arms the leg, `owner_applied_ordinal` that fill's
551/// ExecutionAppliedEvent, `owner_lot_incarnation` the lot it opened,
552/// `owner_fill_price` its resolved price and `owner_cursor` its cursor. `leg`
553/// is the anchored request, `leg_side` the side it trades on (a closing leg
554/// trades against the lot the fill opened), `trigger` which trigger receives
555/// the level, `offset` the anchor's resolved offset in price units,
556/// `price_tick` the run's tick (0 when the run has none) and `kernel_level`
557/// the level the kernel would install: fill + offset after the anchor's own
558/// rounding. A host that answers with a value owns the installed level; the
559/// kernel's representability check still applies.
573
574/// The run's generic risk ledger (L9), as the kernel holds it. Every field is
575/// zero / absent for a run that declares no NativeRunSpec::risk.
576///
577/// `blocked` is whether openings are refused right now, and `reason` names the
578/// limit that did it — a drawdown or consecutive-loss-days block lasts to the
579/// end of the run, the two intraday blocks to the end of their own day.
580/// `day_ordinal` is the risk day the ledger is on (the spec's own day basis),
581/// `fills_today` the applied fills counted in it, `consecutive_loss_days` the
582/// streak of days that closed with a realized loss, `peak_equity` the running
583/// peak of the marked equity and `day_open_equity` the equity the current day
584/// opened at. `has_day` is false before the first evaluated point.
586 bool blocked = false;
587 std::optional<native_order::RiskLimitKind> reason;
588 bool has_day = false;
589 std::int64_t day_ordinal = 0;
590 std::uint64_t fills_today = 0;
591 std::uint32_t consecutive_loss_days = 0;
592 double peak_equity = 0.0;
593 double day_open_equity = 0.0;
594};
595
596/// What current_execution_point() answers inside a callback: the point's decision
597/// context, its price, which quote that price is, and the ordinal the quote came
598/// from. nullopt outside a decision point. C spelling: pf_native_decision_v1's
599/// price and quote_kind, on every callback.
606
607/// Read-only projection of a live generic Trail request. Before its arm is
608/// reached, activated is false and the numeric/ordinal fields are zero. Once
609/// armed, best_price and current_level are the exact raw matcher values and
610/// activation_ordinal identifies the TrailArm event that began tracking.
612 bool activated = false;
613 double best_price = 0.0;
614 double current_level = 0.0;
615 std::uint64_t activation_ordinal = 0;
616};
617
618/// Owning value row for one live request, copied at query time. The
619/// definition is the accepted (and, for an anchored leg, already materialized)
620/// request; remaining is what is left to execute; trigger_state is where the
621/// request's own trigger has reached. Later commands do not invalidate a row
622/// that was already returned.
628
629/// Which of a request's two free-text identity fields a bulk predicate reads.
630/// Both are host text the kernel only copies and compares: Comment is the
631/// established cancel_where selector and keeps value 0, Label is the field a
632/// host that names its orders puts its own id in.
633enum class NativeRequestField : std::uint8_t { Comment = 0, Label = 1 };
634
635/// Why a current-execution command cannot be consumed here. Every value is a fact
636/// about the command or the phase, never a host verdict: the host's own veto is
637/// validate_execution_precommit. strategy_native_execute_current_v1 answers the
638/// same verdicts in C.
644
645/// A synchronous execution of one request accepted or replaced in this very
646/// callback: a target handle and a price rule, and nothing else. Membership,
647/// quantity and ownership come from the request; this command cannot supply
648/// another selection, a saved cursor, a price, a ticket or a prepared financial
649/// plan. Pinned by tests/test_native_current_execution.cpp.
654
655/// Recomputed observations, never an apply token. Readiness is the financial
656/// pre-source preparation boundary, independent of account projection validity
657/// and excluding opening admission and late counter/lifecycle checks.
659 std::optional<NativeCurrentRefusal> refusal;
660 std::optional<execution::Status> settlement_readiness;
662 std::vector<double> closed_row_pnl;
663 std::optional<native_order::MatchRejectReason> terms_rejection;
664 std::optional<native_order::CancelReason> terms_cancellation;
665};
666
667/// What execute_current answers: a refusal, or the applied outcome. Execution
668/// revalidates, so a preview obtained earlier is an observation and never an
669/// apply token.
673
674/// Borrowed begin-call facts. The bar/input/syminfo/override pointers expire when
675/// prepare_native_begin returns; retained configuration must copy them by
676/// value (for example into NativeRunSpec::intrabar).
678 const Bar* bars = nullptr;
679 int n = 0;
680 std::string input_tf;
681 std::string script_tf;
682 bool bar_magnifier = false;
688 const InputsMap* inputs = nullptr;
689 /// The rich run overload's symbol metadata is borrowed only for this
690 /// callback. A provider that uses it must copy the fields it needs into
691 /// its retained NativeRunSpec/staged metadata before returning.
692 const SymInfo* syminfo = nullptr;
693 const void* overrides_opaque = nullptr;
694 bool is_stream = false;
695 int warmup_n = 0;
696 /// Which public overload began the run: the bare run(bars, n) lifecycle
697 /// (true) or a timeframe-aware / magnified / stream begin (false). A host
698 /// may keep lifecycle surfaces (for example its higher-timeframe series
699 /// evaluators) off for the bare overload; empty timeframes alone do not
700 /// identify it, they only request auto-detection.
701 bool simple_run = false;
702};
703
704/// Accepted input facts presented before the generic consumer aggregates the
705/// bar into its script interval or evaluates any matching point. This is not a
706/// source-language callback: native hosts may observe raw input cadence through
707/// it without taking ownership of matching or aggregation.
714
715/// One accepted realtime print before native matching at its current decision
716/// point. The Bar is a value presentation of that print (O=H=L=C=price,
717/// volume=print quantity, timestamp=print timestamp); no source-language
718/// policy is embedded here. Sequence zero retains the public TradeTick
719/// sentinel meaning “provider did not supply a sequence”.
724
725/// One completed higher-timeframe bucket of a declared subscription
726/// (NativeRunSpec::subscriptions), presented before the calculation of the
727/// input bar it is delivered on.
728///
729/// `subscription` indexes NativeRunSpec::subscriptions. `interval` is the
730/// calendar span of the bucket's FIRST contributing input bar, read through the
731/// run's own session calendar; it is left zeroed when that lookup has no answer.
732/// For a series built from the auxiliary feed (NativeSeriesSource::AuxiliaryFeed)
733/// "contributing bar" reads "contributing FEED bar" here, while `delivered_at_ms`
734/// stays the accepted input bar the delivery rides on.
735/// `completion` is Confirmed when the bucket completed on its own last
736/// contributing input bar and LazyComplete when the next period's first input
737/// closed it. `delivered_at_ms` is the timestamp of the input bar the delivery
738/// rides on: the bucket's last contributing bar under lookahead_off and its
739/// first under lookahead_on.
741 std::size_t subscription = 0;
743 NativeCompletionKind completion = NativeCompletionKind::Confirmed;
744 std::int64_t delivered_at_ms = 0;
745};
746
747/// Why the kernel is asking the host to calculate. BarClose is the script
748/// bar's own calculation and is delivered for every run, whatever the spec's
749/// NativeCalculationTrigger is: every calculation is routed through
750/// on_native_recalculate, whose default forwards to on_native_bar, so a host
751/// that only implements on_native_bar sees exactly what it saw before.
752/// OrderFill is one recalculation at the cursor of an applied execution
753/// (NativeCalculationTrigger::BarCloseAndFills and above) and carries that
754/// event as its cause. Tick is one recalculation at a modeled path point or
755/// an observed print (NativeCalculationTrigger::EveryModeledPoint). SubBar is
756/// reserved: a lower-timeframe sub-bar has its own hook, on_native_sub_bar,
757/// and is never delivered through on_native_recalculate.
758enum class NativeCalculationReason : std::uint8_t {
761 Tick = 2,
763};
764
765// Most-derived native strategy host. Binds NativeExecutionConsumer in the
766// protected engine constructor. Noncopyable and nonmovable. Lives in the
767// same inline engine epoch as BacktestEngine so old-header/new-library
768// linkage cannot resolve an unversioned constructor against a different
769// base layout.
770#define PINEFORGE_HAS_NATIVE_STRATEGY_HOST_V18 1
771/// The public native host: an abstract subclass of BacktestEngine with no
772/// PineScript on it. Subclass it, override on_native_bar (the only pure-virtual),
773/// configure_native(spec), then run() or the stream_* family. Noncopyable and
774/// nonmovable: the constructor binds the native consumer, and there is no
775/// attach/replace switch. Do not override the inherited on_bar (it is final) and
776/// do not write protected engine fields. The whole surface, feature by feature, is
777/// docs/pages/native-engine.md; a worked host is examples/native/hello_kernel.cpp.
779public:
786
787 /// The engine's own bar entry, taken over by the native consumer and sealed. A
788 /// native host calculates in on_native_bar; this override is what makes overriding
789 /// on_bar a compile error rather than a silently dead callback.
790 void on_bar(const Bar& bar) final;
791
792 /// Offered once per begin, before the run starts, with the begin's own arguments —
793 /// the bars, the timeframe literals, the magnifier settings, and the rich
794 /// overload's InputsMap / SymInfo / opaque overrides. A provider that reads them
795 /// must copy what it needs before returning: the views expire with the call. The
796 /// default does nothing, which is every bare host. No C spelling: a C run is
797 /// declared up front with strategy_configure_native_ext_v1.
798 virtual void prepare_native_begin(const NativeBeginArgs&) {}
799 /// Offered once per successful begin, after the reset and before any bar. It is
800 /// the one place declare_timeframe_subscriptions and declare_auxiliary_feed are
801 /// legal, and the kernel registers the declared series only after it returns — so
802 /// a host that registers evaluators of its own here keeps them. native_series_bar
803 /// answers nullopt for every index inside it, because nothing is registered yet.
804 /// C spelling: pf_native_callbacks_v1::on_run_begin.
805 virtual void on_native_run_begin() {}
806 /// Called once for every accepted confirmed input bar, before that bar is
807 /// aggregated or matched. It has no current execution point.
808 virtual void on_native_input(const Bar&, const NativeInputContext&) {}
809 /// Called once for every accepted realtime print, before matching at that
810 /// point. inspect_current_execution/execute_current are legal here.
811 virtual void on_native_tick(const Bar&, const NativeTickContext&) {}
812 /// One completed bucket of a declared higher-timeframe subscription,
813 /// delivered on an accepted input bar before that input is aggregated,
814 /// matched or calculated. Never called for a spec whose `subscriptions`
815 /// are empty. native_series_bar() already answers with this bar here.
816 /// A series built from the auxiliary feed may deliver several buckets on
817 /// one input, oldest first.
819 /// Precedes the matching pass at the script bar's open decision point.
820 /// inspect_current_execution/execute_current are legal in this hook.
821 virtual void on_native_bar_open(const Bar&, const NativeDecisionContext&) {}
822 /// The current decision point remains valid for the complete callback.
823 /// A host may therefore execute a command after its own script-body work
824 /// returns, before the consumer advances beyond this calculation point.
825 virtual void on_native_bar(const Bar& bar, const NativeDecisionContext& context) = 0;
826
827 /// EVERY calculation of the run arrives here first, including the script
828 /// bar's own close calculation (reason BarClose, cause nullptr), whose
829 /// default forwarding keeps on_native_bar the complete contract for a host
830 /// that never opts into another cadence.
831 ///
832 /// reason OrderFill: one recalculation at an applied execution's cursor,
833 /// driven from the applied-notification drain after that event's
834 /// on_native_applied and bounded by
835 /// NativeRunSpec::max_recalculations_per_point. `cause` is that event and
836 /// is valid only for this call. reason Tick: one recalculation at a
837 /// modeled path point or an observed print, with a null cause.
838 ///
839 /// `bar` is the bar the calculation is about: the script bar under
840 /// delivery in batch, the print's value bar for a stream Tick. It is the
841 /// COMPLETE script bar even mid-path; current_partial_bar() is the
842 /// lookahead-free bar so far at this cursor. Commands and
843 /// execute_current are legal here exactly as in on_native_applied.
844 virtual void on_native_recalculate(const Bar& bar, const NativeDecisionContext& ctx,
847 (void)reason;
848 (void)cause;
849 on_native_bar(bar, ctx);
850 }
851
852 /// One completed lower-timeframe sub-bar of an IntrabarPath::lower_tf
853 /// path, delivered after that sub-bar's whole matching path and before the
854 /// next sub-bar's. Never called for a run without a retained lower feed:
855 /// a synthesized path and a plain confirmed bar have no sub-bars of their
856 /// own. The decision point is the sub-bar's last modeled point, so
857 /// commands and execute_current are legal and a request born here follows
858 /// the ordinary birth rule.
859 virtual void on_native_sub_bar(const Bar& sub, const NativeDecisionContext& ctx) {
860 (void)sub;
861 (void)ctx;
862 }
863
864 /// The calculate-on-fill hook: offered once per applied execution, FIFO, after the
865 /// account record and the group/owner/dependency drains. Commands are legal here,
866 /// and a request born here is eligible on the remaining path suffix of a
867 /// continuous segment. Event values stay valid for the call. Throwing latches
868 /// CallbackException. C spelling: pf_native_callbacks_v1::on_applied.
871
872 /// The fill-terms hook, consulted at every matching candidate. Return a resolved
873 /// price, and units for an unresolved HostSized request; the default is the
874 /// identity price with no units, which is what every bare host wants. Answering no
875 /// units for a HostSized candidate is MatchRejectReason::TermsUnresolved. It does
876 /// not supply a second matcher, book or cash path. C spelling: the units half
877 /// only, pf_native_callbacks_v1::on_close_units.
879 const NativeExecutionTermsFacts& facts) const {
880 return {facts.default_resolved_price, std::nullopt,
881 native_order::OpeningShape::Transact};
882 }
883 /// The last gate before a physical effect, offered once per Applied-ready attempt
884 /// and never during inspect_current_execution. Proceed takes the kernel's own
885 /// path, Refuse records a nonfinancial HostPrecommit rejection, and
886 /// AdmitWithHostMargin hands that one opening margin check to the host. The
887 /// default proceeds. No C spelling: its view is a deep C++ aggregate; a C host
888 /// gates an opening with PF_NATIVE_INTENT_SIZED's placement-time admission or
889 /// with on_margin_requirement.
894
895 /// Consulted at EVERY kernel check point, BEFORE the breach test, exactly
896 /// as resolve_execution_terms is consulted before a fill is booked. The
897 /// kernel still owns the mechanism -- the level solve, the check points,
898 /// the kernel-originated request, its Superseded re-pricing, the receipt
899 /// and on_native_margin_call; this hook only supplies the two numbers that
900 /// comparison is made of, where brokers legitimately differ. nullopt keeps
901 /// the kernel's own. A host may therefore raise a call the kernel would
902 /// not make (a rounded requirement, a fee-adjusted equity, force_breach)
903 /// or veto one it would (answer numbers that do not breach). Source-
904 /// language money quirks -- TradingView's ten-significant-digit rounding,
905 /// for one -- belong in this hook, never in the run spec.
906 virtual std::optional<NativeMarginDecision> resolve_margin_requirement(
907 const NativeMarginRequirementView&) const {
908 return std::nullopt;
909 }
910 /// Consulted at each kernel check point before anything is evaluated. A
911 /// host whose broker model does not check there answers false, and the
912 /// kernel does not evaluate, re-arm or withdraw at that point: the margin
913 /// state is left exactly as the last admitted check point left it.
914 /// Every point the run's check mode reaches is offered, including the ones
915 /// where the book is flat or the live side has no maintenance fraction --
916 /// withdrawing a resting liquidation is part of the check. CalculationOnly
917 /// rests nothing, so it offers only the points it could act on.
918 virtual bool margin_check_allowed(const NativeMarginCheckPoint&) const {
919 return true;
920 }
921 /// The kernel's own liquidation sizing, offered to the host before the
922 /// reduction rests. Returning nullopt keeps the run spec's sizing policy;
923 /// a returned value is clamped into (0, held] and wins over it. It keeps
924 /// the last word on units, including over a forced breach.
925 virtual std::optional<double> resolve_margin_call_units(
926 const NativeMarginCallView&) const {
927 return std::nullopt;
928 }
929 /// A kernel-issued liquidation that filled. It is delivered after the
930 /// ordinary on_native_applied for the same fill, with the same cursor.
932
933 /// The level an anchored leg (FromOwnerFill) is about to be armed at,
934 /// offered to the host exactly once per materialization, before the
935 /// ArmedEvent is built. Returning nullopt installs the kernel level
936 /// (fill + offset after the anchor's rounding); a returned value is the
937 /// level to install, still subject to the kernel's representability
938 /// check, whose failure is the existing PreparationError path. The
939 /// mechanism (the arm, the once-only materialization, the ArmedEvent,
940 /// matching) stays the kernel's; only the policy of where the level sits
941 /// is the host's, exactly as resolve_execution_terms owns the fill price.
942 virtual std::optional<double> resolve_anchored_level(
943 const NativeAnchoredLevelView&) const {
944 return std::nullopt;
945 }
946
947 /// RULING A48 — the ONE generic per-lot excursion capability. A host that
948 /// returns true here takes ownership of every open lot's favorable/adverse
949 /// excursion: the consumer stops sampling excursion at matched trigger
950 /// prices and the closing row takes both magnitudes from
951 /// closed_lot_excursion(). Facts in, magnitudes out; nothing about the
952 /// host's price model crosses the boundary in either direction.
953 virtual bool owns_lot_excursions() const noexcept { return false; }
954 /// The per-lot excursion a host owns, consulted for every closing row once
955 /// owns_lot_excursions() answers true. Returning the declined value gives that row
956 /// the kernel's own zero magnitudes, because nothing was sampled for it — the
957 /// consumer stops sampling at matched trigger prices for the whole run as soon as
958 /// ownership is declared. C spelling: pf_native_callbacks_v1::on_lot_excursion,
959 /// where installing the hook IS declaring ownership.
961 const ClosedLotExcursionFacts&) const {
962 return {};
963 }
964
965 /// The bar so far at the current cursor, folded from the modeled points
966 /// this script bar has already presented: open of its first point,
967 /// running high/low, close at the cursor. Volume is the activity actually
968 /// consumed so far — the completed lower-timeframe sub-bars of an
969 /// intrabar path, or the prints of an observed stream — and stays 0 for a
970 /// modeled path with no intrabar volume of its own. Valid in the bar-open,
971 /// applied, tick, sub-bar and recalculation callbacks; nullopt outside a
972 /// path walk, including in the bar's own close calculation, where the host
973 /// already holds the complete bar.
974 std::optional<Bar> current_partial_bar() const;
975 /// How many recalculations the kernel has driven this run, and how many it
976 /// suppressed because a point had already spent its
977 /// max_recalculations_per_point budget. Observation only.
978 std::uint64_t native_recalculation_count() const;
979 /// How many recalculations max_recalculations_per_point dropped at their matching
980 /// point. The executions themselves were still applied and still delivered to
981 /// on_native_applied; only the calculation they would have driven was skipped. C
982 /// spelling: strategy_native_recalculations_v1, beside the driven count.
983 std::uint64_t native_recalculations_skipped() const;
984
985 /// The active callback's quote and calendar-derived decision context, as an owning
986 /// value. nullopt outside a decision point. C spelling:
987 /// pf_native_decision_v1::price / ::quote_kind, on every callback.
988 std::optional<NativeCurrentPointView> current_execution_point() const;
989 /// Where one live trail's own trigger has reached: activated, the running best,
990 /// the current level and the ordinal it activated at. nullopt when the handle is
991 /// not a live trail. C spelling: strategy_native_trail_state_v1, with
992 /// PF_NATIVE_ABSENT for the empty. Pinned by tests/test_native_trail_state_l5k.cpp.
993 std::optional<NativeTrailState> trail_state(
994 const native_order::RequestHandle& target) const;
995 /// A read-only preview of a current execution: the settlement readiness, any typed
996 /// refusal or terms outcome, and the ordered closed-row P&L for an Applied-ready
997 /// command. It is never an apply token — execute_current revalidates, and editing
998 /// the preview cannot authorize or alter a fill. No C spelling:
999 /// strategy_native_execute_current_v1 answers the same verdicts.
1001 /// Consume, synchronously, a request accepted or replaced in this very callback.
1002 /// Answers a refusal or the applied outcome; applied effects and relationship
1003 /// drains are visible before the call returns. Only the named target is consumed.
1004 /// C spelling: strategy_native_execute_current_v1.
1006
1007 /// The latest completed bucket delivered for a declared subscription, or
1008 /// nullopt before its first delivery / for an unknown index. Legal inside
1009 /// every native callback, including on_native_timeframe_bar itself. A
1010 /// gaps = true series answers nullopt again on every input bar it
1011 /// delivered nothing on.
1012 std::optional<Bar> native_series_bar(std::size_t subscription) const;
1013
1014 /// Declare this run's higher-timeframe series from inside
1015 /// on_native_run_begin, for a host whose series are known only to its own
1016 /// begin-time registration. The list REPLACES the staged spec's
1017 /// `subscriptions`, and the kernel registers from the staged spec after
1018 /// this callback returns, so a host's own registration cannot erase the
1019 /// kernel's and the run's continuation identity folds what actually ran.
1020 /// Legal only inside on_native_run_begin: anywhere else, and for a list
1021 /// this run's input timeframe would refuse (the same validation
1022 /// configure_native applies), it stages nothing, changes nothing and
1023 /// answers false. Not virtual: the host calls the kernel here, never the
1024 /// other way round.
1026 std::vector<NativeTimeframeSubscription> subscriptions);
1027
1028 /// The same begin-time hook for NativeRunSpec::auxiliary_feed: the feed
1029 /// REPLACES the staged spec's own (nullopt withdraws it), and the kernel
1030 /// registers from the staged spec after on_native_run_begin returns. It is
1031 /// judged together with the series staged at that moment, so a host that
1032 /// names both here declares the feed first and its AuxiliaryFeed series
1033 /// second. Legal only inside on_native_run_begin: anywhere else, for a
1034 /// feed this run's input timeframe would refuse, and for one that would
1035 /// leave a staged AuxiliaryFeed series without its bars, it changes
1036 /// nothing and answers false. Not virtual.
1037 bool declare_auxiliary_feed(std::optional<NativeAuxiliaryFeed> feed);
1038
1039 /// A realtime stream's later bars of its declared auxiliary feed. They
1040 /// join the feed behind every bar it holds and ride on the next accepted
1041 /// input whose period they opened before — the routing rule a batch of the
1042 /// same bars applies. Legal between stream inputs on a Realtime run that
1043 /// declared a feed. Refused by name, changing nothing and without failing
1044 /// the host: bars out of order or not after the feed's last bar, a bar
1045 /// with invalid OHLCV, and a bar that opened inside an input period
1046 /// already accepted (its slice is closed; no batch could build that
1047 /// series). Calling it from inside a callback is the contract failure
1048 /// every reentrant stream input is.
1049 bool append_auxiliary_bars(const Bar* bars, std::size_t n);
1050
1051 /// The only setup call. Copies the candidate spec, normalizes it and stages it
1052 /// atomically: Unconfigured or a Completed run with a larger run number becomes
1053 /// Ready, and a refusal is Failed with no partial apply. Calling it again while
1054 /// Ready is a Contract failure — use a new host to change unconsumed setup. C
1055 /// spelling: strategy_configure_native_v1 / strategy_configure_native_ext_v1.
1057 /// Stage the run's immutable FX epoch, legal only while Ready. Parallel
1058 /// timestamp/rate arrays of equal length, strictly increasing timestamps, finite
1059 /// positive rates; an empty curve clears it and restores the scalar account_fx
1060 /// fallback. Refused with WrongPhase once the run is Running. C spelling:
1061 /// strategy_configure_native_fx_curve_v1.
1063 /// The whole run state as one owning read. The only observation of the lifecycle
1064 /// and of the durable failure; last_error() is presentation text beside it. C
1065 /// spelling: strategy_native_state_v1.
1067
1068 /// Accept one complete request. Answers Accepted with a timeline ordinal and a
1069 /// RequestHandle, or Rejected with a rejection ordinal and a reason. Acceptance is
1070 /// not a fill: no lot and no fee moves here. Legal from a native callback in
1071 /// Batch/Warmup/Realtime, or between realtime inputs on the same thread. C
1072 /// spelling: strategy_native_submit_v1.
1074 /// Replace one live request: validate first, then retire that incarnation and
1075 /// birth a successor with a new handle, a new priority and a predecessor link. A
1076 /// ReplaceRejected leaves the target live; a same-run absent, replaced or terminal
1077 /// handle is NotWorking, a foreign or malformed one InvalidHandle. Every outcome
1078 /// is an event, and no outcome moves a lot. C spelling:
1079 /// strategy_native_replace_v1.
1081 const native_order::Request& request);
1082 /// The deliberately narrow market-default convenience: the same acceptance path as
1083 /// submit, but it REFUSES a nondefault trigger, capacity, owner or group rather
1084 /// than dropping it. No C spelling, by design — the same request is
1085 /// strategy_native_submit_v1 with PF_NATIVE_TRIGGER_MARKET and a zero-filled
1086 /// struct.
1088 /// The same market-default convenience for a replace; see submit_market.
1090 const native_order::Request& request);
1091 /// Replace with options. ReplaceOptions{retain_trigger_state = true} carries the
1092 /// predecessor's live trigger state — a tracking trail's best, an already active
1093 /// stop — into the successor instead of restarting it. Predecessor and successor
1094 /// must hold the same trigger alternative, and a retained best must still produce
1095 /// a representable level; otherwise the replacement is rejected and the
1096 /// predecessor stays live.
1098 const native_order::Request& request,
1100 /// Cancel one live request by handle. A live request becomes Cancelled; a same-run
1101 /// absent, replaced or already terminal handle is NotWorking; a foreign or
1102 /// malformed handle is InvalidHandle. Every outcome is an event. C spelling:
1103 /// strategy_native_cancel_v1.
1105 /// Working-book snapshot and bulk cancellation. cancel_all returns how
1106 /// many requests left the book (one CancelledEvent each, dependants
1107 /// included); cancel_where cancels exactly the live requests carrying that
1108 /// comment and returns how many of them it cancelled.
1109 ///
1110 /// The second form chooses which identity field the text is compared
1111 /// against: NativeRequestField::Comment is the one-argument form, and
1112 /// NativeRequestField::Label addresses the requests by their label, the
1113 /// one-call equivalent of cancelling every order a host issued under its
1114 /// own id. Neither form indexes anything: both walk the live book once,
1115 /// like cancel_all, so a label may be reused, replaced or left empty
1116 /// without any bookkeeping to keep in step. Text that matches nothing is
1117 /// not a command.
1118 std::vector<NativeWorkingRequest> native_working_requests() const;
1119 /// Withdraw every live request, dependants of a cancelled owner included, and
1120 /// answer how many left the book. One CancelledEvent per request. C spelling:
1121 /// strategy_native_cancel_all_v1.
1122 std::size_t cancel_all();
1123 /// Withdraw exactly the live requests carrying this comment, and answer how many
1124 /// of those left the book. An unknown comment is not a command. The comment is
1125 /// free host text the kernel only copies and compares, and it is not indexed: this
1126 /// walks the live book once, exactly as cancel_all does.
1127 std::size_t cancel_where(std::string_view comment);
1128 /// The same predicate over either identity text. NativeRequestField::Label
1129 /// addresses requests by Request::label — the one call that withdraws every live
1130 /// request a host issued under one of its own order ids. "" is the text a request
1131 /// carrying no such field matches. C spelling:
1132 /// strategy_native_cancel_where_v1(host, text, PF_NATIVE_FIELD_LABEL).
1133 std::size_t cancel_where(std::string_view text, NativeRequestField field);
1134 /// Open a roster a later close can bind to. The handle is what a
1135 /// native_order::BindCohort owner names. C spelling:
1136 /// strategy_native_cohort_open_v1.
1138 /// Enroll one accepted opening's handle in a roster. C spelling:
1139 /// strategy_native_cohort_add_v1.
1141 /// Take one opening back off a roster. C spelling:
1142 /// strategy_native_cohort_remove_v1.
1144
1145 /// The book as one aggregate, copied out. C spelling:
1146 /// strategy_native_position_v1.
1148 /// The book lot by lot, oldest first, marked at `mark`: one NativeOpenLot
1149 /// per physical lot (physical_position().lot_count rows), copied at query
1150 /// time. Legal wherever physical_position() is; observation only, it
1151 /// moves no fill, no hash and no row.
1152 std::vector<NativeOpenLot> native_open_lots(double mark) const;
1153 /// The account's equity marked at this price: the realized balance plus every open
1154 /// lot's own fee-net term, which is exactly what native_open_lots(mark) sums. It
1155 /// moves nothing. C spelling: strategy_native_marked_equity_v1.
1156 double native_marked_equity(double mark) const;
1157 /// The units a kernel-sized intent resolves to under this run's spec at a
1158 /// sizing price, a marked equity and an account FX rate -- as a pure query.
1159 /// units = cash / (price * point_value * fx), cash the basis value or
1160 /// fraction * equity, net of the percent fee reserve when the intent asks
1161 /// for it, then the intent's grid policy: this is the same function the
1162 /// kernel runs at acceptance (SizeTime::AtAcceptance) and at the candidate
1163 /// (AtMatch), so a host that gates a command on its quantity before it
1164 /// submits reads the number here rather than keeping its own copy of the
1165 /// conversion. nullopt when the run is not configured or the basis is
1166 /// unresolvable at those inputs (non-positive money or denominator, a
1167 /// below-one-step quotient under SnapToGrid). Observation only: it moves
1168 /// nothing and freezes nothing.
1169 std::optional<double> native_sized_units(const native_order::Sized& sized, double price,
1170 double equity, double fx) const;
1171 /// The price at which the marked equity falls below the run's maintenance
1172 /// requirement for the live position's side. nullopt when the run declares
1173 /// no margin model, the side has no maintenance fraction, the book is flat,
1174 /// or no finite price solves the breach (a long at full maintenance).
1175 std::optional<double> native_liquidation_price() const;
1176 /// The run's generic risk ledger. Every field is its zero for a run that
1177 /// declares no NativeRunSpec::risk; observation only, it moves nothing.
1179 /// Owning snapshots copied at query time. Later commands/reset do not
1180 /// invalidate already returned values.
1181 std::vector<NativeMarketEvent> native_events(uint64_t after_ordinal) const;
1182 /// The run's monotonic decision floor in epoch milliseconds — the same value
1183 /// NativeStateView::decision_floor_ms carries. Every request's birth is compared
1184 /// against this floor, not against a later lowered clock, and a refused preflight
1185 /// does not raise it. C spelling: pf_native_state_v1::decision_floor_ms.
1186 int64_t native_decision_floor() const;
1187 /// The highest run_number this host has consumed. It lives OUTSIDE per-run reset,
1188 /// so a later run on the same host needs a strictly larger number; a fresh host
1189 /// reads 0 and may therefore replay the same logical run. C spelling:
1190 /// pf_native_state_v1::consumed_high_water.
1192 /// The consumer's continuation identity: what a stream resumes against. It folds
1193 /// the run's resolved timezone identity, whose zone file paths are absolute paths
1194 /// on the machine that ran it, so the same spec over the same bars hashes
1195 /// differently on two hosts even for "UTC". Compare it between runs in ONE
1196 /// process; never pin it as a constant. For a portable constant use
1197 /// native_run_spec_digest(spec). C spelling:
1198 /// strategy_native_continuation_hash_v1.
1200
1202};
1203
1204} // inline namespace engine_script_run_v18
1205} // namespace pineforge
NativeFxCurveSetupResult configure_native_fx_curve(const NativeFxCurve &curve)
Stage the run's immutable FX epoch, legal only while Ready.
std::optional< Bar > current_partial_bar() const
The bar so far at the current cursor, folded from the modeled points this script bar has already pres...
virtual void prepare_native_begin(const NativeBeginArgs &)
Offered once per begin, before the run starts, with the begin's own arguments — the bars,...
virtual void on_native_input(const Bar &, const NativeInputContext &)
Called once for every accepted confirmed input bar, before that bar is aggregated or matched.
int64_t native_decision_floor() const
The run's monotonic decision floor in epoch milliseconds — the same value NativeStateView::decision_f...
std::size_t cancel_where(std::string_view comment)
Withdraw exactly the live requests carrying this comment, and answer how many of those left the book.
std::vector< NativeWorkingRequest > native_working_requests() const
Working-book snapshot and bulk cancellation.
double native_marked_equity(double mark) const
The account's equity marked at this price: the realized balance plus every open lot's own fee-net ter...
bool declare_timeframe_subscriptions(std::vector< NativeTimeframeSubscription > subscriptions)
Declare this run's higher-timeframe series from inside on_native_run_begin, for a host whose series a...
virtual std::optional< double > resolve_margin_call_units(const NativeMarginCallView &) const
The kernel's own liquidation sizing, offered to the host before the reduction rests.
NativeStrategyHost & operator=(const NativeStrategyHost &)=delete
NativeCurrentExecutionResult execute_current(const NativeCurrentExecution &)
Consume, synchronously, a request accepted or replaced in this very callback.
void on_bar(const Bar &bar) final
The engine's own bar entry, taken over by the native consumer and sealed.
native_order::CancelResult cancel(const native_order::RequestHandle &target)
Cancel one live request by handle.
std::optional< double > native_sized_units(const native_order::Sized &sized, double price, double equity, double fx) const
The units a kernel-sized intent resolves to under this run's spec at a sizing price,...
virtual bool margin_check_allowed(const NativeMarginCheckPoint &) const
Consulted at each kernel check point before anything is evaluated.
virtual void on_native_bar(const Bar &bar, const NativeDecisionContext &context)=0
The current decision point remains valid for the complete callback.
std::optional< Bar > native_series_bar(std::size_t subscription) const
The latest completed bucket delivered for a declared subscription, or nullopt before its first delive...
native_order::ReplaceResult replace(const native_order::RequestHandle &target, const native_order::Request &request, native_order::ReplaceOptions options)
Replace with options.
NativePhysicalPosition physical_position() const
The book as one aggregate, copied out.
std::size_t cancel_where(std::string_view text, NativeRequestField field)
The same predicate over either identity text.
native_order::SubmitResult submit_market(const native_order::Request &request)
The deliberately narrow market-default convenience: the same acceptance path as submit,...
virtual void on_native_bar_open(const Bar &, const NativeDecisionContext &)
Precedes the matching pass at the script bar's open decision point.
virtual std::optional< NativeMarginDecision > resolve_margin_requirement(const NativeMarginRequirementView &) const
Consulted at EVERY kernel check point, BEFORE the breach test, exactly as resolve_execution_terms is ...
virtual void on_native_timeframe_bar(const Bar &, const NativeTimeframeBarContext &)
One completed bucket of a declared higher-timeframe subscription, delivered on an accepted input bar ...
std::vector< NativeOpenLot > native_open_lots(double mark) const
The book lot by lot, oldest first, marked at mark: one NativeOpenLot per physical lot (physical_posit...
NativeSetupResult configure_native(const NativeRunSpec &spec)
The only setup call.
NativeCurrentExecutionPreview inspect_current_execution(const NativeCurrentExecution &) const
A read-only preview of a current execution: the settlement readiness, any typed refusal or terms outc...
std::uint64_t native_recalculation_count() const
How many recalculations the kernel has driven this run, and how many it suppressed because a point ha...
NativeRiskState native_risk_state() const
The run's generic risk ledger.
std::vector< NativeMarketEvent > native_events(uint64_t after_ordinal) const
Owning snapshots copied at query time.
virtual bool owns_lot_excursions() const noexcept
RULING A48 — the ONE generic per-lot excursion capability.
NativeStrategyHost(const NativeStrategyHost &)=delete
native_order::SubmitResult submit(const native_order::Request &request)
Accept one complete request.
virtual NativePrecommitVerdict validate_execution_precommit(const NativePrecommitView &) const
The last gate before a physical effect, offered once per Applied-ready attempt and never during inspe...
virtual ClosedLotExcursion closed_lot_excursion(const ClosedLotExcursionFacts &) const
The per-lot excursion a host owns, consulted for every closing row once owns_lot_excursions() answers...
std::optional< NativeCurrentPointView > current_execution_point() const
The active callback's quote and calendar-derived decision context, as an owning value.
virtual void on_native_recalculate(const Bar &bar, const NativeDecisionContext &ctx, NativeCalculationReason reason, const native_order::ExecutionAppliedEvent *cause)
EVERY calculation of the run arrives here first, including the script bar's own close calculation (re...
uint64_t native_consumed_high_water() const
The highest run_number this host has consumed.
std::size_t cancel_all()
Withdraw every live request, dependants of a cancelled owner included, and answer how many left the b...
native_order::ReplaceResult replace_market(const native_order::RequestHandle &target, const native_order::Request &request)
The same market-default convenience for a replace; see submit_market.
uint64_t native_continuation_hash() const
The consumer's continuation identity: what a stream resumes against.
virtual std::optional< double > resolve_anchored_level(const NativeAnchoredLevelView &) const
The level an anchored leg (FromOwnerFill) is about to be armed at, offered to the host exactly once p...
native_order::ReplaceResult replace(const native_order::RequestHandle &target, const native_order::Request &request)
Replace one live request: validate first, then retire that incarnation and birth a successor with a n...
virtual void on_native_margin_call(const native_order::MarginCallEvent &)
A kernel-issued liquidation that filled.
NativeStrategyHost(NativeStrategyHost &&)=delete
void cohort_remove(native_order::CohortHandle cohort, native_order::RequestHandle origin)
Take one opening back off a roster.
virtual native_order::ExecutionTerms resolve_execution_terms(const NativeExecutionTermsFacts &facts) const
The fill-terms hook, consulted at every matching candidate.
virtual void on_native_run_begin()
Offered once per successful begin, after the reset and before any bar.
bool append_auxiliary_bars(const Bar *bars, std::size_t n)
A realtime stream's later bars of its declared auxiliary feed.
std::uint64_t native_recalculations_skipped() const
How many recalculations max_recalculations_per_point dropped at their matching point.
virtual void on_native_tick(const Bar &, const NativeTickContext &)
Called once for every accepted realtime print, before matching at that point.
NativeStrategyHost & operator=(NativeStrategyHost &&)=delete
NativeStateView native_state() const
The whole run state as one owning read.
virtual void on_native_sub_bar(const Bar &sub, const NativeDecisionContext &ctx)
One completed lower-timeframe sub-bar of an IntrabarPath::lower_tf path, delivered after that sub-bar...
native_order::CohortHandle cohort_open()
Open a roster a later close can bind to.
bool declare_auxiliary_feed(std::optional< NativeAuxiliaryFeed > feed)
The same begin-time hook for NativeRunSpec::auxiliary_feed: the feed REPLACES the staged spec's own (...
std::optional< NativeTrailState > trail_state(const native_order::RequestHandle &target) const
Where one live trail's own trigger has reached: activated, the running best, the current level and th...
virtual void on_native_applied(const native_order::ExecutionAppliedEvent &, const NativeDecisionContext &)
The calculate-on-fill hook: offered once per applied execution, FIFO, after the account record and th...
void cohort_add(native_order::CohortHandle cohort, native_order::RequestHandle origin)
Enroll one accepted opening's handle in a roster.
std::optional< double > native_liquidation_price() const
The price at which the marked equity falls below the run's maintenance requirement for the live posit...
std::variant< NativeUnconfigured, NativeReady, NativeRunning, NativeCompleted, NativeFailed > NativeLifecycle
The lifecycle as one value. Exhaustive over the five alternatives above.
NativeLifecycleKind
Where a host stands.
NativeCurrentRefusal
Why a current-execution command cannot be consumed here.
constexpr bool native_failure_has_cause(NativeFailureContextKind kind) noexcept
Whether a context of this kind populates its NativeInRunCause.
NativeRequestField
Which of a request's two free-text identity fields a bulk predicate reads.
constexpr NativeFailureContextKind native_failure_context_kind(bool cause, bool recipient, bool cursor) noexcept
The kind that says exactly these three alternatives are populated.
constexpr bool native_failure_has_recipient(NativeFailureContextKind kind) noexcept
Whether a context of this kind populates its NativeInRunRecipient.
NativeCurrentPriceRule
Which price a current execution settles at: the active callback's quote as presented,...
NativeFailureOperation
Which operation was in flight when the failure latched — the second half of "what went wrong",...
std::variant< NativeCurrentRefusal, native_order::ExecutionAppliedEvent, native_order::NoEffectEvent, native_order::MatchRejectedEvent, native_order::CancelledEvent > NativeCurrentExecutionResult
What execute_current answers: a refusal, or the applied outcome.
NativeCompletion
How a Completed run ended: a batch reached the last bar, or a stream was ended.
const native_order::RunIdentity * native_failed_run_identity(const NativeFailed &failed) noexcept
The RunIdentity the failed spec carried, or nullptr when configure failed before staging one.
NativeCalculationReason
Why the kernel is asking the host to calculate.
NativeRunPhase
Which driving is Running: a batch run(), a stream's internal warmup, or its realtime leg.
NativeFailureContext native_failure_context_in_run(const native_order::RunIdentity &run, const native_order::EventId *cause, const native_order::RequestHandle *recipient, const native_order::MatchCursor *cursor) noexcept
Copies only ordinals/incarnation/cursor scalars.
NativeFailureContext native_failure_cause(std::uint64_t ordinal) noexcept
A context carrying one causing event ordinal.
constexpr std::uint8_t native_failure_context_bits(NativeFailureContextKind kind) noexcept
The bit-union under NativeFailureContextKind: Cause=1, Recipient=2, Cursor=4.
NativeFailureContext native_failure_cursor(NativeCoordinate point, double t=0.0) noexcept
A context carrying one path cursor.
NativeMarginCheckKind
Which kernel check point is about to test the maintenance requirement.
NativePrecommitVerdict
The host is consulted before generic opening-margin admission.
NativeEventKind
Which of NativeMarketEvent's three alternatives is populated.
NativeFailureContextKind
In-run failure references.
NativeAnchoredTrigger
Which trigger of an anchored leg the owner's fill is about to supply.
NativeCurrentQuoteKind
Where a price came from: the callback's own market decision point, or the execution it is anchored to...
NativeSetupStatus
Whether a setup call applied its value or refused it.
NativeFailureContext native_failure_recipient(std::uint64_t incarnation) noexcept
A context carrying one addressed request incarnation.
constexpr bool native_failure_has_cursor(NativeFailureContextKind kind) noexcept
Whether a context of this kind populates its NativeInRunCursor.
NativeFailureCode
The durable first failure of a run, in NativeFailure::code.
NativeCompletionKind
How a script interval or a higher-timeframe bucket was closed.
std::variant< AllowanceUnset, AllowanceUnits, AllowanceAllScope, AllowanceDeferred > Allowance
NativeCandidatePriceKind
Which price a candidate is being offered at: the point's own price, or the request's trigger level (a...
std::variant< MarketReady, LimitReady, StopIdle, StopActive, StopLimitPending, StopLimitLive, TrailWaitArm, TrailTrack, TrailActive > TriggerState
std::variant< RemainingUnbound, RemainingFlattenAll, RemainingUnits, RemainingDeferred, NoTarget > Remaining
std::variant< execution::Flatten, order_action::Reduce, order_action::Transact, execution::ReverseTo > ExecutionPlan
The settlement shape one execution takes.
std::shared_ptr< const RequestDefinition > DefinitionRef
std::variant< RemainingProjectionUnbound, RemainingProjectionFlattenAll, RemainingProjectionUnits, RemainingProjectionDeferred, RemainingProjectionNoTarget > RemainingProjection
std::variant< execution::Book, execution::OpeningExposure, SelectedExposure > ExecutionScope
What one execution acted on: the whole book, one opening's exposure, or a bound selection.
MagnifierDistribution
Definition magnifier.hpp:7
std::unordered_map< std::string, std::string > InputsMap
Definition engine.hpp:309
The account row that follows an applied execution in the event history: the shared ordinal,...
Ephemeral read-only facts of one anchored-leg materialization (L7b), offered to the host exactly once...
const SymInfo * syminfo
The rich run overload's symbol metadata is borrowed only for this callback.
bool simple_run
Which public overload began the run: the bare run(bars, n) lifecycle (true) or a timeframe-aware / ma...
Recomputed observations, never an apply token.
std::optional< native_order::CancelReason > terms_cancellation
std::optional< native_order::MatchRejectReason > terms_rejection
A synchronous execution of one request accepted or replaced in this very callback: a target handle an...
What current_execution_point() answers inside a callback: the point's decision context,...
Read-only owning-value facts for one candidate.
bool shared_cursor_collision
A retained crossing can share a rounded cursor quote with another request's level.
native_order::NativeCandidatePriceKind price_kind
The three in-run facts a failure may carry, tagged by kind.
The durable record native_state().failure answers: the code, the operation it happened in,...
What configure_native_fx_curve answers: the status and, on refusal, the curve validation with the ind...
The event ordinal a failure was caused by, 0 when absent.
Where on the modeled path a failure happened: the driver point's coordinate and its interpolation pos...
The request incarnation a failure was addressed to, 0 when absent.
Accepted input facts presented before the generic consumer aggregates the bar into its script interva...
Ephemeral factual view of one kernel-issued liquidation before its units are fixed.
Ephemeral factual view of one kernel check point, offered to the host before the check runs.
bool liquidation_resting
Whether the model already holds a liquidation resting from an earlier admitted point.
The host's answer to one requirement view.
Ephemeral factual view of the numbers the kernel is about to compare, at one check point,...
One owning row of native_events(after_ordinal): a command event, a driver point or an account observa...
std::optional< NativeAccountObservation > account
std::optional< NativeDriverPoint > driver
std::optional< native_order::CommandEvent > command
Owning value row for one open physical lot, copied at query time by native_open_lots(mark) — the lot-...
The book as one aggregate: signed units, the volume-weighted average entry price and the number of op...
Ephemeral factual view of one prepared execution before any physical effect.
The run's generic risk ledger (L9), as the kernel holds it.
std::optional< native_order::RiskLimitKind > reason
What configure_native answers: the status and, on refusal, the first error field validate_native_run_...
The flattened run state native_state() answers: the lifecycle kind, a borrowed pointer to the staged ...
One accepted realtime print before native matching at its current decision point.
One completed higher-timeframe bucket of a declared subscription (NativeRunSpec::subscriptions),...
Read-only projection of a live generic Trail request.
The NativeLifecycle alternatives, one per NativeLifecycleKind.
Owning value row for one live request, copied at query time.
Everything the kernel knows about WHERE a point is, as one owning value: its event ordinal,...
What validate_native_fx_curve and configure_native_fx_curve report: the error and the index of the el...
An immutable account-currency FX curve: parallel arrays of effective-from timestamps in epoch millise...
A host-maintained, run-scoped roster identity.
One committed execution: the definition, the cursor, the resolved price and units,...
A kernel-issued liquidation that actually filled.
A candidate the run refused, with its MatchRejectReason and the cursor it was refused at.
A reduction or a flatten that had nothing to close: terminal, with no execution identity,...
Replacement behaviour that is not expressible in the successor request.
Aggregate field order keeps market construction: Request{Transact{1.0}, "buy", "comment"}...
A kernel-sized opening.
Allocation-free facts suitable for the host's durable failure variant.
One complete setup value, staged/copied by NativeStrategyHost before it is applied at begin.