% / ATR Buy, Target, Stop + Overlay & P/L

% / ATR Buy, Target, Stop + Overlay & P/L

This tool combines volatility‑based and fixed‑percentage trade planning into a single, on‑chart overlay—with built‑in profit‑and‑loss estimates. Toggle between ATR or percentage modes, plot your Buy, Target and Stop levels, and see the dollar gain or loss for a specified position size—all in one interactive table and chart display.

NOTE: To activate plotted lines, price labels, P/L rows and table values, enter a Buy Price greater than zero.



What It Does

Mode Toggle: Choose between “ATR” (volatility‑based) or “%” (fixed‑percentage) calculations.

Buy Price Input: Manually enter your entry price.

ATR Mode:

Target = Buy + (ATR × Target Multiplier)

Stop = Buy − (ATR × Stop Multiplier)

Percentage Mode:

Target = Buy × (1 + Target % / 100)

Stop = Buy × (1 – Stop % / 100)

P/L Estimates: Specify a dollar amount to “invest” at your Buy price, and the script calculates:

Gain ($): Profit if Target is hit

Loss ($): Cost if Stop is hit

Visual Overlay: Draws horizontal lines for Buy, Target and Stop, with optional price labels on the chart scale.

Interactive Table: Displays Buy, Target, Stop, ATR/timeframe info (in ATR mode), percentages (in % mode), and P/L rows.



Customization Options

Line Settings:

Choose color, style (solid/dashed/dotted), and width for Buy, Target, Stop lines.

Extend lines rightward only or in both directions.

Table Settings:

Position the table (top/bottom × left/right).

Toggle individual rows: Buy Price; Target (multiplier or %); Stop (multiplier or %); Target ATR %; Stop ATR %; ATR Time Frame; ATR Value; Gain ($); Loss ($).

Customize text colors for each row and background transparency.

General Inputs:

ATR length and optional ATR timeframe override (e.g. use daily ATR on an intraday chart).

Target/Stop multipliers or percentages.

Dollar Amount for P/L calculations.



How to Use It for Trading

Plan Your Entry: Enter your intended Buy Price and position size (dollar amount).

Select Mode: Toggle between ATR or % mode depending on whether you prefer volatility‑based or fixed offsets.

Assess R:R and P/L: Instantly see your Target, Stop levels, and potential profit or loss in dollars.

Visual Reference: Lines and price labels update in real time as you tweak inputs—ideal for live trading, backtesting or trade journaling.



Ideal For

Traders who want both volatility‑based and percentage‑based exit options in one tool

Those who need on‑chart P/L estimates based on position size

Swing and intraday traders focused on objective, rule‑based trade management

Anyone who uses ATR for adaptive stops/targets or fixed percentages for simpler exits

Jul 23

Release Notes

Version Updates:

Added ATR Smoothing Options (“RMA”, “SMA”, “EMA”, “WMA”)

Removed random line settings from the “Styles” tab.

Jul 23

Release Notes

Cleaned up settings screen

// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0
// © abbadon9 [If you modify this script please acknowledge me.]

//@version=6
indicator("% / ATR Buy, Target, Stop + Overlay & P/L", shorttitle="%/ATR BTS", overlay=true)

// === MODE INPUT ===
mode = input.string("ATR", "Calculation Mode", options=["ATR","%"])

// === COMMON INPUTS ===
buyPriceInput = input.float(title="Buy Price (enter > 0)", defval=0.0)

// === ATR‑SPECIFIC INPUTS ===
atrLength   = input.int(title="ATR Length", defval=14, group="ATR Settings")
atrTF       = input.timeframe("", "ATR Timeframe Override (e.g. 'D', '1h', '5m')", group="ATR Settings")
targetMult  = input.float(title="Target Multiplier (ATR)", defval=1.5, group="ATR Settings")
stopMult    = input.float(title="Stop Multiplier (ATR)", defval=0.5, group="ATR Settings")
atrSmoothing = input.string("RMA", title="ATR Smoothing Method", options=["RMA","SMA","EMA","WMA"], group="ATR Settings")

