Triple Moving Averages + RSI Divergence + Trade Creator [CSJ7]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gtellezgiron2009

//@version=5

indicator(title = "Triple Moving Averages + RSI Divergence + Trade Creator [CSJ7]", shorttitle = "Triple Moving Averages + Trade Creator [CSJ7]", overlay = true, max_bars_back = 2000)

//======================================================================================//
//                                                                                      //
//                           MOVING AVERAGES INDICATOR                                  //
//                                                                                      //
//======================================================================================//

// Adjust colors according to background color
get_dark_bg_flag()=>
    background_color = chart.bg_color

    bg_color_r = color.r(background_color)
    bg_color_g = color.g(background_color)
    bg_color_b = color.b(background_color)

    avg_bg_color = math.avg(bg_color_r, bg_color_g, bg_color_b)

    dark_bg_flag = avg_bg_color < 50

dark_bg_flag = get_dark_bg_flag()

//--------------------------------------------------------------------------------------//
// CONSTANTS                                                                            //
//--------------------------------------------------------------------------------------//

// Titles for input groups
string GR_MOVING_AVERAGES       = "Moving Averages ------------------------------------"
string GR_SIGNALS               = "Buy & Sell Signals ---------------------------------"

// Tooltips
string MA_TYPE_TOOLTIP          = 'Select the moving average type: simple or exponential.'
string LENGTH_FAST_TOOLTIP      = 'Set the duration (in bars) for the short-term average.'
string LENGTH_MEDIUM_TOOLTIP    = 'Set the duration (in bars) for the medium-term average.'
string LENGTH_SLOW_TOOLTIP      = 'Set the duration (in bars) for the long-term average.'

// Trend labels
string BULLISH_MOMENTUM_TXT     = 'Bullish\nMomentum'
string BEARISH_MOMENTUM_TXT     = 'Bearish\nMomentum'
string BULLISH_TREND_START_TXT  = 'Bullish\nTrend\nStart'
string BEARISH_TREND_START_TXT  = 'Bearish\nTrend\nStart'
string TREND_END_TXT            = 'Trend\nEnd'
string ENTRY_ZONE_TXT           = 'Entry\nZone'
string BUY_TXT                  = 'Buy'
string SELL_TXT                 = 'Sell'

// Entry Rating
string ENTRY_RATING_0_TXT       = 'No clear momentum or trend identified.'
string ENTRY_RATING_1_TXT       = 'Initial Momentum Observed' 
string ENTRY_RATING_2_TXT       = 'Trend Commenced'
string ENTRY_RATING_3_TXT       = 'Entry Zone Established'
string ENTRY_RATING_4_TXT       = 'Entry Signal Triggered'
string ENTRY_RATING_5_TXT       = 'Currently Sideways Ranging'

// Define color constants for various scenarios and states
color BRIGHT_RED            = color.rgb(255, 0, 0)
color DARK_RED              = color.rgb(128, 0, 0)
color BRIGHT_GREEN          = color.rgb(0, 255, 8)
color DARK_GREEN            = color.rgb(0, 112, 4)
color COL_BEARGR            = dark_bg_flag ? color.rgb(133, 17, 17) :   color.new(color.red,0)              // Bearish Growing
color COL_BULLGR            = dark_bg_flag ? color.green :              color.new(color.green,0)            // Bullish Growing
color COL_BEARSH	        = dark_bg_flag ? color.red :                color.new(color.red, 0)             // Bearish Shrinking
color COL_BULLSH	        = dark_bg_flag ? color.rgb(27, 96, 29) :    color.new(color.green, 0)           // Bullish Shrinking
color COL_TRANSP            = color.new(color.blue,100)                                                       // Transparent color
color COLOR_UP              = dark_bg_flag ? color.green :              color.green                         // Color for upward movement
color COLOR_DOWN            = dark_bg_flag ? color.red :                color.red                           // Color for downward movement
color COLOR_BUY             = dark_bg_flag ? color.rgb(0, 255, 8) :     color.green                         // Buy signal color
color COLOR_SELL            = dark_bg_flag ? color.rgb(255, 0, 0) :     color.red                           // Sell signal color
color TEXT_COLOR_BUY        = dark_bg_flag ? color.rgb(0, 255, 8) :     color.green                         // Buy signal LABEL color
color TEXT_COLOR_SELL       = dark_bg_flag ? color.rgb(255, 0, 0) :     color.red                           // Sell signal LABEL color
color COLOR_NEUTRAL         = color.gray                                                                      // Neutral color
color COLOR_TREND_END       = dark_bg_flag ? color.yellow :             color.black
color BG_COLOR_BUY_ZONE     = dark_bg_flag ? color.new(color.green,92) :    color.new(color.green,90)
color BG_COLOR_SELL_ZONE    = dark_bg_flag ? color.new(color.red,92) :      color.new(color.red,90)
color BG_COLOR_BUY          = dark_bg_flag ? color.new(color.green,85) :    color.new(color.green,80)
color BG_COLOR_SELL         = dark_bg_flag ? color.new(color.red,85) :      color.new(color.red,80)
color BG_COLOR_RANGING      = color.new(color.yellow,95)

// Define line widths for the moving averages
int FAST_LINE_WIDTH         = 1
int MEDIUM_LINE_WIDTH       = 3
int SLOW_LINE_WIDTH         = 5

// Moving Averages
float src_ma                = close
int MA_TRANSPARENCY         = 0                                                                                 // Transparency level for moving averages
bool fill_areas_input       = true

int MAXIMUM_BARS            = 2000

//--------------------------------------------------------------------------------------//
// INPUTS
//--------------------------------------------------------------------------------------//

string ma_type_input    = input.string('Exponential','Type',options = ['Simple', 'Exponential'], group = GR_MOVING_AVERAGES, display = display.none, tooltip = MA_TYPE_TOOLTIP)
int length_fast_input   = input(50, "Fast", group = GR_MOVING_AVERAGES, display = display.none, tooltip = LENGTH_FAST_TOOLTIP)
int length_medium_input = input(100, "Medium", group = GR_MOVING_AVERAGES, display = display.none, tooltip = LENGTH_MEDIUM_TOOLTIP)
int length_slow_input   = input(200, "Slow", group = GR_MOVING_AVERAGES, display = display.none, tooltip = LENGTH_SLOW_TOOLTIP)

//--------------------------------------------------------------------------------------//
// FUNCTIONS
//--------------------------------------------------------------------------------------//
get_moving_averages(source, length_fast_input, length_medium_input, length_slow_input, ma_type_input) =>     
    float ma_fast   = 0.0
    float ma_med    = 0.0
    float ma_slow   = 0.0

    if ma_type_input == "Simple"
        ma_fast     := ta.sma(source, length_fast_input) 
        ma_med      := ta.sma(source, length_medium_input) 
        ma_slow     := ta.sma(source, length_slow_input) 
    else if ma_type_input == "Exponential"
        ma_fast     := ta.ema(source, length_fast_input) 
        ma_med      := ta.ema(source, length_medium_input) 
        ma_slow     := ta.ema(source, length_slow_input) 

    [ma_fast, ma_med, ma_slow]

get_color_by_direction(source,lookback, col_up,col_dn, transp) =>
    col_p = source > source[lookback] ? col_up : source < source[lookback] ? col_dn : COLOR_NEUTRAL
    col = color.new(col_p, transp)

get_scenarios(signal_fast,signal_slow) =>                                        
    trend_bull = signal_fast > signal_slow
    trend_bear = signal_fast < signal_slow

    dif_ma = math.abs(signal_fast - signal_slow)
    signal_fast_up = signal_fast > signal_fast[1]
    signal_fast_dn = signal_fast < signal_fast[1]
    signal_slow_up = signal_slow > signal_slow[1]
    signal_slow_dn = signal_slow < signal_slow[1] 

    trend_shrinking = dif_ma < dif_ma[1] and not(trend_bull ? signal_fast_up and signal_slow_up : signal_fast_dn and signal_slow_dn)
    trend_growing = not(trend_shrinking)

    bullGr = trend_bull and trend_growing
    bullSh = trend_bull and trend_shrinking
    bearGr = trend_bear and trend_growing
    bearSh = trend_bear and trend_shrinking

    [bullGr,bullSh,bearGr,bearSh, signal_fast_up, signal_fast_dn, signal_slow_up, signal_slow_dn]

check_for_rejects(reference) =>

    // Candle Parts
    bool candle_up              = close > open 
    bool candle_dn              = close < open 
    float body_top              = math.max(close, open)
    float body_bottom           = math.min(close, open)
    float body                  = body_top - body_bottom
    bool bottom_reject_candle   = low <= reference and body_bottom > reference
    bool top_reject_candle      = high >= reference and body_top < reference

    // Top Rejects
    top_reject_1 =   top_reject_candle[1] and candle_dn                                                 // Simple one candle reject
    top_reject_2 =   candle_up[1] and low[1] <= reference[1] and close[1] >= reference[1] and
                     candle_dn and open >= reference and close < reference                              // crosses up/touches -> crosses down
    top_reject_3 =   high[2] < reference[2] and
                     top_reject_candle[1] and 
                     high < reference and candle_dn
    top_reject = top_reject_1 or top_reject_2 or top_reject_3

    // Bottom Rejects
    bottom_reject_1 =    bottom_reject_candle[1] and candle_up                                          // Simple one candle reject
    bottom_reject_2 =    candle_dn[1] and high[1] >= reference[1] and close[1] <= reference[1] and
                         candle_up and open <= reference and close > reference                          // crosses/touches down -> crosses up
    bottom_reject_3 =    low[2] > reference[2] and  
                         bottom_reject_candle[1] and
                         low > reference and candle_up                                                  // above | reject | above

                         
    bottom_reject = bottom_reject_1 or bottom_reject_2 or bottom_reject_3


    [top_reject, bottom_reject]

get_time_as_text(time_format)=>
    str.format_time(time(timeframe.period),time_format, syminfo.timezone)

//--------------------------------------------------------------------------------------//
// LOGS SETUP
//--------------------------------------------------------------------------------------//

// Set system barsback
max_bars_back(time, MAXIMUM_BARS)
max_bars_back(open, MAXIMUM_BARS)
max_bars_back(high, MAXIMUM_BARS)
max_bars_back(close, MAXIMUM_BARS)
max_bars_back(low, MAXIMUM_BARS)

error_log_array         = array.new_string()
status_log_array        = array.new_string()
conditions_log_array    = array.new_string()

//--------------------------------------------------------------------------------------//
// MOVING AVERAGES 
//--------------------------------------------------------------------------------------//

// Calculate moving averages
[ma_fast, ma_med, ma_slow] = get_moving_averages(src_ma, length_fast_input, length_medium_input, length_slow_input, ma_type_input)

// Determine market scenarios based on moving averages
[bullGr,bullSh,bearGr,bearSh, signal_fast_up, signal_fast_dn, signal_slow_up, signal_slow_dn] = get_scenarios(ma_fast,ma_slow)

//--------------------------------------------------------------------------------------//
// SIGNALS
//--------------------------------------------------------------------------------------//

// Entry Ratings Variables
var int long_entry_rating = 0
var int short_entry_rating = 0

// Initial Momentum Signal
bullish_momentum_signal = ta.crossover(ma_fast, ma_slow) and ma_slow > ma_med 
bearish_momentum_signal = ta.crossunder(ma_fast,ma_slow) and ma_slow < ma_med 

// Trend start signal
bullish_trend_start_signal = ta.crossover(ma_med, ma_slow) and ma_fast > ma_med 
bearish_trend_start_signal = ta.crossunder(ma_med, ma_slow) and ma_fast < ma_med 

// Trend end signal
end_bullish_trend_signal = ta.crossunder(close[2],ma_slow[2]) and close[1] < ma_slow[1] and close < ma_slow and long_entry_rating > 0 
end_bearish_trend_signal = ta.crossover(close[2],ma_slow[2]) and close[1] > ma_slow[1] and close > ma_slow and short_entry_rating > 0 

//--------------------------------------------------------------------------------------//
// ENTRY RATINGS
//--------------------------------------------------------------------------------------//

// 0 = Nothing
// 1 = Initial Momentum 
// 2 = Trend Ongoing
// 3 = Zone Initiated
// 4 = Entry Signal occurred
// 5 = Ranging

// Variable for divergence boxes
var float trend_start_bar = 0.0

// Momentum signal 
if bullish_momentum_signal
    long_entry_rating := 1
if bearish_momentum_signal
    short_entry_rating := 1

// Trend start signal
if bullish_trend_start_signal
    long_entry_rating   := 2
    trend_start_bar     := bar_index
if bearish_trend_start_signal
    short_entry_rating  :=2
    trend_start_bar     := bar_index

// End of Trend
if end_bullish_trend_signal
    long_entry_rating := 0
if end_bearish_trend_signal
    short_entry_rating := 0
    
// Check for rejects
[top_reject_med, bottom_reject_med] = check_for_rejects(ma_med)

// Start of entry zones
start_short_entry_zone_signal   = top_reject_med and short_entry_rating == 2
start_long_entry_zone_signal    = bottom_reject_med and long_entry_rating == 2

// Entry Signals
if start_long_entry_zone_signal
    long_entry_rating := 3
if start_short_entry_zone_signal
    short_entry_rating := 3

// TRADE ENTRY_CONDITIONS_TITLE
short_entry = ta.crossunder(close, ma_fast) and short_entry_rating == 3
long_entry = ta.crossover(close, ma_fast) and long_entry_rating == 3

