Strategy · Pine Script v6 · On the chart

RSI(2) pullback + TokIO check

by Kuzi-DEV

This strategy enters a long position when a short RSI falls below a user threshold and price is above a simple moving average trend filter.

View on GitHub

GitHub stars4on the repository
Pine versionv6current
Lines of code186
Settings7inputs
LicenceMIT
Last update2 weeks ago15 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

186 lines of Pine Script v6 from pine/demo_rsi2_pullback.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

demo_rsi2_pullback.pine
//@version=6
// Demo: a classic RSI(2) pullback on SPY daily, with the TokIO check pasted underneath.
// Alone it looks like an edge: plain t-test p=0.0004, dependence-corrected p=0.006.
// Set "Variants tried" to 20 (the RSI lengths, thresholds and exits you might have
// tried) and it is NOT SIGNIFICANT: p=0.11, Deflated Sharpe 0.82, and its minimum
// track record is 351 trades against the 106 it has (0.05% commission, 1 tick slippage).
strategy("RSI(2) pullback + TokIO check", overlay = true, initial_capital = 10000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, commission_value = 0.05, slippage = 1)
rsiLen = input.int(2, "RSI length")
buyBelow = input.int(5, "Buy when RSI below")
sellAbove = input.int(60, "Sell when RSI above")
trendLen = input.int(200, "Trend filter SMA")
r = ta.rsi(close, rsiLen)
trend = ta.sma(close, trendLen)
plot(trend, color = color.orange)
if r < buyBelow and close > trend
    strategy.entry("Long", strategy.long)
if r > sellAbove
    strategy.close("Long")

// ─────────────────────────────────────────────────────────────────────────────
// TokIO backtest check for TradingView — paste below your strategy's code.
// https://github.com/Kuzi-DEV/Tokio-ai   (MIT licence)
//
// Is this strategy's profit distinguishable from luck? Reads the strategy's
// closed trades and draws a table on the chart with:
//   • a one-sided test of the mean trade return that allows for serial
//     dependence (Bartlett HAC, Andrews bandwidth, Kiefer-Vogelsang fixed-b),
//     the same test as TokIO's Python check_backtest on a trade list
//   • Sidak's correction for the number of variants you tried ("Trials")
//   • the Probabilistic / Deflated Sharpe Ratio (Bailey & Lopez de Prado),
//     as published and with the dependence correction
//   • the minimum track record length, and a symmetric-trim check
//
// A trade's return is its P&L as a % of the position's value
// (strategy.closedtrades.profit_percent), so position sizing doesn't move
// the verdict. The Python package does more — several variants corrected
// for each other, probability of backtest overfitting, costs/breakeven, the
// lookahead (one-bar delay) check — on the Strategy Tester's trade export:
//     pip install tokio-ai
//     tokio-ai-backtest "List of trades.csv" --trials 30
//
// Requires: //@version=6 and a strategy() script. Rename nothing below.
// ─────────────────────────────────────────────────────────────────────────────

tokio_trials = input.int(1, "Variants tried (incl. this one)", minval = 1, group = "TokIO check",
     tooltip = "Every parameter set, indicator or rule you tried before keeping this one. Be honest: the correction is only as good as this number.")
tokio_alpha = input.float(0.05, "Significance level", minval = 0.001, maxval = 0.5, group = "TokIO check")
tokio_pos = input.string("bottom_right", "Table position", options = ["top_left", "top_center", "top_right", "middle_left", "middle_center", "middle_right", "bottom_left", "bottom_center", "bottom_right"], group = "TokIO check")

// Standard normal CDF (Abramowitz & Stegun 7.1.26 erf, |error| < 1.5e-7)
tokio_cdf(float tk_z) =>
    tk_x = math.abs(tk_z) / math.sqrt(2.0)
    tk_t = 1.0 / (1.0 + 0.3275911 * tk_x)
    tk_y = 1.0 - (((((1.061405429 * tk_t - 1.453152027) * tk_t) + 1.421413741) * tk_t - 0.284496736) * tk_t + 0.254829592) * tk_t * math.exp(-tk_x * tk_x)
    tk_z >= 0 ? 0.5 * (1.0 + tk_y) : 0.5 * (1.0 - tk_y)

