Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
- // © quantifytools
- //@version=5
- indicator("Session candles & session reversals (+ Backtest)", max_boxes_count=500, max_lines_count=500, max_labels_count=500, overlay=true)
- // Inputs
- //Session time, session candle offset and show/hide session candle
- groupSession = "Sessions"
- //Session 1 (London)
- show_london = input(title='Show session #1', defval=true, inline="london", group=groupSession)
- i_londonOffset = input.int(0, "", inline="london", minval=0, group=groupSession, tooltip="Moves candle forward by specified amount of bars.")
- london = input.session(title="Session #1 period", defval='0800-1700', tooltip="London by default (UTC)", group=groupSession)
- //Session 2 (New York)
- show_ny = input(title='Show session #2', defval=true, inline="ny", group=groupSession)
- i_nyOffset = input.int(0, "", inline="ny", minval=0, group=groupSession)
- ny = input.session(title="Session #2 period", defval='1300-2200', tooltip="New York by default (UTC)", group=groupSession)
- //Session 3 (Sydney)
- show_sydney = input(title='Show session #3', defval=true, inline="sydney", group=groupSession)
- i_sydneyOffset = input.int(0, "", inline="sydney", minval=0, group=groupSession)
- sydney = input.session(title="Session #3 period", defval='2100-0600', tooltip="Sydney by default (UTC)", group=groupSession)
- //Session 4 (Tokyo)
- show_tokyo = input(title='Show session #4', defval=true, inline="tokyo", group=groupSession)
- i_tokyoOffset = input.int(0, "", inline="tokyo", minval=0, group=groupSession)
- tokyo = input.session(title="Session #4 period", defval='0000-0900', tooltip="Tokyo by default (UTC)", group=groupSession)
- //Session moving average type, length and selected sessions for MA
- groupMa = "Session moving average"
- i_smoothingType = input.string("SMA", "", options=["SMA", "EMA", "HMA", "RMA", "WMA"], group=groupMa, inline="ma")
- i_sessionMaLength = input.int(20, "", group=groupMa, inline="ma")
- i_useSession1Ma = input.bool(true, "Include session #1", group=groupMa)
- i_useSession2Ma = input.bool(true, "Include session #2", group=groupMa)
- i_useSession3Ma = input.bool(true, "Include session #3", group=groupMa)
- i_useSession4Ma = input.bool(true, "Include session #4", group=groupMa)
- //Hide chart candles/bars, highlight sessions for selected session candles, hide timeframe notification, numerize sessions
- groupChart = "Chart"
- i_highlightBt = input.string("None", "Highlight backtesting visuals", options=["None", "Session #1", "Session #2", "Session #3", "Session #4"], group=groupChart)
- i_hideChart = input.bool(true, "Hide chart", tooltip="", group=groupChart)
- i_highlightSession = input.bool(false, "Highlight session periods", group=groupChart, tooltip="Highlights session periods on chart background.")
- i_numberedSessions = input.bool(false, "Numerize sessions", group=groupChart, tooltip="Replaces L, N, S, T with 1, 2, 3, 4. Helps with custom sessions.")
- i_hideNotification = input.bool(false, "Hide timeframe notification", group=groupChart, tooltip="Hides timeframe notification that pops up when timeframe is > 1 hour.")
- //Colors
- groupColor= "Colors"
- i_maColUp = input.color(color.green, "MA ▲", group=groupColor, inline="ma")
- i_maColDown = input.color(color.red, "MA ▼", group=groupColor, inline="ma")
- i_londonColUp = input.color(#c8e6c9, "Session #1 ▲", group=groupColor, inline="session1")
- i_londonColDown = input.color(#faa1a4, "Session #1 ▼", group=groupColor, inline="session1")
- i_londonColSession = input.color(color.gray, "Session #1 ON", group=groupColor, inline="session1", tooltip="Session background color. Visible only if enabled.")
- i_nyColUp = input.color(#81c784, "Session #2 ▲", group=groupColor, inline="session2")
- i_nyColDown = input.color(#f46166, "Session #2 ▼", group=groupColor, inline="session2")
- i_nyColSession = input.color(color.black, "Session #2 ON", group=groupColor, inline="session2")
- i_sydneyColUp = input.color(#05900b, "Session #3 ▲", group=groupColor, inline="session3")
- i_sydneyColDown = input.color(#f23645, "Session #3 ▼", group=groupColor, inline="session3")
- i_sydneyColSession = input.color(color.blue, "Session #3 ON", group=groupColor, inline="session3")
- i_tokyoColUp = input.color(#004505, "Session #4 ▲", group=groupColor, inline="session4")
- i_tokyoColDown = input.color(#880e4f, "Session #4 ▼", group=groupColor, inline="session4")
- i_tokyoColSession = input.color(color.navy, "Session #4 ON", group=groupColor, inline="session4")
- // Session start, on and end functions
- sessionStart(session) =>
- na(time(timeframe.period, session, "GMT"))[1] and not na(time(timeframe.period, session, "GMT"))
- sessionOn(session) =>
- not na(time(timeframe.period, session, "GMT"))
- sessionEnd(session) =>
- na(time(timeframe.period, session, "GMT")) and not na(time(timeframe.period, session, "GMT"))[1]
- // Session OHLC arrays
- //London
- var londonOpen = array.new_float(0, 0)
- var londonHigh = array.new_float(0, 0)
- var londonLow = array.new_float(0, 0)
- var londonClose = array.new_float(0, 0)
- recentLondonOpen = array.size(londonOpen) > 0 ? array.get(londonOpen, 0) : na
- recentLondonHigh = array.size(londonHigh) > 0 ? array.get(londonHigh, 0) : na
- recentLondonLow = array.size(londonLow) > 0 ? array.get(londonLow, 0) : na
- recentLondonClose = array.size(londonClose) > 0 ? array.get(londonClose, 0) : na
- //New York
- var nyOpen = array.new_float(0, 0)
- var nyHigh = array.new_float(0, 0)
- var nyLow = array.new_float(0, 0)
- var nyClose = array.new_float(0, 0)
- recentNyOpen = array.size(nyOpen) > 0 ? array.get(nyOpen, 0) : na
- recentNyHigh = array.size(nyHigh) > 0 ? array.get(nyHigh, 0) : na
- recentNyLow = array.size(nyLow) > 0 ? array.get(nyLow, 0) : na
- recentNyClose = array.size(nyClose) > 0 ? array.get(nyClose, 0) : na
- //Sydney
- var sydneyOpen = array.new_float(0, 0)
- var sydneyHigh = array.new_float(0, 0)
- var sydneyLow = array.new_float(0, 0)
- var sydneyClose = array.new_float(0, 0)
- recentSydneyOpen = array.size(sydneyOpen) > 0 ? array.get(sydneyOpen, 0) : na
- recentSydneyHigh = array.size(sydneyHigh) > 0 ? array.get(sydneyHigh, 0) : na
- recentSydneyLow = array.size(sydneyLow) > 0 ? array.get(sydneyLow, 0) : na
- recentSydneyClose = array.size(sydneyClose) > 0 ? array.get(sydneyClose, 0) : na
- //Tokyo
- var tokyoOpen = array.new_float(0, 0)
- var tokyoHigh = array.new_float(0, 0)
- var tokyoLow = array.new_float(0, 0)
- var tokyoClose = array.new_float(0, 0)
- recentTokyoOpen = array.size(tokyoOpen) > 0 ? array.get(tokyoOpen, 0) : na
- recentTokyoHigh = array.size(tokyoHigh) > 0 ? array.get(tokyoHigh, 0) : na
- recentTokyoLow = array.size(tokyoLow) > 0 ? array.get(tokyoLow, 0) : na
- recentTokyoClose = array.size(tokyoClose) > 0 ? array.get(tokyoClose, 0) : na
- // Session calculations
- //Initializing session highest high/lowest low trackers
- var float londonHh = 0
- var float londonLl = 0
- var float nyHh = 0
- var float nyLl = 0
- var float sydneyHh = 0
- var float sydneyLl = 0
- var float tokyoHh = 0
- var float tokyoLl = 0
- //London calculations
- //If session starts, add open to array, high to HH tracker, low to LL tracker
- if sessionStart(london)
- array.unshift(londonOpen, open)
- londonHh := high
- londonLl := low
- //If session is on and high > HH tracker value, replace HH tracker value with high
- if sessionOn(london) and high > londonHh[1]
- londonHh := high
- //If session is on and low < LL tracker value, replace LL tracker value with low
- if sessionOn(london) and low < londonLl[1]
- londonLl := low
- //If session has ended, add session close (candle open, because session ended 1 time period ago) and add highest high/lowest low to session arrays
- if sessionEnd(london)
- array.unshift(londonClose, open)
- array.unshift(londonHigh, londonHh)
- array.unshift(londonLow, londonLl)
- //Repeating above steps for all other sessions.
- //New York calculations
- if sessionStart(ny)
- array.unshift(nyOpen, open)
- nyHh := high
- nyLl := low
- if sessionOn(ny) and high > nyHh[1]
- nyHh := high
- if sessionOn(ny) and low < nyLl[1]
- nyLl := low
- if sessionEnd(ny)
- array.unshift(nyClose, open)
- array.unshift(nyHigh, nyHh)
- array.unshift(nyLow, nyLl)
- //Sydney calculations
- if sessionStart(sydney)
- array.unshift(sydneyOpen, open)
- sydneyHh := high
- sydneyLl := low
- if sessionOn(sydney) and high > sydneyHh[1]
- sydneyHh := high
- if sessionOn(sydney) and low < sydneyLl[1]
- sydneyLl := low
- if sessionEnd(sydney)
- array.unshift(sydneyClose, open)
- array.unshift(sydneyHigh, sydneyHh)
- array.unshift(sydneyLow, sydneyLl)
- //Tokyo calculations
- if sessionStart(tokyo)
- array.unshift(tokyoOpen, open)
- tokyoHh := high
- tokyoLl := low
- if sessionOn(tokyo) and high > tokyoHh[1]
- tokyoHh := high
- if sessionOn(tokyo) and low < tokyoLl[1]
- tokyoLl := low
- if sessionEnd(tokyo)
- array.unshift(tokyoClose, open)
- array.unshift(tokyoHigh, tokyoHh)
- array.unshift(tokyoLow, tokyoLl)
- //Function to keep array sizes fixed
- arraySize(sessionOpen, sessionHigh, sessionLow, sessionClose) =>
- sizeLimit = 2
- if array.size(sessionOpen) >sizeLimit
- array.remove(sessionOpen, sizeLimit)
- array.remove(sessionHigh, sizeLimit)
- array.remove(sessionLow, sizeLimit)
- array.remove(sessionClose, sizeLimit)
- //Clearing arrays
- arraySize(londonOpen, londonHigh, londonLow, londonClose)
- arraySize(nyOpen, nyHigh, nyLow, nyClose)
- arraySize(sydneyOpen, sydneyHigh, sydneyLow, sydneyClose)
- arraySize(tokyoOpen, tokyoHigh, tokyoLow, tokyoClose)
- // Session moving average
- //Function for user defined smoothing method
- smoothedValue(source, length) =>
- i_smoothingType == "SMA" ? ta.sma(source, length) :
- i_smoothingType == "EMA" ? ta.ema(source, length) :
- i_smoothingType == "HMA" ? ta.hma(source, length) :
- i_smoothingType == "RMA" ? ta.rma(source, length) : ta.wma(source, length)
- //Session MA's, if not included use 0
- londonSma = i_useSession1Ma ? smoothedValue(recentLondonClose, i_sessionMaLength) : 0
- nySma = i_useSession2Ma ? smoothedValue(recentNyClose, i_sessionMaLength) : 0
- sydneySma = i_useSession3Ma ? smoothedValue(recentSydneyClose, i_sessionMaLength) : 0
- tokyoSma = i_useSession4Ma ? smoothedValue(recentTokyoClose, i_sessionMaLength) : 0
- //Calculate amount of sessions included in MA calculation
- int maDivider = 0
- if i_useSession1Ma
- maDivider += 1
- if i_useSession2Ma
- maDivider += 1
- if i_useSession3Ma
- maDivider += 1
- if i_useSession4Ma
- maDivider += 1
- //Selected session MA's divided by amount of selected sessions
- hybridSma = (nySma + tokyoSma + londonSma + sydneySma) / maDivider
- // Session reversals
- //Session reversal function with session OHLC variables
- sessionReversal(sessionOpen, sessionHigh, sessionLow, sessionClose) =>
- //Position of session close relative to range (high - low)
- sessionPos = (sessionClose - sessionLow) / (sessionHigh - sessionLow)
- //Position of session open relative to range (high - low)
- sessionOpenPos = (sessionOpen - sessionLow) / (sessionHigh - sessionLow)
- //Session high lower than previous high, session low lower than previous low, close >= 65% position (1% being low, 100% being high) and session open at >= 40% position relative to range. A wick up.
- wickUp = sessionHigh < sessionHigh[1] and sessionLow < sessionLow[1] and sessionPos >= 0.65 and sessionOpenPos >= 0.40
- //Session high higher than previous high, session low higher than previous low, close <= 35% position and session open <= 60% position relative to range. A wick down.
- wickDown = sessionHigh > sessionHigh[1] and sessionLow > sessionLow[1] and sessionPos <= 0.35 and sessionOpenPos <= 0.60
- //Session high higher than previous high, session low lower than previous low and close position at same 65%/35% values. Engulfing candle up/down.
- engulfUp = sessionHigh > sessionHigh[1] and sessionLow < sessionLow[1] and sessionPos >= 0.65
- engulfDown = sessionHigh > sessionHigh[1] and sessionLow < sessionLow[1] and sessionPos <= 0.35
- [wickUp, wickDown, engulfUp, engulfDown]
- //Fetching session reversals for each session
- [wickUpLondon, wickDownLondon, engulfUpLondon, engulfDownLondon] = sessionReversal(recentLondonOpen, recentLondonHigh, recentLondonLow, recentLondonClose)
- [wickUpNy, wickDownNy, engulfUpNy, engulfDownNy] = sessionReversal(recentNyOpen, recentNyHigh, recentNyLow, recentNyClose)
- [wickUpSydney, wickDownSydney, engulfUpSydney, engulfDownSydney] = sessionReversal(recentSydneyOpen, recentSydneyHigh, recentSydneyLow, recentSydneyClose)
- [wickUpTokyo, wickDownTokyo, engulfUpTokyo, engulfDownTokyo] = sessionReversal(recentTokyoOpen, recentTokyoHigh, recentTokyoLow, recentTokyoClose)
- // Session reversal backtest
- //Sessions are backtested by calculating odds of next matching session closing in supporting direction, known as win rate.
- //Magnitude is measured by calculating percentage increase/decrease between session reversal close and next session high/low. This calculation is done only when a reversal is succesful (closes higher/lower compared previous matching session).
- //Session reversal backtest function
- sessionReversalBt(wickUp, wickDown, engulfUp, engulfDown, sessionClose, sessionHigh, sessionLow, session) =>
- //Get bar_index space between sessions
- btPeriod = ta.valuewhen(sessionEnd(session), bar_index, 0) - ta.valuewhen(sessionEnd(session), bar_index, 1)
- //Initializing counters
- var int sessionRevUpCount = 0
- var int sessionRevDownCount = 0
- var int succesfulRevUpCount = 0
- var int succesfulRevDownCount = 0
- var float revUpDepth = 0
- var float revDownDepth = 0
- //Any reversal up/down, either wick or engulfing.
- anyRevUp = wickUp or engulfUp
- anyRevDown = wickDown or engulfDown
- //Add 1 to reversal counter when session reversal occurs
- if anyRevUp
- sessionRevUpCount += 1
- else
- if anyRevDown
- sessionRevDownCount += 1
- //If session closes higher than previous session and previous session was a reversal, add 1 to succesful reversal counter. Add percentage increase (from previous session close to current session high) to magnitude counter.
- if sessionClose > sessionClose[1] and anyRevUp[btPeriod]
- succesfulRevUpCount += 1
- revUpDepth += (sessionHigh / sessionClose[1]) - 1
- //Same, but for reversals down
- if sessionClose < sessionClose[1] and anyRevDown[btPeriod]
- succesfulRevDownCount += 1
- revDownDepth += (sessionLow / sessionClose[1]) - 1
- //Form win rates by dividing succesful reversal count with total reversal count
- revUpWr = math.round((succesfulRevUpCount / sessionRevUpCount) * 100, 0)
- revDownWr = math.round((succesfulRevDownCount / sessionRevDownCount) * 100, 0)
- //Form average magnitude by dividing percentage increase/decrease with total reversal count
- revUpMagnitude = math.round((revUpDepth / sessionRevUpCount) * 100, 2)
- revDownMagnitude = math.round((revDownDepth / sessionRevDownCount) * 100, 2)
- [sessionRevUpCount, sessionRevDownCount, succesfulRevDownCount, succesfulRevUpCount, revUpDepth, revDownDepth,
- revUpWr, revDownWr, revUpMagnitude, revDownMagnitude]
- //Fetching backtest results for each session reversal
- [revUpsLondon, revDownsLondon, sRevDownsLondon, sRevUpsLondon, LondonUpDepth, LondonDownDepth,
- LondonRevUpWr, LondonRevDownWr, LondonRevUpMagnitude, LondonRevDownMagnitude]
- = sessionReversalBt(wickUpLondon, wickDownLondon, engulfUpLondon, engulfDownLondon, recentLondonClose, recentLondonHigh, recentLondonLow, london)
- [revUpsNy, revDownsNy, sRevDownsNy, sRevUpsNy, NyUpDepth, NyDownDepth,
- NyRevUpWr, NyRevDownWr, NyRevUpMagnitude, NyRevDownMagnitude]
- = sessionReversalBt(wickUpNy, wickDownNy, engulfUpNy, engulfDownNy, recentNyClose, recentNyHigh, recentNyLow, ny)
- [revUpsSydney, revDownsSydney, sRevDownsSydney, sRevUpsSydney, SydneyUpDepth, SydneyDownDepth,
- SydneyRevUpWr, SydneyRevDownWr, SydneyRevUpMagnitude, SydneyRevDownMagnitude]
- = sessionReversalBt(wickUpSydney, wickDownSydney, engulfUpSydney, engulfDownSydney, recentSydneyClose, recentSydneyHigh, recentSydneyLow, sydney)
- [revUpsTokyo, revDownsTokyo, sRevDownsTokyo, sRevUpsTokyo, TokyoUpDepth, TokyoDownDepth,
- TokyoRevUpWr, TokyoRevDownWr, TokyoRevUpMagnitude, TokyoRevDownMagnitude]
- = sessionReversalBt(wickUpTokyo, wickDownTokyo, engulfUpTokyo, engulfDownTokyo, recentTokyoClose, recentTokyoHigh, recentTokyoLow, tokyo)
- // Plot related calculations
- //Current timeframe
- currentTf = timeframe.in_seconds(timeframe.period) / 60
- //Note users when timeframe is above 1H and possibly not matching with selected session time periods
- tfNotification = currentTf > 60 and i_hideNotification == false ? "(!) Make sure timeframe supports selected session time periods. By default 1H is recommended." : ""
- //Session candle colors
- londonColor = recentLondonClose > recentLondonClose[1] ? i_londonColUp : i_londonColDown
- nyColor = recentNyClose > recentNyOpen ? i_nyColUp : i_nyColDown
- sydneyColor = recentSydneyClose > recentSydneyClose[1] ? i_sydneyColUp : i_sydneyColDown
- tokyoColor = recentTokyoClose > recentTokyoClose[1] ? i_tokyoColUp : i_tokyoColDown
- //MA color, using "switch" method to avoid incorrect colors when MA value is equal to last MA value (happens on lower timeframes)
- var color maCol = color.gray
- if hybridSma > hybridSma[1]
- maCol := i_maColUp
- if hybridSma == hybridSma[1]
- maCol := maCol[1]
- if hybridSma < hybridSma[1]
- maCol := i_maColDown
- //Session candle visuals
- borderWidth = 0
- linewidth = 2
- //Session reversal colors
- //Any session reversal
- anyWickUp = wickUpNy or wickUpLondon or wickUpSydney or wickUpTokyo
- anyWickDown = wickDownNy or wickDownLondon or wickDownSydney or wickDownTokyo
- anyEngulfUp = engulfUpNy or engulfUpLondon or engulfUpSydney or engulfUpTokyo
- anyEngulfDown = engulfDownNy or engulfDownLondon or engulfDownSydney or engulfDownTokyo
- //Session reversal color
- revCol = anyWickUp ? color.green : anyWickDown ? color.red : anyEngulfUp ? color.teal : anyEngulfDown ? color.maroon : na
- //Reversal number/text. Use LNST by default, 1-4 if numerized sessions is on.
- session1Text = i_numberedSessions ? "1" : "L"
- session2Text = i_numberedSessions ? "2" : "N"
- session3Text = i_numberedSessions ? "3" : "S"
- session4Text = i_numberedSessions ? "4" : "T"
- //Reversal label texts
- revUpL = "▲" + "\n" + session1Text
- revDownL = session1Text + "\n" + "▼"
- revUpN = "▲" + "\n" + session2Text
- revDownN = session2Text + "\n" + "▼"
- revUpS = "▲" + "\n" + session3Text
- revDownS = session3Text + "\n" + "▼"
- revUpT = "▲" + "\n" + session4Text
- revDownT = session4Text + "\n" + "▼"
- //Highest session reversal up win rate
- highestWrUp = LondonRevUpWr >= NyRevUpWr and LondonRevUpWr >= SydneyRevUpWr and LondonRevUpWr >= TokyoRevUpWr ? 1 :
- NyRevUpWr >= LondonRevUpWr and NyRevUpWr >= SydneyRevUpWr and NyRevUpWr >= TokyoRevUpWr ? 2 :
- SydneyRevUpWr >= LondonRevUpWr and SydneyRevUpWr >= NyRevUpWr and SydneyRevUpWr >= TokyoRevUpWr ? 3 : 4
- //Highest session reversal down win rate
- highestWrDown = LondonRevDownWr >= NyRevDownWr and LondonRevDownWr >= SydneyRevDownWr and LondonRevDownWr >= TokyoRevDownWr ? 1 :
- NyRevDownWr >= LondonRevDownWr and NyRevDownWr >= SydneyRevDownWr and NyRevDownWr >= TokyoRevDownWr ? 2 :
- SydneyRevDownWr >= LondonRevDownWr and SydneyRevDownWr >= NyRevDownWr and SydneyRevDownWr >= TokyoRevDownWr ? 3 : 4
- //Highest session magnitude up
- highestMagnitudeUp = LondonRevUpMagnitude >= NyRevUpMagnitude and LondonRevUpMagnitude >= SydneyRevUpMagnitude and LondonRevUpMagnitude >= TokyoRevUpMagnitude ? 1 :
- NyRevUpMagnitude >= LondonRevUpMagnitude and NyRevUpMagnitude >= SydneyRevUpMagnitude and NyRevUpMagnitude >= TokyoRevUpMagnitude ? 2 :
- SydneyRevUpMagnitude >= LondonRevUpMagnitude and SydneyRevUpMagnitude >= NyRevUpMagnitude and SydneyRevUpMagnitude >= TokyoRevUpMagnitude ? 3 : 4
- //Highest session magnitude down
- highestMagnitudeDown = LondonRevDownMagnitude <= NyRevDownMagnitude and LondonRevDownMagnitude <= SydneyRevDownMagnitude and LondonRevDownMagnitude <= TokyoRevDownMagnitude ? 1 :
- NyRevDownMagnitude <= LondonRevDownMagnitude and NyRevDownMagnitude <= SydneyRevDownMagnitude and NyRevDownMagnitude <= TokyoRevDownMagnitude ? 2 :
- SydneyRevDownMagnitude <= LondonRevDownMagnitude and SydneyRevDownMagnitude <= NyRevDownMagnitude and SydneyRevDownMagnitude <= TokyoRevDownMagnitude ? 3 : 4
- //Reversal backtest table texts. Add 🔸 if given session reversal backtest metric is best perofrming
- revUpLText = session1Text + " ▲ : " + str.tostring(revUpsLondon) + " | " + "WR: " + str.tostring(LondonRevUpWr) + "%" + (highestWrUp == 1 ? " 🔸" : "") + " | " + "M: " + str.tostring(LondonRevUpMagnitude) + "%" + (highestMagnitudeUp == 1 ? " 🔸" : "")
- revDownLText = session1Text + " ▼ : " + str.tostring(revDownsLondon) + " | " + "WR: " + str.tostring(LondonRevDownWr) + "%" + (highestWrDown == 1 ? " 🔸" : "") + " | " + " M: " + str.tostring(LondonRevDownMagnitude) + "%" + (highestMagnitudeDown == 1 ? " 🔸" : "")
- revUpNText = session2Text + " ▲ : " + str.tostring(revUpsNy) + " | " + "WR: " + str.tostring(NyRevUpWr) + "%" + (highestWrUp == 2 ? " 🔸" : "") + " | " + "M: " + str.tostring(NyRevUpMagnitude) + "%" + (highestMagnitudeUp == 2 ? " 🔸" : "")
- revDownNText = session2Text + " ▼ : " + str.tostring(revDownsNy) + " | " + "WR: " + str.tostring(NyRevDownWr) + "%" + (highestWrDown == 2 ? " 🔸" : "") + " | " + " M: " + str.tostring(NyRevDownMagnitude) + "%" + (highestMagnitudeDown == 2 ? " 🔸" : "")
- revUpSText = session3Text + " ▲ : " + str.tostring(revUpsSydney) + " | " + "WR: " + str.tostring(SydneyRevUpWr) + "%" + (highestWrUp == 3 ? " 🔸" : "") + " | " + "M: " + str.tostring(SydneyRevUpMagnitude) + "%" + (highestMagnitudeUp == 3 ? " 🔸" : "")
- revDownSText = session3Text + " ▼ : " + str.tostring(revDownsSydney) + " | " + "WR: " + str.tostring(SydneyRevDownWr) + "%" + (highestWrDown == 3 ? " 🔸" : "") + " | " + " M: " + str.tostring(SydneyRevDownMagnitude) + "%" + (highestMagnitudeDown == 3 ? " 🔸" : "")
- revUpTText = session4Text + " ▲ : " + str.tostring(revUpsTokyo) + " | " + "WR: " + str.tostring(TokyoRevUpWr) + "%" + (highestWrUp == 4 ? " 🔸" : "") + " | " + "M: " + str.tostring(TokyoRevUpMagnitude) + "%" + (highestMagnitudeUp == 4 ? " 🔸" : "")
- revDownTText = session4Text + " ▼ : " + str.tostring(revDownsTokyo) + " | " + "WR: " + str.tostring(TokyoRevDownWr) + "%" + (highestWrDown == 4 ? " 🔸" : "") + " | " + " M: " + str.tostring(TokyoRevDownMagnitude) + "%" + (highestMagnitudeDown == 4 ? " 🔸" : "")
- //Function for forming session candles using line and box, available for first 500 bars. Clear look. Forming session reversal labels also.
- sessionCandles(session, sessionOffset, sessionOpen, sessionHigh, sessionLow, sessionClose, sessionWickUp, sessionEngUp, sessionWickDown, sessionEngDown, sessionCol, revUpText, revDownText) =>
- //Session candles
- if sessionEnd(session)[1]
- line.new(bar_index + sessionOffset, sessionHigh, bar_index + sessionOffset, sessionLow, xloc=xloc.bar_index, color=sessionCol, width=linewidth, style=line.style_solid)
- box.new(left=bar_index - 1 + sessionOffset, top=sessionClose, right=bar_index + 1 + sessionOffset, bottom=sessionOpen, bgcolor=sessionCol, border_color=color.new(color.white, 100), border_width=borderWidth)
- //Session reversals
- if (sessionWickUp or sessionEngUp) and sessionEnd(session)[1] and barstate.isconfirmed
- label.new(x=bar_index + sessionOffset, y=sessionLow, xloc=xloc.bar_index, yloc=yloc.price, text=revUpText, style=label.style_label_up, textcolor=color.new(revCol, 1), color=color.new(color.green, 100), size=size.normal)
- if (sessionWickDown or sessionEngDown) and sessionEnd(session)[1] and barstate.isconfirmed
- label.new(x=bar_index + sessionOffset, y=sessionHigh, xloc=xloc.bar_index, yloc=yloc.price, text=revDownText, style=label.style_label_down, textcolor=color.new(revCol, 1), color=color.new(color.red, 100), size=size.normal)
- //Function for forming session candles using plotcandle() function, available for all bars. Not so clear, but goes back indefinitely.
- sessionCandles2(session, sessionOffset, showSession, sessionOpen, sessionHigh, sessionLow, sessionClose) =>
- //Session OHLC values with offset for plotcandle() function
- sessionEndO = ta.barssince(sessionEnd(session)) == 1 + sessionOffset and showSession ? sessionOpen : na
- sessionEndH = ta.barssince(sessionEnd(session)) == 1 + sessionOffset and showSession ? sessionHigh : na
- sessionEndL = ta.barssince(sessionEnd(session)) == 1 + sessionOffset and showSession ? sessionLow : na
- sessionEndC = ta.barssince(sessionEnd(session)) == 1 + sessionOffset and showSession ? sessionClose : na
- [sessionEndO, sessionEndH, sessionEndL, sessionEndC]
- //Function for forming backtest visuals.
- sessionReversalBtVisuals(session, sessionHigh, sessionLow, sessionClose, succesfulRevsUp, succesfulRevsDown, revsUp, revsDown, revUpWr, revUpMagnitude, revDownWr, revDownMagnitude, sessionOffset) =>
- //Get bar_index space between session reversals
- btPeriod = ta.valuewhen(sessionEnd(session), bar_index, 0) - ta.valuewhen(sessionEnd(session), bar_index, 1)
- //Reversal up texts
- sRevUpMagnitudeText = " Gain: +" + str.tostring(math.round((sessionHigh / sessionClose[1]) - 1, 4) * 100) + "%" + "\n" + "◣ Avg: +" + str.tostring(revUpMagnitude) + "%"
- sRevUpWrText = "\n" + "\n" + "\n" + "Succesful: " + str.tostring(succesfulRevsUp) + "\n" + "Win rate: " + str.tostring(revUpWr) + "%"
- revUpCountText = "\n" + "\n" + "Count: " + str.tostring(revsUp)
- //Reversal down texts
- sRevDownMagnitudeText = "◤ Gain: " + str.tostring(math.round((sessionLow / sessionClose[1]) - 1, 4) * 100) + "%" + "\n" + " Avg: " + str.tostring(revDownMagnitude) + "%"
- sRevDownWrText = "Succesful: " + str.tostring(succesfulRevsDown) + "\n" + "Win rate: " + str.tostring(revDownWr) + "%" + "\n" + "\n" + "\n"
- revDownCountText = "Count: " + str.tostring(revsDown) + "\n" + "\n"
- //If reversal is succesful and session ended 1 period ago, plot line and labels
- if succesfulRevsUp > succesfulRevsUp[1] and sessionEnd(session)[1]
- line.new(bar_index[btPeriod] + sessionOffset, sessionClose[1], bar_index + sessionOffset, sessionHigh, xloc=xloc.bar_index, color=color.white, width=1, style=line.style_solid)
- label.new(x=bar_index + sessionOffset, y=sessionHigh, xloc=xloc.bar_index, yloc=yloc.price, text=sRevUpMagnitudeText, style=label.style_label_lower_left, textcolor=color.new(color.white, 1), color=color.new(color.green, 100), size=size.normal)
- label.new(x=bar_index[btPeriod] + sessionOffset, y=sessionLow[btPeriod], xloc=xloc.bar_index, yloc=yloc.price, text=sRevUpWrText, style=label.style_label_up, textcolor=color.new(color.white, 1), color=color.new(color.green, 100), size=size.normal)
- //If reversal occurs, plot label
- if revsUp > revsUp[1]
- label.new(x=bar_index + sessionOffset, y=sessionLow, xloc=xloc.bar_index, yloc=yloc.price, text=revUpCountText, style=label.style_label_up, textcolor=color.new(color.white, 1), color=color.new(color.green, 100), size=size.normal)
- //If reversal is succesful and session ended 1 period ago, plot line and labels
- if succesfulRevsDown > succesfulRevsDown[1] and sessionEnd(session)[1]
- line.new(bar_index[btPeriod] + sessionOffset, sessionClose[1], bar_index + sessionOffset, sessionLow, xloc=xloc.bar_index, color=color.white, width=1, style=line.style_solid)
- label.new(x=bar_index + sessionOffset, y=sessionLow, xloc=xloc.bar_index, yloc=yloc.price, text=sRevDownMagnitudeText, style=label.style_label_upper_left, textcolor=color.new(color.white, 1), color=color.new(color.red, 100), size=size.normal)
- label.new(x=bar_index[btPeriod] + sessionOffset, y=sessionHigh[btPeriod], xloc=xloc.bar_index, yloc=yloc.price, text=sRevDownWrText, style=label.style_label_down, textcolor=color.new(color.white, 1), color=color.new(color.green, 100), size=size.normal)
- //If reversal occurs, plot label
- if revsDown > revsDown[1]
- label.new(x=bar_index + sessionOffset, y=sessionHigh, xloc=xloc.bar_index, yloc=yloc.price, text=revDownCountText, style=label.style_label_down, textcolor=color.new(color.white, 1), color=color.new(color.green, 100), size=size.normal)
- //Session candles using line and box
- londonCandles = show_london ? sessionCandles(london, i_londonOffset, recentLondonOpen, recentLondonHigh, recentLondonLow, recentLondonClose, wickUpLondon, engulfUpLondon, wickDownLondon, engulfDownLondon, londonColor, revUpL, revDownL) : na
- nyCandles = show_ny ? sessionCandles(ny, i_nyOffset, recentNyOpen, recentNyHigh, recentNyLow, recentNyClose, wickUpNy, engulfUpNy, wickDownNy, engulfDownNy, nyColor, revUpN, revDownN) : na
- sydneyCandles = show_sydney ? sessionCandles(sydney, i_sydneyOffset, recentSydneyOpen, recentSydneyHigh, recentSydneyLow, recentSydneyClose, wickUpSydney, engulfUpSydney, wickDownSydney, engulfDownSydney, sydneyColor, revUpS, revDownS) : na
- tokyoCandles = show_tokyo ? sessionCandles(tokyo, i_tokyoOffset, recentTokyoOpen, recentTokyoHigh, recentTokyoLow, recentTokyoClose, wickUpTokyo, engulfUpTokyo, wickDownTokyo, engulfDownTokyo, tokyoColor, revUpT, revDownT) : na
- //Session candles using plotcandle()
- [sessionEndLondonO, sessionEndLondonH, sessionEndLondonL, sessionEndLondonC] = sessionCandles2(london, i_londonOffset, show_london, recentLondonOpen, recentLondonHigh, recentLondonLow, recentLondonClose)
- [sessionEndNyO, sessionEndNyH, sessionEndNyL, sessionEndNyC] = sessionCandles2(ny, i_nyOffset, show_ny, recentNyOpen, recentNyHigh, recentNyLow, recentNyClose)
- [sessionEndSydneyO, sessionEndSydneyH, sessionEndSydneyL, sessionEndSydneyC] = sessionCandles2(sydney, i_sydneyOffset, show_sydney, recentSydneyOpen, recentSydneyHigh, recentSydneyLow, recentSydneyClose)
- [sessionEndTokyoO, sessionEndTokyoH, sessionEndTokyoL, sessionEndTokyoC] = sessionCandles2(tokyo, i_tokyoOffset, show_tokyo, recentTokyoOpen, recentTokyoHigh, recentTokyoLow, recentTokyoClose)
- //Session reversal backtest visuals
- londonBtVisuals = i_highlightBt == "Session #1" and show_london ?
- sessionReversalBtVisuals(london, recentLondonHigh, recentLondonLow, recentLondonClose, sRevUpsLondon, sRevDownsLondon, revUpsLondon, revDownsLondon, LondonRevUpWr, LondonRevUpMagnitude, LondonRevDownWr, LondonRevDownMagnitude, i_londonOffset) : na
- nyBtVisuals = i_highlightBt == "Session #2" and show_ny ?
- sessionReversalBtVisuals(ny, recentNyHigh, recentNyLow, recentNyClose, sRevUpsNy, sRevDownsNy, revUpsNy, revDownsNy, NyRevUpWr, NyRevUpMagnitude, NyRevDownWr, NyRevDownMagnitude, i_nyOffset) : na
- sydneyBtVisuals = i_highlightBt == "Session #3" and show_sydney ?
- sessionReversalBtVisuals(sydney, recentSydneyHigh, recentSydneyLow, recentSydneyClose, sRevUpsSydney, sRevDownsSydney, revUpsSydney, revDownsSydney, SydneyRevUpWr, SydneyRevUpMagnitude, SydneyRevDownWr, SydneyRevDownMagnitude, i_sydneyOffset) : na
- tokyoBtVisuals = i_highlightBt == "Session #4" and show_tokyo ?
- sessionReversalBtVisuals(tokyo, recentTokyoHigh, recentTokyoLow, recentTokyoClose, sRevUpsTokyo, sRevDownsTokyo, revUpsTokyo, revDownsTokyo, TokyoRevUpWr, TokyoRevUpMagnitude, TokyoRevDownWr, TokyoRevDownMagnitude, i_tokyoOffset) : na
- // Plots
- //MA
- plot(hybridSma, color=maCol, title="Session moving average")
- //Regular session candle using plotcandle() function.
- plotcandle(sessionEndLondonO, sessionEndLondonH, sessionEndLondonL, sessionEndLondonC, color=londonColor)
- plotcandle(sessionEndNyO, sessionEndNyH, sessionEndNyL, sessionEndNyC, color=nyColor)
- plotcandle(sessionEndSydneyO, sessionEndSydneyH, sessionEndSydneyL, sessionEndSydneyC, color=sydneyColor)
- plotcandle(sessionEndTokyoO, sessionEndTokyoH, sessionEndTokyoL, sessionEndTokyoC, color=tokyoColor)
- //Session period background highlights
- bgcolor(i_highlightSession == true and show_london == true and sessionOn(london) ? color.new(i_londonColSession, 90) : na)
- bgcolor(i_highlightSession == true and show_london == true and sessionStart(london) ? color.new(i_londonColSession, 50) : na)
- bgcolor(i_highlightSession == true and show_london == true and sessionEnd(london) ? color.new(i_londonColSession, 50) : na)
- bgcolor(i_highlightSession == true and show_ny == true and sessionOn(ny) ? color.new(i_nyColSession, 90) : na)
- bgcolor(i_highlightSession == true and show_ny == true and sessionStart(ny) ? color.new(i_nyColSession, 50) : na)
- bgcolor(i_highlightSession == true and show_ny == true and sessionEnd(ny) ? color.new(i_nyColSession, 50) : na)
- bgcolor(i_highlightSession == true and show_sydney == true and sessionOn(sydney) ? color.new(i_sydneyColSession, 90) : na)
- bgcolor(i_highlightSession == true and show_sydney == true and sessionStart(sydney) ? color.new(i_sydneyColSession, 50) : na)
- bgcolor(i_highlightSession == true and show_sydney == true and sessionEnd(sydney) ? color.new(i_sydneyColSession, 50) : na)
- bgcolor(i_highlightSession == true and show_tokyo == true and sessionOn(tokyo) ? color.new(i_tokyoColSession, 90) : na)
- bgcolor(i_highlightSession == true and show_tokyo == true and sessionStart(tokyo) ? color.new(i_tokyoColSession, 50) : na)
- bgcolor(i_highlightSession == true and show_tokyo == true and sessionEnd(tokyo) ? color.new(i_tokyoColSession, 50) : na)
- //Hide chart
- barcolor(i_hideChart == true ? color.new(color.white, 100) : na)
- // Alerts
- //Confirmed session candle closes
- alertcondition(sessionEnd(london)[1], "Confirmed session #1 candle close", "Confirmed session #1 candle close detected")
- alertcondition(sessionEnd(ny)[1], "Confirmed session #2 candle close", "Confirmed session #2 candle close detected")
- alertcondition(sessionEnd(sydney)[1], "Confirmed session #3 candle close", "Confirmed session #3 candle close detected")
- alertcondition(sessionEnd(tokyo)[1], "Confirmed session #4 candle close", "Confirmed session #4 candle close detected")
- //Confirmed any session candle close
- anySessionClose = sessionEnd(london)[1] or sessionEnd(ny)[1] or sessionEnd(sydney)[1] or sessionEnd(tokyo)[1]
- alertcondition(anySessionClose, "Confirmed session (any) candle close", "Confirmed session (any) candle close detected")
- //Confirmed session reversals up
- alertcondition(revUpsLondon > revUpsLondon[1], "Confirmed session #1 reversal up", "Confirmed session #1 reversal up detected")
- alertcondition(revUpsNy > revUpsNy[1], "Confirmed session #2 reversal up", "Confirmed session #2 reversal up detected")
- alertcondition(revUpsSydney > revUpsSydney[1], "Confirmed session #3 reversal up", "Confirmed session #3 reversal up detected")
- alertcondition(revUpsTokyo > revUpsTokyo[1], "Confirmed session #4 reversal up", "Confirmed session #4 reversal up detected")
- //Confirmed any session reversal up
- anySessionRevUp = revUpsLondon > revUpsLondon[1] or revUpsNy > revUpsNy[1] or revUpsSydney > revUpsSydney[1] or revUpsTokyo > revUpsTokyo[1]
- alertcondition(anySessionRevUp, "Confirmed session (any) reversal up", "Confirmed session (any) reversal up detected")
- //Confirmed session reversals down
- alertcondition(revDownsLondon > revDownsLondon[1], "Confirmed session #1 reversal down", "Confirmed session #1 reversal down detected")
- alertcondition(revDownsNy > revDownsNy[1], "Confirmed session #2 reversal down", "Confirmed session #2 reversal down detected")
- alertcondition(revDownsSydney > revDownsSydney[1], "Confirmed session #3 reversal down", "Confirmed session #3 reversal down detected")
- alertcondition(revDownsTokyo > revDownsTokyo[1], "Confirmed session #4 reversal down", "Confirmed session #4 reversal down detected")
- //Confirmed any session reversal down
- anySessionRevDown = revDownsLondon > revDownsLondon[1] or revDownsNy > revDownsNy[1] or revDownsSydney > revDownsSydney[1] or revDownsTokyo > revDownsTokyo[1]
- alertcondition(anySessionRevDown, "Confirmed session (any) candle reversal down", "Confirmed session (any) reversal down detected")
- //Confirmed any session reversal up/down
- alertcondition(anySessionRevDown or anySessionRevUp, "Confirmed session (any) reversal up/down", "Confirmed session (any) reversal up/down detected")
- // Backtest table
- //Initialize backtest table and timeframe notification table
- var activeTable = table.new(position = position.top_right, columns = 50, rows = 50, bgcolor = color.rgb(29, 29, 29), border_width = 3, border_color = color.new(color.white, 100))
- var notifyTable = table.new(position = position.bottom_right, columns = 50, rows = 50, bgcolor = color.new(color.white, 100), border_width = 3)
- //Populate backtest table cells
- table.cell(table_id = activeTable, column = 0, row = 0, text = revUpLText + "\n" + "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯" + "\n" + revDownLText, bgcolor=color.rgb(48, 48, 48), text_color = color.white)
- table.cell(table_id = activeTable, column = 1, row = 0, text = revUpNText + "\n" + "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯" + "\n" + revDownNText, bgcolor=color.rgb(48, 48, 48), text_color = color.white)
- table.cell(table_id = activeTable, column = 0, row = 2, text = revUpSText + "\n" + "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯" + "\n" + revDownSText, bgcolor=color.rgb(48, 48, 48), text_color = color.white)
- table.cell(table_id = activeTable, column = 1, row = 2, text = revUpTText + "\n" + "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯" + "\n" + revDownTText, bgcolor=color.rgb(48, 48, 48), text_color = color.white)
- //Populate timeframe notification table if applicable
- table.cell(table_id = notifyTable, column = 0, row = 0, text = "" + tfNotification, text_color=color.yellow, bgcolor = color.new(color.white, 100))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement