ProfitView Strategy Template
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

//@version=5
//@strategy_alert_message {{strategy.order.alert_message}}


// # ========================================================================= #
// #                   |  SAMPLE INDICATOR  |
// # ========================================================================= #

// Sample script to plug to the strategy template

////@version=5
//indicator(title='Moving Average Cross', shorttitle='Moving Average Cross', overlay=true, precision=6, max_labels_count=500, max_lines_count=500)

// type_ma1 = input.string(title='MA1 type', defval='SMA', options=['RMA', 'SMA', 'EMA'])
// length_ma1 = input(10, title='[ALL but VWAP] MA1 length')

// type_ma2 = input.string(title='MA2 type', defval='SMA', options=['RMA', 'SMA', 'EMA'])
// length_ma2 = input(100, title='[ALL but VWAP] MA2 length')

// // MA
// f_ma(smoothing, src, length) =>
//     rma_1 = ta.rma(src, length)
//     sma_1 = ta.sma(src, length)
//     ema_1 = ta.ema(src, length)
//     iff_1 = smoothing == 'EMA' ? ema_1 : src
//     iff_2 = smoothing == 'SMA' ? sma_1 : iff_1
//     smoothing == 'RMA' ? rma_1 : iff_2

// MA1 = f_ma(type_ma1, close, length_ma1)
// MA2 = f_ma(type_ma2, close, length_ma2)

// // buy and sell conditions
// buy = ta.crossover(MA1, MA2)
// sell = ta.crossunder(MA1, MA2)

// plot(MA1, color=color.new(color.green, 0), title='Plot MA1', linewidth=3)
// plot(MA2, color=color.new(color.red, 0), title='Plot MA2', linewidth=3)

// plotshape(buy, title='LONG SIGNAL', style=shape.circle, location=location.belowbar, color=color.new(color.green, 0), size=size.normal)
// plotshape(sell, title='SHORT SIGNAL', style=shape.circle, location=location.abovebar, color=color.new(color.red, 0), size=size.normal)

// /////////////////////////// SIGNAL FOR STRATEGY /////////////////////////

// Signal = buy ? 1 : sell ? -1 : 0
// plot(Signal, title='🔌Connector🔌', display = display.data_window)

// # ========================================================================= #
// #                   |   SAMPLE INDICATOR  |
// # ========================================================================= #


SCRIPT_NAME = "ProfitView Strategy Template"

strategy(SCRIPT_NAME, 
 overlay= true, 
 process_orders_on_close = true, 
 calc_on_every_tick = true, 
 pyramiding = 1, 
 initial_capital = 100000, 
 default_qty_type = strategy.percent_of_equity, 
 default_qty_value = 1,
 commission_type = strategy.commission.percent,
 commission_value = 0.075,
 slippage = 1
 )

_ext_connector = input.source(close, title = "External Connector", group = "Connected Indicator Source", tooltip = "Select the indicator you want to connect to this strategy.\nThis indicator will be used to trigger the strategy orders.")
ext_connector = nz(_ext_connector)

// # ========================================================================= #
// #                   | BOT |
// # ========================================================================= #

//pineconnector_licence_ID = input.string(title = "Licence ID", defval = "123456789", group = "ProfitView", tooltip = "Insert your ProfitView Licence ID here\nYou can find it in your ProfitView account webpage")

//use_multiple_account = input.bool(false, title = "Use Multiple Account?", group = "ProfitView General Settings", tooltip = "Use this option if you want to use multiple accounts with the same strategy.\nYou can find the account ID in your ProfitView account page from the Chrome extension")

account_name  = input.string(title = "Account Name", defval = "*", group = "ProfitView General Settings", tooltip = "Insert your account name here\nYou can find it in your ProfitView account page from the Chrome extension")
exchange_name = input.string("bitmex-testnet", title = "Exchange Alias", group = "ProfitView General Settings", tooltip = "Insert the ProfitView exchange ID here\nExample: 'bitmex' or 'bitmex-testnet' or 'binance-ft'")
symbol_name   = input.string("xbtusd", title = "Symbol Alias", group = "ProfitView General Settings", tooltip = "Insert the ProfitView symbol ID here\nExamples: 'BTCUSDT' or 'ETHBTC' or 'XBTUSD'")
trading_mode  = input.string("Spot", title = "Trading Mode", options = ["Spot", "Margin"], group = "ProfitView General Settings", tooltip = "Select the trading mode you want to use for this strategy")

delay_between_orders = input.int(2, minval = 0, title = "Delay Between Commands (seconds)", group = "ProfitView General Settings", tooltip = "Set the delay between orders in seconds.\nThis is useful to prevent the BOT from opening too many orders in a short period of time.")
nb_orders_per_direction = input.int(1, minval = 1, title = "Number of Orders per Direction", group = "ProfitView General Settings", tooltip = "Set the number of orders per direction.\nThis is useful to prevent the BOT from opening too many orders in a short period of time.")

use_drawdown_BOT_halt = input.bool(false, title = "Use Drawdown BOT Halt?", group = "BOT Risk Management", tooltip = "Halt the BOT if the max drawdown value is reached")
max_drawdown_mode  = input.string("%", title = "Mode", options = ["%", "USD"], group = "BOT Risk Management", inline = "max drawdown")
max_drawdown_value = input.float(20, minval = 0, title = "Max Drawdown", group = "BOT Risk Management", inline = "max drawdown")

