Ultimate P&L Indicator
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Steversteves

//@version=5
indicator("Ultimate P&L Indicator")


// Input Ticker Data

ticker = input.symbol("", title="Ticker 1", group = "Position Demographics")
dateandtime = input.time(timestamp("Feb 2023 12:00"), title="Position Date & Time", group = "Position Demographics", tooltip = "This is optional; however, input of the time and date will omit irrelevant data and give you more accurate assessments of your high and low P&L history")
tickerclose = request.security(ticker, "", close, lookahead=barmerge.lookahead_on)

// Position Type 
futurestrading = input.bool(false, title="Futures Trading", group = "Position Type", tooltip = "If you are trading futures, be sure to adjust the tick size and index point variables below to account for the futures contract you are trading")
shareposition = input.bool(true, "Share Position", group = "Position Type")
longposition = input.bool(true, "Long Position", group = "Position Type")
shortposition = input.bool(false, "Short Position", group = "Position Type")
// Input Position Data 

avgcost = input.float(20, title="Ticker Avgerage Cost Basis", group = "Position Variables")
possize = input.int(100, title="Ticker Position Size", group = "Position Variables") 
lookback = input.int(5000, title="Lookback Period", group = "Position Variables") 

// DCA Adjustments 

autodca = input.bool(false, "Automatically Estimate DCA", group = "Additions to Position") 
manualdca = input.bool(true, "Manually Calculcate DCA", group = "Additions to Position") 
dcaadd = input.float(1, title="Added Share Cost", group = "Additions to Position") 
shareadd = input.float(1, title="Number of Added Shares", group = "Additions to Position")


// Long Position 
var tickerpl = 0.0 

tickerdca = avgcost * possize 
tickervalue = tickerclose * possize 

if time>= dateandtime 
    tickerpl := tickervalue - tickerdca  

// Short Position 

var shorttickerpl = 0.0 

if time>= dateandtime 
    shorttickerpl := tickerdca - tickervalue 

// Futures specific P&L 

ticksize = input.float(0.25, title="Tick Size", group = "Futures Adjustments", tooltip = "Tick size on ES1! Mini is 0.25, on WTI Oil it is 1 cent and on MNQ is 2")
indexpoint = input.float(50, title="Index Point", group = "Futures Adjustments", tooltip = "Tick size on ES1! Mini is 50, on WTI Oil it is 1,000 and on MNQ it is 0.5")

tickmovement = ticksize * indexpoint 

futureslongpl = (tickerpl / ticksize) * tickmovement 
futuresshortpl = (shorttickerpl / ticksize) * tickmovement 

// Max and Min 

var maxreturnlong = 0.0 
var minreturnlong = 0.0 
var maxreturnshort = 0.0 
var  minreturnshort = 0.0 

var maxreturnlongfutures = 0.0 
var maxreturnshortfutures = 0.0
var minreturnlongfutures = 0.0 
var minreturnshortfutures = 0.0  

if time >= dateandtime 
    maxreturnlong := ta.highest(tickerpl, lookback) 
    minreturnlong := ta.lowest(tickerpl, lookback) 

    maxreturnshort := ta.highest(shorttickerpl, lookback) 
    minreturnshort := ta.lowest(shorttickerpl, lookback) 

    maxreturnlongfutures := ta.highest(futureslongpl, lookback)
    maxreturnshortfutures := ta.highest(futuresshortpl, lookback) 

    minreturnlongfutures := ta.lowest(futureslongpl, lookback)
    minreturnshortfutures := ta.lowest(futuresshortpl, lookback)


// % Return 

longreturn = (tickervalue - tickerdca) / tickerdca * 100 
shortreturn = (tickerdca - tickervalue) / tickervalue * 100 

longreturnfutures = (futureslongpl / tickerdca) * 100 
shortreturnfutures = (futuresshortpl / tickerdca) * 100 

// Colours 
color bull = color.new(color.lime, 0) 
color bear = color.new(color.red, 0) 
weakGreen   = color.rgb(76, 175, 80, 25)
blue        = color.rgb(20, 123, 134, 25)
red         = color.new(color.red, 80) 
green       = color.new(color.lime, 80)
white       = color.new(color.white, 0)
aqua        = color.new(color.aqua, 85) 

// Plots

plot(longposition and shareposition ? tickerpl : na, "Long Position Plot", style=plot.style_area, color = tickerpl > 0 ? bull : bear, linewidth=3) 
plot(shortposition and shareposition ? shorttickerpl : na, "Short Position Plot", style=plot.style_area, color = shorttickerpl > 0 ? bull : bear, linewidth=3) 
plot(longposition and futurestrading ? futureslongpl : na, "Long Position Plot", style=plot.style_area, color = futureslongpl > 0 ? bull : bear, linewidth=3) 
plot(shortposition and futurestrading ? futuresshortpl : na, "Short Position Plot", style=plot.style_area, color = futuresshortpl > 0 ? bull : bear, linewidth=3)

// DCA Assessments 

dcaautocalc = (shareadd * tickerclose) 
dcaautoadjust = (dcaautocalc + tickerdca) / (possize + shareadd)

dcamanualcalc = (shareadd * dcaadd) 
dcamanualadjust = (dcamanualcalc + tickerdca) / (possize + shareadd) 

dcalongdifauto = (avgcost - dcaautoadjust) / dcaautoadjust * 100 
dcashortdifauto = (dcaautoadjust - avgcost) / avgcost * 100

dcalongdifman = (avgcost - dcamanualadjust) / dcamanualadjust * 100
dcashortdifman = (dcamanualadjust - avgcost) / avgcost * 100


// Alerts 

percentdown = input.float(1, title="Percentage Down Alert", group = "Condition Alerts", tooltip = "Minimum % you want to maintain for your position, falling below this level will trigger your alert") 
percentup = input.float(1, title="Percentage Up Alert", group = "Condition Alerts", tooltip = "Max desired % you want your position to realize, crossing this % will trigger this alert") 

bool longpercentdown = longreturn <= percentdown 
bool shortpercentdown = shortreturn <= percentdown

bool longpercentup = longreturn >= percentup
bool shortpercentup = shortreturn >= percentup

bool dcabelowcurrent = dcaautoadjust < avgcost 
bool dcaabovecurrent = dcaautoadjust > avgcost 

alertcondition(longposition ? dcabelowcurrent : shortposition ? dcaabovecurrent : na, title="Auto DCA Improved", message = "Estimated DCA is improved from current DCA")
alertcondition(longposition ? longpercentdown : shortposition ? shortpercentdown : na, title="Drop Below Desired %", message="Ticker has dropped below desired percent") 
alertcondition(longposition ? longpercentup : shortposition ? shortpercentup : na, title="Rise Above Desired %", message="Ticker has risen above desired percent")


// P&L table

showTable     = input.bool(true, "Show Table")
tablePosInput = input.string(title="Position", defval="Top Right", options=["Bottom Left", "Bottom Right", "Top Left", "Top Right"], tooltip="Select where you want the table to draw.")
var tablePos  = tablePosInput == "Bottom Left" ? position.bottom_left : tablePosInput == "Bottom Right" ? position.bottom_right : tablePosInput == "Top Left" ? position.top_left : tablePosInput == "Top Right" ? position.top_right : na

var dataTable = table.new(tablePos, columns = 4, rows = 10, border_color = color.black, border_width = 2)
if showTable
// Labels
    table.cell(dataTable, 1, 1, text = str.tostring(ticker), bgcolor = weakGreen, text_color = color.white)
    table.cell(dataTable, 2, 1, text = shortposition ? "Short" : longposition ? "Long" : na, bgcolor = weakGreen, text_color = color.white)
    table.cell(dataTable, 1, 2, text = "Open P&L", bgcolor = aqua, text_color = color.white) 
    table.cell(dataTable, 1, 3, text = "% Return", bgcolor = aqua, text_color = white)
    table.cell(dataTable, 1, 4, text = "Position Size", bgcolor = aqua, text_color = white) 
    table.cell(dataTable, 1, 5, text = "DCA", bgcolor = aqua, text_color = white)
    table.cell(dataTable, 1, 6, text = "Highest", bgcolor = aqua, text_color = white)
    table.cell(dataTable, 1, 7, text = "Lowest", bgcolor = aqua, text_color = white)
    table.cell(dataTable, 1, 8, text = autodca ? "Auto Adjusted DCA" : manualdca ? "Manual DCA" : na, bgcolor = aqua, text_color = white)
    table.cell(dataTable, 1, 9, text = "DCA % Dif", bgcolor = aqua, text_color = white)
