Appearance

Personalize your experience

Mode
Accent Color
Direction
MarketplacestrategiesMomentum Term Pullback
QuaScript

Momentum Term Pullback

Admin's ChoiceFree

Long-horizon trend, short-horizon dip, entry on the turn

0.0(0)
0 installs 0 0 comments
Q
159 listings

The QuaTick team's QuaScript analyses, run by the native C++ engine.

View Profile
quascriptstrategymomentumpullbackterm-structure
Free
Backtest this strategy Open in QuaTick IDE Edit in IDE
Version
Updated
Compatible

Live engine preview

QuaScriptQuaScript

The QuaScript engine's own output on the chart the terminal uses. Change the settings or edit the code and press Run to recompute it.

Momentum Term Pullbackengine result
Loading the engine result…
quatick-charts · QuaScript engine on synthetic 1-minute bars · drag to pan · scroll to zoom · Run executes the script on the engine (⌘/Ctrl+Enter while editing)

About

Buys dips that the long horizons have not noticed. Momentum is measured on a short and a long horizon band as volatility-scaled t-statistics (return over the horizon divided by the volatility expected over it). When the long band is strongly positive while the short band has gone negative, price is pulling back inside an established trend; the entry waits until the short band turns back up, so the pullback is already ending. Shorts mirror this. Entry: long-band t above `long_t`, short-band t below `-dip_t` within the last `memory` bars and now rising for two bars (mirror for shorts). Exit: ATR stop under the pullback low, target `reward` R, or the long band losing its sign. Risk: 1 % per trade.


Settings

Short band from: 3

Short band to: 12

Long band from: 60

Long band to: 160

Volatility window: 200

Trend strength (t): 1

Pullback depth (t): 0.6

Pullback memory (bars): 8

Target (R): 2.5


Measured backtests

Run by the backtest engine on public candles, 2025-11-01 to 2026-11-01, with the script's own commission and slippage, on BTCUSDT 1h (Binance) and ETHUSDT 1h (Binance). The figures per market are in the Measured backtest panel below. Past results do not predict future returns.


Backtest it yourself

Open it on the backtesting page to run it on any symbol, interval and date range, then use Monte Carlo, optimisation, walk-forward and robustness tests.

Strategy Rules

Entry Conditions

  • ▸ long-band t above `long_t`, short-band t below `-dip_t` within the last `memory` bars and now rising for two bars (mirror for shorts)

Exit Conditions

  • ▸ ATR stop under the pullback low, target `reward` R, or the long band losing its sign

Measured backtest

BTCUSDT 1h (Binance), 2025-11-01 to 2026-11-01 · backtest engine, script costs included

Backtest this strategy

4.6%

Return

0.52

Sharpe

-7.9%

Max DD

36.4%

Win Rate

44

Trades

MarketTradesReturnSharpeMax DDWin rateProfit factor
BTCUSDT 1h444.6%0.52-7.9%36.4%1.16
ETHUSDT 1h3210.2%1.18-7.4%40.6%1.48

Past results on historical data do not predict future returns.

Source Code

