Indicator · Pine Script v5 · On the chart

Kurutoga Screener Timing Fix

by NakliTechie

Kurutoga Screener Timing Fix calculates price divergence from highest-high and lowest-low midpoints across three lookback horizons.

View on GitHub

GitHub stars1on the repository
Pine versionv5runs as is
Lines of code176
Settings13inputs
LicenceMIT
Last update1 year ago19 Sep 2025

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 indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

176 lines of Pine Script v5 from templates/kurutoga_screener_timing_fix.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

kurutoga_screener_timing_fix.pine
//@version=5
indicator("Kurutoga Screener Timing Fix", overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500)

// --- Inputs ---
// Screener Display
col_width = input.float(5, title="Column Width (%)", group="Screener Display")
scr_numb = input.int(1, title="Screen #", tooltip="1 - rightmost screener", minval=1, group="Screener Display")

// Signal Parameters
baseLength = input.int(14, title="Base Length", minval=1, group="Signal Parameters")

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
// SYMBOLS - Enable Flags
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
u01 = input.bool(true, title="", group="Symbols", inline="s01")
u02 = input.bool(true, title="", group="Symbols", inline="s02")
u03 = input.bool(true, title="", group="Symbols", inline="s03")
u04 = input.bool(true, title="", group="Symbols", inline="s04")
u05 = input.bool(true, title="", group="Symbols", inline="s05")

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
// SYMBOLS - Tickers
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
s01 = input.symbol("NVDA", group="Symbols", inline="s01")
s02 = input.symbol("AAPL", group="Symbols", inline="s02")
s03 = input.symbol("TSLA", group="Symbols", inline="s03")
s04 = input.symbol("AMZN", group="Symbols", inline="s04")
s05 = input.symbol("GOOGL", group="Symbols", inline="s05")

// --- Script Name ---
string SCRIPT_NAME = "KURU"

// --- Colors Definition ---
colorNeutralBG = color.new(color.gray, 0)
colorSignalTXT = color.new(color.white, 0)
colorBullishBG = color.new(color.green, 75)
colorBearishBG = color.new(color.red, 75)

// --- Helper function for symbol name ---
_only_symbol_name(s) => 
    string _sym = ""
    if not na(s)
        if str.contains(s, ":")
            _sym := array.get(str.split(s, ':'), 1)
        else
            _sym := s
        _sym := str.replace_all(_sym, "_", "-")
    _sym

// --- Helper function to calculate midpoint ---
_calc_midpoint(h, l) =>
    (h + l) / 2

// --- Improved Kurutoga Signal Calculation with Timing Fix ---
calculateKurutogaSignalWithTimingFix() =>
    // Define the three lengths
    len1 = baseLength
    len2 = baseLength * 2
    len3 = baseLength * 4

    // Calculations for Length 1 (baseLength)
    high1 = ta.highest(high, len1)
    low1 = ta.lowest(low, len1)
    midpoint1 = _calc_midpoint(high1, low1)
    divergence1 = close - midpoint1

    // Calculations for Length 2 (2 * baseLength)
    high2 = ta.highest(high, len2)
    low2 = ta.lowest(low, len2)
    midpoint2 = _calc_midpoint(high2, low2)
    divergence2 = close - midpoint2

    // Calculations for Length 3 (4 * baseLength)
    high3 = ta.highest(high, len3)
    low3 = ta.lowest(low, len3)
    midpoint3 = _calc_midpoint(high3, low3)
    divergence3 = close - midpoint3

    // Signal Logic - Using explicit bar indexing to ensure proper timing
    // Bullish condition: All three are positive, and weren't on the previous bar
    allPositive = divergence1 > 0 and divergence2 > 0 and divergence3 > 0
    bullishSignal = allPositive and not allPositive[1]

    // Bearish condition: All three are negative, and weren't on the previous bar
    allNegative = divergence1 < 0 and divergence2 < 0 and divergence3 < 0
    bearishSignal = allNegative and not allNegative[1]

    // Signal Determination
    string signalCode = "---"
    if bullishSignal
        signalCode := "BUY"
    else if bearishSignal
        signalCode := "SELL"

    // Append percentage change if a signal exists
    if signalCode != "---"
        // Use the current bar's close and previous bar's close for percentage change
        float pct_change = ((close - close[1]) / close[1]) * 100.0
        string pct_change_str = str.format("{0,number,#.##}%", pct_change)
        signalCode := signalCode + " " + pct_change_str
        
    signalCode

// --- Security Calls with explicit bar indexing ---
s_expr = calculateKurutogaSignalWithTimingFix()

// Use lookahead = barmerge.lookahead_off to ensure we don't get future data
signal01 = request.security(s01, timeframe.period, s_expr, lookahead = barmerge.lookahead_off)
signal02 = request.security(s02, timeframe.period, s_expr, lookahead = barmerge.lookahead_off)
signal03 = request.security(s03, timeframe.period, s_expr, lookahead = barmerge.lookahead_off)
signal04 = request.security(s04, timeframe.period, s_expr, lookahead = barmerge.lookahead_off)
signal05 = request.security(s05, timeframe.period, s_expr, lookahead = barmerge.lookahead_off)

// --- ARRAYS ---
var s_arr = array.new_string(5)
var u_arr = array.new_bool(5)
var signal_arr = array.new_string(5)

