PineForge v0.13.1-379-g9b50973
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
window_sum.hpp
Go to the documentation of this file.
1#pragma once
2#include "na.hpp"
3#include <deque>
4
5namespace pineforge {
6
7// TradingView's sliding-window sum -- the arithmetic behind ta.sma and
8// math.sum, fitted bit-for-bit on the round-7 synthetic pins (see the note
9// above its implementation in src/ta_moving_averages.cpp):
10//
11// * a Kahan-compensated running sum S with compensation c;
12// * the ring stores the COMPENSATED addend y = x - c each source entered
13// with, and subtracts that y (through the same Kahan step) when the
14// source leaves the window `length` bars later -- sub before add;
15// * on the bar whose incoming source UNDER-applies the MAGNITUDE of the
16// carried compensation when it is ADDED (c != 0 and, with z = fl(x + |c|),
17// |z - x| < |c|: fully swallowed or rounded toward x -- the round-10
18// family-W pin; round 9's x - c form and round 7's swallow case are the
19// cases where x - c and x + |c| round alike), the sum is re-summed
20// newest-first over the window's sources, c is reset and the bar's ring
21// addend is its raw source.
22//
23// Both users divide S by `length` themselves (ta.sma) or emit S (math.sum).
25 std::deque<double> values_; // window sources, front = newest
26 std::deque<double> addends_; // the compensated addends, front = newest
27 int length_;
28 int count_; // valid sources pushed so far
29 double sum_; // S
30 double comp_; // c
31
32 // Rewind state for the current bar: the pre-bar (S, c, count), the
33 // source/addend the bar evicted (na when it evicted none), and whether
34 // the bar pushed at all (an na input pushes nothing).
35 double saved_sum_;
36 double saved_comp_;
37 int saved_count_;
38 double saved_evicted_value_;
39 double saved_evicted_addend_;
40 bool saved_pushed_;
41
42 void kahan_add(double v);
43 void enter(double src, double comp_before);
44
45public:
46 explicit KahanWindowSum(int length);
47
48 // A valid source enters the window; returns S. Never pass na: both users
49 // hold their seeded value on na input and call note_no_push() instead.
50 double push(double src);
51 // The current bar carried no source (na input): records that a later
52 // repush() starts a fresh push and unpush() has nothing to rewind.
54 // Replay the current bar with a different valid source (intrabar
55 // recompute): same evicted addend, same pre-bar (S, c). Returns S.
56 double repush(double src);
57 // Rewind the current bar entirely (its source leaves, the evicted source
58 // returns) so the window reads as it did before the bar.
59 void unpush();
60
61 int count() const { return count_; }
62 int length() const { return length_; }
63 bool seeded() const { return count_ >= length_; }
64 double sum() const { return sum_; }
65};
66
67} // namespace pineforge
double repush(double src)
double push(double src)