Status: built 2026-09-06/07, extended 2026-09-07 to ZTD Entry v8.0 (entity 3wowED); verified: H1 gate PASS 0/25,541, chart parity PASS 0/0 on both exports, 3 replay checks matched; arm-tier gate PASS (0 mismatches on all 9 pairs, 39,122 H1 bars compared), arm parity PASS (21 biases, 80 orders, 31 trades, 0 mismatches after the sub-tick tie allowance; 21 range_end and 0 replaced bias ends in the window); v8.0 opposite-side-HTF-triangle exit gate PASS (0 mismatches on all 11 pairs incl. the new htfTriB/htfTriU, 39,138 H1 bars) and parity with the input ON PASS (0/0, 13,782 5m bars, 3 exitCode 5 events in the window). Date: 2026-09-06. Sub-project: entry5m/ (the pyakao harness is the executable reference for every rule below).
A Pine v6 indicator with alerts for the 5m or 15m chart that reproduces the entry5m harness on TradingView: the H1/H4 ZTD bias (divergence fire, or the extreme-triangle arm), the 5m/15m pullback and pivot-break stop order, the stop at the HTF extreme or the pullback swing, a take-profit at a settable R:R, and an optional half-off at a settable R with a breakeven stop. It draws every level, tracks a simulated position so alerts can say what to do next, and exposes a data-window surface for parity checks against pyakao.
Not a strategy: no tester, no strategy.* calls. Verification is signal parity (bias, order levels, simulated fill bars), not trade-for-trade P&L.
Decisions taken by Daniel (2026-09-06): indicator with alerts; rule-level inputs only, ZTD engines at v17 defaults; signal-parity verification.
ztd_divergence.pine --(entry5m/tools/make_entry_core.py)--> f_ztd() core (embedded, marked ENTRY_CORE_BEGIN/END)
|
request.security(tickerid, biasTf, f_ztdPrev(), lookahead_on) -> closed-HTF-bar surface
|
chart (5m/15m): bias tracker -> pivots / pullbacks / order pricing -> simulated position -> drawings, HUD, alerts, data window
make_entry_core.py reads ztd_divergence.pine, keeps the shared blocks, engines T and O, rule atoms and both state machines (the region between the shared blocks and drawings headers), drops drawings, HUD, alerts and pane code, wraps the result in f_ztd() returning a tuple, and writes it between // ENTRY_CORE_BEGIN / // ENTRY_CORE_END markers in entry5m/pine/ztd_entry.pine, preserving everything outside the markers. Idempotent; fail-loud asserts on the anchors it expects (the harmonic transform is the model). The ZTD inputs the core needs become script-level constants equal to the v17 defaults (intrabar = true, refMode = "Until superseded", maxSigPerRef = 1, timeoutBars = 240, cancelOpp = true, zeroRead = "Close", zeroTol = 0, oObTier = "Extreme", both engines Rolling (24-bar) / Percentile 90/95 / calib 2000 / sigma 200 / volume on), except tMinTier, which follows the arm-tier input in arm mode and is "Elevated" in divergence mode (as v17).f_ztdPrev() calls f_ztd() and returns each element shifted by one bar; request.security(syminfo.tickerid, biasTf, f_ztdPrev(), lookahead = barmerge.lookahead_on) therefore yields the last CLOSED HTF bar on every chart bar, with no repainting on history or in real time (the idiom documented in pyakao/src/pyakao/zms/htf.py). A new HTF bar is detected as htfNew: the one-bar-shifted time is carried through the SAME request.security tuple, and htfNew is true on the chart bar where that value changes. The tracker therefore steps exactly once per closed HTF bar, tied to the security series itself rather than to the chart clock (timeframe.change would key off the chart's own bar boundaries and can fire on a bar the security series has not yet advanced past). This matches the harness: an H1 event takes effect on the first 5m bar that opens at or after the H1 close.f_ztd() (all float, ints carried as floats): sigBear, sigBull, contraB, contraU, midLoB, midHiU, curHi, curLo, fRefB, fRefU, ovl, ext — the same names as ZtdRow fields the pyakao BiasTracker reads.| Group | Input | Default | Notes |
|---|---|---|---|
| Bias | Bias timeframe | 60 |
options 60, 240 |
| Bias | Bias source | Divergence |
options Divergence, Extreme arm |
| Bias | Arm triangle tier | Extreme |
options Extreme, Elevated; used in arm mode only |
| Bias | Timeout (bias timeframe bars) | 96 | |
| Entry | Pivot strength | 3 | ta.pivothigh/low(n, n) |
| Entry | Minimum pullback age (bars) | 3 | origin must be this many bars before the pivot |
| Entry | Pending order life (bars) | 48 | |
| Entry | Minimum reward-to-risk | 1.0 | |
| Stop | Stop at | HTF extreme |
options HTF extreme, Pullback swing |
| Target | Target | Fixed R:R |
options Fixed R:R, Zero-touch level (the latter only in divergence mode; arm mode forces Fixed R:R) |
| Target | Reward-to-risk | 3.0 | |
| Target | Exit on opposite-side HTF triangle | off | v8.0; the v7 rule of docs/2026-09-07-entry5m-v7-opptri-prereg.md, in the "Stop and target" group |
| Scale-out | Take partial | off | |
| Scale-out | Partial size (fraction) | 0.5 | |
| Scale-out | Partial at R | 1.0 | must be below the R:R |
| Scale-out | Move stop to breakeven after partial | on | |
| Display | Show bias, orders, position, HUD; label/line budget (keep last N, default 60) | ||
| Alerts | One toggle per event class (bias, order, fill, partial, breakeven, exit) | on |
The entry timeframe is the chart. If the chart is not 5m or 15m the HUD shows a warning and nothing else changes (the rules still run).
pyakao/src/pyakao/entry5m/bias.py)State (var): biasSide (0 none, −1 short, +1 long), biasKind ("RDIV", "HDIV", "ARM"), biasStartBar (chart bar index), biasExt (HTF extreme level; the stop reference in HTF-extreme mode), biasTarget (zero-touch level, na in arm mode), biasDeadline (HTF bar count), biasId.
On each chart bar where htfNew is true (the shifted security time changed; see section 2), using the HTF surface:
bias.py::on_h1_close): contradiction on the bias side ends it; a same-side ext moves biasExt to curHi/curLo and renews the deadline; timeout ends it; a fire (sigBear/sigBull) with a non-na midLoB/midHiU replaces any active bias and starts a new one (ext = curHi/curLo, target = midLoB/midHiU, kind RDIV when abs(sig) == 2 else HDIV); a fire with a na target is ignored.bias.py::_on_h1_arm): the bias ends when its side's curHi/curLo is na (range end); otherwise biasExt follows the running extreme, then timeout; ovl != 0 on the other side (or with no bias) starts a new ARM bias with ext = curHi/curLo and na target; a same-side ovl is ignored; an ovl whose running extreme is na is skipped.runner.py): in divergence mode the bias ends with reason target when the bar trades through biasTarget.A bias end closes the simulated position at the bar close (reason bias_end) and cancels the pending order; a bias start resets the pullback boundary.
setup.py)ta.pivothigh(high, n, n) / ta.pivotlow(low, n, n); a pivot confirmed on bar c sits at c - n. Short bias uses pivot highs, long bias pivot lows. Tie rule: an equal high among the left neighbours is allowed, among the right neighbours it is not (Pine semantics; pyakao.pinets._Pivot matches since 2026-09-07).argmin low / argmax high from the bar after the previous confirmed same-kind pivot since the bias start, ties to the earliest bar), the age rule, order pricing (entry one tick beyond the origin; stop one tick beyond the pullback extreme or biasExt; target = biasTarget or entry ± R:R × risk), the "already broken" check over (p, c], and the reward-to-risk floor are exactly setup.py::PullbackScanner. Rejections are counted in the data window (rrRejected, alreadyBroken, tooShort).var fields: entry, stop, target, cancel level, placed bar, pullback bar, origin bar). A newer qualifying pullback replaces it; it is cancelled when price trades through the cancel level (pullback extreme, or biasExt in HTF-extreme mode), at bias end, or after the pending life.skippedInPosition counter).execution.py)Per chart bar, in the harness order: (1) open position: effective stop, then the partial level (entry ± partialR × risk, sets the half off and, if enabled, moves the effective stop to the fill price from the next bar), then the target, then nothing else (no time stop in the indicator); (2) pending order: fill when the bar trades through the entry (fill price = the entry, or the open when the bar gaps through it; no slippage model in the indicator), then the same stop/partial/target sequence on the fill bar; (3) cancellation checks. A bar that hits the stop and a favourable level is a stop. The position records fill bar and price, quantity (1 or 1 − fraction), partial price and bar, and the running R (size-weighted after the partial), which the HUD shows and the exit alert reports. Slippage is deliberately not modelled: the indicator reports levels, not P&L.
htfTriU for a short, htfTriB for a long) closes the position at the chart bar's close — exitCode 5, reason opp triangle, R computed exactly as the bias-end cleanup does. It is evaluated inside the htfNew block before the bias contradiction/extension/timeout checks, mirroring bias.py::on_h1_close, which emits ("opp_tri", bias) ahead of that bar's end/start events and only while tracker.active is set. It is an exit only: the bias is untouched and a pending order stays live and may still fill later in the same bias. The harness equivalent is broker.close_at(i, t, close, "opp_tri") with counter exit_opp_tri; the indicator has no slippage, so both close at close.biasExt from the bias start bar, dashed, coloured by side, ending at the bias end; target line at biasTarget (divergence mode); pending entry line (dotted) with its stop and target; on fill, solid entry, stop (moves to breakeven), partial and target lines; small labels at bias start ("ZTD bias ▼ RDIV / ARM"), order placed ("stop sell @ …"), fill, partial, exits. Colours mirror ZTD (bear red, bull green).table cell set.alert() with a dynamic message on bar close for each event, gated by the toggles: ZTD ENTRY bias start <side> <kind> stop-ref <px> [target <px>], bias end <reason>, order placed <side> entry <px> stop <px> target <px> cancel <px>, order cancelled <reason>, filled <px>, partial <px> qty <frac>, stop to breakeven <px>, exit <reason> <px> R <r>. Plus one alertcondition "ZTD ENTRY: any event" for users who prefer the classic dialog.htfNew (1 on the chart bar that consumed a new HTF bar), htfSigBear, htfSigBull, htfOvl, htfCurHi, htfCurLo, htfMidLoB, htfMidHiU, htfContraB, htfContraU, htfExt, htfTriB, htfTriU (v8.0), biasSide, biasKind (1 RDIV / 2 HDIV / 3 ARM), biasStartBar, biasExt, biasTarget, biasEndCode, biasStartNow, barIndex, pendEntry, pendStop, pendTarget, pendCancel, pendPlacedBar, orderPlaced, orderCancelCode, posQty, posFill, posFillBar, posStop, partialPx, fillNow, partialNow, exitCode (1 stop / 2 target / 3 bias end / 4 breakeven / 5 opp triangle), exitPx, tradeR, tooShort, rrRejected, alreadyBroken, skippedInPos. 42 plots + 1 alertcondition, under the 64-output budget.pyakao/validation/compare_ztd_tv.py flow with the export tooling, --match on both scripts). Divergence mode compares sigBear/sigBull/curHi/curLo/midLoB/midHiU (the latter two against the pyakao port, since v17 does not plot them); arm mode compares ovl with tMinTier = Extreme against a ZTD instance set to that tier.harmonic/validation/export_tf.py pattern, --tf 5 --match "ZTD Entry"), feed the exported 5m bars to run_entry5m with the matching config (slippage_ticks = 0, the same inputs), and compare: bias starts (chart bar, side, kind, ext, target), bias ends (bar, reason), pending orders (placed bar, entry, stop, target, cancel), fills (bar, price), partials, exits (bar, reason). Pass = zero mismatches on bias and order levels; fills may differ only where Pine's HTF alignment differs from build_htf (documented per case). entry5m/validation/compare_entry_tv.py prints the audit.Done, 2026-09-07 (v7.0, entity 3wowED, FX:EURUSD).
data_entry, 25,541 H1 bars): RESULT: PASS, 0 mismatches on all nine
pairs — htfSigBear/htfSigBull/htfOvl/htfExt/htfCurHi/htfCurLo/htfContra Pine-vs-Pine over 25,540
compared bars (from bar 1) and htfMidLoB/htfMidHiU against the port over 23,141 (from bar 2400).data_entry_arm, 41,522 H1 bars, ZTD v17 Triangle tier that arms = Extreme,
indicator Bias source = Extreme arm): RESULT: PASS, 0 mismatches on the same nine pairs,
ovl included, over 39,122 compared bars. That export reaches the studies' first bar, so the
Pine-vs-Pine gates also need the 2400-bar floor there (--first-pine 2400): the generated core
carries make_entry_core.py's deliberate percentile-window cap (math.min(tCalib, tZBars)) that
v17 lacks, so while cold the core produces tiers from bar ~223 and v17 only from ~1999. Every
mismatch on that export sat in bars 223-2116 and none after.data_entry_arm 5m, 40,291 bars, --first 26700 → 13,591 compared bars):
pyakao's run over the export holds 21 biases, 81 orders and 32 trades (80/31 once the tie below is
allowed for); one bias starting at bar 26653 and the order it placed at 26668 fall before the
--first floor and are therefore not compared. Inside the window: 0 mismatches on biases, bias
ends, order levels, fills, partials and exits — after allowing a sub-tick tolerance on the two price
comparisons that decide a fill and the already-broken test (see below). The window holds 21 biasEndCode 5 (range_end)
events and 0 code 4 (replaced) events; an arm bias here always ends because its side's running
extreme goes na before the opposite side can arm.high = 1.16231 (3ff298d2_5edd0529) against pendEntry = 1.1623100000000002
(…052a), and bar 36821 low = 1.16748 (3ff2adff_822bbecb) against entry = 1.1674799999999999
(…beca). Pine resolves both as touching, Python's IEEE comparison does not. Bit patterns of the
bars themselves are identical between TradingView and the export, and pendEntry/pendStop match
Python's arithmetic bit-for-bit, so this is the comparison, not the data or the port. Controlled
confirmation: adding 1e-9 (far below the 1e-5 tick, far above one ULP) to exactly those two
comparisons in execution.py and setup.py — nothing else — turns the run into 0/0; the patch was
reverted and is not committed. The Pine was not changed: it expresses the same rule as setup.py.Done, 2026-09-07 (v8.0, the opposite-side HTF triangle exit, entity 3wowED updated in place,
42 plots + 1 alertcondition).
data_entry, fresh 41,538-bar H1 export, --first-pine 2400 since it reaches the
studies' first bar): RESULT: PASS, 0 mismatches on all eleven pairs over 39,138 compared bars
— the nine existing ones plus htfTriB and htfTriU, both against the pyakao port's
ZtdRow.triB/triU from bar 2400 (ZTD v17 does not plot the triangle atoms).data_entry_opptri, 40,482 5m bars, --first 26700 → 13,782
compared bars, compare_entry_tv.py --exit-opp-tri running the port with
Entry5mConfig(exit_on_opp_tri=True)): RESULT: PASS, 0 bias/order and 0 fill/exit mismatches;
pyakao's run holds 8 biases, 55 orders and 19 trades. The window contains 3 exitCode 5 events
(2026-07-16 18:00, 2026-09-02 14:00, 2026-09-03 08:00 UTC), 13 over the whole export. The 1-ULP
ties recorded below did not recur on this export.exitCode 5 bar (data window read twice, both
reads identical): htfNew 1, htfTriB 1, htfTriU 0 on a LONG bias, exitCode 5, exitPx 1.160380 — exit code and price match the export exactly. tradeR read 0.8301 versus the export's
0.8341 because the replay session's H1 running low came back one tick lower (biasExt 1.156620 vs
1.156630), which shifts the stop and the risk denominator; a feed-depth difference in the H1 leg
between the two sessions, not a difference in the rule.ztd_divergence.pine (untouched).request.security on an expression with var state re-evaluates the whole H1 series once per compile (acceptable; the ZMS strategy does the same).