if barstate.isfirst
    array.set(s_arr, 0, _only_symbol_name(s01))
    array.set(u_arr, 0, u01)
    array.set(s_arr, 1, _only_symbol_name(s02))
    array.set(u_arr, 1, u02)
    array.set(s_arr, 2, _only_symbol_name(s03))
    array.set(u_arr, 2, u03)
    array.set(s_arr, 3, _only_symbol_name(s04))
    array.set(u_arr, 3, u04)
    array.set(s_arr, 4, _only_symbol_name(s05))
    array.set(u_arr, 4, u05)

// Update signal_arr on every bar
array.set(signal_arr, 0, signal01)
array.set(signal_arr, 1, signal02)
array.set(signal_arr, 2, signal03)
array.set(signal_arr, 3, signal04)
array.set(signal_arr, 4, signal05)

// --- Table Drawing ---
var tbl = table.new(position.top_right, scr_numb > 1 ? 3 : 2, 10, frame_color=#151715, frame_width=1, border_width=2, border_color=color.new(color.white, 100))

if barstate.islast
    table.clear(tbl, 0, 0, scr_numb > 1 ? 2 : 1, 9)

    var int countBuy = 0
    var int countSell = 0
    countBuy := 0
    countSell := 0

    int rounded_col_width = int(math.round(col_width))

    string header_text = SCRIPT_NAME + " - " + str.tostring(scr_numb)
    table.cell(tbl, 0, 0, 'Symbol', width=rounded_col_width, text_halign=text.align_center, bgcolor=color.gray, text_color=color.white, text_size=size.small)
    table.cell(tbl, 1, 0, header_text, width=rounded_col_width, text_halign=text.align_center, bgcolor=color.gray, text_color=color.white, text_size=size.small)
    if scr_numb > 1
        table.cell(tbl, 2, 0, '', width=rounded_col_width * 2 * (scr_numb - 1), text_halign=text.align_center, bgcolor=color.new(color.gray, 100), text_size=size.small)

    int visible_row_index = 1 
    for i = 0 to 4 by 1
        if array.get(u_arr, i) 
            string signal_val_from_array = array.get(signal_arr, i)
            string current_signal = na(signal_val_from_array) ? "---" : signal_val_from_array
            string ticker_name = array.get(s_arr, i)

            color signal_bg_col = colorNeutralBG 
            
            if str.contains(current_signal, "BUY")
                countBuy += 1
                signal_bg_col := colorBullishBG
            else if str.contains(current_signal, "SELL")
                countSell += 1
                signal_bg_col := colorBearishBG

            table.cell(tbl, 0, visible_row_index, ticker_name, text_halign=text.align_center, bgcolor=color.gray, text_color=color.white, text_size=size.small, width=rounded_col_width)
            table.cell(tbl, 1, visible_row_index, current_signal, text_halign=text.align_center, bgcolor=signal_bg_col, text_color=colorSignalTXT, text_size=size.small, width=rounded_col_width)

            visible_row_index += 1

Overview

By assessing divergence consistency across base, double, and quadruple lengths, it identifies synchronized momentum conditions. The results are formatted into an on-chart screener table overlay for up to five user-defined symbols. Configurable settings include the base lookback period, table width, screener position, and individual symbol toggles.

Details

Published by

NakliTechie on GitHub

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

Screeners & dashboards, Oscillators & momentum, Divergence

Markets

Stocks

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

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

SettingTypeDefaultVariable
Column Width (%)float5col_width
Screen #int1scr_numb
Base Lengthint14baseLength
u01booltrueu01
u02booltrueu02
u03booltrueu03
u04booltrueu04
u05booltrueu05
s01symbolNVDAs01
s02symbolAAPLs02
s03symbolTSLAs03
s04symbolAMZNs04
Show all 13 settings
SettingTypeDefaultVariable
s05symbolGOOGLs05
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

This indicator implements a full Chanlun pipeline on the price chart. It merges contained bars, marks top and bottom fractals, and connects alternating fractals into strokes. Overlapping strokes form pivot boxes, and MACD area ratios flag trend or consolidatio

Indicator v6 Support & resistanceDivergence
Updated 2 months ago · GPL-3.0 GitHub repository of 缠论 - 分型与笔 [Chanlun Core]

This indicator plots calendar-spread context for commodity futures on the price chart. It maps the chart symbol to front and next month contracts automatically, or uses manual symbols, then calculates the spread as a difference or ratio. Fast and slow EMAs, a

Indicator v6 TrendOscillators & momentum
Updated yesterday · MIT GitHub repository of Vein: Spread Context [WavesUnchained]

This indicator projects a dual-asset momentum matrix visualizer directly onto the price chart overlay. It calculates normalized momentum for the chart symbol using either RSI or Stochastic inputs adjusted by ATR volatility, and compares it against a benchmark

Indicator v6 Oscillators & momentumVolatility & bands Repaints
Updated 3 months ago · None stated GitHub repository of Pro Grid Elite: Advanced Dual-Asset Momentum Matrix

This indicator scans a pasted list of symbols for RSI directional momentum and shows matching long and short signals in a table in a separate pane. The user chooses continuous break, continuous retracement, flip break, flip retracement, divergence, or hidden d

Indicator v6 Oscillators & momentumDivergence
Updated 1 year ago · MPL-2.0 GitHub repository of Momentum Setup - RSI Directional Momentum Scanner

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers