Strategy · Pine Script v5 · On the chart

5min Williams Fractals Scalping (3commas)

by hasnocool

This strategy generates trading signals on the 5-minute price chart using Williams Fractals for trend reversals, combined with EMA fast and slow trend filters and optional RSI confirmation.

View on GitHub

GitHub stars106on the repository
Pine versionv5runs as is
Lines of code185
Settings34inputs
LicenceGPL-3.0
Last update2 years ago18 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

185 lines of Pine Script v5 from 5min Williams Fractals scalping (3commas).pine, published under GPL-3.0. Keep the author's credit and licence lines when you reuse it.

5min Williams Fractals scalping (3commas).pine
//@version=5
strategy("5min Williams Fractals scalping (3commas)", shorttitle="5min WF scalp", format=format.price, precision=0, overlay=true)
// Define "n" as the number of periods and keep a minimum value of 2 for error handling.
import ZenAndTheArtOfTrading/ZenLibrary/2 as l_zen
var g_strategy      = "Strategy"
i_chkLong           = input.bool(true, title = 'Long', inline = '1', group = g_strategy)
i_chkShort          = input.bool(true, title = 'Short', inline = '1', group = g_strategy)
i_startTime         = input.time(title = 'Start Date', defval = timestamp('01 Jan 2020 00:00 +0100'), group = g_strategy, tooltip = 'Date & time to begin trading from')
i_endTime           = input.time(title = 'End Date', defval = timestamp('1 Jan 2099 00:00 +0100'), group = g_strategy, tooltip = 'Date & time to stop trading')
i_longProfitPerc    = input.float(title ='Long Target Profit R:R', minval = 1.1, step = 0.1, defval = 1.5, inline ='2', group = g_strategy, tooltip = "Times the Stop Loss which is always the current Ema slow value")
i_shortProfitPerc   = input.float(title = 'Short Target Profit R:R', minval = 1.1, step = 0.1, defval = 1.5, inline = '3', group = g_strategy, tooltip = "Times the Stop Loss which is always the current Ema slow value")
i_tradeDontClose    = input.int(title = "Stop loss not sooner than", defval = 0, minval = 0, group = g_strategy, tooltip = "If an open trade hits the Stop loss sooner than the expected amount of bars have passed, then SL will not trigger (eg. for thight stop losses)")
var g_wf            = "Williams Fractals"
i_wf                = input.int(title="Periods", defval=2, minval=2, group = g_wf)
i_wfBarsBack        = input.bool(defval = true, title = "Evaluate WF bar", group = g_wf, tooltip = "By default it evaluates the bar for which the WF signal triggers so when turned off it evaluates the current bar")
var g_ema           = "EMA trend"
i_emaFast           = input.int(title = "Ema fast lenght", defval = 20, step = 1, group = g_ema)
i_emaSlow           = input.int(title = "Ema slow lenght", defval = 50, step = 1, group = g_ema)
i_emaGapUse         = input.bool(title = "Use Ema Gap", defval = false, group = g_ema, tooltip = "Gap between Emas must be greater than % of the whole security price,\neg. 0.1 = 0.1% of the security price which is the minimum gap tolerated for an entry")
i_emaGap            = input.float(title = "Ema Gap %", defval = 0.2, step = 0.05, group = g_ema)
var g_rsi           = "RSI filter"
i_rsiChk            = input.bool(false, "Use RSI Filter", group = g_rsi)
i_rsiRes            = input.timeframe("", "TimeFrame", group = g_rsi)
i_rsiLen            = input.int(14, "Lenght", group = g_rsi)
i_rsiMinLong        = input.float(0.0, "Min for Long", minval = 0.0, maxval = 100.0, step = 0.5, group = g_rsi, inline = "4")
i_rsiMaxLong        = input.float(70.0, "Max for Long", minval = 0.0, maxval = 100.0, step = 0.5, group = g_rsi, inline = "4")
i_rsiMinShort       = input.float(30.0, "Min for Short", minval = 0.0, maxval = 100.0, step = 0.5, group = g_rsi, inline = "5")
i_rsiMaxShort       = input.float(100.0, "Max for Short", minval = 0.0, maxval = 100.0, step = 0.5, group = g_rsi, inline = "5")
i_rsiDirectChk      = input.bool(false, "RSI direction confirmation", group = g_rsi, tooltip = "Long only if its supported by rising RSI and Short only if its supported by falling RSI\nWorks only if Use RSI is ON")
i_rsiDirectLen      = input.int(1, "Bars back for direction", minval = 1, group = g_rsi, tooltip = "Lookback period for RSI values")
var g_additional    = "Pullback filter"
i_usePullbackChk    = input.bool(false, title = 'Use Pullback', group = g_additional, tooltip = "Checks if the amount of oposite candles (bearish when long) in the lookback period (counts from second history candle)is smaller than the NOT bigger count and vice versa")
i_pullbackCount     = input.int(title="Lookback period", defval=2, minval = 1, group = g_additional)
i_pullbackNotBigger = input.int(title="NOT bigger than", defval=1, minval = 0, group = g_additional)
var g_tester        = 'Back tester table'
i_drawTester        = input.bool(title='Show back tester', defval=true, group=g_tester, tooltip='Turn on/off inbuilt backtester display', inline = "backtester1")
i_testerPosition    = input.string(title='', defval="Top right", options = ["Top right", "Top left", "Bottom right", "Bottom left"], group=g_tester, tooltip='Position of the backtester table', inline = "backtester1")
i_rr                = input.float(title='R:R', defval=1.0, group=g_tester, tooltip='Risk:Reward profile')
startBalance        = input.float(title='Starting Balance', defval=100.0, group=g_tester, tooltip='Your starting balance for the custom 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)')
var i_3Commas       = '3Commas bot settings'
i_useComments       = input.bool(false, "Show 3Commas bot comments", group = i_3Commas)
i_botIDLong         = input(title="Long Bot ID", defval="", group = i_3Commas)
i_botIDShort        = input(title="Short Bot ID", defval="", group = i_3Commas)
i_tokenID           = input(title="Email Token", defval="", group = i_3Commas)
// Get strategy direction and set time
strategy.risk.allow_entry_in(i_chkLong and i_chkShort ? strategy.direction.all : i_chkLong ? strategy.direction.long : strategy.direction.short)
c_dateFilter = time >= i_startTime and time <= i_endTime // See if this bar's time happened within date filter
// Get Ema trend and conditions
c_emaFast = ta.ema(close[barstate.isrealtime ? 1 : 0], i_emaFast)
c_emaSlow = ta.ema(close[barstate.isrealtime ? 1 : 0], i_emaSlow)
c_emaCrossBull = c_emaFast >= c_emaSlow
c_emaCrossBear = c_emaFast < c_emaSlow
c_emaLong = i_wfBarsBack ? 
 close[i_wf] < c_emaFast[i_wf] and close[i_wf] > c_emaSlow[i_wf] :
 close[barstate.isrealtime ? 1 : 0] < c_emaFast and close[barstate.isrealtime ? 1 : 0] > c_emaSlow
