Statistics Table
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © DinGrogu

//@version=5

library('statistics')

// ############################################################
// # INTERNAL FUNCTIONS
// ############################################################

table_margin(int margin) =>
    margin_string = ''
    for i = 1 to margin
        margin_string := margin_string + ' '
    margin_string

statistics_average_bars_per_trade() =>
    sum_bars_per_trade = 0
    for trade_number = 0 to strategy.closedtrades - 1
        sum_bars_per_trade += strategy.closedtrades.exit_bar_index(trade_number) - strategy.closedtrades.entry_bar_index(trade_number) + 1

    response = math.round(nz(sum_bars_per_trade / strategy.closedtrades))

statistics_maximum_trade_drawdown() =>
    highest_drawdown = 0.0

    for trade_number = 0 to strategy.closedtrades - 1
        trade_price = strategy.closedtrades.entry_price(trade_number) * math.abs(strategy.closedtrades.size(trade_number))
        trade_drawdown = strategy.closedtrades.max_drawdown(trade_number)
        drawdown = trade_drawdown / trade_price * 100

        if (drawdown > highest_drawdown)
            highest_drawdown := drawdown

    response = math.round(highest_drawdown, 2)

statistics_maximum_trade_runup() =>
    highest_runup = 0.0

    for trade_number = 0 to strategy.closedtrades - 1
        trade_price = strategy.closedtrades.entry_price(trade_number) * math.abs(strategy.closedtrades.size(trade_number))
        trade_drawdown = strategy.closedtrades.max_runup(trade_number)
        runup = trade_drawdown / trade_price * 100

        if (runup > highest_runup)
            highest_runup := runup

    response = math.round(highest_runup, 2)

statistics_avg_trade_profit_percent(int _maximum_trades=5000) =>
    profits_list = array.new_float(0)

    for trade_number = 0 to strategy.closedtrades - 1
        if (array.size(profits_list) > _maximum_trades)
            array.remove(profits_list, 0)

        commision = math.abs(strategy.closedtrades.commission(trade_number) / (strategy.netprofit + strategy.closedtrades.commission(trade_number))) * 100
        profit = ((strategy.closedtrades.exit_price(trade_number) - strategy.closedtrades.entry_price(trade_number)) / strategy.closedtrades.entry_price(trade_number)) * 100
        profit := profit - (commision * 2)

        if (profit > 0)
            array.push(profits_list, profit)

    response = array.size(profits_list) > 1 ? math.round(array.avg(profits_list), 2) : 0

// ############################################################
// # EXPORT FUNCTIONS
// ############################################################

