Appearance
Personalize your experience
Hawkes Shock Reversal
Admin's ChoiceFreeBuys the end of a selling cascade, sells the end of a frenzy
Live engine preview
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.
About
Buys the end of a selling cascade and sells the end of a buying frenzy. Large moves are counted as events in a self-exciting Hawkes process, so clusters build intensity and the intensity then decays. When a cluster of down shocks has decayed (calm returning) and price closes back above a short mean, the forced selling is likely done. Entry: down-shock intensity peaked above the cluster level and has since decayed below the calm level, close above the 10-bar EMA (mirror for shorts). Exit: stop below the cascade low, target `reward` R, time stop. Risk: 1 % per trade. Method: Hawkes (1971).
Settings
Volatility window: 100
Shock size (sigma): 2
Decay per bar: 0.12
Cluster level: 1.2
Calm level: 0.3
Target (R): 2
Maximum bars held: 48
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
- ▸ down-shock intensity peaked above the cluster level and has since decayed below the calm level, close above the 10-bar EMA (mirror for shorts)
Exit Conditions
- ▸ stop below the cascade low, target `reward` R, time stop
Measured backtest
BTCUSDT 1h (Binance), 2025-11-01 to 2026-11-01 · backtest engine, script costs included
1.2%
Return
0.16
Sharpe
-10.1%
Max DD
41.4%
Win Rate
116
Trades
| Market | Trades | Return | Sharpe | Max DD | Win rate | Profit factor |
|---|---|---|---|---|---|---|
| BTCUSDT 1h | 116 | 1.2% | 0.16 | -10.1% | 41.4% | 1.02 |
| ETHUSDT 1h | 112 | 18.3% | 1.40 | -7.3% | 43.8% | 1.31 |
Past results on historical data do not predict future returns.
Source Code
Edit in IDE| 1 | strategy "Hawkes Shock Reversal" { |
| 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 the end of a selling cascade and sells the end of a buying frenzy. Large moves are counted |
| 12 | /// as events in a self-exciting Hawkes process, so clusters build intensity and the intensity then |
| 13 | /// decays. When a cluster of down shocks has decayed (calm returning) and price closes back above |
| 14 | /// a short mean, the forced selling is likely done. |
| 15 | /// Entry: down-shock intensity peaked above the cluster level and has since decayed below the calm |
| 16 | /// level, close above the 10-bar EMA (mirror for shorts). Exit: stop below the cascade low, target |
| 17 | /// `reward` R, time stop. Risk: 1 % per trade. Method: Hawkes (1971). |
| 18 | use "viz/premium" as pr |
| 19 | len = param.int(100, title = "Volatility window", min = 20, max = 2000, group = "Shocks") |
| 20 | k_sd = param.float(2.0, title = "Shock size (sigma)", min = 1, max = 5, step = 0.1, group = "Shocks") |
| 21 | decay = param.float(0.12, title = "Decay per bar", min = 0.01, max = 0.8, step = 0.01, group = "Process") |
| 22 | hot = param.float(1.2, title = "Cluster level", min = 0.2, max = 10, step = 0.1, group = "Signals") |
| 23 | calm = param.float(0.3, title = "Calm level", min = 0.01, max = 5, step = 0.01, group = "Signals") |
| 24 | reward = param.float(2.0, title = "Target (R)", min = 0.5, max = 10, step = 0.1, group = "Risk") |
| 25 | hold = param.int(48, title = "Maximum bars held", min = 2, max = 500, group = "Risk") |
| 26 | r = math.log(close / close[1]) |
| 27 | sd_now = stat.stdev(r, len) |
| 28 | sd = sd_now[1] |
| 29 | lam_d = hft.hawkes(r < -k_sd * sd, decay, 1) |
| 30 | lam_u = hft.hawkes(r > k_sd * sd, decay, 1) |
| 31 | e10 = ta.ema(close, 10) |
| 32 | low20 = ta.lowest(low, 20) |
| 33 | high20 = ta.highest(high, 20) |
| 34 | persist armed_l = false |
| 35 | persist armed_s = false |
| 36 | if lam_d > hot { armed_l := true } |
| 37 | if lam_u > hot { armed_s := true } |
| 38 | flat = position.size == 0 |
| 39 | go_l = armed_l and lam_d < calm and close > e10 |
| 40 | go_s = armed_s and lam_u < calm and close < e10 |
| 41 | if flat and go_l { |
| 42 | order.market("L", side.long) |
| 43 | exit.bracket("L exit", entry = "L", stop = low20, target = close + (close - low20) * reward) |
| 44 | armed_l := false |
| 45 | } |
| 46 | if flat and go_s { |
| 47 | order.market("S", side.short) |
| 48 | exit.bracket("S exit", entry = "S", stop = high20, target = close - (high20 - close) * reward) |
| 49 | armed_s := false |
| 50 | } |
| 51 | if position.size != 0 and position.bars_held >= hold { exit.close_all() } |
| 52 | risk.max_drawdown(25) |
| 53 | render.line(e10, "10-bar EMA", color = color.slate.300, width = 1) |
| 54 | render.mark(lam_d > hot and lam_d[1] <= hot, shape = shape.x, at = anchor.below_bar, color = color.rose.400, size = 0.6, title = "Selling cascade") |
| 55 | render.mark(lam_u > hot and lam_u[1] <= hot, shape = shape.x, at = anchor.above_bar, color = color.emerald.400, size = 0.6, title = "Buying frenzy") |
| 56 | render.mark(go_l and flat, shape = shape.triangle_up, at = anchor.below_bar, color = color.sky.300, text = "Calm", title = "Long after cascade") |
| 57 | render.mark(go_s and flat, shape = shape.triangle_down, at = anchor.above_bar, color = color.amber.300, text = "Calm", title = "Short after frenzy") |
| 58 | persist t = draw.table.create(anchor.top_right, 4, 2) |
| 59 | if bar.is_last { |
| 60 | pr.heading(t, 2, "Hawkes Shock Reversal", "Strategy · self-exciting shocks") |
| 61 | pr.row(t, 2, "Down / up intensity", str.format("{:.2f} / {:.2f}", lam_d, lam_u), color.white) |
| 62 | pr.row(t, 3, "Armed", armed_l ? "Long" : armed_s ? "Short" : "No", armed_l ? pr.BULL : armed_s ? pr.BEAR : pr.LABEL) |
| 63 | } |
| 64 |
Reviews
No reviews yet. Be the first to review this listing.