c_emaShort =  i_wfBarsBack ? 
 (close[i_wf] > c_emaFast[i_wf] and close[i_wf] < c_emaSlow[i_wf]) :
  close[barstate.isrealtime ? 1 : 0] > c_emaFast and close[barstate.isrealtime ? 1 : 0] < c_emaSlow
c_emaGap = math.abs(c_emaFast - c_emaSlow) >= ((close[barstate.isrealtime ? 1 : 0] / 100) * i_emaGap)
c_tradesOpen = ta.barssince(strategy.opentrades != 0)
// Get RSI values
f_rpSecurity(_symbol, _res, _src) =>
    request.security(_symbol, _res, _src[barstate.isrealtime ? 1 : 0])
    
c_rsiSrc = f_rpSecurity("", i_rsiRes, close)
c_rsi = ta.rsi(c_rsiSrc, i_rsiLen)
c_rsiRising = ta.rising(c_rsi, i_rsiDirectLen)
c_rsiFalling = ta.falling(c_rsi, i_rsiDirectLen)
// Get pullback filter
c_pullbackCountGreen = l_zen.getPullbackBarCount(i_pullbackCount, 1)
c_pullbackCountRed = l_zen.getPullbackBarCount(i_pullbackCount, -1)
// Get Williams Fractals
bool c_upflagDownFrontier = true
bool c_upflagUpFrontier0 = true
bool c_upflagUpFrontier1 = true
bool c_upflagUpFrontier2 = true
bool c_upflagUpFrontier3 = true
bool c_upflagUpFrontier4 = true
for i = 1 to i_wf
    c_upflagDownFrontier := c_upflagDownFrontier and (high[i_wf - i] < high[i_wf])
    c_upflagUpFrontier0 := c_upflagUpFrontier0 and (high[i_wf + i] < high[i_wf])
    c_upflagUpFrontier1 := c_upflagUpFrontier1 and (high[i_wf + 1] <= high[i_wf] and high[i_wf+i + 1] < high[i_wf])
    c_upflagUpFrontier2 := c_upflagUpFrontier2 and (high[i_wf + 1] <= high[i_wf] and high[i_wf + 2] <= high[i_wf] and high[i_wf + i + 2] < high[i_wf])
    c_upflagUpFrontier3 := c_upflagUpFrontier3 and (high[i_wf + 1] <= high[i_wf] and high[i_wf + 2] <= high[i_wf] and high[i_wf + 3] <= high[i_wf] and high[i_wf + i + 3] < high[i_wf])
    c_upflagUpFrontier4 := c_upflagUpFrontier4 and (high[i_wf + 1] <= high[i_wf] and high[i_wf + 2] <= high[i_wf] and high[i_wf + 3] <= high[i_wf] and high[i_wf + 4] <= high[i_wf] and high[i_wf+i + 4] < high[i_wf])
