INVITE-ONLY SCRIPT
Telah dikemas kini

پنل سود/زیان + چند تارگت R:R

14
//version=6
indicator("پنل سود/زیان + چند تارگت (۴ ورود مستقل) - پنل چپ نزدیک قیمت + میانگین R:R", overlay=true, max_lines_count=500, max_labels_count=500)

// ====== تنظیمات عمومی ======
side = input.string("لانگ", "نوع پوزیشن", options=["لانگ","شورت"])
usd_dp = input.int(2, "تعداد اعشار نمایش دلار", minval=0, maxval=6)

// ====== تنظیمات پنل ======
hud_font = input.string("large", "اندازۀ فونت پنل", options=["tiny","small","normal","large","huge"])
hud_bg = input.color(color.new(color.black, 0), "رنگ پس‌زمینه پنل")
hud_txtc = input.color(color.white, "رنگ متن پنل")

// محل پنل: کمی «چپِ» آخرین کندل + کمی فاصله عمودی از قیمت
hud_off_bars = input.int(3, "فاصلۀ افقی از قیمت به سمت چپ (تعداد کندل، فقط روی آخرین کندل)", minval=0, maxval=50)
hud_off_atr = input.float(0.2, "فاصلۀ عمودی از قیمت (ATR)", step=0.1)
atr_len = input.int(14, "طول ATR برای فاصله عمودی", minval=1)

// نمایش اجباری پنل حتی بدون ورود
force_show_hud = input.bool(true, "🔍 نمایش اجباری پنل حتی بدون ورود")

// ====== حد ضرر و تارگت‌های مشترک ======
stop_inp = input.float(0.0, "حد ضرر (مشترک، اختیاری)", step=0.0001)
use_tp1 = input.bool(false, "فعال‌سازی تارگت ۱")
tp1 = input.float(0.0, "قیمت تارگت ۱", step=0.0001)
use_tp2 = input.bool(false, "فعال‌سازی تارگت ۲")
tp2 = input.float(0.0, "قیمت تارگت ۲", step=0.0001)
use_tp3 = input.bool(false, "فعال‌سازی تارگت ۳")
tp3 = input.float(0.0, "قیمت تارگت ۳", step=0.0001)
use_tp4 = input.bool(false, "فعال‌سازی تارگت ۴")
tp4 = input.float(0.0, "قیمت تارگت ۴", step=0.0001)
use_tp5 = input.bool(false, "فعال‌سازی تارگت ۵")
tp5 = input.float(0.0, "قیمت تارگت ۵", step=0.0001)

// ====== ورودی‌های ۴ ورود مستقل ======
group1 = "ورود ۱"
en1 = input.bool(true, "فعال‌سازی ورود ۱", inline=group1)
lev1 = input.int(10, "لوریج", minval=1, maxval=200, inline=group1)
entry1 = input.float(0.0, "قیمت ورود ۱", step=0.0001)
set_now1 = input.bool(false, "⚡ ثبت ورود۱ = قیمت فعلی")
mode1 = input.string("دلاری (USDT)", "واحد اندازه ۱", options=["دلاری (USDT)","تعداد کوین"])
sem1 = input.string("مارجین (اعمال لوریج)", "تعبیر اندازه ۱", options=["مارجین (اعمال لوریج)","ناتیونال (از قبل لوریج شده)"])
size1 = input.float(0.0, "اندازه پوزیشن ۱", step=0.0001)
baseLev1 = input.bool(false, "اعمال لوریج روی حالت «تعداد کوین» (۱)")