use_max_consecutive_days_BOT_halt = input.bool(false, title = "Use Max Consecutive Days BOT Halt?", group = "BOT Risk Management", inline = "max consecutive days", tooltip = "Halt the BOT if the max consecutive losing days value is reached")
nb_max_consecutive_days = input.int(3, minval = 0, title = "Max Consecutive Days", group = "BOT Risk Management", inline = "max consecutive days")

use_max_losing_streak = input.bool(false, title = "Use Max Losing Streak?", group = "BOT Risk Management", inline = "max losing streak", tooltip = "To prevent the BOT from taking too many losses in a row")
maxLosingStreak = input.int(15, title="Max Losing Streak Length", minval=1, group = "BOT Risk Management", inline = "max losing streak")

use_margin_call = input.bool(false, title = "Use Margin Call?", group = "BOT Risk Management", inline = "margin call", tooltip = "Margin longs/shorts need to be different than 0% from the Properties tab.\nExit when we're X% away from a margin call, to prevent it")
margin_call_value = input.float(10, minval = 0, title = "Margin Call (%)", group = "BOT Risk Management", inline = "margin call")

use_close_BOT_total_loss = input.bool(false, title = "Use Close BOT Total Loss?", group = "BOT Risk Management", inline = "close BOT total loss", tooltip = "Close all the trades + halt BOT if the total loss is reached")
total_loss_value = input.float(-5000, maxval = 0, title = "Total Loss ($)", group = "BOT Risk Management", inline = "close BOT total loss")

use_intraday_losses_BOT_halt = input.bool(false, title = "Use Intraday Losses BOT Halt?", group = "Intraday BOT Risk Management")
intraday_loss_value = input.string("%", title = "Mode", options = ["%", "USD"], group = "Intraday BOT Risk Management", inline = "intraday losses")
nb_intraday_losses = input.int(3, minval = 0, title = "Max Intraday Losses (%)", group = "Intraday BOT Risk Management", inline = "intraday losses")

use_limit_intraday_trades = input.bool(false, title = "Use Limit Intraday Trades?", group = "Intraday BOT Risk Management", inline = "max intraday trades")
nb_max_intraday_trades = input.int(5, minval = 0, title = "Max Intraday Trades", group = "Intraday BOT Risk Management", inline = "max intraday trades")

use_restart_intraday_BOT = input.bool(false, title = "Use Restart Intraday EA?", group = "Intraday BOT Risk Management", inline = "restart intraday EA", tooltip = "Restart the BOT at the first bar of next day if it has been stoppped with an intraday risk management safeguard")

//use_spread_filter = input.bool(false, title = "Use Spread Filter?", group = "BOT Spread Filter", inline = "spread filter", tooltip = "Enter the position only if the spread is equal or less than the specified value in pips.")
//spread_value      = input.float(3.5, minval = 0, title = "Spread Value (pips)", group = "BOT Spread Filter", inline = "spread filter")

//use_acc_filter    = input.bool(false, title = "Use Account Filter?", group = "BOT Account Filter", inline = "account filter", tooltip = "Enter the position only if the account requirement is met.\nBOT Options: Account Balance, Account Equity, Margin Percentage and Free Margin")
//accfilter_value   = input.float(1000, minval = 0, title = "Account Balance/Equity (USD)", group = "BOT Account Filter", inline = "account filter")

// # ========================================================================= #
// #                   | Retries |
// # ========================================================================= #

use_retries = input.bool(false, title = "Use Retries?", group = "Retries", tooltip = "Retry to open the order if it fails")
nb_retries  = input.int(3, minval = 0, title = "Number of Retries", group = "Retries", tooltip = "Set the number of retries")

// # ========================================================================= #
// #                   | Order Types |
// # ========================================================================= #

var string ORDER_TYPE_TOOLTIP = 'Limit: Place order on the books waiting to be filled for price p\n
 Market: Fill order immediately for whatever prices are available (p is ignored – slippage!)\n
 FOK: Fill Or Kill orders will be cancelled if they cannot be filled immediately completely\n
 IOC: Immediate Or Cancel orders can be partially filled – any remaining portion is cancelled\n
 Post: If any part of the order would be filled immediately (for price p) the whole order will be cancelled\n
 Day (BitMEX / OANDA): "Good For Day", will be cancelled at 5pm EDT (New York)\n
 Settle (Kraken): Settle position(s) at the original order price Click here for more info from Kraken!\n
 Open / Close: Can be used together with c=order for specific order types – open targets limit/opening orders, close targets stops/closing orders'

order_type_mode = input.string("Market", title = "Order Type", options = ["Market", "Limit", "Stop", "FOK", "IOC", "Post", "Day", "Settle", "Open/Close"], group = "Order Types", tooltip = ORDER_TYPE_TOOLTIP)
order_type_price = input.float(10, title = "Price", group = "Order Types", 
 tooltip = "With 'Limit', below the current market price for a buy - above the current market price for a sell\nWith 'Stop', above the current market price for a buy - below the current market price for a sell\n")

// # ========================================================================= #
// #                   | Position Size |
// # ========================================================================= #

pos_type       = input.string("Contracts", title = "Position Type", options = ["Contracts", "Percent", "Currency"], group = "Position Size", tooltip = "Select the position type you want to use for this strategy")
pos_size       = input.float(3, minval = 0, maxval = 100, title = "Position Size", group = "Position Size", tooltip = "Required to specify the position size here for ProfitView to work properly")