// === PERCENTAGE‑SPECIFIC INPUTS ===
targetPct   = input.float(title="Target Percentage (%)", defval=1.5, group="Percentage Settings")
stopPct     = input.float(title="Stop Percentage (%)", defval=0.5, group="Percentage Settings")

// === DOLLAR AMOUNT INPUT ===
dollarAmt   = input.float(title="Dollar Amount", defval=10000.0, group="Gain / Loss Calculation")

// === LINE EXTENSION INPUT ===
extendBoth   = input.bool(false, title="Extend Lines Both Directions", group="Line Settings")
extendOption = extendBoth ? extend.both : extend.right

// === BUY LINE INPUTS ===
buyLineColor    = input.color(color.green, title="Buy Line:  Color", group="Line Settings", inline="BL"),
buyLineStyleStr = input.string("dotted", title="Style", options=["solid","dashed","dotted"], group="Line Settings", inline="BL")
buyLineWidth    = input.int(1, title="Width", minval=1, maxval=5, group="Line Settings", inline="BL")
buyLineStyle    = buyLineStyleStr == "dotted" ? line.style_dotted : buyLineStyleStr == "dashed" ? line.style_dashed : line.style_solid

// === TARGET LINE INPUTS ===
targetLineColor    = input.color(color.blue, title="Target Line:  Color", group="Line Settings", inline="TL")
targetLineStyleStr = input.string("dotted", title="Style", options=["solid","dashed","dotted"], group="Line Settings", inline="TL")
targetLineWidth    = input.int(1, title="Width", minval=1, maxval=5, group="Line Settings", inline="TL")
targetLineStyle    = targetLineStyleStr == "dotted" ? line.style_dotted : targetLineStyleStr == "dashed" ? line.style_dashed : line.style_solid

// === STOP LINE INPUTS ===
stopLineColor    = input.color(color.red, title="Stop Line:  Color", group="Line Settings", inline="SL")
stopLineStyleStr = input.string("dotted", title="Style", options=["solid","dashed","dotted"], group="Line Settings", inline="SL")
stopLineWidth    = input.int(1, title="Width", minval=1, maxval=5, group="Line Settings", inline="SL")
stopLineStyle    = stopLineStyleStr == "dotted" ? line.style_dotted : stopLineStyleStr == "dashed" ? line.style_dashed : line.style_solid

// === TABLE TEXT COLORS ===
tablePositionOption = input.string("bottom_right", title="Table Position", options=["top_right","top_left","bottom_right","bottom_left"], group="Table Settings")
buyTextColor              = input.color(color.green, title="Buy Text Color",    group="Table Settings")
targetTextColor           = input.color(color.blue,  title="Target Text Color", group="Table Settings")
stopTextColor             = input.color(color.red,   title="Stop Text Color",   group="Table Settings")
targetATRPercentTextColor = input.color(color.blue,  title="Target ATR % Text Color", group="Table Settings")
stopATRPercentTextColor   = input.color(color.red,   title="Stop ATR % Text Color",   group="Table Settings")
atrRowTextColor           = input.color(color.gray, title="ATR Time Frame Text Color", group="Table Settings")
atrValueRowTextColor      = input.color(color.gray, title="ATR Value Text Color",      group="Table Settings")

// === GAIN/LOSS TEXT COLORS ===
gainTextColor             = input.color(color.green, title="Gain Text Color",  group="Table Settings")
lossTextColor             = input.color(color.red,   title="Loss Text Color",  group="Table Settings")

// === TABLE SETTINGS INPUTS ===
bg_col              = input.color(color.new(color.black, 100), title="Background Color", group="Table Settings")
showTableHeader     = input.bool(true, title="Add Empty Top Spacer Row", group="Table Settings")

