Strategy · Pine Script v5 · On the chart

Grid Bot Simulator

by g-moe· code credited to goodgains

The Grid Bot Simulator strategy models automated grid trading directly on the price chart.

View on GitHub

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code182
Settings14inputs
LicenceNone statedfile: MPL-2.0
Last update5 months ago27 May 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

182 lines of Pine Script v5 from Tradingview/grid-bot-simulator.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

grid-bot-simulator.pine
//@version=5

//------------------------------------------------------------------------------------------------<>
//      This source code is subject to the terms of the Mozilla Public License 2.0 
// © goodgains

//      https://mozilla.org/MPL/2.0/ 
//      Updated 01/17/2022: Pinescript v5: 
//          Price Selectors--Converted color transparences to prevent deprecation warning
strategy('Grid Bot Simulator', shorttitle='GridBot', overlay=true)

// @keywords: grid-bot-simulator, price-grid, grid-lines, buy-signal, sell-signal, upper-limit, lower-limit, grid-interval, ema-trend-line, trend-ema, backtest-window, trade-zone-highlight, direction-filter, extreme-cross, grid-entry, grid-exit, signal-tracker, grid-boundary, interval-lines, long-short-entries

//-----<Inputs>-----------------------------------------------------------------------------------<> 
UpperLimit = input.price(49000.0, 'Upper Limit', confirm=false)
LowerLimit = input.price(43000.0, 'Lower Limit', confirm=false)
No_Grids = input(60, 'Number of Grids(10)') + 1
Dir = input.string('neutral', 'Market Direction', options=['up', 'neutral', 'down'])
SS = input.string('small', 'Signal Size', options=['small', 'large'])
ShowGrids = input(true, 'Show Grids')
HighLight = input(true, 'Highlight Trade Zones')
ShowCurrent = input(false, 'Show Only Current Grids')
Extremes = input(true, 'High/Low for signals')
//Dates
bt_start = input.time(timestamp("01 mar 2022  00:00 +0000"), title="Start Date", group="backtesting period")
bt_end = input.time(timestamp("31 dec 9999  00:00 +0000"), title="End Date", group="backtesting period")
backtestPeriod = input("day", "backtest period", tooltip="month = 30 days year = 365 days", group="backtesting period")
//if backtestPeriod == "day"
//    bt_start := timestamp(year(timenow), month(timenow), dayofmonth(timenow), 00, 00) - 86400000
//if backtestPeriod == "week"
 //   bt_start := timestamp(year(timenow), month(timenow), dayofmonth(timenow), 00, 00) - (86400000 * 7)