// Entry Signals
if long_entry
    long_entry_rating := 4
if short_entry
    short_entry_rating := 4

//--------------------------------------------------------------------------------------//
// MARKET OUTLOOK EVENTS
//--------------------------------------------------------------------------------------//

// Initialize Variables
string  market_outlook_txt      = ENTRY_RATING_0_TXT
string  indicator_trade_side    = na
var     outlook_log_array       = array.new_string()
var     outlook_log_array_times = array.new_string()
string  time_now_txt            = get_time_as_text('yyyy-MM-dd HH:mm')

// Create arrays from conext strings
entry_rating_txts_array = array.from(ENTRY_RATING_0_TXT, ENTRY_RATING_1_TXT, ENTRY_RATING_2_TXT, ENTRY_RATING_3_TXT, ENTRY_RATING_4_TXT, ENTRY_RATING_5_TXT)

// If current rating is 0 we clear the outlook logs
if (long_entry_rating == 0 and short_entry_rating == 0) or (long_entry_rating == 5 and short_entry_rating == 5)
    array.clear(outlook_log_array)
    array.clear(outlook_log_array_times)

// Get indicator trade side
indicator_trade_side := long_entry_rating > 0 and long_entry_rating <= 4 ? 'Bullish' :
                     short_entry_rating > 0 and short_entry_rating <= 4 ? 'Bearish' :
                     long_entry_rating == 4 ? 'Long' :
                     short_entry_rating == 4 ? 'Short':
                     (long_entry_rating == 5 or short_entry_rating == 5) ? '' : indicator_trade_side

// Define UpTrend or DownTrend
up_trend_flag = long_entry_rating >= 2 and long_entry_rating < 5
dn_trend_flag = short_entry_rating >= 2 and short_entry_rating < 5

// Create the market outlook entry log
if long_entry_rating > 0
    market_outlook_txt := indicator_trade_side + ' ' + array.get(entry_rating_txts_array, long_entry_rating)
if short_entry_rating > 0
    market_outlook_txt := indicator_trade_side + ' ' + array.get(entry_rating_txts_array, short_entry_rating)

// Update the market outlook log
if long_entry_rating != long_entry_rating[1] or short_entry_rating != short_entry_rating[1]
    array.push(outlook_log_array, market_outlook_txt)
    array.push(outlook_log_array_times, time_now_txt)

//--------------------------------------------------------------------------------------//
// PLOTS
//--------------------------------------------------------------------------------------//

// Plot buy and sell signals on the chart
plotshape(bullish_momentum_signal,'Bullish Momentum Signal', shape.triangleup,location.belowbar, COLOR_BUY,0, BULLISH_MOMENTUM_TXT, COLOR_BUY,true,size.tiny)//, display = display.none)
plotshape(bearish_momentum_signal,'Bearish Momentum Signal', shape.triangledown,location.abovebar, COLOR_SELL,0, BEARISH_MOMENTUM_TXT,COLOR_SELL,true,size.tiny)//, display = display.none)

plotshape(bullish_trend_start_signal,'Bullish Trend Start Signal', shape.triangleup,location.belowbar, COLOR_BUY,0, BULLISH_TREND_START_TXT,COLOR_BUY,true,size.small)//, display = display.)
plotshape(bearish_trend_start_signal,'Bearish Trend Start Signal', shape.triangledown,location.abovebar, COLOR_SELL,0, BEARISH_TREND_START_TXT,COLOR_SELL,true,size.small)//, display = display.none)

plotshape(end_bullish_trend_signal,'End Bullish Trend Signal', shape.xcross,location.belowbar, COLOR_TREND_END,0,TREND_END_TXT,COLOR_TREND_END,true,size.tiny)//, display = display.none)
plotshape(end_bearish_trend_signal,'End Bearish Trend Signal', shape.xcross,location.abovebar, COLOR_TREND_END,0,TREND_END_TXT,COLOR_TREND_END,true,size.tiny)//, display = display.none)

plotshape(start_long_entry_zone_signal,'Bottom Reject Bull Confirmation', shape.triangleup,location.belowbar, COLOR_BUY,0,ENTRY_ZONE_TXT,COLOR_BUY,true,size.small)//, display = display.none)
plotshape(start_short_entry_zone_signal,'Top Reject Bear Confirmation', shape.triangledown,location.abovebar, COLOR_SELL,0,ENTRY_ZONE_TXT,COLOR_SELL,true,size.small)//, display = display.none)

plotshape(long_entry,'Long Entry', shape.arrowup,location.belowbar, COLOR_BUY,0,BUY_TXT, TEXT_COLOR_BUY,true,size.normal)//, display = display.none)
plotshape(short_entry,'Short Entry', shape.arrowdown,location.abovebar, COLOR_SELL,0,SELL_TXT, TEXT_COLOR_SELL,true,size.normal)//, display = display.none)

// Background color
bgcolor(short_entry_rating >= 3 and short_entry_rating <= 4 ? BG_COLOR_SELL :
         long_entry_rating >= 3 and long_entry_rating <= 4 ? BG_COLOR_BUY :
         short_entry_rating == 2 ? BG_COLOR_SELL_ZONE :
         long_entry_rating == 2 ? BG_COLOR_BUY_ZONE : COL_TRANSP)


// Determine lookback periods for moving averages
int div = 5
ma_slow_lookback = int(math.round(length_slow_input / div,0))
ma_medium_lookback = int(math.round(length_medium_input / div,0))
ma_fast_lookback = int(math.round(length_slow_input / div,0))

// Determine trend color based on scenarios
col_trend = bullGr ? COL_BULLGR : bullSh ? COL_BULLSH : bearGr ? COL_BEARGR : bearSh ? COL_BEARSH : color.yellow 

// Configuration for plot transparency
int ma_transparency_fill = 50
int transp_superBull_fill = 40
int transp_superBear_fill = 20
if not(fill_areas_input)
    ma_transparency_fill := 100
    transp_superBull_fill := 100
    transp_superBear_fill := 100

// Plot moving averages on the chart
ln_ma_fast = plot(ma_fast, title="Fast", color=get_color_by_direction(ma_fast,ma_fast_lookback, COLOR_UP,COLOR_DOWN, MA_TRANSPARENCY), linewidth = FAST_LINE_WIDTH)
ln_ma_medium = plot(ma_med, title="Medium", color=get_color_by_direction(ma_med,ma_medium_lookback, COLOR_UP,COLOR_DOWN, MA_TRANSPARENCY), linewidth = MEDIUM_LINE_WIDTH)
ln_ma_slow = plot(ma_slow, title="Slow", color=get_color_by_direction(ma_slow,ma_slow_lookback, COLOR_UP,COLOR_DOWN, MA_TRANSPARENCY), linewidth = SLOW_LINE_WIDTH)

// Fill the area between Medium and Slow moving averages based on trend color
fill(ln_ma_medium, ln_ma_slow, color = color.new(col_trend,ma_transparency_fill), fillgaps = true)

//======================================================================================//
//                                                                                      //
//                                  DIVERGENCE BOX                                      //
//                                                                                      //
//======================================================================================//

//--------------------------------------------------------------------------------------//
// CONSTANTS                                                                            //
//--------------------------------------------------------------------------------------//

// Colors
color   BORDER_COLOR_BOX                = dark_bg_flag ?  color.new(color.black,0) : color.new(color.gray,50)       // RSI Box
color   BGCOLOR_BOX                     = dark_bg_flag ?  color.new(color.black,50) : color.new(color.white,40)     // RSI Box
color   RSI_LINE_COLOR                  = dark_bg_flag ?  color.new(color.yellow,0): color.orange                   // RSI Box
color   CLOSE_LINE_COLOR                = dark_bg_flag ?  color.new(color.yellow,50): color.orange                  // RSI Box
color   RSI_50_LINE_COLOR               = dark_bg_flag ?  color.new(color.gray,0): color.black                      // RSI Box
color   BOX_TEXT_COLOR                  = dark_bg_flag ?  color.new(color.gray,0): color.black                      // RSI Box
color   COLOR_RSI_LINREG                = dark_bg_flag ? color.new(color.yellow,0) :color.orange                    // Linear regresssion
color   COLOR_CLOSE_LINREG              = dark_bg_flag ? color.new(color.yellow,0): color.orange                    // Linear regresssion
color   TEXTCOLOR_RSI_LINREG_LABEL      = dark_bg_flag ? color.new(color.white,0) : color.white                     // Linear regresssion
color   TEXTCOLOR_CLOSE_LINREG_LABEL    = dark_bg_flag ? color.new(color.white,0) : color.white                     // Linear regresssion

// Strings
string GR_RSI_BOX                       = 'Divergence ---------------------------------------'
string BULLISH_RSI_DVRG_LOG_TXT         = 'Detected Bullish RSI Divergence.'
string BEARISH_RSI_DVRG_LOG_TXT         = 'Detected Bearish RSI Divergence.'
string BULLISH_RSI_DVRG_ERROR_LOG_TXT   = 'Bullish RSI Divergence: Consider evaluating a Long trade.'
string BEARISH_RSI_DVRG_ERROR_LOG_TXT   = 'Bearish RSI Divergence: Consider evaluating a Short trade.'
string SHOW_RSI_BOX_TOOLTIP             = "Toggle the display of a box showing the linear regression of RSI during the current Long or Short trend (if present)."
string SHOW_LINREG_LABELS_TOOLTIP       = "Toggle the display of labels for the RSI and Close linear regression lines."
string BOX_TEXT                         = 'RSI'
string RSI_LINREG_TXT                   = 'RSI (LR)'
string CLOSE_LINREG_TXT                 = 'Close (LR)'
string RSI_BOX_SIZE_TOOLTIP             = 'Select the size of the vertical size of the RSI box.'

// RSI Box
int     LENGTH_RSI                          = 14
float   SRC_RSI                             = close
float   BOX_SEPARATION_FACTOR               = 0.05       // Percentage of the highest lowest range for placeing the box.
float   COMPACT_BOX_VERTICAL_SIZE_FACTOR    = 0.25      // Percentage of the higest/lowest range
float   NORMAL_BOX_VERTICAL_SIZE_FACTOR     = 0.5       // Percentage of the higest/lowest range
float   LARGE_BOX_VERTICAL_SIZE_FACTOR      = 1.0       // Percentage of the higest/lowest range

// BOX Configuration
string  BOX_TEXT_SIZE       = size.small
string  BOX_TEXT_HALING     = text.align_left
string  BOX_TEXT_VALIGN     = text.align_top

// BOX Line Styles
string  VOLUME_LINE_STYLE   = line.style_solid
string  RSI_LINE_STYLE      = line.style_solid
string  CLOSE_LINE_STYLE    = line.style_solid
string  RSI_50_LINE_STYLE   = line.style_dashed

// BOX line Widths
int     BORDER_WIDTH_BOX    = 1
int     VOLUME_LINE_WIDTH   = 1
int     RSI_LINE_WIDTH      = 3
int     CLOSE_LINE_WIDTH    = 3
int     RSI_50_LINE_WIDTH   = 1

// Lineal Regression labels
string  SIZE_RSI_LINREG         = size.small
string  SIZE_CLOSE_LINREG       = size.small
string  STYLE_RSI_LINREG        = label.style_label_right
string  STYLE_CLOSE_LINREG      = label.style_label_right

//--------------------------------------------------------------------------------------//
// INPUTS                                                                               //
//--------------------------------------------------------------------------------------//

bool show_rsi_box           = input.bool(true, "Show RSI box", group = GR_RSI_BOX, display = display.none, tooltip = SHOW_RSI_BOX_TOOLTIP)
string rsi_box_size_input   = input.string('Compact','Vertical size of RSI box', options = ['Compact', 'Normal','Large'], group = GR_RSI_BOX, tooltip = RSI_BOX_SIZE_TOOLTIP, display = display.none)
bool show_linreg_labels     = input.bool(true, "Show Linear Regression Labels", group = GR_RSI_BOX, display = display.none, tooltip = SHOW_LINREG_LABELS_TOOLTIP)


// Selection of box size
box_vertical_size_factor = switch rsi_box_size_input
    'Compact'   => COMPACT_BOX_VERTICAL_SIZE_FACTOR
    'Normal'    => NORMAL_BOX_VERTICAL_SIZE_FACTOR
    'Large'     => LARGE_BOX_VERTICAL_SIZE_FACTOR

//--------------------------------------------------------------------------------------//
// FUNCTIONS                                                                            //
//--------------------------------------------------------------------------------------//
get_best_fitting_line(bar_index_array, data_array)=>

    // Initialize Variables
    int first_barIndex = na
    int last_barIndex = na
    float y_first = na
    float y_last = na
    float m = na
    float b = na
    float R2 = na
    float sum_x = 0.0
    float sum_y = 0.0
    float sum_x_squared = 0.0
    float sum_xy = 0.0

    // Get array size
    int N = array.size(bar_index_array)
    int NP = array.size(data_array)


    // Only if array contains more than one
    if (N > 0 and NP > 0) and N == NP 

        for i = 0 to N - 1
            x = array.get(bar_index_array, i)
            y = array.get(data_array, i)
            
            sum_x := sum_x + x
            sum_y := sum_y + y
            sum_x_squared := sum_x_squared + (x * x)
            sum_xy := sum_xy + (x * y)

        // Calculate slope (m) and y-intercept (b) for y = mx + b
        m := (N * sum_xy - sum_x * sum_y) / (N * sum_x_squared - sum_x * sum_x)
        b := (sum_y - m * sum_x) / N


        // Finding lowest bar_index and last bar_index
        first_barIndex := int(array.min(bar_index_array))
        last_barIndex := int(array.max(bar_index_array))

        // Calculate y-values for the lowest and last bar_index
        y_first := m * first_barIndex + b
        y_last := m * last_barIndex + b

        // Initialize variables for calculating R2
        SST = 0.0
        SSE = 0.0

        // Calculate mean of y-values
        y_mean = sum_y / N

        // Calculate SST and SSE
        for i = 0 to N - 1
            y = array.get(data_array, i)
            x = array.get(bar_index_array, i)
            y_hat = m * x + b

            SST := SST + math.pow(y - y_mean, 2)
            SSE := SSE + math.pow(y - y_hat, 2)


        // Calculate R-squared
        R2 := 1 - (SSE / SST)

    [first_barIndex, last_barIndex, y_first, y_last, m, b, R2]