// Inverse standard normal CDF (Acklam, relative error < 1.2e-9)
tokio_inv(float tk_p) =>
    tk_a1 = -3.969683028665376e+01
    tk_a2 = 2.209460984245205e+02
    tk_a3 = -2.759285104469687e+02
    tk_a4 = 1.383577518672690e+02
    tk_a5 = -3.066479806614716e+01
    tk_a6 = 2.506628277459239e+00
    tk_b1 = -5.447609879822406e+01
    tk_b2 = 1.615858368580409e+02
    tk_b3 = -1.556989798598866e+02
    tk_b4 = 6.680131188771972e+01
    tk_b5 = -1.328068155288572e+01
    tk_c1 = -7.784894002430293e-03
    tk_c2 = -3.223964580411365e-01
    tk_c3 = -2.400758277161838e+00
    tk_c4 = -2.549732539343734e+00
    tk_c5 = 4.374664141464968e+00
    tk_c6 = 2.938163982698783e+00
    tk_d1 = 7.784695709041462e-03
    tk_d2 = 3.224671290700398e-01
    tk_d3 = 2.445134137142996e+00
    tk_d4 = 3.754408661907416e+00
    float tk_r = na
    if tk_p < 0.02425
        tk_q = math.sqrt(-2.0 * math.log(tk_p))
        tk_r := (((((tk_c1 * tk_q + tk_c2) * tk_q + tk_c3) * tk_q + tk_c4) * tk_q + tk_c5) * tk_q + tk_c6) / ((((tk_d1 * tk_q + tk_d2) * tk_q + tk_d3) * tk_q + tk_d4) * tk_q + 1.0)
    else if tk_p <= 1.0 - 0.02425
        tk_q = tk_p - 0.5
        tk_s = tk_q * tk_q
        tk_r := (((((tk_a1 * tk_s + tk_a2) * tk_s + tk_a3) * tk_s + tk_a4) * tk_s + tk_a5) * tk_s + tk_a6) * tk_q / (((((tk_b1 * tk_s + tk_b2) * tk_s + tk_b3) * tk_s + tk_b4) * tk_s + tk_b5) * tk_s + 1.0)
    else
        tk_q = math.sqrt(-2.0 * math.log(1.0 - tk_p))
        tk_r := -(((((tk_c1 * tk_q + tk_c2) * tk_q + tk_c3) * tk_q + tk_c4) * tk_q + tk_c5) * tk_q + tk_c6) / ((((tk_d1 * tk_q + tk_d2) * tk_q + tk_d3) * tk_q + tk_d4) * tk_q + 1.0)
    tk_r

tokio_fmt(float tk_v, int dp) =>
    na(tk_v) ? "–" : str.tostring(tk_v, dp == 2 ? "#,##0.00" : dp == 3 ? "0.000" : "0.0000")

