Strategy · Pine Script v5 · On the chart

Pinbar Strategy

by Web3Degenerate

Pinbar Strategy identifies pinbar candlestick patterns (hammers and shooting stars) via the imported ZenLibrary and trades reversals or continuations on confirmed bars.

View on GitHub

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code150
Settings11inputs
LicenceNone statedfile: MPL-2.0
Last update2 years ago13 Sep 2024

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

150 lines of Pine Script v5 from advanced-pine-script/9.Strategy-Scripts/9B.Displaying-Backtest-Results-Pinbar-Strategy.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

9B.Displaying-Backtest-Results-Pinbar-Strategy.pine
/// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

// Last Updated: 2nd February 2022
// @version=5
strategy("Pinbar Strategy", shorttitle="PBS", overlay=true)

// Import Zen library
import ZenAndTheArtOfTrading/ZenLibrary/3 as zen

// Strategy Settings
var g_strategy      = "Strategy Settings"
stopMultiplier      = input.float(title="Stop Loss ATR", defval=1.0, group=g_strategy, tooltip="Stop loss multiplier (x ATR)")
rr                  = input.float(title="R:R", defval=1.0, group=g_strategy, tooltip="Risk:Reward profile")
fibLevel            = input.float(title="Fib Level", defval=0.333, group=g_strategy, tooltip="Used to calculate upper/lower third of candle. (For example, setting it to 0.5 will mean hammers must close >= 50% mark of the total candle size)")
// Filter Settings
var g_filter        = "Filter Settings"
atrMinFilterSize    = input.float(title=">= ATR Filter", defval=0.0, minval=0.0, group=g_filter, tooltip="Minimum size of entry candle compared to ATR")
atrMaxFilterSize    = input.float(title="<= ATR Filter", defval=3.0, minval=0.0, group=g_filter, tooltip="Maximum size of entry candle compared to ATR")
emaFilter           = input.int(title="EMA Filter", defval=0, group=g_filter, tooltip="EMA length to filter trades - set to zero to disable")
i_startTime         = input.time(title="Start Date Filter", defval=timestamp("01 Jan 2000 13:30 +0000"), group=g_filter, tooltip="Date & time to begin trading from")
i_endTime           = input.time(title="End Date Filter", defval=timestamp("1 Jan 2099 19:30 +0000"), group=g_filter, tooltip="Date & time to stop trading")
// Backtester Settings
var g_tester        = "Backtester Settings"
startBalance        = input.float(title="Starting Balance", defval=10000.0, group=g_tester, tooltip="Your starting balance for the inbuilt tester system")
riskPerTrade        = input.float(title="Risk Per Trade", defval=1.0, group=g_tester, tooltip="Your desired % risk per trade (as a whole number)")
drawTester          = input.bool(title="Draw Backtester", defval=true, group=g_tester, tooltip="Turn on/off inbuilt backtester display")

// See if this bar's time happened within date filter
dateFilter = time >= i_startTime and time <= i_endTime

// Get indicator values
atr = ta.atr(14)
ema = ta.ema(close, emaFilter == 0 ? 1 : emaFilter)

// Check EMA Filter
emaFilterLong = emaFilter == 0 or close > ema
emaFilterShort = emaFilter == 0 or close < ema

// Check ATR filter
atrMinFilter = high - low >= (atrMinFilterSize * atr) or atrMinFilterSize == 0.0
atrMaxFilter = high - low <= (atrMaxFilterSize * atr) or atrMaxFilterSize == 0.0
atrFilter = atrMinFilter and atrMaxFilter and not na(atr)

// Determine if we have a valid setup
validHammer = zen.isHammer(fibLevel) and atrFilter and emaFilterLong and dateFilter and close != open
validStar   = zen.isStar(fibLevel) and atrFilter and emaFilterShort and dateFilter and close != open

// Check if we have confirmation of our setup
validLong = validHammer and strategy.position_size == 0 and barstate.isconfirmed
validShort = validStar and strategy.position_size == 0 and barstate.isconfirmed

// Calculate our stops & targets for the current bar
stopSize = atr * stopMultiplier
longStopPrice = low < low[1] ? low - stopSize : low[1] - stopSize
longStopDistance = close - longStopPrice
longTargetPrice = close + (longStopDistance * rr)
shortStopPrice = high > high[1] ? high + stopSize : high[1] + stopSize
shortStopDistance = shortStopPrice - close
shortTargetPrice = close - (shortStopDistance * rr)