//--------------------------------------------------------------------------------------//
// RSI & BARSBACK                                                                       //
//--------------------------------------------------------------------------------------//

// Get RSI
rsi = ta.rsi(SRC_RSI,LENGTH_RSI)

// Get barsback
int trend_start_barsback = 1
if (long_entry_rating >= 2 or short_entry_rating >= 2) and barstate.islast
    trend_start_barsback := int(last_bar_index - trend_start_bar)

//--------------------------------------------------------------------------------------//
// CALCULATE RSI BOX DIMENTIONS                                                                   //
//--------------------------------------------------------------------------------------//

// Create array for datasets
volume_array    = array.new_float()
rsi_array       = array.new_float()
close_array     = array.new_float()
bar_index_array = array.new_float()

// Get highest / lowest range
barsback_highest        = ta.highest(trend_start_barsback)
barsback_lowest         = ta.lowest(trend_start_barsback)
highest_lowest_range    = barsback_highest - barsback_lowest

// Get box measurements and coordinates
box_separation          = highest_lowest_range * BOX_SEPARATION_FACTOR
box_height              = highest_lowest_range * box_vertical_size_factor


// Get box coordinates
//------------------------------------
int box_left_margin     = int(trend_start_bar)
int box_right_margin    = last_bar_index
float box_top_margin    = na
float box_bottom_margin = na

// If trend is bullish
if up_trend_flag

    box_bottom_margin   := barsback_highest + box_separation
    box_top_margin      := box_bottom_margin + box_height

//If trend is Bearish
if dn_trend_flag

    box_top_margin      := barsback_lowest - box_separation
    box_bottom_margin   := box_top_margin - box_height

box_vertical_middle = math.avg(box_top_margin, box_bottom_margin)

//--------------------------------------------------------------------------------------//
// DRAW RSI BOX                                                                         //
//--------------------------------------------------------------------------------------//

// Divergence variables
float close_m   = na
float rsi_m     = na
float rsi_dvrg  = na

// Draw initial box and lines
var rsi_line            = line.new(1,1,1,1,xloc.bar_index,extend.none, RSI_LINE_COLOR, RSI_LINE_STYLE, RSI_LINE_WIDTH)
var close_line          = line.new(1,1,1,1,xloc.bar_index,extend.none, CLOSE_LINE_COLOR, CLOSE_LINE_STYLE, CLOSE_LINE_WIDTH)
var rsi_50_line         = line.new(1,1,1,1,xloc.bar_index,extend.none, RSI_50_LINE_COLOR, RSI_50_LINE_STYLE, RSI_50_LINE_WIDTH)
var dvrg_box            = box.new(1,1,1,1, BORDER_COLOR_BOX, BORDER_WIDTH_BOX, line.style_solid, extend.none, xloc.bar_index, BGCOLOR_BOX, BOX_TEXT, BOX_TEXT_SIZE, BOX_TEXT_COLOR, BOX_TEXT_HALING, BOX_TEXT_VALIGN)
var rsi_linreg_label    = label.new(1,1,'',xloc.bar_index,color = COLOR_RSI_LINREG, style = STYLE_RSI_LINREG, textcolor = TEXTCOLOR_RSI_LINREG_LABEL, size = SIZE_RSI_LINREG)
var close_linreg_label  = label.new(1,1,'',xloc.bar_index,color = COLOR_CLOSE_LINREG, style = STYLE_CLOSE_LINREG, textcolor = TEXTCOLOR_CLOSE_LINREG_LABEL, size = SIZE_CLOSE_LINREG)

// Update boxes and lines
if barstate.islast and show_rsi_box

    // Loop through all barsback
    for i = 0 to trend_start_barsback - 1

        // Add data to arrays
        array.push(rsi_array,rsi[i])
        array.push(close_array,close[i])
        array.push(bar_index_array, last_bar_index - i)

    // Get the best fitting lines for each dataset
    [first_barIndex_rsi, last_barIndex_rsi, y_first_rsi, y_last_rsi, m_rsi, b_rsi, R2_rsi]                      = get_best_fitting_line(bar_index_array, rsi_array)
    [first_barIndex_close, last_barIndex_close, y_first_close, y_last_close, m_close, b_close, R2_close]        = get_best_fitting_line(bar_index_array, close_array)

    // Get RSI y levels
    y1_rsi = ((y_first_rsi / 100) * box_height) + box_bottom_margin
    y2_rsi = ((y_last_rsi / 100) * box_height) + box_bottom_margin

    // Box middle
    box_middle = box_bottom_margin + (box_height / 2)

    // Update divergence values
    close_m   := m_close
    rsi_m     := m_rsi

    // Line colors
    rsi_color   = rsi_m > 0 ? color.green : color.red
    close_color = close_m > 0 ? color.green : color.red

    // Update dvrg_box
    box.set_lefttop(dvrg_box, box_left_margin, box_top_margin)
    box.set_rightbottom(dvrg_box, box_right_margin, box_bottom_margin)

    // Update RSI line
    line.set_xy1(rsi_line,box_left_margin, y1_rsi)
    line.set_xy2(rsi_line,box_right_margin, y2_rsi)
    line.set_color(rsi_line, rsi_color)

    // Update Close line
    line.set_xy1(close_line,box_left_margin, y_first_close)
    line.set_xy2(close_line,box_right_margin, y_last_close)
    line.set_color(close_line, close_color)

    // RSI 50
    line.set_xy1(rsi_50_line,box_left_margin, box_middle)
    line.set_xy2(rsi_50_line,box_right_margin, box_middle)

    // Update the labels
    if show_linreg_labels

        // Update RSI labels
        label.set_xy(rsi_linreg_label,box_left_margin, y1_rsi)
        label.set_text(rsi_linreg_label, RSI_LINREG_TXT)
        label.set_color(rsi_linreg_label, rsi_color)

        // Update CLOSE labels
        label.set_xy(close_linreg_label,box_left_margin, y_first_close)
        label.set_text(close_linreg_label, CLOSE_LINREG_TXT)
        label.set_color(close_linreg_label, close_color)

//---------------------------------------//
// GET DIVERGENCE                        //
//---------------------------------------//

// Variagles
string rsi_dvrg_flag = 'None'

// Calculate divergence
rsi_dvrg := close_m + rsi_m

// Get divergence flag and log entry
if rsi_dvrg > 0 and dn_trend_flag
    rsi_dvrg_flag := 'Bullish'
    array.push(status_log_array, BULLISH_RSI_DVRG_LOG_TXT)

if rsi_dvrg < 0 and up_trend_flag
    rsi_dvrg_flag := 'Negative'
    array.push(status_log_array, BEARISH_RSI_DVRG_LOG_TXT)




//======================================================================================//
//**************************************************************************************//
//*********************************                 ************************************//
//*********************************  TRADE CREATOR  ************************************//
//*********************************                 ************************************//
//**************************************************************************************//
//======================================================================================//

//**************************************************************************************//
// TYPES 
//**************************************************************************************//

type entry_condition 
    string  name            = na
    string  description     = na
    float   actual_float    = na 
    float   min_condition   = na
    bool    true_condition  = na 
    bool    pass            = na

//**************************************************************************************//
// CONSTANTS
//**************************************************************************************//

