PineForge
v0.13.1-379-g9b50973
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
trail_ticks.hpp
Go to the documentation of this file.
1
#pragma once
2
// TradingView's trailing-exit tick arithmetic: how strategy.exit's
3
// trail_points / trail_offset are read as tick counts and how a trailing
4
// level is materialized on the tick grid. Every constant here is a
5
// TradingView calibration (the pins are quoted below), so it belongs to the
6
// source layer; the kernel's own trail is TrailTicks (native_order.hpp),
7
// which needs none of it (R5 lane N14: moved verbatim from
8
// src/engine_internal.hpp, where no kernel translation unit used it).
9
#include <cmath>
10
11
namespace
pineforge::compat::pine
{
12
13
// ── Trailing-exit tick arithmetic ─────────────────────────────────────
14
//
15
// TradingView reads strategy.exit's trail_points / trail_offset as TICK
16
// COUNTS: trail_points is ceiled WITH a tolerance that swallows floating-
17
// point residue — a value computed as close * 0.02 / syminfo.mintick that
18
// lands a few ulps past a whole number is that whole number, not the next
19
// one — while trail_offset is floored EXACTLY. Pinned with `lab tv` on
20
// NYSE:F 15m 2025-04-01..05, short from the 04-02 19:00Z signal (entry
21
// 10.11, mintick 0.01; scratchpad/r7/pins/trail-eq-*), each zero-offset
22
// exit filling at its activation level:
23
// trail_points 14.00001 -> 14 ticks (9.97)
24
// trail_points 14.0001 / 14.001 -> 15 ticks (9.96)
25
// trail_points 0.14 / syminfo.mintick (= 14.000000000000002) -> 14 (9.97)
26
// trail_points 14.0000001 -> 14 (9.97)
27
// trail_points 18.2 -> 19 (9.92)
28
// trail_offset 0.3 / (syminfo.mintick * 10) (= 2.9999999999999996)
29
// -> 2 ticks (trail_points 18: fills 04-03 14:15Z @9.85 = trough 9.83
30
// + 2t; a tolerant floor would trail 3t and print 9.86)
31
// and BINANCE:BTCUSDT 15m short 2025-08-17 23:30Z @117559.99 with
32
// trail_points = 117560 * 0.02 / 0.01 = 235120.00000000003: TV exits
33
// 08-18 03:30Z @115208.79 (235120 ticks); std::ceil gave 235121 -> .78.
34
// The ceil tolerance is bounded in [1e-5, 1e-4) by the 14.00001 / 14.0001
35
// pair; 5e-5 sits in the middle. Round 5's sub-tick pins hold: 0.0006 ->
36
// 1 tick, offsets 0 / 0.5 / 0.9 -> 0, 1.4 -> 1.
37
constexpr
double
kTrailPointsCeilEps
= 5e-5;
38
39
inline
double
trail_points_to_ticks
(
double
trail_points) {
40
return
std::ceil(trail_points -
kTrailPointsCeilEps
);
// NaN stays NaN
41
}
42
43
inline
double
trail_offset_to_ticks
(
double
trail_offset) {
44
return
std::floor(trail_offset);
// exact; NaN stays NaN
45
}
46
47
// The broker keeps trailing levels ON the tick grid: an activation level
48
// entry -/+ N ticks and a trailing level best -/+ K ticks are tick counts,
49
// and a bar extreme landing exactly on the level TOUCHES it. Built in
50
// doubles, 10.11 - 21 * 0.01 is 9.899999999999999 — one ulp under the 9.9
51
// low — and the inclusive segment test reads it as "not reached" (NYSE:F
52
// 15m 2025-04-03 13:45Z, bar O 10.165 H 10.18 L 9.9 C 9.9: TV fills the
53
// trail there @9.90, `lab tv` trail-eq-S-off0-tp21; the engine gap-filled
54
// the next open @9.89). Materialize a level within a millionth of a tick
55
// of the grid as the grid point, spelled the way tick_grid_price
56
// (engine.hpp) spells it so it compares EQUAL to a feed print bit for bit;
57
// a genuinely sub-tick level (best 196.135 - 1 tick = 196.125) stays raw
58
// and takes the directional fill snap downstream.
59
inline
double
snap_trail_level_to_tick_grid
(
double
price
,
double
mintick) {
60
if
(std::isnan(
price
) || !(mintick > 0.0))
return
price
;
61
const
double
r =
price
/ mintick;
62
const
double
k = std::floor(r + 0.5);
63
if
(std::abs(r - k) > 1e-6)
return
price
;
64
const
double
inv = 1.0 / mintick;
65
const
double
inv_int = std::floor(inv + 0.5);
66
if
(inv_int > 0.0 && std::abs(inv - inv_int) <= 1e-6 * inv_int) {
67
return
k / inv_int;
68
}
69
return
k * mintick;
70
}
71
72
}
// namespace pineforge::compat::pine
pineforge::compat::pine
Definition
exit_activation.hpp:14
pineforge::compat::pine::trail_offset_to_ticks
double trail_offset_to_ticks(double trail_offset)
Definition
trail_ticks.hpp:43
pineforge::compat::pine::trail_points_to_ticks
double trail_points_to_ticks(double trail_points)
Definition
trail_ticks.hpp:39
pineforge::compat::pine::snap_trail_level_to_tick_grid
double snap_trail_level_to_tick_grid(double price, double mintick)
Definition
trail_ticks.hpp:59
pineforge::compat::pine::kTrailPointsCeilEps
constexpr double kTrailPointsCeilEps
Definition
trail_ticks.hpp:37
pineforge::YLoc::price
@ price
Definition
drawing.hpp:33
include
pineforge
compat
pine
trail_ticks.hpp
PineForge v0.13.1-379-g9b50973 — Apache-2.0 —
github.com/pineforge-4pass/pineforge-engine