Curve Diagnosis

Language English Español Português العربية Русский 中文

This page answers:What stage is this data in right now, and what comes next?

How to read this verdict: the engine looks at momentum, not at the level.
A score of 6 means two completely different things depending on whether it just climbed up from 2 or has fallen back from 9 — the engine takes the last 3 points and computes the recent slope (current value − the third-from-last value) ÷ 2, then subtracts the slope over the whole series from it to get the acceleration. “Remaining room” = 10 − current value: it says how far the value is from the top of the ±10 scale, not how many time points are left. The stage is decided by two quantities only: which band the current value falls into (the five lines at −8 / −4 / 0 / 5 / 8), and whether the recent slope inside that band is positive or negative, and steep enough.

What this page ports and what it does not (stated plainly)
· Ported: analyze_single_trend (single-series stage detection) — all 15 stage bands, the five dividing lines −8/−4/0/5/8, the 0.5 / 1 / −0.5 / −1 sub-bands inside each band, the remaining_space and score formulas, and the convention of taking the last 3 points for the slope.
· Not ported (not needed on this page rather than out of alignment): compute_main_line (needs 7 weighted sub-lines), cross_validate (needs pairwise correlation and lead/lag) and the overall conclusion of predict_trend — all of them need “7 chains × many points” as input, while this page has a single series.
· Convention difference: in the Python version one sub-line comes from one of 7 database columns, and the scale mapping v*2−10 is copied verbatim here; the database's status_label/status_color (strong breakout / drifting at a low level …) has no data source on this page, so it is not displayed — it was always a different convention from the engine's stage.
· Floating point: Python's round() rounds half to even, and pyRound() mirrors it here; see the comparison report in the build directory.

Known defects (measured, stated plainly)
· The “Plunge” band can never trigger inside the 0–10 range. Its condition is equivalent to “the third-from-last point > current value + 2”, and after mapping the ceiling is 10, so it is unreachable. An exhaustive sweep of 0–10 in steps of 0.1 over every triple (1,030,301 combinations) produced 0 hits; the steepest negative slope inside the range only ever lands in “Falling from the peak”.
· Only out-of-range input (raw values > 10 — amounts, counts, anything on a far larger scale) can produce a “Plunge”.
· So: if you are pasting amounts or counts, normalise them to 0–10 before diagnosing, otherwise the behaviour changes and the engine will not warn you. For now, read that band as an out-of-range alarm.

[Evidence section · where every number can be checked]
(1) Source: the algorithm-port machine /opt/curve_engine/app_v4.2.py, lines 387-472, analyze_single_trend() (read-only; unchanged in this round); the scale mapping v*2-10 is on line 205. Threshold line numbers are registered in the contract card /opt/contracts/curve_engine.md under “hard-coded thresholds / weights”: the five dividing lines −8/−4/0/5/8 = 398/402/411/420/433; the in-band slopes 0.5/1/−0.5/−1 = 412/421/438/447; remaining = 10 - current = 460; score=(current+10)/20*100 = 471; the last-3-points slope = 394-395.
(2) Three categories
· [Verifiable] The 15 stage bands, the five dividing lines, the in-band slope sub-bands, the remaining_space and score formulas, and the last-3-points slope convention — each lands verbatim on those line numbers in app_v4.2.py.
· [This page's display convention] The SVG line chart (±10 scale, markLine, point markers) is drawn by this page and is not source-code output; the engine only emits numeric fields.
· [No source found] Why the five lines sit at −8 / −4 / 0 / 5 / 8 has no provenance note in the engine source or in the contract card (the card registers the line numbers but not their origin).
(3) How to verify it yourself: run the page's “Rising steadily” example 2.1,2.8,3.5,4.1,4.9,5.6,6.4,7.2,7.9 → the current value 7.9 falls in [5,8) and the last-3-points slope is (7.9−6.4)/2 = +0.75 > 0 → it should return “Nearing the peak”; the “Falling steadily” example 9.2,8.6,7.8,7.1,6.3,5.4,4.6,3.7,2.9 → the current value 2.9 falls in [0,5) and the slope is (2.9−4.6)/2 = −0.85 < 0 → it should return “Growth slowing”. Feeding the same numbers through the if/else chain at app_v4.2.py 387-472 should give word-for-word the same result.

What you can do next

Stage Atlas

The 15 stage bands of curve diagnosis, with each one's decision conditions and its outlook text

Why this link: This page outputs trend_verdict, and this slice takes trend_verdict as its input

Scale Mapper

Convert between 0–10 scores and the engine's −10 to +10 scale, both directions

Why this link: Follow-on picked by hand (score-map)
Generated by /opt/slices_build/build.py from the spec /_shared/slices/curve-diagnose.json — to change this page, edit the spec and re-run the generator; never hand-edit the HTML.