PnL and Buy & Hold Tracker
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Fedra_Algotrading

//@version=5

indicator('PnL Tracker', 'PnL Tracker 2.5', overlay = true, format=format.price, precision=2, max_labels_count=500)
/////////Source and lenght of the MAs

MAsource = input.source(close, title= "MAs Source", group='MA Settings')
emaLength = input.int(title='Fast MA Length', defval=20, group='MA Settings')
emaLength2 = input.int(title='Slow MA Length', defval=100, step=10, group='MA Settings')

///////Set variables
var totalPnl = 0.0 //This variable will store the cumulative PnL
var hold = 0.0 // This variable will store the price of the firs BUY signal
var tradecloseprice = 0.0// this variable will store the opening price of a trade
var pnlPos = 0
var pnlNeg = 0
var totalTrades = 0
winratio = pnlPos/pnlNeg


byh = (((close-hold)/hold)*100)// Buy & Hold calculation


//////////Set MA type
string i_maType = input.string("SMA", "Fast MA type", options = ["SMA","EMA", "RMA", "WMA","HMA", "CHANGE","CMO","COG","DEV","HIGHEST","LOWEST","MEDIAN","MOM","RANGE","STDEV","VARIANCE"], group='MA Settings to determine downtrend (BUY & SELL)')

float ma = switch i_maType
	"SMA" => ta.sma(MAsource, emaLength)
	"EMA" => ta.ema(MAsource, emaLength)
	"RMA" => ta.rma(MAsource, emaLength)
	"HMA" => ta.hma(MAsource, emaLength)
	"CHANGE" => ta.change(MAsource, emaLength)
	"CMO" => ta.cmo(MAsource, emaLength)
	"COG" => ta.cog(MAsource, emaLength)
	"DEV" => ta.dev(MAsource, emaLength)
	"HIGHEST" => ta.highest(MAsource, emaLength)
	"LOWEST" => ta.lowest(MAsource, emaLength)
	"MEDIAN" => ta.median(MAsource, emaLength)
	"MOM" => ta.mom(MAsource, emaLength)
    "RANGE" => ta.range(MAsource, emaLength)
    "STDEV" => ta.stdev(MAsource, emaLength)
    "VARIANCE" => ta.variance(MAsource, emaLength)
	// Default used when the three first cases do not match.
	=> ta.wma(MAsource, emaLength)


string i_maType2 = input.string("SMA", "Slow MA type", options = ["SMA","EMA","RMA", "WMA","HMA", "CHANGE", "CMO","COG","DEV","HIGHEST","LOWEST","MEDIAN", "MOM","RANGE","STDEV","VARIANCE"], group='MA Settings to determine downtrend (BUY & SELL)')

float ma2 = switch i_maType2
	"SMA" => ta.sma(MAsource, emaLength2)
	"EMA" => ta.ema(MAsource, emaLength2)
	"RMA" => ta.rma(MAsource, emaLength2)
	"HMA" => ta.hma(MAsource, emaLength2)
	"CHANGE" => ta.change(MAsource, emaLength2)
	"CMO" => ta.cmo(MAsource, emaLength2)
	"COG" => ta.cog(MAsource, emaLength2)
	"DEV" => ta.dev(MAsource, emaLength2)
	"HIGHEST" => ta.highest(MAsource, emaLength2)
	"LOWEST" => ta.lowest(MAsource, emaLength2)
	"MEDIAN" => ta.median(MAsource, emaLength2)
	"MOM" => ta.mom(MAsource, emaLength2)
	"RANGE" => ta.range(MAsource, emaLength2)
	"STDEV" => ta.stdev(MAsource, emaLength2)
	"VARIANCE" => ta.variance(MAsource, emaLength2)
	// Default used when the three first cases do not match.
	=> ta.wma(MAsource, emaLength2)

///Set BUY crossover
EMAbuy = ta.crossover(ma,ma2)
///Set SELL crossover
EMAsell = ta.crossunder(ma,ma2)
////Plot the MAs
line1 = plot(ma, linewidth=2, color=color.new(color.yellow, 0))
line2 = plot(ma2, linewidth=2, color=color.new(color.blue, 0))
fill(line1, line2, color = ma > ma2 ? color.green : color.red, transp=85)

