Strategy · Pine Script v5 · On the chart

Box Scalper

by wynnforthework· code credited to Uncle-Gua 油管:布欧的区块日记

This strategy draws on the price chart and combines a momentum zigzag, a custom QQE built from RSI, ADX directional strength, an SSL filter, and a coefficient-of-variation weighted average.

View on GitHub

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code330
Settings22inputs
LicenceNone statedfile: MPL-2.0
Last update1 year ago7 Oct 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 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

330 lines of Pine Script v5 from 策略/开源分享/Box Scalper 魔改自瓜叔.txt, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

Box Scalper 魔改自瓜叔.txt
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Uncle-Gua 油管:布欧的区块日记

//@version=5
strategy(title='Box Scalper 魔改自瓜叔', overlay=true, initial_capital=1000, default_qty_type=strategy.cash, default_qty_value=1000, commission_type=strategy.commission.percent, commission_value=0.05,use_bar_magnifier=false)

start           = input.time(timestamp('2020-01-01T00:00:00'), group='Back Test', title='Start')
finish          = input.time(timestamp('2030-12-31T00:00:00'), group='Back Test', title='Finish')
window          = time >= start and time <= finish ? true : false


// *****************************************************************************
// *                                    Functions                              *
// *                                   Box Scalper                             *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
fn_zigzag(_momentum_direction) =>
    zz_goingup = _momentum_direction == 1
    zz_goingdown = _momentum_direction == -1
    zz_peak = float(na)
    zz_bottom = float(na)
    zz_peak := high > zz_peak[1] and zz_goingup or zz_goingdown[1] ? high : nz(zz_peak[1])
    zz_bottom := low < zz_bottom[1] and zz_goingdown or zz_goingup[1] ? low : nz(zz_bottom[1])
    zigzag = zz_goingup and zz_goingdown[1] ? zz_bottom[1] : zz_goingup[1] and zz_goingdown ? zz_peak[1] : na
    zigzag

fn_rsi(src, len, mtf)=>
    change = src - src[mtf]

    up = math.max(change, 0)
    dn =-math.min(change, 0)

    up_change = ta.rma(up, (len * mtf))
    dn_change = ta.rma(dn, (len * mtf))
    
    rsi = dn_change == 0 ? 100 : up_change == 0 ? 0 : 100 - (100 / (1 + up_change / dn_change))

// 14, 5, 8, 4.3
fn_qqe(len, mtf, smooth, mult)=>
    wilders =  len * 2 - 1 

    up = 0.0
    up_rsi = fn_rsi(low, len, mtf)
    up_ema = ta.ema(up_rsi, smooth)
    up_atr = math.abs(up_ema[1] - up_ema)
    up_diff = ta.ema(ta.ema(up_atr, wilders), wilders) * mult
    up_ma = up_ema - up_diff
    up := up_ema[1] > up[1] and up_ema > up[1] ? math.max(up_ma, up[1]) : up_ma

    dn = 0.0
    dn_rsi = fn_rsi(high, len, mtf)
    dn_ema = ta.ema(dn_rsi, smooth)
    dn_atr = math.abs(dn_ema[1] - dn_ema)
    dn_diff = ta.ema(ta.ema(dn_atr, wilders), wilders) * mult
    dn_ma = dn_ema + dn_diff
    dn := dn_ema[1] < dn[1] and dn_ema < dn[1] ? math.min(dn_ma, dn[1]) : dn_ma
    
    qqe_up = dn_ema > dn[1] and dn_ema[1] <= dn[2] //ta.crossover(dn_ema, dn[1])
    qqe_dn = up_ema < up[1] and up_ema[1] >= up[2] //ta.crossunder(up_ema, up[1])
    [qqe_up, qqe_dn]

fn_adx(len, smooth) =>
    up      =  ta.change(high)
    dn      = -ta.change(low)
    pdm     = na(up) ? na : up > dn and up > 0 ? up : 0
    mdm     = na(dn) ? na : dn > up and dn > 0 ? dn : 0
    atr     = ta.atr(len)
    plus    = fixnan(100 * ta.rma(pdm, len) / atr)
    minus   = fixnan(100 * ta.rma(mdm, len) / atr)
    sum     = plus + minus
    adx     = 100 * ta.rma(math.abs(plus - minus) / (sum == 0 ? 1 : sum), smooth)
    [plus, minus, adx]

fn_covwma(a, b) =>
    cov    = ta.stdev(a, b)/ta.sma(a, b)
    cw     = a*cov
    covwma = math.sum(cw, b)/math.sum(cov, b)

fn_ssl(length) =>
    hh = ta.hma(high, length)
    ll = ta.hma(low, length)

    hlv = int(na)
    hlv := close > hh ? 1 : close < ll ? -1 : hlv[1]
    ssl = hlv < 0 ? hh : ll


// *****************************************************************************
// *                                      ADX                                  *
// *                                   Box Scalper                             *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
ADX_Group       = 'ADX'
ADX_Length      = input.int(14,             title='Length',             group=ADX_Group,    minval=1,       step=1)
ADX_Smooth      = input.int(14,             title='Smooth',             group=ADX_Group,    minval=1,       step=1)
ADX_Range       = input.float(25,           title='Range',              group=ADX_Group,    minval=1,       step=1)
ADX_Trend       = input.float(50,           title='Trend',              group=ADX_Group,    minval=1,       step=1)

[ADX_plus, ADX_minus, ADX] = fn_adx(ADX_Length, ADX_Smooth)


// *****************************************************************************
// *                                      SSL                                  *
// *                                   Box Scalper                             *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
SSL_Group       = 'SSL'
SSL_Length      = input.int(55,             title='Length',             group=SSL_Group,    minval=1,       step=10)

SSL = fn_ssl(SSL_Length)

SSL_color = close > SSL ? #00c3ff : close < SSL ? #ff0062 : na
plot(SSL, title='SSL', linewidth=3, color=SSL_color)


// *****************************************************************************
// *                                   Squeeze Box                             *
// *                                   Box Scalper                             *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
BOX_Group       = 'Squeeze Box'
BOX_Period      = input.int(24,             title='Periods',            group=BOX_Group,    minval=1,       step=1)
BOX_Deviation   = input.int(3,              title='Deviation',          group=BOX_Group,    minval=1,       step=1)
BOX_Threshold   = input.int(50,             title='Threshold',          group=BOX_Group,    minval=1,       step=1)

BOX_src = hlc3
BOX_ma = fn_covwma(BOX_src, BOX_Period)
BOX_bu = BOX_ma + ta.stdev(BOX_src, BOX_Period)*BOX_Deviation
BOX_bd = BOX_ma - ta.stdev(BOX_src, BOX_Period)*BOX_Deviation

//Bandwidth
BOX_bw = (BOX_bu - BOX_bd)

//Squeeze Percentage
BOX_buh = ta.highest(BOX_bu, BOX_Period)
BOX_bdl = ta.lowest(BOX_bd, BOX_Period)
BOX_rng = BOX_buh - BOX_bdl
BOX_sqp = 100*BOX_bw/BOX_rng

//Squeeze Box
BOX_sqz  = (BOX_sqp < BOX_Threshold) ? 1 : 0
BOX_hh   = ta.highest(BOX_src, BOX_Period)
BOX_boxh = BOX_sqz ? BOX_hh : BOX_src
BOX_ll   = ta.lowest(BOX_src, BOX_Period)
BOX_boxl = BOX_sqz ? BOX_ll : BOX_src
BOX_bh   = ta.valuewhen(BOX_sqz, BOX_boxh, 1)
BOX_bl   = ta.valuewhen(BOX_sqz, BOX_boxl, 1)

//Colors
boxcolor = BOX_src > BOX_bh ? color.lime : BOX_src < BOX_bl ? color.red : color.orange
bhcolor  = BOX_sqz ? boxcolor : na
blcolor  = BOX_sqz ? boxcolor : na

bhplot = plot(BOX_bh, color=color.new(boxcolor, 50), title="Box High Level")
blplot = plot(BOX_bl, color=color.new(boxcolor, 50), title="Box Low Level")
fill(bhplot, blplot, color=color.new(boxcolor, 87), title="Box Fill")


// *****************************************************************************
// *                                      QQE                                  *
// *                                   Box Scalper                             *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
QQE_Group       = 'QQE'
QQE_Length      = input.int(14,             title='RSI Length',         group=QQE_Group,    minval=1,       step=1)
QQE_Mtf         = input.int(5,              title='MTF Mult',           group=QQE_Group,    minval=1,       step=1)
QQE_Smooth      = input.int(8,              title='RSI Smooth',         group=QQE_Group,    minval=1,       step=1)
QQE_Mult        = input.float(4.3,          title='QQE Mult',           group=QQE_Group,    minval=1,       step=0.1)

[QQE_up, QQE_dn] = fn_qqe(QQE_Length, QQE_Mtf, QQE_Smooth, QQE_Mult)

QQE_direction = 0
QQE_direction := QQE_up ? 1 : QQE_dn ? -1 : nz(QQE_direction[1])


// *****************************************************************************
// *                                    QQE ZONE                               *
// *                                   Box Scalper                             *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
ZON_Group       = 'QQE ZONE'
ZON_Length      = input.int(5,              title='Length',             group=ZON_Group,    minval=1,       step=1)
ZON_Upper       = input.float(75,           title='Upper',              group=ZON_Group,    minval=50,      maxval=100,     step=1)
ZON_Lower       = input.float(22,           title='Lower',              group=ZON_Group,    minval=0,       maxval=50,      step=1)

qqe_rsi = ta.rsi(close, ZON_Length)
barssince_qqe_up = ta.barssince(QQE_up)
barssince_qqe_dn = ta.barssince(QQE_dn)
barssince_rsi_up = ta.barssince(qqe_rsi > ZON_Upper)
barssince_rsi_dn = ta.barssince(qqe_rsi < ZON_Lower)
qqe_was_force_up = QQE_dn and barssince_qqe_up[1] >= barssince_rsi_up[1]
qqe_was_force_dn = QQE_up and barssince_qqe_dn[1] >= barssince_rsi_dn[1]
zzcolor = qqe_was_force_up ? color.lime : qqe_was_force_dn ? color.red : color.black

ZigZag = fn_zigzag(QQE_direction)
plot(ZigZag, linewidth=2, color=zzcolor, title='ZigZag', style=plot.style_line)


// *****************************************************************************
// *                                       Box                                 *
// *                                   Box Scalper                             *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
var float zz_top = high
var float zz_bot = low

pl = ta.valuewhen(QQE_up, ZigZag, 0)
ph = ta.valuewhen(QQE_dn, ZigZag, 0)
if QQE_dn
    zz_top := nz(high > ph ? high : ph, zz_top[1])
if QQE_up
    zz_bot := nz(low < pl ? low : pl, zz_bot[1])

plot(zz_top, color=color.aqua, style=plot.style_cross, title='Resistance')
plot(zz_bot, color=color.yellow, style=plot.style_cross, title='Support')


// *****************************************************************************
// *                                Position Setting                           *
// *                                  Box Scalper                              *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
PS_Group        = 'POSITION'
PS_Expect       = input.string('BOTH',      title='Expect',             group=PS_Group,     options=['BOTH','LONG', 'SHORT'])
PS_Mode         = input.string('Capital',   title='Mode',               group=PS_Group,     options=['Capital', 'Equity'])
PS_Initial      = input.int(100,            title='Initial(%)',         group=PS_Group,     minval=1,       maxval=100)


// *****************************************************************************
// *                                  Stop Loss                                *
// *                                Super Scalper                              *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
TSL_Group       = 'Stop Loss'
TSL_SL2         = input.float(9.9,          title='Stop Loss Max(%)',   group=TSL_Group,    minval=0,       step=0.1)