group2 = "ورود ۲"
en2 = input.bool(false, "فعال‌سازی ورود ۲", inline=group2)
lev2 = input.int(10, "لوریج", minval=1, maxval=200, inline=group2)
entry2 = input.float(0.0, "قیمت ورود ۲", step=0.0001)
set_now2 = input.bool(false, "⚡ ثبت ورود۲ = قیمت فعلی")
mode2 = input.string("دلاری (USDT)", "واحد اندازه ۲", options=["دلاری (USDT)","تعداد کوین"])
sem2 = input.string("مارجین (اعمال لوریج)", "تعبیر اندازه ۲", options=["مارجین (اعمال لوریج)","ناتیونال (از قبل لوریج شده)"])
size2 = input.float(0.0, "اندازه پوزیشن ۲", step=0.0001)
baseLev2 = input.bool(false, "اعمال لوریج روی حالت «تعداد کوین» (۲)")

group3 = "ورود ۳"
en3 = input.bool(false, "فعال‌سازی ورود ۳", inline=group3)
lev3 = input.int(10, "لوریج", minval=1, maxval=200, inline=group3)
entry3 = input.float(0.0, "قیمت ورود ۳", step=0.0001)
set_now3 = input.bool(false, "⚡ ثبت ورود۳ = قیمت فعلی")
mode3 = input.string("دلاری (USDT)", "واحد اندازه ۳", options=["دلاری (USDT)","تعداد کوین"])
sem3 = input.string("مارجین (اعمال لوریج)", "تعبیر اندازه ۳", options=["مارجین (اعمال لوریج)","ناتیونال (از قبل لوریج شده)"])
size3 = input.float(0.0, "اندازه پوزیشن ۳", step=0.0001)
baseLev3 = input.bool(false, "اعمال لوریج روی حالت «تعداد کوین» (۳)")

group4 = "ورود ۴"
en4 = input.bool(false, "فعال‌سازی ورود ۴", inline=group4)
lev4 = input.int(10, "لوریج", minval=1, maxval=200, inline=group4)
entry4 = input.float(0.0, "قیمت ورود ۴", step=0.0001)
set_now4 = input.bool(false, "⚡ ثبت ورود۴ = قیمت فعلی")
mode4 = input.string("دلاری (USDT)", "واحد اندازه ۴", options=["دلاری (USDT)","تعداد کوین"])
sem4 = input.string("مارجین (اعمال لوریج)", "تعبیر اندازه ۴", options=["مارجین (اعمال لوریج)","ناتیونال (از قبل لوریج شده)"])
size4 = input.float(0.0, "اندازه پوزیشن ۴", step=0.0001)
baseLev4 = input.bool(false, "اعمال لوریج روی حالت «تعداد کوین» (۴)")

// ثبت سریع ورود = قیمت فعلی
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