// Position 
    table.cell(dataTable, 2, 2, text = longposition and shareposition ? str.tostring(math.round(tickerpl, 2)) : shortposition and shareposition ? str.tostring(math.round(shorttickerpl, 2)) : longposition and futurestrading ? str.tostring(math.round(futureslongpl, 2)) : shortposition and futurestrading ? str.tostring(math.round(futuresshortpl, 2)) : na, bgcolor = longposition and tickerpl > 0 ? green : shortposition and shorttickerpl > 0 ? green : red, text_color = white)
    table.cell(dataTable, 2, 3, text = longposition and shareposition ? str.tostring(math.round(longreturn, 2)) : shortposition and shareposition ? str.tostring(math.round(shortreturn, 2)) : longposition and futurestrading ? str.tostring(math.round(longreturnfutures, 2)) : shortposition and futurestrading ? str.tostring(math.round(shortreturnfutures,2)) : na, bgcolor = longposition and tickerpl > 0 ? green : shortposition and shorttickerpl > 0 ? green : red, text_color = white)
    table.cell(dataTable, 2, 4, text = str.tostring(possize), bgcolor = blue, text_color = white)
    table.cell(dataTable, 2, 5, text = str.tostring(avgcost), bgcolor = blue, text_color = white)
    table.cell(dataTable, 2, 6, text = longposition and shareposition ? str.tostring(math.round(maxreturnlong, 2)) : shortposition and shareposition ? str.tostring(math.round(maxreturnshort, 2)) : longposition and futurestrading ? str.tostring(math.round(maxreturnlongfutures, 2)) : shortposition and futurestrading ? str.tostring(math.round(maxreturnshortfutures, 2)) : na, bgcolor = blue, text_color = white)
    table.cell(dataTable, 2, 7, text = longposition and shareposition ? str.tostring(math.round(minreturnlong, 2)) : shortposition and shareposition ? str.tostring(math.round(minreturnshort, 2)) : longposition and futurestrading ? str.tostring(math.round(minreturnlongfutures, 2)) : shortposition and futurestrading ? str.tostring(math.round(minreturnshortfutures, 2)) : na, bgcolor = longposition and minreturnlong < 0 ? red : longposition and minreturnlong > 0 ? green : shortposition and minreturnshort < 0 ? red : shortposition and minreturnshort > 0 ? green : blue, text_color = white)
    table.cell(dataTable, 2, 8, text = autodca ? str.tostring(math.round(dcaautoadjust, 2)) : manualdca ? str.tostring(math.round(dcamanualadjust, 2)) : na, bgcolor = aqua, text_color = white)
    table.cell(dataTable, 2, 9, text = longposition and autodca ? str.tostring(math.round(dcalongdifauto, 2)) : shortposition and autodca ? str.tostring(math.round(dcashortdifauto , 2)) : longposition and manualdca ? str.tostring(math.round(dcalongdifman, 2)) : shortposition and manualdca ? str.tostring(math.round(dcashortdifman, 2)) : na, bgcolor = blue, text_color = white)

// Price Table 
    var pricetable = table.new(position.bottom_left, columns = 3, rows = 3, border_color = color.black, border_width = 2)
    // Labels
    table.cell(pricetable, 1, 2, text = "Current Price", bgcolor = blue, text_color = white)
    // Price
    table.cell(pricetable, 2, 2, text = str.tostring(tickerclose), bgcolor = green, text_color = white)