// *****************************************************************************
// *                                  Take Profit                              *
// *                                  Box Scalper                              *
// *                              @Author : Uncle-Gua                          *
// *                                                                           *
// *****************************************************************************
// -------------|---------------------------|---------------------------|-------------------|---------------|
TP_Group        = 'Take Profit'
TP_Ts2          = input.float(1.0,          title='Profit Target 2(%)', group=TP_Group,     minval=0,       step=0.1)

PIP_ts2         = close * TP_Ts2 / syminfo.mintick / 100

TICKER = syminfo.prefix + ':' + syminfo.ticker


week = dayofweek
BULL = (close > SSL and QQE_up and not qqe_was_force_dn and (week != 7 and week != 1 or ADX > ADX_Trend)) or (close > SSL and ta.crossover(close, BOX_bl))
BEAR = (close < SSL and QQE_dn and not qqe_was_force_up and (week != 7 and week != 1 or ADX > ADX_Trend)) or (close < SSL and ta.crossunder(close, BOX_bh))

sign = strategy.position_size > 0 ? 1 : strategy.position_size < 0 ? -1 : na
ROE = sign * (close - strategy.position_avg_price) / strategy.position_avg_price * 100

if strategy.position_size > 0 and PS_Expect == 'LONG' and BEAR
    SIZE = str.tostring(math.abs(strategy.position_size))
    cl_msg = '{"symbol":"'+TICKER+'","action":"CLOSE","side":"LONG","size":' + SIZE + ',"comment":"CL-L"}'
    strategy.close('LONG', comment='CL-L', alert_message=cl_msg)

if strategy.position_size < 0 and PS_Expect == 'SHORT' and BULL
    SIZE = str.tostring(math.abs(strategy.position_size))
    cl_msg = '{"symbol":"'+TICKER+'","action":"CLOSE","side":"SHORT","size":' + SIZE + ',"comment":"CL-S"}'
    strategy.close('SHORT', comment='CL-S', alert_message=cl_msg)


pivotsizing = 20 //length
pivotLookup = 1
L_TP = strategy.position_avg_price * (1 + TP_Ts2/100)
hih     = ta.pivothigh(high, pivotLookup, pivotLookup)
top     = ta.valuewhen(hih, high[pivotLookup], 0)
float highest = ta.highest(top,pivotsizing)
moveHigh = ta.crossunder(close,highest*0.99)
L_reversal = ta.crossunder(close,L_TP)

S_TP = strategy.position_avg_price * (1 - TP_Ts2/100)
bot     = ta.pivotlow(low, pivotLookup, pivotLookup)
bottom     = ta.valuewhen(bot, low[pivotLookup], 0)
float bottomst = ta.lowest(bottom,pivotsizing)
moveBottom = ta.crossunder(close,bottomst*0.99)
S_reversal = ta.crossunder(close,S_TP)

if window and strategy.position_size <= 0 and PS_Expect != 'SHORT' and BULL
    size = (PS_Mode == 'Capital' ? strategy.initial_capital : strategy.equity) / close * (PS_Initial / 100)
    SIZE = str.tostring(size)
    op_msg = '{"symbol":"'+TICKER+'","action":"OPEN","side":"LONG","size":' + SIZE + ',"comment":"OP-L@' + str.tostring(close, format.mintick) + '"}'
    strategy.entry('LONG', strategy.long, qty=size, comment='OP-L@' + str.tostring(close, format.mintick), alert_message=op_msg)
    redline2 = close * (100 - TSL_SL2) / 100
    strategy.exit('CL-L', 'LONG', comment_profit='TP-L', comment_loss='SL-L', comment_trailing='TR-L', stop=redline2)

if close > L_TP and moveHigh and strategy.position_size > 0
    strategy.close_all(comment = "多头趋势止盈")
else if close > L_TP and L_reversal and strategy.position_size > 0
    strategy.close_all(comment = "多头趋势不明显保护性止盈")
    
