Trading Strategyv6

A fixed-range grid strategy in TradingView

A grid places orders at several price levels inside a chosen range. This tutorial builds a long-only arithmetic example: buy below the current price, then offer each filled leg one step higher. Repeated small exits can coexist with a large losing open position. The code is a backtest example, not an exchange bot or evidence of positive returns.

Define the inventory and exit rules first

For N interior buy levels, this example uses spacing = (upper − lower) / (N + 1). Buy level i is lower + i × spacing, for i = 1…N; its target is the next level. Prices are rounded to the chart’s minimum tick. The lower boundary is the common stop.

For example, lower 100, upper 140 and N = 3 give buys at 110, 120 and 130, with targets 120, 130 and 140. A buy is submitted only when it is below the current close. That matters: a limit buy above the market is marketable, not a resting order waiting for price to fall.

The grid adds inventory as price falls. Its capital check compares nominal level budgets with initial capital; it does not reserve cash for fees or guarantee sufficient equity after losses. Stops may fill beyond their price during gaps.

Order timing, pyramiding, currency conversion and broker-emulator limits are described in TradingView’s strategy documentation.

v6 Implementation

v6
//@version=6
strategy("Pineify Fixed-Range Long Grid Example", overlay=true, initial_capital=10000, currency=currency.USD, pyramiding=20, close_entries_rule="ANY", commission_type=strategy.commission.percent, commission_value=0.1, slippage=1, margin_long=100)

lowerInput = input.float(40000, "Lower boundary", minval=0.000001)
upperInput = input.float(60000, "Upper boundary", minval=0.000001)
gridCount = input.int(10, "Interior buy levels", minval=1, maxval=20)
cashPerGrid = input.float(500, "USD notional per level", minval=1)
lower = math.round_to_mintick(lowerInput)
upper = math.round_to_mintick(upperInput)
spacing = (upper - lower) / (gridCount + 1)

if barstate.isfirst
    if lower <= 0 or upper <= lower or spacing < 2 * syminfo.mintick
        runtime.error("Use positive ordered bounds with at least two ticks per step.")
    if gridCount * cashPerGrid > strategy.initial_capital
        runtime.error("Combined level budgets must not exceed initial capital.")

inside = close > lower and close < upper
if barstate.isconfirmed
    if not inside
        strategy.cancel_all()
        if strategy.position_size > 0
            strategy.close_all(comment="Outside range: market exit")
    else
        for i = 0 to gridCount - 1
            level = math.round_to_mintick(lower + (i + 1) * spacing)
            target = math.round_to_mintick(lower + (i + 2) * spacing)
            buyId = "Grid " + str.tostring(i + 1)
            bool isOpen = false
            if strategy.opentrades > 0
                for t = 0 to strategy.opentrades - 1
                    if strategy.opentrades.entry_id(t) == buyId
                        isOpen := true
            symbolCash = strategy.convert_to_symbol(cashPerGrid)
            rawQty = symbolCash / (level * syminfo.pointvalue)
            qty = math.floor(rawQty / syminfo.mincontract) * syminfo.mincontract
            canPlace = not isOpen and close > level and not na(qty) and qty > 0
            if canPlace
                strategy.entry(buyId, strategy.long, qty=qty, limit=level)
            else if not isOpen
                strategy.cancel(buyId)
            if isOpen or canPlace
                strategy.exit("Exit " + str.tostring(i + 1), from_entry=buyId, limit=target, stop=lower)

plot(lower, "Lower boundary / stop", color=color.red)
plot(upper, "Upper boundary", color=color.green)
var gridLines = array.new_line()
if barstate.islastconfirmedhistory or (barstate.isrealtime and barstate.isconfirmed)
    for gridLine in gridLines
        line.delete(gridLine)
    array.clear(gridLines)
    for i = 0 to gridCount - 1
        level = math.round_to_mintick(lower + (i + 1) * spacing)
        array.push(gridLines, line.new(math.max(0, bar_index - 100), level, bar_index, level, color=color.new(color.gray, 60), style=line.style_dashed))