// # ========================================================================= #
// #                   | Leverage |
// # ========================================================================= #

margin_type    = input.string("Isolated", title = "Margin Type", options = ["Isolated", "Crossed"], group = "Leverage", tooltip = "Select the margin type you want to use for this strategy")
leverage_value = input.float(1, minval = 0, title = "Value", group = "Leverage", tooltip = "Required to specify the leverage here for ProfitView to work properly")
use_hedge_mode = input.bool(false, title = "Use Hedge Mode?", group = "Leverage", tooltip = "Use this option if you want to use the Hedge mode for this strategy")

// # ========================================================================= #
// #                   | Sessions |
// # ========================================================================= #

use_session = input.bool(false, title='Use Sessions ?', group='Session', tooltip = "Limit the trades between a start and end time")
Session = input.session(title='Trading Session', defval='0000-2345', group='Session')
sess_timezone = input.string('UTC-5', title='Session Timezone', group='Session')

// # ========================================================================= #
// #                   | Dates |
// # ========================================================================= #

// ————— Syntax coming from https://www.tradingview.com/blog/en/new-parameter-for-date-input-added-to-pine-21812/

use_date = input.bool(false, title='Use Date Filter ?', group='Date', tooltip = "Limit the trades between a start and end date")
i_startTime = input.time(defval=timestamp('01 Jan 2019 13:30 +0000'), title='Start Time', group='Date')
i_endTime = input.time(defval=timestamp('30 Dec 2021 23:30 +0000'), title='End Time', group='Date')

TradeDateIsAllowed() =>
    use_date ? time >= i_startTime and time <= i_endTime : true

// # ========================================================================= #
// #                   | Direction |
// # ========================================================================= #

strat_direction = input.string(strategy.direction.all, title = "Direction", options = [strategy.direction.all, strategy.direction.long, strategy.direction.short], group = "Trades Direction", tooltip = "To specify in which market direction the strategy is allowed to open positions.")

//use_close_opposite = input.bool(false, title = "Close on Opposite Signal?", group = "Close on Opposite", tooltip = "Close the position if 1 or more MACDs become bearish (for longs) or bullish (for shorts)")

// # ========================================================================= #
// #                   | General SL/TP |
// # ========================================================================= #

sl_tp_mode = input.string("pips", title = "Mode", options = ["pips", "%"], group = "General SL/TP", tooltip = "Select the mode you want to use for the SL/TP values\nSelect the same mode in the ProfitView BOT on Metatrader")

// # ========================================================================= #
// #                   | Stop Loss |
// # ========================================================================= #

use_sl = input.bool(true, title = "Use Stop Loss?", group = "Stop Loss")
sl_value = input.float(40, minval = 0, title = "Value", group = "Stop Loss", inline = "stoploss")// * 0.01

// # ========================================================================= #
// #                   | Trailing Stop Loss |
// # ========================================================================= #

use_tsl         = input.bool(false, title = "Use Trailing Stop Loss?", group = "Trailing Stop Loss")
tsl_input_value = input.float(10, minval = 0, title = "Value", group = "Trailing Stop Loss")

// # ========================================================================= #
// #                   | Take Profit |
// # ========================================================================= #

use_tp1 = input.bool(true, title = "Use Take Profit 1?", group = "Take Profit 1")
tp1_value = input.float(30, minval = 0, title = "Value", group = "Take Profit 1")
tp1_qty   = 100//input.float(50, minval = 0, title = "Quantity (%)", group = "Take Profit 1")

//use_tp2   = input.bool(true, title = "Use Take Profit 2?", group = "Take Profit 2")
//tp2_value = input.float(50, minval = 0, title = "Value", group = "Take Profit 2")

// # ========================================================================= #
// #                   | Stop Loss to Breakeven |
// # ========================================================================= #

use_sl_be         = input.bool(false, title = "Use Stop Loss to Breakeven Mode?", group = "Break Even")
sl_be_value       = input.float(30, step = 0.1, minval = 0, title = "Value (pips)", group = "Break Even", inline = "breakeven")
sl_be_offset      = input.int(1, step = 1, minval = 0, title = "Offset (pips)", group = "Break Even", tooltip = "Set the SL at BE price +/- offset value")

// # ========================================================================= #
// #                   | Telegram/Discord |
// # ========================================================================= #

NOTIFY_TOOLTIP = "0, 1: Disable/suppress or enable/force built-in notifications for this command\n2: Force built-in notifications including balance info for this command\n3: Force built-in notifications including balance and account info for this command\n4: Force built-in notifications including balance, account and leverage info for this command\n"

disable_custom_notifications = input.bool(false, title = "Disable Custom Notifications?", group = "Custom Notifications", tooltip = "Disable the custom notifications for this strategy")

use_telegram = input.bool(false, title = "Use Telegram?", group = "Telegram", tooltip = "Send the alerts to Telegram", inline = "telegram")
//notify_telegram_int = input.int(0, minval = 0, maxval=4, title= "", group = "Telegram", inline = "telegram", tooltip = NOTIFY_TOOLTIP)
telegram_txt = input.text_area("Exchange: {exchange}, Price: {price}", title = "Telegram Notifications Text", group = "Telegram", tooltip = "Documentation: https://wiki.profitview.app/syntax/notify")