c_flagUpFrontier = c_upflagUpFrontier0 or c_upflagUpFrontier1 or c_upflagUpFrontier2 or c_upflagUpFrontier3 or c_upflagUpFrontier4
c_upFractal = (c_upflagDownFrontier and c_flagUpFrontier)
bool c_downflagDownFrontier = true
bool c_downflagUpFrontier0 = true
bool c_downflagUpFrontier1 = true
bool c_downflagUpFrontier2 = true
bool c_downflagUpFrontier3 = true
bool c_downflagUpFrontier4 = true
for i = 1 to i_wf
    c_downflagDownFrontier := c_downflagDownFrontier and (low[i_wf - i] > low[i_wf])
    c_downflagUpFrontier0 := c_downflagUpFrontier0 and (low[i_wf + i] > low[i_wf])
    c_downflagUpFrontier1 := c_downflagUpFrontier1 and (low[i_wf + 1] >= low[i_wf] and low[i_wf+i + 1] > low[i_wf])
    c_downflagUpFrontier2 := c_downflagUpFrontier2 and (low[i_wf + 1] >= low[i_wf] and low[i_wf + 2] >= low[i_wf] and low[i_wf + i + 2] > low[i_wf])
    c_downflagUpFrontier3 := c_downflagUpFrontier3 and (low[i_wf + 1] >= low[i_wf] and low[i_wf + 2] >= low[i_wf] and low[i_wf + 3] >= low[i_wf] and low[i_wf+i + 3] > low[i_wf])
    c_downflagUpFrontier4 := c_downflagUpFrontier4 and (low[i_wf + 1] >= low[i_wf] and low[i_wf + 2] >= low[i_wf] and low[i_wf + 3] >= low[i_wf] and low[i_wf + 4] >= low[i_wf] and low[i_wf+i + 4] > low[i_wf])
c_flagDownFrontier = c_downflagUpFrontier0 or c_downflagUpFrontier1 or c_downflagUpFrontier2 or c_downflagUpFrontier3 or c_downflagUpFrontier4
c_downFractal = (c_downflagDownFrontier and c_flagDownFrontier)
c_sinceLastTrade = ta.barssince(strategy.closedtrades > strategy.closedtrades[1]) 
c_sinceLastLossTrade = ta.barssince(strategy.losstrades > strategy.losstrades[1])
var float c_longExitPrice = 0.0
var float c_shortExitPrice = 0.0
var float c_longStopPrice = 0.0
var float c_shortStopPrice = 0.0
c_longCondition = c_dateFilter and (c_downFractal) and
 c_emaLong and c_emaCrossBull and (i_emaGapUse ? c_emaGap : true) and
 (i_rsiChk ? (c_rsi >= i_rsiMinLong and c_rsi <= i_rsiMaxLong and (i_rsiDirectChk ? c_rsiRising : true)) : true) and
 (i_usePullbackChk ? c_pullbackCountGreen : true)
c_shortCondition = c_dateFilter and (c_upFractal) and
 c_emaShort and c_emaCrossBear and (i_emaGapUse ? c_emaGap : true) and
 (i_rsiChk ? (c_rsi >= i_rsiMinShort and c_rsi <= i_rsiMaxShort and (i_rsiDirectChk ? c_rsiFalling : true)) : true) and
 (i_usePullbackChk ? c_pullbackCountRed : true) 