// Save trade stop & target if a valid setup is detected
var t_entry = 0.0
var t_stop = 0.0
var t_target = 0.0
var label lastTradeLabel = na
var stringFormat = syminfo.currency == "JPY" ? "0.000" : "0.00000"

// Detect valid long setups & trigger alert
if validLong
    t_entry := close
    t_stop := longStopPrice
    t_target := longTargetPrice
    positionSize = math.floor((strategy.equity * (riskPerTrade/100)) / math.abs(close - t_stop))
    lastTradeLabel := label.new(bar_index, t_target + (atr/2), text="EP = " + str.tostring(t_entry, stringFormat) + "\nTP = " + str.tostring(t_target, stringFormat) + "\nSL = " + str.tostring(t_stop, stringFormat), color=color.green, size=size.large)
    label.delete(lastTradeLabel[1])
    strategy.entry(id="Long", direction=strategy.long, qty=positionSize, comment="(SL=" + str.tostring(zen.truncate(zen.toWhole(longStopDistance))) + " pips)")

// Detect valid short setups & trigger alert
if validShort
    t_entry := close
    t_stop := shortStopPrice
    t_target := shortTargetPrice
    positionSize = math.floor((strategy.equity * (riskPerTrade/100)) / math.abs(close - t_stop))
    lastTradeLabel := label.new(bar_index, t_stop + (atr/2), text="EP = " + str.tostring(t_entry, stringFormat) + "\nTP = " + str.tostring(t_target, stringFormat) + "\nSL = " + str.tostring(t_stop, stringFormat), color=color.red, size=size.large)
    label.delete(lastTradeLabel[1])
    strategy.entry(id="Short", direction=strategy.short, qty=positionSize, comment="(SL=" + str.tostring(zen.truncate(zen.toWhole(shortStopDistance))) + " pips)")

// Exit trades whenever our stop or target is hit
strategy.exit(id="Long Exit", from_entry="Long", limit=t_target, stop=t_stop, when=strategy.position_size > 0)
strategy.exit(id="Short Exit", from_entry="Short", limit=t_target, stop=t_stop, when=strategy.position_size < 0)

// Draw trade data
plot(strategy.position_size != 0 or validLong or validShort ? t_stop : na, title="Trade Stop Price", color=color.red, style=plot.style_linebr)
plot(strategy.position_size != 0 or validLong or validShort ? t_target : na, title="Trade Target Price", color=color.green, style=plot.style_linebr)

// Draw EMA if it's enabled
plot(emaFilter == 0 ? na : ema, color=emaFilterLong ? color.green : color.red, linewidth=2, title="EMA")

// Draw price action setup arrows
plotshape(validLong ? 1 : na, style=shape.triangleup, location=location.belowbar, color=color.green, title="Bullish Setup")
plotshape(validShort ? 1 : na, style=shape.triangledown, location=location.abovebar, color=color.red, title="Bearish Setup")

// =============================================================================
// START BACKTEST CODE
// =============================================================================
// Declare balance tracking variables (for backtester simulation)
var balance = startBalance
var drawdown = 0.0
var maxDrawdown = 0.0
var maxBalance = 0.0
var totalPips = 0.0

// Increase profit for wins
if strategy.wintrades != strategy.wintrades[1]
    balance += riskPerTrade / 100 * balance * rr
    totalPips += zen.toWhole(math.abs(t_entry - t_target))
    if balance > maxBalance
        maxBalance := balance

// Decrease profit for losses
if strategy.losstrades != strategy.losstrades[1]
    balance -= riskPerTrade / 100 * balance
    totalPips -= zen.toWhole(math.abs(t_stop - t_entry))
    // Update drawdown
    drawdown := balance / maxBalance - 1
    if drawdown < maxDrawdown
        maxDrawdown := drawdown

// Prepare stats table
var table testTable = table.new(position.top_right, 5, 2, border_width=1)
f_fillCell(_table, _column, _row, _title, _value, _bgcolor, _txtcolor) =>
    _cellText = _title + "\n" + _value
    table.cell(_table, _column, _row, _cellText, bgcolor=_bgcolor, text_color=_txtcolor)

