OPEN-SOURCE SCRIPT
gex levels Rafael

//version=5
indicator("GEX Levels (10-slot, symbol-specific)", overlay=true, max_lines_count=500, max_labels_count=500)
//===========================
// User inputs (10 slots)
//===========================
slotSym1 = input.string("IREN", "Slot 1 Symbol")
slotDat1 = input.string('IREN: Key Delta, 20.0, Implied Movement -2σ, 43.83, Implied Movement -σ, 47.97, Implied Movement +2σ, 62.15, Put Dominate , 41.0, Large Gamma 1 & Gamma Field CE & Call Wall & Call Wall CE, 55.0, Put Wall & Large Gamma 2 & Gamma Field, 50.0, Implied Movement +σ, 58.01, Call Dominate , 57.0, Put Wall CE & Gamma Flip & Gamma Flip CE, 43.5,', "Slot 1 Data")
slotSym2 = input.string("", "Slot 2 Symbol")
slotDat2 = input.string("", "Slot 2 Data")
slotSym3 = input.string("", "Slot 3 Symbol")
slotDat3 = input.string("", "Slot 3 Data")
slotSym4 = input.string("", "Slot 4 Symbol")
slotDat4 = input.string("", "Slot 4 Data")
slotSym5 = input.string("", "Slot 5 Symbol")
slotDat5 = input.string("", "Slot 5 Data")
slotSym6 = input.string("", "Slot 6 Symbol")
slotDat6 = input.string("", "Slot 6 Data")
slotSym7 = input.string("", "Slot 7 Symbol")
slotDat7 = input.string("", "Slot 7 Data")
slotSym8 = input.string("", "Slot 8 Symbol")
slotDat8 = input.string("", "Slot 8 Data")
slotSym9 = input.string("", "Slot 9 Symbol")
slotDat9 = input.string("", "Slot 9 Data")
slotSym10 = input.string("", "Slot 10 Symbol")
slotDat10 = input.string("", "Slot 10 Data")
showOnlyOnMatch = input.bool(true, "Show only when chart symbol matches a slot?")
labelOnRight = input.bool(true, "Show labels on right")
extendRight = input.bool(true, "Extend lines to the right")
lineWidth = input.int(2, "Line width", minval=1, maxval=4)
labelOffsetBars = input.int(30, "Label offset (bars to the right)", minval=5, maxval=300)
//===========================
// Helpers
//===========================
trim(s) =>
// Safe trim
str.trim(s)
containsCI(hay, needle) =>
str.contains(str.lower(hay), str.lower(needle))
// Decide color based on label keywords
levelColor(lbl) =>
// You can tune this mapping to match your old indicator’s palette
containsCI(lbl, "key delta") ? color.new(color.red, 0) :
containsCI(lbl, "gamma flip") ? color.new(color.fuchsia, 0) :
containsCI(lbl, "put wall") ? color.new(color.purple, 0) :
containsCI(lbl, "call wall") ? color.new(color.orange, 0) :
containsCI(lbl, "put dominate") ? color.new(color.yellow, 0) :
containsCI(lbl, "call dominate") ? color.new(color.teal, 0) :
containsCI(lbl, "implied movement") ? color.new(color.blue, 0) :
color.new(color.gray, 0)
//===========================
// Pick active slot by chart symbol
//===========================
chartSym = syminfo.ticker // e.g. "IREN" on most US stocks
getSlotData() =>
string sym = ""
string dat = ""
if chartSym == trim(slotSym1) and trim(slotSym1) != ""
sym := trim(slotSym1), dat := slotDat1
else if chartSym == trim(slotSym2) and trim(slotSym2) != ""
sym := trim(slotSym2), dat := slotDat2
else if chartSym == trim(slotSym3) and trim(slotSym3) != ""
sym := trim(slotSym3), dat := slotDat3
else if chartSym == trim(slotSym4) and trim(slotSym4) != ""
sym := trim(slotSym4), dat := slotDat4
else if chartSym == trim(slotSym5) and trim(slotSym5) != ""
sym := trim(slotSym5), dat := slotDat5
else if chartSym == trim(slotSym6) and trim(slotSym6) != ""
sym := trim(slotSym6), dat := slotDat6
else if chartSym == trim(slotSym7) and trim(slotSym7) != ""
sym := trim(slotSym7), dat := slotDat7
else if chartSym == trim(slotSym8) and trim(slotSym8) != ""
sym := trim(slotSym8), dat := slotDat8
else if chartSym == trim(slotSym9) and trim(slotSym9) != ""
sym := trim(slotSym9), dat := slotDat9
else if chartSym == trim(slotSym10) and trim(slotSym10) != ""
sym := trim(slotSym10), dat := slotDat10
[sym, dat]
//===========================
// Parse "label, value, label, value, ..."
//===========================
parsePairs(raw) =>
// Split by comma, then step through tokens 2 at a time.
// Expect format: label, number, label, number, ...
string[] t = str.split(raw, ",")
int n = array.size(t)
string[] outLabels = array.new_string()
float[] outValues = array.new_float()
for i = 0 to n - 1
array.set(t, i, trim(array.get(t, i)))
for i = 0 to n - 2
if i % 2 == 0
string lbl = array.get(t, i)
string valS = array.get(t, i + 1)
// Skip empty label/value
if lbl != "" and valS != ""
float v = str.tonumber(valS)
if not na(v)
// Optional: remove leading "SYMBOL:" prefix from label
// e.g. "IREN: Key Delta" -> "Key Delta"
string cleaned = lbl
int colonPos = str.pos(cleaned, ":")
if colonPos != -1
cleaned := trim(str.substring(cleaned, colonPos + 1, str.length(cleaned)))
array.push(outLabels, cleaned)
array.push(outValues, v)
[outLabels, outValues]
//===========================
// Drawing state
//===========================
var line[] lines = array.new_line()
var label[] labels = array.new_label()
var string lastRaw = ""
// Delete all existing drawings
clearAll() =>
for i = 0 to array.size(lines) - 1
line.delete(array.get(lines, i))
for i = 0 to array.size(labels) - 1
label.delete(array.get(labels, i))
array.clear(lines)
array.clear(labels)
// Draw levels
drawLevels(sym, raw) =>
[lbls, vals] = parsePairs(raw)
int m = array.size(lbls)
// Build on last bar only to reduce clutter and avoid heavy redraw
if barstate.islast
clearAll()
// If user wants strict symbol match, and no slot matched, show nothing
bool ok = (sym != "")
if not showOnlyOnMatch
ok := true
if ok
int x1 = bar_index
int x2 = bar_index + (extendRight ? 200 : 1)
for i = 0 to m - 1
string lbl = array.get(lbls, i)
float y = array.get(vals, i)
color c = levelColor(lbl)
// Line
line ln = line.new(x1, y, x2, y, extend=extendRight ? extend.right : extend.none, color=c, width=lineWidth)
array.push(lines, ln)
// Label (right side)
if labelOnRight
int lx = bar_index + labelOffsetBars
string text = lbl + " (" + str.tostring(y) + ")"
label la = label.new(lx, y, text=text, style=label.style_label_left, textcolor=color.white, color=color.new(c, 0))
array.push(labels, la)
//===========================
// Main
//===========================
[sym, raw] = getSlotData()
// If not matched but user wants to still show something, fallback to slot1
if not showOnlyOnMatch and sym == ""
sym := trim(slotSym1)
raw := slotDat1
// Redraw only when raw changes (or first run); still rebuild on last bar to keep labels aligned
if raw != lastRaw
lastRaw := raw
drawLevels(sym, raw)
indicator("GEX Levels (10-slot, symbol-specific)", overlay=true, max_lines_count=500, max_labels_count=500)
//===========================
// User inputs (10 slots)
//===========================
slotSym1 = input.string("IREN", "Slot 1 Symbol")
slotDat1 = input.string('IREN: Key Delta, 20.0, Implied Movement -2σ, 43.83, Implied Movement -σ, 47.97, Implied Movement +2σ, 62.15, Put Dominate , 41.0, Large Gamma 1 & Gamma Field CE & Call Wall & Call Wall CE, 55.0, Put Wall & Large Gamma 2 & Gamma Field, 50.0, Implied Movement +σ, 58.01, Call Dominate , 57.0, Put Wall CE & Gamma Flip & Gamma Flip CE, 43.5,', "Slot 1 Data")
slotSym2 = input.string("", "Slot 2 Symbol")
slotDat2 = input.string("", "Slot 2 Data")
slotSym3 = input.string("", "Slot 3 Symbol")
slotDat3 = input.string("", "Slot 3 Data")
slotSym4 = input.string("", "Slot 4 Symbol")
slotDat4 = input.string("", "Slot 4 Data")
slotSym5 = input.string("", "Slot 5 Symbol")
slotDat5 = input.string("", "Slot 5 Data")
slotSym6 = input.string("", "Slot 6 Symbol")
slotDat6 = input.string("", "Slot 6 Data")
slotSym7 = input.string("", "Slot 7 Symbol")
slotDat7 = input.string("", "Slot 7 Data")
slotSym8 = input.string("", "Slot 8 Symbol")
slotDat8 = input.string("", "Slot 8 Data")
slotSym9 = input.string("", "Slot 9 Symbol")
slotDat9 = input.string("", "Slot 9 Data")
slotSym10 = input.string("", "Slot 10 Symbol")
slotDat10 = input.string("", "Slot 10 Data")
showOnlyOnMatch = input.bool(true, "Show only when chart symbol matches a slot?")
labelOnRight = input.bool(true, "Show labels on right")
extendRight = input.bool(true, "Extend lines to the right")
lineWidth = input.int(2, "Line width", minval=1, maxval=4)
labelOffsetBars = input.int(30, "Label offset (bars to the right)", minval=5, maxval=300)
//===========================
// Helpers
//===========================
trim(s) =>
// Safe trim
str.trim(s)
containsCI(hay, needle) =>
str.contains(str.lower(hay), str.lower(needle))
// Decide color based on label keywords
levelColor(lbl) =>
// You can tune this mapping to match your old indicator’s palette
containsCI(lbl, "key delta") ? color.new(color.red, 0) :
containsCI(lbl, "gamma flip") ? color.new(color.fuchsia, 0) :
containsCI(lbl, "put wall") ? color.new(color.purple, 0) :
containsCI(lbl, "call wall") ? color.new(color.orange, 0) :
containsCI(lbl, "put dominate") ? color.new(color.yellow, 0) :
containsCI(lbl, "call dominate") ? color.new(color.teal, 0) :
containsCI(lbl, "implied movement") ? color.new(color.blue, 0) :
color.new(color.gray, 0)
//===========================
// Pick active slot by chart symbol
//===========================
chartSym = syminfo.ticker // e.g. "IREN" on most US stocks
getSlotData() =>
string sym = ""
string dat = ""
if chartSym == trim(slotSym1) and trim(slotSym1) != ""
sym := trim(slotSym1), dat := slotDat1
else if chartSym == trim(slotSym2) and trim(slotSym2) != ""
sym := trim(slotSym2), dat := slotDat2
else if chartSym == trim(slotSym3) and trim(slotSym3) != ""
sym := trim(slotSym3), dat := slotDat3
else if chartSym == trim(slotSym4) and trim(slotSym4) != ""
sym := trim(slotSym4), dat := slotDat4
else if chartSym == trim(slotSym5) and trim(slotSym5) != ""
sym := trim(slotSym5), dat := slotDat5
else if chartSym == trim(slotSym6) and trim(slotSym6) != ""
sym := trim(slotSym6), dat := slotDat6
else if chartSym == trim(slotSym7) and trim(slotSym7) != ""
sym := trim(slotSym7), dat := slotDat7
else if chartSym == trim(slotSym8) and trim(slotSym8) != ""
sym := trim(slotSym8), dat := slotDat8
else if chartSym == trim(slotSym9) and trim(slotSym9) != ""
sym := trim(slotSym9), dat := slotDat9
else if chartSym == trim(slotSym10) and trim(slotSym10) != ""
sym := trim(slotSym10), dat := slotDat10
[sym, dat]
//===========================
// Parse "label, value, label, value, ..."
//===========================
parsePairs(raw) =>
// Split by comma, then step through tokens 2 at a time.
// Expect format: label, number, label, number, ...
string[] t = str.split(raw, ",")
int n = array.size(t)
string[] outLabels = array.new_string()
float[] outValues = array.new_float()
for i = 0 to n - 1
array.set(t, i, trim(array.get(t, i)))
for i = 0 to n - 2
if i % 2 == 0
string lbl = array.get(t, i)
string valS = array.get(t, i + 1)
// Skip empty label/value
if lbl != "" and valS != ""
float v = str.tonumber(valS)
if not na(v)
// Optional: remove leading "SYMBOL:" prefix from label
// e.g. "IREN: Key Delta" -> "Key Delta"
string cleaned = lbl
int colonPos = str.pos(cleaned, ":")
if colonPos != -1
cleaned := trim(str.substring(cleaned, colonPos + 1, str.length(cleaned)))
array.push(outLabels, cleaned)
array.push(outValues, v)
[outLabels, outValues]
//===========================
// Drawing state
//===========================
var line[] lines = array.new_line()
var label[] labels = array.new_label()
var string lastRaw = ""
// Delete all existing drawings
clearAll() =>
for i = 0 to array.size(lines) - 1
line.delete(array.get(lines, i))
for i = 0 to array.size(labels) - 1
label.delete(array.get(labels, i))
array.clear(lines)
array.clear(labels)
// Draw levels
drawLevels(sym, raw) =>
[lbls, vals] = parsePairs(raw)
int m = array.size(lbls)
// Build on last bar only to reduce clutter and avoid heavy redraw
if barstate.islast
clearAll()
// If user wants strict symbol match, and no slot matched, show nothing
bool ok = (sym != "")
if not showOnlyOnMatch
ok := true
if ok
int x1 = bar_index
int x2 = bar_index + (extendRight ? 200 : 1)
for i = 0 to m - 1
string lbl = array.get(lbls, i)
float y = array.get(vals, i)
color c = levelColor(lbl)
// Line
line ln = line.new(x1, y, x2, y, extend=extendRight ? extend.right : extend.none, color=c, width=lineWidth)
array.push(lines, ln)
// Label (right side)
if labelOnRight
int lx = bar_index + labelOffsetBars
string text = lbl + " (" + str.tostring(y) + ")"
label la = label.new(lx, y, text=text, style=label.style_label_left, textcolor=color.white, color=color.new(c, 0))
array.push(labels, la)
//===========================
// Main
//===========================
[sym, raw] = getSlotData()
// If not matched but user wants to still show something, fallback to slot1
if not showOnlyOnMatch and sym == ""
sym := trim(slotSym1)
raw := slotDat1
// Redraw only when raw changes (or first run); still rebuild on last bar to keep labels aligned
if raw != lastRaw
lastRaw := raw
drawLevels(sym, raw)
Open-source script
In true TradingView spirit, the creator of this script has made it open-source, so that traders can review and verify its functionality. Kudos to the author! While you can use it for free, remember that republishing the code is subject to our House Rules.
Disclaimer
The information and publications are not meant to be, and do not constitute, financial, investment, trading, or other types of advice or recommendations supplied or endorsed by TradingView. Read more in the Terms of Use.
Open-source script
In true TradingView spirit, the creator of this script has made it open-source, so that traders can review and verify its functionality. Kudos to the author! While you can use it for free, remember that republishing the code is subject to our House Rules.
Disclaimer
The information and publications are not meant to be, and do not constitute, financial, investment, trading, or other types of advice or recommendations supplied or endorsed by TradingView. Read more in the Terms of Use.