PineForge unreleased
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
pine_host_reads.hpp
Go to the documentation of this file.
1#pragma once
2
3// R5 lane D2-C: the source layer's reads of the run it serves, taken in place.
4//
5// NativeStrategyHost answers its reads of kernel state out of line and by
6// value: native_state() builds a whole NativeStateView -- the failure record
7// and its context included -- for the one field a caller wants,
8// current_execution_point() copies the callback's point, execution_consumer()
9// is a call, and the Pine layer asks them some fifteen times a bar before it
10// places an order. The consumer already holds each answer for as long as it
11// cannot change: the run's lifecycle, spec and phase for the run, the
12// callback's point for the callback, the book until the next settlement. So
13// the layer reads them there, through these inline forms, each answering
14// exactly what the accessor it stands for answers at the same moment
15// (tests/test_adapter_in_place_reads.cpp holds them to the accessors at every
16// callback). One fact derived from the spec -- whether the chart aggregates
17// its input bars -- is taken once per run and kept with the consumer for the
18// host (run_aggregates_input_bars, the host cache of R5 lane PERF-P7).
19// Not installed API.
20
21#include "../native_execution_consumer.hpp"
22#include "pine_intent_state.hpp"
23
24#include <cstdint>
25#include <optional>
26
27namespace pineforge::source {
28
30
31namespace detail {
32
33// NativeStrategyHost::execution_consumer(), as the native consumer it is.
34inline NativeExecutionConsumer& run_consumer(const NativeStrategyHost& host) {
35 return NativeExecutionConsumer::bound(host);
36}
37
38// native_state()'s kind, spec and phase: the view's fields the source layer
39// reads, filled as view() fills them.
40struct RunState {
41 NativeLifecycleKind kind = NativeLifecycleKind::Unconfigured;
42 const NativeRunSpec* spec = nullptr;
43 NativeRunPhase phase = NativeRunPhase::Batch;
44};
46 const NativeExecutionConsumer& consumer = NativeExecutionConsumer::bound(host);
47 if (consumer.running())
48 return {NativeLifecycleKind::Running, consumer.state_spec(), consumer.state_phase()};
49 const NativeStateView view = consumer.view();
50 return {view.kind, view.spec, view.phase};
51}
52
53// native_state().kind / .spec / .phase alone.
55 return run_consumer(host).state_kind();
56}
57inline const NativeRunSpec* run_spec(const NativeStrategyHost& host) {
58 return run_consumer(host).state_spec();
59}
61 return run_consumer(host).state_phase();
62}
63
64// physical_position().
66 return run_consumer(host).position(host);
67}
68
69// current_execution_point(), by reference: null where it answers nullopt.
70// Valid inside the callback that asked. The consumer's own frame, which the
71// kernel acts on whether or not the source layer is replaying a retained one.
73 return run_consumer(host).current_point();
74}
75
76// The point the source layer reads at a callback: the retained point of the
77// row a selected run is replaying (selected_replay_point), else the live one.
78// With nothing replaying, as in every run with the selected window off, it is
79// live_callback_point's pointer itself.
81 if (const NativeCurrentPointView* replayed = selected_replay_point(host)) return replayed;
82 return live_callback_point(host);
83}
84
85// The source layer's state parked with the consumer for one run (R5 lane
86// PERF-P7's NativeHostCache: the adapter's lookup index derives from this,
87// pine_adapter.cpp). The consumer drops it at every run begin and never reads
88// it. `owner` and `run` are the adapter and run counter it was adopted for;
89// the facts below are the running spec's, taken once at the run's begin
90// (take_run_facts) and fixed with the spec for the run.
91extern const char kPineRunCacheKind;
92struct PineRunCache : NativeHostCache {
93 PineRunCache() noexcept : NativeHostCache(&kPineRunCacheKind) {}
94 const void* owner = nullptr;
95 std::uint64_t run = 0;
96 std::optional<bool> aggregates_input_bars;
97 // Reads the facts answered (the witness's probe), apart from the
98 // lookups the index answers.
99 std::uint64_t fact_answers = 0;
100};
101
102// The consumer's PineRunCache for the adapter at `owner` in run `run`, or null.
103inline PineRunCache* run_cache(const NativeExecutionConsumer& consumer, const void* owner,
104 std::uint64_t run) noexcept {
105 NativeHostCache* const cache = consumer.host_cache();
106 if (cache == nullptr || cache->kind() != &kPineRunCacheKind) return nullptr;
107 auto* facts = static_cast<PineRunCache*>(cache);
108 return facts->owner == owner && facts->run == run ? facts : nullptr;
109}
110
111// Whether a script bar of the chart gathers several input bars -- the
112// kernel's answer (NativeStrategyHost::native_aggregates_input_bars) -- for the
113// adapter at `owner` in run `run`: while the run runs, the answer taken at its
114// begin; otherwise, or when the consumer keeps no host cache
115// (set_host_cache(false), the reference tests/test_adapter_in_place_reads.cpp
116// compares against), asked of the consumer.
117inline bool run_aggregates_input_bars(const NativeExecutionConsumer& consumer,
118 const void* owner, std::uint64_t run) {
119 if (consumer.running()) {
120 if (PineRunCache* facts = run_cache(consumer, owner, run);
121 facts != nullptr && facts->aggregates_input_bars) {
122 ++facts->fact_answers;
123 return *facts->aggregates_input_bars;
124 }
125 }
126 return consumer.aggregates_input();
127}
128
129// Takes the facts above for the run that has just begun (on_native_run_begin).
130void take_run_facts(NativeExecutionConsumer& consumer, const PineExecutionAdapter& adapter,
131 std::uint64_t run);
132
133} // namespace detail
134} // namespace pineforge::source
The public native host: an abstract subclass of BacktestEngine with no PineScript on it.
NativeRunPhase
Which driving is Running: a batch run(), a stream's internal warmup, or its realtime leg.
NativeLifecycleKind
Where a host stands.
RunState run_state(const NativeStrategyHost &host)
NativePhysicalPosition run_position(const NativeStrategyHost &host)
void take_run_facts(NativeExecutionConsumer &consumer, const PineExecutionAdapter &adapter, std::uint64_t run)
const NativeCurrentPointView * callback_point(const NativeStrategyHost &host)
bool run_aggregates_input_bars(const NativeExecutionConsumer &consumer, const void *owner, std::uint64_t run)
const NativeCurrentPointView * selected_replay_point(const NativeStrategyHost &host) noexcept
const NativeCurrentPointView * live_callback_point(const NativeStrategyHost &host)
const NativeRunSpec * run_spec(const NativeStrategyHost &host)
NativeExecutionConsumer & run_consumer(const NativeStrategyHost &host)
NativeRunPhase run_phase(const NativeStrategyHost &host)
PineRunCache * run_cache(const NativeExecutionConsumer &consumer, const void *owner, std::uint64_t run) noexcept
NativeLifecycleKind run_kind(const NativeStrategyHost &host)
What current_execution_point() answers inside a callback: the point's decision context,...
The book as one aggregate: signed units, the volume-weighted average entry price and the number of op...
The flattened run state native_state() answers: the lifecycle kind, a borrowed pointer to the staged ...
One complete setup value, staged/copied by NativeStrategyHost before it is applied at begin.