P/L Panel + Multi Targets (4 Entries) – HUD near Price + Avg R:R

indicator("P/L Panel + Multi Targets (4 Entries) – HUD near Price + Avg R:R", overlay=true, max_lines_count=500, max_labels_count=500)
// ====== General ======
side = input.string("Long", "Position Side", options=["Long","Short"])
usd_dp = input.int(2, "USD decimals", minval=0, maxval=6)
// ====== HUD Settings ======
hud_font = input.string("large", "HUD font size", options=["tiny","small","normal","large","huge"])
hud_bg = input.color(color.new(color.black, 0), "HUD background color")
hud_txtc = input.color(color.white, "HUD text color")
hud_side = input.string("Right of price", "HUD side", options=["Right of price","Left of price"])
hud_off_bars = input.int(3, "Horizontal offset (bars)", minval=0, maxval=50)
hud_off_atr = input.float(0.2, "Vertical offset from price (ATR)", step=0.1)
atr_len = input.int(14, "ATR length for vertical offset", minval=1)
lock_to_last_bar = input.bool(true, "Lock HUD to the last bar")
// Show HUD even when there are no entries (test text)
force_show_hud = input.bool(true, "🔍 Show HUD even with no entries")
// ====== Shared SL & Targets ======
stop_inp = input.float(0.0, "Stop Loss (shared, optional)", step=0.0001)
use_tp1 = input.bool(false, "Enable Target 1")
tp1 = input.float(0.0, "Target 1 price", step=0.0001)
use_tp2 = input.bool(false, "Enable Target 2")
tp2 = input.float(0.0, "Target 2 price", step=0.0001)
use_tp3 = input.bool(false, "Enable Target 3")
tp3 = input.float(0.0, "Target 3 price", step=0.0001)
use_tp4 = input.bool(false, "Enable Target 4")
tp4 = input.float(0.0, "Target 4 price", step=0.0001)
use_tp5 = input.bool(false, "Enable Target 5")
tp5 = input.float(0.0, "Target 5 price", step=0.0001)
// ====== Four Independent Entries ======
group1 = "Entry 1"
en1 = input.bool(true, "Enable Entry 1", inline=group1)
lev1 = input.int(10, "Leverage", minval=1, maxval=200, inline=group1)
entry1 = input.float(0.0, "Entry 1 price", step=0.0001)
set_now1 = input.bool(false, "⚡ Set Entry1 = Current Price")
mode1 = input.string("USD (USDT)", "Size unit 1", options=["USD (USDT)","Coin Quantity"])
sem1 = input.string("Margin (apply leverage)", "Size meaning 1", options=["Margin (apply leverage)","Notional (already leveraged)"])
size1 = input.float(0.0, "Position size 1", step=0.0001)
baseLev1 = input.bool(false, "Apply leverage to 'Coin Quantity' (1)")
group2 = "Entry 2"
en2 = input.bool(false, "Enable Entry 2", inline=group2)
lev2 = input.int(10, "Leverage", minval=1, maxval=200, inline=group2)
entry2 = input.float(0.0, "Entry 2 price", step=0.0001)
set_now2 = input.bool(false, "⚡ Set Entry2 = Current Price")
mode2 = input.string("USD (USDT)", "Size unit 2", options=["USD (USDT)","Coin Quantity"])
sem2 = input.string("Margin (apply leverage)", "Size meaning 2", options=["Margin (apply leverage)","Notional (already leveraged)"])
size2 = input.float(0.0, "Position size 2", step=0.0001)
baseLev2 = input.bool(false, "Apply leverage to 'Coin Quantity' (2)")
group3 = "Entry 3"
en3 = input.bool(false, "Enable Entry 3", inline=group3)
lev3 = input.int(10, "Leverage", minval=1, maxval=200, inline=group3)
entry3 = input.float(0.0, "Entry 3 price", step=0.0001)
set_now3 = input.bool(false, "⚡ Set Entry3 = Current Price")
mode3 = input.string("USD (USDT)", "Size unit 3", options=["USD (USDT)","Coin Quantity"])
sem3 = input.string("Margin (apply leverage)", "Size meaning 3", options=["Margin (apply leverage)","Notional (already leveraged)"])
size3 = input.float(0.0, "Position size 3", step=0.0001)
baseLev3 = input.bool(false, "Apply leverage to 'Coin Quantity' (3)")
group4 = "Entry 4"
en4 = input.bool(false, "Enable Entry 4", inline=group4)
lev4 = input.int(10, "Leverage", minval=1, maxval=200, inline=group4)
entry4 = input.float(0.0, "Entry 4 price", step=0.0001)
set_now4 = input.bool(false, "⚡ Set Entry4 = Current Price")
mode4 = input.string("USD (USDT)", "Size unit 4", options=["USD (USDT)","Coin Quantity"])
sem4 = input.string("Margin (apply leverage)", "Size meaning 4", options=["Margin (apply leverage)","Notional (already leveraged)"])
size4 = input.float(0.0, "Position size 4", step=0.0001)
baseLev4 = input.bool(false, "Apply leverage to 'Coin Quantity' (4)")
// Quick set entries = current price
entry1 := (en1 and set_now1) ? close : entry1
entry2 := (en2 and set_now2) ? close : entry2
entry3 := (en3 and set_now3) ? close : entry3
entry4 := (en4 and set_now4) ? close : entry4
// ====== Helpers ======
to_size(s) =>
s == "tiny" ? size.tiny : s == "small" ? size.small : s == "normal" ? size.normal : s == "large" ? size.large : size.huge
f_usd_str(_val, _decimals) =>
na(_val) ? "—" : str.tostring(math.round(_val * math.pow(10, _decimals)) / math.pow(10, _decimals))
f_qty_base(mode, sem, size, entry, baseLev, lev) =>
float _qty = na
if mode == "USD (USDT)"
_qty := (size > 0 and entry > 0) ? ((sem == "Margin (apply leverage)" ? size * lev : size) / entry) : na
else
_qty := size > 0 ? (baseLev ? size * lev : size) : na
_qty
f_notional_quote(mode, sem, size, entry, lev, baseLev) =>
if mode == "USD (USDT)"
sem == "Margin (apply leverage)" ? size * lev : size
else
(baseLev ? size * lev : size) * entry
f_pnl_quote(side, entry, qty) =>
na(qty) or na(entry) ? na : (side=="Long" ? (close - entry) : (entry - close)) * qty
f_pct(side, entry) =>
na(entry) ? na : ((close - entry) / entry * 100.0) * (side=="Long" ? 1 : -1)
f_roi_pct(side, entry, lev) =>
na(entry) ? na : f_pct(side, entry) * lev
// NOTE: _lineIn must be a line, not a float
f_stickyHLine(_price, _lineIn, _color, _width) =>
var line _out = na
_out := _lineIn
if na(_out)
_out := line.new(bar_index-1, _price, bar_index+1, _price, xloc=xloc.bar_index, extend=extend.both, width=_width, style=line.style_dashed, color=_color)
else
line.set_xy1(_out, bar_index-1, _price)
line.set_xy2(_out, bar_index+1, _price)
line.set_color(_out, _color)
line.set_width(_out, _width)
_out
// ====== 4 Entries Calculations ======
var color[] entryCols = array.from(color.new(color.yellow, 0), color.new(color.orange, 0), color.new(color.teal, 0), color.new(color.fuchsia, 0))
bool[] ens = array.from(en1, en2, en3, en4)
float[] entries = array.from(entry1, entry2, entry3, entry4)
int[] levs = array.from(lev1, lev2, lev3, lev4)
string[] modes = array.from(mode1, mode2, mode3, mode4)
string[] sems = array.from(sem1, sem2, sem3, sem4)
float[] sizes = array.from(size1, size2, size3, size4)
bool[] baseLevs = array.from(baseLev1, baseLev2, baseLev3, baseLev4)
float[] qtys = array.new_float(4, na)
float[] pnls = array.new_float(4, na)
float[] pcts = array.new_float(4, na)
float[] rois = array.new_float(4, na)
float[] notionals = array.new_float(4, na)
for i = 0 to 3
if array.get(ens, i) and array.get(entries, i) > 0
ent = array.get(entries, i)
levX = array.get(levs, i)
modeX= array.get(modes, i)
semX = array.get(sems, i)
sizeX= array.get(sizes, i)
bLev = array.get(baseLevs, i)
qty = f_qty_base(modeX, semX, sizeX, ent, bLev, levX)
array.set(qtys, i, qty)
pnlq = f_pnl_quote(side, ent, qty)
array.set(pnls, i, pnlq)
pct = f_pct(side, ent)
array.set(pcts, i, pct)
roi = f_roi_pct(side, ent, levX)
array.set(rois, i, roi)
notq = f_notional_quote(modeX, semX, sizeX, ent, levX, bLev)
array.set(notionals, i, notq)
// ====== Totals & Weighted Avg Entry ======
float totalPnlUSD = 0.0
float totalNotional = 0.0
float totalQty = 0.0
float wAvgEntry = na
for i = 0 to 3
if not na(array.get(pnls, i))
totalPnlUSD += array.get(pnls, i)
if not na(array.get(notionals, i))
totalNotional += array.get(notionals, i)
if not na(array.get(qtys, i)) and array.get(entries, i) > 0
totalQty += array.get(qtys, i)
if totalQty > 0
num = 0.0
for i = 0 to 3
qi = array.get(qtys, i)
ei = array.get(entries, i)
if not na(qi) and ei > 0
num += qi * ei
wAvgEntry := num / totalQty
totalROIweighted = totalNotional > 0 ? (totalPnlUSD / totalNotional) * 100.0 : na
// ====== Nearest TP & R:R ======
float nearestTP = na
float nearestDistPrice = na
float nearestDistPct = na
float risk_pct = na
float reward_pct = na
float rr = na
var float[] tps = array.new_float()
array.clear(tps)
if use_tp1 and tp1 > 0
array.push(tps, tp1)
if use_tp2 and tp2 > 0
array.push(tps, tp2)
if use_tp3 and tp3 > 0
array.push(tps, tp3)
if use_tp4 and tp4 > 0
array.push(tps, tp4)
if use_tp5 and tp5 > 0
array.push(tps, tp5)
// nearest target in the trade direction (from current price)
if array.size(tps) > 0
for i = 0 to array.size(tps) - 1
_tp = array.get(tps, i)
cond = side=="Long" ? (_tp > close) : (_tp < close)
if cond
distP = math.abs(_tp - close)
if na(nearestDistPrice) or distP < nearestDistPrice
nearestDistPrice := distP
nearestTP := _tp
if not na(nearestDistPrice) and close != 0
nearestDistPct := (nearestDistPrice / close) * 100.0
float stop = stop_inp > 0 ? stop_inp : na
if not na(wAvgEntry) and not na(stop)
rawRisk = (side=="Long" ? (stop - wAvgEntry) : (wAvgEntry - stop)) / wAvgEntry * 100.0
risk_pct := math.abs(rawRisk)
if not na(wAvgEntry) and not na(nearestTP)
reward_pct := math.abs((side=="Long" ? (nearestTP - wAvgEntry) : (wAvgEntry - nearestTP)) / wAvgEntry * 100.0)
rr := (not na(risk_pct) and not na(reward_pct) and risk_pct != 0) ? reward_pct / risk_pct : na
// ====== Average R:R across all valid targets ======
float rr_avg = na
if not na(wAvgEntry) and not na(stop) and array.size(tps) > 0 and not na(risk_pct) and risk_pct != 0
float sum_rr = 0.0
int cnt_rr = 0
for i = 0 to array.size(tps) - 1
_tp = array.get(tps, i)
bool validDir = side=="Long" ? (_tp > wAvgEntry) : (_tp < wAvgEntry)
if validDir
_reward = math.abs((side=="Long" ? (_tp - wAvgEntry) : (wAvgEntry - _tp)) / wAvgEntry * 100.0)
_rr = _reward / risk_pct
sum_rr += _rr
cnt_rr += 1
rr_avg := cnt_rr > 0 ? (sum_rr / cnt_rr) : na
// ====== Entry/SL/TP Lines ======
var line[] entryLines = array.new_line(4, na)
for i = 0 to 3
ln = array.get(entryLines, i)
if array.get(ens, i) and array.get(entries, i) > 0
col = array.get(entryCols, i)
ent = array.get(entries, i)
ln := f_stickyHLine(ent, ln, col, 2)
array.set(entryLines, i, ln)
else
if not na(ln)
line.delete(ln)
array.set(entryLines, i, na)
var line slLine = na
if not na(stop)
slLine := f_stickyHLine(stop, slLine, color.new(color.red, 0), 1)
else
if not na(slLine)
line.delete(slLine)
slLine := na
var line tpLine1 = na
var line tpLine2 = na
var line tpLine3 = na
var line tpLine4 = na
var line tpLine5 = na
if use_tp1 and tp1 > 0
tpLine1 := f_stickyHLine(tp1, tpLine1, color.new(color.teal, 0), 1)
else
if not na(tpLine1)
line.delete(tpLine1)
tpLine1 := na
if use_tp2 and tp2 > 0
tpLine2 := f_stickyHLine(tp2, tpLine2, color.new(color.teal, 0), 1)
else
if not na(tpLine2)
line.delete(tpLine2)
tpLine2 := na
if use_tp3 and tp3 > 0
tpLine3 := f_stickyHLine(tp3, tpLine3, color.new(color.teal, 0), 1)
else
if not na(tpLine3)
line.delete(tpLine3)
tpLine3 := na
if use_tp4 and tp4 > 0
tpLine4 := f_stickyHLine(tp4, tpLine4, color.new(color.teal, 0), 1)
else
if not na(tpLine4)
line.delete(tpLine4)
tpLine4 := na
if use_tp5 and tp5 > 0
tpLine5 := f_stickyHLine(tp5, tpLine5, color.new(color.teal, 0), 1)
else
if not na(tpLine5)
line.delete(tpLine5)
tpLine5 := na
// ====== Build HUD Text ======
string txt = ""
// Per-entry rows
for i = 0 to 3
if array.get(ens, i) and array.get(entries, i) > 0
idx = i + 1
ent = array.get(entries, i)
pct = array.get(pcts, i)
pnlq = array.get(pnls, i)
roi = array.get(rois, i)
levX = array.get(levs, i)
txt += (txt=="" ? "" : "\n") + "📌 Entry " + str.tostring(idx) + ": " + str.tostring(ent, format.mintick)
txt += "\n 📊 Live: " + (na(pct) ? "—" : str.tostring(pct, format.mintick) + "%") + " | 💵 " + (na(pnlq) ? "—" : "$" + f_usd_str(pnlq, usd_dp))
txt += "\n 🧮 ROI(x" + str.tostring(levX) + "): " + (na(roi) ? "—" : str.tostring(roi, format.mintick) + "%")
// Summary or test HUD
if txt != ""
if totalQty > 0
txt += "\n— — —"
txt += "\n⚖️ Weighted Avg Entry: " + str.tostring(wAvgEntry, format.mintick)
if not na(stop)
txt += "\n❌ SL: " + str.tostring(stop, format.mintick)
// Nearest target (from current price)
string tpInfo = "—"
if not na(nearestTP)
tpInfo := str.tostring(nearestTP, format.mintick) + (na(nearestDistPct) ? "" : " (Δ " + str.tostring(nearestDistPct, format.mintick) + "%)")
txt += "\n🎯 Nearest: " + tpInfo
// R:R (nearest)
if not na(rr)
txt += "\n📐 R:R (nearest): " + str.tostring(rr, format.mintick)
// Avg R:R across all valid TPs (by direction from weighted entry)
if not na(rr_avg)
txt += "\n📐 Avg R:R (all valid TPs): " + str.tostring(rr_avg, format.mintick)
// Totals
txt += "\n🧾 Total P/L: " + "$" + f_usd_str(totalPnlUSD, usd_dp)
txt += "\n🧮 Weighted ROI (by Notional): " + (na(totalROIweighted) ? "—" : str.tostring(totalROIweighted, format.mintick) + "%")
else if force_show_hud
txt := "🧪 HUD is active.\nFill Entry prices or tick ⚡.\nEnable TP/SL to see lines."
// ====== HUD Placement (near live price) ======
var label hud = na
atr_val = nz(ta.atr(atr_len), 0.0)
anchor_price = close
y_pos = na(anchor_price) ? na : anchor_price + (atr_val * hud_off_atr)
x_pos_base = bar_index
off = hud_side == "Right of price" ? hud_off_bars : -hud_off_bars
x_pos = lock_to_last_bar ? (barstate.islast ? (x_pos_base + off) : x_pos_base) : (x_pos_base + off)
// Pick label style by side:
// - Right of price → pointer on LEFT edge → style_label_left
// - Left of price → pointer on RIGHT edge → style_label_right
label_style = hud_side == "Right of price" ? label.style_label_left : label.style_label_right
if not na(y_pos) and txt != ""
if na(hud)
hud := label.new(x_pos, y_pos, txt, xloc=xloc.bar_index, style=label_style, textcolor=hud_txtc, color=hud_bg, size=to_size(hud_font))
else
label.set_x(hud, x_pos)
label.set_y(hud, y_pos)
label.set_text(hud, txt)
label.set_textcolor(hud, hud_txtc)
label.set_color(hud, hud_bg)
label.set_style(hud, label_style)
label.set_size(hud, to_size(hud_font))
else
if not na(hud)
label.delete(hud)
hud := na
Skript nur auf Einladung
Ausschließlich Nutzer mit einer Erlaubnis des Autors können Zugriff auf dieses Script erhalten. Sie müssen diese Genehmigung bei dem Autor beantragen. Dies umfasst üblicherweise auch eine Zahlung. Wenn Sie mehr erfahren möchten, dann sehen Sie sich unten die Anweisungen des Autors an oder kontaktieren Sie hsuyvm direkt.
TradingView empfiehlt NICHT, für die Nutzung eines Scripts zu bezahlen, wenn Sie den Autor nicht als vertrauenswürdig halten und verstehen, wie das Script funktioniert. Sie können außerdem auch kostenlose Open-Source-Alternativen in unseren Community-Scripts finden.
Hinweise des Autors
Warnung: Lesen Sie bitte unseren Guide für "Invite-Only" Scripts, bevor Sie den Zugang beantragen.
Haftungsausschluss
Skript nur auf Einladung
Ausschließlich Nutzer mit einer Erlaubnis des Autors können Zugriff auf dieses Script erhalten. Sie müssen diese Genehmigung bei dem Autor beantragen. Dies umfasst üblicherweise auch eine Zahlung. Wenn Sie mehr erfahren möchten, dann sehen Sie sich unten die Anweisungen des Autors an oder kontaktieren Sie hsuyvm direkt.
TradingView empfiehlt NICHT, für die Nutzung eines Scripts zu bezahlen, wenn Sie den Autor nicht als vertrauenswürdig halten und verstehen, wie das Script funktioniert. Sie können außerdem auch kostenlose Open-Source-Alternativen in unseren Community-Scripts finden.
Hinweise des Autors
Warnung: Lesen Sie bitte unseren Guide für "Invite-Only" Scripts, bevor Sie den Zugang beantragen.