Entry Alert Bot
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © drother

//@version=5
indicator("Entry Alert Bot", overlay = true)
f_tp = input.float(2, title = "Take Profit")
f_entry = input.float(1.0, minval = 0, title = "Entry Price")
f_sl_perc = input.float(2.0, minval = 0, title = "Total Stoploss %")
f_leverage = input.float(10.0, minval = 1, title ="Leverage")
b_re_entry = input.bool(true, title = "Automatic re-entry after Stopped out?")
s_margin_mode = input.string("% of Portfolio", title = "Margin Type", options=["% of Portfolio", "Static Amount"])
f_orig_size = input.float(1, title = "Margin size")
start_day_time = input.time(timestamp('20 Mar 2023 00:20'), "Entry Begin Date/Time")
s_alert_freq = input.string("Once per Bar", title = "Alert Frequency", options=["Once per Bar", "Once per Bar Close", "All"])
s_long_entry_text = input.text_area(defval = "Long Entry \n #leverage# \n #symbol# \n #tpfull# \n #stoplossprice# \n #stoplosspercent# \n #margin# \n #margintype#", title = "Long Entry")
s_short_entry_text = input.text_area(defval = "Short Entry \n #leverage# \n #symbol# \n #tpfull# \n #stoplossprice# \n #stoplosspercent# \n #margin# \n #margintype#", title = "Short Entry")
b_enable_dashboard = input.bool(true, title = "Enable Dashboard?")
i_line_bars = input.int(15, title = "Future Positions box width")
bool b_long_trade = if f_tp > f_entry
    true
else
    false




// Create Arrays and initialize vars
var int i_entry_num = 0
var float f_sl = if b_long_trade
    math.round_to_mintick(f_entry * ((100 - f_sl_perc) * .01))
else
    math.round_to_mintick(f_entry * ((100 + f_sl_perc) * .01))
var box box_prof = na
var box box_loss = na
box.set_top(box_prof, b_long_trade? f_tp: f_entry)
box.set_top(box_loss, b_long_trade? f_entry : f_sl)
box.set_bottom(box_prof, b_long_trade? f_entry : f_tp)
box.set_bottom(box_loss, b_long_trade? f_sl : f_entry)
varip bool b_trade_entered = false
varip bool b_cross_up_entry = false
varip bool b_cross_dn_entry = false
varip bool b_cross_sl = false
varip bool b_cross_tp = false
varip bool b_trade_finished = false
varip bool b_stopped_out = false
time_to_trade = time > start_day_time
trade_time_index = bar_index + (-1 * (time - start_day_time) / (1000 * timeframe.in_seconds(timeframe.period)))
var int trade_fin_time = 0
var int trade_beg_time = 0

//replace text in alerts
s_long_entry_text := str.replace_all(s_long_entry_text, "#symbol#", str.replace_all(syminfo.ticker, ".P", ""))
s_long_entry_text := str.replace_all(s_long_entry_text, "#leverage#", str.tostring(f_leverage))
s_long_entry_text := str.replace_all(s_long_entry_text, "#tpfull#", str.tostring(f_tp))
s_long_entry_text := str.replace_all(s_long_entry_text, "#stoplossprice#", str.tostring(f_sl))
s_long_entry_text := str.replace_all(s_long_entry_text, "#stoplosspercent#", str.tostring(f_sl_perc))
s_long_entry_text := str.replace_all(s_long_entry_text, "#margin#", str.tostring(f_orig_size))
s_long_entry_text := str.replace_all(s_long_entry_text, "#margintype#", str.tostring(s_margin_mode =="Static Amount"? 2: 1))
s_short_entry_text := str.replace_all(s_short_entry_text, "#symbol#", str.replace_all(syminfo.ticker, ".P", ""))
s_short_entry_text := str.replace_all(s_short_entry_text, "#leverage#", str.tostring(f_leverage))
s_short_entry_text := str.replace_all(s_short_entry_text, "#tpfull#", str.tostring(f_tp))
s_short_entry_text := str.replace_all(s_short_entry_text, "#stoplossprice#", str.tostring(f_sl))
s_short_entry_text := str.replace_all(s_short_entry_text, "#stoplosspercent#", str.tostring(f_sl_perc))
s_short_entry_text := str.replace_all(s_short_entry_text, "#margin#", str.tostring(f_orig_size))
s_short_entry_text := str.replace_all(s_short_entry_text, "#margintype#", str.tostring(s_margin_mode =="Static Amount"? 2: 1))


if bar_index == 0
    if b_long_trade
        box_prof := box.new(na, f_tp, na, f_entry, border_color = color.gray, border_width = 1, bgcolor = color.new(color.green, 80))
        box_loss := box.new(na, f_entry, na, f_sl, border_color = color.gray, border_width = 1, bgcolor = color.new(color.red, 80))
    else
        box_prof := box.new(na, f_entry, na, f_tp, border_color = color.gray, border_width = 1, bgcolor = color.new(color.green, 80))
        box_loss := box.new(na, f_sl, na, f_entry, border_color = color.gray, border_width = 1, bgcolor = color.new(color.red, 80))


b_cross_up_entry := if (ta.crossover(high, f_entry) and time_to_trade) or (ta.crossover(close, f_entry) and time_to_trade)
    true
else
    false
b_cross_dn_entry := if (ta.crossunder(low, f_entry) and time_to_trade) or ta.crossunder(close, f_entry) and time_to_trade
    true
else
    false

b_cross_sl := if low <= f_sl and high >= f_sl and time_to_trade
    true
else
    false
b_cross_tp := if high >= f_tp and low <= f_tp and time_to_trade
    true
else
    false