use_discord = input.bool(false, title = "Use Discord?", group = "Discord", tooltip = "Send the alerts to Discord", inline = "discord")
notify_discord_int = input.int(0, minval = 0, maxval=4, title= "", group = "Discord", inline = "discord", tooltip = NOTIFY_TOOLTIP)
discord_txt = input.text_area("Exchange: {exchange}, Price: {price}", title = "Discord Notifications Text", group = "Discord", tooltip = "Documentation: https://wiki.profitview.app/syntax/notify")

use_email      = input.bool(false, title = "Use Email?", group = "Email", tooltip = "Send the alerts to Email")
//notify_email_int = input.int(1, minval = 0, maxval=4, title= "", group = "Email", tooltip = NOTIFY_TOOLTIP)
email_subject  = input.string("ProfitView Alert", title = "Email Subject", group = "Email", tooltip = "Set the email subject")
//email_txt      = input.text_area("Exchange: {exchange}, Price: {price}", title = "Email Notifications Text", group = "Email", tooltip = "Documentation: https://wiki.profitview.app/syntax/notify")

use_ifttt   = input.bool(false, title = "Use IFTTT?", group = "IFTTT", tooltip = "Send the alerts to IFTTT", inline = "ifttt")
//notify_ifttt_int = input.int(0, minval = 0, maxval=4, title= "", group = "IFTTT", inline = "ifttt", tooltip = NOTIFY_TOOLTIP)
ifttt_txt   = input.text_area("Exchange: {exchange}, Price: {price}", title = "IFTTT Notifications Text", group = "IFTTT", tooltip = "Documentation: https://wiki.profitview.app/syntax/notify")

use_twilio  = input.bool(false, title = "Use Twilio?", group = "Twilio", tooltip = "Send the alerts to Twilio", inline = "twilio")
//notify_twilio_int = input.int(0, minval = 0, maxval=4, title= "", group = "Twilio", inline = "twilio", tooltip = NOTIFY_TOOLTIP)
twilio_txt  = input.text_area("Exchange: {exchange}, Price: {price}", title = "Twilio Notifications Text", group = "Twilio", tooltip = "Documentation: https://wiki.profitview.app/syntax/notify")

use_log     = input.bool(false, title = "Use Log?", group = "Log", tooltip = "Send the alerts to the ProfitView Logger")
log_txt     = input.text_area("Exchange: {exchange}, Price: {price}", title = "Log Notifications Text", group = "Log", tooltip = "Documentation: https://wiki.profitview.app/syntax/notify")

// # ========================================================================= #
// #                   |Bars Colouring |
// # ========================================================================= #

clrBars = input.bool(true, title='Colour Candles to Trade Order state', group='Coloring')


// # ========================================================================= #
// #                   | Pine Utilities |
// # ========================================================================= #

// Source: https://www.tradingview.com/pine-script-reference/v5/#var_strategy.margin_liquidation_price
changePercent(v1, v2) => 
    float result = (v1 - v2) * 100 / math.abs(v2)

// Source: https://www.tradingview.com/pine-script-reference/v5/#fun_strategy.closedtrades.profit
// Calculate sum gross profit from all closed trades by adding the difference between gross profit and commission.
SumGrossProfitClosedTrades() =>
    sumGrossProfit = 0.0
    for tradeNo = 0 to strategy.closedtrades - 1
        sumGrossProfit += strategy.closedtrades.profit(tradeNo) - strategy.closedtrades.commission(tradeNo)
    result = nz(sumGrossProfit)

get_pip_size() =>

    float _pipsize = 1.

    if syminfo.type == "forex" 
        _pipsize := (syminfo.mintick * (str.contains(syminfo.ticker, "JPY") ? 100 : 10))
    else if str.contains(syminfo.ticker, "XAU") or str.contains(syminfo.ticker, "XAG")
        _pipsize := 0.1

    _pipsize

// # ========================================================================= #
// #                   | Calculations |
// # ========================================================================= #

bull = ext_connector == 1  and barstate.isconfirmed
bear = ext_connector == -1 and barstate.isconfirmed

signal_candle = bull or bear

signal_bull = bull and strategy.position_size[1] <= 0
signal_bear = bear and strategy.position_size[1] >= 0

entryLongPrice  = ta.valuewhen(signal_bull, close, 0)
entryShortPrice = ta.valuewhen(signal_bear, close, 0)

plot(strategy.position_size > 0 ? entryLongPrice : na, title = "Long Entry Price", color = color.green, linewidth = 2, style = plot.style_circles)
plot(strategy.position_size < 0 ? entryShortPrice : na, title = "Short Entry Price", color = color.red, linewidth = 2, style = plot.style_circles)

var label entry_label = na

if barstate.islast

    if strategy.position_size > 0
        entry_label := label.new(x = bar_index + 5, y = entryLongPrice, text = "Long Entry: " + str.tostring(entryLongPrice, format.mintick), style = label.style_label_left, color = color.green, size = size.normal)
    else if strategy.position_size < 0
        entry_label := label.new(x = bar_index + 5, y = entryShortPrice, text = "Short Entry: " + str.tostring(entryShortPrice, format.mintick), style = label.style_label_left, color = color.red, size = size.normal)

// # ========================================================================= #
// #                   |   Stop Loss |
// # ========================================================================= #

var float final_SL_Long = 0.
var float final_SL_Short = 0.

var float final_SL_Long_Pineconnector = 0.
var float final_SL_Short_Pineconnector = 0.