if window and strategy.position_size >= 0 and PS_Expect != 'LONG' and BEAR
    size = (PS_Mode == 'Capital' ? strategy.initial_capital : strategy.equity) / close * (PS_Initial / 100)
    SIZE = str.tostring(size)
    op_msg = '{"symbol":"'+TICKER+'","action":"OPEN","side":"SHORT","size":' + SIZE + ',"comment":"OP-S@' + str.tostring(close, format.mintick) + '"}'
    strategy.entry('SHORT', strategy.short, qty=size, comment='OP-S@' + str.tostring(close, format.mintick), alert_message=op_msg)
    redline2 = close * (100 + TSL_SL2) / 100
    strategy.exit('CL-S', 'SHORT', comment_profit='TP-S', comment_loss='SL-S', comment_trailing='TR-S', stop=redline2)


if close < S_TP and moveBottom and strategy.position_size < 0
    strategy.close_all(comment = "空头趋势止盈")
else if close < S_TP and S_reversal and strategy.position_size < 0
    strategy.close_all(comment = "空头趋势不明显保护性止盈")

Overview

Box period, deviation, and threshold inputs set the box filter, while zone bounds and QQE settings shape the conditions. A start and finish window limits the backtest. Position size uses a capital percentage, with inputs for a maximum stop-loss percent and a second profit target. The excerpt ends before the order rules, so the exact entry combinations are not fully shown.

Details

Published by

wynnforthework on GitHub

Code credit

Uncle-Gua 油管:布欧的区块日记, as written in the script's header

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

Oscillators & momentum, Trend, Volatility & bands, Scalping

Markets

Any symbol

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
Starttimetimestamp('2020-01-01T00:00:00')start
Finishtimetimestamp('2030-12-31T00:00:00')finish
Lengthint14ADX_Length
Smoothint14ADX_Smooth
Rangefloat25ADX_Range
Trendfloat50ADX_Trend
Lengthint55SSL_Length
Periodsint24BOX_Period
Deviationint3BOX_Deviation
Thresholdint50BOX_Threshold
RSI Lengthint14QQE_Length
MTF Multint5QQE_Mtf
Show all 22 settings
SettingTypeDefaultVariable
RSI Smoothint8QQE_Smooth
QQE Multfloat4.3QQE_Mult
Lengthint5ZON_Length
Upperfloat75ZON_Upper
Lowerfloat22ZON_Lower
ExpectstringBOTHPS_Expect
ModestringCapitalPS_Mode
Initial(%)int100PS_Initial
Stop Loss Max(%)float9.9TSL_SL2
Profit Target 2(%)float1.0TP_Ts2
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

27 stars

LuxAlgo Hybrid Gold Scalper is a price-chart strategy aimed at gold. It stacks a fast, slow, trend and 200-period bias EMA to mark trend direction, then filters strength with RSI, ADX and an intraday VWAP. Swing highs and lows are marked from pivot length. Set

Strategy v5 TrendOscillators & momentum
Updated 5 months ago · None stated GitHub repository of LuxAlgo Hybrid Gold Scalper

This trend-following scalping strategy combines a moving average trend filter with the Absolute Strength Histogram indicator. It opens long positions when price is above a selectable baseline moving average and the histogram signals bullish momentum, and short

Strategy v5 TrendOscillators & momentum
Updated 1 year ago · None stated GitHub repository of Ruckard TradingZone Absolute Strength Histogram ATR

Hari Sweep Scalper

by godlesscherry
2 stars

This overlay strategy looks for Bollinger Band and optional fractal sweeps only in the Supertrend direction, with an optional MACD filter. Long and short setups expire after a set number of bars, and the first bar after a Supertrend flip is ignored. It enters

Strategy v6 TrendVolatility & bands
Updated 7 months ago · None stated GitHub repository of Hari Sweep Scalper
106 stars

This trading strategy combines three Exponential Moving Averages (8, 14, and 50 periods by default) with Stochastic RSI and Average True Range (ATR). It enters a long position when EMA 1 is above EMA 2, EMA 2 is above EMA 3, and the Stochastic RSI %K line cros

Strategy v4 TrendOscillators & momentum
Updated 2 years ago · GPL-3.0 GitHub repository of 3 x EMA + Stochastic RSI + ATR

More strategys

Trade Your Charts With a Regulated Broker

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

Compare brokers