// Draw stats table
var bgcolor = color.black
if barstate.islastconfirmedhistory
    if drawTester
        dollarReturn = balance - startBalance
        f_fillCell(testTable, 0, 0, "Total Trades:", str.tostring(strategy.closedtrades), bgcolor, color.white)
        f_fillCell(testTable, 0, 1, "Win Rate:", str.tostring(zen.truncate(strategy.wintrades / strategy.closedtrades * 100)) + "%", bgcolor, color.white)
        f_fillCell(testTable, 1, 0, "Starting:", "$" + str.tostring(startBalance), bgcolor, color.white)
        f_fillCell(testTable, 1, 1, "Ending:", "$" + str.tostring(zen.truncate(balance)), bgcolor, color.white)
        f_fillCell(testTable, 2, 0, "Return:", "$" + str.tostring(zen.truncate(dollarReturn)), bgcolor, dollarReturn > 0 ? color.green : color.red)
        f_fillCell(testTable, 2, 1, "Pips:", (totalPips > 0 ? "+" : "") + str.tostring(zen.truncate(totalPips)), bgcolor, color.white)
        f_fillCell(testTable, 3, 0, "Return:", (dollarReturn > 0 ? "+" : "") + str.tostring(zen.truncate(dollarReturn / startBalance * 100)) + "%", dollarReturn > 0 ? color.green : color.red, color.white)
        f_fillCell(testTable, 3, 1, "Max DD:", str.tostring(zen.truncate(maxDrawdown * 100)) + "%", color.red, color.white)
// =============================================================================
// END BACKTEST CODE
// =============================================================================

Overview

Entries are filtered by an optional exponential moving average and candle range thresholds relative to the Average True Range. Stop losses are anchored to recent swing extremes offset by an ATR multiplier, while profit targets scale via a user-defined risk-to-reward ratio. The strategy draws trade levels and an optional backtest performance table on the main price chart.

Details

Published by

Web3Degenerate on GitHub

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

Candlestick patterns, Trend, Screeners & dashboards

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
Stop Loss ATRfloat1.0stopMultiplier
R:Rfloat1.0rr
Fib Levelfloat0.333fibLevel
>= ATR Filterfloat0.0atrMinFilterSize
<= ATR Filterfloat3.0atrMaxFilterSize
EMA Filterint0emaFilter
Start Date Filtertimetimestamp("01 Jan 2000 13:30 +0000")i_startTime
End Date Filtertimetimestamp("1 Jan 2099 19:30 +0000")i_endTime
Starting Balancefloat10000.0startBalance
Risk Per Tradefloat1.0riskPerTrade
Draw BacktesterbooltruedrawTester
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

Pin Bar Magic v1

by Alorse
330 stars

This strategy trades price action pin bar patterns aligned with moving average trend alignment on the main price chart. It defines uptrends or downtrends using a fan arrangement of three moving averages (6 EMA, 18 EMA, and 50 SMA). Entry conditions require a b

Strategy v4 Candlestick patternsTrend
Updated 2 months ago · None stated GitHub repository of Pin Bar Magic v1
285 stars

Mean Reversion Strategy is an overlay strategy that identifies pullbacks using a long-term EMA, RSI, and candlestick patterns. It generates long signals when a bullish engulfing candle forms below the EMA while RSI is oversold, and short signals when a bearish

Strategy v4 Mean reversionCandlestick patterns
Updated 3 years ago · None stated GitHub repository of Mean Reversion Strategy

ESU2023-10M - V1

by dearvn
257 stars

ESU2023-10M - V1 is an intraday trend-reversal strategy designed for index futures contracts on the price chart. It calculates a 3-period moving average of candle highs and lows alongside specific three-bar price action patterns to detect short-term swing high

Strategy v5 TrendCandlestick patterns
Updated 6 weeks ago · None stated GitHub repository of ESU2023-10M - V1
106 stars

This strategy trades the three-candle strike pattern filtered by trend direction and time sessions. It calculates market regime using linear regression and exponential or smoothed moving averages to distinguish between ranging and trending conditions. Risk man

Strategy v5 Candlestick patternsTrend
Updated 2 years ago · GPL-3.0 GitHub repository of 3 Candle Strike Strategy

Consecutive Up/Down Strategy

by TWODS-CAPITAL
37 stars

This strategy tracks consecutive bullish and bearish candlestick closes relative to the preceding bar. It enters a long position when price closes higher for a specified number of consecutive bars, and enters a short position when price closes lower for a desi

Strategy v5 Candlestick patternsTrend
Updated 3 years ago · MIT GitHub repository of Consecutive Up/Down Strategy

DI Engulfing A002

by ruckard
13 stars

This strategy executes trades based on candlestick engulfing patterns aligned with a 200-period exponential moving average trend filter. It enters long positions when a bullish engulfing candle follows three consecutive bearish candles while price trades above

Strategy v5 Candlestick patternsTrend
Updated 1 year ago · None stated GitHub repository of DI Engulfing A002

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