// === TABLE ROW TOGGLES ===
showBuyRow              = input.bool(true, title="Show Buy Row",             group="Table Settings")
showTargetRow           = input.bool(true, title="Show Target Row",          group="Table Settings")
showTargetATRPercentRow = input.bool(true, title="Show Target ATR % Row",    group="Table Settings")
showStopRow             = input.bool(true, title="Show Stop Row",            group="Table Settings")
showStopATRPercentRow   = input.bool(true, title="Show Stop ATR % Row",      group="Table Settings")
showATRRow              = input.bool(true, title="Show ATR Time Frame Row",  group="Table Settings")
showATRValueRow         = input.bool(true, title="Show ATR Value Row",       group="Table Settings")
showGainRow             = input.bool(true, title="Show Gain ($) Row",        group="Table Settings")
showLossRow             = input.bool(true, title="Show Loss ($) Row",        group="Table Settings")

// === CALCULATIONS ===
validBuy         = buyPriceInput > 0
buyPrice         = validBuy ? buyPriceInput : na
atrRaw           = atrSmoothing == "RMA" ? ta.rma(ta.tr, atrLength) : atrSmoothing == "SMA" ? ta.sma(ta.tr, atrLength) : atrSmoothing == "EMA" ? ta.ema(ta.tr, atrLength) : ta.wma(ta.tr, atrLength)
atr              = atrTF == "" ? atrRaw : request.security(syminfo.tickerid, atrTF, atrRaw)
targetPriceATR   = validBuy ? buyPrice + atr * targetMult : na
stopPriceATR     = validBuy ? buyPrice - atr * stopMult : na
targetATRPercent = validBuy ? (atr * targetMult / buyPrice) * 100 : na
stopATRPercent   = validBuy ? (atr * stopMult / buyPrice) * 100 : na
targetPricePct   = validBuy ? buyPrice * (1 + targetPct/100) : na
stopPricePct     = validBuy ? buyPrice * (1 - stopPct/100) : na
// select based on mode
targetPrice      = mode == "ATR" ? targetPriceATR : targetPricePct
stopPrice        = mode == "ATR" ? stopPriceATR   : stopPricePct
// dollar‑gain/loss (assumes investing dollarAmt at buyPrice)
shares           = dollarAmt > 0 and validBuy ? dollarAmt / buyPrice : na
gainAmt          = shares * (targetPrice - buyPrice)
lossAmt          = shares * (buyPrice - stopPrice)

// === PLOT LINES ===
var line buyLine    = na
var line targetLine = na
var line stopLine   = na
if barstate.islast
    if not na(buyLine)
        line.delete(buyLine)
    if not na(targetLine)
        line.delete(targetLine)
    if not na(stopLine)
        line.delete(stopLine)
    if validBuy
        buyLine    := line.new(bar_index, buyPrice,    bar_index+1, buyPrice,    color=buyLineColor,    width=buyLineWidth,   style=buyLineStyle)
        targetLine := line.new(bar_index, targetPrice,  bar_index+1, targetPrice, color=targetLineColor, width=targetLineWidth, style=targetLineStyle)
        stopLine   := line.new(bar_index, stopPrice,    bar_index+1, stopPrice,   color=stopLineColor,   width=stopLineWidth,  style=stopLineStyle)
        line.set_extend(buyLine,    extendOption)
        line.set_extend(targetLine, extendOption)
        line.set_extend(stopLine,   extendOption)

// === PRICE LABELS ON SCALE ===
plot(buyPrice,    title="Buy Price Label",    color=color.new(buyLineColor,   100), linewidth=1, trackprice=true, editable=false)
plot(targetPrice, title="Target Price Label", color=color.new(targetLineColor, 100), linewidth=1, trackprice=true, editable=false)
plot(stopPrice,   title="Stop Price Label",   color=color.new(stopLineColor,   100), linewidth=1, trackprice=true, editable=false)

