PineForge unreleased
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
pine_position_tail_binding.hpp
Go to the documentation of this file.
1#pragma once
2
3// All L8c / L6b-4 binding lives here. Reconcile this file when those lanes
4// land; the footer codec and percentage-exit predicate have no dependency
5// on their implementation details.
7#include "../report_scratch.hpp"
8
10#include <pineforge/engine.hpp>
12
13#include <limits>
14#include <stdexcept>
15
17
19 // L6b-4: empty directory uses disk-backed TMPDIR or /tmp, then /var/tmp.
20 class File {
21 public:
22 explicit File(const std::string& directory)
23 : file_(directory, pineforge::detail::ScratchStore::position_tail) {}
24 int descriptor() const noexcept { return file_.descriptor(); }
25 std::uint64_t read_count() const noexcept { return file_.read_count(); }
26 std::uint64_t read_bytes() const noexcept { return file_.read_bytes(); }
27 void write(std::uint64_t offset, const void* bytes, std::size_t count) {
28 file_.write(static_cast<std::int64_t>(offset), bytes, count);
29 }
30 void read(std::uint64_t offset, void* bytes, std::size_t count) const {
31 file_.read(static_cast<std::int64_t>(offset), bytes, count);
32 }
33 void clear() { file_.clear(); }
34 void release() noexcept { file_.release(); }
35 private:
36 report_sink::ScratchFile file_;
37 };
38
39 // L8c: call once on the approved resident prefix BEFORE trades.seal(end).
40 // A failure propagates before any row can be discarded.
41 static void preserve(std::shared_ptr<PositionTailSpill>& spill,
42 const TradeLedger& trades, std::size_t end,
43 std::int64_t position_open, const std::string& directory,
44 std::size_t cache_bytes = PositionTailSpill::kWindowBytes) {
45 preserve_with_capacity(spill, trades, end, position_open, directory, cache_bytes);
46 }
47 static void preserve(std::shared_ptr<PositionTailSpill>& spill,
48 const TradeLedger& trades, std::size_t end,
49 std::int64_t position_open, const std::string& directory,
50 CacheCapacity capacity) {
51 preserve_with_capacity(spill, trades, end, position_open, directory, capacity);
52 }
53
54private:
55 template<class Capacity>
56 static void preserve_with_capacity(std::shared_ptr<PositionTailSpill>& spill,
57 const TradeLedger& trades, std::size_t end,
58 std::int64_t position_open, const std::string& directory,
59 Capacity cache_bytes) {
60 if (end < trades.base() || end > trades.size()) {
62 "invalid Pine position-tail seal prefix");
63 }
64 if (position_open == std::numeric_limits<std::int64_t>::min()) {
65 spill.reset();
66 return;
67 }
68 for (std::size_t i = trades.base(); i < end; ++i) {
69 const Trade& trade = trades[i];
70 if (trade.exit_time < position_open) {
71 // A scan barrier cuts off all older rows even when exit
72 // times are not monotone in global trade-row order.
73 spill.reset();
74 } else {
75 if (!spill) spill = std::make_shared<PositionTailSpill>(directory, cache_bytes);
76 spill->append(trade);
77 }
78 }
79 }
80};
81
82} // namespace pineforge::source::detail
Base with a code: throw coded<std::invalid_argument>(code, {args}, text).
void read(std::uint64_t offset, void *bytes, std::size_t count) const
void write(std::uint64_t offset, const void *bytes, std::size_t count)
static void preserve(std::shared_ptr< PositionTailSpill > &spill, const TradeLedger &trades, std::size_t end, std::int64_t position_open, const std::string &directory, std::size_t cache_bytes=PositionTailSpill::kWindowBytes)
static void preserve(std::shared_ptr< PositionTailSpill > &spill, const TradeLedger &trades, std::size_t end, std::int64_t position_open, const std::string &directory, CacheCapacity capacity)