///Set variables to track satus of an operation
var S_sell = false
var S_buy = false
///////Set BUY and SELL conditions (crossover + operation open/closed)
buyalert = not S_sell and EMAbuy
sellalert = not S_buy and EMAsell


////Track the unrealized PnL
if close > 0 and not S_buy
    tplabel = label.new(x=bar_index[0], y=high[0]+high[0]*0.02, color=color.gray, textcolor=color.white, style=label.style_label_down, text='Unr.PnL: ' + str.tostring(((close-tradecloseprice)/tradecloseprice)*100)+'%')
    tplabel 
    label.delete(tplabel[1])
////Plot Buy Label with the opening price, store the opening price in a variable and change the trade position to open
if buyalert
    buylabel = label.new(x=bar_index, y=low[0] - low[0]*0.02, color=color.blue, textcolor=color.white, style=label.style_label_up, text='BUY :' + str.tostring(close))
    buylabel
    tradecloseprice := close 
    S_sell := true
    S_buy := false
    //////////Store the price of the first trade
    if totalPnl == 0.0
        hold := close
    
////Plot Buy Label with the PnL of a trade, and change the trade position to flat
if sellalert and tradecloseprice != 0.0
    sell_label = label.new(x=bar_index[0], y=high[0] + high[0] * 0.02, color=color.green, textcolor=color.white, style=label.style_label_down, text='PnL: ' + str.tostring(((close-tradecloseprice)/tradecloseprice)*100)+'%')
    
    sell_label
    S_sell := false
    S_buy := true
    pnl = (((close-tradecloseprice)/tradecloseprice)*100)
    totalTrades := totalTrades +1//Adding to the total closed trades counter
    
    if pnl >= tradecloseprice
        pnlPos := pnlPos +1//Adding to the positive trades counter
    else
        pnlNeg := pnlNeg +1//Adding to the negative trades counter
    
    //Change the color of the closing label to green if is a win or red if is a loose
    if pnl > tradecloseprice
        label.set_color(sell_label, color= color.green)
    else
        label.set_color(sell_label, color= color.red)
    
    totalPnl := totalPnl + pnl ///Add the PnL of the last trade to the cumulative PnL



var pnlTable = table.new(position = position.top_right, columns = 4, rows = 2, border_color = color.white, border_width = 1) ///Define the table

table.cell(table_id = pnlTable, column = 0, row = 0, bgcolor = color.gray, text_color = color.white, text = "Closed Trades")
table.cell(table_id = pnlTable, column = 1, row = 0, bgcolor = color.green,  text_color = color.white, text = "Profit Factor")
table.cell(table_id = pnlTable, column = 2, row = 0, bgcolor = color.gray, text_color = color.white, text = "Cumulative PnL")
table.cell(table_id = pnlTable, column = 3, row = 0, bgcolor = color.gray,  text_color = color.white, text = "Buy & Hold")
table.cell(table_id = pnlTable, column = 0, row = 1, bgcolor = color.gray, text = str.tostring(totalTrades))
table.cell(table_id = pnlTable, column = 1, row = 1, bgcolor = color.gray, text_color = color.yellow, text = str.tostring(winratio))
table.cell(table_id = pnlTable, column = 2, row = 1, bgcolor = color.gray, text = str.tostring(totalPnl)+'%')
table.cell(table_id = pnlTable, column = 3, row = 1, bgcolor = color.gray, text_color = color.yellow, text = str.tostring(byh)+'%')
///Change the PnL cell color to green if its positive or red if its negative
if totalPnl > 0
    table.cell_set_bgcolor(pnlTable, column = 2, row = 1, bgcolor = color.green) 
else
    table.cell_set_bgcolor(pnlTable, column = 2, row = 1, bgcolor = color.red) 
if winratio > 1
    table.cell_set_bgcolor(pnlTable, column = 1, row = 1, bgcolor = color.green) 
else
    table.cell_set_bgcolor(pnlTable, column = 1, row = 1, bgcolor = color.red) 