if c_longCondition and strategy.opentrades == 0
    strategy.entry(
     id = "LONG open",
     direction = strategy.long,
     comment = i_useComments ? '{\n  "action": "start_bot_and_start_deal",\n  "message_type": "bot",\n  "bot_id": ' + str.tostring(i_botIDLong) + ',\n  "email_token": "' + str.tostring(i_tokenID) + '",\n  "delay_seconds": 0}' : na)
    c_longStopPrice := c_emaSlow
    c_longExitPrice := close + ((close - c_emaSlow) * i_longProfitPerc)
if ta.barssince(strategy.opentrades == 0) >= i_tradeDontClose
    strategy.exit(
     id = "Long close",
     from_entry = "LONG open",
     limit = c_longExitPrice,
     stop = c_longStopPrice,
     comment = i_useComments ? '{\n  "action": "close_at_market_price_all_and_stop_bot",\n  "message_type": "bot",\n  "bot_id": ' + str.tostring(i_botIDLong) + ',\n  "email_token": "' + str.tostring(i_tokenID) + '",\n  "delay_seconds": 0}' : na)
if c_shortCondition and strategy.opentrades == 0
    strategy.entry(
     id = "SHORT open",
     direction = strategy.short,
     comment = i_useComments ? '{\n  "action": "start_bot_and_start_deal",\n  "message_type": "bot",\n  "bot_id": ' + str.tostring(i_botIDShort) + ',\n  "email_token": "' + str.tostring(i_tokenID) + '",\n  "delay_seconds": 0}' : na)
    c_shortStopPrice := c_emaSlow
    c_shortExitPrice := close - ((c_emaSlow - close) * i_shortProfitPerc)
if ta.barssince(strategy.opentrades == 0) >= i_tradeDontClose
    strategy.exit(
     id = "Short close",
     from_entry = "SHORT open",
     limit = c_shortExitPrice,
     stop = c_shortStopPrice,
     comment = i_useComments ? '{\n  "action": "close_at_market_price_all_and_stop_bot",\n  "message_type": "bot",\n  "bot_id": ' + str.tostring(i_botIDShort) + ',\n  "email_token": "' + str.tostring(i_tokenID) + '",\n  "delay_seconds": 0}' : na)