Edit in IDE
quascript
1strategy "Momentum Term Pullback" {
2 overlay = true
3 capital = 100000
4 commission = 0.05
5 slippage = 1
6 sizing = risk_percent
7 max_leverage = 1
8 size = 1
9 pyramiding = 1
10}
11/// Buys dips that the long horizons have not noticed. Momentum is measured on a short and a long
12/// horizon band as volatility-scaled t-statistics (return over the horizon divided by the
13/// volatility expected over it). When the long band is strongly positive while the short band has
14/// gone negative, price is pulling back inside an established trend; the entry waits until the
15/// short band turns back up, so the pullback is already ending. Shorts mirror this.
16/// Entry: long-band t above `long_t`, short-band t below `-dip_t` within the last `memory` bars and
17/// now rising for two bars (mirror for shorts). Exit: ATR stop under the pullback low, target
18/// `reward` R, or the long band losing its sign. Risk: 1 % per trade.
19use "viz/premium" as pr
20s_lo = param.int(3, title = "Short band from", min = 1, max = 50, group = "Horizons")
21s_hi = param.int(12, title = "Short band to", min = 2, max = 100, group = "Horizons")
22l_lo = param.int(60, title = "Long band from", min = 10, max = 500, group = "Horizons")
23l_hi = param.int(160, title = "Long band to", min = 20, max = 1000, group = "Horizons")
24vol_n = param.int(200, title = "Volatility window", min = 20, max = 5000, group = "Horizons")
25long_t = param.float(1.0, title = "Trend strength (t)", min = 0.2, max = 4, step = 0.1, group = "Signals")
26dip_t = param.float(0.6, title = "Pullback depth (t)", min = 0.1, max = 4, step = 0.1, group = "Signals")
27memory = param.int(8, title = "Pullback memory (bars)", min = 1, max = 100, group = "Signals")
28reward = param.float(2.5, title = "Target (R)", min = 0.5, max = 10, step = 0.1, group = "Risk")
29r1 = math.log(close / close[1])
30sig = stat.stdev(r1, vol_n)
31/// Average t-statistic of the horizons lo .. hi (four evenly spaced samples).
32fn band_t(lo: int, hi: int, sig: float) -> float {
33 acc = 0.0
34 for j in 0..4 {
35 h = math.max(1, math.round(lo + (hi - lo) * j / 3))
36 acc := acc + math.log(close / close[h]) / math.max(sig * math.sqrt(h), 1e-12)
37 }
38 return acc / 4
39}
40st = band_t(s_lo, s_hi, sig)
41lt = band_t(l_lo, l_hi, sig)
42a = ta.atr(14)
43dipped = st < -dip_t
44popped = st > dip_t
45since_dip = ta.bars_since(dipped)
46since_pop = ta.bars_since(popped)
47turn_up = st > st[1] and st[1] > st[2]
48turn_dn = st < st[1] and st[1] < st[2]
49go_l = lt > long_t and math.coalesce(since_dip, 1000000) <= memory and turn_up and st < 0.5
50go_s = lt < -long_t and math.coalesce(since_pop, 1000000) <= memory and turn_dn and st > -0.5
51lo_n = ta.lowest(low, memory + 2)
52hi_n = ta.highest(high, memory + 2)
53persist used = 0
54if dipped { used := used == 1 ? 0 : used }
55if popped { used := used == -1 ? 0 : used }
56flat = position.size == 0
57if flat and go_l and used != 1 {
58 stop = math.min(lo_n - 0.25 * a, close - a)
59 order.market("L", side.long)
60 exit.bracket("L exit", entry = "L", stop = stop, target = close + (close - stop) * reward)
61 used := 1
62}
63if flat and go_s and used != -1 {
64 stop = math.max(hi_n + 0.25 * a, close + a)
65 order.market("S", side.short)
66 exit.bracket("S exit", entry = "S", stop = stop, target = close - (stop - close) * reward)
67 used := -1
68}
69if position.size > 0 and lt < 0 { exit.close("L") }
70if position.size < 0 and lt > 0 { exit.close("S") }
71risk.max_drawdown(25)
72render.candle_color(lt > long_t ? (st < 0 ? color.teal.300 : na) : lt < -long_t ? (st > 0 ? color.orange.300 : na) : na)
73render.mark(go_l and flat and used[1] != 1, shape = shape.triangle_up, at = anchor.below_bar, color = color.emerald.300, text = "Dip", title = "Long pullback entry")
74render.mark(go_s and flat and used[1] != -1, shape = shape.triangle_down, at = anchor.above_bar, color = color.rose.300, text = "Pop", title = "Short pullback entry")
75persist t = draw.table.create(anchor.top_right, 5, 2)
76if bar.is_last {
77 pr.heading(t, 2, "Momentum Term Pullback", "Strategy · short vs long momentum")
78 pr.row(t, 2, "Long band (t)", str.format("{:+.2f}", lt), lt > 0 ? pr.BULL : pr.BEAR)
79 pr.row(t, 3, "Short band (t)", str.format("{:+.2f}", st), st > 0 ? pr.BULL : pr.BEAR)
80 pr.row(t, 4, "Setup", lt > long_t and st < 0 ? "Pullback in uptrend" : lt < -long_t and st > 0 ? "Bounce in downtrend" : "None", pr.WARN)
81}
82 
Read-only preview. Open in the QuaTick IDE to edit and deploy.

Reviews

No reviews yet. Be the first to review this listing.

Discussion

Sign in to join the discussion. Your posts and replies show up on your profile.