Repository navigation
fix(ta): exact-order window summation for short SMAs + corpus warmup-origin reconfigs (309 excellent) - #156
Merged
Merged
Conversation
Pine defines ta.sma(src, length) as the mean of the last `length` values,
which makes it a pure function of its window. The incremental running sum
(`running_sum += src - popped`) broke that: the emitted value became a
function of every value ever accumulated, and the periodic exact re-summation
at (bar_count & 255) == 0 only re-PHASED that drift rather than removing it.
The failure is observable at the signal layer through the stochRSI shape
k = ta.sma(stoch, 3); d = ta.sma(k, 3). On a saturating source the three
k-windows feeding d are rotations of one multiset, so the s_{t-2} term
cancels identically and
9 * (k_t - d_t) = 2*s_t + s_{t-1} - 2*s_{t-3} - s_{t-4}
is EXACTLY ZERO whenever s_t == s_{t-3} and s_{t-1} == s_{t-4}. stochRSI hits
that constantly because stoch saturates at exactly 100.0 / 0.0 (x/x -> 1.0,
*100 exact in IEEE-754) every time rsi is its own 14-window extremum.
ta.crossover / ta.crossunder are strict inequalities, so no correct
implementation at any precision may fire at such a bar. Running-sum drift
broke those ties at +-1 ULP and manufactured crossings the mathematics
forbids, with a sign set by the resync phase rather than by the data.
Windows of length <= 16 now re-sum the buffer every bar: exact-order
deterministic, history-independent, and bounded at 16 additions per bar.
Longer windows keep the amortised incremental path, where the chained-tie
geometry does not arise. recompute() follows the same rule so a recomputed
bar and a freshly computed one with an identical window agree bit-for-bit.
Corpus (312 strategies): 3 tapes move, 0 regress.
composite-kkb-margin-100-pct-01 unmatched 1 -> 0
ta-stochastic-rsi-cross-01 matched 1292 -> 1305 (96.6% -> 97.6%)
ta-triple-sma-stack-latch-01 metrics unchanged (100% both)
Tier distribution unchanged: excellent=307 strong=4 anomaly=1.
tests/test_ta_sma_exact_order.cpp pins the invariant (red before, green
after): equal windows -> bitwise equal output, and chained SMA(3) rotation
ties stay exactly tied so no cross can fire.
Co-Authored-By: Claude Opus 5 <[email protected]>
…run (309 excellent / 2 strong / 1 anomaly) Co-Authored-By: Claude Fable 5 <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Aug 13, 2026
…reconfigs + exact-order SMA) (#157) Co-authored-by: Claude Fable 5 <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Oct 2, 2026
* docs: release notes and version scoping for v1.0.1 v1.0.1 is a documentation-only release that pairs with pineforge-codegen 1.0.1 (codegen #156, #157: history reads of objects, drawings, arrays and matrices whose C++ did not compile now compile, and an int na given to a float field reads na). Since v1.0.0 only Markdown changed (#309, #310): no file under src/, include/, cmake/ or examples/, no CMake file, and docker/run_json.py is unchanged, so the C ABI, the script ABI epoch and the JSON report keys are v1.0.0's. - CHANGELOG.md: "1.0.1 — 2026-10-02". - README.md: front door 1 and the runtime-not-compiler line install pineforge-codegen==1.0.1; the prebuilt library names the v1.0.1 tarballs; the pairing sentence, the scoreboard, the benchmark line and the Releases list name 1.0.1. The MCP image line names no version (its engine_info tool reports it), as codegen #155 did for its hosted-server line. - docs/pages/install.md: the v1.0.1 tarballs and the hub tag engine1.0.1-codegen1.0.1. - docs/pages/public-contract.md: 1.0.1's release line, and engine v1.0.1 with codegen 1.0.1 among the supported pairs. Lines that state what v1.0.0 or codegen 1.0.0 shipped or did (coverage, ABI history, the version.h and find_package examples, the hub 1.0.0 image's tutorial numbers) stay. Replaces text introduced by c5383e6 (#309): README.md's "The image bundles engine v1.0.0 with codegen 1.0.0." and public-contract.md's release line, which now runs on into 1.0.1's. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> * docs: the 1.0.1 code was graded before it merged, with no tier change Replaces text introduced by cca621c (this branch's first commit): README.md's "The 1.0.1 releases (2026-10-02) were not re-graded" sentence, which the pre-merge grading of the 1.0.1 code supersedes. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFVRQ4gcJCLbjfYqGtmy4k --------- Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gate
pr-gatePASS — engine corpus zero regressions, scraped entering excellent+strong >= leaving.Verdict:
/Users/haoliangwen/code/pineforge-lab/pr-gate-verdict.json🤖 Generated with Claude Code