if time_to_trade and not b_trade_finished and b_trade_entered
    if not b_trade_finished
        if b_cross_sl
            b_stopped_out := true
            trade_fin_time := bar_index
        if b_cross_tp
            b_trade_finished := true
            trade_fin_time := bar_index



// Alerts and drawings
if b_cross_tp and b_trade_finished and not b_trade_finished[1]
    box.set_right(box_prof, bar_index)
    box.set_right(box_loss, bar_index)

if b_cross_sl and b_trade_finished and not b_trade_finished[1]
    box.set_right(box_prof, bar_index)
    box.set_right(box_loss, bar_index)

if b_long_trade and b_cross_up_entry and time_to_trade and not b_trade_finished
    if s_alert_freq == "Once per Bar"
        alert(s_long_entry_text, freq=alert.freq_once_per_bar)
    if s_alert_freq == "Once per Bar Close"
        alert(s_long_entry_text, freq=alert.freq_once_per_bar_close)
    if s_alert_freq == "All"
        alert(s_long_entry_text, freq=alert.freq_all)
    b_trade_entered := true
    trade_beg_time := bar_index
if not b_long_trade and b_cross_dn_entry and time_to_trade
    if s_alert_freq == "Once per Bar"
        alert(s_short_entry_text, freq=alert.freq_once_per_bar)
    if s_alert_freq == "Once per Bar Close"
        alert(s_short_entry_text, freq=alert.freq_once_per_bar_close)
    if s_alert_freq == "All"
        alert(s_short_entry_text, freq=alert.freq_all)
    b_trade_entered := true
    trade_beg_time := bar_index



//do stuff
if b_stopped_out and not b_stopped_out[1]
    box.set_right(box_prof, bar_index)
    box.set_right(box_loss, bar_index)
    if b_long_trade
        box.new(box.get_left(box_prof), box.get_top(box_prof), box.get_right(box_prof), box.get_bottom(box_prof), border_color = color.gray, border_width = 1, bgcolor = color.new(color.green, 80))
        box.new(box.get_left(box_loss), box.get_top(box_loss), box.get_right(box_loss), box.get_bottom(box_loss), border_color = color.gray, border_width = 1, bgcolor = color.new(color.red, 80))
    else
        box.new(box.get_left(box_prof), box.get_top(box_prof), box.get_right(box_prof), box.get_bottom(box_prof), border_color = color.gray, border_width = 1, bgcolor = color.new(color.green, 80))
        box.new(box.get_left(box_loss), box.get_top(box_loss), box.get_right(box_loss), box.get_bottom(box_loss), border_color = color.gray, border_width = 1, bgcolor = color.new(color.red, 80))
    if b_re_entry
        b_trade_entered := false
        b_stopped_out := false
        box.set_left(box_prof, bar_index)
        box.set_left(box_loss, bar_index)
        i_entry_num += 1
    else
        b_stopped_out := true
        b_trade_entered := true
        b_trade_finished := true
        box.delete(box_prof)
        box.delete(box_loss)
    
        


if time_to_trade and not b_trade_finished
    if not b_trade_entered
        box.set_left(box_prof, bar_index)
        box.set_left(box_loss, bar_index)
    box.set_right(box_prof, bar_index + i_line_bars)
    box.set_right(box_loss, bar_index + i_line_bars)
    
if not time_to_trade
    if trade_time_index - bar_index > i_line_bars
        box.set_left(box_prof, bar_index + i_line_bars)
        box.set_left(box_loss, bar_index + i_line_bars)
        box.set_right(box_prof, bar_index + 2 * i_line_bars)
        box.set_right(box_loss, bar_index + 2 * i_line_bars)
    else
        box.set_left(box_prof, trade_time_index)
        box.set_left(box_loss, trade_time_index)
        box.set_right(box_prof, trade_time_index + i_line_bars)
        box.set_right(box_loss, trade_time_index + i_line_bars)

info_table_color = color.gray
var table debug_table = table.new(position.top_right, 1, 20, bgcolor = info_table_color, frame_width = 2, frame_color = color.black)
deb_txt_size = size.small
if barstate.islast and b_enable_dashboard
    s_trade_type = b_long_trade? "Long" : "Short"
    table.cell(debug_table, 0, 0, text=" Trade Direction? " + str.tostring(s_trade_type), text_color = color.white, text_size = deb_txt_size)
    table.cell(debug_table, 0, 1, text=" Current Take Profit " + str.tostring(f_tp), text_color = color.white, text_size = deb_txt_size)    
    table.cell(debug_table, 0, 2, text=" Current Entry " + str.tostring(f_entry), text_color = color.white, text_size = deb_txt_size)
    table.cell(debug_table, 0, 3, text=" Current Stoploss " + str.tostring(f_sl), text_color = color.white, text_size = deb_txt_size)
    table.cell(debug_table, 0, 4, text=" Current Stoploss " + str.tostring(math.round(f_sl_perc, 3)) + "% ", text_color = color.white, text_size = deb_txt_size)
    table.cell(debug_table, 0, 5, text=" Current Entry Attmept " + str.tostring(i_entry_num + 1), text_color = color.white, text_size = deb_txt_size)
    table.cell(debug_table, 0, 6, text=" Is Trade Entered? " + str.tostring(b_trade_entered), text_color = color.white, text_size = deb_txt_size)
    table.cell(debug_table, 0, 7, text=" Is it time to trade? " + str.tostring(time_to_trade), text_color = color.white, text_size = deb_txt_size)
    table.cell(debug_table, 0, 8, text=" Is trade finished? " + str.tostring(b_trade_finished), text_color = color.white, text_size = deb_txt_size)




