From ff54a557ac751244dafd60df0bb22886ec35792d Mon Sep 17 00:00:00 2001 From: luisleo526 Date: Thu, 10 Sep 2026 22:01:09 +0800 Subject: [PATCH] Bind exit-leg activation to exposure owners and enforce readiness Replace two stored suppression flags with concrete owner-bound activation coordinates and immutable Pine placement evidence. Resolve bindings on real creation, replacement, exposure creation and flat transitions. Enforce each fixed leg's readiness in revival, prearmed gap precedence and chart-extreme rounding fallback. Preserve independent risk liquidation and ready sibling pricing; cover the bypasses with literal native controls. Preserve the public C mirror prefix and version changed C++ types as v6. --- CMakeLists.txt | 1 + docs/pages/abi-stability.md | 26 +- docs/pages/exit-leg-activation.md | 60 +++ .../pineforge/compat/pine/exit_activation.hpp | 95 +++++ include/pineforge/compat/pine/order_birth.hpp | 2 +- .../pineforge/compat/pine/order_priority.hpp | 2 +- include/pineforge/engine.hpp | 27 +- include/pineforge/leg_activation.hpp | 37 ++ include/pineforge/pending_order_mirror.hpp | 20 +- scripts/check_broker_state_hash_coverage.py | 56 ++- scripts/check_script_cpp_abi.py | 26 +- scripts/gen_pending_order_mirror.py | 27 +- scripts/test_broker_state_hash_coverage.py | 38 +- src/compat/pine/exit_activation.cpp | 64 +++ src/engine_fills.cpp | 29 +- src/engine_internal.hpp | 4 +- src/engine_orders.cpp | 22 + src/engine_path_resolve.cpp | 15 +- src/engine_state_hash.cpp | 19 +- src/engine_strategy_commands.cpp | 91 +---- src/engine_stream.cpp | 2 +- src/pending_order_mirror.cpp | 32 +- tests/CMakeLists.txt | 2 + .../leg_activation/149f77c_pending_mirror.hpp | 156 +++++++ tests/fixtures/leg_activation/README.md | 2 + .../fixtures/script_cpp_abi/base149/README.md | 2 + .../script_cpp_abi/base149/headers.json.gz | Bin 0 -> 142481 bytes .../script_cpp_abi/base149/manifest.json | 81 ++++ tests/test_exit_activation_routes.cpp | 203 +++++++++ tests/test_exit_leg_activation.cpp | 384 ++++++++++++++++++ tests/test_live_state_hash.cpp | 11 +- 31 files changed, 1378 insertions(+), 158 deletions(-) create mode 100644 docs/pages/exit-leg-activation.md create mode 100644 include/pineforge/compat/pine/exit_activation.hpp create mode 100644 include/pineforge/leg_activation.hpp create mode 100644 src/compat/pine/exit_activation.cpp create mode 100644 tests/fixtures/leg_activation/149f77c_pending_mirror.hpp create mode 100644 tests/fixtures/leg_activation/README.md create mode 100644 tests/fixtures/script_cpp_abi/base149/README.md create mode 100644 tests/fixtures/script_cpp_abi/base149/headers.json.gz create mode 100644 tests/fixtures/script_cpp_abi/base149/manifest.json create mode 100644 tests/test_exit_activation_routes.cpp create mode 100644 tests/test_exit_leg_activation.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d8503f29..b157db1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,7 @@ endif() add_library(pineforge STATIC src/c_abi.cpp src/compat/pine/order_birth.cpp + src/compat/pine/exit_activation.cpp src/compat/pine/order_priority.cpp src/engine_aux_security.cpp src/engine_fills.cpp diff --git a/docs/pages/abi-stability.md b/docs/pages/abi-stability.md index 97186c61..e167ce33 100644 --- a/docs/pages/abi-stability.md +++ b/docs/pages/abi-stability.md @@ -112,32 +112,34 @@ notice: - The shape of internal log lines (use them for humans, not parsers). Rebuild generated and native C++ objects against matching engine headers and -runtime. The integrated quantity, predecessor and order-birth representation -changes `PendingOrder` and uses internal `engine_script_run_v5`. Exact frozen -c45/v4 headers are compiled before link tests: both native and generated-style -v4 callers must fail to link to the v5 archive, while matched v5 callers link. -Earlier exact base38/v2 and f864/v3 mismatch controls remain. A compile failure -cannot masquerade as mismatch protection; no pairing executable is run. +runtime. Owner-bound leg activation changes `PendingOrder` layout again; both +`PendingOrder` and `BacktestEngine` use internal `engine_script_run_v6`. Exact +shipped149/v5 headers are compiled before mismatch links. Native and +generated-style old engine callers, plus standalone priority callers using +`vector` without any engine-method reference, must reject the +v6 archive. Matching current and historical symbol-control links must succeed. +Earlier base38/v2, f864/v3 and c45/v4 controls remain. A compilation failure +cannot masquerade as stale-layout rejection; no pairing executable runs. `PINEFORGE_HAS_SCRIPT_RUN_PREPARE_V1` remains 1: it describes the existing hook capability, not the class layout version. Regenerate and rebuild a strategy module to obtain complete script-state reset; replacing an archive does not retrofit an old module. Public C function signatures, `PF_ABI_VERSION` (4), and `strategy_stream_api_version()` (1) are unchanged. The pending-order v1 -mirror keeps all 108 existing field names/types/offsets and its full old prefix; +mirror keeps all 128 shipped149 field names/types/offsets and its full old prefix; new typed facts append, and removed native booleans survive only as read-only derived outputs. Size-limited reads keep old callers within their buffers. Namespace versioning protects referenced internal C++ symbols; it does not validate an erased `pf_strategy_t` handle. Use a handle only with functions from its creating strategy module. A fully self-contained old module can still use -its own matching runtime; this check does not turn it into a v5 module. +its own matching runtime; this check does not turn it into a v6 module. The integrated representation advances the broker fingerprint domain to -`pineforge-broker-state/v5` and stream fingerprint version to 5. These identify -changed serialized quantity/reservation, predecessor and birth facts, alongside -existing Pine policy state. The Pine component schema remains 1; it is -independent of the aggregate fingerprint version. Prior v2/v3/v4 fingerprints are +`pineforge-broker-state/v6` and stream fingerprint version to 6. These identify +changed serialized leg owner/bounds and Pine placement evidence, alongside +existing quantity, predecessor and birth facts. The Pine component schema remains 1; it is +independent of the aggregate fingerprint version. Prior v2/v3/v4/v5 fingerprints are not comparable. Fingerprints are replay checks, not serialized checkpoints or complete hashes of private strategy state. The native runner already binds its strategy-library SHA; its ledger format and Python provenance fingerprints diff --git a/docs/pages/exit-leg-activation.md b/docs/pages/exit-leg-activation.md new file mode 100644 index 00000000..758246e9 --- /dev/null +++ b/docs/pages/exit-leg-activation.md @@ -0,0 +1,60 @@ +Exit stop and limit matching now consumes concrete activation bounds attached +to a position-cycle identity. Each bound names the earliest script bar where +that leg may be evaluated for that owner. A mismatch cannot reuse another +cycle's constraint; an unbound value imposes no lower-bound constraint. +This is one exposure-cycle scope, not a physical lot or `from_entry` claim. +Existing quantity/entry ownership and other path/trailing rules remain separate. + +The lower bounds also apply when a dormant bracket is revived after a margin +partial and when a prearmed bracket selects a stop or limit at the open. +Revival can restore the bracket without executing an unready stop. Open-gap +selection checks each leg before applying stop/limit precedence, so an eligible +sibling retains its own execution and slippage semantics. Risk liquidation +itself is independent of a bracket's activation time. +The historical chart-extreme rounding fallback checks the same per-leg bounds; +a normal no-fill result cannot become an early fill through that fallback. + +The transitions are connected to the current book. New or replaced EXIT +construction binds against live exposure. Both fresh-position producers bind +retained exits after establishing the new cycle, before later matching or +callbacks. Going flat clears bindings while retained policy evidence stays +with the order. Partial reductions and same-cycle adds do not refresh a +deadline. Order replacement creates fresh placement evidence and activation; +cancellation and OCA erasure remove the values with their owning order. + +For Pine compatibility, immutable `ExitPlacementEvidence` retains the original +callback marketability inputs: placement cycle/entry bar, physical exposure +direction, cursor price, raw stop/limit levels and any named limit continuation. +Current trigger fields can be neutralized or modified without rewriting those +facts. `LaterSameOpen` and `FirstHighRecross` continuations remain explicit +Pine exceptions; their existing predicates are evaluated in the adapter. +Their recorded observed fill sequence is the sequence visible at policy +selection; the separate `OrderBirth` still owns the actual callback interval. + +At binding, the adapter resolves the retained original decision to concrete +bounds for the new owner. A held leg receives `owner_entry_bar + 1`; the other +leg receives `owner_entry_bar`. The arithmetic uses a wider bar coordinate. +The matcher never refreshes these numbers from the current position. In +particular a surviving same-ID exit can bind a new cycle and receive another +hold, even though its original birth-bar deadline has already passed. New +marketability is not recalculated from the replacement owner's opposite side. + +The two native `coof_suppress_*_on_entry_bar` booleans are removed. Their old +C mirror fields are read-only projections from the Pine evidence; no native +decision reads those outputs. All 128 pre-existing mirror fields and the full +old byte prefix remain unchanged, and new activation/evidence fields append. +Every new owner, coordinate, evidence value and optional-presence discriminator +is hashed and mirrored. There is no side map or second pending-order book. + +This slice moves the two decisions out of the matching masks, but does not +eliminate the Pine policies or detach their producer from existing native +callback use. The Pine adapter is still invoked by the current exit producer. +`PineHistoricalBirthReach`, cascade leg/gap permissions, dormant-leg revival and +other historical execution rules remain separate work. The effective-level +accessor still reports resolved levels rather than masking eligibility. + +The internal object layout changes and requires matching C++ headers/library. +Both PendingOrder and BacktestEngine now use internal v6 with broker/stream +fingerprint v6. Exact shipped149/v5 engine and standalone PendingOrder clients +are checked by compile/link-only mismatch controls with matching positives. +Public C ABI 4, stream API 1 and pending mirror version 1 are preserved. diff --git a/include/pineforge/compat/pine/exit_activation.hpp b/include/pineforge/compat/pine/exit_activation.hpp new file mode 100644 index 00000000..5024b013 --- /dev/null +++ b/include/pineforge/compat/pine/exit_activation.hpp @@ -0,0 +1,95 @@ +#pragma once +#include "../../bar.hpp" +#include "../../leg_activation.hpp" +#include +#include +#include +#include +#include + +namespace pineforge { +enum class PositionSide; +inline namespace engine_script_run_v6 { struct PendingOrder; } +} +namespace pineforge::compat::pine { + +enum class LimitContinuationCause : int32_t { LaterSameOpen, FirstHighRecross }; +struct LimitContinuation { + LimitContinuationCause cause; + // Sequence observed when policy was selected; callback cause remains the + // independent immutable OrderBirth interval on the order. + uint64_t observed_fill_sequence; +}; + +// Immutable original policy evidence. Rebinding must not recompute original +// marketability from the new owner's side or a later-mutated trigger level. +struct ExitPlacementEvidence { + int64_t position_cycle; + int entry_bar; + int direction; + double cursor_price; + double stop_level; + double limit_level; + std::optional limit_continuation; +}; + +class ExitActivationPolicy { +public: + ExitActivationPolicy() = default; + explicit ExitActivationPolicy(ExitPlacementEvidence evidence) : evidence_(evidence) { + if (evidence.position_cycle <= 0 || evidence.entry_bar < 0 + || (evidence.direction != 1 && evidence.direction != -1) + || !std::isfinite(evidence.cursor_price)) + throw std::invalid_argument("invalid Pine exit placement evidence"); + } + const std::optional& evidence() const { return evidence_; } + bool holds_stop() const; + bool holds_limit() const; + bool continues_at_later_open() const; + ExitLegActivationBounds resolve(int64_t owner_cycle, int owner_entry_bar) const; +private: + std::optional evidence_; +}; + +// Transient producer facts, never retained as a parallel mutable mode bag. +struct ExitActivationContext { + const Bar& bar; + PositionSide side; + int64_t cycle; + int bar_index; + int position_open_bar; + int position_entry_count; + double position_quantity; + int pyramiding; + std::size_t lot_count; + const std::string& first_lot_id; + uint64_t first_lot_incarnation; + bool fill_recalc; + bool scheduler; + double cursor_price; + bool after_first_open_fill; + int recalc_leg; + bool historical_segment; + bool at_extreme; + int historical_point; + uint64_t market_recalc_incarnation; + uint64_t market_recalc_fill; + uint64_t current_fill; + bool magnifier; + bool process_on_close; + bool warmup; + bool stream_idle; + bool pending_empty; + int slippage; + double pointvalue; + double account_fx; + bool fx_series_empty; + double tick_high; +}; + +ExitActivationPolicy select_exit_activation(const PendingOrder& order, + double requested_stop, double requested_limit, const ExitActivationContext& context); + +} // namespace pineforge::compat::pine + +namespace pineforge { using PineExitActivationPolicy = compat::pine::ExitActivationPolicy; } diff --git a/include/pineforge/compat/pine/order_birth.hpp b/include/pineforge/compat/pine/order_birth.hpp index 78906582..b57ffe0e 100644 --- a/include/pineforge/compat/pine/order_birth.hpp +++ b/include/pineforge/compat/pine/order_birth.hpp @@ -1,7 +1,7 @@ #pragma once #include "../../order_birth.hpp" -namespace pineforge { inline namespace engine_script_run_v5 { struct PendingOrder; } } +namespace pineforge { inline namespace engine_script_run_v6 { struct PendingOrder; } } namespace pineforge::compat::pine { // Historical Pine permissions remain policy, not physical birth facts. diff --git a/include/pineforge/compat/pine/order_priority.hpp b/include/pineforge/compat/pine/order_priority.hpp index 3621990f..86aac962 100644 --- a/include/pineforge/compat/pine/order_priority.hpp +++ b/include/pineforge/compat/pine/order_priority.hpp @@ -5,7 +5,7 @@ #include #include -namespace pineforge { inline namespace engine_script_run_v5 { struct PendingOrder; } } +namespace pineforge { inline namespace engine_script_run_v6 { struct PendingOrder; } } namespace pineforge::compat::pine { struct OrderPriorityContext { diff --git a/include/pineforge/engine.hpp b/include/pineforge/engine.hpp index 7a75d98a..64c73225 100644 --- a/include/pineforge/engine.hpp +++ b/include/pineforge/engine.hpp @@ -14,6 +14,8 @@ #include "bar.hpp" #include "broker_events.hpp" #include "quantity_intent.hpp" +#include "leg_activation.hpp" +#include "compat/pine/exit_activation.hpp" #include "order_birth.hpp" #include "compat/pine/order_birth.hpp" #include "compat/pine/intraday_cap.hpp" @@ -404,7 +406,7 @@ enum class ShortSeedCollisionRole : uint8_t { // PendingOrder crosses out-of-line helper boundaries independently of the // engine class, so its changed layout must carry the same internal epoch. -inline namespace engine_script_run_v5 { +inline namespace engine_script_run_v6 { struct PendingOrder { std::string id; std::string from_entry; // for exit orders @@ -459,14 +461,10 @@ struct PendingOrder { // fires, later bars—and later COOF scheduler segments on the same bar— // evaluate only the live limit leg until the order fills or is replaced. bool stop_limit_activated = false; - // A stop/limit leg emitted by a COOF recalc on the position's entry bar - // cannot consume the fill cursor that caused that recalc when the leg is - // already marketable there. Suppression is deliberately per-leg: the - // other, correctly-sided bracket leg remains live on the remaining path. - // Both bits expire automatically once bar_index_ advances, so an unfilled - // suppressed leg carries into the next bar as an ordinary order. - bool coof_suppress_stop_on_entry_bar = false; - bool coof_suppress_limit_on_entry_bar = false; + // Concrete activation bounds belong to the currently bound exposure cycle. + // Pine placement evidence is retained separately for explicit rebinding. + ExitLegActivation leg_activation; + PineExitActivationPolicy pine_exit_activation; // Immutable evaluation/fill origin, captured once for this incarnation. // Historical extreme-only/trailing permissions live in compat::pine. OrderBirth birth; @@ -1035,7 +1033,7 @@ struct PendingOrder { ShortSeedCollisionRole::NONE; }; - } // inline namespace engine_script_run_v5 (PendingOrder) + } // inline namespace engine_script_run_v6 (PendingOrder) // default_qty_type constants (matches TradingView) enum class QtyType { FIXED = 0, PERCENT_OF_EQUITY = 1, CASH = 2 }; @@ -1090,10 +1088,10 @@ struct StrategyOverrides { // The C++ subclass contract is internal, unlike pineforge.h's stable C ABI. // Changing its layout or vtable requires all generated/native C++ objects to be rebuilt. -// v5 integrates typed quantity, replacement identity and causal order birth. +// v6 adds explicit owner-bound exit-leg activation and Pine placement evidence. // Version the mangled class name so older headers' member offsets/vtable cannot // silently bind out-of-line members of this different object layout. -inline namespace engine_script_run_v5 { +inline namespace engine_script_run_v6 { class BacktestEngine { protected: // --- Position state --- @@ -4321,6 +4319,9 @@ class BacktestEngine { double fill_price, double explicit_qty, int explicit_qty_type, uint64_t entry_incarnation); + void bind_exit_activation(PendingOrder& order); + void bind_retained_exit_activations(); + void unbind_exit_activations(); void open_fresh_position(PositionSide requested, double fill_price, double qty, const std::string& id, uint64_t entry_incarnation); @@ -5128,5 +5129,5 @@ class BacktestEngine { void trace(const std::string& name, int value) { trace(name, static_cast(value)); } }; -} // inline namespace engine_script_run_v5 +} // inline namespace engine_script_run_v6 } // namespace pineforge diff --git a/include/pineforge/leg_activation.hpp b/include/pineforge/leg_activation.hpp new file mode 100644 index 00000000..4160c841 --- /dev/null +++ b/include/pineforge/leg_activation.hpp @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include + +namespace pineforge { + +// Concrete lower bounds resolved when an exit binds an exposure cycle. Other +// path/price/lifetime constraints remain independent of this lower bound. +struct ExitLegActivationBounds { + int64_t position_cycle; + int64_t stop_first_bar; + int64_t limit_first_bar; +}; + +class ExitLegActivation { +public: + void bind(ExitLegActivationBounds bounds) { + if (bounds.position_cycle <= 0 || bounds.stop_first_bar < 0 || bounds.limit_first_bar < 0) + throw std::invalid_argument("invalid exit-leg activation bounds"); + bounds_ = bounds; + } + void unbind() { bounds_.reset(); } + const std::optional& bounds() const { return bounds_; } + // An unbound value imposes no lower-bound constraint. Production EXIT + // producers bind on live exposure; exposure creation binds retained exits. + bool stop_ready(int64_t cycle, int64_t bar) const { + return !bounds_ || (bounds_->position_cycle == cycle && bar >= bounds_->stop_first_bar); + } + bool limit_ready(int64_t cycle, int64_t bar) const { + return !bounds_ || (bounds_->position_cycle == cycle && bar >= bounds_->limit_first_bar); + } +private: + std::optional bounds_; +}; + +} // namespace pineforge diff --git a/include/pineforge/pending_order_mirror.hpp b/include/pineforge/pending_order_mirror.hpp index 0bc79a65..3d23478b 100644 --- a/include/pineforge/pending_order_mirror.hpp +++ b/include/pineforge/pending_order_mirror.hpp @@ -1,5 +1,5 @@ // GENERATED by scripts/gen_pending_order_mirror.py from include/pineforge/engine.hpp -- do not edit. -// 94 PendingOrder members mirrored (128 POD fields incl. struct_version/size). +// 94 PendingOrder members mirrored (142 POD fields incl. struct_version/size). #pragma once #include @@ -46,8 +46,8 @@ typedef struct pf_pending_order_v1_s { uint64_t recreated_after_named_cancelled_entry_incarnation; uint64_t named_cancel_surviving_exit_incarnation; uint8_t stop_limit_activated; - uint8_t coof_suppress_stop_on_entry_bar; - uint8_t coof_suppress_limit_on_entry_bar; + uint8_t coof_suppress_stop_on_entry_bar; // deprecated, derived output only + uint8_t coof_suppress_limit_on_entry_bar; // deprecated, derived output only uint8_t created_during_coof_recalc; // deprecated, derived output only uint8_t coof_born_at_close_recalc; // deprecated, derived output only uint8_t coof_born_mid_bar; // deprecated, derived output only @@ -140,6 +140,20 @@ typedef struct pf_pending_order_v1_s { uint8_t quantity_reservation_present; double quantity_reservation_units; double quantity_reservation_basis_units; + int64_t leg_activation_owner_cycle; + uint8_t leg_activation_present; + int64_t leg_activation_stop_first_bar; + int64_t leg_activation_limit_first_bar; + int64_t pine_exit_activation_owner_cycle_at_birth; + uint8_t pine_exit_activation_present; + int32_t pine_exit_activation_entry_bar_at_birth; + int32_t pine_exit_activation_direction_at_birth; + double pine_exit_activation_cursor_price_at_birth; + double pine_exit_activation_stop_level_at_birth; + double pine_exit_activation_limit_level_at_birth; + uint8_t pine_exit_activation_limit_continuation_present; + int32_t pine_exit_activation_limit_continuation_cause; + uint64_t pine_exit_activation_limit_continuation_fill; } pf_pending_order_v1_t; /* One row of the self-describing layout table returned by diff --git a/scripts/check_broker_state_hash_coverage.py b/scripts/check_broker_state_hash_coverage.py index 78d35a62..be8190e4 100644 --- a/scripts/check_broker_state_hash_coverage.py +++ b/scripts/check_broker_state_hash_coverage.py @@ -166,7 +166,7 @@ def _class_fields(src: str, name: str) -> dict[str, str]: remaining data declaration must be one TYPE NAME; adding a new field is visible even when its name has no trailing underscore. """ - body = _one_braced_body(src, rf"\bclass\s+{name}\s*\{{", name) + body = _one_braced_body(src, rf"\b(?:class|struct)\s+{name}\s*\{{", name) fields = {} statement = "" i = 0 @@ -193,6 +193,8 @@ def _class_fields(src: str, name: str) -> dict[str, str]: statement = "" if re.fullmatch(re.escape(name) + r"\(\)\s*=\s*default", decl): continue + if re.fullmatch(r"(?:bool|ExitLegActivationBounds)\s+\w+\([^;{}]*\)\s+const", decl): + continue # declared read-only value query, never a stored field if decl and not decl.startswith("using "): match = re.fullmatch(r"((?:(?:static|constexpr|const)\s+)*[\w:<>]+)\s+(\w+)(?:\s*=\s*[^,]+)?", decl) if not match or match[2] in fields: @@ -411,8 +413,44 @@ def _birth_coverage(header: str, source: str) -> None: raise ValueError("birth facts must be unconditionally hashed at order-loop scope") +def _exit_activation_coverage(activation: str, policy: str, source: str) -> None: + activation = _strip_cpp_comments(activation) + policy = _strip_cpp_comments(policy) + expected = [ + (activation, "ExitLegActivation", {"bounds_": "std::optional"}), + (activation, "ExitLegActivationBounds", {"position_cycle": "int64_t", "stop_first_bar": "int64_t", "limit_first_bar": "int64_t"}), + (policy, "ExitActivationPolicy", {"evidence_": "std::optional"}), + (policy, "ExitPlacementEvidence", {"position_cycle": "int64_t", "entry_bar": "int", "direction": "int", "cursor_price": "double", "stop_level": "double", "limit_level": "double", "limit_continuation": "std::optional"}), + (policy, "LimitContinuation", {"cause": "LimitContinuationCause", "observed_fill_sequence": "uint64_t"}), + ] + for text, name, fields in expected: + if _class_fields(text, name) != fields: + raise ValueError(name + " activation fields changed; every value must be hashed") + loop = _collection_loop_body(source, "pending_orders_", "o") + expected = """f.b(o.leg_activation.bounds().has_value()); + if (const auto& bounds = o.leg_activation.bounds()) { + f.i(bounds->position_cycle); f.i(bounds->stop_first_bar); f.i(bounds->limit_first_bar); + } + f.b(o.pine_exit_activation.evidence().has_value()); + if (const auto& evidence = o.pine_exit_activation.evidence()) { + f.i(evidence->position_cycle); f.i(evidence->entry_bar); f.i(evidence->direction); + f.d(evidence->cursor_price); f.d(evidence->stop_level); f.d(evidence->limit_level); + f.b(evidence->limit_continuation.has_value()); + if (const auto& continuation = evidence->limit_continuation) { + f.i(static_cast(continuation->cause)); f.u(continuation->observed_fill_sequence); + } + }""" + compact = re.sub(r"\s+", "", loop) + folded = re.sub(r"\s+", "", expected) + if compact.count(folded) != 1: + raise ValueError("exit activation needs every nested fact and optional discriminator") + prefix = compact[:compact.index(folded)] + if prefix.count("{") != prefix.count("}"): + raise ValueError("exit activation hash block must be unconditional") + + def _runtime_version_coverage(header: str, source: str, stream: str) -> None: - """The v5 layout and serialized-state contracts must advance together. + """The v6 layout and serialized-state contracts must advance together. Pin the actual hash entry points, rather than accepting a version string mentioned in a comment or an unrelated helper. Public C ABI versions have @@ -420,18 +458,18 @@ def _runtime_version_coverage(header: str, source: str, stream: str) -> None: """ header = _strip_cpp_comments(header) namespaces = re.findall(r"inline\s+namespace\s+(engine_script_run_v\d+)\s*\{", header) - if namespaces != ["engine_script_run_v5", "engine_script_run_v5"]: - raise ValueError("PendingOrder and BacktestEngine layouts require internal namespace engine_script_run_v5") + if namespaces != ["engine_script_run_v6", "engine_script_run_v6"]: + raise ValueError("PendingOrder and BacktestEngine layouts require internal namespace engine_script_run_v6") broker = _one_braced_body(source, r"uint64_t\s+BacktestEngine::broker_state_hash\(\)\s+const\s*\{", "broker hash") - if not re.match(r'\s*Fnv\s+f;\s*f\.s\("pineforge-broker-state/v5"\);', broker): - raise ValueError("broker hash must start with pineforge-broker-state/v5") + if not re.match(r'\s*Fnv\s+f;\s*f\.s\("pineforge-broker-state/v6"\);', broker): + raise ValueError("broker hash must start with pineforge-broker-state/v6") stream_body = _one_braced_body(_strip_cpp_comments(stream), r"uint64_t\s+BacktestEngine::stream_state_hash\(\)\s+const\s*\{", "stream hash") compact = re.sub(r"\s+", "", stream_body) - fold = "integer(5);integer(broker_state_hash());" + fold = "integer(6);integer(broker_state_hash());" if compact.count(fold) != 1: - raise ValueError("stream hash requires version 5 followed by the broker hash") + raise ValueError("stream hash requires version 6 followed by the broker hash") prefix = compact[:compact.index(fold)] if prefix.count("{") != prefix.count("}") or (prefix and prefix[-1] not in ";}"): raise ValueError("stream version fold must be unconditional at function scope") @@ -447,6 +485,8 @@ def main(root: Path = ROOT) -> int: try: _runtime_version_coverage(hpp, src, (root / "src/engine_stream.cpp").read_text()) _birth_coverage((root / "include/pineforge/order_birth.hpp").read_text(), src) + _exit_activation_coverage((root / "include/pineforge/leg_activation.hpp").read_text(), + (root / "include/pineforge/compat/pine/exit_activation.hpp").read_text(), src) _opening_coverage((root / "include/pineforge/broker_events.hpp").read_text(), src) _quantity_request_coverage((root / "include/pineforge/quantity_intent.hpp").read_text(), src) _intraday_coverage( diff --git a/scripts/check_script_cpp_abi.py b/scripts/check_script_cpp_abi.py index 32797b35..afed8a76 100644 --- a/scripts/check_script_cpp_abi.py +++ b/scripts/check_script_cpp_abi.py @@ -16,7 +16,7 @@ BASE_COMMIT = "38dc73e5503fe5395458e5f8df2a2ad78054a1ae" BASE_ENGINE_SHA256 = "06c937a1ccd31815ca7775268ac699ffdfddb1a1f19de4628b777f37e9a6d193" -CURRENT_NAMESPACE = "engine_script_run_v5" +CURRENT_NAMESPACE = "engine_script_run_v6" BASE_NAMESPACE = "engine_script_run_v2" FIXTURE = Path(__file__).resolve().parents[1] / "tests/fixtures/script_cpp_abi/base38" @@ -150,6 +150,10 @@ def main(): frozen_headers(prior_include, FIXTURE.parent / "basec45", "c45cf5a4d0e67a2ac098d9066977e1fa21c408a9", "engine_script_run_v4", "3b4e2937a9b5f275dd119144373b1bf15e433092009500092cd32ea34963b293") + activation_include = root / "base149/include" + frozen_headers(activation_include, FIXTURE.parent / "base149", + "149f77ce16ef84c6da77e67d812bf8fa88e51cde", "engine_script_run_v5", + "5ba773889d947e4fdab3995cc55f22f88ab037a86e0ad4016a126d297ce82eed") common = [args.compiler, "-std=c++17", "-O0", *args.extra_flag] def compile_object(name, source, include): @@ -204,6 +208,13 @@ def compile_object(name, source, include): prior_priority = compile_object("basec45_pending_priority", priority_caller, prior_include) prior_priority_symbols = compile_object("basec45_pending_priority_symbols", priority_symbols, prior_include) + activation_native = compile_object("base149_native", caller("engine_script_run_v5"), activation_include) + activation_generated = compile_object("base149_generated", caller("engine_script_run_v5", True), activation_include) + activation_symbols = compile_object("base149_symbol_control", + BASE_SYMBOL_CONTROL.replace("engine_script_run_v2", "engine_script_run_v5"), activation_include) + activation_priority = compile_object("base149_pending_priority", priority_caller, activation_include) + activation_priority_symbols = compile_object("base149_pending_priority_symbols", priority_symbols, activation_include) + def link(name, obj, runtime, missing_namespace=None): linked = subprocess.run( [*common, str(obj), str(runtime), "-pthread", "-o", str(root / name)], @@ -253,10 +264,19 @@ def link(name, obj, runtime, missing_namespace=None): link("current_generated_to_v4_symbol_control", current_generated, prior_symbols, CURRENT_NAMESPACE) link("current_pending_priority_to_current", current_priority, args.library) link("basec45_pending_priority_to_v4_symbols", prior_priority, prior_priority_symbols) + link("base149_native_to_v5_symbol_control", activation_native, activation_symbols) + link("base149_generated_to_v5_symbol_control", activation_generated, activation_symbols) + link("base149_native_to_current", activation_native, args.library, "engine_script_run_v5") + link("base149_generated_to_current", activation_generated, args.library, "engine_script_run_v5") + link("current_native_to_v5_symbol_control", current_native, activation_symbols, CURRENT_NAMESPACE) + link("current_generated_to_v5_symbol_control", current_generated, activation_symbols, CURRENT_NAMESPACE) + link("base149_pending_priority_to_v5_symbols", activation_priority, activation_priority_symbols) for name, obj, runtime, expected in [ + ("base149_pending_priority_to_current", activation_priority, args.library, "pineforge::engine_script_run_v5::PendingOrder"), + ("current_pending_priority_to_v5_symbols", current_priority, activation_priority_symbols, "pineforge::engine_script_run_v6::PendingOrder"), ("basec45_pending_priority_to_current", prior_priority, args.library, "pineforge::PendingOrder"), ("current_pending_priority_to_v4_symbols", current_priority, prior_priority_symbols, - "pineforge::engine_script_run_v5::PendingOrder"), + "pineforge::engine_script_run_v6::PendingOrder"), ]: result = subprocess.run([*common, str(obj), str(runtime), "-pthread", "-o", str(root / name)], capture_output=True, text=True, timeout=60) @@ -264,7 +284,7 @@ def link(name, obj, runtime, missing_namespace=None): or "OrderPriority::select(" not in result.stderr or expected not in result.stderr): raise RuntimeError(name + " did not reject the expected PendingOrder type: " + result.stderr) print(name + ": rejected stale standalone PendingOrder argument type (not executed)") - print("15 translation units compiled; 10 positive links; 15 rejected links; no executable run") + print("20 translation units compiled; 13 positive links; 21 rejected links; no executable run") if __name__ == "__main__": diff --git a/scripts/gen_pending_order_mirror.py b/scripts/gen_pending_order_mirror.py index 4d127ad7..f740407e 100644 --- a/scripts/gen_pending_order_mirror.py +++ b/scripts/gen_pending_order_mirror.py @@ -61,6 +61,8 @@ # Public v1 is append-only. Removed native fields survive only as one-way # deprecated output projections at their original offsets. LEGACY_OUTPUTS = { + "coof_suppress_stop_on_entry_bar": "src.pine_exit_activation.holds_stop() ? 1 : 0", + "coof_suppress_limit_on_entry_bar": "src.pine_exit_activation.holds_limit() ? 1 : 0", "created_during_coof_recalc": "src.birth.from_fill() ? 1 : 0", "coof_born_at_close_recalc": "src.birth.at_terminal_fill() ? 1 : 0", "coof_born_mid_bar": "compat::pine::historical_cascade_reach(src) ? 1 : 0", @@ -71,6 +73,24 @@ "full_percent_exit_request": "src.quantity_request.requests_all() ? 1 : 0", } COMPOSITE_MAP = { + "ExitLegActivation": [ + ("owner_cycle", "int64_t", "src.{m}.bounds() ? src.{m}.bounds()->position_cycle : 0"), + ("present", "uint8_t", "src.{m}.bounds().has_value() ? 1 : 0"), + ("stop_first_bar", "int64_t", "src.{m}.bounds() ? src.{m}.bounds()->stop_first_bar : 0"), + ("limit_first_bar", "int64_t", "src.{m}.bounds() ? src.{m}.bounds()->limit_first_bar : 0"), + ], + "PineExitActivationPolicy": [ + ("owner_cycle_at_birth", "int64_t", "src.{m}.evidence() ? src.{m}.evidence()->position_cycle : 0"), + ("present", "uint8_t", "src.{m}.evidence().has_value() ? 1 : 0"), + ("entry_bar_at_birth", "int32_t", "src.{m}.evidence() ? src.{m}.evidence()->entry_bar : 0"), + ("direction_at_birth", "int32_t", "src.{m}.evidence() ? src.{m}.evidence()->direction : 0"), + ("cursor_price_at_birth", "double", "src.{m}.evidence() ? src.{m}.evidence()->cursor_price : 0.0"), + ("stop_level_at_birth", "double", "src.{m}.evidence() ? src.{m}.evidence()->stop_level : 0.0"), + ("limit_level_at_birth", "double", "src.{m}.evidence() ? src.{m}.evidence()->limit_level : 0.0"), + ("limit_continuation_present", "uint8_t", "src.{m}.evidence() && src.{m}.evidence()->limit_continuation ? 1 : 0"), + ("limit_continuation_cause", "int32_t", "src.{m}.evidence() && src.{m}.evidence()->limit_continuation ? static_cast(src.{m}.evidence()->limit_continuation->cause) : 0"), + ("limit_continuation_fill", "uint64_t", "src.{m}.evidence() && src.{m}.evidence()->limit_continuation ? src.{m}.evidence()->limit_continuation->observed_fill_sequence : 0"), + ], "QuantityRequest": [ ("intent_kind", "uint64_t", "src.{m}.intent() ? static_cast(src.{m}.intent()->kind()) + 1 : 0"), ("intent_units", "double", "src.{m}.intent() && src.{m}.intent()->kind() == QuantityIntent::Kind::Units ? src.{m}.intent()->units() : 0.0"), @@ -218,7 +238,12 @@ def generate() -> tuple[str, str]: if name not in LEGACY_OUTPUTS and native.get(name) != kind: _fail(f"public v1 prefix member {name} needs an explicit derived projection") prefix_names = {name for _, name in prefix} - ordered = prefix + [(kind, name) for kind, name in mirrored if name not in prefix_names] + # Preserve the full 149f77c extension as well as the original c45 prefix. + existing_extension = ["replaced_order_incarnation", "birth", "pine_birth_reach", "quantity_request"] + tail = [(native[name], name) for name in existing_extension] + tail += [(kind, name) for kind, name in mirrored + if name not in prefix_names and name not in existing_extension] + ordered = prefix + tail for t, m in ordered: if m in LEGACY_OUTPUTS: ct = TYPE_MAP[t][0] diff --git a/scripts/test_broker_state_hash_coverage.py b/scripts/test_broker_state_hash_coverage.py index 07b450f4..afa5398c 100644 --- a/scripts/test_broker_state_hash_coverage.py +++ b/scripts/test_broker_state_hash_coverage.py @@ -17,6 +17,8 @@ HEADER = (ROOT / "include/pineforge/engine.hpp").read_text() QUANTITY = (ROOT / "include/pineforge/quantity_intent.hpp").read_text() EVENTS = (ROOT / "include/pineforge/broker_events.hpp").read_text() +ACTIVATION = (ROOT / "include/pineforge/leg_activation.hpp").read_text() +EXIT_POLICY = (ROOT / "include/pineforge/compat/pine/exit_activation.hpp").read_text() BIRTH = (ROOT / "include/pineforge/order_birth.hpp").read_text() INTRADAY = (ROOT / "include/pineforge/compat/pine/intraday_order_budget.hpp").read_text() POLICY = (ROOT / "include/pineforge/compat/pine/intraday_cap.hpp").read_text() @@ -28,7 +30,7 @@ class PhysicalLotCoverage(unittest.TestCase): def check(self, header=HEADER, source=SOURCE, waivers=WAIVERS, events=EVENTS, - intraday=INTRADAY, policy=POLICY, obligation=OBLIGATION, stream=STREAM, quantity=QUANTITY, birth=BIRTH): + intraday=INTRADAY, policy=POLICY, obligation=OBLIGATION, stream=STREAM, quantity=QUANTITY, birth=BIRTH, activation=ACTIVATION, exit_policy=EXIT_POLICY): with tempfile.TemporaryDirectory(prefix="pf-lot-hash-check-") as temp: root = Path(temp) for name, content in [ @@ -36,6 +38,8 @@ def check(self, header=HEADER, source=SOURCE, waivers=WAIVERS, events=EVENTS, ("include/pineforge/broker_events.hpp", events), ("include/pineforge/quantity_intent.hpp", quantity), ("include/pineforge/order_birth.hpp", birth), + ("include/pineforge/leg_activation.hpp", activation), + ("include/pineforge/compat/pine/exit_activation.hpp", exit_policy), ("include/pineforge/compat/pine/intraday_order_budget.hpp", intraday), ("include/pineforge/compat/pine/intraday_cap.hpp", policy), ("include/pineforge/position_close_obligation.hpp", obligation), @@ -55,6 +59,16 @@ def check(self, header=HEADER, source=SOURCE, waivers=WAIVERS, events=EVENTS, output.write(str(exc.code)) return code, output.getvalue() + def test_exit_activation_has_complete_unconditional_coverage(self): + for fold in ["f.b(o.leg_activation.bounds().has_value());", "f.i(bounds->position_cycle);", + "f.i(bounds->stop_first_bar);", "f.i(bounds->limit_first_bar);", + "f.b(o.pine_exit_activation.evidence().has_value());", "f.d(evidence->stop_level);", + "f.d(evidence->limit_level);", "f.i(evidence->direction);", + "f.u(continuation->observed_fill_sequence);", "f.b(evidence->limit_continuation.has_value());"]: + with self.subTest(fold=fold): self.assertEqual(self.check(source=SOURCE.replace(fold,""))[0],1) + self.assertEqual(self.check(activation=ACTIVATION.replace("int64_t limit_first_bar;", "int64_t limit_first_bar; int64_t hidden;"))[0],1) + self.assertEqual(self.check(exit_policy=EXIT_POLICY.replace("double cursor_price;", "double cursor_price; double hidden;"))[0],1) + def test_actual_source_and_named_parser(self): self.assertEqual(self.check()[0], 0) self.assertEqual(len(members(HEADER, "PyramidEntry")), 18) @@ -85,26 +99,26 @@ def test_quantity_model_additions_and_variant_drift_fail_closed(self): self.assertIn(old, QUANTITY) self.assertEqual(self.check(quantity=QUANTITY.replace(old, new))[0], 1) - def test_layout_and_hash_versions_must_match_v5_contract(self): - self.assertIn("engine_script_run_v5", HEADER) - self.assertIn('f.s("pineforge-broker-state/v5");', SOURCE) - self.assertIn("integer(5); integer(broker_state_hash());", STREAM) - self.assertEqual(self.check(header=HEADER.replace("engine_script_run_v5", "engine_script_run_v2"))[0], 1) + def test_layout_and_hash_versions_must_match_v6_contract(self): + self.assertIn("engine_script_run_v6", HEADER) + self.assertIn('f.s("pineforge-broker-state/v6");', SOURCE) + self.assertIn("integer(6); integer(broker_state_hash());", STREAM) + self.assertEqual(self.check(header=HEADER.replace("engine_script_run_v6", "engine_script_run_v2"))[0], 1) for replacement in ['f.s("pineforge-broker-state/v2");', '', - '// f.s("pineforge-broker-state/v5");']: + '// f.s("pineforge-broker-state/v6");']: self.assertEqual(self.check(source=SOURCE.replace( - 'f.s("pineforge-broker-state/v5");', replacement))[0], 1) + 'f.s("pineforge-broker-state/v6");', replacement))[0], 1) for replacement in ["integer(2); integer(broker_state_hash());", "integer(broker_state_hash());", - "if (false) { integer(5); integer(broker_state_hash()); }"]: + "if (false) { integer(6); integer(broker_state_hash()); }"]: self.assertEqual(self.check(stream=STREAM.replace( - "integer(5); integer(broker_state_hash());", replacement))[0], 1) + "integer(6); integer(broker_state_hash());", replacement))[0], 1) def test_version_folds_in_unrelated_helpers_do_not_cover_entry_points(self): - broker_fold = 'f.s("pineforge-broker-state/v5");' + broker_fold = 'f.s("pineforge-broker-state/v6");' altered = SOURCE.replace(broker_fold, '') + '\nvoid other() { ' + broker_fold + ' }\n' self.assertEqual(self.check(source=altered)[0], 1) - stream_fold = "integer(5); integer(broker_state_hash());" + stream_fold = "integer(6); integer(broker_state_hash());" altered = STREAM.replace(stream_fold, '') + '\nvoid other() { ' + stream_fold + ' }\n' self.assertEqual(self.check(stream=altered)[0], 1) diff --git a/src/compat/pine/exit_activation.cpp b/src/compat/pine/exit_activation.cpp new file mode 100644 index 00000000..166f9bc0 --- /dev/null +++ b/src/compat/pine/exit_activation.cpp @@ -0,0 +1,64 @@ +#include +#include +#include "../../engine_internal.hpp" +#include + +namespace pineforge::compat::pine { + +bool ExitActivationPolicy::holds_stop() const { + return evidence_ && !std::isnan(evidence_->stop_level) + && (evidence_->direction > 0 ? evidence_->cursor_price <= evidence_->stop_level + : evidence_->cursor_price >= evidence_->stop_level); +} +bool ExitActivationPolicy::holds_limit() const { + return evidence_ && !evidence_->limit_continuation && !std::isnan(evidence_->limit_level) + && (evidence_->direction > 0 ? evidence_->cursor_price >= evidence_->limit_level + : evidence_->cursor_price <= evidence_->limit_level); +} +bool ExitActivationPolicy::continues_at_later_open() const { + return evidence_ && evidence_->limit_continuation + && evidence_->limit_continuation->cause == LimitContinuationCause::LaterSameOpen; +} +ExitLegActivationBounds ExitActivationPolicy::resolve(int64_t cycle, int entry_bar) const { + const int64_t first = entry_bar; + return {cycle, first + (holds_stop() ? 1 : 0), first + (holds_limit() ? 1 : 0)}; +} + +ExitActivationPolicy select_exit_activation(const PendingOrder& order, + double stop, double limit, const ExitActivationContext& c) { + if (!c.fill_recalc || !c.scheduler || !std::isfinite(c.cursor_price) + || c.side == PositionSide::FLAT || c.position_open_bar != c.bar_index) + return {}; + const bool long_side = c.side == PositionSide::LONG; + const bool limit_marketable = !std::isnan(limit) + && (long_side ? c.cursor_price >= limit : c.cursor_price <= limit); + const bool trailing = !std::isnan(order.trail_points) || !std::isnan(order.trail_price); + const bool later_open = !c.magnifier && historical_cascade_reach(order) + && c.after_first_open_fill && c.recalc_leg == 0 + && (!std::isnan(stop) || !std::isnan(limit)) && !trailing && limit_marketable; + const bool first_high_recross = !c.magnifier && !c.process_on_close + && !c.warmup && c.stream_idle && historical_cascade_reach(order) + && !c.historical_segment && c.at_extreme && c.historical_point == 1 + && c.recalc_leg == 1 && c.market_recalc_incarnation != 0 + && c.market_recalc_fill == c.current_fill + && long_side && c.position_entry_count == 1 && c.pyramiding == 0 + && c.lot_count == 1 && c.first_lot_incarnation == c.market_recalc_incarnation + && !order.from_entry.empty() && order.from_entry == c.first_lot_id + && !order.quantity_request.is_partial(internal::kFullQtyEps, internal::kFullPercentEps) + && std::isfinite(order.qty) + && std::abs(order.qty - c.position_quantity) <= internal::kQtyEpsilon + && c.pending_empty && order.oca_name.empty() && !trailing + && c.slippage == 0 && c.pointvalue == 1 && c.account_fx == 1 + && c.fx_series_empty && limit_marketable + && internal::bar_path_uses_high_first(c.bar) + && c.cursor_price == c.tick_high + && c.bar.low < order.limit_price && order.limit_price < c.bar.high + && (std::isnan(order.stop_price) || order.stop_price < c.bar.low); + std::optional continuation; + if (later_open) continuation = LimitContinuation{LimitContinuationCause::LaterSameOpen, c.current_fill}; + else if (first_high_recross) continuation = LimitContinuation{LimitContinuationCause::FirstHighRecross, c.current_fill}; + return ExitActivationPolicy({c.cycle, c.position_open_bar, long_side ? 1 : -1, + c.cursor_price, stop, limit, continuation}); +} + +} // namespace pineforge::compat::pine diff --git a/src/engine_fills.cpp b/src/engine_fills.cpp index e124c43c..eb5db227 100644 --- a/src/engine_fills.cpp +++ b/src/engine_fills.cpp @@ -683,11 +683,13 @@ BacktestEngine::CoofFillResult BacktestEngine::process_next_pending_order( const bool lower = raw == chart_bar->low && tick < raw; const bool long_position = position_side_ == PositionSide::LONG; const bool stop_touch = std::isfinite(order.stop_price) + && order.leg_activation.stop_ready(position_cycle_seq_, bar_index_) && ((!long_position && upper && raw < order.stop_price && order.stop_price <= tick) || (long_position && lower && tick <= order.stop_price && order.stop_price < raw)); const bool limit_touch = std::isfinite(order.limit_price) + && order.leg_activation.limit_ready(position_cycle_seq_, bar_index_) && ((long_position && upper && raw < order.limit_price && order.limit_price <= tick) || (!long_position && lower && tick <= order.limit_price @@ -2298,7 +2300,9 @@ void BacktestEngine::revive_position_brackets_after_margin_call_partial( ? o.qty_percent >= 100.0 - internal::kFullPercentEps : (!o.quantity_request.is_partial(kFullQtyEps, kFullPercentEps) || o.qty >= position_qty_ - kQtyEpsilon); + // Revival restores the leg, but cannot advance its activation bound. if (!full_pct || std::isnan(revive_stop) + || !o.leg_activation.stop_ready(position_cycle_seq_, bar_index_) || !std::isfinite(mc_price)) continue; const bool mk = (position_side_ == PositionSide::SHORT) ? (revive_stop <= mc_price) @@ -3072,10 +3076,10 @@ void BacktestEngine::sort_exit_siblings_by_path_fill(const Bar& bar) { bool is_ent_bar = (position_open_bar_ == bar_index_); double ma = exit_order_earliest_path_metric_no_trail( trigger_bar, high_first, a, position_side_, is_ent_bar, - position_entry_price_); + position_entry_price_, position_cycle_seq_, bar_index_); double mb = exit_order_earliest_path_metric_no_trail( trigger_bar, high_first, b, position_side_, is_ent_bar, - position_entry_price_); + position_entry_price_, position_cycle_seq_, bar_index_); const double inf = std::numeric_limits::infinity(); const double eps = kPathPosEps; if (ma < inf && mb < inf) { @@ -4113,19 +4117,15 @@ void BacktestEngine::sort_orders_by_fill_phase(const Bar& bar) { } bool exit_style = order_is_exit_style(o, position_side_); - const bool suppress_entry_bar_leg = - exit_style && position_open_bar_ == bar_index_; // Round 9 family X: a dormant bracket's stop / limit legs // are dead (finding-311 leg-scoped) — only its trail leg // can still fill, on the path. bool has_stop = !std::isnan(o.stop_price) && !o.dormant_bracket - && !(suppress_entry_bar_leg - && o.coof_suppress_stop_on_entry_bar); + && (!exit_style || o.leg_activation.stop_ready(position_cycle_seq_, bar_index_)); bool has_limit = !std::isnan(o.limit_price) && !o.dormant_bracket - && !(suppress_entry_bar_leg - && o.coof_suppress_limit_on_entry_bar); + && (!exit_style || o.leg_activation.limit_ready(position_cycle_seq_, bar_index_)); bool has_trail = !std::isnan(o.trail_points) || !std::isnan(o.trail_price); if (o.type == OrderType::MARKET @@ -4646,10 +4646,14 @@ bool BacktestEngine::prearmed_market_parent_bracket_gaps_at_open( // try_exit_open_gap_fill's resting-bracket precedence (trail, stop, // limit) for the same open-gap event on a later bar. const bool live_long = position_side_ == PositionSide::LONG; + // Apply readiness before precedence so a held stop cannot hide a ready + // limit or acquire a fill merely because an independent trail is present. const bool stop_gapped = std::isfinite(order.stop_price) + && order.leg_activation.stop_ready(position_cycle_seq_, bar_index_) && (live_long ? bar.open <= order.stop_price : bar.open >= order.stop_price); const bool limit_marketable = std::isfinite(order.limit_price) + && order.leg_activation.limit_ready(position_cycle_seq_, bar_index_) && (live_long ? bar.open >= order.limit_price : bar.open <= order.limit_price); if (!stop_gapped && !limit_marketable) return false; @@ -7779,6 +7783,7 @@ void BacktestEngine::apply_raw_order_fill(PendingOrder& order, double fill_price if (stream_observe_actions_) stream_observe_entry(pyramid_entries_.back()); id_unclosed_qty_[order.id] += qty; cycle_filled_entry_ids_.insert(order.id); + bind_retained_exit_activations(); if (!std::isnan(order.stop_price) || !std::isnan(order.limit_price)) { set_entry_fill_excursion_masks(pyramid_entries_.back(), current_bar_, fill_price); } @@ -8483,10 +8488,10 @@ BacktestEngine::FillEvaluation BacktestEngine::evaluate_fill_price( std::unordered_set& pass0_opposing_skip_ids) { bool exit_style = order_is_exit_style(order, position_side_); bool is_entry_bar = (exit_style && position_open_bar_ == bar_index_); - const bool suppress_stop = - is_entry_bar && order.coof_suppress_stop_on_entry_bar; - const bool suppress_limit = - is_entry_bar && order.coof_suppress_limit_on_entry_bar; + const bool suppress_stop = exit_style + && !order.leg_activation.stop_ready(position_cycle_seq_, bar_index_); + const bool suppress_limit = exit_style + && !order.leg_activation.limit_ready(position_cycle_seq_, bar_index_); // Round 9 family X (finding-311 is leg-scoped): a bracket killed by a // declined reversal reaches this kernel only for its live TRAIL leg; // its stop and limit legs stay dead until REVIVE-A/B. diff --git a/src/engine_internal.hpp b/src/engine_internal.hpp index 4f419145..a9c4a57f 100644 --- a/src/engine_internal.hpp +++ b/src/engine_internal.hpp @@ -376,14 +376,14 @@ double exit_order_earliest_path_metric_no_trail( const PendingOrder& order, PositionSide position_side, bool is_entry_bar, - double position_entry_price); + double position_entry_price, int64_t position_cycle = 0, int64_t bar_index = 0); double exit_order_earliest_path_metric_no_trail( const Bar& bar, bool high_first, const PendingOrder& order, PositionSide position_side, bool is_entry_bar, - double position_entry_price); + double position_entry_price, int64_t position_cycle = 0, int64_t bar_index = 0); // design-stop-tick-rounding: `tick_bar` is the bar the STOP / LIMIT legs are diff --git a/src/engine_orders.cpp b/src/engine_orders.cpp index b461fc4e..cbcb33c7 100644 --- a/src/engine_orders.cpp +++ b/src/engine_orders.cpp @@ -737,6 +737,7 @@ void BacktestEngine::emit_close_trade(const PyramidEntry& pe, double close_qty, // every full-close path (execute_market_exit) and by partial-exit settlement // when the FIFO loop drained the position. void BacktestEngine::reset_position_state_to_flat() { + unbind_exit_activations(); position_side_ = PositionSide::FLAT; position_cycle_seq_ = 0; position_entry_price_ = 0.0; @@ -798,6 +799,26 @@ void BacktestEngine::settle_position_after_partial_exit( } +// Exposure transitions resolve activation once. Matchers never refresh a +// deadline from whichever position happens to be current at read time. +void BacktestEngine::bind_exit_activation(PendingOrder& order) { + if (order.type != OrderType::EXIT) return; + if (position_side_ == PositionSide::FLAT || position_cycle_seq_ <= 0) { + order.leg_activation.unbind(); + return; + } + order.leg_activation.bind(order.pine_exit_activation.resolve( + position_cycle_seq_, position_open_bar_)); +} +void BacktestEngine::bind_retained_exit_activations() { + for (auto& order : pending_orders_) bind_exit_activation(order); +} +void BacktestEngine::unbind_exit_activations() { + for (auto& order : pending_orders_) { + if (order.type == OrderType::EXIT) order.leg_activation.unbind(); + } +} + // Establish a fresh position at fill_price/qty after a transition from FLAT // or a same-bar close. Resets all per-position state and seeds the first // pyramid entry. Used by every entry path that opens a brand-new position @@ -831,6 +852,7 @@ void BacktestEngine::open_fresh_position(PositionSide requested, double fill_pri if (stream_observe_actions_) stream_observe_entry(pyramid_entries_.back()); id_unclosed_qty_[id] += qty; cycle_filled_entry_ids_.insert(id); + bind_retained_exit_activations(); } diff --git a/src/engine_path_resolve.cpp b/src/engine_path_resolve.cpp index 3ddd64cf..9db88062 100644 --- a/src/engine_path_resolve.cpp +++ b/src/engine_path_resolve.cpp @@ -1108,10 +1108,10 @@ double exit_order_earliest_path_metric_no_trail( const PendingOrder& order, PositionSide position_side, bool is_entry_bar, - double position_entry_price) { + double position_entry_price, int64_t position_cycle, int64_t bar_index) { return exit_order_earliest_path_metric_no_trail( bar, bar_path_uses_high_first(bar), order, position_side, - is_entry_bar, position_entry_price); + is_entry_bar, position_entry_price, position_cycle, bar_index); } double exit_order_earliest_path_metric_no_trail( @@ -1120,7 +1120,7 @@ double exit_order_earliest_path_metric_no_trail( const PendingOrder& order, PositionSide position_side, bool is_entry_bar, - double position_entry_price) { + double position_entry_price, int64_t position_cycle, int64_t bar_index) { if (order.type != OrderType::EXIT) { return std::numeric_limits::infinity(); } @@ -1129,15 +1129,14 @@ double exit_order_earliest_path_metric_no_trail( } const bool is_long = (position_side == PositionSide::LONG); - // COOF entry-bar suppression is leg-scoped. A wrong-side leg is dormant - // only for the creation/entry bar; a correctly-sided sibling must retain - // its real path coordinate so sibling ordering cannot hide its fill. + // The owner transition resolved each leg's lower-bound coordinate. An + // unavailable leg cannot hide its independently ready sibling's path. const double stop_price = - is_entry_bar && order.coof_suppress_stop_on_entry_bar + !order.leg_activation.stop_ready(position_cycle, bar_index) ? std::numeric_limits::quiet_NaN() : order.stop_price; const double limit_price = - is_entry_bar && order.coof_suppress_limit_on_entry_bar + !order.leg_activation.limit_ready(position_cycle, bar_index) ? std::numeric_limits::quiet_NaN() : order.limit_price; if (std::isnan(stop_price) && std::isnan(limit_price)) { diff --git a/src/engine_state_hash.cpp b/src/engine_state_hash.cpp index f7222195..704892ee 100644 --- a/src/engine_state_hash.cpp +++ b/src/engine_state_hash.cpp @@ -86,9 +86,9 @@ void hash_str_set(Fnv& f, const std::unordered_set& s) { uint64_t BacktestEngine::broker_state_hash() const { Fnv f; - // v5 hashes typed request/reservation, generic predecessor and immutable birth. + // v6 includes resolved exit-leg owner/coordinates and immutable Pine placement evidence. // It is a serialization boundary, independent of the public C ABI version. - f.s("pineforge-broker-state/v5"); + f.s("pineforge-broker-state/v6"); // --- Position core --- f.i(static_cast(position_side_)); @@ -246,8 +246,19 @@ uint64_t BacktestEngine::broker_state_hash() const { f.u(o.named_cancel_surviving_exit_incarnation); // calc_on_order_fills birth provenance and per-leg suppression // (decide which waypoints / legs the order may fill at). - f.b(o.coof_suppress_stop_on_entry_bar); - f.b(o.coof_suppress_limit_on_entry_bar); + f.b(o.leg_activation.bounds().has_value()); + if (const auto& bounds = o.leg_activation.bounds()) { + f.i(bounds->position_cycle); f.i(bounds->stop_first_bar); f.i(bounds->limit_first_bar); + } + f.b(o.pine_exit_activation.evidence().has_value()); + if (const auto& evidence = o.pine_exit_activation.evidence()) { + f.i(evidence->position_cycle); f.i(evidence->entry_bar); f.i(evidence->direction); + f.d(evidence->cursor_price); f.d(evidence->stop_level); f.d(evidence->limit_level); + f.b(evidence->limit_continuation.has_value()); + if (const auto& continuation = evidence->limit_continuation) { + f.i(static_cast(continuation->cause)); f.u(continuation->observed_fill_sequence); + } + } f.i(static_cast(o.birth.cause())); f.i(o.birth.bar()); f.i(o.birth.timestamp()); diff --git a/src/engine_strategy_commands.cpp b/src/engine_strategy_commands.cpp index 302ea411..5a0fd56a 100644 --- a/src/engine_strategy_commands.cpp +++ b/src/engine_strategy_commands.cpp @@ -2171,75 +2171,27 @@ void BacktestEngine::strategy_exit(const std::string& id, const std::string& fro order.birth, has_trail_request); // Later-open trailing permission is derived by the Pine policy from the // immutable physical origin. It never rewrites that origin. - // A priced exit born after a later fill at the SAME O is already held by - // the KI-67 cascade gate for its in-flight leg 0. The pinned exception is - // LIMIT-only: a marketable limit may resume at W1. A marketable stop keeps - // the established whole-entry-bar suppression (including M1). - const bool later_same_open_priced_exit_on_entry_bar = - !bar_magnifier_enabled_ && compat::pine::historical_cascade_reach(order) - && coof_recalc_after_first_open_fill_ - && coof_cascade_recalc_leg_ == 0 - && position_open_bar_ == bar_index_ - && (!std::isnan(stop_price) || !std::isnan(limit_price)) - && std::isnan(trail_points) && std::isnan(trail_price); - bool stop_marketable_at_coof_cursor = false; - bool limit_marketable_at_coof_cursor = false; - bool later_same_open_marketable_limit = false; - if (coof_fill_recalc_active_ && coof_scheduler_active_ - && std::isfinite(coof_cursor_price_) - && position_side_ != PositionSide::FLAT - && position_open_bar_ == bar_index_) { - const bool closing_long = position_side_ == PositionSide::LONG; - stop_marketable_at_coof_cursor = !std::isnan(stop_price) - && (closing_long ? coof_cursor_price_ <= stop_price - : coof_cursor_price_ >= stop_price); - limit_marketable_at_coof_cursor = !std::isnan(limit_price) - && (closing_long ? coof_cursor_price_ >= limit_price - : coof_cursor_price_ <= limit_price); - later_same_open_marketable_limit = - later_same_open_priced_exit_on_entry_bar - && limit_marketable_at_coof_cursor; - // Round15 F/EUR JOAT pins: a fresh MARKET long at W1=H arms a - // marketable full limit, waits through H->L, and takes its later L->C - // recross at the exact level. It neither fills at placement nor gets - // a new waypoint-gap permission. Keep KI-67's existing leg gate. - // This first patch covers only a limit strictly inside H/L with no - // reachable stop competitor and the actual opening's first callback. - const bool first_high_market_limit_recross = - !bar_magnifier_enabled_ && !process_orders_on_close_ - && !stream_warmup_mode_ && stream_phase_ == StreamPhase::IDLE - && compat::pine::historical_cascade_reach(order) && !coof_hist_is_segment_ - && coof_at_extreme_waypoint_ && coof_hist_path_index_ == 1 - && coof_cascade_recalc_leg_ == 1 - && coof_market_entry_recalc_incarnation_ != 0 - && coof_market_entry_recalc_fill_seq_ == broker_fill_event_seq_ - && position_side_ == PositionSide::LONG - && position_entry_count_ == 1 && pyramiding_ == 0 - && pyramid_entries_.size() == 1 - && pyramid_entries_.front().entry_incarnation - == coof_market_entry_recalc_incarnation_ - && !from_entry.empty() - && from_entry == pyramid_entries_.front().entry_id - && !is_partial && std::isfinite(reserved_qty) - && std::abs(reserved_qty - position_qty_) <= kQtyEpsilon - && pending_orders_.empty() && oca_name.empty() - && !has_trail_request && slippage_ == 0 - && syminfo_.pointvalue == 1 && account_currency_fx_ == 1 - && account_currency_fx_timestamps_.empty() - && limit_marketable_at_coof_cursor - && internal::bar_path_uses_high_first(current_bar_) - && coof_cursor_price_ == bar_fill_price(current_bar_.high) - && current_bar_.low < order.limit_price - && order.limit_price < current_bar_.high - && (std::isnan(order.stop_price) - || order.stop_price < current_bar_.low); - order.coof_suppress_stop_on_entry_bar = - stop_marketable_at_coof_cursor; - order.coof_suppress_limit_on_entry_bar = - limit_marketable_at_coof_cursor - && !later_same_open_marketable_limit - && !first_high_market_limit_recross; - } + const std::string no_entry_id; + const auto& first_entry_id = pyramid_entries_.empty() + ? no_entry_id : pyramid_entries_.front().entry_id; + const uint64_t first_entry_incarnation = pyramid_entries_.empty() + ? 0 : pyramid_entries_.front().entry_incarnation; + order.pine_exit_activation = compat::pine::select_exit_activation( + order, stop_price, limit_price, + {current_bar_, position_side_, position_cycle_seq_, bar_index_, + position_open_bar_, position_entry_count_, position_qty_, pyramiding_, + pyramid_entries_.size(), first_entry_id, first_entry_incarnation, + coof_fill_recalc_active_, coof_scheduler_active_, coof_cursor_price_, + coof_recalc_after_first_open_fill_, coof_cascade_recalc_leg_, + coof_hist_is_segment_, coof_at_extreme_waypoint_, coof_hist_path_index_, + coof_market_entry_recalc_incarnation_, coof_market_entry_recalc_fill_seq_, + broker_fill_event_seq_, bar_magnifier_enabled_, process_orders_on_close_, + stream_warmup_mode_, stream_phase_ == StreamPhase::IDLE, + pending_orders_.empty(), slippage_, syminfo_.pointvalue, account_currency_fx_, + account_currency_fx_timestamps_.empty(), bar_fill_price(current_bar_.high)}); + const bool later_same_open_marketable_limit = + order.pine_exit_activation.continues_at_later_open(); + bind_exit_activation(order); // KI-67 exit cascade (Model S). Record this mid-bar cascade exit's in-flight // leg so the historical dispatch gate can hold it on that leg's remainder, // exact-fill it on subsequent legs, and gap-fill it at the in-flight leg-end @@ -2890,6 +2842,7 @@ uint64_t BacktestEngine::queue_deferred_close_order( // against E2 can reserve 2 against new E4). Do not fabricate an original // Pine percentage, or an exposure-coverage receipt before that binding. order.quantity_request.request(QuantityIntent::units(qty_to_close)); + bind_exit_activation(order); order.oca_name = ""; order.oca_type = 0; order.created_bar = bar_index_; diff --git a/src/engine_stream.cpp b/src/engine_stream.cpp index c121c11f..1e522edd 100644 --- a/src/engine_stream.cpp +++ b/src/engine_stream.cpp @@ -678,7 +678,7 @@ uint64_t BacktestEngine::stream_state_hash() const { integer(static_cast(bar.timestamp)); real(bar.open); real(bar.high); real(bar.low); real(bar.close); real(bar.volume); }; - integer(5); integer(broker_state_hash()); + integer(6); integer(broker_state_hash()); integer(static_cast(stream_phase_)); integer(static_cast(stream_input_mode_)); integer(static_cast(stream_input_tf_ms_)); diff --git a/src/pending_order_mirror.cpp b/src/pending_order_mirror.cpp index f0e99c57..e6e82a76 100644 --- a/src/pending_order_mirror.cpp +++ b/src/pending_order_mirror.cpp @@ -58,8 +58,8 @@ void fill_pending_order_mirror(const PendingOrder& src, pf_pending_order_v1_t* o out->recreated_after_named_cancelled_entry_incarnation = src.recreated_after_named_cancelled_entry_incarnation; out->named_cancel_surviving_exit_incarnation = src.named_cancel_surviving_exit_incarnation; out->stop_limit_activated = src.stop_limit_activated ? 1 : 0; - out->coof_suppress_stop_on_entry_bar = src.coof_suppress_stop_on_entry_bar ? 1 : 0; - out->coof_suppress_limit_on_entry_bar = src.coof_suppress_limit_on_entry_bar ? 1 : 0; + out->coof_suppress_stop_on_entry_bar = src.pine_exit_activation.holds_stop() ? 1 : 0; + out->coof_suppress_limit_on_entry_bar = src.pine_exit_activation.holds_limit() ? 1 : 0; out->created_during_coof_recalc = src.birth.from_fill() ? 1 : 0; out->coof_born_at_close_recalc = src.birth.at_terminal_fill() ? 1 : 0; out->coof_born_mid_bar = compat::pine::historical_cascade_reach(src) ? 1 : 0; @@ -150,6 +150,20 @@ void fill_pending_order_mirror(const PendingOrder& src, pf_pending_order_v1_t* o out->quantity_reservation_present = src.quantity_request.reservation().has_value() ? 1 : 0; out->quantity_reservation_units = src.quantity_request.reservation() ? src.quantity_request.reservation()->units : 0.0; out->quantity_reservation_basis_units = src.quantity_request.reservation() ? src.quantity_request.reservation()->basis_units : 0.0; + out->leg_activation_owner_cycle = src.leg_activation.bounds() ? src.leg_activation.bounds()->position_cycle : 0; + out->leg_activation_present = src.leg_activation.bounds().has_value() ? 1 : 0; + out->leg_activation_stop_first_bar = src.leg_activation.bounds() ? src.leg_activation.bounds()->stop_first_bar : 0; + out->leg_activation_limit_first_bar = src.leg_activation.bounds() ? src.leg_activation.bounds()->limit_first_bar : 0; + out->pine_exit_activation_owner_cycle_at_birth = src.pine_exit_activation.evidence() ? src.pine_exit_activation.evidence()->position_cycle : 0; + out->pine_exit_activation_present = src.pine_exit_activation.evidence().has_value() ? 1 : 0; + out->pine_exit_activation_entry_bar_at_birth = src.pine_exit_activation.evidence() ? src.pine_exit_activation.evidence()->entry_bar : 0; + out->pine_exit_activation_direction_at_birth = src.pine_exit_activation.evidence() ? src.pine_exit_activation.evidence()->direction : 0; + out->pine_exit_activation_cursor_price_at_birth = src.pine_exit_activation.evidence() ? src.pine_exit_activation.evidence()->cursor_price : 0.0; + out->pine_exit_activation_stop_level_at_birth = src.pine_exit_activation.evidence() ? src.pine_exit_activation.evidence()->stop_level : 0.0; + out->pine_exit_activation_limit_level_at_birth = src.pine_exit_activation.evidence() ? src.pine_exit_activation.evidence()->limit_level : 0.0; + out->pine_exit_activation_limit_continuation_present = src.pine_exit_activation.evidence() && src.pine_exit_activation.evidence()->limit_continuation ? 1 : 0; + out->pine_exit_activation_limit_continuation_cause = src.pine_exit_activation.evidence() && src.pine_exit_activation.evidence()->limit_continuation ? static_cast(src.pine_exit_activation.evidence()->limit_continuation->cause) : 0; + out->pine_exit_activation_limit_continuation_fill = src.pine_exit_activation.evidence() && src.pine_exit_activation.evidence()->limit_continuation ? src.pine_exit_activation.evidence()->limit_continuation->observed_fill_sequence : 0; } namespace { @@ -287,6 +301,20 @@ const pf_field_desc_t kLayout[] = { PF_PO_FIELD(quantity_reservation_present, "uint8_t"), PF_PO_FIELD(quantity_reservation_units, "double"), PF_PO_FIELD(quantity_reservation_basis_units, "double"), + PF_PO_FIELD(leg_activation_owner_cycle, "int64_t"), + PF_PO_FIELD(leg_activation_present, "uint8_t"), + PF_PO_FIELD(leg_activation_stop_first_bar, "int64_t"), + PF_PO_FIELD(leg_activation_limit_first_bar, "int64_t"), + PF_PO_FIELD(pine_exit_activation_owner_cycle_at_birth, "int64_t"), + PF_PO_FIELD(pine_exit_activation_present, "uint8_t"), + PF_PO_FIELD(pine_exit_activation_entry_bar_at_birth, "int32_t"), + PF_PO_FIELD(pine_exit_activation_direction_at_birth, "int32_t"), + PF_PO_FIELD(pine_exit_activation_cursor_price_at_birth, "double"), + PF_PO_FIELD(pine_exit_activation_stop_level_at_birth, "double"), + PF_PO_FIELD(pine_exit_activation_limit_level_at_birth, "double"), + PF_PO_FIELD(pine_exit_activation_limit_continuation_present, "uint8_t"), + PF_PO_FIELD(pine_exit_activation_limit_continuation_cause, "int32_t"), + PF_PO_FIELD(pine_exit_activation_limit_continuation_fill, "uint64_t"), }; #undef PF_PO_FIELD diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index aab7cf1f..5a7de69a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,6 @@ set(TEST_SOURCES + test_exit_leg_activation + test_exit_activation_routes test_pending_order_core test_pending_quantity_intent test_bulk_preflight diff --git a/tests/fixtures/leg_activation/149f77c_pending_mirror.hpp b/tests/fixtures/leg_activation/149f77c_pending_mirror.hpp new file mode 100644 index 00000000..0bc79a65 --- /dev/null +++ b/tests/fixtures/leg_activation/149f77c_pending_mirror.hpp @@ -0,0 +1,156 @@ +// GENERATED by scripts/gen_pending_order_mirror.py from include/pineforge/engine.hpp -- do not edit. +// 94 PendingOrder members mirrored (128 POD fields incl. struct_version/size). +#pragma once +#include + +/* C-compatible value snapshot of one resting pineforge::PendingOrder + * (spec 3.6). struct_version identifies the field set (this file: + * 1); size is sizeof(pf_pending_order_v1_t) as the producer + * compiled it. Strings are copied into a NUL-terminated char[64] + * (name_truncated = 1 when the source was longer than 63 bytes) with + * name_hash64 = FNV-1a 64 of the FULL source string. Enums are their + * int32 value; bool is 0/1 in a uint8_t. Append-only, like every + * pineforge.h POD. */ +typedef struct pf_pending_order_v1_s { + uint32_t struct_version; + uint32_t size; + char id[64]; + uint8_t id_truncated; + uint64_t id_hash64; + char from_entry[64]; + uint8_t from_entry_truncated; + uint64_t from_entry_hash64; + int32_t type; + uint8_t is_long; + double limit_price; + double stop_price; + double trail_points; + double trail_price; + double trail_offset; + double profit_ticks; + double loss_ticks; + double qty; + int32_t qty_type; + double qty_percent; + char oca_name[64]; + uint8_t oca_name_truncated; + uint64_t oca_name_hash64; + int32_t oca_type; + int32_t created_bar; + int64_t created_seq; + uint64_t incarnation; + uint8_t created_by_same_id_replacement; // deprecated, derived output only + uint64_t replaced_default_market_incarnation; + uint8_t declined_by_replaced_short_market; + uint64_t replaced_exit_order_incarnation; // deprecated, derived output only + uint64_t recreated_after_named_cancelled_entry_incarnation; + uint64_t named_cancel_surviving_exit_incarnation; + uint8_t stop_limit_activated; + uint8_t coof_suppress_stop_on_entry_bar; + uint8_t coof_suppress_limit_on_entry_bar; + uint8_t created_during_coof_recalc; // deprecated, derived output only + uint8_t coof_born_at_close_recalc; // deprecated, derived output only + uint8_t coof_born_mid_bar; // deprecated, derived output only + int32_t coof_cascade_seg_i; + uint8_t coof_cascade_inflight_fires; + int32_t created_position_side; + int64_t created_position_cycle_seq; + uint8_t created_after_position_close_in_bar; + uint8_t over_pyramiding_cap_at_placement; + int32_t same_id_stop_deferred_close_all_bar; + uint64_t same_id_stop_deferred_close_all_incarnation; + uint8_t reverses_same_bar_market_from_flat; + uint8_t paired_flat_market_candidate; + double paired_flat_market_own_qty; + double paired_flat_market_signal_close; + double paired_flat_market_signal_equity; + double paired_flat_market_signal_margin_pct; + double paired_flat_market_signal_pointvalue; + double paired_flat_market_signal_fx; + int64_t paired_flat_market_peer_seq; + double paired_flat_market_transaction_qty; + uint8_t default_flat_market_gross_candidate; + double tv_carry_qty; + double frozen_default_qty; + double default_stop_placement_qty; + double default_stop_placement_equity; + double default_stop_placement_signal_close; + double default_stop_sizing_price; + double sizing_equity; + double sizing_price; + double sizing_fx; + double sizing_mark; + uint8_t opening_affordability_exemption_candidate; + uint8_t explicit_flat_admission_candidate; + double explicit_placement_equity; + double explicit_slipped_signal_close; + double affordability_placement_equity; + double affordability_signal_price; + double affordability_held_qty; + uint8_t affordability_close_only; + uint8_t rounded_signal_cost_close_only; + int32_t signal_close_mc_bar; + uint64_t signal_close_mc_entry_incarnation; + uint64_t signal_close_mc_fill_seq; + double signal_close_mc_remaining_qty; + char comment[64]; + uint8_t comment_truncated; + uint64_t comment_hash64; + uint8_t requested_partial; // deprecated, derived output only + uint8_t full_percent_exit_request; // deprecated, derived output only + uint8_t pooc_global_full_exit_dynamic_qty; + uint8_t pooc_global_full_exit_tracks_bound_adds; + uint8_t pooc_global_full_exit_bound_add; + uint8_t created_while_in_position; // deprecated, derived output only + uint8_t sbmt_member; + double sbmt_own_qty; + double sbmt_tx_qty; + uint8_t sbmt_kept_over_cap; + double sbmt_close_qty; + uint8_t sbmt_close_buy; + uint8_t suppress_as_declined_reversal_close; + uint8_t dormant_bracket; + uint8_t dormant_reissue_pending; + double dormant_original_stop_price; + int32_t dormant_hold_bar; + int32_t dormant_reversal_kill_bar; + double dormant_trail_best; + double dormant_trail_best_start; + uint8_t dormant_trail_leg_dead; + double suppressed_close_consumed_ledger_qty; + double suppressed_close_retired_ledger_qty; + int32_t short_seed_collision_role; + uint64_t replaced_order_incarnation; + int64_t birth_timestamp; + int32_t birth_cause; + int32_t birth_bar; + int32_t birth_cursor_domain; + int32_t birth_cursor_position; + int32_t birth_cursor_index; + int32_t birth_cursor_count; + double birth_cursor_price; + uint64_t birth_first_fill; + uint64_t birth_last_fill; + uint64_t birth_evaluation_ordinal; + int32_t pine_birth_reach; + uint64_t quantity_intent_kind; + double quantity_intent_units; + double quantity_intent_numerator; + double quantity_intent_denominator; + uint8_t quantity_reservation_present; + double quantity_reservation_units; + double quantity_reservation_basis_units; +} pf_pending_order_v1_t; + +/* One row of the self-describing layout table returned by + * strategy_pending_order_layout(): field name, C type spelling + * ("uint8_t", "int32_t", "int64_t", "uint64_t", "double", "char[64]", + * "uint32_t"), byte offset inside pf_pending_order_v1_t, byte size. */ +typedef struct pf_field_desc_s { + const char* name; + const char* type; + uint32_t offset; + uint32_t size; +} pf_field_desc_t; +#define PF_PENDING_ORDER_STRUCT_VERSION 1 +#define PF_PENDING_ORDER_STR_CAP 64 diff --git a/tests/fixtures/leg_activation/README.md b/tests/fixtures/leg_activation/README.md new file mode 100644 index 00000000..d4e6829a --- /dev/null +++ b/tests/fixtures/leg_activation/README.md @@ -0,0 +1,2 @@ +Exact base149f77c public pending-order mirror, used only for compile-time prefix-layout controls. +SHA-256 27d2c6b6345521bcae14d24c23cce75846516b8bff52541ea1d499f8e2fc8163 diff --git a/tests/fixtures/script_cpp_abi/base149/README.md b/tests/fixtures/script_cpp_abi/base149/README.md new file mode 100644 index 00000000..bb9c862e --- /dev/null +++ b/tests/fixtures/script_cpp_abi/base149/README.md @@ -0,0 +1,2 @@ +Exact shipped149f77c/v5 public header closure for native, generated-style and standalone PendingOrder compile/link-only controls. +No executable runs; old symbol stubs only prove link compatibility. Files are independently bound to original Git blobs. diff --git a/tests/fixtures/script_cpp_abi/base149/headers.json.gz b/tests/fixtures/script_cpp_abi/base149/headers.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..3b74f40b6ef7b169d9bb50fad624261ae4311b2a GIT binary patch literal 142481 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 +#include +#include +#include +#include +#include +using namespace pineforge; +namespace { +constexpr double missing = std::numeric_limits::quiet_NaN(); +int checks = 0, failures = 0; +#define CHECK(value) do { ++checks; if (!(value)) { ++failures; std::fprintf(stderr, "FAIL %d: %s\n", __LINE__, #value); } } while (0) + +class MarginBook : public BacktestEngine { +public: + MarginBook() { + initial_capital_ = 1000; + commission_value_ = 0; + margin_long_ = margin_short_ = 50; + pyramiding_ = 10; + qty_step_ = 1; + current_bar_ = {100, 100, 100, 100, 1, 0}; + } + void on_bar(const Bar&) override {} + PendingOrder& child() { + for (auto& order : pending_orders_) if (order.id == "X") return order; + throw std::logic_error("missing native bracket"); + } + void exercise(int mode) { + strategy_entry("E", true, missing, missing, 20); + ++bar_index_; + current_bar_ = {100, 100, 100, 100, 1, 60000}; + process_pending_orders(current_bar_); + CHECK(position_qty_ == 20 && position_cycle_seq_ == 1); + strategy_exit("X", "E", missing, 110); + // A valid dormant state is the fixture precondition. The originating + // rejection is separate from this activation/risk settlement contract. + child().dormant_bracket = true; + const bool ready = mode == 1; + const bool foreign = mode == 2; + child().leg_activation.bind({foreign ? 99 : position_cycle_seq_, ready ? 2 : 5, 5}); + ++bar_index_; + current_bar_ = {95, 95, 95, 95, 1, 120000}; + process_margin_call(current_bar_); + // Equity900 < margin950. The existing risk rule liquidates + // 4 * floor((950-900)/0.5/95) = 4 units, independently of the bracket. + CHECK(!trades_.empty()); + if (trades_.empty()) return; + CHECK(trades_[0].exit_id == "__margin_call__"); + CHECK(trades_[0].qty == 4 && trades_[0].exit_price == 95); + CHECK(trades_[0].exit_bar_index == 2); + if (ready) { + CHECK(position_qty_ == 0 && trades_.size() == 2); + if (trades_.size() != 2) return; + CHECK(trades_[1].exit_id == "X" && trades_[1].qty == 16); + CHECK(trades_[1].exit_price == 95 && trades_[1].exit_bar_index == 2); + return; + } + CHECK(position_qty_ == 16 && trades_.size() == 1); + CHECK(!child().dormant_bracket); // metadata revival is independent + CHECK(child().leg_activation.bounds()->stop_first_bar == 5); + for (int bar = 3; bar <= 5; ++bar) { + bar_index_ = bar; + current_bar_ = {95, 95, 95, 95, 1, bar * 60000LL}; + process_pending_orders(current_bar_); + CHECK(position_qty_ == (bar < 5 || foreign ? 16 : 0)); + } + if (foreign) { + CHECK(trades_.size() == 1); + child().leg_activation.bind({position_cycle_seq_, 5, 5}); + bar_index_ = 6; + current_bar_ = {95, 95, 95, 95, 1, 360000}; + process_pending_orders(current_bar_); + } + CHECK(position_qty_ == 0 && trades_.size() == 2); + if (trades_.size() != 2) return; + CHECK(trades_[1].exit_id == "X" && trades_[1].qty == 16); + CHECK(trades_[1].exit_price == 95); + CHECK(trades_[1].exit_bar_index == (foreign ? 6 : 5)); + } +}; + +enum class GapCase { HeldStop, ReadyLimit, HeldWithTrail, ReadyStop, + BothHeld, ForeignWithTrail, BothReady, LimitOnly }; +class PrearmedFrame : public BacktestEngine { +public: + PrearmedFrame() { + initial_capital_ = 100000; + commission_value_ = 0; + margin_long_ = margin_short_ = 0; + pyramiding_ = 0; + slippage_ = 2; + syminfo_mintick_ = 0.01; + current_bar_ = {100, 100, 100, 100, 1, 0}; + } + void on_bar(const Bar&) override {} + void exercise(GapCase mode) { + const bool trail = mode == GapCase::HeldWithTrail || mode == GapCase::ForeignWithTrail; + strategy_entry("E", true, missing, missing, 1); + strategy_exit("X", "E", mode == GapCase::HeldStop ? 150 : 90, + mode == GapCase::LimitOnly ? missing : 110, + trail ? 1000 : missing, trail ? 1 : missing); + const auto frame = pending_orders_; + CHECK(frame.size() == 2); + if (frame.size() != 2) return; + pending_orders_.resize(1); + ++bar_index_; + current_bar_ = {100, 100, 100, 100, 1, 60000}; + process_pending_orders(current_bar_); + CHECK(position_qty_ == 1 && position_side_ == PositionSide::LONG); + CHECK(std::abs(position_entry_price_ - 100.02) < 1e-9); + // Explicit post-parent/pre-compaction snapshot: retain the actual + // parent identity with no executable remainder. This targets the real + // matching route, not public placement chronology. + pending_orders_ = frame; + pending_orders_[0].qty = 0; + const bool stop_ready = mode == GapCase::ReadyStop || mode == GapCase::BothReady; + const bool limit_ready = mode == GapCase::HeldStop || mode == GapCase::ReadyLimit + || mode == GapCase::BothReady || mode == GapCase::LimitOnly; + pending_orders_[1].leg_activation.bind({ + mode == GapCase::ForeignWithTrail ? 99 : position_cycle_seq_, + stop_ready ? 1 : 5, limit_ready ? 1 : 5}); + process_pending_orders(current_bar_); + const bool filled = mode == GapCase::ReadyLimit || mode == GapCase::ReadyStop + || mode == GapCase::BothReady || mode == GapCase::LimitOnly; + CHECK(position_qty_ == (filled ? 0 : 1)); + CHECK(trades_.size() == (filled ? 1u : 0u)); + if (filled && trades_.size() == 1) { + const bool limit = mode == GapCase::ReadyLimit || mode == GapCase::LimitOnly; + CHECK(trades_[0].exit_id == "X" && trades_[0].qty == 1); + // Ready limits use the unslipped100 open; stop precedence uses + // 99.98. A held stop cannot borrow a ready sibling's permission. + CHECK(std::abs(trades_[0].exit_price - (limit ? 100 : 99.98)) < 1e-9); + } + } +}; + +class ChartPointBook : public BacktestEngine { + bool long_side_; + bool stop_leg_; + bool armed_ = false; + int first_bar_; +public: + ChartPointBook(bool long_side, bool stop_leg, int first_bar) + : long_side_(long_side), stop_leg_(stop_leg), first_bar_(first_bar) { + initial_capital_ = 100000; + commission_value_ = 0; + margin_long_ = margin_short_ = 0; + default_qty_type_ = QtyType::FIXED; + default_qty_value_ = 1; + pyramiding_ = 0; + calc_on_order_fills_ = true; + syminfo_mintick_ = 0.01; + } + double level() const { return long_side_ == stop_leg_ ? 9.90 : 10.26; } + void on_bar(const Bar&) override { + if (bar_index_ == 0) strategy_entry("E", long_side_, missing, missing, 1); + if (bar_index_ != 1 || !coof_fill_recalc_active_ || armed_) return; + armed_ = true; + strategy_exit("X", "E", stop_leg_ ? missing : level(), stop_leg_ ? level() : missing); + for (auto& order : pending_orders_) if (order.id == "X") { + order.leg_activation.bind({position_cycle_seq_, first_bar_, first_bar_}); + } + } + void exercise() { + // The raw extremes do not reach9.90/10.26, but their chart tick + // projections do. Test all long/short stop/limit combinations. + const Bar bars[] = { + {10, 10, 10, 10, 1, 0}, {10, 10, 10, 10, 1, 60000}, + {10, 10.256, 9.904, 10, 1, 120000}, + {10, 10, 10, 10, 1, 180000}, {10, 10, 10, 10, 1, 240000}, + {10, 10.256, 9.904, 10, 1, 300000}, + }; + run(bars, 6); + CHECK(last_error().empty()); + CHECK(trades_.size() == 1); + if (trades_.size() != 1) return; + CHECK(trades_[0].exit_id == "X" && trades_[0].qty == 1); + CHECK(trades_[0].exit_bar_index == first_bar_); + CHECK(std::abs(trades_[0].exit_price - level()) < 1e-9); + } +}; +} +int main() { + for (int mode = 0; mode < 3; ++mode) { + try { MarginBook book; book.exercise(mode); } + catch (const std::exception& e) { ++failures; std::fprintf(stderr, "margin: %s\n", e.what()); } + } + for (int mode = 0; mode < 8; ++mode) { + try { PrearmedFrame book; book.exercise(static_cast(mode)); } + catch (const std::exception& e) { ++failures; std::fprintf(stderr, "prearmed: %s\n", e.what()); } + } + for (bool long_side : {false, true}) { + for (bool stop_leg : {false, true}) { + for (int first_bar : {2, 5}) { + try { ChartPointBook book(long_side, stop_leg, first_bar); book.exercise(); } + catch (const std::exception& e) { ++failures; std::fprintf(stderr, "chart point: %s\n", e.what()); } + } + } + } + std::printf("native activation routes: %d checks, %d failures\n", checks, failures); + return failures ? 1 : 0; +} diff --git a/tests/test_exit_leg_activation.cpp b/tests/test_exit_leg_activation.cpp new file mode 100644 index 00000000..e7099dcf --- /dev/null +++ b/tests/test_exit_leg_activation.cpp @@ -0,0 +1,384 @@ +// Literal native source-boundary witness. No Pine, reference tape or grader. +#include +#include +#include +namespace prior_leg_mirror { +#include "fixtures/leg_activation/149f77c_pending_mirror.hpp" +} +#include +#include +#include +static_assert(offsetof(pf_pending_order_v1_t, struct_version) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, struct_version), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, size) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, size), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, id) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, id), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, id_truncated) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, id_truncated), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, id_hash64) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, id_hash64), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, from_entry) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, from_entry), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, from_entry_truncated) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, from_entry_truncated), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, from_entry_hash64) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, from_entry_hash64), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, type) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, type), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, is_long) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, is_long), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, limit_price) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, limit_price), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, stop_price) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, stop_price), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, trail_points) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, trail_points), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, trail_price) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, trail_price), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, trail_offset) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, trail_offset), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, profit_ticks) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, profit_ticks), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, loss_ticks) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, loss_ticks), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, qty_type) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, qty_type), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, qty_percent) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, qty_percent), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, oca_name) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, oca_name), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, oca_name_truncated) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, oca_name_truncated), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, oca_name_hash64) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, oca_name_hash64), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, oca_type) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, oca_type), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, created_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, created_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, created_seq) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, created_seq), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, incarnation) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, incarnation), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, created_by_same_id_replacement) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, created_by_same_id_replacement), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, replaced_default_market_incarnation) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, replaced_default_market_incarnation), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, declined_by_replaced_short_market) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, declined_by_replaced_short_market), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, replaced_exit_order_incarnation) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, replaced_exit_order_incarnation), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, recreated_after_named_cancelled_entry_incarnation) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, recreated_after_named_cancelled_entry_incarnation), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, named_cancel_surviving_exit_incarnation) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, named_cancel_surviving_exit_incarnation), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, stop_limit_activated) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, stop_limit_activated), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, coof_suppress_stop_on_entry_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, coof_suppress_stop_on_entry_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, coof_suppress_limit_on_entry_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, coof_suppress_limit_on_entry_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, created_during_coof_recalc) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, created_during_coof_recalc), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, coof_born_at_close_recalc) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, coof_born_at_close_recalc), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, coof_born_mid_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, coof_born_mid_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, coof_cascade_seg_i) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, coof_cascade_seg_i), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, coof_cascade_inflight_fires) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, coof_cascade_inflight_fires), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, created_position_side) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, created_position_side), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, created_position_cycle_seq) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, created_position_cycle_seq), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, created_after_position_close_in_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, created_after_position_close_in_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, over_pyramiding_cap_at_placement) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, over_pyramiding_cap_at_placement), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, same_id_stop_deferred_close_all_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, same_id_stop_deferred_close_all_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, same_id_stop_deferred_close_all_incarnation) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, same_id_stop_deferred_close_all_incarnation), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, reverses_same_bar_market_from_flat) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, reverses_same_bar_market_from_flat), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_candidate) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_candidate), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_own_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_own_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_signal_close) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_signal_close), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_signal_equity) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_signal_equity), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_signal_margin_pct) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_signal_margin_pct), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_signal_pointvalue) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_signal_pointvalue), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_signal_fx) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_signal_fx), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_peer_seq) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_peer_seq), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, paired_flat_market_transaction_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, paired_flat_market_transaction_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, default_flat_market_gross_candidate) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, default_flat_market_gross_candidate), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, tv_carry_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, tv_carry_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, frozen_default_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, frozen_default_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, default_stop_placement_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, default_stop_placement_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, default_stop_placement_equity) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, default_stop_placement_equity), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, default_stop_placement_signal_close) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, default_stop_placement_signal_close), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, default_stop_sizing_price) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, default_stop_sizing_price), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sizing_equity) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sizing_equity), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sizing_price) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sizing_price), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sizing_fx) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sizing_fx), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sizing_mark) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sizing_mark), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, opening_affordability_exemption_candidate) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, opening_affordability_exemption_candidate), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, explicit_flat_admission_candidate) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, explicit_flat_admission_candidate), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, explicit_placement_equity) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, explicit_placement_equity), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, explicit_slipped_signal_close) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, explicit_slipped_signal_close), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, affordability_placement_equity) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, affordability_placement_equity), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, affordability_signal_price) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, affordability_signal_price), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, affordability_held_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, affordability_held_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, affordability_close_only) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, affordability_close_only), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, rounded_signal_cost_close_only) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, rounded_signal_cost_close_only), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, signal_close_mc_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, signal_close_mc_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, signal_close_mc_entry_incarnation) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, signal_close_mc_entry_incarnation), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, signal_close_mc_fill_seq) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, signal_close_mc_fill_seq), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, signal_close_mc_remaining_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, signal_close_mc_remaining_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, comment) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, comment), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, comment_truncated) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, comment_truncated), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, comment_hash64) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, comment_hash64), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, requested_partial) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, requested_partial), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, full_percent_exit_request) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, full_percent_exit_request), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, pooc_global_full_exit_dynamic_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, pooc_global_full_exit_dynamic_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, pooc_global_full_exit_tracks_bound_adds) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, pooc_global_full_exit_tracks_bound_adds), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, pooc_global_full_exit_bound_add) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, pooc_global_full_exit_bound_add), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, created_while_in_position) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, created_while_in_position), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sbmt_member) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sbmt_member), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sbmt_own_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sbmt_own_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sbmt_tx_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sbmt_tx_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sbmt_kept_over_cap) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sbmt_kept_over_cap), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sbmt_close_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sbmt_close_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, sbmt_close_buy) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, sbmt_close_buy), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, suppress_as_declined_reversal_close) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, suppress_as_declined_reversal_close), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, dormant_bracket) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, dormant_bracket), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, dormant_reissue_pending) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, dormant_reissue_pending), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, dormant_original_stop_price) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, dormant_original_stop_price), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, dormant_hold_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, dormant_hold_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, dormant_reversal_kill_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, dormant_reversal_kill_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, dormant_trail_best) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, dormant_trail_best), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, dormant_trail_best_start) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, dormant_trail_best_start), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, dormant_trail_leg_dead) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, dormant_trail_leg_dead), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, suppressed_close_consumed_ledger_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, suppressed_close_consumed_ledger_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, suppressed_close_retired_ledger_qty) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, suppressed_close_retired_ledger_qty), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, short_seed_collision_role) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, short_seed_collision_role), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, replaced_order_incarnation) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, replaced_order_incarnation), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_timestamp) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_timestamp), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_cause) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_cause), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_bar) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_bar), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_cursor_domain) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_cursor_domain), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_cursor_position) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_cursor_position), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_cursor_index) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_cursor_index), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_cursor_count) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_cursor_count), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_cursor_price) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_cursor_price), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_first_fill) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_first_fill), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_last_fill) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_last_fill), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, birth_evaluation_ordinal) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, birth_evaluation_ordinal), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, pine_birth_reach) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, pine_birth_reach), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, quantity_intent_kind) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, quantity_intent_kind), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, quantity_intent_units) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, quantity_intent_units), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, quantity_intent_numerator) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, quantity_intent_numerator), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, quantity_intent_denominator) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, quantity_intent_denominator), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, quantity_reservation_present) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, quantity_reservation_present), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, quantity_reservation_units) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, quantity_reservation_units), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, quantity_reservation_basis_units) == offsetof(prior_leg_mirror::pf_pending_order_v1_t, quantity_reservation_basis_units), "preserve existing v1 prefix offset"); +static_assert(offsetof(pf_pending_order_v1_t, leg_activation_owner_cycle) >= sizeof(prior_leg_mirror::pf_pending_order_v1_t), "append after old full prefix"); +using namespace pineforge; +namespace { +const double nan = std::numeric_limits::quiet_NaN(); +const Bar bars[] = { + {100, 101, 99, 100, 1, 0}, + {100, 105, 95, 100, 1, 60000}, + {90, 112, 80, 100, 1, 120000}, + {100, 112, 80, 100, 1, 180000}, +}; +class FutureOwner : public BacktestEngine { +public: + explicit FutureOwner(bool stop) : use_stop(stop) { + calc_on_order_fills_ = true; + initial_capital_ = 100000; + default_qty_type_ = QtyType::FIXED; + default_qty_value_ = 1; + pyramiding_ = 10; + syminfo_mintick_ = 0.01; + commission_value_ = 0; + } + bool use_stop; + bool armed = false; + int born_bar = -1; + int bound_bar = -1; + int64_t born_cycle = 0, bound_cycle = 0; + uint64_t exit_incarnation = 0, bound_exit_incarnation = 0; + bool stop_flag_at_birth = false, limit_flag_at_birth = false; + bool stop_flag_at_binding = false, limit_flag_at_binding = false; + bool persisted_on_target_entry_bar = false; + int64_t first_stop_bar = -1, first_limit_bar = -1; + int64_t rebound_stop_bar = -1, rebound_limit_bar = -1; + int64_t first_activation_cycle = 0, rebound_activation_cycle = 0; + int seen_entry_callbacks = 0; + void on_bar(const Bar&) override { + if (bar_index_ == 0) { + strategy_entry("A", true, nan, nan, 1); + return; + } + if (bar_index_ == 1 && coof_fill_recalc_active_ && !armed) { + armed = true; + strategy_entry("A", false, nan, 90, 1); + strategy_exit("EY", "A", use_stop ? nan : 85, use_stop ? 110 : nan); + for (const auto& o : pending_orders_) if (o.id == "EY") { + born_bar = o.created_bar; + born_cycle = position_cycle_seq_; + exit_incarnation = o.incarnation; + stop_flag_at_birth = o.pine_exit_activation.holds_stop(); + limit_flag_at_birth = o.pine_exit_activation.holds_limit(); + if (o.leg_activation.bounds()) { + first_stop_bar = o.leg_activation.bounds()->stop_first_bar; + first_limit_bar = o.leg_activation.bounds()->limit_first_bar; + first_activation_cycle = o.leg_activation.bounds()->position_cycle; + } + } + } + if (bar_index_ == 2 && coof_fill_recalc_active_ + && position_side_ == PositionSide::SHORT) { + ++seen_entry_callbacks; + for (const auto& o : pending_orders_) if (o.id == "EY") { + bound_bar = position_open_bar_; + bound_cycle = position_cycle_seq_; + bound_exit_incarnation = o.incarnation; + stop_flag_at_binding = o.pine_exit_activation.holds_stop(); + limit_flag_at_binding = o.pine_exit_activation.holds_limit(); + if (o.leg_activation.bounds()) { + rebound_stop_bar = o.leg_activation.bounds()->stop_first_bar; + rebound_limit_bar = o.leg_activation.bounds()->limit_first_bar; + rebound_activation_cycle = o.leg_activation.bounds()->position_cycle; + } + } + } + if (bar_index_ == 2 && !coof_fill_recalc_active_) { + persisted_on_target_entry_bar = position_side_ == PositionSide::SHORT; + } + } + void print() const { + std::printf("%s born_bar=%d bound_bar=%d born_cycle=%lld bound_cycle=%lld exit_inc=%llu bound_exit_inc=%llu birth_stop=%d birth_limit=%d binding_stop=%d binding_limit=%d held_at_target_bar_close=%d target_callbacks=%d\n", + use_stop ? "stop" : "limit", born_bar, bound_bar, + (long long)born_cycle, (long long)bound_cycle, + (unsigned long long)exit_incarnation, (unsigned long long)bound_exit_incarnation, + stop_flag_at_birth, limit_flag_at_birth, stop_flag_at_binding, + limit_flag_at_binding, persisted_on_target_entry_bar, seen_entry_callbacks); + for (const auto& t : trades_) + std::printf("trade entry=%s exit=%s entry_bar=%d exit_bar=%d qty=%.6f entry_price=%.6f exit_price=%.6f\n", + t.entry_id.c_str(), t.exit_id.c_str(), t.entry_bar_index, + t.exit_bar_index, t.qty, t.entry_price, t.exit_price); + } + bool contract_holds() const { + if (born_bar != 1 || bound_bar != 2 || born_cycle != 1 || bound_cycle != 2 + || exit_incarnation != 3 || bound_exit_incarnation != exit_incarnation + || !persisted_on_target_entry_bar || seen_entry_callbacks != 1 + || first_activation_cycle != born_cycle || rebound_activation_cycle != bound_cycle + || first_stop_bar != (use_stop ? 2 : 1) || first_limit_bar != (use_stop ? 1 : 2) + || rebound_stop_bar != (use_stop ? 3 : 2) || rebound_limit_bar != (use_stop ? 2 : 3) + || stop_flag_at_birth != use_stop || limit_flag_at_birth == use_stop + || stop_flag_at_binding != stop_flag_at_birth + || limit_flag_at_binding != limit_flag_at_birth || trades_.size() != 2) + return false; + const auto& exit = trades_.back(); + return exit.entry_id == "A" && exit.exit_id == "EY" + && exit.entry_bar_index == 2 && exit.exit_bar_index == 3 + && exit.qty == 1 && exit.entry_price == 90 + && exit.exit_price == (use_stop ? 110 : 85) + // A fixed next-bar deadline from original birth is already past + // when the same exit binds the new position and is held again. + && bound_bar >= born_bar + 1; + } +}; +} +int preserved_rebinding_controls() { + int failures = 0; + for (bool stop : {true, false}) { + FutureOwner engine(stop); + engine.run(bars, 4); + engine.print(); + if (!engine.contract_holds()) ++failures; + } + std::printf("literal owner-rebinding contracts: %d failure(s)\n", failures); + return failures ? 1 : 0; +} + +namespace { +int native_checks = 0, native_failures = 0; +#define CHECK(x) do { ++native_checks; if (!(x)) { ++native_failures; std::fprintf(stderr,"FAIL %d %s\n",__LINE__,#x); } } while (0) +class NativeBook : public BacktestEngine { +public: + NativeBook() { + initial_capital_=100000; commission_value_=0; margin_long_=margin_short_=0; + pyramiding_=10; current_bar_={100,100,100,100,1,0}; + } + void on_bar(const Bar&) override {} + void step(double price=100) { + ++bar_index_; current_bar_={price,price,price,price,1,bar_index_*60000LL}; + process_pending_orders(current_bar_); + } + void raw_open(){strategy_order("A",true,1);step();} + void bracket(){strategy_exit("X","A",120,90);} + void add(){strategy_order("A",true,1);} + void partial(){strategy_close("A","",0.5);} + PendingOrder& exit(){for(auto& o:pending_orders_)if(o.id=="X")return o;throw std::logic_error("missing exit");} + int64_t cycle()const{return position_cycle_seq_;} + double quantity()const{return position_qty_;} + int bar()const{return bar_index_;} + void replace(){bracket();} + void cancel(){strategy_cancel("X");} +}; +void native_values_and_connected_constraints() { + ExitLegActivation activation; + CHECK(activation.stop_ready(1,0)); + activation.bind({7,3,5}); + CHECK(!activation.stop_ready(7,2)&&activation.stop_ready(7,3)); + CHECK(!activation.limit_ready(7,4)&&activation.limit_ready(7,5)); + CHECK(!activation.stop_ready(8,100)&&!activation.limit_ready(8,100)); + bool refused=false;try{activation.bind({0,1,1});}catch(const std::invalid_argument&){refused=true;} + CHECK(refused&&activation.bounds()->position_cycle==7); + activation.unbind();CHECK(!activation.bounds()); + NativeBook retained;retained.bracket(); + CHECK(!retained.exit().leg_activation.bounds()); + retained.raw_open(); + CHECK(retained.exit().leg_activation.bounds().has_value()); + CHECK(retained.exit().leg_activation.bounds()->position_cycle==retained.cycle()); + CHECK(retained.exit().leg_activation.bounds()->stop_first_bar==retained.bar()); + NativeBook b;b.raw_open();b.bracket(); + CHECK(b.exit().leg_activation.bounds()->position_cycle==b.cycle()); + CHECK(b.exit().leg_activation.bounds()->stop_first_bar==1); + CHECK(!b.exit().pine_exit_activation.evidence()); + const auto cycle=b.cycle(); + b.exit().leg_activation.bind({cycle,4,4}); + b.add();b.step(); + CHECK(b.quantity()==2&&b.cycle()==cycle); + CHECK(b.exit().leg_activation.bounds()->stop_first_bar==4); + b.partial();b.step(); + CHECK(b.quantity()==1.5&&b.cycle()==cycle); + CHECK(b.exit().leg_activation.bounds()->stop_first_bar==4); + const auto before=b.exit().incarnation; + b.replace(); + CHECK(b.exit().incarnation!=before&&b.exit().replaced_order_incarnation==before); + CHECK(b.exit().leg_activation.bounds()->stop_first_bar==1); + b.cancel();b.bracket();CHECK(b.exit().replaced_order_incarnation==0); + NativeBook bound;bound.raw_open();bound.bracket(); + bound.exit().leg_activation.bind({bound.cycle(),3,3}); + bound.step(90);CHECK(bound.quantity()==1); // actual matcher cannot refresh/delete the bound + bound.step(90);CHECK(bound.quantity()==0); +} +void original_policy_evidence_survives_new_owner_side() { + bool invalid=false; + try { (void)PineExitActivationPolicy({1,1,0,100,110,nan,std::nullopt}); } + catch(const std::invalid_argument&) { invalid=true; } + CHECK(invalid); + PineExitActivationPolicy policy({1,1,1,100,110,nan,std::nullopt}); + CHECK(policy.holds_stop()&&!policy.holds_limit()); + const auto one=policy.resolve(1,1), two=policy.resolve(2,5); + CHECK(one.position_cycle==1&&one.stop_first_bar==2&&one.limit_first_bar==1); + CHECK(two.position_cycle==2&&two.stop_first_bar==6&&two.limit_first_bar==5); + CHECK(policy.evidence()->position_cycle==1&&policy.evidence()->stop_level==110); + PineExitActivationPolicy recross({1,1,1,110,nan,105, + compat::pine::LimitContinuation{compat::pine::LimitContinuationCause::FirstHighRecross,9}}); + CHECK(!recross.holds_limit()&&!recross.continues_at_later_open()); + PineExitActivationPolicy later({1,1,1,110,nan,105, + compat::pine::LimitContinuation{compat::pine::LimitContinuationCause::LaterSameOpen,9}}); + CHECK(!later.holds_limit()&&later.continues_at_later_open()); +} +void named_pine_continuations_keep_their_guards() { + const Bar bar{100,105,90,104,1,120000}; + const std::string id="A"; + PendingOrder order{}; order.type=OrderType::EXIT; order.from_entry=id; + order.stop_price=nan; order.limit_price=102; order.trail_points=nan; order.trail_price=nan; + order.qty=1; order.quantity_request.request(QuantityIntent::all()); + order.quantity_request.reserve(1,1); + order.pine_birth_reach=PineHistoricalBirthReach::ExtremeWaypoints; + compat::pine::ExitActivationContext context{ + bar,PositionSide::LONG,1,2,2,1,1.0,0,1,id,7, + true,true,105,false,1,false,true,1,7,9,9, + false,false,false,true,true,0,1,1,true,105}; + const auto high=compat::pine::select_exit_activation(order,nan,102,context); + CHECK(high.evidence()&&high.evidence()->limit_continuation); + CHECK(high.evidence()->limit_continuation->cause==compat::pine::LimitContinuationCause::FirstHighRecross); + CHECK(!high.holds_limit()&&!high.continues_at_later_open()); + context.pending_empty=false; + const auto competitor=compat::pine::select_exit_activation(order,nan,102,context); + CHECK(competitor.holds_limit()&&!competitor.evidence()->limit_continuation); + context.pending_empty=true; context.cursor_price=100; context.after_first_open_fill=true; + context.recalc_leg=0; context.historical_point=0; context.at_extreme=false; + order.stop_price=101;order.limit_price=99; + const auto later=compat::pine::select_exit_activation(order,101,99,context); + CHECK(later.holds_stop()&&!later.holds_limit()&&later.continues_at_later_open()); + order.trail_points=5; + const auto trailing=compat::pine::select_exit_activation(order,101,99,context); + CHECK(trailing.holds_stop()&&trailing.holds_limit()&&!trailing.continues_at_later_open()); + context.fill_recalc=false; + const auto direct=compat::pine::select_exit_activation(order,101,99,context); + CHECK(!direct.evidence()); + // Later trigger neutralization cannot mutate the original policy evidence. + order.stop_price=order.limit_price=nan; + CHECK(later.holds_stop()&&later.evidence()->stop_level==101); +} + +} +int main(){ + const int preserved=preserved_rebinding_controls(); + try{native_values_and_connected_constraints();original_policy_evidence_survives_new_owner_side();named_pine_continuations_keep_their_guards();} + catch(const std::exception& e){++native_failures;std::fprintf(stderr,"native exception: %s\n",e.what());} + std::printf("native leg activation: %d checks, %d failures\n",native_checks,native_failures); + return preserved||native_failures?1:0; +} diff --git a/tests/test_live_state_hash.cpp b/tests/test_live_state_hash.cpp index 5830e855..f32af268 100644 --- a/tests/test_live_state_hash.cpp +++ b/tests/test_live_state_hash.cpp @@ -402,13 +402,12 @@ class Probe final : public BacktestEngine { if (!s.pending_orders_.empty()) s.pending_orders_[0].declined_by_replaced_short_market = !s.pending_orders_[0].declined_by_replaced_short_market; }}, - {"pending_orders_[].coof_suppress_stop_on_entry_bar", [](Probe& s) { - if (!s.pending_orders_.empty()) - s.pending_orders_[0].coof_suppress_stop_on_entry_bar = !s.pending_orders_[0].coof_suppress_stop_on_entry_bar; + {"pending_orders_[].leg_activation", [](Probe& s) { + if (!s.pending_orders_.empty()) s.pending_orders_[0].leg_activation.bind({1,2,3}); }}, - {"pending_orders_[].coof_suppress_limit_on_entry_bar", [](Probe& s) { - if (!s.pending_orders_.empty()) - s.pending_orders_[0].coof_suppress_limit_on_entry_bar = !s.pending_orders_[0].coof_suppress_limit_on_entry_bar; + {"pending_orders_[].pine_exit_activation", [](Probe& s) { + if (!s.pending_orders_.empty()) s.pending_orders_[0].pine_exit_activation = + PineExitActivationPolicy({1,0,1,100,110,90,std::nullopt}); }}, {"pending_orders_[].birth.fill_origin", [](Probe& s) { if (!s.pending_orders_.empty())