//if backtestPeriod == "month"
//    bt_start := timestamp(year(timenow), month(timenow), dayofmonth(timenow), 00, 00) - (86400000 * 30)
//if backtestPeriod == "year"
//    bt_start := timestamp(year(timenow), month(timenow), dayofmonth(timenow), 00, 00) - (86400000 * 365)
bt_window = time >= bt_start and time <= bt_end
//-----<Variables>--------------------------------------------------------------------------------<>
LastSignal = 0
LastSignal_Index = 0
LastSignal_Time = time
SignalLine = 0.0
CurrentGrid = 0.0
Buy = false
Sell = false
Direction = Dir == 'up' ? 1 : Dir == 'down' ? -1 : 0
//-----<Signal variables>-----------------------------------------------------------------------------------<>
length1 = input.int(5, minval=1)
ema1 = ta.ema(close, length1)
ema2 = ta.ema(ema1, length1)
ema3 = ta.ema(ema2, length1)
t1 = 3 * (ema1 - ema2) + ema3
plot(t1,"T1", color=#FFFFFF)

length = input.int(5, minval=1)
ema4 = ta.ema(t1, length)
ema5 = ta.ema(ema4, length)
ema6 = ta.ema(ema5, length)
t2 = 3 * (ema4 - ema5) + ema6
plot(t2, "T2", color=#2962FF)
//-----<RE-ENTRY>-----------------------------------------------------------------------------------<>
//call_reentry = crossover(t1,t2)





//-----<Colors>-----------------------------------------------------------------------------------<>
RedGrid = color.new(color.red, 50)
GreenGrid = color.new(color.green, 40)
Crimson = #DC143C
LimeGreen = #32CD32
//-----<Calculate Grids>--------------------------------------------------------------------------<>
GridRange = UpperLimit - LowerLimit
GridInterval = GridRange / (No_Grids - 1)
//-----<Grid Array>-------------------------------------------------------------------------------<>
a_grid = array.new_float(No_Grids)
for x = 0 to No_Grids - 1 by 1
    array.set(a_grid, x, LowerLimit + GridInterval * x)
//-----<Get Array Function>-----------------------------------------------------------------------<>
Get_Array_Values(ArrayName, index) =>
    value = array.get(ArrayName, index)
    value
//-----<Calculate Signals>------------------------------------------------------------------------<>
Get_BuyLine_Index() =>
    Index = 0
    BuyValue = 0.0
    for x = 0 to No_Grids - 1 by 1
        BuyValue := LowerLimit + GridInterval * x - 50
        if Extremes
            Index := high[1] > BuyValue and low <= BuyValue ? x : Index
            Index
        else
            Index := close[1] > BuyValue and close <= BuyValue ? x : Index
            Index
Get_SellLine_Index() =>
    Index = 0
    SellValue = 0.0
    for x = 0 to No_Grids - 1 by 1
        SellValue := LowerLimit + GridInterval * x + 50
        if Extremes
            Index := low[1] < SellValue and high >= SellValue ? x : Index
            Index
        else
            Index := close[1] < SellValue and close >= SellValue ? x : Index
            Index
BuyLine_Index = Get_BuyLine_Index()
SellLine_Index = Get_SellLine_Index()
//-----<Signals>----------------------------------------------------------------------------------<>
Buy := BuyLine_Index > 0 ? true : Buy
Sell := SellLine_Index > 0 ? true : Sell
//No repeat trades at current level                                                                                     
if Extremes
    Buy := low >= SignalLine[1] - GridInterval ? false : Buy
    Sell := high <= SignalLine[1] + GridInterval ? false : Sell
    Sell
else
    Buy := close >= SignalLine[1] - GridInterval ? false : Buy
    Sell := close <= SignalLine[1] + GridInterval ? false : Sell
    Sell
//No trades outside of grid limits
Buy := close >= UpperLimit ? false : Buy
Buy := close < LowerLimit ? false : Buy
Sell := close <= LowerLimit ? false : Sell
Sell := close > UpperLimit ? false : Sell
//Direction Filter (skip one signal if against market direction)
Buy := Direction == -1 and low >= SignalLine[1] - GridInterval * 2 ? false : Buy
Sell := Direction == 1 and high <= SignalLine[1] + GridInterval * 2 ? false : Sell
//-----<Trackers>---------------------------------------------------------------------------------<>
LastSignal := Buy ? 1 : Sell ? -1 : LastSignal[1]
LastSignal_Index := Buy ? BuyLine_Index : Sell ? SellLine_Index : LastSignal_Index[1]
LastSignal_Time := Buy or Sell ? time : LastSignal_Time[1]
SignalLine := LowerLimit + GridInterval * LastSignal_Index
//-----<Plot Grids>-------------------------------------------------------------------------------<>
for i = 1 to No_Grids - 1 by 1
    Array_Value = Get_Array_Values(a_grid, i)
    ClosestGrid = Array_Value - close
    color linecolor = ClosestGrid > 0 ? RedGrid : ClosestGrid < 0 ? GreenGrid : na
    linecolor := i == LastSignal_Index ? na : linecolor
    if ShowGrids
        if ShowCurrent
            LineAbove = line.new(x1=LastSignal_Time, y1=SignalLine + GridInterval, x2=time + 1000000, y2=SignalLine + GridInterval, color=color.red, width=1, extend=extend.left, xloc=xloc.bar_time)
            LineBelow = line.new(x1=LastSignal_Time, y1=SignalLine - GridInterval, x2=time + 1000000, y2=SignalLine - GridInterval, color=color.green, width=1, extend=extend.left, xloc=xloc.bar_time)
            LineBelow
        else
            color colCurrent = LastSignal == 1 ? color.new(color.green, 95) : color.new(color.red, 95)
            GridLines = line.new(x1=time, y1=Array_Value, x2=time[1], y2=Array_Value, color=linecolor, width=1, extend=extend.right, xloc=xloc.bar_time)
            //draw line before latest signal
            CurrentLine = line.new(x1=LastSignal_Time, y1=SignalLine, x2=LastSignal_Time - 100000, y2=SignalLine, color=colCurrent, width=1, extend=extend.right, xloc=xloc.bar_time)
            CurrentLine
UL = ShowGrids and not ShowCurrent
plot(UL ? UpperLimit : na, color=close >= UpperLimit ? color.green : color.red, linewidth=3)
plot(UL ? LowerLimit : na, color=close <= LowerLimit ? color.red : color.green, linewidth=3)
//Lines One Above & One Below
LineAbove = SignalLine == UpperLimit ? SignalLine : SignalLine + GridInterval
LineBelow = SignalLine == LowerLimit ? SignalLine : SignalLine - GridInterval
a = plot(LineAbove, color=color.new(color.red, 100), style=plot.style_circles)
b = plot(LineBelow, color=color.new(color.green, 100), style=plot.style_circles)
boxColor = LastSignal == -1 ? color.new(color.green, 90) : color.new(color.red, 90)
boxColor := HighLight ? boxColor : na
fill(a, b, color=color.new(boxColor, 90))
//-----<Plot Signals>-----------------------------------------------------------------------------<>
plotchar(Buy and SS == 'small', 'Buy', color=color.new(LimeGreen, 0), size=size.tiny, location=location.belowbar, char='▲')
plotchar(Sell and SS == 'small', 'Sell', color=color.new(Crimson, 0), size=size.tiny, location=location.abovebar, char='▼')
plotchar(Buy and SS == 'large', 'Buy', color=color.new(LimeGreen, 0), size=size.small, location=location.belowbar, char='▲')
plotchar(Sell and SS == 'large', 'Sell', color=color.new(Crimson, 0), size=size.small, location=location.abovebar, char='▼')
//-----<Entry Conditions>-----------------------------------------------------------------------------------<>
//Buy Conditions 







//-----<Strategy Long Entry>---------<>
if (Buy)
    strategy.entry("GbsLE", strategy.long, comment="GbsLETK")
//alertcondition(condition=Buy, title='buy', message='buy')
//   ----<Strategy Short Entry>---------<>
if (Sell)
    strategy.entry("GbsSE", strategy.short, comment="GbsSETK")
//alertcondition(condition=Sell, title='sell', message='sell')

Overview

Grid Bot Simulator divides a user-specified price channel between upper and lower bounds into equal grid intervals. Depending on the chosen market direction filter, the strategy executes buy and sell orders at grid levels to capture price oscillations. Main inputs include upper and lower price boundaries, grid count, direction filters, and date range parameters for backtesting. Designed for range-bound market simulation, the strategy operates without built-in stop losses by default.

Details

Published by

g-moe on GitHub

Code credit

goodgains, as written in the script's header

Draws

On the price chart

Markets

Crypto

Timeframes

Any timeframe

Risk Notes

  • The strategy enters trades without a stop loss

Settings

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

SettingTypeDefaultVariable
Upper Limitprice49000.0UpperLimit
Lower Limitprice43000.0LowerLimit
Number of Grids(10)int60No_Grids
Market DirectionstringneutralDir
Signal SizestringsmallSS
Show GridsbooltrueShowGrids
Highlight Trade ZonesbooltrueHighLight
Show Only Current GridsboolfalseShowCurrent
High/Low for signalsbooltrueExtremes
Start Datetimetimestamp("01 mar 2022 00:00 +0000")bt_start
End Datetimetimestamp("31 dec 9999 00:00 +0000")bt_end
backtest periodstringdaybacktestPeriod
Show all 14 settings
SettingTypeDefaultVariable
length1int5length1
lengthint5length
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

Omar Edited WF

by Alorse
330 stars

Omar Edited WF is a trading strategy overlay built around Williams Fractals and multiple Exponential Moving Averages. It detects high and low fractal pivot points over configurable lookback periods alongside three adjustable EMA trendlines. Long entries are ma

Strategy v5 TrendMoving averages
Updated 2 months ago · None stated GitHub repository of Omar Edited WF
257 stars

This strategy calculates dynamic support and resistance levels using pivot highs and lows alongside a custom smoothed trend filter and a 3-period EMA. It identifies entry opportunities when price breaks out relative to the trend filter and short-term EMA cross

Strategy v5 TrendSupport & resistance Repaints
Updated 7 weeks ago · None stated GitHub repository of 30s - ES 1m Strategy Candle Bar
106 stars

This strategy plots on the price chart and enters when three smoothed moving averages are aligned, RSI is on the matching side of 50, and a Williams fractal appears. An upward stack with RSI above 50 and a down fractal opens a long; the opposite setup opens a

Strategy v5 Moving averagesOscillators & momentum
Updated 2 years ago · GPL-3.0 GitHub repository of 3SmmaCrossUp + Fractal + RSI
104 stars

This strategy combines three Exponential Moving Averages with Williams Fractals to execute trend-following or mean-reverting trades. It analyzes price structure using short, medium, and long-term EMAs along with fractal highs and lows. Entries trigger when fra

Strategy v5 TrendMoving averages
Updated 3 years ago · MIT GitHub repository of 3MA and Fractals Strategy

This strategy executes trades based on pivot levels, an exponential moving average, and a multi-stage smoothing trend line. It identifies support and resistance points from pivot highs and lows, combining them with price relationship rules against a custom smo

Strategy v5 TrendMoving averages Repaints
Updated 2 years ago · None stated GitHub repository of Binancash - Candle Strategy Futures on Binance

KC15

by benso87
24 stars

KC15 is a price-chart strategy that configures two moving averages, a Bollinger Band Width Percentile filter, and PMARP entry and exit thresholds for long and short trades. Users can switch each average between SMA and EMA, set lengths and colors, and toggle l

Strategy v5 Moving averagesVolatility & bands
Updated 4 years ago · MPL-2.0 GitHub repository of KC15

More Support & resistance 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