// @function - A function to show a table with statistics on strategies.
// @param _initial_capital <float> The initial capital used for trading (usually the value from properties tab).
// @param _src <series float> The source for all calculations (usually close)
// @param _statistics_table_enabled <string> Input value if the table is enabled.
// @param _statistics_table_position <string> Input value for the table position.
// @param _statistics_table_margin <string> Input value for the table margin.
// @param _statistics_table_transparency <string> Input value for the table transparency.
// @param _statistics_table_text_color <series color> Input value for the table cell text color.
// @param _statistics_table_title_cell_color <series color> Input value for the table title cell text color.
// @param _statistics_table_text_color <series color> Input value for the table cell text color.
// @param _statistics_table_cell_color <series color> Input value for the table cell background color.
export table(float _initial_capital, series float _src, string _statistics_table_enabled, string _statistics_table_position, int _statistics_table_margin, int _statistics_table_transparency, series color _statistics_table_text_color, series color _statistics_table_title_cell_color, series color _statistics_table_cell_color) =>
    var green_increase = #26A69A
	var red_increase = #FF5252

	var table_price = 0.0
    table_price := na(table_price[1]) ? na : table_price[1]

    var table_percentage_prefix = ''
    var table_percentage = 0.0
    table_percentage := na(table_percentage[1]) ? na : table_percentage[1]

    var table_bars = '0'
    table_bars := na(table_bars[1]) ? na : table_bars[1]

    if (_statistics_table_enabled == 'YES')
        has_trades = strategy.closedtrades > 0
        open_trade = strategy.position_size != 0

        first_order = strategy.closedtrades.entry_price(0)
        bars_since_closed = has_trades ? bar_index - strategy.closedtrades.exit_bar_index(strategy.closedtrades - 1) + 1 : 0
        bars_since_opened = has_trades ? bar_index - strategy.opentrades.entry_bar_index(strategy.opentrades - 1) + 1 : 0

        order_entry_price = has_trades ? strategy.opentrades.entry_price(strategy.opentrades - 1) : _src
        last_order_exit_price = has_trades ? strategy.closedtrades.exit_price(strategy.closedtrades - 1) : _src
        last_order_price = open_trade ? _src : last_order_exit_price

        //initial_capital = strategy.initial_capital
        final_balance = _initial_capital + strategy.netprofit
        net_profit_percentage = (final_balance - _initial_capital) / _initial_capital * 100
        average_trade_profit_percentage = has_trades ? statistics_avg_trade_profit_percent(100) : 0
        buy_and_hold_percentage = has_trades ? math.round(((last_order_price - first_order) / first_order) * 100, 2) : 0
        profit_factor = has_trades ? math.round(net_profit_percentage / buy_and_hold_percentage, 2) : 0
        win_trades = strategy.wintrades
        loss_trades = strategy.losstrades
        winrate = nz(math.round((win_trades / (win_trades + loss_trades) * 100), 2))

		table_color = color.blue            

        if (open_trade)
			table_price := order_entry_price
            table_percentage := math.abs((order_entry_price - _src) / _src * 100)
			table_bars := str.tostring(nz(bars_since_opened))
			table_color := _src > order_entry_price ? green_increase : red_increase
            table_percentage_prefix := close > order_entry_price ? '' : '-'
        else
			table_price := last_order_exit_price
            table_percentage := math.abs((last_order_exit_price - _src) / _src * 100)
			table_bars := str.tostring(nz(bars_since_closed))
			table_color := _src < last_order_exit_price ? green_increase : red_increase
            table_percentage_prefix := close > last_order_exit_price ? '-' : ''

        var table_width = 0
        var table_margin_right = _statistics_table_margin > 0 ? str.tostring(table_margin(_statistics_table_margin)) : ''
        var table_position = _statistics_table_position == 'LEFT' ? position.bottom_left : position.bottom_right

        var statistics_table_titles = _statistics_table_position == 'LEFT' ? 1 : 0
        var statistics_table_values = _statistics_table_position == 'LEFT' ? 2 : 1
        var statistics_table_offset = _statistics_table_position == 'LEFT' ? 0 : 2

        profit_color = open_trade ? close > order_entry_price ? green_increase : red_increase : _statistics_table_cell_color
        var statistics_table = table.new(table_position, 3, 13, border_width=3)

		table.cell(statistics_table, statistics_table_titles, 0, '    (%) EXIT PRICE    ', width=table_width, bgcolor=color.new(color.white, 100), text_color=color.new(color.white, 100), text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 1, '    ($) TRADE PRICE    ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 2, '    (%) SINCE TRADE    ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 3, '    (B) SINCE TRADE    ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 4, '    (%) NET PROFIT    ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 5, '    (%) BUY & HOLD    ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 6, '    (X) PROFIT FACTOR ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 7, '    (%) WINRATE    ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 8, '    (N) WIN / LOSS    ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 9, '    (B) AVG BARS     ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 10, '    (%) AVG PROFIT   ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 11, '    (%) MAX DRAWDOWN ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)
        table.cell(statistics_table, statistics_table_titles, 12, '    (%) MAX RUNUP   ', width=table_width, bgcolor=_statistics_table_title_cell_color, text_color=_statistics_table_text_color, text_size=size.small, text_halign=text.align_left)

		table.cell(statistics_table, statistics_table_values, 0, '    ' + str.tostring(math.round_to_mintick(table_price)) + '%   ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, 100), text_color=color.new(color.white, 100), text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 1, '    ' + str.tostring(math.round_to_mintick(table_price)) + '    ', width=table_width, bgcolor=color.new(open_trade ? profit_color : _statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 2, '    ' + table_percentage_prefix + str.tostring(table_percentage, '#.##') + '%    ', width=table_width, bgcolor=color.new(open_trade ? profit_color : _statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 3, '    ' + table_bars + '    ', width=table_width, bgcolor=open_trade ? color.new(color.orange, _statistics_table_transparency) : color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 4, '    ' + str.tostring(math.round(net_profit_percentage, 2)) + '%    ', width=table_width, bgcolor=net_profit_percentage < 0 ? color.new(red_increase, _statistics_table_transparency) : color.new(green_increase, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 5, '    ' + str.tostring(buy_and_hold_percentage) + '%   ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 6, '    ' + str.tostring(profit_factor) + 'x   ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 7, '    ' + str.tostring(winrate, '#.##') + '%   ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 8, '    ' + str.tostring(win_trades) + ' / ' + str.tostring(loss_trades) + '   ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 9, '    ' + str.tostring(statistics_average_bars_per_trade()) + '    ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 10, '    ' + str.tostring(statistics_avg_trade_profit_percent()) + '%   ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 11, '    ' + str.tostring(statistics_maximum_trade_drawdown()) + '%   ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)
        table.cell(statistics_table, statistics_table_values, 12, '    ' + str.tostring(statistics_maximum_trade_runup()) + '%   ', width=table_width, bgcolor=color.new(_statistics_table_cell_color, _statistics_table_transparency), text_color=_statistics_table_text_color, text_size=size.small)

        table.cell(statistics_table, statistics_table_offset, 0, table_margin_right, bgcolor=color.new(color.white, 100), text_color=color.white, text_size=size.small)