if use_sl

    if signal_bull
        final_SL_Long  := (sl_tp_mode == "pips") ? entryLongPrice  - (sl_value * get_pip_size()) : entryLongPrice * (1 - (sl_value * 0.01))
    else if signal_bear
        final_SL_Short := (sl_tp_mode == "pips") ? entryShortPrice + (sl_value * get_pip_size()) : entryShortPrice * (1 + (sl_value * 0.01))

// # ========================================================================= #
// #                   |   Trailing Stop Loss |
// # ========================================================================= #

var MaxReached = 0.0  

if signal_candle[1]

    MaxReached := strategy.position_size > 0 ? high : low

MaxReached := strategy.position_size > 0
 ? math.max(nz(MaxReached, high), high)
 : strategy.position_size < 0 ? math.min(nz(MaxReached, low), low) : na

if use_tsl and use_sl

    if strategy.position_size > 0

        stopValue = MaxReached - (tsl_input_value * get_pip_size())
        final_SL_Long := math.max(stopValue, final_SL_Long[1])

    else if strategy.position_size < 0

        stopValue = MaxReached + (tsl_input_value * get_pip_size())
        final_SL_Short := math.min(stopValue, final_SL_Short[1])

// # ========================================================================= #
// #                   |   Take Profit 1 |
// # ========================================================================= #

var float final_TP1_Long  = 0.
var float final_TP1_Short = 0.

if use_tp1

    if signal_bull
        final_TP1_Long  := (sl_tp_mode == "pips") ? entryLongPrice  + (tp1_value * get_pip_size()) : entryLongPrice * (1 + (tp1_value * 0.01))
    else if signal_bear
        final_TP1_Short := (sl_tp_mode == "pips") ? entryShortPrice - (tp1_value * get_pip_size()) : entryShortPrice * (1 - (tp1_value * 0.01))

plot(use_tp1 and strategy.position_size > 0 ? final_TP1_Long : na, title = "TP1 Long", color = color.aqua, linewidth=2, style=plot.style_linebr)
plot(use_tp1 and strategy.position_size < 0 ? final_TP1_Short : na, title = "TP1 Short", color = color.blue, linewidth=2, style=plot.style_linebr)

var label tp1_label = na

if barstate.islast and use_tp1

    if strategy.position_size > 0
        tp1_label := label.new(x = bar_index + 5, y = final_TP1_Long, text = "TP1: " + str.tostring(final_TP1_Long, format.mintick), style = label.style_label_left, color = color.aqua, size = size.normal)
    else if strategy.position_size < 0
        tp1_label := label.new(x = bar_index + 5, y = final_TP1_Short, text = "TP1: " + str.tostring(final_TP1_Short, format.mintick), style = label.style_label_left, color = color.blue, size = size.normal)

// # ========================================================================= #
// #                   |   Take Profit 2 |
// # ========================================================================= #

//var float final_TP2_Long  = 0.
//var float final_TP2_Short = 0.

//if use_tp2 and tp1_qty != 100

//    if signal_bull
//        final_TP2_Long  := (sl_tp_mode == "pips") ? entryLongPrice  + (tp2_value * get_pip_size()) : entryLongPrice * (1 + (tp2_value * 0.01))
//    else if signal_bear
//        final_TP2_Short := (sl_tp_mode == "pips") ? entryShortPrice - (tp2_value * get_pip_size()) : entryShortPrice * (1 - (tp2_value * 0.01))

//plot(use_tp2 and strategy.position_size > 0 and tp1_qty != 100 ? final_TP2_Long : na, title = "TP2 Long", color = color.orange, linewidth=2, style=plot.style_linebr)
//plot(use_tp2 and strategy.position_size < 0 and tp1_qty != 100 ? final_TP2_Short : na, title = "TP2 Short", color = color.white, linewidth=2, style=plot.style_linebr)

//var label tp2_label = na

//if barstate.islast and use_tp2

//   if strategy.position_size > 0 and tp1_qty != 100
//        tp2_label := label.new(x = bar_index + 5, y = final_TP2_Long, text = "TP2: " + str.tostring(final_TP2_Long, format.mintick), style = label.style_label_left, color = color.orange, size = size.normal)
//    else if strategy.position_size < 0 and tp1_qty != 100
//        tp2_label := label.new(x = bar_index + 5, y = final_TP2_Short, text = "TP2: " + str.tostring(final_TP2_Short, format.mintick), style = label.style_label_left, color = color.white, size = size.normal)

// # ========================================================================= #
// #                   |   Stop Loss to Breakeven |
// # ========================================================================= #

var bool SL_BE_REACHED = false

// Calculate open profit or loss for the open positions.
tradeOpenPL() =>
    sumProfit = 0.0
    for tradeNo = 0 to strategy.opentrades - 1
        sumProfit += strategy.opentrades.profit(tradeNo)
    result = sumProfit

current_profit = tradeOpenPL()// * get_pip_size()

current_long_profit = (close - entryLongPrice) / (syminfo.mintick * 10)
current_short_profit = (entryShortPrice - close) / (syminfo.mintick * 10)

plot(current_short_profit, title = "Current Short Profit", display = display.data_window)
plot(current_long_profit, title = "Current Long Profit", display = display.data_window)