// Plot
plot(c_emaFast, "Ema fast", color = color.new(#4db6ac, 40), linewidth = 2, display = display.none)
plot(c_emaSlow, "Ema slow", color = color.new(#f57c00, 40), linewidth = 2, display = display.none)
plotshape(c_downFractal, title = "Long shape", style=shape.triangleup, location=location.belowbar, offset=-i_wf, color=#009688, size = size.tiny, display = display.none)
plotshape(c_upFractal, title = "Short shape", style=shape.triangledown, location=location.abovebar, offset=-i_wf, color=#F44336, size = size.tiny, display = display.none)
// --- BEGIN TESTER CODE --- //
// Declare performance tracking variables
var balance = startBalance
var maxBalance = 0.0
var totalWins = 0
var totalLoss = 0
// Detect winning trades
if strategy.wintrades != strategy.wintrades[1]
    balance := balance + riskPerTrade / 100 * balance * i_rr 
    totalWins := totalWins + 1
    if balance > maxBalance
        maxBalance := balance
        maxBalance
// Detect losing trades
if strategy.losstrades != strategy.losstrades[1]
    balance := balance - riskPerTrade / 100 * balance
    totalLoss := totalLoss + 1
 
// Prepare stats table
var table testTable = table.new(i_testerPosition == "Top right" ? position.top_right : i_testerPosition == "Top left" ? position.top_left : i_testerPosition == "Bottom right" ? position.bottom_right :position.bottom_left, 5, 2, border_width=2)
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.new(color.black, 0)
if i_drawTester
    if barstate.islastconfirmedhistory
        // Update table
        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(l_zen.truncate(strategy.wintrades / strategy.closedtrades * 100, 2)) + '%', (strategy.wintrades / strategy.closedtrades * 100) >= 50 ? color.green : bgcolor, color.white)
        f_fillCell(testTable, 1, 0, 'Starting:', '$' + str.tostring(startBalance), bgcolor, color.white)
        f_fillCell(testTable, 1, 1, 'Ending:', '$' + str.tostring(l_zen.truncate(balance, 2)), balance > startBalance ? color.green : bgcolor, color.white)
// --- END BACKTESTER CODE --- //
Expand (219 lines)

Overview

Long entries trigger on bullish fractals aligned with rising EMA and RSI conditions, while short entries occur on bearish fractals with falling EMA and RSI. The stop loss is set to the EMA slow value, with profit targets set to a configurable R:R multiple of that stop loss. It supports time-based entry windows and bar evaluation options, with backtesting visualization on the chart.

Details

Published by

hasnocool on GitHub

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

Trend, Oscillators & momentum, Moving averages, Scalping

Markets

Any symbol

Timeframes

M1-M5

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.

Topics

analysisbtcusdtcryptocurrencydatapandaspythonsimulationtradingtradingview

Settings

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

SettingTypeDefaultVariable
Longbooltruei_chkLong
Shortbooltruei_chkShort
Start Datetimetimestamp('01 Jan 2020 00:00 +0100')i_startTime
End Datetimetimestamp('1 Jan 2099 00:00 +0100')i_endTime
Long Target Profit R:Rfloat1.5i_longProfitPerc
Short Target Profit R:Rfloat1.5i_shortProfitPerc
Stop loss not sooner thanint0i_tradeDontClose
Periodsint2i_wf
Evaluate WF barbooltruei_wfBarsBack
Ema fast lenghtint20i_emaFast
Ema slow lenghtint50i_emaSlow
Use Ema Gapboolfalsei_emaGapUse
Show all 34 settings
SettingTypeDefaultVariable
Ema Gap %float0.2i_emaGap
Use RSI Filterboolfalsei_rsiChk
TimeFrametimeframei_rsiRes
Lenghtint14i_rsiLen
Min for Longfloat0.0i_rsiMinLong
Max for Longfloat70.0i_rsiMaxLong
Min for Shortfloat30.0i_rsiMinShort
Max for Shortfloat100.0i_rsiMaxShort
RSI direction confirmationboolfalsei_rsiDirectChk
Bars back for directionint1i_rsiDirectLen
Use Pullbackboolfalsei_usePullbackChk
Lookback periodint2i_pullbackCount
NOT bigger thanint1i_pullbackNotBigger
Show back testerbooltruei_drawTester
i_testerPositionstringTop righti_testerPosition
R:Rfloat1.0i_rr
Starting Balancefloat100.0startBalance
Risk Per Tradefloat1.0riskPerTrade
Show 3Commas bot commentsboolfalsei_useComments
Long Bot IDstringi_botIDLong
Short Bot IDstringi_botIDShort
Email Tokenstringi_tokenID
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

53 stars

This strategy trades EUR/USD on the price chart using a fast and slow exponential moving average crossover filtered by RSI. It enters long when the fast EMA crosses above the slow EMA while RSI is above 50 and below the overbought level, and enters short on th

Strategy v6 TrendMoving averages
Updated 2 months ago · MPL-2.0 GitHub repository of EUR/USD EMA9-21 + RSI Scalping Strategy
13 stars

This strategy plots on the price chart and enters from a moving-average filter, ADX and Gann colours. Price above a 200-period EMA allows only longs; price below allows only shorts. A Gann aqua colour with ADX above a key level opens a long, and a Gann brown c

Strategy v5 TrendOscillators & momentum
Updated 1 year ago · None stated GitHub repository of Ruckard TradingZone ADX Gann

Scalping 3EMA

by rodrigo-brito
9 stars

This long-only strategy calculates three exponential moving averages with lengths of 50, 100, and 150 periods, plotting them directly on the price chart. It also calculates a 14-period RSI and MACD. The strategy opens long positions when the moving averages al

Strategy v4 TrendOscillators & momentum
Updated 5 years ago · MIT GitHub repository of Scalping 3EMA
330 stars

2 EMA/SMA + RSI Strategy [Alorse] combines three configurable moving averages with a short-period Relative Strength Index filter. It plots fast, slow, and trend moving averages on the price chart. Long entries trigger when the fast moving average is above the

Strategy v4 TrendOscillators & momentum
Updated 2 months ago · None stated GitHub repository of 2 EMA/SMA + RSI Strategy [Alorse]

Acrypto - Weighted Strategy

by AlbertoCuadra
318 stars

This strategy plots on the price chart and opens long or short positions when a weighted score from MACD, Stochastic RSI, RSI, Supertrend and a moving-average crossover exceeds a user-set trigger. Each component has its own weight and candle delay. Entries can

Strategy v5 TrendOscillators & momentum
Updated 3 years ago · Custom licence GitHub repository of Acrypto - Weighted Strategy

This strategy combines Arnaud Legoux Moving Average percentage price change calculations with an adaptive Gaussian Moving Average to generate trend-following signals. Long and short entries are triggered when the ALMA change calculation crosses above or below

Strategy v5 Moving averagesOscillators & momentum
Updated 6 weeks ago · None stated GitHub repository of ESM2024 - ALMA Smoothed Gaussian Moving Average

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