What the example actually does

  1. 1

    Each level has its own entry ID and bracket. close_entries_rule="ANY" lets the emulator associate the exit with the named entry; up to 20 long entries are allowed. An open level cannot add another leg under that ID.

  2. 2

    Cash per level is in the USD strategy account currency. strategy.convert_to_symbol converts it to chart currency, then level × point value converts that notional to contracts or units. Quantity rounds down to syminfo.mincontract; a budget too small for one unit produces no order.

  3. 3

    Orders are evaluated at confirmed bar closes. Inside the range, eligible limit buys rest below the close. Outside the range, all pending orders are cancelled and remaining inventory receives a market-close instruction, normally filled on the next available tick. This is not a guaranteed boundary-price exit.

  4. 4

    The example uses fixed bounds, not a trailing or geometric grid. Default bounds are illustrative and must be changed for the selected symbol. It does not send exchange orders or manage a live bot.

Backtest Assumptions and Metrics

No reproducible performance dataset accompanies this example. The table lists code assumptions, not measured returns. To reproduce a test, record symbol and venue, chart type, timeframe, date range, session, inputs and all Strategy Properties.

MetricValueInterpretation
Starting capitalUSD 10,000Strategy account setting; not a suggested deposit.
Level budgets10 × USD 500Nominal USD 5,000 before fees; rounded contract sizes may use less.
Commission0.1% per fillIllustrative entry and exit charge; replace with the applicable fee model.
Slippage1 tickEmulator setting for applicable orders; not a complete spread or limit-fill model.
PerformanceNot establishedInspect realized profit, open inventory and drawdown together.

Use standard-price candles. Inspect individual entry IDs, quantities and exits in the Strategy Tester, especially bars that touch several levels or cross the lower boundary. Compare the default emulator with Bar Magnifier where available. Lower-timeframe data does not establish queue priority, liquidity, funding costs or executable live fills. Fix rules before evaluating a separate period; choosing bounds from the completed test range introduces hindsight.

Review the rules and exported trades

Pineify Backtest Deep Report imports a TradingView trade-list CSV for additional trade summaries. Check that prices, quantities, currency and fees match the Strategy Tester export. Closed-trade summaries cannot reconstruct missing intrabar exposure or establish live execution quality.

The AI Coding Agent can help draft changes. Compile the resulting script and inspect its orders in TradingView before treating a change as correct.

Strategy Optimization Suggestions

1

Check order costs against spacing

Compare a completed leg’s gross price difference with both fees and realistic execution costs. Narrower spacing is not automatically better.

2

Test a range break

Include persistent declines and gaps. Record maximum open inventory and account equity, not only the proportion of profitable closed legs.

3

Keep the evaluation period separate

Choose bounds and level count using only information available before evaluation. Report all tried settings rather than only the best historical result.

Frequently Asked Questions

No. Pine strategies simulate orders in TradingView. Live routing would require a separately configured and tested execution system; this example does not provide one.

The close must be inside the range and above that level, no trade under that level ID may already be open, and the rounded quantity must be positive. A small budget can round to zero contracts.

At a confirmed close outside the range, pending orders are cancelled and remaining inventory receives a market-close instruction. Orders can already have filled within that bar, and the market close normally fills on the next tick. A gap can exceed the intended loss.

No such compatibility is established. Check point value, account-currency conversion, minimum contract size, margin, sessions and costs for the exact chart and instrument. The script is a simplified positive-price, long-only example.

Check a specific rule change

Keep the original settings, change one rule, and compare the orders and costs on a separate test period. A code draft or trade report does not establish profitability.

Disclaimer: Trading involves significant risk. The strategies and code provided are for educational purposes only and do not constitute financial advice. Past performance is not indicative of future results.