# Reverse Pulse System FractalTP – Strategy Description for TradingView
---
## Overview
**Reverse Pulse System FractalTP** is a variant of the Reverse Pulse sweep-and-reverse system with **Fractal-based Take-Profit**. Instead of a fixed R:R, the TP can target the next fractal level—the nearest resistance (long) or support (short).
- **Type:** Mean-reversion / Sweep-reversal
- **Timeframe:** M5 (recommended)
- **Instruments:** XAUUSD, EURUSD, and similar liquid pairs
- **Session:** 09:00–17:00 (Europe/Berlin, DST-safe)
- **Non-repainting:** Closed-bar logic, no lookahead bias
---
## Concept
1. **Trend Bias (H1):** Supertrend on H1 with body-break confirmation—long setups only when bias is long, short setups only when bias is short.
2. **POI Level:** Fractal highs (short bias) or fractal lows (long bias) define the key levels to watch.
3. **Sweep:** Price breaks the POI level (wick) but reverses back.
4. **Entry:** "Attempted Candle"—the candle that prints the new extreme and confirms reversal (either directly bullish/bearish or via a trigger break).
5. **TP (FractalTP):** Take-profit at the **next fractal**—long targets the nearest fractal high above entry, short targets the nearest fractal low below entry.
---
## Components
### Trend Bias (Supertrend H1)
- Supertrend on H1 with adjustable Factor and ATR Length.
- **Body-break:** Direction change only when the candle body breaks the Supertrend line (not just the wick).
### POI (Point of Interest)
- **MTF Fractals ** – CC BY-NC-SA 4.0
- Long bias: Fractal low as POI (lowest fractal low in lookback).
- Short bias: Fractal high as POI (highest fractal high in lookback).
- Fractal size: 3, 5, 7, or 9 bars.
- Optional: Higher timeframe for fractals (MTF).
### Sweep Detection
- **Long:** Price makes a new low below the POI level.
- **Short:** Price makes a new high above the POI level.
- While sweep is active, the extreme low/high is tracked.
### Entry Logic (Two Paths)
**1. Attempted Candle (direct)** – Sweep + failure on the same candle:
- **Long:** `low < poiLevel` (sweep), `close > open` (bullish), `low < low ` (new low).
- **Short:** `high > poiLevel` (sweep), `close < open` (bearish), `high > high ` (new high).
- SL: Low/High of this attempted candle. Entry: Close.
**2. Trigger + Break** – Candle prints the extreme but has the wrong color → wait for break:
- **Long:** Trigger candle = bearish, prints low. Trigger level = its high. Entry when a bullish candle closes above the trigger level.
- **Short:** Trigger candle = bullish, prints high. Trigger level = its low. Entry when a bearish candle closes below the trigger level.
- SL: Option A = Low/High of the break candle. Option B = Low/High of the trigger candle.
### Williams %R Filter (Optional)
- **Long:** Trade only if Williams %R (0–100) reached at least 80 (overbought) within the last X bars.
- **Short:** Trade only if Williams %R (0–100) reached at most 20 (oversold) within the last X bars.
- Default lookback: 20 bars. Default length: 14.
- When disabled, the filter is not applied.
---
## Exits – TP Mode: Fixed CRV vs Next Fractal
### TP Mode (Default: Next Fractal)
| Mode | Description |
|------|-------------|
| **Fixed CRV** | TP = Entry ± (Risk × Min R:R), same as base Reverse Pulse. |
| **Next Fractal** | TP at the next fractal level above (long) or below (short) entry. |
### Next Fractal Logic
- **Long:** TP = smallest fractal high **above** entry (nearest resistance).
- **Short:** TP = largest fractal low **below** entry (nearest support).
- **Fallback:** If no valid fractal exists, or the fractal is closer than "Min R:R (Fallback)", the CRV-based TP is used instead.
### SL
- Stop-Loss based on entry logic (Low/High of the relevant candle).
---
## Risk Management
- **Position sizing:** `qty = RiskAmount / (SL distance × USD per point)`.
- **XAUUSD:** USD per point = 1 (1 USD P&L per 1 USD price move per oz).
- **Daily stop:** After N stop-loss losses (default: 3), no further trades until session reset (09:00).
- **Max Qty:** Upper limit for position size (e.g. 500 oz for Gold).
---
## Session & Time
- **DST-safe:** Timestamps use IANA timezone (e.g. `Europe/Berlin`).
- **Default:** 09:00–17:00 Europe/Berlin. Timezone selectable via dropdown.
- **Session OFF:** Debug option to disable session filter (24/7 testing).
---
## Settings Overview
| Group | Parameter | Default |
|-------|-----------|---------|
| Session | Start/End Hour, Min, Timezone | 09:00–17:00, Europe/Berlin |
| Supertrend | Factor, ATR Length | 3.0, 10 |
| Fractals | Bars in Fractal, Timeframe | 5, Chart TF |
| Entry | Trigger-Break SL (A/B) | A |
| Filter Williams %R | Use Filter, Lookback, Length | Off, 20, 14 |
| Filter Williams %R | Min for Long, Max for Short | 80, 20 |
| Risk | Risk %, USD per Point, Max Qty | 1%, 1, 500 |
| Risk | **TP Mode** | **Next Fractal** |
| Risk | Min R:R (TP), Fractal TP: Min R:R (Fallback) | 2, 1 |
| Risk | Max SL per Day | 3 |
| Alerts | Alert Output, Telegram / PineConnector options | Off |
| Debug | Show Debug, Level Lines, Legend | true, true, true |
---
## Alerts – Telegram or PineConnector
### Alert Output
- **Off:** No alerts.
- **Telegram:** Webhook/Telegram, copier-friendly format.
- **PineConnector:** Format for PineConnector EA (MT4/MT5).
### Telegram / Webhook
- **Alert prefix:** First line (e.g. "Reverse Pulse").
- **Telegram Channel ID:** For webhook routing (e.g. `-1001234567890`).
- **Format:** `SYMBOL Buy/Sell now SL: X.XX TP: X.XX` – copier compatible.
### PineConnector
- **License ID:** Your PineConnector license (13–14 digits).
- **Volume Parameter:** `vol_lots` (strategy qty), `vol_pct_bal_loss` (% balance), `vol_dollar` ($ risk).
- **Symbol Override:** Broker symbol (e.g. GOLD instead of XAUUSD), empty = chart symbol.
- **Format:** `LicenseID,buy,Symbol,vol_lots=0.15,sl_price=2650.50,tp_price=2660.75`
---
## Recommended Instruments
- **XAUUSD** (Gold)
- **EURUSD**
- Other liquid forex and metal pairs with suitable tick size
---
## Technical Notes
- **process_orders_on_close:** Orders are executed at bar close.
- **pyramiding:** 0 (no pyramiding).
- **Float comparison:** `approxEq()` with `syminfo.mintick` for stable behavior.
---
## License Notice
- Fractals: MTF Fractals – CC BY-NC-SA 4.0
creativecommons.org
---
## Disclaimer
This system is for educational and research purposes only. There is no guarantee of profits. Trading involves substantial risk. Only trade with capital you can afford to lose.
![]()
// @version=5
// Reverse Pulse System – FractalTP Version
// TP wählbar: Fixed CRV oder Next Fractal (Long = nächstes höheres Fractal-High, Short = nächstes tieferes Fractal-Low)
// Deterministic, closed-bar, non-repainting. Session 09:00–17:00. Stop after 3 SL losses per day.
// Fractals: MTF Fractals [RunRox] – CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
strategy("Reverse Pulse System FractalTP", overlay=true, process_orders_on_close=true, default_qty_type=strategy.fixed, default_qty_value=0.01, pyramiding=0, initial_capital=10000, max_lines_count=500, max_labels_count=500, max_polylines_count=100)
// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS
// ═══════════════════════════════════════════════════════════════════════════════
grpSession = "Session (DST-safe)"
inputSessionStart = input.int(9, "Session Start Hour", minval=0, maxval=23, group=grpSession)
inputSessionStartMin = input.int(0, "Session Start Min", minval=0, maxval=59, group=grpSession)
inputSessionEnd = input.int(17, "Session End Hour", minval=0, maxval=23, group=grpSession, tooltip="Default 17 = bis 17:00.")
inputSessionEndMin = input.int(0, "Session End Min", minval=0, maxval=59, group=grpSession)
inputTz = input.string("Europe/Berlin", "Session Timezone", options=["Europe/Berlin", "Etc/UTC", "America/New_York", "America/Los_Angeles", "America/Chicago", "Europe/London", "Asia/Tokyo"], group=grpSession, tooltip="Europe/Berlin = DST-safe (CET/CEST). Etc/UTC = keine DST-Umstellung.")
grpST = "Supertrend (H1)"
inputStFactor = input.float(3.0, "Factor", minval=0.1, step=0.1, group=grpST)
inputStAtrLen = input.int(10, "ATR Length", minval=1, group=grpST)
grpFractal = "Fractals (POI) - MTF Fractals [RunRox]"
inputFractalPeriod = input.string("5", "Bars in Fractal", options=["3", "5", "7", "9"], group=grpFractal, tooltip="3/5/7/9-bar fractal")
inputFractalTF = input.timeframe("", "Fractals Timeframe", group=grpFractal, tooltip="Empty = chart TF. Higher TF = MTF fractals.")
inputPoiUseLowest = input.bool(true, "POI = tiefstes Fractal (untere Linie)", group=grpFractal, tooltip="An: Tiefstes Fractal-Low resp. höchstes Fractal-High im Lookback = die Linie, die gesweept werden muss.")
inputPoiLookback = input.int(50, "POI Lookback (Bars)", minval=5, maxval=200, group=grpFractal, tooltip="Wenn POI=tiefstes: Anzahl Bars für Min/Max der Fractals.")
// RunRox 1:1
maxFractalAge = input.int(2500, "Max Age, bars", minval=50, group=grpFractal)
showFractalLine = input.bool(true, "Show Fractal Line", group=grpFractal)
inFracLineStyle = input.string("sol", "Line Style", options=["sol", "dsh", "dot"], group=grpFractal)
fracLineWidth = input.int(1, "Line Width", options=[1,2,3,4], group=grpFractal)
highColor = input.color(color.green, "High Fractal", inline="frac", group=grpFractal)
inputHighStyle = input.string("triUp", " ", options=["arDn","arUp","cir","cross","xcross","diam","flag","sqr","triDn","triUp"], inline="frac", group=grpFractal)
lowColor = input.color(color.red, "Low Fractal", inline="frac2", group=grpFractal)
inputLowStyle = input.string("triDn", " ", options=["arDn","arUp","cir","cross","xcross","diam","flag","sqr","triDn","triUp"], inline="frac2", group=grpFractal)
PIV_LB_SIZE = input.string(size.auto, "Fractal Label Size", options=[size.auto, size.tiny, size.small, size.normal, size.large, size.huge], group=grpFractal)
showSweepLabel = input.bool(false, "Show Sweep Label", group=grpFractal)
lbBullColor = input.color(#00e67794, "Sweep Label Long", inline="lb", group=grpFractal)
lbBullTxtColor = input.color(color.silver, "", inline="lb", group=grpFractal)
lbBearColor = input.color(#ff525294, "Sweep Label Short", inline="lb", group=grpFractal)
lbBearTxtColor = input.color(color.silver, "", inline="lb", group=grpFractal)
enBgSweep = input.bool(false, "Shade Sweep Area", group=grpFractal)
bgBullColor = input.color(#7bda7e9f, "Sweep Area Long", inline="bg", group=grpFractal)
bgBearColor = input.color(#d375729f, "Sweep Area Short", inline="bg", group=grpFractal)
grpEntry = "Entry / SL"
inputTriggerSLOption = input.string("A", "Trigger-Break SL", options=["A", "B"], tooltip="A = SL = Low/High of break candle. B = SL = Low/High of original bearish/bullish trigger candle.", group=grpEntry)
grpAlerts = "Alerts"
inputAlertOutput = input.string("Off", "Alert Output", options=["Off", "Telegram", "PineConnector"], group=grpAlerts, tooltip="Off = keine Alerts. Telegram = Webhook/Telegram (Copier-Format). PineConnector = Format für PineConnector EA (MT4/MT5).")
grpTelegram = "Telegram / Webhook"
inputTelegramPrefix = input.string("Reverse Pulse", "Alert prefix", group=grpTelegram, tooltip="Erste Zeile der Nachricht (Strategiename).")
inputTelegramChannelId = input.string("", "Telegram Channel ID", group=grpTelegram, tooltip="Deine Chat/Channel-ID (z.B. -1001234567890). Für Webhook-Routing.")
grpPineConnector = "PineConnector"
inputPCLicenseId = input.string("", "License ID (13–14 Ziffern)", group=grpPineConnector, tooltip="Deine PineConnector License ID (z.B. 60123456789). Findest du im Portal.")
inputPCVolType = input.string("vol_lots", "Volume Parameter", options=["vol_lots", "vol_pct_bal_loss", "vol_dollar"], group=grpPineConnector, tooltip="vol_lots = Strategie-Qty. vol_pct_bal_loss = Risk % Balance. vol_dollar = Risk in $.")
inputPCSymbolOverride = input.string("", "Symbol Override (leer = Chart)", group=grpPineConnector, tooltip="Broker-Symbol überschreiben (z.B. GOLD statt XAUUSD). Leer = Chart-Symbol.")
grpFilter = "Filter Williams %R"
inputUseWilliamsFilter = input.bool(false, "Use Williams %R Filter", group=grpFilter, tooltip="Nur Trade wenn Williams %R kurz zuvor im Extrembereich war.")
inputWilliamsLookback = input.int(20, "Lookback (max. Bars)", minval=1, maxval=100, group=grpFilter, tooltip="Wie viele Bars zurück nach Extrembereich suchen.")
inputWilliamsLen = input.int(14, "Williams %R Length", minval=5, group=grpFilter)
inputWilliamsLongLevel = input.int(80, "Min für Long (0–100)", minval=0, maxval=100, group=grpFilter, tooltip="Long nur wenn Williams %R (0–100) innerhalb Lookback mind. so hoch war (Overbought).")
inputWilliamsShortLevel = input.int(20, "Max für Short (0–100)", minval=0, maxval=100, group=grpFilter, tooltip="Short nur wenn Williams %R (0–100) innerhalb Lookback mind. so tief war (Oversold).")
grpRisk = "Risk / TP"
inputRiskPct = input.float(1.0, "Risk % pro Trade", minval=0.1, step=0.1, group=grpRisk, tooltip="Verlust bei SL = dieser Prozentsatz der Equity. XAUUSD: Qty = RiskAmount / SL-Distanz.")
inputContractValue = input.float(1.0, "USD pro Punkt (Qty)", minval=0.01, step=0.01, group=grpRisk, tooltip="XAUUSD: 1 = 1 USD P&L pro 1 USD Preisbewegung pro Oz. Standard: 1.")
inputMaxQty = input.float(500.0, "Max Qty", minval=0.01, step=10, group=grpRisk, tooltip="Obergrenze (z.B. 500 oz).")
inputTPMode = input.string("Next Fractal", "TP Mode", options=["Fixed CRV", "Next Fractal"], group=grpRisk, tooltip="Fixed CRV = TP nach R:R. Next Fractal = TP am nächsten Fractal (Long= höheres, Short= tieferes).")
inputCrvMin = input.float(2.0, "Min R:R (TP)", minval=2.0, step=0.5, group=grpRisk, tooltip="Bei Fixed CRV: TP = Entry ± R:R. Bei Next Fractal: Fallback wenn kein gültiges Fractal.")
inputTPFractalMinRR = input.float(1.0, "Fractal TP: Min R:R (Fallback)", minval=0.5, step=0.5, group=grpRisk, tooltip="Nur bei Next Fractal: Wenn Fractal näher als dies, nutze CRV-Fallback.")
inputMaxSLPerDay = input.int(3, "Max SL Losses per Day", minval=1, maxval=20, group=grpRisk)
grpDebug = "Debug / Visuals"
inputShowDebug = input.bool(true, "Show Debug Plots", group=grpDebug)
inputShowLevelLines = input.bool(true, "Show Level Lines (POI, Extreme, etc.)", group=grpDebug, tooltip="Linien wie Fractals: line.new() statt plot().")
inputShowLegend = input.bool(true, "Show Legend", group=grpDebug, tooltip="Legende: Farbe = Linie.")
inputSkipSession = input.bool(false, "Session OFF (Debug)", group=grpDebug, tooltip="An: Session-Filter deaktiviert (24/7) zum Testen.")
// ═══════════════════════════════════════════════════════════════════════════════
// CONSTANTS
// ═══════════════════════════════════════════════════════════════════════════════
LONG = 1
SHORT = -1
IDLE = 0
TRACK_POI = 1
SWEEP_ACTIVE = 2
WAIT_TRIGGER = 3
IN_TRADE = 4
DAY_STOP = 5
// ═══════════════════════════════════════════════════════════════════════════════
// SESSION & TIME – DST-safe via timestamp()
// ═══════════════════════════════════════════════════════════════════════════════
// Session-Grenzen als Unix-Timestamps (IANA-TZ = automatisch CET/CEST)
y_ = year(time, inputTz)
m_ = month(time, inputTz)
d_ = dayofmonth(time, inputTz)
sessionStartTs = timestamp(inputTz, y_, m_, d_, inputSessionStart, inputSessionStartMin)
sessionEndTs = timestamp(inputTz, y_, m_, d_, inputSessionEnd, inputSessionEndMin)
inSession = inputSkipSession or (time >= sessionStartTs and time < sessionEndTs)
isNewDay = ta.change(time("D", inputTz)) != 0
// ═══════════════════════════════════════════════════════════════════════════════
// Bias() – H1 Supertrend with body-break confirmed flips
// ═══════════════════════════════════════════════════════════════════════════════
f_bias_get_h1_data() =>
h1_o = request.security(syminfo.tickerid, "60", open[1], barmerge.gaps_off, barmerge.lookahead_off)
h1_h = request.security(syminfo.tickerid, "60", high[1], barmerge.gaps_off, barmerge.lookahead_off)
h1_l = request.security(syminfo.tickerid, "60", low[1], barmerge.gaps_off, barmerge.lookahead_off)
h1_c = request.security(syminfo.tickerid, "60", close[1], barmerge.gaps_off, barmerge.lookahead_off)
h1_atr = request.security(syminfo.tickerid, "60", ta.atr(inputStAtrLen)[1], barmerge.gaps_off, barmerge.lookahead_off)
[h1_o, h1_h, h1_l, h1_c, h1_atr]
// Supertrend computed on H1 (last closed bar). Body-break: flip only when full body breaks the line.
var int stDir = 1
var float stTl = 0.0
var float stLine = 0.0
[h1_o, h1_h, h1_l, h1_c, h1_atr] = f_bias_get_h1_data()
newH1Close = ta.change(h1_c) != 0 and not na(h1_c) and not na(h1_atr) and h1_atr > 0
if newH1Close
st_hl2 = (h1_h + h1_l) / 2.0
upper = st_hl2 + inputStFactor * h1_atr
lower = st_hl2 - inputStFactor * h1_atr
oc = h1_o
cc = h1_c
if stDir == 1
if lower > stTl
stTl := lower
if h1_l < stTl
stTl := h1_l
// Would flip to short: close < stTl. Body-break: max(O,C) < stTl
bodyBreakShort = math.max(oc, cc) < stTl
if bodyBreakShort
stDir := -1
stTl := upper
else
if upper < stTl or stTl == 0.0
stTl := upper
if h1_h > stTl
stTl := h1_h
// Would flip to long: close > stTl. Body-break: min(O,C) > stTl
bodyBreakLong = math.min(oc, cc) > stTl
if bodyBreakLong
stDir := 1
stTl := lower
stLine := stTl
biasDir = stDir
// ═══════════════════════════════════════════════════════════════════════════════
// MTF Fractals [RunRox] – CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
// 1:1 Übernahme des RunRox-Indikators
// ═══════════════════════════════════════════════════════════════════════════════
const int MAX_PIV_ARR_SIZE = 1000
const string SWEEP_HIGH_LB_STYLE = label.style_label_lower_left
const string SWEEP_LOW_LB_STYLE = label.style_label_upper_left
getLabelStyle(string style) =>
switch style
"arDn" => label.style_arrowdown
"arUp" => label.style_arrowup
"cir" => label.style_circle
"cross" => label.style_cross
"diam" => label.style_diamond
"flag" => label.style_flag
"sqr" => label.style_square
"triDn" => label.style_triangledown
"triUp" => label.style_triangleup
"xcross" => label.style_xcross
=> label.style_triangleup
PIV_HIGH_LB_STYLE = getLabelStyle(inputHighStyle)
PIV_LOW_LB_STYLE = getLabelStyle(inputLowStyle)
inputTF = inputFractalTF
isHTF = inputTF != "" and timeframe.in_seconds(inputTF) > timeframe.in_seconds(timeframe.period)
htf = isHTF ? inputTF : timeframe.period
tfRatio = math.ceil(timeframe.in_seconds(htf) / timeframe.in_seconds(timeframe.period))
fracLineStyle = inFracLineStyle == "dot" ? line.style_dotted : inFracLineStyle == "dsh" ? line.style_dashed : line.style_solid
DT = 1000 * timeframe.in_seconds()
period = inputFractalPeriod == "3" ? 1 : inputFractalPeriod == "5" ? 2 : inputFractalPeriod == "7" ? 3 : 4
type Fractal
bool isHigh
chart.point point
line ln
label lb
int brokenAt
var localHighs = array.new<chart.point>()
var localLows = array.new<chart.point>()
var fracHighs = array.new<Fractal>()
var fracLows = array.new<Fractal>()
var brokenHighs = array.new<Fractal>()
var brokenLows = array.new<Fractal>()
locPivLen = math.max(math.floor(tfRatio / 2), 1)
if isHTF
locPh = ta.pivothigh(locPivLen, locPivLen)
if not na(locPh)
localHighs.push(chart.point.new(time[locPivLen], bar_index[locPivLen], locPh))
locPl = ta.pivotlow(locPivLen, locPivLen)
if not na(locPl)
localLows.push(chart.point.new(time[locPivLen], bar_index[locPivLen], locPl))
getFractalPoint(bool isHigh, float price, int minTime) =>
arr = isHigh ? localHighs : localLows
chart.point res = na
chart.point extremum = na
i = arr.size() - 1
while i >= 0
p = arr.get(i)
if na(extremum)
extremum := p
if p.price == price
res := p
break
else
if p.time < minTime
break
if isHigh ? extremum.price < p.price : extremum.price > p.price
extremum := p
i -= 1
res := na(res) ? extremum : res
fractalHigh(int len) =>
res = true
for i = 1 to len
res := res and high[len] > high[len - i] and high[len] > high[len + i]
if res
high[len]
fractalLow(int len) =>
res = true
for i = 1 to len
res := res and low[len] < low[len - i] and low[len] < low[len + i]
if res
low[len]
method drawFractal(Fractal this) =>
_style = this.isHigh ? PIV_HIGH_LB_STYLE : PIV_LOW_LB_STYLE
loc = this.isHigh ? yloc.abovebar : yloc.belowbar
clr = this.isHigh ? highColor : lowColor
this.lb := label.new(this.point, style=_style, xloc=xloc.bar_time, yloc=loc, color=clr, size=PIV_LB_SIZE)
end = chart.point.now(this.point.price)
if showFractalLine
this.ln := line.new(this.point, end, xloc=xloc.bar_time, color=clr, style=fracLineStyle, width=fracLineWidth)
method deleteFractal(Fractal this) =>
if not na(this.lb)
this.lb.delete()
if not na(this.ln)
this.ln.delete()
method extendFractals(array<Fractal> arr) =>
i = arr.size() - 1
while i >= 0
piv = arr.get(i)
if bar_index - piv.point.index > maxFractalAge
arr.remove(i)
piv.deleteFractal()
else
piv.ln.set_x2(time)
i -= 1
addFractals(bool isHigh, float price, int openTime, bool isCurrentTF = false) =>
res = false
if not na(price)
arr = isHigh ? fracHighs : fracLows
point = isCurrentTF ? chart.point.from_time(openTime, price) : getFractalPoint(isHigh, price, openTime)
if not na(point)
piv = Fractal.new(isHigh, point)
piv.drawFractal()
arr.push(piv)
if arr.size() > MAX_PIV_ARR_SIZE
arr.shift()
res := true
res
markBroken(bool isHigh) =>
arr = isHigh ? fracHighs : fracLows
broken = isHigh ? brokenHighs : brokenLows
i = arr.size() - 1
while i >= 0
frac = arr.get(i)
if isHigh ? high > frac.point.price : low < frac.point.price
frac.brokenAt := time
arr.remove(i)
broken.push(frac)
else
break
i -= 1
newSweep(Fractal this) =>
if na(this)
false
else
endWasFound = false
cpArr = array.new<chart.point>()
price = this.point.price
chart.point lbCp = na
for i = 0 to tfRatio
if not endWasFound
if this.isHigh ? high[i] > price : low[i] < price
lbCp := i == 0 ? chart.point.new(time + DT, bar_index + 1, price) : chart.point.new(time[i-1], bar_index[i-1], price)
cpArr.push(lbCp)
endWasFound := true
if not enBgSweep
break
if endWasFound
if time[i] < this.brokenAt
cpArr.push(chart.point.new(time[i], bar_index[i], price))
break
dotPrice = this.isHigh ? math.max(price, high[i]) : math.min(price, low[i])
cpArr.push(chart.point.new(time[i], bar_index[i], dotPrice))
if endWasFound
if enBgSweep
clr = this.isHigh ? bgBullColor : bgBearColor
bgClr = color.new(clr, 80)
if cpArr.size() == 3
p0 = cpArr.get(0)
peak = cpArr.get(1)
p1 = p0.copy()
p1.price := peak.price
p3 = cpArr.get(2)
p2 = p3.copy()
p2.price := peak.price
cpArr := array.from(p0, p1, p2, p3)
polyline.new(cpArr, false, true, xloc.bar_time, clr, bgClr)
if showSweepLabel
if this.isHigh
label.new(lbCp, "Sweep", xloc=xloc.bar_time, yloc=yloc.price, color=lbBullColor, textcolor=lbBullTxtColor, style=SWEEP_HIGH_LB_STYLE)
else
label.new(lbCp, "Sweep", xloc=xloc.bar_time, yloc=yloc.price, color=lbBearColor, textcolor=lbBearTxtColor, style=SWEEP_LOW_LB_STYLE)
this.ln.set_x2(lbCp.time)
true
else
false
getSweepFractals(bool isHigh, float extremum, float o, float c) =>
arr = isHigh ? brokenHighs : brokenLows
sign = isHigh ? 1 : -1
toSweep = array.new<Fractal>()
if not na(extremum)
for frac in arr
if sign * extremum > sign * frac.point.price and sign * o < sign * frac.point.price and sign * c < sign * frac.point.price
toSweep.push(frac)
arr.clear()
toSweep
var htfTimestamps = array.new<int>()
var int prevHtfTs = 0
if barstate.isconfirmed
markBroken(true)
markBroken(false)
upFractal = fractalHigh(period)
dnFractal = fractalLow(period)
[htfOpen, htfHigh, htfLow, htfClose, htfTime, htfUpFractal, htfDnFractal] = request.security(syminfo.tickerid, htf, [open, high, low, close, time, fractalHigh(period), fractalLow(period)], barmerge.gaps_on, barmerge.lookahead_off)
isNewCandleHtf = not na(htfTime)
if isNewCandleHtf
htfTimestamps.unshift(htfTime)
if htfTimestamps.size() > period + 1
prevHtfTs := htfTimestamps.get(period)
if isHTF
if showFractalLine
fracHighs.extendFractals()
fracLows.extendFractals()
addFractals(true, htfUpFractal, prevHtfTs)
addFractals(false, htfDnFractal, prevHtfTs)
else
if showFractalLine
fracHighs.extendFractals()
fracLows.extendFractals()
addFractals(true, upFractal, time[period], true)
addFractals(false, dnFractal, time[period], true)
// getSweepFractals + newSweep immer auf顶层 (Pine-Konsistenz)
detectSweepRun = (isHTF and isNewCandleHtf) or (not isHTF and barstate.isconfirmed)
detExtHigh = detectSweepRun ? (isHTF ? htfHigh : high) : na
detExtLow = detectSweepRun ? (isHTF ? htfLow : low) : na
detExtClose = detectSweepRun ? (isHTF ? htfClose : close) : na
detExtOpen = detectSweepRun ? (isHTF ? htfOpen : open) : na
sweepHighs = getSweepFractals(true, detExtHigh, detExtClose, detExtOpen)
sweepLows = getSweepFractals(false, detExtLow, detExtClose, detExtOpen)
newSweep(sweepHighs.size() > 0 ? sweepHighs.get(0) : na)
newSweep(sweepHighs.size() > 1 ? sweepHighs.get(1) : na)
newSweep(sweepHighs.size() > 2 ? sweepHighs.get(2) : na)
newSweep(sweepHighs.size() > 3 ? sweepHighs.get(3) : na)
newSweep(sweepHighs.size() > 4 ? sweepHighs.get(4) : na)
newSweep(sweepLows.size() > 0 ? sweepLows.get(0) : na)
newSweep(sweepLows.size() > 1 ? sweepLows.get(1) : na)
newSweep(sweepLows.size() > 2 ? sweepLows.get(2) : na)
newSweep(sweepLows.size() > 3 ? sweepLows.get(3) : na)
newSweep(sweepLows.size() > 4 ? sweepLows.get(4) : na)
fractalHighPrice = isHTF ? htfUpFractal : upFractal
fractalLowPrice = isHTF ? htfDnFractal : dnFractal
// POI: Long = tiefstes Fractal-Low (untere Linie) oder neuestes. Short = höchstes Fractal-High oder neuestes.
var float poiLevel = na
if inputPoiUseLowest
lowestFractalLow = ta.lowest(nz(fractalLowPrice, 999999.0), inputPoiLookback)
highestFractalHigh = ta.highest(nz(fractalHighPrice, 0.0), inputPoiLookback)
if biasDir == LONG and lowestFractalLow < 999999.0
poiLevel := lowestFractalLow
else if biasDir == SHORT and highestFractalHigh > 0.0
poiLevel := highestFractalHigh
else
if biasDir == LONG and not na(fractalLowPrice)
poiLevel := fractalLowPrice
else if biasDir == SHORT and not na(fractalHighPrice)
poiLevel := fractalHighPrice
// Invalidate POI on bias flip
var int prevBiasDir = 0
biasFlipped = prevBiasDir != 0 and biasDir != 0 and prevBiasDir != biasDir
if biasFlipped
poiLevel := na
prevBiasDir := biasDir
// ═══════════════════════════════════════════════════════════════════════════════
// SWEEP DETECTION – price breaks POI (wick sufficient), track extreme
// Closed bar: evaluate on last closed bar [1] for sweep start; use current bar for entry
// ═══════════════════════════════════════════════════════════════════════════════
sweepLong = biasDir == LONG and not na(poiLevel) and low < poiLevel
sweepShort = biasDir == SHORT and not na(poiLevel) and high > poiLevel
var float extreme = na
var bool sweepActive = false
var float sweptPoiLevel = na // POI-Level, das beim Sweep-Start gültig war – daran prüfen wir extreme
// Reset sweep state auf bias flip ODER wenn POI sich ändert (neues Fractal)
poiLevelChanged = not na(poiLevel) and not na(poiLevel[1]) and math.abs(poiLevel - poiLevel[1]) >= syminfo.mintick
if biasFlipped or poiLevelChanged
sweepActive := false
extreme := na
sweptPoiLevel := na
if sweepLong and not sweepActive
sweepActive := true
extreme := low
sweptPoiLevel := poiLevel // Lock: dieses Level wurde gesweept
else if sweepShort and not sweepActive
sweepActive := true
extreme := high
sweptPoiLevel := poiLevel
// Track extreme while sweep active (current bar contributes)
if sweepActive and biasDir == LONG
extreme := math.min(nz(extreme), low)
else if sweepActive and biasDir == SHORT
extreme := math.max(nz(extreme), high)
// ═══════════════════════════════════════════════════════════════════════════════
// SIGNAL & ENTRY – Attempted Candle logic (current bar = signal bar)
// ═══════════════════════════════════════════════════════════════════════════════
// Approx. float comparison (mintick tolerance) – avoids precision failure
approxEq(a, b) => math.abs(a - b) < syminfo.mintick
// Extreme muss unter POI liegen (Long) bzw. über POI (Short) – sowohl swept als auch AKTUELL
// (Wenn neues Fractal unter Extreme liegt, ist die Struktur anders – kein Entry)
extremeBelowPoiLong = not na(extreme) and not na(sweptPoiLevel) and extreme < sweptPoiLevel and not na(poiLevel) and extreme < poiLevel
extremeAbovePoiShort = not na(extreme) and not na(sweptPoiLevel) and extreme > sweptPoiLevel and not na(poiLevel) and extreme > poiLevel
barPrintsNewExtremeLong = sweepActive and biasDir == LONG and extremeBelowPoiLong and approxEq(low, extreme) and (na(extreme[1]) or low < extreme[1])
barPrintsNewExtremeShort = sweepActive and biasDir == SHORT and extremeAbovePoiShort and approxEq(high, extreme) and (na(extreme[1]) or high > extreme[1])
// Candle type: bullish = close > open, bearish = close < open
barBullish = close > open
barBearish = close < open
// Attempted Candle (klassisch): Sweep + Failure auf DERSELBEN Kerze – kein Trigger Level.
// Long: low < poiLevel, close > open, low < low[1].
// Short: high > poiLevel, close < open, high > high[1].
// Trigger + Break: Wenn Kerze das Extrem druckt aber falsche Farbe → Trigger Level, warten auf Break.
var float triggerLevel = na
var float triggerCandleLow = na
var float triggerCandleHigh = na
var bool waitTrigger = false
if biasFlipped or poiLevelChanged
triggerLevel := na
triggerCandleLow := na
triggerCandleHigh := na
waitTrigger := false
// Attempted Candle (klassisch): Sweep + bullish/bearish Close + neues Extrem auf derselben Kerze
// Extreme muss unter POI (Long) bzw. über POI (Short) – sonst kein gültiger Sweep
attemptedLongDirect = sweepLong and extremeBelowPoiLong and barBullish and (low < low[1])
attemptedShortDirect = sweepShort and extremeAbovePoiShort and barBearish and (high > high[1])
// Trigger nur, wenn Kerze Extrem druckt aber falsche Farbe (bearish für Long, bullish für Short)
if barPrintsNewExtremeLong and barBearish
triggerLevel := high
triggerCandleLow := low
triggerCandleHigh := high
waitTrigger := true
if barPrintsNewExtremeShort and barBullish
triggerLevel := low
triggerCandleLow := low
triggerCandleHigh := high
waitTrigger := true
// Reset Trigger bei Direct Entry (kein Warten nötig)
if attemptedLongDirect
triggerLevel := na
triggerCandleLow := na
triggerCandleHigh := na
waitTrigger := false
if attemptedShortDirect
triggerLevel := na
triggerCandleLow := na
triggerCandleHigh := na
waitTrigger := false
// Trigger Break: nachfolgende Kerze durchbricht Level mit richtiger Farbe
triggerBreakLong = waitTrigger and not na(triggerLevel) and close > triggerLevel and barBullish
triggerBreakShort = waitTrigger and not na(triggerLevel) and close < triggerLevel and barBearish
// ═══════════════════════════════════════════════════════════════════════════════
// Filter: Williams %R im Extrembereich (optional)
// Williams %R Standard: -100*(HH-close)/(HH-LL). 0–100: wrNorm = 100 + williamsR
// Long: darf nur wenn Williams innerhalb Lookback mind. inputWilliamsLongLevel war (Overbought)
// Short: darf nur wenn Williams innerhalb Lookback max. inputWilliamsShortLevel war (Oversold)
// ═══════════════════════════════════════════════════════════════════════════════
wrHH = ta.highest(high, inputWilliamsLen)
wrLL = ta.lowest(low, inputWilliamsLen)
wrRaw = wrHH == wrLL ? 0.0 : -100.0 * (wrHH - close) / (wrHH - wrLL)
wrNorm = 100.0 + wrRaw
wrLongOk = not inputUseWilliamsFilter or ta.highest(wrNorm, inputWilliamsLookback) >= inputWilliamsLongLevel
wrShortOk = not inputUseWilliamsFilter or ta.lowest(wrNorm, inputWilliamsLookback) <= inputWilliamsShortLevel
// Bias übergeordnet. Extreme MUSS unter POI (Long) bzw. über POI (Short) – letzter Check vor Entry
entryLong = (attemptedLongDirect or triggerBreakLong) and biasDir == LONG and extremeBelowPoiLong and wrLongOk
entryShort = (attemptedShortDirect or triggerBreakShort) and biasDir == SHORT and extremeAbovePoiShort and wrShortOk
// ═══════════════════════════════════════════════════════════════════════════════
// Risk() – SL, TP computation
// ═══════════════════════════════════════════════════════════════════════════════
// Nächstes Fractal für TP: Long = kleinstes Fractal-High über Entry, Short = größtes Fractal-Low unter Entry
getNextFractalTP(bool isHigh, float refPrice) =>
float result = na
sz = isHigh ? fracHighs.size() : fracLows.size()
if sz > 0
if isHigh
for i = 0 to sz - 1
p = fracHighs.get(i).point.price
if p > refPrice
result := na(result) ? p : math.min(result, p)
else
for i = 0 to sz - 1
p = fracLows.get(i).point.price
if p < refPrice
result := na(result) ? p : math.max(result, p)
result
f_risk_compute(entryPrice, slPrice, dir, crv) =>
riskR = math.abs(entryPrice - slPrice)
tp = dir == LONG ? entryPrice + riskR * crv : entryPrice - riskR * crv
[riskR, tp]
// ═══════════════════════════════════════════════════════════════════════════════
// DAILY SL COUNT – block after 4 SL losses
// ═══════════════════════════════════════════════════════════════════════════════
var int slCount = 0
var int prevClosedTrades = 0
// Reset at session start (09:00)
sessionJustStarted = inSession and not inSession[1]
if sessionJustStarted
slCount := 0
dayStopped = slCount >= inputMaxSLPerDay
if strategy.closedtrades > prevClosedTrades
prevClosedTrades := strategy.closedtrades
lastProfit = strategy.closedtrades.profit(strategy.closedtrades - 1)
if lastProfit < 0
slCount := slCount + 1
// ═══════════════════════════════════════════════════════════════════════════════
// STATE MACHINE
// ═══════════════════════════════════════════════════════════════════════════════
var int state = IDLE
inPos = strategy.position_size != 0
// Reset on new day
if isNewDay and state == DAY_STOP
state := IDLE
if dayStopped and not inPos
state := DAY_STOP
if inPos
state := IN_TRADE
// Transition out of IN_TRADE when position closes
if ta.change(bar_index) != 0 and not inPos and state == IN_TRADE
state := IDLE
if state != DAY_STOP and state != IN_TRADE and not inSession and not inPos
state := IDLE
// State transitions
if state == IDLE and inSession and not dayStopped and biasDir != 0
state := TRACK_POI
if state == TRACK_POI
if biasFlipped
state := IDLE
else if sweepLong or sweepShort
state := SWEEP_ACTIVE
if state == SWEEP_ACTIVE
if biasFlipped
state := IDLE
else if entryLong or entryShort
if waitTrigger and (triggerBreakLong or triggerBreakShort)
state := WAIT_TRIGGER
else
state := WAIT_TRIGGER
if state == WAIT_TRIGGER
if entryLong or entryShort
state := IN_TRADE
if biasFlipped
state := IDLE
// ═══════════════════════════════════════════════════════════════════════════════
// Execute() – entry at bar close, SL/TP (process_orders_on_close=true)
// ═══════════════════════════════════════════════════════════════════════════════
// SL: Attempted Direct = Low/High der Attempted-Kerze. Trigger Break = Option A oder B
slDirectLong = low
slDirectShort = high
slTriggerLongA = low
slTriggerLongB = triggerCandleLow
slTriggerShortA = high
slTriggerShortB = triggerCandleHigh
slTriggerLong = inputTriggerSLOption == "A" ? slTriggerLongA : slTriggerLongB
slTriggerShort = inputTriggerSLOption == "A" ? slTriggerShortA : slTriggerShortB
entryPriceLong = close
entryPriceShort = close
slLong = attemptedLongDirect ? slDirectLong : slTriggerLong
slShort = attemptedShortDirect ? slDirectShort : slTriggerShort
[riskLong, tpLongCrv] = f_risk_compute(entryPriceLong, slLong, LONG, inputCrvMin)
[riskShort, tpShortCrv] = f_risk_compute(entryPriceShort, slShort, SHORT, inputCrvMin)
// TP: Fixed CRV oder Next Fractal
tpLongFractal = inputTPMode == "Next Fractal" ? getNextFractalTP(true, entryPriceLong) : na
tpShortFractal = inputTPMode == "Next Fractal" ? getNextFractalTP(false, entryPriceShort) : na
useTpLongFractal = not na(tpLongFractal) and tpLongFractal > entryPriceLong and (tpLongFractal - entryPriceLong) >= riskLong * inputTPFractalMinRR
useTpShortFractal = not na(tpShortFractal) and tpShortFractal < entryPriceShort and (entryPriceShort - tpShortFractal) >= riskShort * inputTPFractalMinRR
tpLong = inputTPMode == "Next Fractal" and useTpLongFractal ? tpLongFractal : tpLongCrv
tpShort = inputTPMode == "Next Fractal" and useTpShortFractal ? tpShortFractal : tpShortCrv
// Positionsgröße Gold-kompatibel: qty = RiskAmount / (SL-Distanz * USD pro Punkt)
riskAmount = strategy.equity * inputRiskPct / 100.0
slDistLong = math.abs(entryPriceLong - slLong)
slDistShort = math.abs(slShort - entryPriceShort)
qtyLongRaw = slDistLong > 0 and inputContractValue > 0 ? riskAmount / (slDistLong * inputContractValue) : 0.01
qtyShortRaw = slDistShort > 0 and inputContractValue > 0 ? riskAmount / (slDistShort * inputContractValue) : 0.01
qtyLong = math.max(0.01, math.min(inputMaxQty, math.round(qtyLongRaw * 100) / 100))
qtyShort = math.max(0.01, math.min(inputMaxQty, math.round(qtyShortRaw * 100) / 100))
// Execute – market order fills at bar close (process_orders_on_close)
// Bias als Filter: ST H1 bullish = nur Longs, ST H1 bearish = nur Shorts
if entryLong and biasDir == LONG and not inPos and inSession and not dayStopped and strategy.position_size == 0
strategy.entry("Long", strategy.long, qty=qtyLong)
strategy.exit("ExitLong", "Long", stop=slLong, limit=tpLong)
sweepActive := false
extreme := na
sweptPoiLevel := na
waitTrigger := false
triggerLevel := na
if inputAlertOutput == "Telegram"
_ch = inputTelegramChannelId != "" ? "\nChannel: " + inputTelegramChannelId : ""
alert(inputTelegramPrefix + "\n" + syminfo.ticker + " Buy now SL: " + str.tostring(slLong, "#.##") + " TP: " + str.tostring(tpLong, "#.##") + _ch, alert.freq_once_per_bar_close)
else if inputAlertOutput == "PineConnector" and inputPCLicenseId != ""
_sym = inputPCSymbolOverride != "" ? inputPCSymbolOverride : syminfo.ticker
_vol = inputPCVolType == "vol_lots" ? "vol_lots=" + str.tostring(qtyLong, "#.##") : inputPCVolType == "vol_pct_bal_loss" ? "vol_pct_bal_loss=" + str.tostring(inputRiskPct, "#.#") : "vol_dollar=" + str.tostring(math.round(riskAmount, 2), "#.##")
alert(inputPCLicenseId + ",buy," + _sym + "," + _vol + ",sl_price=" + str.tostring(slLong, "#.##") + ",tp_price=" + str.tostring(tpLong, "#.##"), alert.freq_once_per_bar_close)
if entryShort and biasDir == SHORT and not inPos and inSession and not dayStopped and strategy.position_size == 0
strategy.entry("Short", strategy.short, qty=qtyShort)
strategy.exit("ExitShort", "Short", stop=slShort, limit=tpShort)
sweepActive := false
extreme := na
sweptPoiLevel := na
waitTrigger := false
triggerLevel := na
if inputAlertOutput == "Telegram"
_ch = inputTelegramChannelId != "" ? "\nChannel: " + inputTelegramChannelId : ""
alert(inputTelegramPrefix + "\n" + syminfo.ticker + " Sell now SL: " + str.tostring(slShort, "#.##") + " TP: " + str.tostring(tpShort, "#.##") + _ch, alert.freq_once_per_bar_close)
else if inputAlertOutput == "PineConnector" and inputPCLicenseId != ""
_sym = inputPCSymbolOverride != "" ? inputPCSymbolOverride : syminfo.ticker
_vol = inputPCVolType == "vol_lots" ? "vol_lots=" + str.tostring(qtyShort, "#.##") : inputPCVolType == "vol_pct_bal_loss" ? "vol_pct_bal_loss=" + str.tostring(inputRiskPct, "#.#") : "vol_dollar=" + str.tostring(math.round(riskAmount, 2), "#.##")
alert(inputPCLicenseId + ",sell," + _sym + "," + _vol + ",sl_price=" + str.tostring(slShort, "#.##") + ",tp_price=" + str.tostring(tpShort, "#.##"), alert.freq_once_per_bar_close)
// ═══════════════════════════════════════════════════════════════════════════════
// Level Lines – Fractal-Style mit line.new() (POI, sweptPoi, extreme, trigger)
// ═══════════════════════════════════════════════════════════════════════════════
COLOR_POI = color.new(color.orange, 30)
COLOR_SWEPTPOI = color.new(color.orange, 0)
COLOR_EXTREME = color.new(color.purple, 30)
COLOR_TRIGGER = color.new(#00d4ff, 20)
COLOR_ST_LONG = color.new(color.green, 30)
COLOR_ST_SHORT = color.new(color.red, 30)
updateLevelLine(line ln, float level, float prevLevel, int startTime, color clr, int w) =>
if na(level)
if not na(ln)
line.delete(ln)
na
else if na(ln) or not approxEq(level, prevLevel)
if not na(ln)
line.delete(ln)
line.new(startTime, level, time, level, xloc=xloc.bar_time, color=clr, width=w)
else
line.set_x2(ln, time)
ln
poiSwept = sweepLong or sweepShort
var bool poiWasSwept = false
if poiSwept
poiWasSwept := true
if biasFlipped or (not na(poiLevel) and (na(poiLevel[1]) or poiLevel != poiLevel[1]))
poiWasSwept := false
poiShow = not na(poiLevel) and not poiWasSwept
poiToDraw = inputShowDebug and inputShowLevelLines and poiShow ? poiLevel : na
var line poiLine = na
var line sweptPoiLine = na
var line extremeLine = na
var line triggerLine = na
sweptPoiToDraw = inputShowDebug and inputShowLevelLines and sweepActive and not na(sweptPoiLevel) ? sweptPoiLevel : na
extremeToDraw = inputShowDebug and inputShowLevelLines and sweepActive and not na(extreme) ? extreme : na
triggerToDraw = inputShowDebug and inputShowLevelLines and waitTrigger and not na(triggerLevel) ? triggerLevel : na
if barstate.isconfirmed and inputShowLevelLines
poiLine := updateLevelLine(poiLine, poiToDraw, poiToDraw[1], time, COLOR_POI, 2)
sweptPoiLine := updateLevelLine(sweptPoiLine, sweptPoiToDraw, sweptPoiToDraw[1], time, COLOR_SWEPTPOI, 1)
extremeLine := updateLevelLine(extremeLine, extremeToDraw, extremeToDraw[1], time, COLOR_EXTREME, 1)
triggerLine := updateLevelLine(triggerLine, triggerToDraw, triggerToDraw[1], time, COLOR_TRIGGER, 1)
plot(inputShowDebug ? stLine : na, "Supertrend H1", color=biasDir == LONG ? COLOR_ST_LONG : COLOR_ST_SHORT, linewidth=2)
// Sweep-Markierung (Strategy-POI): für Debug
sweepStartLong = sweepLong and not sweepActive[1]
sweepStartShort = sweepShort and not sweepActive[1]
plotshape(inputShowDebug and sweepStartLong, "Sweep L", shape.triangledown, location.abovebar, color.new(color.orange, 0), size=size.small)
plotshape(inputShowDebug and sweepStartShort, "Sweep S", shape.triangleup, location.belowbar, color.new(color.orange, 0), size=size.small)
// Fractal-Marker: RunRox zeichnet Labels via drawFractal()
stateStr = state == IDLE ? "IDLE" : state == TRACK_POI ? "TRACK_POI" : state == SWEEP_ACTIVE ? "SWEEP" : state == WAIT_TRIGGER ? "WAIT_TRIG" : state == IN_TRADE ? "IN_TRADE" : "DAY_STOP"
biasStr = biasDir == LONG ? "LONG" : "SHORT"
var table dbg = table.new(position.top_right, 2, 10, bgcolor=color.new(#1a1a2e, 5), border_width=1)
if inputShowDebug
table.cell(dbg, 0, 0, "Reverse Pulse FractalTP", text_color=color.white, text_size=size.small, bgcolor=color.new(#16213e, 0))
table.cell(dbg, 1, 0, "", bgcolor=color.new(#16213e, 0))
table.cell(dbg, 0, 1, "State", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 1, 1, stateStr, text_color=#e2e8f0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 0, 2, "Bias", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 1, 2, biasStr, text_color=#e2e8f0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 0, 3, "poiLevel", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 1, 3, not na(poiLevel) ? str.tostring(poiLevel, "#.##") : "-", text_color=#e2e8f0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 0, 4, "extreme/sweptPoi", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 1, 4, (not na(extreme) ? str.tostring(extreme, "#.##") : "-") + " / " + (not na(sweptPoiLevel) ? str.tostring(sweptPoiLevel, "#.##") : "-"), text_color=#e2e8f0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 0, 5, "triggerLevel", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 1, 5, not na(triggerLevel) ? str.tostring(triggerLevel, "#.##") : "-", text_color=#e2e8f0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 0, 6, "slCount", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 1, 6, str.tostring(slCount), text_color=#e2e8f0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 0, 7, "dayStopped", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 1, 7, dayStopped ? "Y" : "N", text_color=#e2e8f0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 0, 8, "inSession", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
blockSession = (entryLong or entryShort) and not inSession
sessColor = blockSession ? color.orange : (inSession ? #22c55e : #e2e8f0)
table.cell(dbg, 1, 8, inSession ? "Y" : (blockSession ? "N (blocked!)" : "N"), text_color=sessColor, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 0, 9, "qty L/S", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(dbg, 1, 9, str.tostring(qtyLong, "#.##") + " / " + str.tostring(qtyShort, "#.##"), text_color=#e2e8f0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
// Legende: Farbe = Linie
var table legendTbl = table.new(position.bottom_right, 2, 9, bgcolor=color.new(#1a1a2e, 5), border_width=1)
if inputShowLegend
table.cell(legendTbl, 0, 0, "Legende", text_color=color.white, text_size=size.small, bgcolor=color.new(#16213e, 0))
table.cell(legendTbl, 1, 0, "", bgcolor=color.new(#16213e, 0))
table.cell(legendTbl, 0, 1, "POI", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 1, 1, "■", text_color=COLOR_POI, text_size=size.small, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 0, 2, "sweptPOI", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 1, 2, "■", text_color=COLOR_SWEPTPOI, text_size=size.small, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 0, 3, "Extreme", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 1, 3, "■", text_color=COLOR_EXTREME, text_size=size.small, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 0, 4, "Trigger", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 1, 4, "■", text_color=COLOR_TRIGGER, text_size=size.small, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 0, 5, "ST Long", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 1, 5, "■", text_color=COLOR_ST_LONG, text_size=size.small, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 0, 6, "ST Short", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 1, 6, "■", text_color=COLOR_ST_SHORT, text_size=size.small, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 0, 7, "Fractal High", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 1, 7, "▲", text_color=highColor, text_size=size.small, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 0, 8, "Fractal Low", text_color=#a0aec0, text_size=size.tiny, bgcolor=color.new(#0f0f1a, 10))
table.cell(legendTbl, 1, 8, "▼", text_color=lowColor, text_size=size.small, bgcolor=color.new(#0f0f1a, 10))