if barstate.islastconfirmedhistory or (barstate.islast and barstate.isrealtime)
    int tk_n = strategy.closedtrades
    var table tk_tbl = na
    if not na(tk_tbl)
        table.delete(tk_tbl)
    tk_pos = switch tokio_pos
        "top_left" => position.top_left
        "top_center" => position.top_center
        "top_right" => position.top_right
        "middle_left" => position.middle_left
        "middle_center" => position.middle_center
        "middle_right" => position.middle_right
        "bottom_left" => position.bottom_left
        "bottom_center" => position.bottom_center
        => position.bottom_right
    tk_tbl := table.new(tk_pos, 2, 12, bgcolor = color.new(color.black, 0), border_color = color.gray, border_width = 1, frame_color = color.gray, frame_width = 1)
    tk_txt = color.white
    table.cell(tk_tbl, 0, 0, "TokIO check", text_color = tk_txt, text_size = size.small)
    if tk_n < 60
        table.cell(tk_tbl, 1, 0, "NOT REPORTABLE", text_color = color.orange, text_size = size.small)
        table.cell(tk_tbl, 0, 1, "Closed trades", text_color = tk_txt, text_size = size.small)
        table.cell(tk_tbl, 1, 1, str.tostring(tk_n) + " (need 60+)", text_color = tk_txt, text_size = size.small)
    else
        tk_rets = array.new_float(0)
        for tk_i = 0 to tk_n - 1
            array.push(tk_rets, strategy.closedtrades.profit_percent(tk_i) / 100.0)
        float tk_m = array.avg(tk_rets)
        // central moments (population), Bartlett long-run variance
        float tk_s2 = 0.0
        float tk_s3 = 0.0
        float tk_s4 = 0.0
        float tk_g1 = 0.0
        for tk_i = 0 to tk_n - 1
            tk_d = array.get(tk_rets, tk_i) - tk_m
            tk_s2 += tk_d * tk_d
            tk_s3 += tk_d * tk_d * tk_d
            tk_s4 += tk_d * tk_d * tk_d * tk_d
            if tk_i > 0
                tk_g1 += tk_d * (array.get(tk_rets, tk_i - 1) - tk_m)
        tk_v = tk_s2 / tk_n
        tk_sd = math.sqrt(tk_s2 / (tk_n - 1))
        tk_skew = (tk_s3 / tk_n) / math.pow(tk_v, 1.5)
        tk_kurt = (tk_s4 / tk_n) / (tk_v * tk_v)
        // Andrews (1991) AR(1) plug-in and the Newey-West rule; the larger wins
        tk_rho = math.max(-0.97, math.min(0.97, tk_g1 / tk_s2))
        tk_a1 = 4.0 * tk_rho * tk_rho / (math.pow(1.0 - tk_rho, 2) * math.pow(1.0 + tk_rho, 2))
        int tk_L = math.min(tk_n - 1, math.max(int(math.floor(4.0 * math.pow(tk_n / 100.0, 2.0 / 9.0))), int(1.1447 * math.pow(tk_a1 * tk_n, 1.0 / 3.0))))
        float tk_lrv = tk_s2
        if tk_L > 0
            for tk_l = 1 to tk_L
                float tk_gl = 0.0
                for tk_t = tk_l to tk_n - 1
                    tk_gl += (array.get(tk_rets, tk_t) - tk_m) * (array.get(tk_rets, tk_t - tk_l) - tk_m)
                tk_lrv += 2.0 * (1.0 - tk_l / (tk_L + 1.0)) * tk_gl
        tk_lrv := math.max(tk_lrv / tk_n, 1e-18)
        tk_b = (tk_L + 1.0) / tk_n
        tk_fb = 1.6449 / (1.6449 + 2.1859 * tk_b + 0.3142 * tk_b * tk_b - 0.3427 * tk_b * tk_b * tk_b)
        tk_z = tk_m / math.sqrt(tk_lrv / tk_n) * tk_fb
        tk_p_alone = 1.0 - tokio_cdf(tk_z)
        tk_p_adj = 1.0 - math.pow(1.0 - tk_p_alone, tokio_trials)
        tk_z_naive = tk_m / (tk_sd / math.sqrt(tk_n))
        tk_p_naive = 1.0 - tokio_cdf(tk_z_naive)
        // Sharpe per trade; annualized by trades per year
        tk_sr = tk_m / tk_sd
        tk_span_years = (strategy.closedtrades.exit_time(tk_n - 1) - strategy.closedtrades.entry_time(0)) / (365.25 * 86400000.0)
        tk_tpy = tk_span_years > 0 ? tk_n / tk_span_years : na
        tk_sr_ann = na(tk_tpy) ? na : tk_sr * math.sqrt(tk_tpy)
        // PSR / DSR (Bailey & Lopez de Prado); vr scales Var(SR) for dependence
        tk_vr = (tk_lrv / tk_v) / (tk_fb * tk_fb)
        tk_core = math.max(1.0 - tk_skew * tk_sr + (tk_kurt - 1.0) / 4.0 * tk_sr * tk_sr, 1e-12)
        tk_gam = 0.5772156649015329
        tk_bench = tokio_trials > 1 ? math.sqrt(1.0 / (tk_n - 1)) * ((1.0 - tk_gam) * tokio_inv(1.0 - 1.0 / tokio_trials) + tk_gam * tokio_inv(1.0 - 1.0 / (tokio_trials * math.e))) : 0.0
        tk_psr_pub = tokio_cdf((tk_sr - tk_bench) * math.sqrt(tk_n - 1) / math.sqrt(tk_core))
        tk_psr_dep = tokio_cdf((tk_sr - tk_bench) * math.sqrt(tk_n - 1) / math.sqrt(tk_core * tk_vr))
        tk_mintrl = tk_sr > tk_bench ? 1.0 + tk_core * tk_vr * math.pow(tokio_inv(0.95) / (tk_sr - tk_bench), 2) : na
        // symmetric trim: drop the 5 best and 5 worst trades
        tk_sorted = array.copy(tk_rets)
        array.sort(tk_sorted, order.ascending)
        tk_k = math.min(5, int(tk_n / 20))
        tk_tr = array.slice(tk_sorted, tk_k, tk_n - tk_k)
        tk_sr_trim = array.stdev(tk_tr, false) > 0 ? array.avg(tk_tr) / array.stdev(tk_tr, false) * (na(tk_tpy) ? 1.0 : math.sqrt(tk_tpy)) : na
        tk_sig = tk_p_adj <= tokio_alpha
        tk_verdict = tk_sig ? "SIGNIFICANT" : "NOT SIGNIFICANT"
        table.cell(tk_tbl, 1, 0, tk_verdict + (tokio_trials > 1 ? " (" + str.tostring(tokio_trials) + " trials)" : ""), text_color = tk_sig ? color.lime : color.red, text_size = size.small)
        tk_rows = array.from("p-value, corrected", "p-value, this alone", "p-value, plain t-test", "Sharpe (annualized)", (tokio_trials > 1 ? "Deflated" : "Probabilistic") + " Sharpe Ratio", "  as published (indep. trades)", "Min. track record (trades)", "Sharpe w/o 5 best & 5 worst", "Closed trades", "Trades per year")
        tk_vals = array.from(tokio_fmt(tk_p_adj, 4), tokio_fmt(tk_p_alone, 4), tokio_fmt(tk_p_naive, 4), tokio_fmt(tk_sr_ann, 2), tokio_fmt(tk_psr_dep, 3) + "  (0.95 passes)", tokio_fmt(tk_psr_pub, 3), na(tk_mintrl) ? "never" : str.tostring(math.ceil(tk_mintrl)), tokio_fmt(tk_sr_trim, 2), str.tostring(tk_n), tokio_fmt(tk_tpy, 2))
        for tk_i = 0 to array.size(tk_rows) - 1
            table.cell(tk_tbl, 0, tk_i + 1, array.get(tk_rows, tk_i), text_color = tk_txt, text_size = size.small, text_halign = text.align_left)
            table.cell(tk_tbl, 1, tk_i + 1, array.get(tk_vals, tk_i), text_color = tk_txt, text_size = size.small, text_halign = text.align_right)
        table.cell(tk_tbl, 0, 11, "Mean trade return " + tokio_fmt(tk_m * 100.0, 3) + "%; HAC lag window " + str.tostring(tk_L), text_color = color.gray, text_size = size.tiny, text_halign = text.align_left)
        table.merge_cells(tk_tbl, 0, 11, 1, 11)