if use_sl_be

    if strategy.position_size > 0

        if not SL_BE_REACHED

            if current_long_profit >= sl_be_value 
                final_SL_Long := entryLongPrice + (sl_be_offset * get_pip_size())
                SL_BE_REACHED := true

    else if strategy.position_size < 0

        if not SL_BE_REACHED

            if current_short_profit >= sl_be_value 
                final_SL_Short := entryShortPrice - (sl_be_offset * get_pip_size())
                SL_BE_REACHED := true

plot(use_sl and strategy.position_size > 0 ? final_SL_Long : na, title = "SL Long", color = color.fuchsia, linewidth=2, style=plot.style_linebr)
plot(use_sl and strategy.position_size < 0 ? final_SL_Short : na, title = "SL Short", color = color.fuchsia, linewidth=2, style=plot.style_linebr)

var label sl_label = na

if barstate.islast and use_sl

    if strategy.position_size > 0
        sl_label := label.new(x = bar_index + 5, y = final_SL_Long, text = "SL: " + str.tostring(final_SL_Long, format.mintick), style = label.style_label_left, color = color.fuchsia, size = size.normal)
    else if strategy.position_size < 0
        sl_label := label.new(x = bar_index + 5, y = final_SL_Short, text = "SL: " + str.tostring(final_SL_Short, format.mintick), style = label.style_label_left, color = color.fuchsia, size = size.normal)

// # ========================================================================= #
// #                   |   Sessions  |
// # ========================================================================= #

// Session calculations
// The BarInSession function returns true when
// the current bar is inside the session parameter
BarInSession(sess) =>
    time(timeframe.period, sess, sess_timezone) != 0

in_session = BarInSession(Session)
okToTradeInSession = use_session ? in_session : true
new_session = in_session and not in_session[1]

bgcolor(color=use_session and BarInSession(Session)[1] ? color.new(color.green, 85) : na, title='Trading Session')

// # ========================================================================= #
// #                   |   ProfitView Alerts Message  |
// # ========================================================================= #

string entry_long_limit_alert_message = ""
string entry_long_TP1_alert_message = ""
string entry_long_TP2_alert_message = ""

var float tp1_qty_perc = tp1_qty / 100

var string first_line_command = ""
var string pyr_line_command = ""
var string bull_command = ""
var string bear_command = ""

ignore_pyr_orders    = "check=pos side=[side] iffound=abort\n"

// Executing this only once at the beginning of the strategy
if barstate.isfirst

    // First Line
    first_line_command := "a=" + account_name + " e=" + exchange_name + " s=" + symbol_name + "\n"

    // Pyramiding
    pyr_line_command := nb_orders_per_direction ? ignore_pyr_orders + "\n" : ""

    // Spot or Margin
    if trading_mode == "Spot"
        bull_command := bull_command  + " side=buy "
        bear_command := bear_command + " side=sell "
    else if trading_mode == "Margin"
        bull_command := bull_command  + " side=long "
        bear_command := bear_command + " side=short "

    // Order Type
    if order_type_mode == "Market"
        bull_command := bull_command  + "type=market "
        bear_command := bear_command + "type=market "
    else if order_type_mode == "Limit"
        bull_command := bull_command + "type=limit p=" + str.tostring(order_type_price) + " "
        bear_command := bear_command + "type=limit p=-" + str.tostring(order_type_price) + " "
    else if order_type_mode == "Stop"
        bull_command := bull_command + "type=limit p=-" + str.tostring(order_type_price) + " "
        bear_command := bear_command + "type=limit p=" + str.tostring(order_type_price) + " "
    else if order_type_mode == "FOK"
        bull_command := bull_command + "type=fok "
        bear_command := bear_command + "type=fok "
    else if order_type_mode == "IOC"
        bull_command := bull_command + "type=ioc "
        bear_command := bear_command + "type=ioc "
    else if order_type_mode == "Post"
        bull_command := bull_command + "type=post "
        bear_command := bear_command + "type=post "
    else if order_type_mode == "Day"
        bull_command := bull_command + "type=day "
        bear_command := bear_command + "type=day "
    else if order_type_mode == "Settle"
        bull_command := bull_command + "type=settle "
        bear_command := bear_command + "type=settle "    
    else if order_type_mode == "Open/Close"
        bull_command := bull_command + "type=open/close "
        bear_command := bear_command + "type=open/close "
    
    // Quantity
    if pos_type == "Contracts"
        bull_command := bull_command + "qty=" + str.tostring(pos_size) + " "
        bear_command := bear_command + "qty=" + str.tostring(pos_size) + " "
    else if pos_type == "Percent"
        bull_command := bull_command + "qty=" + str.tostring(pos_size) + "% "
        bear_command := bear_command + "qty=" + str.tostring(pos_size) + "% "
    else if pos_type == "Currency"
        bull_command := bull_command + "qty=" + str.tostring(pos_size) + " unit=currency "
        bear_command := bear_command + "qty=" + str.tostring(pos_size) + " unit=currency "

    // Leverage
    if margin_type == "Isolated"
        bull_command := bull_command + "leverage=" + str.tostring(leverage_value) + " mt=isolated " 
        bear_command := bear_command + "leverage=" + str.tostring(leverage_value) + " mt=isolated "
    else if margin_type == "Crossed"
        bull_command := bull_command + "leverage=" + str.tostring(leverage_value) + " mt=crossed "
        bear_command := bear_command + "leverage=" + str.tostring(leverage_value) + " mt=crossed "

    // Hedge Mode
    if use_hedge_mode
        bull_command := bull_command + "pm=hedge "
        bear_command := bear_command + "pm=hedge "

    // Retry
    if use_retries
        bull_command := bull_command + "error=abort retries=" + str.tostring(nb_retries) + " "
        bear_command := bear_command + "error=abort retries=" + str.tostring(nb_retries) + " "

    // Notifications

    count_notifications = (use_telegram ? 1 : 0) + (use_discord ? 1 : 0) + (use_email ? 1 : 0) + (use_ifttt ? 1 : 0) + (use_twilio ? 1 : 0) + (use_log ? 1 : 0)

    if count_notifications > 0
        bull_command := bull_command + 'notify=' + (disable_custom_notifications ? "0," : "")
        bear_command := bear_command + 'notify=' + (disable_custom_notifications ? "0," : "")

    if count_notifications > 1
        bull_command := bull_command + ','
        bear_command := bear_command + ','

    if count_notifications > 0

        if use_telegram
            bull_command := bull_command + 'telegram:"' + telegram_txt + '"'
            bear_command := bear_command + 'telegram:"' + telegram_txt + '"'

        if use_email 
            bull_command := bull_command + 'email:' + ':"' + email_subject + '"'
            bear_command := bear_command + 'email:' + ':"' + email_subject + '"'

        if use_discord
            bull_command := bull_command + 'discord:' + str.tostring(notify_discord_int)
            bear_command := bear_command + 'discord:' + str.tostring(notify_discord_int)

        if use_ifttt
            bull_command := bull_command + 'ifttt:"' + ifttt_txt + '"'
            bear_command := bear_command + 'ifttt:"' + ifttt_txt + '"'

        if use_twilio
            bull_command := bull_command + 'twilio:"' + twilio_txt + '"'
            bear_command := bear_command + 'twilio:"' + twilio_txt + '"'

        if use_log
            bull_command := bull_command + 'log:"' + log_txt + '"'
            bear_command := bear_command + 'log:"' + log_txt + '"'

