indicator_template.pine
//@version=6
indicator("euroPRO Express • TV-Port (v6++) — FIP Layout • Card UI • Config FIBs • License", overlay=true, max_bars_back=5000)
// =================== Inputs / Card Controls ===================
session_day = input.session("0700-2200", "Tag-Session")
session_night = input.session("2200-0700", "Nacht-Session (ĂĽber Mitternacht)")
tz = input.string("Europe/Berlin", "Zeitzone")
// Zielbereiche (Nacht/Vortag) & Filter
ui_scope = input.string("V", "Zielbereiche", options=["N","V"], tooltip="N = Nacht (22–07), V = Vortag (07–22).")
ui_showFilter = input.bool(true, "Filter (MA/Fill anzeigen)", tooltip="Ein-/Ausblenden der Filterdarstellung (MA1–MA5 & Fill).")
// Filter-Längen
len_ma1 = input.int(34, "MA1 (WMA) Trend", minval=1)
len_ma2 = input.int(5 , "MA2 (WMA)", minval=1)
len_ma3 = input.int(34, "MA3 (WMA)", minval=1)
len_ma5 = input.int(8 , "MA5 (SMA(MA2-MA3))", minval=1)
// FIP Einstellungen
show_live_today = input.bool(true, "Heutige Session-Range (HL) anzeigen")
anchor_mode = input.string("PrevClose", "FIP Anker",
options = ["PrevClose", "PrevMid(H/L)", "TodayOpen", "PrevLow", "PrevHigh"],
tooltip = "Referenz, um die FIP-Level zu spiegeln.")
// =================== Konfigurierbare FIBO-Level ===================
fibs_pos_input = input.string("0,23.6,38.2,50,61.8,76.4,100,141.4,161.8,261.8,423.6", "FIBO Levels (oberhalb, +)", tooltip="Kommagetrennte Liste. 23.6 = 0.236, 423.6 = 4.236 usw.")
fibs_neg_input = input.string("-41.4,-61.8,-161.8,-323.6", "FIBO Levels (unterhalb, -)", tooltip="Kommagetrennte Liste. -61.8 = -0.618 usw.")
// Parser
f_parse_fibs(strlist, bool percentMode) =>
string s = str.replace_all(strlist, " ", "")
s := str.replace_all(s, ";", ",")
s := str.replace_all(s, ",", ",")
string[] parts = str.split(s, ",")
float[] out = array.new_float()
for i = 0 to array.size(parts) - 1
string tok = array.get(parts, i)
tok := str.replace_all(tok, ",", ".")
float v = str.tonumber(tok)
if not na(v)
if percentMode
v := v / 100.0
array.push(out, v)
out
float[] fib_pos = f_parse_fibs(fibs_pos_input, fibs_percent_mode)
float[] fib_neg = f_parse_fibs(fibs_neg_input, fibs_percent_mode)
// =================== Lightweight License (client-side) ===================
// Pine hat keine HTTP-Requests → für harte Paywall Invite-Only verwenden.
license_customer_id = input.string("", "Lizenz-ID (nur Ziffern)")
license_key = input.string("", "LizenzschlĂĽssel (letzte 6 Ziffern = PrĂĽfsumme)")
license_expires_ymd = input.int(20991231, "Lizenz gĂĽltig bis (YYYYMMDD)")
const_saltA = 137
const_saltB = 9973
const_saltC = 7919
const_mod = 1000000.0 // 6-stellige PrĂĽfsumme
f_digits_only(s) =>
string out = ""
int L = str.length(s)
for i = 0 to L - 1
string ch = str.substring(s, i, i + 1)
float d = str.tonumber(ch)
if not na(d)
out += ch
out
f_hash_digits(s) =>
float h = 0.0
string ds = f_digits_only(s)
int L = str.length(ds)
for i = 0 to L - 1
float d = str.tonumber(str.substring(ds, i, i + 1))
h := math.fmod(h * const_saltA + d * (i + const_saltB) + const_saltC, 1e12)
h
f_expected_check(idStr, expiryYmd) =>
float h1 = f_hash_digits(idStr)
float h2 = f_hash_digits(str.tostring(expiryYmd))
int chk = int(math.round(math.fmod(h1 * 97.0 + h2 * 193.0 + const_saltA * const_saltB + const_saltC, const_mod)))
chk
f_key_last6(keyStr) =>
string k = f_digits_only(keyStr)
int Lk = str.length(k)
int start = math.max(Lk - 6, 0)
string tail = str.substring(k, start, Lk)
int val = int(str.tonumber(tail))
val
// AblaufprĂĽfung (Berlin-Zeit)
t_bln_license = request.security(syminfo.tickerid, "1", time("1", "0000-2359", tz), barmerge.gaps_off, barmerge.lookahead_off)
int today_ymd = year(t_bln_license) * 10000 + month(t_bln_license) * 100 + dayofmonth(t_bln_license)
bool not_expired = today_ymd <= license_expires_ymd
int expected = f_expected_check(license_customer_id, license_expires_ymd)
int provided = f_key_last6(license_key)
bool license_ok = (not_expired and expected == provided)
// Hinweis-Overlay bei fehlender Lizenz
var label licWarn = na
if barstate.islast
if not license_ok
if na(licWarn)
licWarn := label.new(bar_index, close, xloc=xloc.bar_index, yloc=yloc.price,
text="Lizenz ungĂĽltig oder abgelaufen.\nBitte gĂĽltige Daten eingeben.",
style=label.style_label_center, color=color.new(color.red, 0), textcolor=color.white, size=size.large)
else
label.set_x(licWarn, bar_index),
label.set_text(licWarn, "Lizenz ungĂĽltig oder abgelaufen.\nBitte gĂĽltige Daten eingeben.")
else
if not na(licWarn)
label.delete(licWarn), licWarn := na
// =================== Session-Engine (M1 backbone) ===================
tfSess = "1"
in_day_m1 = request.security(syminfo.tickerid, tfSess, not na(time(timeframe.period, session_day, tz)), barmerge.gaps_off, barmerge.lookahead_off)
in_night_m1 = request.security(syminfo.tickerid, tfSess, not na(time(timeframe.period, session_night, tz)), barmerge.gaps_off, barmerge.lookahead_off)
day_start_m1 = in_day_m1 and not in_day_m1[1]
day_end_m1 = not in_day_m1 and in_day_m1[1]
night_start_m1= in_night_m1 and not in_night_m1[1]
// M1 Basiserien global
close_m1 = request.security(syminfo.tickerid, tfSess, close, barmerge.gaps_off, barmerge.lookahead_off)
open_m1 = request.security(syminfo.tickerid, tfSess, open, barmerge.gaps_off, barmerge.lookahead_off)
high_m1 = request.security(syminfo.tickerid, tfSess, high, barmerge.gaps_off, barmerge.lookahead_off)
low_m1 = request.security(syminfo.tickerid, tfSess, low, barmerge.gaps_off, barmerge.lookahead_off)
// =================== Range-Tracking ===================
var float day_hi_m1 = na
var float day_lo_m1 = na
var float prev_day_hi = na
var float prev_day_lo = na
var float prev_day_close = na
var float prev_day_range = na
var float today_open_m1 = na
if day_start_m1
prev_day_hi := day_hi_m1
prev_day_lo := day_lo_m1
today_open_m1 := open_m1
day_hi_m1 := high_m1
day_lo_m1 := low_m1
else if in_day_m1
day_hi_m1 := na(day_hi_m1) ? high_m1 : math.max(day_hi_m1, high_m1)
day_lo_m1 := na(day_lo_m1) ? low_m1 : math.min(day_lo_m1, low_m1)
if day_end_m1
prev_day_close := close_m1[1]
prev_day_range := (not na(day_hi_m1) and not na(day_lo_m1)) ? (day_hi_m1 - day_lo_m1) : prev_day_range
// Nacht (22–07)
var float night_hi_m1 = na
var float night_lo_m1 = na
var float prev_night_range = na
if night_start_m1
prev_night_range := (not na(night_hi_m1) and not na(night_lo_m1)) ? (night_hi_m1 - night_lo_m1) : prev_night_range
night_hi_m1 := high_m1
night_lo_m1 := low_m1
else if in_night_m1
night_hi_m1 := na(night_hi_m1) ? high_m1 : math.max(night_hi_m1, high_m1)
night_lo_m1 := na(night_lo_m1) ? low_m1 : math.min(night_lo_m1, low_m1)
if day_start_m1 and na(prev_night_range) and not na(night_hi_m1) and not na(night_lo_m1)
prev_night_range := night_hi_m1 - night_lo_m1
// =================== Filter (Chart-TF) ===================
ma1 = ta.wma(close, len_ma1)
ma2 = ta.wma(close, len_ma2)
ma3 = ta.wma(close, len_ma3)
ma4 = ma2 - ma3
ma5 = ta.sma(ma4, len_ma5)
bull = close >= ma1 and ma4 >= ma5
bear = close < ma1 and ma4 < ma5
showFilter = ui_showFilter and license_ok
p_ma2 = plot(showFilter ? ma2 : na, display=display.none)
p_ma3 = plot(showFilter ? ma3 : na, display=display.none)
fillColor = showFilter ? (bear ? color.new(color.red, 60) : color.new(color.blue, 50)) : na
fill(p_ma2, p_ma3, color=fillColor)
bgCol = showFilter ? (bear ? color.new(color.red, 88) : bull ? color.new(color.blue, 88) : na) : na
bgcolor(bgCol)
plot(showFilter ? ma1 : na, "MA1 Trend", color=bull ? color.new(color.blue, 50) : color.new(color.red, 0), linewidth=2)
float today_hi_series = (show_live_today and in_day_m1 and license_ok) ? day_hi_m1 : na
float today_lo_series = (show_live_today and in_day_m1 and license_ok) ? day_lo_m1 : na
plot(today_hi_series, "Heute High", color=color.new(color.blue, 50), style=plot.style_linebr)
plot(today_lo_series, "Heute Low", color=color.new(color.red, 40), style=plot.style_linebr)
// =================== Zeitfenster (07:00–22:00) ===================
t_bln_day = request.security(syminfo.tickerid, tfSess, time("1", "0000-2359", tz), barmerge.gaps_off, barmerge.lookahead_off)
year_bln = year(t_bln_day)
month_bln = month(t_bln_day)
day_bln = dayofmonth(t_bln_day)
tsStart = timestamp(tz, year_bln, month_bln, day_bln, 7, 0)
tsEnd = timestamp(tz, year_bln, month_bln, day_bln, 22, 0)
// =================== Draw-Logic & Zielbereiche (N/V) ===================
var bool did_draw_today = false
if day_start_m1
did_draw_today := false
prev_day_hi := day_hi_m1
prev_day_lo := day_lo_m1
should_draw_now = license_ok and (day_start_m1 or (in_day_m1 and not did_draw_today))
var line[] proj_lines = array.new_line()
f_clear_all() =>
while array.size(proj_lines) > 0
line.delete(array.pop(proj_lines))
if should_draw_now
f_clear_all()
range_selected = ui_scope == "N" ? prev_night_range : prev_day_range
float anchor = switch anchor_mode
"PrevClose" => prev_day_close
"PrevMid(H/L)" => (not na(prev_day_hi) and not na(prev_day_lo)) ? (prev_day_hi + prev_day_lo) / 2.0 : na
"TodayOpen" => today_open_m1
"PrevLow" => prev_day_lo
"PrevHigh" => prev_day_hi
=> na
bool ok = not na(anchor) and not na(range_selected) and range_selected > 0
if ok
color colBlue = color.new(color.blue, 0)
color colOrca = color.new(color.black, 0)
int wThin = 1
int wOrca = 2
// Positive Levels (inkl. 0/100)
for i = 0 to array.size(fib_pos) - 1
float mul = array.get(fib_pos, i)
float level = anchor + mul * range_selected
bool isOrca = (mul == 0.0) or (math.abs(mul - 1.0) < 0.000001)
color col = isOrca ? colOrca : colBlue
int w = isOrca ? wOrca : wThin
array.push(proj_lines, line.new(tsStart, level, tsEnd, level, xloc=xloc.bar_time, extend=extend.none, color=col, width=w))
// Negative Levels (unterhalb)
for i = 0 to array.size(fib_neg) - 1
float mulN = array.get(fib_neg, i)
float levelN = anchor + mulN * range_selected
array.push(proj_lines, line.new(tsStart, levelN, tsEnd, levelN, xloc=xloc.bar_time, extend=extend.none, color=colBlue, width=wThin))
did_draw_today := true
// =================== Minimal Card-UI (Statusanzeige) ===================
var table card = table.new(position.top_right, 6, 2, border_width=1)
f_cell(c, r, txt, bgcol, txtcol) =>
table.cell(card, c, r, txt, text_color=txtcol, bgcolor=bgcol, text_halign=text.align_center, text_valign=text.align_center)
if barstate.islast
color colLic = license_ok ? color.new(color.green, 60) : color.new(color.red, 20)
f_cell(0, 0, "euroPRO", color.new(color.blue, 80), color.white)
f_cell(1, 0, "Lizenz", color.new(color.gray, 85), color.white)
f_cell(3, 0, "Zielbereiche", color.new(color.gray, 85), color.white)
f_cell(5, 0, "Filter", color.new(color.gray, 85), color.white)
f_cell(1, 1, license_ok ? "OK" : "NEIN", colLic, color.white)
color colN = ui_scope == "N" ? color.new(color.blue, 60) : color.new(color.gray, 90)
color colV = ui_scope == "V" ? color.new(color.blue, 60) : color.new(color.gray, 90)
f_cell(3, 1, "N", colN, color.white)
f_cell(4, 1, "V", colV, color.white)
color colFilt = ui_showFilter ? color.new(color.blue, 60) : color.new(color.gray, 90)
f_cell(5, 1, "Filter", colFilt, color.white)
{{LICENSE_KEY}}