// === TABLE SETUP ===
tablePos = tablePositionOption == "top_right"    ? position.top_right    : tablePositionOption == "top_left"     ? position.top_left     : tablePositionOption == "bottom_right" ? position.bottom_right : position.bottom_left
var table infoTable = table.new(tablePos, 2, (mode == "ATR" ? ((showBuyRow ? 1 : 0) + (showTargetRow ? 1 : 0) + (showTargetATRPercentRow ? 1 : 0) + (showStopRow ? 1 : 0) + (showStopATRPercentRow ? 1 : 0) + (showATRRow ? 1 : 0) + (showATRValueRow ? 1 : 0)) : ((showBuyRow ? 1 : 0) + (showTargetRow ? 1 : 0) + (showStopRow ? 1 : 0))) + (showGainRow ? 1 : 0) + (showLossRow ? 1 : 0) + (showTableHeader ? 1 : 0), border_width=1)

// === TABLE RENDER ===
if validBuy
    row = showTableHeader ? 1 : 0
    if showTableHeader
        table.cell(infoTable, 0, 0, "", bgcolor=bg_col)
        table.cell(infoTable, 1, 0, "", bgcolor=bg_col)
    if showBuyRow
        table.cell(infoTable, 0, row, "Buy Price", text_color=buyTextColor)
        table.cell(infoTable, 1, row, str.tostring(buyPrice, "#.##"), text_color=buyTextColor)
        row += 1
    if showTargetRow
        titleTarget = mode == "ATR" ? "Target (" + str.tostring(targetMult) + "x ATR)" : "Target (" + str.tostring(targetPct) + "%)"
        table.cell(infoTable, 0, row, titleTarget, text_color=targetTextColor)
        table.cell(infoTable, 1, row, str.tostring(targetPrice, "#.##"), text_color=targetTextColor)
        row += 1
    if mode == "ATR" and showTargetATRPercentRow
        table.cell(infoTable, 0, row, "Target ATR %", text_color=targetATRPercentTextColor)
        table.cell(infoTable, 1, row, str.tostring(targetATRPercent, "#.##") + "%", text_color=targetATRPercentTextColor)
        row += 1
    if showStopRow
        titleStop = mode == "ATR" ? "Stop (" + str.tostring(stopMult) + "x ATR)" : "Stop (" + str.tostring(stopPct) + "%)"
        table.cell(infoTable, 0, row, titleStop, text_color=stopTextColor)
        table.cell(infoTable, 1, row, str.tostring(stopPrice, "#.##"), text_color=stopTextColor)
        row += 1
    if mode == "ATR" and showStopATRPercentRow
        table.cell(infoTable, 0, row, "Stop ATR %", text_color=stopATRPercentTextColor)
        table.cell(infoTable, 1, row, str.tostring(stopATRPercent, "#.##") + "%", text_color=stopATRPercentTextColor)
        row += 1
    if mode == "ATR" and showATRRow
        table.cell(infoTable, 0, row, "ATR Time Frame", text_color=atrRowTextColor)
        table.cell(infoTable, 1, row, atrTF == "" ? "Chart" : atrTF, text_color=atrRowTextColor)
        row += 1
    if mode == "ATR" and showATRValueRow
        table.cell(infoTable, 0, row, "ATR Value", text_color=atrValueRowTextColor)
        table.cell(infoTable, 1, row, str.tostring(atr, "#.###"), text_color=atrValueRowTextColor)
        row += 1
    if showGainRow
        table.cell(infoTable, 0, row, "Gain ($)", text_color=gainTextColor)
        table.cell(infoTable, 1, row, str.tostring(gainAmt, "#.##"), text_color=gainTextColor)
        row += 1
    if showLossRow
        table.cell(infoTable, 0, row, "Loss ($)", text_color=lossTextColor)
        table.cell(infoTable, 1, row, str.tostring(lossAmt, "#.##"), text_color=lossTextColor)
        row += 1
else
    table.clear(infoTable, 0, 0)