//pos_size = math.abs(strategy.position_size)

delay_command        = "\ndelay=" + str.tostring(delay_between_orders) + "s "

entry_bull_command = first_line_command
 + pyr_line_command
 + bull_command + "sl=-" + ((sl_tp_mode == "pips") ? str.tostring(final_SL_Long, format.mintick) : str.tostring(final_SL_Long) + "%")
 + " tp=" + ((sl_tp_mode == "pips") ? str.tostring(final_TP1_Long, format.mintick) : str.tostring(final_TP1_Long) + "%")

entry_bear_command = first_line_command
 + pyr_line_command
 + bear_command + "sl=" + ((sl_tp_mode == "pips") ? str.tostring(final_SL_Short, format.mintick) : str.tostring(final_SL_Short) + "%")
 + " tp=" + ((sl_tp_mode == "pips") ? str.tostring(final_TP1_Short, format.mintick) : str.tostring(final_TP1_Short) + "%")

close_opposite_side  = first_line_command + "close=[!side] type=market "
close_current_side   = first_line_command + "close=[side] type=market "
close_all_pos_market = first_line_command + "close type=market"

halt_BOT_message     = "exitall"
restart_BOT_message  = "resumeall"

// # ========================================================================= #
// #                   |   BOT global variables |
// # ========================================================================= #

// Flag to remember to stop taking trades if we get too much Rekt :) 
var bool HALT_STRATEGY = false

// Orders part
longs_opened = strategy.position_size > 0
shorts_opened = strategy.position_size < 0
trades_opened = strategy.position_size != 0
longs_opened_in_session = use_session and longs_opened
shorts_opened_in_session = use_session and shorts_opened

// # ========================================================================= #
// #                   |   Risk Management |
// # ========================================================================= #

strategy.risk.max_drawdown(use_drawdown_BOT_halt ? max_drawdown_value : 100, use_drawdown_BOT_halt ? (max_drawdown_mode == "%" ? strategy.percent_of_equity : strategy.cash) : strategy.percent_of_equity, halt_BOT_message)

strategy.risk.max_intraday_loss(use_intraday_losses_BOT_halt and timeframe.isintraday ? nb_intraday_losses : 999999, use_intraday_losses_BOT_halt and timeframe.isintraday ? (intraday_loss_value == "%" ? strategy.percent_of_equity : strategy.cash) : strategy.percent_of_equity, halt_BOT_message)

strategy.risk.max_cons_loss_days(use_max_consecutive_days_BOT_halt ? nb_max_consecutive_days : 999999, halt_BOT_message)

strategy.risk.max_intraday_filled_orders(use_limit_intraday_trades and timeframe.isintraday ? nb_max_intraday_trades : 999999, halt_BOT_message)

// Restart the BOT if it's an intraday chart and it has been paused due to intraday max losses or intraday max filled orders

// test if it's a new day
newDay = dayofmonth != dayofmonth[1]

bgcolor(use_restart_intraday_BOT and newDay and timeframe.isintraday ? color.aqua : na, title = "Restart BOT at the first candle of the day")

if use_restart_intraday_BOT and newDay and timeframe.isintraday
    alert(restart_BOT_message, alert.freq_once_per_bar_close)

// # ========================================================================= #
// #                   |   Streak Management |
// # ========================================================================= #

// Source: https://www.tradingcode.net/tradingview/losing-streak/

// Check if there's a new losing trade that increased the streak
newLoss = strategy.losstrades > strategy.losstrades[1] and
     strategy.wintrades == strategy.wintrades[1] and
     strategy.eventrades == strategy.eventrades[1]

// Determine current losing streak length
streakLen = 0

streakLen := if newLoss
    nz(streakLen[1]) + 1
else
    if strategy.wintrades > strategy.wintrades[1] or
         strategy.eventrades > strategy.eventrades[1]
        0
    else
        nz(streakLen[1])

// Show current losing streak and its limit on chart
//plot(use_max_losing_streak ? streakLen : na, style=plot.style_columns, color=streakLen < maxLosingStreak ? color.maroon : color.red, title = "Max Losing Streak")
bgcolor(use_max_losing_streak and newLoss ? color.new(color.red, 80) : na, title = "New Loss Streak")

// Send the message to ProfitView if the losing streak is too long
if streakLen > maxLosingStreak
    HALT_STRATEGY := true
    alert(halt_BOT_message, alert.freq_once_per_bar_close)

// # ========================================================================= #
// #                   |   Money Management |
// # ========================================================================= #

if use_margin_call
    if math.abs(changePercent(close, strategy.margin_liquidation_price)) <= margin_call_value
        HALT_STRATEGY := true
        strategy.close_all(comment = "Closing all trades to avoid Margin Liq", alert_message = halt_BOT_message)
        //alert(halt_BOT_message, alert.freq_once_per_bar_close)  

if use_close_BOT_total_loss
    strategy_closeprofit = SumGrossProfitClosedTrades()
    // Test if the total profit/loss of all close//open positions is below the total loss input value
    if (strategy_closeprofit + strategy.openprofit) <= total_loss_value
        HALT_STRATEGY := true
        strategy.close_all(comment = "Closing all trades to avoid Total Loss", alert_message = halt_BOT_message)

// # ========================================================================= #
// #                   |   Trades Direction |
// # ========================================================================= #

// Didn't work
// strategy.risk.allow_entry_in(strat_direction)

// # ========================================================================= #
// #                   |   Strategy Calls (Entries/SL/TPs) |
// # ========================================================================= #

open_all  = strat_direction  == strategy.direction.all
open_long  = strat_direction != strategy.direction.short
open_short = strat_direction != strategy.direction.long

OK_TO_TRADE = okToTradeInSession and TradeDateIsAllowed() and not HALT_STRATEGY

// Entries
if bull and strategy.position_size <= 0 and open_long and OK_TO_TRADE
    
    alert(close_opposite_side, alert.freq_once_per_bar_close)
    strategy.entry("Long", strategy.long, limit = order_type_mode == "Limit" ? order_type_price : na, stop = order_type_mode == "Stop" ? order_type_price : na)
    alert(entry_bull_command, alert.freq_once_per_bar_close)
   //alert(entry_long_TP2_alert_message, alert.freq_once_per_bar_close)

else if bear and strategy.position_size >= 0 and open_short and OK_TO_TRADE
    
    alert(close_opposite_side, alert.freq_once_per_bar_close)
    strategy.entry("Short", strategy.short, limit = order_type_mode == "Limit" ? order_type_price : na, stop = order_type_mode == "Stop" ? order_type_price : na)
    alert(entry_bear_command, alert.freq_once_per_bar_close)
    //alert(entry_short_TP2_alert_message, alert.freq_once_per_bar_close)

if strategy.position_size[1] > 0

    // This handles the SL being hit even after a SL/BE and/or TSL has been triggered
    if low <= final_SL_Long and use_sl
        strategy.close("Long", alert_message = close_current_side, comment = "SL Long")
    else
        strategy.exit("Exit TP1 Long", "Long", limit = use_tp1 ? final_TP1_Long : na, comment_profit = "Exit TP Long")
        //strategy.exit("Exit TP2 Long", "Long", limit = use_tp2 ? final_TP2_Long : na, comment_profit = "Exit TP2 Long", alert_message = close_long)

else if strategy.position_size[1] < 0

    // This handles the SL being hit even after a SL/BE and/or TSL has been triggered
    if high >= final_SL_Short and use_sl
        strategy.close("Short", alert_message = close_current_side, comment = "SL Short")
    else
        strategy.exit("Exit TP1 Short", "Short", limit = use_tp1 ? final_TP1_Short : na, comment_profit = "Exit TP Short")
        //strategy.exit("Exit TP2 Short", "Short", limit = use_tp2 ? final_TP2_Short : na, comment_profit = "Exit TP2 Short")


// # ========================================================================= #
// #                   |   Bars Colouring  |
// # ========================================================================= #

bclr = not clrBars ? na : strategy.position_size == 0 ? color.gray : longs_opened ? color.lime : shorts_opened ? color.red : color.gray

barcolor(bclr, title='Trade State Bar Colouring')

// # ========================================================================= #
// #                   |   Logs  |
// # ========================================================================= #

if bull and strategy.position_size <= 0
    log.info(entry_bull_command)

else if bear and strategy.position_size >= 0
    log.info(entry_bear_command)

// # ========================================================================= #
// #                   |   Reset Variables  |
// # ========================================================================= #


if (strategy.position_size > 0 and strategy.position_size[1] <= 0)
 or (strategy.position_size < 0 and strategy.position_size[1] >= 0)

    //is_TP1_REACHED := false
    SL_BE_REACHED := false