Overview

RSI(2) pullback + TokIO check closes the long when RSI rises above a second threshold and does not set a stop loss. Position size defaults to full equity. It plots the trend average on the price chart and draws a TokIO table that tests closed-trade returns for serial dependence, trial-count correction, and Sharpe-style significance. Trial count, significance level, and table position are configurable.

Details

Published by

Kuzi-DEV on GitHub

Draws

On the price chart

Markets

Stocks

Timeframes

H4 and above

Risk Notes

  • The strategy enters trades without a stop loss

Topics

algorithmic-tradingfinancehypothesis-testingllm-agentpythonquantitative-financestatisticspermutation-testreproducible-researchbacktest-overfitting

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
RSI lengthint2rsiLen
Buy when RSI belowint5buyBelow
Sell when RSI aboveint60sellAbove
Trend filter SMAint200trendLen
Variants tried (incl. this one)int1tokio_trials
Significance levelfloat0.05tokio_alpha
Table positionstringbottom_righttokio_pos
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

104 stars

This overlay strategy combines a machine-learning distance model with a MACD oscillator to open trades on the price chart. It compares recent history using cosine similarity or Euclidean and Lorentzian distance, then filters direction with selectable moving-av

Strategy v5 AI / machine learningOscillators & momentum
Updated 3 years ago · MIT GitHub repository of MLCEL and MACD Strategy

This long-only trend-following strategy combines Ichimoku Kinko Hyo components with higher timeframe moving average filters. It triggers long entries when price trades above a higher timeframe EMA and a bullish Tenkan-Sen cross above Kijun-Sen occurs under fav

Strategy v5 TrendOscillators & momentum
Updated 1 year ago · MPL-2.0 GitHub repository of Ichimoku Kinko Hyo Momentum Strategy

This strategy calculates trend direction across three user-defined higher timeframes using dual Simple Moving Averages, filtered by On-Balance Volume and Commodity Channel Index conditions alongside fractal pivot swings. Entries trigger when multi-timeframe tr

Strategy v5 TrendMoving averages Repaints
Updated 5 months ago · None stated GitHub repository of Fractals with Pivot Trendlines Strategy
2 stars

This strategy plots on the gold price chart and combines stochastic, RSI, and three EMAs with ATR. Confirm buys and sells can require an M15 overbought or oversold rejection wick, a Fibonacci or EMA zone, and a no-chase distance from the fast EMA. Optional LSB

Strategy v5 Oscillators & momentumMoving averages
Updated 4 months ago · None stated GitHub repository of XAUUSD Strategy - Hook Trap Guard

This strategy automatically adapts its moving average lengths and types based on the chart's timeframe, covering scalping, intraday, and swing styles. It generates entry signals when a fast moving average crosses a slow moving average, provided price is on the

Strategy v6 TrendMoving averages
Updated 10 months ago · MIT GitHub repository of EMA / SMA Crossover + ADX + EMA100 Trend Filter

Tn Sovereign CCI v6

by raybird
1 stars

This strategy draws on the price chart and trades a fast and slow Commodity Channel Index against an exponential moving average regime. It enters long when the fast CCI crosses above the lower extreme, the slow CCI is already above that level, and price is abo

Strategy v6 Oscillators & momentumMoving averages
Updated 2 months ago · None stated GitHub repository of Tn Sovereign CCI v6

More Oscillators & momentum scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers