SmartMoneyConcepts.pine
Copy
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © tamth_
// @version=5
indicator("Smart Money Concepts", "Smart Money Concepts", overlay = true, max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500, max_bars_back = 500)
//-----------------------------------------------------------------------------*
// Constants
//-----------------------------------------------------------------------------{
color TRANSPARENT_COLOR = #ffffff00
color WHITE_COLOR = #ffffff
color RED_COLOR = #e91e62
color AQUA_COLOR = #00bbf9
color LIGHT_GRAY_COLOR = #364156
color DARK_GRAY_COLOR = #212d40
color GREEN_COLOR = #008170
color PURPLE_COLOR = #764AF1
color YELLOW_COLOR = #f2e40a
color ORANGE_COLOR = #f2aa0a
color TXT_COLOR = #787b86
color BLOCK_COLOR = #5d606b19
//-----------------------------------------------------------------------------}
//-----------------------------------------------------------------------------*
// Common Functions
//-----------------------------------------------------------------------------{
debug(simple string txt) =>
// Create label on the first bar
var label = label.new(bar_index, na, txt, xloc.bar_index, yloc.price, color(na), label.style_none, WHITE_COLOR, size.large, text.align_left)
// On next bars, update the label"s x and y position, and the text it displays
label.set_xy(label, bar_index, ta.highest(10)[1])
label.set_text(label, txt)
//-----------------------------------------------------------------------------}
//-----------------------------------------------------------------------------*
// Common Variables
//-----------------------------------------------------------------------------{
series int barIdx = bar_index
series int BAR_IDX_RIGHT_ALIGNMENT = barIdx + 21
series int BAR_TIME_RIGHT_ALIGNMENT = timenow + (time[1] - time[101]) / 100 * 20
//-----------------------------------------------------------------------------}
//-----------------------------------------------------------------------------*
// General Settings
//-----------------------------------------------------------------------------{
string generalGrp = "General"
// 7 * 24 * 4
int generalLen = input.int(672, "Length", minval = 1, maxval = 672, group = generalGrp, tooltip = "Number of most recent bars to use for the calculation of supporter")
bool shouldDisplay = last_bar_index - bar_index < generalLen
//-----------------------------------------------------------------------------}
//-----------------------------------------------------------------------------*
// Volume Profile
//-----------------------------------------------------------------------------*
// Settings
//-----------------------------------------------------------------------------{
string vpGrp = "Volume Profile"
bool vpShowed = input.bool(false, "Show", group = vpGrp)
int vpLen = input.int(200, "Lookback", minval = 1, maxval = 500, tooltip = "Number of most recent bars", group = vpGrp)
int vpLevelsSize = input.int(360, "Size Of Levels", minval = 1, maxval = 400, group = vpGrp)
int vpWidth = input.int(16, "Profile's Width", minval = 1, maxval = 100, tooltip = "The length of the bars relative to the Lookback value", group = vpGrp)
int vpBarWidth = input.int(2, "Bar's Width", tooltip = "Width of each bar", group = vpGrp)
int vpOffset = input.int(20, "Offset From Last Bar", group = vpGrp)
color vpColor = input.color(DARK_GRAY_COLOR, "Color", group = vpGrp)
//-----------------------------------------------------------------------------}
// Render Volume Profile
//-----------------------------------------------------------------------------{
var vpLines = array.new_line()
if barstate.isfirst
for i = 0 to vpLevelsSize - 1
array.push(vpLines, line.new(na, na, na, na, width = 2))
series float vpHighest = ta.highest(vpLen)
series float vpLowest = ta.lowest(vpLen)
array<float> vpLevels = array.new_float(0)
array<int> vpVols = array.new_int(0)
array<float> vpSumv = array.new_float(0)
line vpLine = na
if barstate.islast and vpShowed
for i = 0 to vpLevelsSize
array.push(vpLevels, vpLowest + i / vpLevelsSize * (vpHighest - vpLowest))
for i = 0 to vpLevelsSize - 1
series float sum = 0.
for j = 0 to vpLen - 1
sum := high[j] > array.get(vpLevels, i) and low[j] < array.get(vpLevels, i + 1) ? sum + volume[j] : sum
array.push(vpSumv, sum)
for i = 0 to vpLevelsSize - 1
series float mult = array.get(vpSumv, i) / array.max(vpSumv)
series int vol = math.round(vpLen * vpWidth / 100 * mult)
array.push(vpVols, vol)
series int maxVol = array.max(vpVols)
int shift = barIdx + maxVol + vpOffset
for i = 0 to vpLevelsSize - 1
series int vol = array.get(vpVols, i)
series float level = array.get(vpLevels, i)
vpLine := array.get(vpLines, i)
line.set_xy1(vpLine, shift, level)
line.set_xy2(vpLine, shift - vol, level)
line.set_color(vpLine, vpColor)
line.set_width(vpLine, vpBarWidth)
//-----------------------------------------------------------------------------}
//-----------------------------------------------------------------------------*
// Killzones
//------------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------{
string kzGrp = "Killzones"
bool kzShowed = input.bool(false, "Show", group = kzGrp)
bool kzLabelsShowed = input.bool(false, "Show Labels", group = kzGrp)
// New York
bool kzNyShowed = input.bool(true, "New York", inline = "ny", group = kzGrp)
color kzNyColor = input.color(color.new(YELLOW_COLOR, 96), "", inline = "ny", group = kzGrp)
// London Open
bool kzLdnoShowed = input.bool(true, "London Open", inline = "ldno", group = kzGrp)
color kzLdnoColor = input.color(color.new(AQUA_COLOR, 96), "", inline = "ldno", group = kzGrp)
// London Close
bool kzLdncShowed = input.bool(true, "London Close", inline = "ldnc", group = kzGrp)
color kzLdncColor = input.color(color.new(RED_COLOR, 96), "", inline = "ldnc", group = kzGrp)
// Asian
bool kzAsianShowed = input.bool(true, "Asian", inline = "asian", group = kzGrp)
color kzAsiaColor = input.color(color.new(PURPLE_COLOR, 96), "", inline = "asian", group = kzGrp)
//-----------------------------------------------------------------------------}
// Functions
//-----------------------------------------------------------------------------{
showKzLabels(bool session, color css, string txt)=>
var label lbl = na
var float max = na
var int anchor = na
var getCss = color.rgb(color.r(css), color.g(css), color.b(css))
if session and not session[1]
max := high
anchor := time
lbl := label.new(anchor, max
, txt
, xloc.bar_time
, color = #ffffff00
, style = label.style_label_down
, textcolor = getCss
, size = size.small)
if session
max := math.max(high, max)
label.set_x(lbl, int(math.avg(time - (time[1] - time[5]) / 5, anchor)))
label.set_y(lbl, max)
//-----------------------------------------------------------------------------}
// Retracements
//-----------------------------------------------------------------------------{
bool isKzNySession = time(timeframe.period, "0700-0900", "UTC-5") and kzShowed and kzNyShowed and shouldDisplay
bool isKzLdnoSession = time(timeframe.period, "0200-0500", "UTC-5") and kzShowed and kzLdnoShowed and shouldDisplay
bool isKzLdncSession = time(timeframe.period, "1000-1200", "UTC-5") and kzShowed and kzLdncShowed and shouldDisplay
bool isKzAsianSession = time(timeframe.period, "2000-0000", "UTC-5") and kzShowed and kzAsianShowed and shouldDisplay
//-----------------------------------------------------------------------------}
// Labels
//-----------------------------------------------------------------------------{
showKzLabels(kzLabelsShowed and isKzNySession, kzNyColor, "New York")
showKzLabels(kzLabelsShowed and isKzLdnoSession, kzLdnoColor, "London Open")
showKzLabels(kzLabelsShowed and isKzLdncSession, kzLdncColor, "London Close")
showKzLabels(kzLabelsShowed and isKzAsianSession, kzAsiaColor, "Asian")
//-----------------------------------------------------------------------------}
// Background
//-----------------------------------------------------------------------------{
bgcolor(isKzNySession ? kzNyColor : na, editable = false)
bgcolor(isKzLdnoSession ? kzLdnoColor : na, editable = false)
bgcolor(isKzLdncSession ? kzLdncColor : na, editable = false)
bgcolor(isKzAsianSession ? kzAsiaColor : na, editable = false)
//-----------------------------------------------------------------------------}
//-----------------------------------------------------------------------------*
// Smart Money Concepts
//-----------------------------------------------------------------------------*
// Tooltips
//-----------------------------------------------------------------------------{
string MODE_TOOLTIP = "Allows to display historical Structure or only the recent ones"
string STYLE_TOOLTIP = "Indicator color theme"
string COLOR_CANDLES_TOOLTIP = "Display additional candles with a color reflecting the current trend detected by structure"
string SHOW_INTERNAL = "Display internal market structure"
string CONFLUENCE_FILTER = "Filter non significant internal structure breakouts"
string SHOW_SWING = "Display swing market Structure"
string SHOW_SWING_POINTS = "Display swing point as labels on the chart"
string SHOW_SWHL_POINTS = "Highlight most recent strong and weak high/low points on the chart"
string INTERNAL_OB = 'Display internal order blocks on the chart\n\nNumber of internal order blocks to display on the chart'
string SWING_OB = 'Display swing order blocks on the chart\n\nNumber of internal swing blocks to display on the chart'
string FILTER_OB = 'Method used to filter out volatile order blocks \n\nIt is recommended to use the cumulative mean range method when a low amount of data is available'
string SHOW_EQHL = "Display equal highs and equal lows on the chart"
string EQHL_BARS = "Number of bars used to confirm equal highs and equal lows"
string EQHL_THRESHOLD = "Sensitivity threshold in a range (0, 1) used for the detection of equal highs & lows\n\nLower values will return fewer but more pertinent results"
string SHOW_FVG = "Display fair values gaps on the chart"
string AUTO_FVG = "Filter out non significant fair value gaps"
string FVG_TF = "Fair value gaps timeframe"
string EXTEND_FVG = "Determine how many bars to extend the Fair Value Gap boxes on chart"
string PED_ZONES = "Display premium, discount, and equilibrium zones on chart"
//-----------------------------------------------------------------------------}
// Settings
//-----------------------------------------------------------------------------{
// General
//----------------------------------------{
string mode = input.string("Historical"
, options = ["Historical", "Present"]
, group = "Smart Money Concepts"
, tooltip = MODE_TOOLTIP)
bool trendShowed = input.bool(false, "Color Candles"
, group = "Smart Money Concepts"
, tooltip = COLOR_CANDLES_TOOLTIP)
//----------------------------------------}
// Internal Structure
//----------------------------------------{
bool iStructureShowed = input.bool(true, "Show Internal Structure"
, group = "Real Time Internal Structure"
, tooltip = SHOW_INTERNAL)
string iBullShowed = input.string("All", "Bullish Structure"
, options = ["All", "BOS", "CHoCH"]
, inline = "ibull"
, group = "Real Time Internal Structure")
color iBullColor = input.color(AQUA_COLOR, ""
, inline = "ibull"
, group = "Real Time Internal Structure")
string iBearShowed = input.string("All", "Bearish Structure"
, options = ["All", "BOS", "CHoCH"]
, inline = "ibear"
, group = "Real Time Internal Structure")
color iBearColor = input.color(RED_COLOR, ""
, inline = "ibear"
, group = "Real Time Internal Structure")
bool iConfluenceFiltered = input.bool(true, "Confluence Filter"
, group = "Real Time Internal Structure"
, tooltip = CONFLUENCE_FILTER)
int internalLen = input.int(5, ""
, minval = 2
, maxval = 10
, inline = "swings"
, group = "Real Time Swing Structure")
string iStructureSize = input.string("Tiny", "Internal Label Size"
, options = ["Tiny", "Small", "Normal"]
, group = "Real Time Internal Structure")
//----------------------------------------}
// Swing Structure
//----------------------------------------{
bool sStructureShowed = input.bool(true, "Show Swing Structure"
, group = "Real Time Swing Structure"
, tooltip = SHOW_SWING)
string sBullShowed = input.string("All", "Bullish Structure"
, options = ["All", "BOS", "CHoCH"]
, inline = "bull"
, group = "Real Time Swing Structure")
color sBullColor = input.color(AQUA_COLOR, ""
, inline = "bull"
, group = "Real Time Swing Structure")
string sBearShowed = input.string("All", "Bearish Structure"
, options = ["All", "BOS", "CHoCH"]
, inline = "bear"
, group = "Real Time Swing Structure")
color sBearColor = input.color(RED_COLOR, ""
, inline = "bear"
, group = "Real Time Swing Structure")
string sStructureSize = input.string("Small", "Swing Label Size"
, options = ["Tiny", "Small", "Normal"]
, group = "Real Time Swing Structure")
bool swingsPointsShowed = input.bool(false, "Show Swings Points"
, inline = "swings"
, group = "Real Time Swing Structure"
, tooltip = SHOW_SWING_POINTS)
int swingLen = input.int(50, ""
, minval = 10
, inline = "swings"
, group = "Real Time Swing Structure")
bool hlSwingsShowed = input.bool(true, "Show Strong/Weak High/Low"
, group = "Real Time Swing Structure"
, tooltip = SHOW_SWHL_POINTS)
//----------------------------------------}
// Order Blocks
//----------------------------------------{
string obGrp = "Order Blocks"
bool iobShowed = input.bool(true, 'Internal Order Blocks', inline = 'iob', group = obGrp, tooltip = INTERNAL_OB)
int numOfIobs = input.int(5, '', minval = 1, inline = 'iob', group = obGrp)
bool sobShowed = input.bool(false, 'Swing Order Blocks', inline = 'ob', group = obGrp, tooltip = SWING_OB)
int numOfSobs = input.int(5, '', minval = 1, inline = 'ob', group = obGrp)
string obFilter = input.string('Atr', 'Order Block Filter', options = ['Atr', 'Cumulative Mean Range'], group = obGrp, tooltip = FILTER_OB)
color obBullishColor = input.color(BLOCK_COLOR, "", inline = "ob1", group = obGrp)
color obBearishColor = input.color(BLOCK_COLOR, "", inline = "ob1", group = obGrp)
var iobTop = array.new_float(0)
var iobBtm = array.new_float(0)
var iobLeft = array.new_int(0)
var iobType = array.new_int(0)
var obTop = array.new_float(0)
var obBtm = array.new_float(0)
var obLeft = array.new_int(0)
var obType = array.new_int(0)
//----------------------------------------}
// Liquidity Levels
//----------------------------------------{
string llGrp = "Liquidity Levels"
bool llShowed = input.bool(true, title = "Showed", group = llGrp, inline = "1")
var llTf = input.timeframe("", title = "Timeframe", group = llGrp, inline = "2")
int llPivotLen = input.int(8, title = "Pivot Length", group = llGrp, inline = "3")
int llMaxLevels = input.int(6, title = "Max Levels", group = llGrp, inline = "4")
color llSellSideColor = input.color(color.new(AQUA_COLOR, 50), "", group = llGrp, inline = "1")
color llBuySideColor = input.color(color.new(RED_COLOR, 50), "", group = llGrp, inline = "1")
float llBoxWidth = 1
series float llAtrLiq = ta.atr(300)
float llTholdLiq = llAtrLiq * llBoxWidth / 10
//----------------------------------------}
// EQH/EQL
//----------------------------------------{
bool eqShowed = input.bool(false, "Equal High/Low"
, group = "EQH/EQL"
, tooltip = SHOW_EQHL)
int eqLen = input.int(3, "Bars Confirmation"
, minval = 1
, group = "EQH/EQL"
, tooltip = EQHL_BARS)
float eqThreshold = input.float(0.1, "Threshold"
, minval = 0
, maxval = 0.5
, step = 0.1
, group = "EQH/EQL"
, tooltip = EQHL_THRESHOLD)
string eqSize = input.string("Tiny", "Label Size"
, options = ["Tiny", "Small", "Normal"]
, group = "EQH/EQL")
//----------------------------------------}
// Fair Value Gaps
//----------------------------------------{
bool fvgShowed = input.bool(true, "Fair Value Gaps"
, group = "Fair Value Gaps"
, tooltip = SHOW_FVG)
bool fvgAuto = input.bool(true, "Auto Threshold"
, group = "Fair Value Gaps"
, tooltip = AUTO_FVG)
var fvgTf = input.timeframe("", "Timeframe"
, group = "Fair Value Gaps"
, tooltip = FVG_TF)
color fvgBullColor = input.color(color.new(AQUA_COLOR, 70), "Bullish FVG"
, group = "Fair Value Gaps")
color fvgBearColor = input.color(color.new(RED_COLOR, 70), "Bearish FVG"
, group = "Fair Value Gaps")
int fvgExtend = input.int(1, "Extend FVG"
, minval = 0
, group = "Fair Value Gaps"
, tooltip = EXTEND_FVG)
//----------------------------------------}
// Previous day/week high/low
//----------------------------------------{
// Daily
bool pdhlShowed = input.bool(false, "Daily"
, inline = "daily"
, group = "Highs & Lows MTF")
string pdhlStyle = input.string("⎯⎯⎯", ""
, options = ["⎯⎯⎯", "----", "····"]
, inline = "daily"
, group = "Highs & Lows MTF")
color pdhlColor = input.color(TXT_COLOR, ""
, inline = "daily"
, group = "Highs & Lows MTF")
// Weekly
bool pwhlShowed = input.bool(false, "Weekly"
, inline = "weekly"
, group = "Highs & Lows MTF")
string pwhlStyle = input.string("⎯⎯⎯", ""
, options = ["⎯⎯⎯", "----", "····"]
, inline = "weekly"
, group = "Highs & Lows MTF")
color pwhlColor = input.color(TXT_COLOR, ""
, inline = "weekly"
, group = "Highs & Lows MTF")
// Monthly
bool pmhlShowed = input.bool(false, "Monthly"
, inline = "monthly"
, group = "Highs & Lows MTF")
string pmhlStyle = input.string("⎯⎯⎯", ""
, options = ["⎯⎯⎯", "----", "····"]
, inline = "monthly"
, group = "Highs & Lows MTF")
color pmhlColor = input.color(TXT_COLOR, ""
, inline = "monthly"
, group = "Highs & Lows MTF")
//----------------------------------------}
// Premium/Discount zones
//----------------------------------------{
bool pdzShowed = input.bool(false, "Premium/Discount Zones", group = "Premium & Discount Zones", tooltip = PED_ZONES)
color pdzBgColor = input.color(BLOCK_COLOR, "Background Color", group = "Premium & Discount Zones")
color pdzTextColor = input.color(TXT_COLOR, "Text Color", group = "Premium & Discount Zones")
//-----------------------------------------------------------------------------}
// Functions
//-----------------------------------------------------------------------------{
series float atr = ta.atr(200)
series float cmean_range = ta.cum(high - low) / barIdx
// Order block coordinates function
getObCoord(bool maxUsed, series int loc, array<float> targetTop, array<float> targetBtm, array<int> targetLeft, array<int> targetType) =>
float min = 99999999.
float max = 0.
int idx = 1
series float ob_threshold = obFilter == 'Atr' ? atr : cmean_range
// Search for highest/lowest high within the structure interval and get range
if maxUsed
for i = 1 to (barIdx - loc)-1
if (high[i] - low[i]) < ob_threshold[i] * 2
max := math.max(high[i], max)
min := max == high[i] ? low[i] : min
idx := max == high[i] ? i : idx
else
for i = 1 to (barIdx - loc)-1
if (high[i] - low[i]) < ob_threshold[i] * 2
min := math.min(low[i], min)
max := min == low[i] ? high[i] : max
idx := min == low[i] ? i : idx
array.unshift(targetTop, max)
array.unshift(targetBtm, min)
array.unshift(targetLeft, time[idx])
array.unshift(targetType, maxUsed ? -1 : 1)
displayOb(array<box> boxes, array<float> targetTop, array<float> targetBtm, array<int> targetLeft, array<int> targetType, int lastShowed, bool swing, series int size) =>
for i = 0 to math.min(lastShowed - 1, size - 1)
box box = array.get(boxes, i)
box.set_lefttop(box, array.get(targetLeft, i), array.get(targetTop, i))
box.set_rightbottom(box, BAR_TIME_RIGHT_ALIGNMENT, array.get(targetBtm, i))
color contractionColor = na
if swing
contractionColor := array.get(targetType, i) == 1 ? obBullishColor : obBearishColor
box.set_border_color(box, contractionColor)
box.set_bgcolor(box, contractionColor)
else
contractionColor := array.get(targetType, i) == 1 ? obBullishColor : obBearishColor
box.set_border_color(box, contractionColor)
box.set_bgcolor(box, contractionColor)
getHL() => [high, low]
getOHLC() => [close[1], open[1], high, low, high[2], low[2]]
displayStructure(series int x, series float y, string txt, color color, bool dashed, bool down, string lblSize) =>
line structureLine = line.new(x, y, barIdx, y, color = color, style = dashed ? line.style_dashed : line.style_solid)
label structureLbl = label.new(int(math.avg(x, barIdx)), y, txt, color = TRANSPARENT_COLOR, textcolor = color, style = down ? label.style_label_down : label.style_label_up, size = lblSize)
if mode == "Present"
line.delete(structureLine[1])
label.delete(structureLbl[1])
getSwings(int len) =>
var os = 0
series float upper = ta.highest(len)
series float lower = ta.lowest(len)
os := high[len] > upper ? 0 : low[len] < lower ? 1 : os[1]
float top = os == 0 and os[1] != 0 ? high[len] : 0
float btm = os == 1 and os[1] != 1 ? low[len] : 0
[top, btm]
getLineStyle(string style) =>
string out = switch style
"⎯⎯⎯" => line.style_solid
"----" => line.style_dashed
"····" => line.style_dotted
getPHL(series float h, series float l, string tf, color css) =>
var line highLine = line.new(na,na,na,na
, xloc = xloc.bar_time
, color = css
, style = getLineStyle(pdhlStyle))
var label highLbl = label.new(na,na
, xloc = xloc.bar_time
, text = str.format("P{0}H", tf)
, color = TRANSPARENT_COLOR
, textcolor = css
, size = size.small
, style = label.style_label_left)
var line lowLine = line.new(na,na,na,na
, xloc = xloc.bar_time
, color = css
, style = getLineStyle(pdhlStyle))
var label lowLbl = label.new(na,na
, xloc = xloc.bar_time
, text = str.format("P{0}L", tf)
, color = TRANSPARENT_COLOR
, textcolor = css
, size = size.small
, style = label.style_label_left)
series float hy = ta.valuewhen(h != h[1], h, 1)
series int hx = ta.valuewhen(h == high, time, 1)
series float ly = ta.valuewhen(l != l[1], l, 1)
series int lx = ta.valuewhen(l == low, time, 1)
if barstate.islast
// High
line.set_xy1(highLine, hx, hy)
line.set_xy2(highLine, BAR_TIME_RIGHT_ALIGNMENT, hy)
label.set_xy(highLbl, BAR_TIME_RIGHT_ALIGNMENT, hy)
// Low
line.set_xy1(lowLine, lx, ly)
line.set_xy2(lowLine, BAR_TIME_RIGHT_ALIGNMENT, ly)
label.set_xy(lowLbl, BAR_TIME_RIGHT_ALIGNMENT, ly)
//-----------------------------------------------------------------------------}
// Global variables
//-----------------------------------------------------------------------------{
var trend = 0, var itrend = 0
var topY = 0., var topX = 0
var btmY = 0., var btmX = 0
var iTopY = 0., var iTopX = 0
var iBtmY = 0., var iBtmX = 0
var trailUp = high, var trailDn = low
var trailUpX = 0, var trailDnX = 0
var topCross = true, var btmCross = true
var iTopCross = true, var iBtmCross = true
var txtTop = "", var txtBtm = ""
// Structure colors
var bull_css = sBullColor
var bear_css = sBearColor
var ibull_css = iBullColor
var ibear_css = iBearColor
// Labels size
var internal_structureLblSize = iStructureSize == "Tiny"
? size.tiny
: iStructureSize == "Small"
? size.small
: size.normal
var swing_structureLblSize = sStructureSize == "Tiny"
? size.tiny
: sStructureSize == "Small"
? size.small
: size.normal
var eqhl_lblSize = eqSize == "Tiny"
? size.tiny
: eqSize == "Small"
? size.small
: size.normal
// Swings
[top, btm] = getSwings(swingLen)
[itop, ibtm] = getSwings(internalLen)
//-----------------------------------------------------------------------------}
// Pivot High
//-----------------------------------------------------------------------------{
var line extendTop = na
var label extendTopLbl = label.new(na, na
, color = TRANSPARENT_COLOR
, textcolor = bear_css
, style = label.style_label_down
, size = size.tiny)
if top
topCross := true
txtTop := top > topY ? "HH" : "LH"
if swingsPointsShowed
top_lbl = label.new(barIdx - swingLen, top, txtTop
, color = TRANSPARENT_COLOR
, textcolor = bear_css
, style = label.style_label_down
, size = swing_structureLblSize)
if mode == "Present"
label.delete(top_lbl[1])
// Extend recent top to last bar
line.delete(extendTop[1])
series int xOffset = barIdx - swingLen
extendTop := line.new(xOffset, top, barIdx, top, color = bear_css)
topY := top
topX := xOffset
trailUp := top
trailUpX := xOffset
if itop
iTopCross := true
iTopY := itop
iTopX := barIdx - internalLen
// Trailing maximum
trailUp := math.max(high, trailUp)
trailUpX := trailUp == high ? barIdx : trailUpX
// Set top extension label/line
if barstate.islast and hlSwingsShowed
line.set_xy1(extendTop, trailUpX, trailUp)
line.set_xy2(extendTop, BAR_IDX_RIGHT_ALIGNMENT, trailUp)
label.set_x(extendTopLbl, BAR_IDX_RIGHT_ALIGNMENT)
label.set_y(extendTopLbl, trailUp)
label.set_text(extendTopLbl, trend < 0 ? "Strong High" : "Weak High")
//-----------------------------------------------------------------------------}
// Pivot Low
//-----------------------------------------------------------------------------{
var line extend_btm = na
var label extend_btm_lbl = label.new(na, na
, color = TRANSPARENT_COLOR
, textcolor = bull_css
, style = label.style_label_up
, size = size.tiny)
if btm
btmCross := true
txtBtm := btm < btmY ? "LL" : "HL"
if swingsPointsShowed
btm_lbl = label.new(barIdx - swingLen, btm, txtBtm
, color = TRANSPARENT_COLOR
, textcolor = bull_css
, style = label.style_label_up
, size = swing_structureLblSize)
if mode == "Present"
label.delete(btm_lbl[1])
// Extend recent btm to last bar
series int xOffset = barIdx - swingLen
line.delete(extend_btm[1])
extend_btm := line.new(xOffset, btm, barIdx, btm, color = bull_css)
btmY := btm
btmX := xOffset
trailDn := btm
trailDnX := xOffset
if ibtm
iBtmCross := true
iBtmY := ibtm
iBtmX := barIdx - internalLen
// Trailing minimum
trailDn := math.min(low, trailDn)
trailDnX := trailDn == low ? barIdx : trailDnX
// Set btm extension label/line
if barstate.islast and hlSwingsShowed
line.set_xy1(extend_btm, trailDnX, trailDn)
line.set_xy2(extend_btm, BAR_IDX_RIGHT_ALIGNMENT, trailDn)
label.set_x(extend_btm_lbl, BAR_IDX_RIGHT_ALIGNMENT)
label.set_y(extend_btm_lbl, trailDn)
label.set_text(extend_btm_lbl, trend > 0 ? "Strong Low" : "Weak Low")
//-----------------------------------------------------------------------------}
// Pivot High BOS/CHoCH
//-----------------------------------------------------------------------------{
// Filtering
var bullConcordant = true
if iConfluenceFiltered
bullConcordant := high - math.max(close, open) > math.min(close, open - low)
// Detect internal bullish Structure
if ta.crossover(close, iTopY) and iTopCross and topY != iTopY and bullConcordant
bool choch = na
if itrend < 0
choch := true
txt = choch ? "CHoCH" : "BOS"
if iStructureShowed
if (iBullShowed == "All" or (iBullShowed == "BOS" and not choch) or (iBullShowed == "CHoCH" and choch)) and shouldDisplay
displayStructure(iTopX, iTopY, txt, ibull_css, true, true, internal_structureLblSize)
iTopCross := false
itrend := 1
// Internal Order Block
if iobShowed
getObCoord(false, iTopX, iobTop, iobBtm, iobLeft, iobType)
// Detect bullish Structure
if ta.crossover(close, topY) and topCross
bool choch = na
if trend < 0
choch := true
txt = choch ? "CHoCH" : "BOS"
if sStructureShowed
if (sBullShowed == "All" or (sBullShowed == "BOS" and not choch) or (sBullShowed == "CHoCH" and choch)) and shouldDisplay
displayStructure(topX, topY, txt, bull_css, false, true, swing_structureLblSize)
topCross := false
trend := 1
// Order Block
if sobShowed
getObCoord(false, topX, obTop, obBtm, obLeft, obType)
//-----------------------------------------------------------------------------}
// Pivot Low BOS/CHoCH
//-----------------------------------------------------------------------------{
var bear_concordant = true
if iConfluenceFiltered
bear_concordant := high - math.max(close, open) < math.min(close, open - low)
// Detect internal bearish Structure
if ta.crossunder(close, iBtmY) and iBtmCross and btmY != iBtmY and bear_concordant
bool choch = false
if itrend > 0
choch := true
string txt = choch ? "CHoCH" : "BOS"
if iStructureShowed
if (iBearShowed == "All" or (iBearShowed == "BOS" and not choch) or (iBearShowed == "CHoCH" and choch)) and shouldDisplay
displayStructure(iBtmX, iBtmY, txt, ibear_css, true, false, internal_structureLblSize)
iBtmCross := false
itrend := -1
// Internal Order Block
if iobShowed
getObCoord(true, iBtmX, iobTop, iobBtm, iobLeft, iobType)
// Detect bearish Structure
if ta.crossunder(close, btmY) and btmCross
bool choch = na
if trend > 0
choch := true
string txt = choch ? "CHoCH" : "BOS"
if sStructureShowed
if (sBearShowed == "All" or (sBearShowed == "BOS" and not choch) or (sBearShowed == "CHoCH" and choch)) and shouldDisplay
displayStructure(btmX, btmY, txt, bear_css, false, false, swing_structureLblSize)
btmCross := false
trend := -1
// Order Block
if sobShowed
getObCoord(true, btmX, obTop, obBtm, obLeft, obType)
//-----------------------------------------------------------------------------}
// Order Blocks
//-----------------------------------------------------------------------------{
// Set order blocks
var iobBoxes = array.new_box(0)
var obBoxes = array.new_box(0)
// Delete internal order blocks box coordinates if top/bottom is broken
for element in iobType
series int idx = array.indexof(iobType, element)
if close < array.get(iobBtm, idx) and element == 1
array.remove(iobTop, idx)
array.remove(iobBtm, idx)
array.remove(iobLeft, idx)
array.remove(iobType, idx)
else if close > array.get(iobTop, idx) and element == -1
array.remove(iobTop, idx)
array.remove(iobBtm, idx)
array.remove(iobLeft, idx)
array.remove(iobType, idx)
// Delete internal order blocks box coordinates if top/bottom is broken
for element in obType
series int idx = array.indexof(obType, element)
if close < array.get(obBtm, idx) and element == 1
array.remove(obTop, idx)
array.remove(obBtm, idx)
array.remove(obLeft, idx)
array.remove(obType, idx)
else if close > array.get(obTop, idx) and element == -1
array.remove(obTop, idx)
array.remove(obBtm, idx)
array.remove(obLeft, idx)
array.remove(obType, idx)
series int iobSize = array.size(iobType)
series int obSize = array.size(obType)
if barstate.isfirst
if iobShowed
for i = 0 to numOfIobs - 1
array.push(iobBoxes, box.new(na,na,na,na, xloc = xloc.bar_time))
if sobShowed
for i = 0 to numOfSobs - 1
array.push(obBoxes, box.new(na,na,na,na, xloc = xloc.bar_time))
if iobSize > 0
if barstate.islast
displayOb(iobBoxes, iobTop, iobBtm, iobLeft, iobType, numOfIobs, false, iobSize)
if obSize > 0
if barstate.islast
displayOb(obBoxes, obTop, obBtm, obLeft, obType, numOfSobs, true, obSize)
//-----------------------------------------------------------------------------}
// Liquidity Levels
//-----------------------------------------------------------------------------{
getTfMulti(string tf) =>
simple int ts = timeframe.in_seconds("")
series int htfs = timeframe.in_seconds(tf)
htfs / ts
shiftLimitBox(array<box> arr) =>
if array.size(arr) > llMaxLevels / 2
box.delete(array.shift(arr))
extendBoxToCurrent(array<box> arr) =>
if array.size(arr) > 0
for i = array.size(arr) - 1 to 0 by 1
box.set_right(array.get(arr, i), BAR_TIME_RIGHT_ALIGNMENT)
removeMitigatedBoxes(array<box> arr, string hl) =>
bool removed = false
if array.size(arr) > 0
for i = array.size(arr) - 1 to 0 by 1
series box l = array.get(arr, i)
series float hh = close[1]
series float ll = close[1]
if hl == "High" and hh > box.get_top(l)
array.remove(arr, i)
box.delete(l)
removed := true
if hl == "Low" and ll < box.get_top(l)
array.remove(arr, i)
box.delete(l)
removed := true
shiftLimitBox(arr)
removed
[_llTime, _llOpen, _llHigh, _llLow, _llClose] = request.security(syminfo.tickerid, llTf, [time, open, high, low, close])
series float llPivotHigh = ta.pivothigh(_llHigh, llPivotLen * getTfMulti(llTf), llPivotLen + getTfMulti(llTf))
series float llPivotLow = ta.pivotlow(_llLow, llPivotLen * getTfMulti(llTf), llPivotLen + getTfMulti(llTf))
var llHtfHighBoxes = array.new_box()
var llHtfLowBoxes = array.new_box()
if llShowed
series float displacement = llPivotLen + getTfMulti(llTf)
if not na(llPivotHigh)
series float yOffset = _llHigh[displacement] - llTholdLiq
array.push(llHtfHighBoxes, box.new(_llTime[displacement], _llHigh[displacement], _llTime[+1], yOffset, bgcolor = llBuySideColor, border_color = color.new(llBuySideColor, 80), xloc = xloc.bar_time, border_style = line.style_solid, extend = extend.none, border_width = 2, text_halign = text.align_center, text_color = WHITE_COLOR, text_size = size.small))
if not na(llPivotLow)
series float yOffset = _llLow[displacement] + llTholdLiq
array.push(llHtfLowBoxes, box.new(_llTime[displacement], _llLow[displacement], _llTime[+1], yOffset, bgcolor = llSellSideColor, border_color = color.new(llSellSideColor, 80), xloc = xloc.bar_time, border_style = line.style_solid, extend = extend.none, border_width = 2, text_halign = text.align_center, text_color = WHITE_COLOR, text_size = size.small))
removeMitigatedBoxes(llHtfHighBoxes, "High")
removeMitigatedBoxes(llHtfLowBoxes, "Low")
extendBoxToCurrent(llHtfHighBoxes)
extendBoxToCurrent(llHtfLowBoxes)
//-----------------------------------------------------------------------------}
// EQH/EQL
//-----------------------------------------------------------------------------{
var eqPrevTop = 0.
var eqTopX = 0
var eqPrevBtm = 0.
var eqBtmX = 0
if eqShowed
series float eqTop = ta.pivothigh(eqLen, eqLen)
series float eqBtm = ta.pivotlow(eqLen, eqLen)
if not na(eqTop)
max = math.max(eqTop, eqPrevTop)
min = math.min(eqTop, eqPrevTop)
if max < min + atr * eqThreshold and shouldDisplay
eqhLine = line.new(eqTopX, eqPrevTop, barIdx - eqLen, eqTop
, color = bear_css
, style = line.style_dotted)
eqhLbl = label.new(int(math.avg(barIdx - eqLen, eqTopX)), eqTop, "EQH"
, color = #00000000
, textcolor = bear_css
, style = label.style_label_down
, size = eqhl_lblSize)
if mode == "Present"
line.delete(eqhLine[1])
label.delete(eqhLbl[1])
eqPrevTop := eqTop
eqTopX := barIdx - eqLen
if not na(eqBtm)
max = math.max(eqBtm, eqPrevBtm)
min = math.min(eqBtm, eqPrevBtm)
if min > max - atr * eqThreshold and shouldDisplay
eqlLine = line.new(eqBtmX, eqPrevBtm, barIdx - eqLen, eqBtm
, color = bull_css
, style = line.style_dotted)
eqlLbl = label.new(int(math.avg(barIdx - eqLen, eqBtmX)), eqBtm, "EQL"
, color = #00000000
, textcolor = bull_css
, style = label.style_label_up
, size = eqhl_lblSize)
if mode == "Present"
line.delete(eqlLine[1])
label.delete(eqlLbl[1])
eqPrevBtm := eqBtm
eqBtmX := barIdx - eqLen
//-----------------------------------------------------------------------------}
// Fair Value Gaps
//-----------------------------------------------------------------------------{
var bullishFvgMax = array.new_box(0)
var bullishFvgMin = array.new_box(0)
var bearishFvgMax = array.new_box(0)
var bearishFvgMin = array.new_box(0)
float bullishFvgAvg = na
float bearishFvgAvg = na
bool bullishFvgCond = false
bool bearishFvgCond = false
[srcC1, srcO1, srcH, srcL, srcH2, srcL2] = request.security(syminfo.tickerid, fvgTf, getOHLC())
if fvgShowed
series float delta = (srcC1 - srcO1) / srcO1 * 100
series bool tfChanged = timeframe.change(fvgTf)
series float threshold = fvgAuto ? ta.cum(math.abs(tfChanged ? delta : 0)) / barIdx * 2 : 0
// FVG conditions
bullishFvgCond := srcL > srcH2
and srcC1 > srcH2
and delta > threshold
and tfChanged
bearishFvgCond := srcH < srcL2
and srcC1 < srcL2
and -delta > threshold
and tfChanged
// FVG Areas
if bullishFvgCond and shouldDisplay
array.unshift(bullishFvgMax, box.new(barIdx - 1, srcL, barIdx + fvgExtend, math.avg(srcL, srcH2)
, border_color = fvgBullColor
, bgcolor = fvgBullColor))
array.unshift(bullishFvgMin, box.new(barIdx - 1, math.avg(srcL, srcH2), barIdx + fvgExtend, srcH2
, border_color = fvgBullColor
, bgcolor = fvgBullColor))
if bearishFvgCond and shouldDisplay
array.unshift(bearishFvgMax, box.new(barIdx - 1, srcH, barIdx + fvgExtend, math.avg(srcH, srcL2)
, border_color = fvgBearColor
, bgcolor = fvgBearColor))
array.unshift(bearishFvgMin, box.new(barIdx - 1, math.avg(srcH, srcL2), barIdx + fvgExtend, srcL2
, border_color = fvgBearColor
, bgcolor = fvgBearColor))
for bx in bullishFvgMin
if low < box.get_bottom(bx)
box.delete(bx)
box.delete(array.get(bullishFvgMax, array.indexof(bullishFvgMin, bx)))
for bx in bearishFvgMax
if high > box.get_top(bx)
box.delete(bx)
box.delete(array.get(bearishFvgMin, array.indexof(bearishFvgMax, bx)))
//-----------------------------------------------------------------------------}
// Previous day/week high/lows
//-----------------------------------------------------------------------------{
// Daily high/low
[pdh, pdl] = request.security(syminfo.tickerid, "D", getHL()
, lookahead = barmerge.lookahead_on)
// Weekly high/low
[pwh, pwl] = request.security(syminfo.tickerid, "W", getHL()
, lookahead = barmerge.lookahead_on)
// Monthly high/low
[pmh, pml] = request.security(syminfo.tickerid, "M", getHL()
, lookahead = barmerge.lookahead_on)
// Display Daily
if pdhlShowed
getPHL(pdh, pdl, "D", pdhlColor)
// Display Weekly
if pwhlShowed
getPHL(pwh, pwl, "W", pwhlColor)
// Display Monthly
if pmhlShowed
getPHL(pmh, pml, "M", pmhlColor)
//-----------------------------------------------------------------------------}
// Premium/Discount/Equilibrium zones
//-----------------------------------------------------------------------------{
var premium = box.new(na, na, na, na, bgcolor = pdzBgColor, border_color = pdzBgColor, border_width = 2)
var premiumLbl = label.new(na, na
, text = "Premium"
, color = TRANSPARENT_COLOR
, textcolor = pdzTextColor
, style = label.style_label_down
, size = size.small)
var eq = box.new(na, na, na, na, bgcolor = pdzBgColor, border_color = pdzBgColor, border_width = 2)
var eqLbl = label.new(na, na
, text = "Equilibrium"
, color = TRANSPARENT_COLOR
, textcolor = pdzTextColor
, style = label.style_label_left
, size = size.small)
var discount = box.new(na, na, na, na, bgcolor = pdzBgColor, border_color = pdzBgColor, border_width = 2)
var discountLbl = label.new(na, na
, text = "Discount"
, color = TRANSPARENT_COLOR
, textcolor = pdzTextColor
, style = label.style_label_up
, size = size.small)
// Show Premium/Discount Areas
if barstate.islast and pdzShowed
// TODO
series float avg = math.avg(trailUp, trailDn)
box.set_lefttop(premium, math.max(topX, btmX), trailUp)
box.set_rightbottom(premium, BAR_IDX_RIGHT_ALIGNMENT, .95 * trailUp + .05 * trailDn)
label.set_xy(premiumLbl, int(math.avg(math.max(topX, btmX), BAR_IDX_RIGHT_ALIGNMENT)), trailUp)
box.set_lefttop(eq, math.max(topX, btmX), .525 * trailUp + .475*trailDn)
box.set_rightbottom(eq, BAR_IDX_RIGHT_ALIGNMENT, .525 * trailDn + .475 * trailUp)
label.set_xy(eqLbl, BAR_IDX_RIGHT_ALIGNMENT, avg)
box.set_lefttop(discount, math.max(topX, btmX), .95 * trailDn + .05 * trailUp)
box.set_rightbottom(discount, BAR_IDX_RIGHT_ALIGNMENT, trailDn)
label.set_xy(discountLbl, int(math.avg(math.max(topX, btmX), BAR_IDX_RIGHT_ALIGNMENT)), trailDn)
//-----------------------------------------------------------------------------}
// Trend
//-----------------------------------------------------------------------------{
var color trendColor = na
if trendShowed
trendColor := itrend == 1 ? bull_css : bear_css
plotcandle(open, high, low, close, color = trendColor, wickcolor = trendColor, bordercolor = trendColor, editable = false)
//-----------------------------------------------------------------------------}
//-----------------------------------------------------------------------------*
// OTE
//-----------------------------------------------------------------------------*
// Settings
//-----------------------------------------------------------------------------{
string oteGrp = "OTE"
bool oteShowed = input.bool(false, "Show", group = oteGrp)
string oteDepthTooltip = "The minimum number of bars that will be taken into account when calculating the indicator."
int oteDepth = input.int(10, "Depth", group = oteGrp, tooltip = oteDepthTooltip)
string oteDevTooltip = "Deviation is a multiplier that affects how much the price should deviate from the previous pivot in order for the bar to become a new pivot."
float oteThresholdMultiplier = input.float(3, "Deviation", group = oteGrp, tooltip = oteDevTooltip)
color oteColor = input.color(YELLOW_COLOR, "Color", group = oteGrp)
//-----------------------------------------------------------------------------}
// Types
//-----------------------------------------------------------------------------{
type Settings
float devThreshold = 3
int depth = 10
type Point
int unixTime
float price
type Pivot
bool isHigh
float vol
Point start
Point end
type ZigZag
Settings settings
array<Pivot> pivots
float volTotal = 0
Pivot extend = na
//-----------------------------------------------------------------------------}
// Methods
//-----------------------------------------------------------------------------{
findPivotPoint(series float src, series float len, simple bool isHigh) =>
float pivot = nz(src[len])
if len == 0
Point.new(time, pivot)
else if len * 2 <= bar_index
bool found = true
for i = 0 to math.abs(len - 1)
if (isHigh and src[i] > pivot) or (not isHigh and src[i] < pivot)
found := false
break
for i = len + 1 to 2 * len
if (isHigh and src[i] >= pivot) or (not isHigh and src[i] <= pivot)
found := false
break
if found
Point.new(time[len], pivot)
calcDev(series float basePrice, series float price) =>
float result = 100 * (price - basePrice) / math.abs(basePrice)
method updatePivot(Pivot this, Point end, float vol, Settings settings) =>
this.end := end
this.vol := vol
getNewPivot(series Point start, series Point end, series float vol, series bool isHigh, series Settings settings) =>
Pivot pivot = Pivot.new(isHigh, vol, start, end)
pivot.updatePivot(end, vol, settings)
pivot
method isPriceHigher(series Pivot this, series Point point) =>
int mult = this.isHigh ? 1 : -1
point.price * mult > this.end.price * mult
method getLastPivot(series ZigZag this) =>
int size = this.pivots.size()
size > 0 ? this.pivots.get(size - 1) : na
method updateLastPivot(series ZigZag this, series Point point) =>
Pivot lastPivot = this.getLastPivot()
if this.pivots.size() == 1
lastPivot.start := point
lastPivot.updatePivot(point, lastPivot.vol + this.volTotal, this.settings)
this.volTotal := 0
method addNewPivot(series ZigZag this, series Pivot pivot) =>
this.pivots.push(pivot)
this.volTotal := 0
method hasNewPivotPointFound(series ZigZag this, simple bool isHigh, series Point point) =>
bool found = false
Pivot lastPivot = this.getLastPivot()
if not na(lastPivot)
if lastPivot.isHigh == isHigh
if lastPivot.isPriceHigher(point)
this.updateLastPivot(point)
found := true
else
float dev = calcDev(lastPivot.end.price, point.price)
if (not lastPivot.isHigh and dev >= this.settings.devThreshold) or (lastPivot.isHigh and dev <= -1 * this.settings.devThreshold)
this.addNewPivot(getNewPivot(lastPivot.end, point, this.volTotal, isHigh, this.settings))
found := true
else
this.addNewPivot(getNewPivot(point, point, this.volTotal, isHigh, this.settings))
found := true
found
method findPivot(series ZigZag this, series float src, simple bool isHigh, series int depth, series bool pivotRegistered = true) =>
Point point = findPivotPoint(src, depth, isHigh)
not na(point) and pivotRegistered ? this.hasNewPivotPointFound(isHigh, point) : false
method updateZigzag(series ZigZag this, series float vols, series float highVal, series float lowVal, series int timeVal) =>
int depth = math.max(2, math.floor(this.settings.depth / 2))
this.volTotal += nz(vols[depth])
bool updated = this.findPivot(highVal, true, depth)
updated := this.findPivot(lowVal, false, depth, not updated) or updated
Pivot lastPivot = this.getLastPivot()
float remVol = math.sum(vols, math.max(depth, 1))
if barstate.islast and not na(lastPivot)
bool isHigh = not lastPivot.isHigh
float curSeries = isHigh ? highVal : lowVal
Point end = Point.new(timeVal, curSeries)
if na(this.extend) or updated
this.extend := getNewPivot(lastPivot.end, end, this.volTotal, isHigh, this.settings)
this.extend.updatePivot(end, this.volTotal + remVol, this.settings)
updated
initZigzag(series Settings settings = na) =>
ZigZag result = ZigZag.new(na(settings) ? Settings.new() : settings, array.new<Pivot>())
getOTEVals(series float close_val, series float vol_val, series float highVal, series float lowVal, series int timeVal) =>
var settings = Settings.new(oteThresholdMultiplier, oteDepth)
var ZigZag zigzagInstance = initZigzag(settings)
var Pivot lastPivot = na
var float startPrice = na
var float height = na
settings.devThreshold := ta.atr(10) / close_val * 100 * oteThresholdMultiplier
if zigzagInstance.updateZigzag(vol_val, highVal, lowVal, timeVal)
lastPivot := zigzagInstance.getLastPivot()
if not na(lastPivot)
var line lastLine = na
if na(lastLine) and oteShowed
lastLine := line.new(lastPivot.start.unixTime, lastPivot.start.price, lastPivot.end.unixTime, lastPivot.end.price, xloc = xloc.bar_time, color = color.new(oteColor, 20), width = 1, style = line.style_dashed)
else
line.set_xy1(lastLine, lastPivot.start.unixTime, lastPivot.start.price)
line.set_xy2(lastLine, lastPivot.end.unixTime, lastPivot.end.price)
startPrice := lastPivot.end.price
endPrice = lastPivot.start.price
height := (startPrice > endPrice ? -1 : 1) * math.abs(startPrice - endPrice)
[lastPivot, startPrice, height]
[oteLastPivot, oteStartPrice, oteHeight] = getOTEVals(close, volume, high, low, time)
drawFibLevel(Pivot pivot, float level, color color) =>
var line fibLine = na, line.delete(fibLine)
fibLine := line.new(pivot.start.unixTime, level, BAR_TIME_RIGHT_ALIGNMENT, level, color = color, width = 1, xloc = xloc.bar_time, extend = extend.none)
fibLine
processFibLevel(Pivot pivot, series float startPrice, series float height, simple float val, color color) =>
float level = startPrice + height * val
if not na(pivot)
line fibLine = drawFibLevel(pivot, level, color)
[level, fibLine]
else
na
getPrdWidthByPerc(int prd, int perc) => (ta.highest(prd) - ta.lowest(prd)) * perc / 100
getTfTxt() =>
string prd = timeframe.period
string tf = na
if str.contains(prd, "S")
tf := str.length(prd) == 1 ? "1S" : prd
else if str.contains(prd, "D")
tf := str.length(prd) == 1 ? "1D" : prd
else if str.contains(prd, "W")
tf := str.length(prd) == 1 ? "1W" : prd
else if str.contains(prd, "M")
tf := str.length(prd) == 1 ? "1M" : prd
else
float mins = str.tonumber(prd)
if mins >= 60
tf := str.format("{0}H", mins / 60)
else
tf := str.format("{0}M", mins)
tf
//-----------------------------------------------------------------------------}
// Plots
//-----------------------------------------------------------------------------{
if oteShowed
[retracement1, retracement1Line] = processFibLevel(oteLastPivot, oteStartPrice, oteHeight, 0.618, color.new(oteColor, 20))
[OTE, OTELine] = processFibLevel(oteLastPivot, oteStartPrice, oteHeight, 0.705, color.new(oteColor, 40))
[retracement2, retracement2Line] = processFibLevel(oteLastPivot, oteStartPrice, oteHeight, 0.79, color.new(oteColor, 20))
if barstate.islast
linefill.new(retracement1Line, retracement2Line, color = color.new(oteColor, 95))
float middle = (math.abs(retracement1 - retracement2) / 2) + (retracement1 > retracement2 ? retracement2 : retracement1)
var label oteLabel = na, label.delete(oteLabel)
oteLabel := label.new(BAR_TIME_RIGHT_ALIGNMENT, middle, xloc = xloc.bar_time, text = "OTE", color = TRANSPARENT_COLOR, textcolor = YELLOW_COLOR, size = size.small, style = label.style_label_left)
//-----------------------------------------------------------------------------}
Show all 1,350 lines