// ====== کمک‌تابع‌ها ======
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 == "دلاری (USDT)"
_qty := (size > 0 and entry > 0) ? ((sem == "مارجین (اعمال لوریج)" ? 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 == "دلاری (USDT)"
sem == "مارجین (اعمال لوریج)" ? size * lev : size
else
(baseLev ? size * lev : size) * entry

f_pnl_quote(side, entry, qty) =>
na(qty) or na(entry) ? na : (side=="لانگ" ? (close - entry) : (entry - close)) * qty

f_pct(side, entry) =>
na(entry) ? na : ((close - entry) / entry * 100.0) * (side=="لانگ" ? 1 : -1)

f_roi_pct(side, entry, lev) =>
na(entry) ? na : f_pct(side, entry) * lev

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

// ====== محاسبات ۴ ورود ======
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)

// ====== مجموع و میانگین ورود وزنی ======
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

// ====== نزدیک‌ترین تارگت و 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)

// نزدیک‌ترین تارگت همسو با جهت
if array.size(tps) > 0
for i = 0 to array.size(tps) - 1
_tp = array.get(tps, i)
cond = side=="لانگ" ? (_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=="لانگ" ? (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=="لانگ" ? (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

// ====== «میانگین R:R» روی همه تارگت‌های معتبر ======
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=="لانگ" ? (_tp > wAvgEntry) : (_tp < wAvgEntry)
if validDir
_reward = math.abs((side=="لانگ" ? (_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

// ====== خطوط ورود/SL/TP ======
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

// ====== ساخت متن پنل ======
string txt = ""

// ردیف‌های هر ورود
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") + "📌 ورود " + str.tostring(idx) + ": " + str.tostring(ent, format.mintick)
txt += "\n 📊 لحظه‌ای: " + (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) + "%")

// خلاصه پایانی یا پنل تست
if txt != ""
if totalQty > 0
txt += "\n— — —"
txt += "\n⚖️ میانگین ورود وزنی: " + str.tostring(wAvgEntry, format.mintick)
if not na(stop)
txt += "\n❌ SL: " + str.tostring(stop, format.mintick)

// نزدیک‌ترین تارگت
string tpInfo = "—"
if not na(nearestTP)
tpInfo := str.tostring(nearestTP, format.mintick) + (na(nearestDistPct) ? "" : " (Δ " + str.tostring(nearestDistPct, format.mintick) + "%)")
txt += "\n🎯 نزدیک‌ترین: " + tpInfo

// R:R نزدیک‌ترین
if not na(rr)
txt += "\n📐 R:R نزدیک‌ترین: " + str.tostring(rr, format.mintick)

// میانگین R:R روی همه تارگت‌های معتبر
if not na(rr_avg)
txt += "\n📐 میانگین R:R (همۀ تارگت‌های معتبر): " + str.tostring(rr_avg, format.mintick)

// مجموع‌ها
txt += "\n🧾 مجموع سود/زیان: " + "$" + f_usd_str(totalPnlUSD, usd_dp)
txt += "\n🧮 ROĪ وزنی (بر اساس ناتیونال): " + (na(totalROIweighted) ? "—" : str.tostring(totalROIweighted, format.mintick) + "%")
else if force_show_hud
txt := "🧪 پنل فعال است.\nاز فیلدهای «قیمت ورود» استفاده کن یا تیک‌های ⚡ را بزن.\nبرای دیدن TP/SL خطوط، تیک‌های مربوطه را فعال کن."

// ====== HUD (پنل سمت چپ، نوک اشاره نزدیک قیمت لحظه‌ای) ======
// ====== HUD (پنل سمت راست، نوک اشاره نزدیک قیمت لحظه‌ای) ======
var label hud = na
atr_val = ta.atr(atr_len)

// لنگر عمودی روی قیمت لحظه‌ای با کمی فاصله عمودی
anchor_price = close
y_pos = na(anchor_price) ? na : anchor_price + (atr_val * hud_off_atr)

// فقط روی آخرین کندل، چند بار به «راست» می‌بریم تا نوک پنل نزدیک کندل باشد
x_pos_base = bar_index
x_pos = barstate.islast ? (x_pos_base + hud_off_bars) : x_pos_base

if not na(y_pos) and txt != ""
if na(hud)
// ⚠️ style_label_left = نوک پنل سمت چپ است ⇒ متن به راست باز می‌شود ⇒ کل پنل در «راستِ» قیمت قرار می‌گیرد
hud := label.new(x_pos, y_pos, txt,xloc=xloc.bar_index,style=label.style_label_left, 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_left)
label.set_size(hud, to_size(hud_font))
else
if not na(hud)
label.delete(hud)
hud := na
Nota Keluaran
//version=6
indicator("پنل سود/زیان + چند تارگت (۴ ورود مستقل) - پنل چپ نزدیک قیمت + میانگین R:R + وزن خروج (v1.3.1-minFixed)", overlay=true, max_lines_count=500, max_labels_count=500)

Penafian

Maklumat dan penerbitan adalah tidak dimaksudkan untuk menjadi, dan tidak membentuk, nasihat untuk kewangan, pelaburan, perdagangan dan jenis-jenis lain atau cadangan yang dibekalkan atau disahkan oleh TradingView. Baca dengan lebih lanjut di Terma Penggunaan.