// Colors
color COLOR_TRANSP                  = color.new(color.gray, 100)                                                  // General
color EMPTY_CELL_BG_COLOR           = dark_bg_flag ? color.white : color.new(#eaeaea, 0)                        // Dashboard
color DASHBOARD_FRAME_COLOR         = color.gray                                                                  // Dashboard
color MAIN_HEADER_COLOR             = dark_bg_flag ? color.new(#000000, 0) : color.new(#000000, 0)              // Dashboard
color TABLE_HEADER_COLOR            = dark_bg_flag ? color.new(#373737, 0) : color.new(#373737, 0)              // Dashboard
color TABLE_SUBHEADER_COLOR         = dark_bg_flag ? color.new(#5f5f5f, 0) : color.new(#5f5f5f, 0)              // Dashboard
color TABLE_CELL_COLOR              = dark_bg_flag ? color.new(#767676, 0) : color.new(#767676, 0)              // Dashboard
color COLOR_CONDITION_PASS          = dark_bg_flag ? color.new(color.green,0) : color.new(color.green,0)        // Dashboard
color COLOR_CONDITION_FAIL          = dark_bg_flag ? EMPTY_CELL_BG_COLOR : EMPTY_CELL_BG_COLOR                      // Dashboard
color TRADEBOX_PROFIT_COLOR         = dark_bg_flag ? color.new(color.green,80) : color.new(color.green,60)      // Tradebox
color TRADEBOX_LOSS_COLOR           = dark_bg_flag ? color.new(color.red,80) : color.new(color.red,60)          // Tradebox
color FIRST_ENTRY_LINE_COLOR        = dark_bg_flag ? color.gray : color.gray                                    // Tradebox
color AVG_ENTRY_LINE_COLOR          = dark_bg_flag ? color.gray : color.gray                                    // Tradebox
color LAST_ENTRY_LINE_COLOR         = dark_bg_flag ? color.gray :  color.gray                                   // Tradebox
color EXIT_LINE_COLOR               = dark_bg_flag ? color.green : color.green                                  // Tradebox
color STOPLOSS_LINE_COLOR           = dark_bg_flag ? color.red :  color.red                                     // Tradebox
color TRADEBOX_POSITION_TEXT_COLOR  = dark_bg_flag ? color.white : color.white                                    // Tradebox
color PRICE_LABEL_COLOR             = dark_bg_flag ? color.new(color.gray,50) : color.new(color.gray,20)        // Tradebox
color PRICE_LABEL_TEXTCOLOR         = dark_bg_flag ? color.new(color.white,0) : color.new(color.white,0)        // Tradebox
color ACTIVE_TRADE_LABEL_COLOR      = dark_bg_flag ? color.new(color.black,30) : color.new(color.black,30)      // Active Trade
color ACTIVE_TRADE_LABEL_TEXTCOLOR  = dark_bg_flag ? color.white  : color.white                                 // Active Trade

// Temporary input
string execution_mode_input     = 'Analyze'

// Dashboard Table
string DASHBOARD_TITLE          = 'Trade Creator [CSJ7]'
string MARKET_OUTLOOK_TITLE     = "Market Outlook Events"
string ENTRY_CONDITIONS_TITLE   = "Entry Conditions"
string ESTIMATED_PNL_TITLE      = "Estimated P&L"
string OPERATION_LOGS_TITLE     = "Operation Logs"

// Inputs titles
string GR_DASHBOARD_COMPONENTS      = "[TC]: DASHBOARD COMPONENTS ====================================="
string GR_ACTIVE_TRADE_SETUP        = "[TC]: TRADE SETUP =============================================="
string GR_SHORT                     = "SHORT LEVELS"
string GR_LONG                      = "LONG LEVELS"
string GR_RISK_SETUP                = "RISK CONTROL"
string GR_ENTRY_CONDITIONS          = 'ENTRY CONDITIONS'
string GR_EXCHANGE                  = "[TC]: ECONOMICS ================================================"
string GR_ALERTS                    = "[TC]: ALERTS ============================================="
string GR_LAYOUT                    = "[TC]: LAYOUT ============================================="

// Tooltips
string TABLE_HEADER_TOOLTIP                     = 'Toggle content visibility via Settings.'
string SHOW_MARKET_OUTLOOK_TOOLTIP              = 'Toggle the list of detected Market Outlook events.'               
string SHOW_ENTRY_CONDITIONS_TOOLTIP            = 'Toggle the table displaying selected conditions for trade entry and their current values.'                        
string SHOW_ESTIMATED_PNL_TOOLTIP               = 'Toggle the table displaying estimated Profit and Loss based on current trade settings.'                         
string SHOW_LOGS_TOOLTIP                        = 'Toggle the list of status and error log entries.'                                           
string DRAW_TRADE_BOX_TOOLTIP                   = 'Toggle the trade box displaying entry, exit levels, and profit and loss areas for the planned trade.'                                       
string SHOW_PRICE_LABELS_TOOLTIP                = 'Toggle the display of price levels for the planned trade.'                                    
string SIDE_TOOLTIP                             = 'Choose the trade side. When set to Auto, the Trade Creator recommends the appropriate side based on the trend.'                            
string LEVERAGE_TOOLTIP                         = 'Specify the leverage level (multiplier of equity investment) for each trade.'                      
string LAST_ENTRY_SHORT_TOOLTIP                 = 'Set the price level for the final entry in a short trade.'                    
string FIRST_ENTRY_SHORT_TOOLTIP                = 'Set the price level for the initial entry in a short trade.'                    
string EXIT_SHORT_TOOLTIP                       = 'Set the target exit price for a short trade. If set to Auto, the Trade Creator will determine an exit level meeting the established minimum conditions.'               
string EXIT_LONG_TOOLTIP                        = 'Set the target exit price for a long trade. If set to Auto, the Trade Creator will determine an exit level meeting the established minimum conditions.'                   
string FIRST_ENTRY_LONG_TOOLTIP                 = 'Set the price level for the initial entry in a long trade.'                   
string LAST_ENTRY_LONG_TOOLTIP                  = 'Set the price level for the final entry in a long trade.'                       
string EQUITY_INVESTMENT_PER_TRADE_TOOLTIP      = 'Specify the percentage of available equity to use for each trade.'                    
string STOPLOSS_TYPE_TOOLTIP                    = 'Choose the type of stoploss to be calculated.'                        
string ACT_MINIMUM_WINING_ROI_TOOLTIP           = 'Toggle whether a minimum Return On Equity (ROI) is required for trade entry.'                        
string ACT_MAXIMUM_LOOSING_ROI_TOOLTIP          = 'Toggle whether a maximum negative Return On Equity (ROI) is set as a condition for trade entry.'                            
string ACT_MINIMUM_RRR_TOOLTIP                  = 'Toggle whether a minimum Risk Reward Ratio (RRR) is required for trade entry.'                                   
string MINIMUM_WINING_ROI_TOOLTIP               = 'Specify the minimum Return On Equity (ROI) required for trade entry.'                            
string MAXIMUM_LOOSING_ROI_TOOLTIP              = 'Specify the maximum negative ROI acceptable for trade entry.'                           
string MINIMUM_RRR_TOOLTIP                      = 'Specify the minimum Risk Reward Ratio for trade entry.'                              
string OUTLOOK_RATING_INPUT_TOOLTIP             = 'Choose the minimum Trend Stage needed for trade entry.'                             
string ACT_RSI_DIVERGENCE_TOOLTIP               = 'Toggle whether an RSI Divergence is a condition for trade entry.'                                          
string MINIMUM_TRADE_RATING_TOOLTIP             = 'Specify the minimum Trade Rating required for trade entry.'                         
string EQUITY_TOOLTIP                           = 'Specify the starting equity available for trading.'                         
string ENTRY_FEE_RATE_TOOLTIP                   = 'Specify the fee rate charged by your exchange/broker for trade entry.'                    
string EXIT_FEE_RATE_TOOLTIP                    = 'Specify the fee rate charged by your exchange/broker for trade exit.'                         
string MARKET_OUTLOOK_ALERT_TOOLTIP             = 'Toggle whether an alert should be triggered upon a specific market outlook status change.'                          
string MINIMUM_TRADE_RATING_ALERT_TOOLTIP       = 'Toggle whether an alert should be triggered when minimum trade entry conditions are met.'                      
string TEXT_SIZE_INPUT_TOOLTIP                  = 'Select the text size for the dashboard.'                    
string TABLEYPOS_TOOLTIP                        = 'Adjust the vertical position of the dashboard.'                    
string TABLEXPOS_TOOLTIP                        = 'Adjust the horizontal position of the dashboard.'                   

// Error log messages
string LONG_LEVELS_INPUT_ERROR_TXT      = 'Invalid Long levels: Please adjust.'
string SHORT_LEVELS_INPUT_ERROR_TXT     = 'Invalid Short levels: Please adjust.'
string NO_SIDE_DETECTED_TXT             = 'Trade side not detected.'
string NO_CLIENT_DATA_MESSAGE_TXT       = 'Client Data required for trading is incomplete.\nPlease check Settings.'
string FAR_BARSBACK_ERROR_TXT           = 'Support & Resistance start dates are too distant.\nPlease bring them closer.'
string ZERO_BARSBACK_ERROR_TXT          = 'Issue with Support & Resistance start dates.\nPlease adjust their positions.'
string BARSBACK_ERROR_FIX_ZERO_TXT      = 'A Start Date was reset to default\nas it was set to Zero. Please review.'
string BARSBACK_ERROR_FIX_NA_TXT        = 'A Start Date was reset to default\nas it was set to NA. Please review.'
string BARSBACK_ERROR_FIX_TOOFAR_TXT    = 'A Start Date was reset to default\nas it was too distant. Please review.'

// Ok log messages
string LONG_LEVELS_INPUT_OK_TXT         = 'Long levels set correctly.'
string SHORT_LEVELS_INPUT_OK_TXT        = 'Short levels set correctly.'
string AUTO_SIDE_DETECT_ACTIVATED_TXT   = 'Auto Side Detection enabled.'
string ENTRY_REJECTS_CONFIRMATION       = 'Entry rejections confirmed.'
string SEND_ENTRY_ORDERS_TXT            = 'Entry conditions satisfied; entry orders ready to be placed.'

// Alerts
string ENTRY_CONDITIONS_ALERT_MESSAGE           = 'All conditions for entry are satisfied.'
string INITIAL_MOMENTUM_ALERT_DETECTED_TXT      = 'Initial Momentum detected'
string INITIAL_MOMENTUM_ALERT_PROGRAMED_TXT     = 'Initial Momentum alert has been programmed.'
string TREND_STARTS_TXT                         = 'Trend Starts'
string TREND_STARTING_TXT                       = 'Trend Starting.'
string TREND_STARTING_ALERT_PROGRAMED_TXT       = 'Trend Starting alert has been programmed.'
string ENTRY_ZONE_STARTS_TXT                    = 'Entry Zone Starts'
string ENTRY_ZONE_STARTING_TXT                  = 'Entry Zone Starting.'
string ENTRY_ZONE_ALERT_PROGRAMMED_TXT          = 'Entry Zone alert has been programmed.'
string FIRST_ENTRY_SIGNAL_TXT                   = 'First Entry Signal'
string FIRST_ENTRY_SIGNAL_TRIGGERED_TXT         = 'First Entry Signal Triggered.'
string FIRST_ENTRY_SIGNAL_PROGRAMED_TXT         = 'First Entry Signal alert has been programmed.'
string MINIMUM_RATING_ALERT_PROGRAMMED_TXT      = 'Minimum Trade Rating alert has been programmed.'

// Conditions
string CONDITION_WINNING_ROI_NAME       = 'Positive ROI (%)'
string CONDITION_LOOSING_ROI_NAME       = 'Negative ROI (%)'
string CONDITION_RRR_NAME               = 'Risk Reward Ratio (x)'
string CONDITION_TREND_NAME             = 'Trend Stage'
string CONDITION_RSI_DIVERGENCE         = 'RSI Divergence Indicator'
string CONDITION_PASS_TXT               = 'OK'
string CONDITION_FAIL_TXT               = '--'

// Debugging
bool ACTIVATE_ENTRY_CONDITIONS_EVAL     = true
bool SHOW_TRADE_TABLE                   = true

// Entry Conditions
float   MINIMUM_RSI_M               = 0.2       //'Min m for RSI divergence', group = GR_ENTRY_CONDITIONS)
float   MINIMUM_RSI_R2              = 0.65      //'Min R2 in RSI', group = GR_ENTRY_CONDITIONS)
int     NUMBER_OF_ENTRIES_PER_ZONE  = 2
float   MARGIN_OVER_RRR             = 0.2       // Margin used to calculate automatic target
float   MIN_DVRG_M                  = 0.1

// Support and Resistance zones
float   STOPLOSS_BUFFER_MARGIN_TIGHT    = 50        // % of ATR
float   STOPLOSS_BUFFER_MARGIN_MEDIUM   = 100       // % of ATR
float   STOPLOSS_BUFFER_MARGIN_LOOSE    = 200       // % of ATR
float   TAKEPROFIT_BUFFER_MARGIN_INPUT  = 0         // % of ATR

// Dashboard
int TOTAL_COLUMNS           = 6
int TOTAL_ROWS              = 30
int DASHBOARD_FRAME_WIDTH   = dark_bg_flag ? 0 : 1

// TradeBox
int SEPARATION_FROM_LEVELS_INPUT        = 3     // Separation from level boxes
int TRADEBOX_WIDTH_INPUT                = 40    // Trade Box width (bars)
int TRADEBOX_WIDTH_OPEN_POSITION_INPUT  = 30
string TRADEBOX_POSITION_TXT            = ''
string PRICE_LABEL_STYLE                = label.style_label_left
string TRADEBOX_TEXT_HALIGN             = text.align_center
string TRADEBOX_TEXT_VALIGN             = text.align_center
string TRADEBOX_TEXT_SIZE               = size.small

// Active Trade Label
string ACTIVE_TRADE_LABEL_STYLE         = label.style_label_down    // label.style_label_lower_left
string AUTO_TRADE_NAME                  = 'Trade'                   // Name used in the input selector for choosing auto trade
string ACTIVE_TRADE_LABEL_TEXT_ALIGN    = text.align_left

// Price labels
int DECIMALS_QTY_LABELS = 4

//**************************************************************************************//
// INPUTS
//**************************************************************************************//
                   
// Initial options
bool    show_market_outlook      = input.bool(true, 'Expand Market Outlook', display = display.none, group = GR_DASHBOARD_COMPONENTS, tooltip = SHOW_MARKET_OUTLOOK_TOOLTIP)
bool    show_entry_conditions    = input.bool(false, 'Expand Entry Conditions Table', display = display.none, group = GR_DASHBOARD_COMPONENTS, tooltip = SHOW_ENTRY_CONDITIONS_TOOLTIP)
bool    show_estimated_pnl_input = input.bool(false, 'Expand Estimated P&L Table', display = display.none, group = GR_DASHBOARD_COMPONENTS, tooltip = SHOW_ESTIMATED_PNL_TOOLTIP)
bool    show_logs                = input.bool(false, 'Expand Logs Table', display = display.none, group = GR_DASHBOARD_COMPONENTS, tooltip = SHOW_LOGS_TOOLTIP)
bool    draw_trade_box           = input.bool(true, 'Show Trade Box', display = display.none, group = GR_DASHBOARD_COMPONENTS, tooltip = DRAW_TRADE_BOX_TOOLTIP)
bool    show_price_labels        = input.bool(false, 'Show Trade Levels', display = display.none, group = GR_DASHBOARD_COMPONENTS, tooltip = SHOW_PRICE_LABELS_TOOLTIP)
string  side_input               = input.string('Auto','Side',options = ['Auto','Long','Short'], group = GR_ACTIVE_TRADE_SETUP, display = display.none, tooltip = SIDE_TOOLTIP)
float   leverage_input           = input.float(30,'Leverage (x)', group = GR_ACTIVE_TRADE_SETUP, display = display.none, tooltip = LEVERAGE_TOOLTIP, minval = 1, maxval = 100)

// Short Trade Setup
string  last_entry_short_input  = input.string('Medium MA', 'Last Entry', options = [
                                                                 '400 Highest',
                                                                 '200 Highest',
                                                                 '100 Highest',
                                                                 '50 Highest',
                                                                 '20 Highest',
                                                                 'Slow MA', 
                                                                 'Medium MA',
                                                                 'Fast MA',   
                                                                 '20 Lowest',
                                                                 '50 Lowest',
                                                                 '100 Lowest',
                                                                 '200 Lowest',
                                                                 '400 Lowest'
                                                                 ],  group = GR_SHORT, display = display.none, tooltip = LAST_ENTRY_SHORT_TOOLTIP)
string  first_entry_short_input = input.string('Fast MA', 'First Entry', options = [
                                                                 '400 Highest',
                                                                 '200 Highest',
                                                                 '100 Highest',
                                                                 '50 Highest',
                                                                 '20 Highest',
                                                                 'Slow MA', 
                                                                 'Medium MA',
                                                                 'Fast MA',   
                                                                 '20 Lowest',
                                                                 '50 Lowest',
                                                                 '100 Lowest',
                                                                 '200 Lowest',
                                                                 '400 Lowest'
                                                                 ], group = GR_SHORT, display = display.none, tooltip = FIRST_ENTRY_SHORT_TOOLTIP)

string  exit_short_input        = input.string('Auto', 'Target', options = [
                                                                 'Auto',
                                                                 '400 Highest',
                                                                 '200 Highest',
                                                                 '100 Highest',
                                                                 '50 Highest',
                                                                 '20 Highest',
                                                                 'Slow MA', 
                                                                 'Medium MA',
                                                                 'Fast MA',   
                                                                 '20 Lowest',
                                                                 '50 Lowest',
                                                                 '100 Lowest',
                                                                 '200 Lowest',
                                                                 '400 Lowest'
                                                                 ], group = GR_SHORT, display = display.none, tooltip = EXIT_SHORT_TOOLTIP )
  

// Long Trade Setup 
string  exit_long_input         = input.string('Auto', 'Target', options = [
                                                                 'Auto',
                                                                 '400 Highest',
                                                                 '200 Highest',
                                                                 '100 Highest',
                                                                 '50 Highest',
                                                                 '20 Highest',
                                                                 'Fast MA', 
                                                                 'Medium MA',
                                                                 'Slow MA',   
                                                                 '20 Lowest',
                                                                 '50 Lowest',
                                                                 '100 Lowest',
                                                                 '200 Lowest',
                                                                 '400 Lowest'
                                                                 ], group = GR_LONG, display = display.none, tooltip = EXIT_LONG_TOOLTIP)
string  first_entry_long_input  = input.string('Fast MA', 'First Entry', options = [
                                                                 '400 Highest',
                                                                 '200 Highest',
                                                                 '100 Highest',
                                                                 '50 Highest',
                                                                 '20 Highest',
                                                                 'Fast MA', 
                                                                 'Medium MA',
                                                                 'Slow MA',   
                                                                 '20 Lowest',
                                                                 '50 Lowest',
                                                                 '100 Lowest',
                                                                 '200 Lowest',
                                                                 '400 Lowest'
                                                                 ], group = GR_LONG, display = display.none, tooltip = FIRST_ENTRY_LONG_TOOLTIP)
string  last_entry_long_input   = input.string('Medium MA', 'Last Entry', options = [
                                                                 '400 Highest',
                                                                 '200 Highest',
                                                                 '100 Highest',
                                                                 '50 Highest',
                                                                 '20 Highest',
                                                                 'Fast MA', 
                                                                 'Medium MA',
                                                                 'Slow MA',   
                                                                 '20 Lowest',
                                                                 '50 Lowest',
                                                                 '100 Lowest',
                                                                 '200 Lowest',
                                                                 '400 Lowest'
                                                                 ], group = GR_LONG, display = display.none, tooltip = LAST_ENTRY_LONG_TOOLTIP)

                                                    
// Risk Control
float   equity_investment_per_trade_input   = input.float(10, 'Equity investment per entry (%)', group = GR_RISK_SETUP, display = display.none, tooltip = EQUITY_INVESTMENT_PER_TRADE_TOOLTIP, minval = 0.1, maxval = 100)
string  stoploss_type_input                 = input.string('Medium','Stoploss size', options =['Tight', 'Medium', 'Loose'], group = GR_RISK_SETUP, display = display.none, tooltip =  STOPLOSS_TYPE_TOOLTIP)

// Entry Conditions
bool    act_minimum_wining_roi_input   = input.bool(true, '', inline = 'EC1', group = GR_ENTRY_CONDITIONS, tooltip = ACT_MINIMUM_WINING_ROI_TOOLTIP)
bool    act_maximum_loosing_roi_input  = input.bool(true, '', inline = 'EC2', group = GR_ENTRY_CONDITIONS, tooltip = ACT_MAXIMUM_LOOSING_ROI_TOOLTIP)
bool    act_minimum_rrr_input          = input.bool(true, '', inline = 'EC3',group = GR_ENTRY_CONDITIONS, tooltip = ACT_MINIMUM_RRR_TOOLTIP)
float   minimum_wining_roi_input       = input.float(45, 'Min winning ROI (%)', inline = 'EC1', group = GR_ENTRY_CONDITIONS, display = display.none, tooltip = MINIMUM_WINING_ROI_TOOLTIP, minval = 1)
float   maximum_loosing_roi_input      = input.float(20, 'Max loosing ROI (%)', inline = 'EC2', group = GR_ENTRY_CONDITIONS, display = display.none, tooltip = MAXIMUM_LOOSING_ROI_TOOLTIP, minval = 0, maxval = 100)
float   minimum_rrr_input              = input.float(3,'Min Risk Reward Ratio (x)', inline = 'EC3',group = GR_ENTRY_CONDITIONS, display = display.none, tooltip = MINIMUM_RRR_TOOLTIP, minval = 0)
string  outlook_rating_input_txt       = input.string(
                                                                 'Entry Zone','Trend Stage',options =[
                                                                 'Initial Momentmum','Trend Started','Entry Zone','Entry Signal','None'
                                                                 ], inline = 'EC4',group = GR_ENTRY_CONDITIONS, display = display.none, tooltip = OUTLOOK_RATING_INPUT_TOOLTIP)
bool    act_rsi_divergence             = input.bool(true,'Auto RSI Divergence',group = GR_ENTRY_CONDITIONS, display = display.none, tooltip = ACT_RSI_DIVERGENCE_TOOLTIP)
int     minimum_trade_rating_input     = input.int(80,'Minimum Trade Rating (%)', group = GR_ENTRY_CONDITIONS, display = display.none, tooltip = MINIMUM_TRADE_RATING_TOOLTIP, minval = 0, maxval = 100)

// Exchange setup
float   equity_input                = input.float(5000,'Available equity (USDT)', group = GR_EXCHANGE, display = display.none, tooltip = EQUITY_TOOLTIP, minval = 0)
float   entry_fee_rate_input        = input.float(0.02, 'Exchange Entry Fees (%)', group = GR_EXCHANGE, display = display.none, tooltip = ENTRY_FEE_RATE_TOOLTIP, minval = 0)
float   exit_fee_rate_input         = input.float(0.055, 'Exchange Exit Fees (%)', group = GR_EXCHANGE, display = display.none, tooltip = EXIT_FEE_RATE_TOOLTIP, minval = 0)  

// Alerts
string market_outlook_alert         = input.string('None','Activate when ', options = [
                                                                 'Initial Momentmum detected','Trend Starts','Entry Zone Starts','First Entry Signal','None'], group = GR_ALERTS, display = display.none, tooltip = MARKET_OUTLOOK_ALERT_TOOLTIP)
bool minimum_trade_rating_alert     = input.bool(false,'Activate when minimum Entry Conditions are met', group = GR_ALERTS, display = display.none, tooltip = MINIMUM_TRADE_RATING_ALERT_TOOLTIP)

// Dashboard
var string text_size_input  = input.string('Small','Dashboard text size', options = ['Tiny','Small','Normal','Auto'], group = GR_LAYOUT, display = display.none, tooltip = TEXT_SIZE_INPUT_TOOLTIP)
var string tableYposInput   = input.string("top", "Dashboard position", inline = "11", options = ["top", "middle", "bottom"], group = GR_LAYOUT, display = display.none, tooltip = TABLEYPOS_TOOLTIP)
var string tableXposInput   = input.string("right", "", inline = "11", options = ["left", "center", "right"], group = GR_LAYOUT, display = display.none, tooltip = TABLEXPOS_TOOLTIP)

//**************************************************************************************//
// FUNCTIONS
//**************************************************************************************//
toPercentageString(x, decimals) =>
    str.tostring(math.round(x * 100, decimals)) + '%'
toFactorString(x, decimals) =>
    str.tostring(math.round(x,decimals)) + 'x'
toNumberString(x,decimals) =>
    str.tostring(math.round(x,decimals),"#,###.#####")
toCurrencyString(x,decimals) =>
    '$' + str.tostring(math.round(x,decimals),"#,###.##")
get_buffer_margin(atr_length, buffer_margin_input)=>
    ta.atr(atr_length) * (buffer_margin_input / 100)
get_log_text(log_array)=>

    txt_log = ''
    log_array_size = array.size(log_array)

    if log_array_size > 0 

        for i = 0 to log_array_size - 1

            log = array.get(log_array, i)
            txt_log := txt_log + log 
            txt_log := i == log_array_size - 1 ? txt_log : txt_log + '\n'
    
    txt_log

create_and_populate_entry_condition(name, description, min_condition, true_condition)=>
    
    // Create condition
    entry_condition condition = entry_condition.new()

    // Populate condition fields
    condition.name              := name
    condition.description       := description
    condition.actual_float      := na
    condition.min_condition     := min_condition
    condition.true_condition    := true_condition 
    condition.pass              := na

    condition

//**************************************************************************************//
// INITIAL SETUP 
//**************************************************************************************//

// Update log with type of operation.
array.push(status_log_array, execution_mode_input +' operation mode selected.')

// Update log with side selection.
if side_input == 'Auto'
    array.push(status_log_array,AUTO_SIDE_DETECT_ACTIVATED_TXT)
else
    array.push(status_log_array,'Manually, ' + side_input + ' trade side selected.')

//**************************************************************************************//
// INITIALIZE ENTRY CONDITIONS
//**************************************************************************************//

// Get numeric value of outlook rating input
float outlook_rating_input = switch outlook_rating_input_txt
    
    'Initial Momentmum'  => 1
    'Trend Started'      => 2
    'Entry Zone'         => 3
    'Entry Signal'       => 4


// Get the RSI Divergence requirement
required_rsi_divergence = true // <<<<<<<<ARREGLAR

// Creae array where entry conditions will be stored
entry_conditions_array = array.new<entry_condition>()

// Create entry condition variables
if act_minimum_wining_roi_input
    condition = create_and_populate_entry_condition('minimum_wining_roi_input', CONDITION_WINNING_ROI_NAME, minimum_wining_roi_input, false)
    array.push(entry_conditions_array, condition)

if act_maximum_loosing_roi_input
    condition = create_and_populate_entry_condition('maximum_loosing_roi_input', CONDITION_LOOSING_ROI_NAME, maximum_loosing_roi_input, false)
    array.push(entry_conditions_array, condition)

if act_minimum_rrr_input
    condition = create_and_populate_entry_condition('minimum_rrr_input', CONDITION_RRR_NAME, minimum_rrr_input, false)
    array.push(entry_conditions_array, condition)

if outlook_rating_input > 0
    condition = create_and_populate_entry_condition('outlook_rating_input', CONDITION_TREND_NAME, outlook_rating_input, false)
    array.push(entry_conditions_array, condition)

if act_rsi_divergence
    condition = create_and_populate_entry_condition('rsi_divergence', CONDITION_RSI_DIVERGENCE, 0, required_rsi_divergence)
    array.push(entry_conditions_array, condition)

//**************************************************************************************//
// TRADE
//**************************************************************************************//

// Variable initiation
float long_target_auto = na
float short_target_auto = na


// Highest and lowest datapoint
float highest_400 = ta.highest(400)
float highest_200 = ta.highest(200)
float highest_100 = ta.highest(100)
float highest_50 = ta.highest(50)
float highest_20 = ta.highest(20)
float lowest_20 = ta.lowest(20)
float lowest_50 = ta.lowest(50)
float lowest_100 = ta.lowest(100)
float lowest_200 = ta.lowest(200)
float lowest_400 = ta.lowest(200)
     

// SWITCH OF SELECTED TRADE LEVELS
//---------------------------------------------------------------------

// Short
float last_entry_price_short = switch last_entry_short_input
    
    '400 Highest'                   => highest_400
    '200 Highest'                   => highest_200
    '100 Highest'                   => highest_100
    '50 Highest'                    => highest_50
    '20 Highest'                    => highest_20
    'Slow MA'                       => ma_slow
    'Medium MA'                     => ma_med
    'Fast MA'                       => ma_fast
    '20 Lowest'                     => lowest_20
    '50 Lowest'                     => lowest_50
    '100 Lowest'                    => lowest_100
    '200 Lowest'                    => lowest_200
    '400 Lowest'                    => lowest_400



float first_entry_price_short = switch first_entry_short_input   

    '400 Highest'                   => highest_400
    '200 Highest'                   => highest_200
    '100 Highest'                   => highest_100
    '50 Highest'                    => highest_50
    '20 Highest'                    => highest_20
    'Slow MA'                       => ma_slow
    'Medium MA'                     => ma_med
    'Fast MA'                       => ma_fast
    '20 Lowest'                     => lowest_20
    '50 Lowest'                     => lowest_50
    '100 Lowest'                    => lowest_100
    '200 Lowest'                    => lowest_200
    '400 Lowest'                    => lowest_400

float exit_price_win_short = switch exit_short_input
    
    'Auto'                      => short_target_auto
    '400 Highest'                   => highest_400
    '200 Highest'                   => highest_200
    '100 Highest'                   => highest_100
    '50 Highest'                    => highest_50
    '20 Highest'                    => highest_20
    'Slow MA'                       => ma_slow
    'Medium MA'                     => ma_med
    'Fast MA'                       => ma_fast
    '20 Lowest'                     => lowest_20
    '50 Lowest'                     => lowest_50
    '100 Lowest'                    => lowest_100
    '200 Lowest'                    => lowest_200
    '400 Lowest'                    => lowest_400

// Long
float exit_price_win_long = switch exit_long_input
   
    'Auto'                      => long_target_auto
    '400 Highest'                   => highest_400
    '200 Highest'                   => highest_200
    '100 Highest'                   => highest_100
    '50 Highest'                    => highest_50
    '20 Highest'                    => highest_20
    'Slow MA'                       => ma_slow
    'Medium MA'                     => ma_med
    'Fast MA'                       => ma_fast
    '20 Lowest'                     => lowest_20
    '50 Lowest'                     => lowest_50
    '100 Lowest'                    => lowest_100
    '200 Lowest'                    => lowest_200
    '400 Lowest'                    => lowest_400

float first_entry_price_long = switch first_entry_long_input
   
    '400 Highest'                   => highest_400
    '200 Highest'                   => highest_200
    '100 Highest'                   => highest_100
    '50 Highest'                    => highest_50
    '20 Highest'                    => highest_20
    'Slow MA'                       => ma_slow
    'Medium MA'                     => ma_med
    'Fast MA'                       => ma_fast
    '20 Lowest'                     => lowest_20
    '50 Lowest'                     => lowest_50
    '100 Lowest'                    => lowest_100
    '200 Lowest'                    => lowest_200
    '400 Lowest'                    => lowest_400

float last_entry_price_long = switch last_entry_long_input
   
    '400 Highest'                   => highest_400
    '200 Highest'                   => highest_200
    '100 Highest'                   => highest_100
    '50 Highest'                    => highest_50
    '20 Highest'                    => highest_20
    'Slow MA'                       => ma_slow
    'Medium MA'                     => ma_med
    'Fast MA'                       => ma_fast
    '20 Lowest'                     => lowest_20
    '50 Lowest'                     => lowest_50
    '100 Lowest'                    => lowest_100
    '200 Lowest'                    => lowest_200
    '400 Lowest'                    => lowest_400

// Stoploss Buffer
float STOPLOSS_BUFFER_MARGIN_MULT = switch stoploss_type_input
    'Tight'             => STOPLOSS_BUFFER_MARGIN_TIGHT
    'Medium'            => STOPLOSS_BUFFER_MARGIN_MEDIUM
    'Loose'             => STOPLOSS_BUFFER_MARGIN_LOOSE

// GET STOPLOSS PRICE
//-------------------------
stoploss_buffer_margin  = get_buffer_margin(14, STOPLOSS_BUFFER_MARGIN_MULT)
long_stoploss_price     = last_entry_price_long - stoploss_buffer_margin
short_stoploss_price    = last_entry_price_short + stoploss_buffer_margin

// GET TARGET PRICE WHEN AUTO
//--------------------------------

// Get price definitions
avg_entry_price_long    = math.avg(first_entry_price_long, last_entry_price_long)
avg_entry_price_short   = math.avg(first_entry_price_short, last_entry_price_short)
equity_investment       = (equity_investment_per_trade_input / 100) * equity_input
total_investment        = equity_investment * leverage_input
exchange_entry_fees     = (total_investment * (entry_fee_rate_input/100))
exchange_exit_fees_rrr  = exchange_entry_fees * minimum_rrr_input
exchange_exit_fees_roi  = exchange_entry_fees * (1 + (minimum_wining_roi_input/100))
exchange_exit_fees      = math.max(exchange_exit_fees_rrr,exchange_exit_fees_roi)
total_exchange_fees     = exchange_entry_fees + exchange_exit_fees
minimum_profit          = equity_investment * (minimum_wining_roi_input / 100)
min_exit_amount         = minimum_profit + total_investment + exchange_entry_fees + exchange_exit_fees

// Get exit price when Long
if na(exit_price_win_long)

    // Get target by RRR
    long_loss_range     = (avg_entry_price_long - long_stoploss_price) //+ total_exchange_fees
    long_profit_range   = long_loss_range * minimum_rrr_input * (1 + MARGIN_OVER_RRR)
    long_price_win_rrr  = avg_entry_price_long + long_profit_range

    // Get target by ROI
    qty_invested_long   = total_investment / avg_entry_price_long
    long_price_win_roi  = min_exit_amount / qty_invested_long

    // Choose target
    exit_price_win_long := math.max(long_price_win_rrr, long_price_win_roi)

// Get exit price when Short
float short_loss_range = na
float short_profit_range = na
float short_price_win_rrr = na

if na(exit_price_win_short)

    // GEt target by RRR
    short_loss_range     := (short_stoploss_price - avg_entry_price_short) //+ total_exchange_fees
    short_profit_range   := short_loss_range * minimum_rrr_input  * (1 + MARGIN_OVER_RRR)
    short_price_win_rrr  := avg_entry_price_short - short_profit_range

    // Get target by ROI
    qty_invested_short   = total_investment / avg_entry_price_short
    short_price_win_roi  = min_exit_amount / qty_invested_short

    // Choose target
    exit_price_win_short := math.min(short_price_win_rrr, short_price_win_roi)



// Validate that levels are correctly selected
//------------------------------------------------------
bool long_levels_input_ok_flg = exit_price_win_long > first_entry_price_long and first_entry_price_long > last_entry_price_long
bool short_levels_input_ok_flg = exit_price_win_short < first_entry_price_short and first_entry_price_short < last_entry_price_short

// Log success or error messages on validation
//-----------------------------------------------
if long_levels_input_ok_flg
    array.push(status_log_array, LONG_LEVELS_INPUT_OK_TXT)
else if not(long_levels_input_ok_flg) and (up_trend_flag or side_input == 'Long')
    array.push(error_log_array, LONG_LEVELS_INPUT_ERROR_TXT)

if short_levels_input_ok_flg 
    array.push(status_log_array, SHORT_LEVELS_INPUT_OK_TXT)
else if not(short_levels_input_ok_flg) and (dn_trend_flag or side_input == 'Short')
    array.push(error_log_array, SHORT_LEVELS_INPUT_ERROR_TXT)

// Trade side definition
//-------------------------

// Variable initialization
float first_entry_price     = na
float last_entry_price      = na 
float exit_price_win        = na 
bool detected_side_long     = na
bool detected_side_short    = na
bool selected_side_long     = na
bool selected_side_short    = na
string trade_side           = na

// Side detection depending on trend direction
long_side_flag = (indicator_trade_side == 'Bullish' or indicator_trade_side == 'Long') //and long_levels_input_ok_flg
short_side_flag = (indicator_trade_side == 'Bearish' or indicator_trade_side == 'Short') //and short_levels_input_ok_flg
detected_side_txt = long_side_flag and short_side_flag ? 'Long & Short' :
                     long_side_flag ? 'Long' :
                     short_side_flag ? 'Short' : 'No'

// If no side was detected, inform it.
if not(long_side_flag) and not(short_side_flag)
    array.push(error_log_array,NO_SIDE_DETECTED_TXT)

// Automatic vs manual detection
if side_input == 'Auto'
    detected_side_long := long_side_flag ? true : false
    detected_side_short := short_side_flag ? true : false

    // Update log
    array.push(status_log_array, detected_side_txt + ' side detected.' )

// Manual side assignment 
else
    selected_side_long := long_levels_input_ok_flg and side_input == 'Long' ? true : false
    selected_side_short := short_levels_input_ok_flg and side_input == 'Short' ? true : false

// Get the correct price
if detected_side_long or selected_side_long 
    first_entry_price   := first_entry_price_long 
    last_entry_price    := last_entry_price_long 
    exit_price_win      := exit_price_win_long 
    trade_side          := 'Long'

else if detected_side_short or selected_side_short
    first_entry_price   := first_entry_price_short
    last_entry_price    := last_entry_price_short
    exit_price_win      := exit_price_win_short
    trade_side          := 'Short'


// Trade Levels
//---------------------------------------------------------------------

// Prices
avg_entry_price = trade_side == 'Long' ? avg_entry_price_long : avg_entry_price_short
price_change_win = (exit_price_win / avg_entry_price) - 1
//equity_investment = (equity_investment_per_trade_input / 100) * equity_input

// Takerprofit
takeprofit_buffer_margin = get_buffer_margin(14, TAKEPROFIT_BUFFER_MARGIN_INPUT)
exit_price_win := trade_side == 'Long' ? exit_price_win - takeprofit_buffer_margin : exit_price_win + takeprofit_buffer_margin

// Stoploss
stoploss_price = trade_side == 'Long' ? long_stoploss_price : short_stoploss_price
price_change_loss = (stoploss_price / avg_entry_price) - 1

// Entry and exit values
entry_value = equity_investment * leverage_input
entry_qty = entry_value / avg_entry_price

first_entry_qty = entry_qty / 2
last_entry_qty = entry_qty / 2

exit_value_win = entry_qty * exit_price_win
exit_value_loss = entry_qty * stoploss_price

first_entry_value = first_entry_qty * first_entry_price
last_entry_value = last_entry_qty * last_entry_price

// Trade P&L
//---------------------------------------------------------------------

// Initialize variables
float target_profit     = na
float potential_loss    = na
float pnl_win           = na
float pnl_loss          = na
float roi_win           = na
float roi_loss          = na
float rrr               = na
float roe_win           = na
float roe_loss          = na

// Update values if a trade exists
if entry_value > 0 and exit_value_win > 0

    // Fees
    entry_fees      = entry_value * (entry_fee_rate_input / 100)
    exit_fees_win   = exit_value_win * (exit_fee_rate_input / 100)
    exit_fees_loss  = exit_value_loss * (exit_fee_rate_input / 100)

    // PNL
    target_profit   := trade_side == 'Long' ? exit_value_win - entry_value : entry_value - exit_value_win
    potential_loss  := trade_side == 'Long' ? exit_value_loss - entry_value : entry_value - exit_value_loss
    pnl_win         := target_profit - entry_fees - exit_fees_win
    pnl_loss        := potential_loss - entry_fees - exit_fees_loss

    // ROI
    roi_win         := pnl_win / equity_investment
    roi_loss        := pnl_loss / equity_investment
    rrr             := roi_win / math.abs(roi_loss)
    roe_win         := pnl_win / equity_input
    roe_loss        := pnl_loss / equity_input

else 
    // If no trade exists update values so that they are zero
    price_change_win := 0
    price_change_loss := 0

// Trade Evaluation
//---------------------------------------------------------------------
minimum_winning_roi_ok_flag = roi_win >= (minimum_wining_roi_input / 100)
maximum_loosing_roi_input_ok_flag = math.abs(roi_loss) <= (maximum_loosing_roi_input / 100)
minimum_rrr_input_ok_flag = rrr >= minimum_rrr_input
trade_economics_ok_flag = minimum_winning_roi_ok_flag and maximum_loosing_roi_input_ok_flag and minimum_rrr_input_ok_flag

//---------------------------------------------------------------------
// Trade Flags
//---------------------------------------------------------------------

bool bullish_trend = na 
bool bearish_trend = na

// Messages
txt_trend = 
     bullish_trend ? 'Bullish' :
     bearish_trend ? 'Bearish' : 'None'

txt_economics =
     trade_economics_ok_flag ? 'Ok' : 'Not Good'


//**************************************************************************************//
// MARKET OUTLOOK RATING
//**************************************************************************************//
market_outlook_rating = trade_side == 'Long' ? long_entry_rating :
                         trade_side == 'Short' ? short_entry_rating : 0

market_outlook_rating_OK_flag = market_outlook_rating >= outlook_rating_input

//**************************************************************************************//
// UPDATE DIVERGENCE CONDITION
//**************************************************************************************//

// Initialize variables
float rsi_divrg_min_condition   = na
bool rsi_divergence_ok_flag     = na

// if trade is long
if trade_side == 'Long' and act_rsi_divergence

    // Define minimu condition
    rsi_divrg_min_condition := MIN_DVRG_M

    // Get divergence flag
    rsi_divergence_ok_flag := rsi_dvrg >= MIN_DVRG_M


// If trade is short
else if trade_side == 'Short' and act_rsi_divergence

    // Define minimum conditon
    rsi_divrg_min_condition := - MIN_DVRG_M

    // Get divergence flag
    rsi_divergence_ok_flag := rsi_dvrg <= MIN_DVRG_M


// If Divergence and selected trade incorrect the suggest changing sides 
if rsi_dvrg > 0 and dn_trend_flag and trade_side == 'Short'

    array.push(error_log_array, BULLISH_RSI_DVRG_ERROR_LOG_TXT)

if rsi_dvrg < 0 and up_trend_flag and trade_side == 'Long'

    array.push(error_log_array, BEARISH_RSI_DVRG_ERROR_LOG_TXT)


//**************************************************************************************//
// DEFINE ENTRY CONDITIONS & GET TRADE RATING
//**************************************************************************************//

// Initialize variables
bool buyZone_active             = 0
bool sellZone_active            = 0
float start_buyZone_webh        = na
float end_buyZone_webh          = na  
float start_sellZone_webh       = na    
float end_sellZone_webh         = na      
bool confirmation_flag          = false
int num_confirmation_rejects    = 0

// Initiate variables for rating 
int total_entry_conditions  = array.size(entry_conditions_array)
int passed_entry_conditions = 0
float trade_rating          = 0.0

// Evaluate Entry Conditions if trading has been activated 
if barstate.islast and ACTIVATE_ENTRY_CONDITIONS_EVAL 

    // Check for Entry Conditions
    //-------------------------------------
    for i = 0 to total_entry_conditions - 1 

        // Get conditions 
        condition = array.get(entry_conditions_array, i)

        // Update condition values and update array
        //-------------------------------------------
        if condition.name == 'minimum_wining_roi_input'
            condition.min_condition := minimum_wining_roi_input
            condition.actual_float  := roi_win * 100
            condition.pass          := minimum_winning_roi_ok_flag

        if condition.name == 'maximum_loosing_roi_input'
            condition.min_condition := - maximum_loosing_roi_input
            condition.actual_float  := roi_loss * 100
            condition.pass          := maximum_loosing_roi_input_ok_flag

        if condition.name == 'minimum_rrr_input'
            condition.min_condition := minimum_rrr_input
            condition.actual_float  := rrr
            condition.pass          := minimum_rrr_input_ok_flag

        if condition.name == 'outlook_rating_input'
            condition.min_condition := outlook_rating_input
            condition.actual_float  := market_outlook_rating
            condition.pass          := market_outlook_rating_OK_flag

        if condition.name == 'rsi_divergence'
            condition.min_condition := rsi_divrg_min_condition
            condition.actual_float  := rsi_dvrg
            condition.pass          := rsi_divergence_ok_flag
            
        // Add a passed entry condition
        passed_entry_conditions := condition.pass ? passed_entry_conditions + 1 : passed_entry_conditions

        // Update array
        array.set(entry_conditions_array,i, condition)


// Get trade rating
//---------------------
trade_rating := (passed_entry_conditions / total_entry_conditions) * 100
trade_rating_ok_flag = trade_rating >= minimum_trade_rating_input ? true : false
trade_rating_txt = toNumberString(trade_rating,1)


// If the reject is confirmed, send orders 
//-------------------------------------------------------------------------------
send_entry_orders = false
if trade_rating_ok_flag //and confirmation_flag

    send_entry_orders := true
    array.push(status_log_array,SEND_ENTRY_ORDERS_TXT)


    //Populate the fields that will be used to send the order    
    if trade_side == 'Long'

        buyZone_active      := 1
        start_buyZone_webh  := first_entry_price
        end_buyZone_webh    := last_entry_price

    else if trade_side == 'Short'

        sellZone_active     := 1
        start_sellZone_webh := first_entry_price
        end_sellZone_webh   := last_entry_price


//**************************************************************************************//
// ALERTS
//**************************************************************************************//

// Alerts when Market Outlook Events occur 
if market_outlook_alert != 'None'

    // Initial Momentum Alert
    if market_outlook_alert == INITIAL_MOMENTUM_ALERT_DETECTED_TXT

        if
         (long_entry_rating == 1 and long_entry_rating[1] == 0) or
         ((short_entry_rating == 1 and short_entry_rating[1] == 0))

            alert(INITIAL_MOMENTUM_ALERT_DETECTED_TXT, alert.freq_all)

        array.push(status_log_array,INITIAL_MOMENTUM_ALERT_PROGRAMED_TXT)

    // Trend starting alert
    if market_outlook_alert == TREND_STARTS_TXT

        if
         (long_entry_rating == 2 and long_entry_rating[1] == 1) or
         ((short_entry_rating == 2 and short_entry_rating[1] == 1))

            alert(TREND_STARTING_TXT, alert.freq_all)

        array.push(status_log_array,TREND_STARTING_ALERT_PROGRAMED_TXT)

    // Entry Zone Alert
    if market_outlook_alert == ENTRY_ZONE_STARTS_TXT

        if
         (long_entry_rating == 3 and long_entry_rating[1] == 2) or
         ((short_entry_rating == 3 and short_entry_rating[1] == 2))

            alert(ENTRY_ZONE_STARTING_TXT, alert.freq_all)

        array.push(status_log_array,ENTRY_ZONE_ALERT_PROGRAMMED_TXT)

    // First entry signal alert
    if market_outlook_alert == FIRST_ENTRY_SIGNAL_TXT

        if
         (long_entry_rating == 4 and long_entry_rating[1] == 3) or
         ((short_entry_rating == 4 and short_entry_rating[1] == 3))

            alert(FIRST_ENTRY_SIGNAL_TRIGGERED_TXT, alert.freq_all)

        array.push(status_log_array,FIRST_ENTRY_SIGNAL_PROGRAMED_TXT)

// Alert when minimum trade rating has been met
if minimum_trade_rating_alert

    // Only triggered when the flag is generated
    if trade_rating_ok_flag and not(trade_rating_ok_flag[1])
        alert(ENTRY_CONDITIONS_ALERT_MESSAGE, alert.freq_all)

    array.push(status_log_array,MINIMUM_RATING_ALERT_PROGRAMMED_TXT)

//**************************************************************************************//
// LOGS 
//**************************************************************************************//

// Determine number of error logs 
number_errors = array.size(error_log_array)

// Create text messages of logs
txt_error_log = get_log_text(error_log_array)
txt_status_log = get_log_text(status_log_array) 

//**************************************************************************************//
// DASHBOARD
//**************************************************************************************//

// Trade side color 
color_trade_side = trade_side == 'Long' ? color.green : trade_side == 'Short' ? color.red : color.white

// Choose text size 
string text_size = switch text_size_input
    'Tiny'      => size.tiny
    'Small'     => size.small
    'Normal'    => size.normal
    'Auto'      => size.auto

// Create tables
var table dashboard = table.new(tableYposInput + "_" + tableXposInput, columns = TOTAL_COLUMNS, rows = TOTAL_ROWS, frame_color = DASHBOARD_FRAME_COLOR, frame_width = DASHBOARD_FRAME_WIDTH)

// Update table
if barstate.islast and SHOW_TRADE_TABLE

    table.set_border_color(dashboard, TABLE_CELL_COLOR)
    table.set_border_width(dashboard, 1)

//--------------------------------------------------- MAIN HEADER
    row =0
    table.cell(dashboard,0,row,DASHBOARD_TITLE, bgcolor = MAIN_HEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = size.large)
    table.merge_cells(dashboard, 0, row, TOTAL_COLUMNS - 1, row)
    table.cell_set_tooltip(dashboard, 0, row, TABLE_HEADER_TOOLTIP)

//--------------------------------------------------- MARKET OUTLOOK EVENTS
    
    // Add plus minus sign for expanding and contracting
    market_outlook_title = show_market_outlook ? MARKET_OUTLOOK_TITLE + ' [-]' : MARKET_OUTLOOK_TITLE + ' [+]'

    // Logs Header
    row +=1
    table.cell(dashboard,0, row, market_outlook_title, bgcolor = TABLE_HEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)
    table.merge_cells(dashboard, 0, row, TOTAL_COLUMNS - 1, row)

    if show_market_outlook

        outlook_log_size = array.size(outlook_log_array)

        if outlook_log_size > 0

            for i = 0 to outlook_log_size - 1
            
                row +=1
                table.cell(dashboard,0,row,toNumberString(i + 1,0), bgcolor = TABLE_CELL_COLOR , text_color = color.white, text_halign = text.align_right, text_size = text_size)
                table.cell(dashboard,1,row,array.get(outlook_log_array,i), bgcolor = EMPTY_CELL_BG_COLOR , text_color = color.black, text_halign = text.align_left, text_size = text_size)
                table.merge_cells(dashboard, 1, row, TOTAL_COLUMNS - 2, row)
                table.cell(dashboard,TOTAL_COLUMNS - 1,row,array.get(outlook_log_array_times,i), bgcolor = EMPTY_CELL_BG_COLOR , text_color = color.black, text_halign = text.align_left, text_size = text_size)
        
        else

            row +=1
            table.cell(dashboard,0,row,'1', bgcolor = TABLE_CELL_COLOR , text_color = color.white, text_halign = text.align_right, text_size = text_size)
            table.cell(dashboard,1,row,ENTRY_RATING_0_TXT, bgcolor = EMPTY_CELL_BG_COLOR , text_color = color.black, text_halign = text.align_left, text_size = text_size)
            table.merge_cells(dashboard, 1, row, TOTAL_COLUMNS - 1, row)

//--------------------------------------------------- ENTRY CONDITIONS

    // Colors
    trade_rating_color = color.from_gradient(trade_rating, 0, 100, color.red, color.green)
    trade_rating_color := trade_rating_txt == '0' ? TABLE_CELL_COLOR : trade_rating_color
    
    // Add plus minus sign for expanding and contracting
    entry_conditions_title = show_entry_conditions ? ENTRY_CONDITIONS_TITLE + ' [-]' : ENTRY_CONDITIONS_TITLE + ' [+]'

    // Entry Conditions Header
    row +=1
    table.cell(dashboard,0, row, entry_conditions_title, bgcolor = TABLE_HEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)
    table.merge_cells(dashboard, 0, row, TOTAL_COLUMNS - 1, row)

    if show_entry_conditions

        // Sub Header
        row +=1
        
        table.cell(dashboard,0,row,'Trade\nRating\n(0-100)', bgcolor = TABLE_SUBHEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)
        table.cell(dashboard,1,row,'Name', bgcolor = TABLE_SUBHEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)
        table.merge_cells(dashboard, 1, row, 2, row)
        table.cell(dashboard,3,row,'Minimum\nCondition', bgcolor = TABLE_SUBHEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)
        table.cell(dashboard,4,row,'Current\nValue', bgcolor = TABLE_SUBHEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)
        table.cell(dashboard,5,row,'Status', bgcolor = TABLE_SUBHEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)


        // Entry Conditions Entry Contents
        //----------------------------------

        // Get number of conditions
        entry_conditions_array_size = array.size(entry_conditions_array)

        // Only if conditions exist
        if entry_conditions_array_size > 0
            
            // Loop through all conditions
            for i = 0 to entry_conditions_array_size - 1

                // Get conditions
                condition               = array.get(entry_conditions_array,i)
                condition_name_txt      = condition.description
                condition_min_txt       = toNumberString(condition.min_condition, 1)
                condition_actual_txt    = na(condition.actual_float) ? '--' : toNumberString(condition.actual_float, 1)
                condition_status_txt    = condition.pass ? CONDITION_PASS_TXT : CONDITION_FAIL_TXT

                // Set color for status
                bg_color_condition_status = condition.pass ? COLOR_CONDITION_PASS : COLOR_CONDITION_FAIL

                // Set default color for current value
                bg_color_status = EMPTY_CELL_BG_COLOR

                // Conditional colors for conditions
                if not(condition_actual_txt == '--') and not(condition.actual_float == 0)

                    if condition.name == 'maximum_loosing_roi_input' 
                        bg_color_status := color.from_gradient(condition.actual_float, condition.min_condition, 0, color.red, color.green)

                    else if condition.name == 'rsi_divergence' 

                        if rsi_divrg_min_condition > 0
                            bg_color_status := color.from_gradient(condition.actual_float, 0, condition.min_condition, color.red, color.green)

                        else if rsi_divrg_min_condition < 0
                            bg_color_status := color.from_gradient(condition.actual_float, condition.min_condition, 0, color.green, color.red)

                    else
                        bg_color_status := color.from_gradient(condition.actual_float, 0, condition.min_condition, color.red, color.green)


                row +=1
                table.cell(dashboard,0,row,trade_rating_txt, bgcolor = trade_rating_color , text_color = color.black, text_halign = text.align_center, text_size = text_size)
                table.cell(dashboard,1,row,condition_name_txt, bgcolor = EMPTY_CELL_BG_COLOR , text_color = color.black, text_halign = text.align_left, text_size = text_size)
                table.merge_cells(dashboard, 1, row, 2, row)
                table.cell(dashboard,3,row, condition_min_txt, bgcolor = EMPTY_CELL_BG_COLOR , text_color = color.black, text_halign = text.align_center, text_size = text_size)
                table.cell(dashboard,4,row, condition_actual_txt, bgcolor = bg_color_status , text_color = color.black, text_halign = text.align_center, text_size = text_size)
                table.cell(dashboard,5,row, condition_status_txt, bgcolor = bg_color_condition_status , text_color = color.black, text_halign = text.align_center, text_size = text_size)
            
            // Merge the rows for the Trade Rating
            table.merge_cells(dashboard, 0, row - entry_conditions_array_size + 1, 0, row)

//--------------------------------------------------- ESTIMATED P&L

    // Conditioned colors
    color_win_roi_flag  = minimum_winning_roi_ok_flag ?          color.green : color.red
    color_loss_roi_flag = maximum_loosing_roi_input_ok_flag ?   color.green : color.red
    color_rrr_flag      = minimum_rrr_input_ok_flag ?                color.green : color.red

    // Adjust if values are zero
    color_win_roi_flag  := na(roi_win) ? EMPTY_CELL_BG_COLOR : color_win_roi_flag
    color_loss_roi_flag := na(roi_loss) ? EMPTY_CELL_BG_COLOR : color_loss_roi_flag
    color_rrr_flag      := na(rrr) ? EMPTY_CELL_BG_COLOR : color_rrr_flag
    
    // Add plus minus sign for expanding and contracting
    estimated_pnl_title = show_estimated_pnl_input ? ESTIMATED_PNL_TITLE + ' [-]' : ESTIMATED_PNL_TITLE + ' [+]'

    // Trade Results Header
    row +=1
    table.cell(dashboard, 0, row, estimated_pnl_title, bgcolor = TABLE_HEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)
    table.merge_cells(dashboard, 0, row, TOTAL_COLUMNS - 1, row)

    if show_estimated_pnl_input

        // Sub Header: Investment Data
        row +=1
        table.cell(dashboard,0,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row, 'Active\nSide', bgcolor = TABLE_SUBHEADER_COLOR, text_color = color.white, text_size = text_size)
        table.cell(dashboard,2,row, 'Total\nEquity', bgcolor = TABLE_SUBHEADER_COLOR, text_color = color.white, text_size = text_size)
        table.cell(dashboard,3,row, 'Equity\nInvestment', bgcolor = TABLE_SUBHEADER_COLOR, text_color = color.white, text_size = text_size)
        table.cell(dashboard,4,row, 'Max Investment\nPer Trade', bgcolor = TABLE_SUBHEADER_COLOR, text_color = color.white, text_size = text_size)
        table.cell(dashboard,5,row, 'Leverage', bgcolor = TABLE_SUBHEADER_COLOR, text_color = color.white, text_size = text_size)


        // Equity Investment
        row +=1
        table.cell(dashboard,0,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row, trade_side, bgcolor = color_trade_side, text_color = color.black, text_size = text_size)
        table.cell(dashboard,2,row, toCurrencyString(equity_input,1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,3,row, toCurrencyString(equity_investment,1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,4,row, toPercentageString(equity_investment_per_trade_input / 100,1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,5,row, toFactorString(leverage_input, 1) , bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)



        // Sub Header: P&L
        row +=1
        table.cell(dashboard,0,row,"", bgcolor = TABLE_CELL_COLOR, text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row,'Win', bgcolor = TABLE_SUBHEADER_COLOR, text_color = color.white, text_size = text_size)
        table.cell(dashboard,2,row,'Loss', bgcolor = TABLE_SUBHEADER_COLOR, text_color = color.white, text_size = text_size)
        table.cell(dashboard,3,row,'RRR', bgcolor = TABLE_SUBHEADER_COLOR, text_color = color.white, text_size = text_size)
        table.cell(dashboard,4,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,5,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)


        // Price Change
        row +=1
        table.cell(dashboard,0,row,"Price Change", bgcolor = TABLE_CELL_COLOR, text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row,toPercentageString(price_change_win, 1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,2,row,toPercentageString(price_change_loss, 1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,3,row,'', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,4,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,5,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)

        // P&L
        row +=1
        table.cell(dashboard,0,row,"P&L", bgcolor = TABLE_CELL_COLOR, text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row, toCurrencyString(na(pnl_win)?0:pnl_win,1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,2,row, toCurrencyString(na(pnl_loss)?0:pnl_loss,1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,3,row,'', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,4,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,5,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)

        // ROI
        row +=1
        table.cell(dashboard,0,row,"ROI", bgcolor = TABLE_CELL_COLOR, text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row, toPercentageString(na(roi_win)?0:roi_win, 1), bgcolor = color_win_roi_flag, text_color = color.black, text_size = text_size)
        table.cell(dashboard,2,row, toPercentageString(na(roi_loss)?0:roi_loss, 1), bgcolor = color_loss_roi_flag, text_color = color.black, text_size = text_size)
        table.cell(dashboard,3,row, toFactorString(na(rrr)?0:rrr, 1), bgcolor = color_rrr_flag, text_color = color.black, text_size = text_size)
        table.cell(dashboard,4,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,5,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)

        // ROI
        row +=1
        table.cell(dashboard,0,row,"ROE", bgcolor = TABLE_CELL_COLOR, text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row, toPercentageString(na(roe_win)?0:roe_win, 1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,2,row, toPercentageString(na(roe_loss)?0:roe_loss, 1), bgcolor = EMPTY_CELL_BG_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,3,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,4,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)
        table.cell(dashboard,5,row, '', bgcolor = TABLE_CELL_COLOR, text_color = color.black, text_size = text_size)

//--------------------------------------------------- LOGS
    
    // Add plus minus sign for expanding and contracting
    operation_logs_title = show_logs ? OPERATION_LOGS_TITLE + ' [-]' : OPERATION_LOGS_TITLE + ' [+]'

    // Logs Header
    row +=1
    table.cell(dashboard,0, row, operation_logs_title, bgcolor = TABLE_HEADER_COLOR , text_color = color.white, text_halign = text.align_center, text_size = text_size)
    table.merge_cells(dashboard, 0, row, TOTAL_COLUMNS - 1, row)

    if show_logs

        row +=1
        table.cell(dashboard,0,row,'Status', bgcolor = TABLE_CELL_COLOR , text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row,txt_status_log, bgcolor = EMPTY_CELL_BG_COLOR , text_color = color.black, text_halign = text.align_left, text_size = text_size)
        table.merge_cells(dashboard, 1, row, TOTAL_COLUMNS - 1, row)

    if show_logs or number_errors > 0

        row +=1
        table.cell(dashboard,0,row,'Errors', bgcolor = TABLE_CELL_COLOR , text_color = color.white, text_halign = text.align_right, text_size = text_size)
        table.cell(dashboard,1,row,txt_error_log, bgcolor = EMPTY_CELL_BG_COLOR , text_color = color.red, text_halign = text.align_left, text_size = text_size)
        table.merge_cells(dashboard, 1, row, TOTAL_COLUMNS - 1, row)


//**************************************************************************************//
// TRADE BOX
//**************************************************************************************//

// Initialize variables
int tradeBox_left_margin  = 0
int tradeBox_right_margin = 0

// Define Trade Box Margins
tradeBox_left_margin := execution_mode_input == AUTO_TRADE_NAME ? last_bar_index : last_bar_index + SEPARATION_FROM_LEVELS_INPUT
tradeBox_right_margin := execution_mode_input == AUTO_TRADE_NAME ? last_bar_index + TRADEBOX_WIDTH_INPUT : last_bar_index + SEPARATION_FROM_LEVELS_INPUT + TRADEBOX_WIDTH_INPUT

//Define Trade box Up
trade_box_up_x1     = tradeBox_left_margin
trade_box_up_y1     = trade_side == 'Long' ? exit_price_win : stoploss_price
trade_box_up_x2     = tradeBox_right_margin
trade_box_up_y2     = avg_entry_price 
trade_box_up_text   = '' 

//Define Trade box Dn
trade_box_dn_x1     = tradeBox_left_margin
trade_box_dn_y1     = avg_entry_price 
trade_box_dn_x2     = tradeBox_right_margin
trade_box_dn_y2     = trade_side == 'Long' ? stoploss_price : exit_price_win
trade_box_dn_text   = '' 


//Draw TradeBox
tradeBox_color_up = trade_side == 'Long' ? TRADEBOX_PROFIT_COLOR : TRADEBOX_LOSS_COLOR
tradeBox_color_dn = trade_side == 'Long' ? TRADEBOX_LOSS_COLOR : TRADEBOX_PROFIT_COLOR





var trade_box_up        = box.new(1, 1, 1, 1, xloc = xloc.bar_index, border_color = COLOR_TRANSP, bgcolor = tradeBox_color_up,
         text = '', text_halign = TRADEBOX_TEXT_HALIGN, text_valign = TRADEBOX_TEXT_VALIGN, text_color = TRADEBOX_POSITION_TEXT_COLOR, text_size = TRADEBOX_TEXT_SIZE)
var trade_box_dn        = box.new(1, 1, 1, 1, xloc = xloc.bar_index, border_color = COLOR_TRANSP, bgcolor = tradeBox_color_dn,
         text = '', text_halign = TRADEBOX_TEXT_HALIGN, text_valign = TRADEBOX_TEXT_VALIGN, text_color = TRADEBOX_POSITION_TEXT_COLOR, text_size = TRADEBOX_TEXT_SIZE)
var first_entry_line    = line.new(x1=1, y1=1, x2=1, y2=1, color=FIRST_ENTRY_LINE_COLOR, width=1, xloc=xloc.bar_index, style = line.style_dashed)
var avg_entry_line      = line.new(x1=1, y1=1, x2=1, y2=1, color=AVG_ENTRY_LINE_COLOR, width=1, xloc=xloc.bar_index)
var last_entry_line     = line.new(x1=1, y1=1, x2=1, y2=1, color=LAST_ENTRY_LINE_COLOR, width=1, xloc=xloc.bar_index, style = line.style_dashed)
var exit_line           = line.new(x1=1, y1=1, x2=1, y2=1, color=EXIT_LINE_COLOR, width=1, xloc=xloc.bar_index)
var stoploss_line       = line.new(x1=1, y1=1, x2=1, y2=1, color=STOPLOSS_LINE_COLOR, width=1, xloc=xloc.bar_index)
if barstate.islast and tradeBox_left_margin > 0 and draw_trade_box and (trade_side == 'Long' or trade_side == 'Short')

    // Update resistance box Up
    box.set_lefttop(trade_box_up, trade_box_up_x1, trade_box_up_y1)
    box.set_rightbottom(trade_box_up, trade_box_up_x2, trade_box_up_y2)

    // Update resistance box Dn
    box.set_lefttop(trade_box_dn, trade_box_dn_x1, trade_box_dn_y1)
    box.set_rightbottom(trade_box_dn, trade_box_dn_x2, trade_box_dn_y2)

    // Update trade box text
    box.set_text(trade_box_up, trade_box_up_text)
    box.set_text(trade_box_dn, trade_box_dn_text)

    // Update Text Color
    box.set_text_color(trade_box_up, TRADEBOX_POSITION_TEXT_COLOR)
    box.set_text_color(trade_box_dn, TRADEBOX_POSITION_TEXT_COLOR)

    // Update Background color 
    box.set_bgcolor(trade_box_up, tradeBox_color_up)
    box.set_bgcolor(trade_box_dn, tradeBox_color_dn)

    // Update lines
    line.set_xy1(first_entry_line, tradeBox_left_margin , first_entry_price)
    line.set_xy2(first_entry_line, tradeBox_right_margin , first_entry_price)

    line.set_xy1(avg_entry_line, tradeBox_left_margin , avg_entry_price)
    line.set_xy2(avg_entry_line, tradeBox_right_margin , avg_entry_price)


    line.set_xy1(last_entry_line, tradeBox_left_margin , last_entry_price)
    line.set_xy2(last_entry_line, tradeBox_right_margin , last_entry_price)


    line.set_xy1(exit_line, tradeBox_left_margin , exit_price_win)
    line.set_xy2(exit_line, tradeBox_right_margin , exit_price_win)


    line.set_xy1(stoploss_line, tradeBox_left_margin , stoploss_price)
    line.set_xy2(stoploss_line, tradeBox_right_margin , stoploss_price)

//**************************************************************************************//
// TRADE BOX LABELS
//**************************************************************************************//

// Positions
trd_summary_left_margin     = tradeBox_left_margin + ((tradeBox_right_margin - tradeBox_left_margin) / 2) 
trd_summary_up_top_margin   = trade_box_up_y1 - ((trade_box_up_y1 - trade_box_up_y2) / 4)
trd_summary_dn_top_margin   = trade_box_dn_y2 - (math.abs(stoploss_buffer_margin) * 2)

// Build required texts
entry_action_txt    = trade_side == 'Long' ? 'Buy ' : 'Sell '
exit_action_txt     = trade_side == 'Long' ? 'Sell ' : 'Buy '

// Text labels
entry_qty_txt           = toNumberString(entry_qty, DECIMALS_QTY_LABELS) 
first_entry_qty_txt     = toNumberString(first_entry_qty,DECIMALS_QTY_LABELS) 
last_entry_qty_txt      = toNumberString(last_entry_qty, DECIMALS_QTY_LABELS)
first_entry_price_txt   = toCurrencyString(first_entry_price,2)
last_entry_price_text   = toCurrencyString(last_entry_price,2)
first_entry_value_txt   = toCurrencyString(first_entry_value,2)
last_entry_value_txt    = toCurrencyString(last_entry_value,2)
exit_price_win_txt      = toCurrencyString(exit_price_win,2)
exit_value_win_txt      = toCurrencyString(exit_value_win,2)
stoploss_price_txt      = toCurrencyString(stoploss_price,2) 
exit_value_loss_txt     = toCurrencyString(exit_value_loss,2)

// Price definitions
price_labels_left_margin    = tradeBox_right_margin + SEPARATION_FROM_LEVELS_INPUT
first_entry_price_label_txt = '1st Entry: ' + entry_action_txt + first_entry_qty_txt + ' @ ' + first_entry_price_txt + ' = ' + first_entry_value_txt
last_entry_price_label_txt  =  '2nd Entry: ' + entry_action_txt + last_entry_qty_txt + ' @ ' + last_entry_price_text + ' = ' + last_entry_value_txt
exit_price_label_txt        =  'Target: ' + exit_action_txt + entry_qty_txt + ' @ ' + exit_price_win_txt + ' = ' + exit_value_win_txt
stoploss_label_txt          =  'Stoploss: '+ exit_action_txt + entry_qty_txt + ' @ ' +  stoploss_price_txt + ' = ' + exit_value_loss_txt

// Trade summary
win_txt         = 'Win: \nPrice ▲: ' + str.tostring(price_change_win,"###.#%") + '\n'
roi_win_txt     = 'ROI: ' + str.tostring(roi_win, '##.#%') + '\n'                  
loss_txt        = 'Loss: \nPrice ▲: ' + str.tostring(price_change_loss,"###.#%") + '\n'
roi_loss_txt    = 'ROI: ' + str.tostring(roi_loss, '##.#%')  + '\n'
rrr_txt         = 'RRR: ' + str.tostring(rrr,'###.#') + 'x' + '\n'
leverage_txt    = 'Leverage: ' + str.tostring(leverage_input,'###.#') + 'x' 
trd_summary_txt = win_txt + roi_win_txt + '\n' + loss_txt + roi_loss_txt + '\n' + rrr_txt  + '\n' + leverage_txt
                 
// Draw Labels
var first_entry_price_label = label.new(1, 1, '', color = PRICE_LABEL_COLOR, textcolor = PRICE_LABEL_TEXTCOLOR, style = PRICE_LABEL_STYLE)
var last_entry_price_label  = label.new(1, 1, '', color = PRICE_LABEL_COLOR, textcolor = PRICE_LABEL_TEXTCOLOR, style = PRICE_LABEL_STYLE)
var exit_price_label        = label.new(1, 1, '', color = PRICE_LABEL_COLOR, textcolor = PRICE_LABEL_TEXTCOLOR, style = PRICE_LABEL_STYLE)
var stoploss_price_label    = label.new(1, 1, '', color = PRICE_LABEL_COLOR, textcolor = PRICE_LABEL_TEXTCOLOR, style = PRICE_LABEL_STYLE)


// Draw price labels
if barstate.islast and show_price_labels and draw_trade_box and (trade_side == 'Long' or trade_side == 'Short')
    label.set_xy(first_entry_price_label,x = price_labels_left_margin , y = first_entry_price)
    label.set_xy(last_entry_price_label,x = price_labels_left_margin , y = last_entry_price)
    label.set_xy(exit_price_label,x = price_labels_left_margin , y = exit_price_win)
    label.set_xy(stoploss_price_label,x = price_labels_left_margin , y = stoploss_price)
    label.set_text(first_entry_price_label,first_entry_price_label_txt)
    label.set_text(last_entry_price_label,last_entry_price_label_txt)
    label.set_text(exit_price_label,exit_price_label_txt)
    label.set_text(stoploss_price_label,stoploss_label_txt)

if barstate.islast and draw_trade_box and (trade_side == 'Long' or trade_side == 'Short')

    // Trade summary to tradeBox
    trade_box_side_for_summary = trade_side == 'Long' ? trade_box_up : trade_box_dn
    box.set_text(trade_box_side_for_summary, trd_summary_txt)
    













