3 Indicator Strategy (StochRSI, MFI & EMA) With Safety Orders
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ggekko21

//@version=5
strategy("3 Indicator Strategy (StochRSI, MFI & EMA) With Safety Orders", shorttitle="StochRSI MFI EMA With Safety Orders", overlay=true, max_labels_count=500)

bal_group = "Balance/Risk Settings"

trade_group = "Trade Settings"
long_or_shorts = input.string(defval = "Both", title = "Long/Short", options = ["Longs Only", "Shorts Only", "Both"], group=trade_group)
// Balance & Risk inputs
starting_balance = input.float(defval=10000.0, title="Starting Balance", tooltip="The starting balance for the strategy", group=bal_group)
risk_per_trade = input.float(defval=1.0, minval = 0.01, maxval = 100, title="Risk Per Trade", tooltip="Risk per trade as a percentage of the equity", group=bal_group)

// TP/SL inputs
tpsl_group = "Take Profit / Stop Loss Settings"
tp_sl_type = input.string(defval = "Pips", title="Take Profit/Stop Loss Type", options = ["Pips", "Base Value", "Opposite Signal"], tooltip = "The type of TP/SL used to close the position.", group=tpsl_group)

rr_ratio = input.float(defval = 1.0, minval = 0.1, maxval = 10.0, title="Risk Reward Ratio", group=tpsl_group)
tpsl = input.float(defval = 10.0, minval = 0.1, maxval = 1000000, title="Min Profit/Loss to Close Trade", group=tpsl_group)
tpsl_percentage = input.float(defval = 1.0, minval = 0.01, maxval = 100, title = "Take Profit/Stop Loss Target Percentage", group=tpsl_group)
long_tp = input.float(1000, title="Long Take Profit (mintick)", group=tpsl_group)
long_sl = input.float(2000, title="Long Stop Loss (mintick)", group=tpsl_group)

short_tp = input.float(1000, title="Short Take Profit (mintick)", group=tpsl_group)
short_sl = input.float(2000, title="Short Stop Loss (mintick)", group=tpsl_group)

// Safety Order inputs
safety_group = "Safety Order Settings"

// First safety order price deviation.
safety_order_percent = input.float(defval = 2, title = "Safety Order Percent", group=safety_group, tooltip = "Percentage of price deviation to open the first safety order.")

// What increments do you want the safety order to increase by?
safety_order_mul = input.float(defval = 1, minval = 1, maxval = 10, title = "Safety Order Multiplier", group=safety_group, tooltip = "Multiplies the current position size for each safety order.")

// How many safety order steps?
safety_order_steps = input.int(defval = 5, minval = 1, maxval = 10, title = "Safety Order Max Steps", group=safety_group, tooltip = "Maximum number of safety orders before the trade is a loss.")

src = input.source(defval = close, title = "Source", group = "Strategy Settings")


// ==================================================================================================================== //
// ============================================= StochRSI ============================================================= //
// ==================================================================================================================== //
StochRSI_group = "Stochastic RSI Settings"
StochRSI_kvalue = input.int(1, "K", minval=1, group=StochRSI_group)
StochRSI_dvalue = input.int(1, "D", minval=1, group=StochRSI_group)
lengthRSI = input.int(100, "RSI Length", minval=1, group=StochRSI_group)
lengthStoch = input.int(100, "Stochastic Length", minval=1, group=StochRSI_group)
StochRSI_long = input.float(20, minval = 0, maxval = 50, title = "Stochastic RSI Long Signal", group=StochRSI_group)
StochRSI_short = input.float(80, minval = 50, maxval = 100, title = "Stochastic RSI Short Signal", group=StochRSI_group)

rsi1 = ta.rsi(src, lengthRSI)
kvalue = ta.sma(ta.stoch(rsi1, rsi1, rsi1, lengthStoch), StochRSI_kvalue)
stochrsi_d = ta.sma(kvalue, StochRSI_dvalue)


// ==================================================================================================================== //
// =============================================== MFI ================================================================ //
// ==================================================================================================================== //

MFI_length = input.int(title="MFI Length", defval=30, minval=1, maxval=2000, group="Money Flow Index Settings")
MFI = ta.mfi(src, MFI_length)
MFI_long = input.float(20, minval = 0, maxval = 50, title = "MFI Long Signal", group="Money Flow Index Settings")
MFI_short = input.float(80, minval = 50, maxval = 100, title = "MFI Short Signal", group="Money Flow Index Settings")

// EMA Indicator
EMA_length = input.int(100, title="EMA Length", group = "EMA Settings")
EMA_indicator = ta.ema(src, EMA_length)


// ==================================================================================================================== //
// ============================================ Apply Strategy ======================================================== //
// ==================================================================================================================== //
stochrsi_long = stochrsi_d < StochRSI_long
stochrsi_short = stochrsi_d > StochRSI_short

mfi_long = MFI < MFI_long
mfi_short = MFI > MFI_short

ema_long = close < EMA_indicator
ema_short = close > EMA_indicator

long_condition = stochrsi_long and mfi_long and ema_long
short_condition = stochrsi_short and mfi_short and ema_short

// ==================================================================================================================== //
// ========================================== Apply Safety Orders ===================================================== //
// ==================================================================================================================== //


varip float current_balance = starting_balance
varip float order_size = ((risk_per_trade/100) * current_balance)/open
varip int current_step = 0
varip float price_entry = close


upnl_percentage = (strategy.openprofit/math.abs(strategy.position_avg_price*strategy.position_size))*100

// Make sure strategy doesn't duplicate orders
if long_or_shorts == "Longs Only" or long_or_shorts == "Both"
    if long_condition and strategy.position_size == 0
        //label.new(bar_index, high, text=str.tostring(upnl_percentage, format=format.mintick))
        order_size := ((risk_per_trade/100) * current_balance)/open
        strategy.entry("Enter Long", strategy.long, qty=order_size)
        price_entry := close
if long_or_shorts == "Shorts Only" or long_or_shorts == "Both"
    if short_condition and strategy.position_size == 0
        //label.new(bar_index, high, text=str.tostring(upnl_percentage, format=format.mintick))
    
        order_size := ((risk_per_trade/100) * current_balance)/open
        strategy.entry("Enter Short", strategy.short, qty=order_size)
        price_entry := close
    
    
// Enter Safety Orders Here
if upnl_percentage <= -safety_order_percent
    //if current_step < safety_order_steps
    // Enter safety order here
    order_qty = math.abs(strategy.position_size)// * safety_order_mul
    //order_size := (((risk_per_trade/100) * current_balance)/open)*safety_order_mul*current_step
    order_size := (((risk_per_trade/100) * strategy.equity)/open)*safety_order_mul
    
    if strategy.position_size > 0 and current_step < safety_order_steps
        strategy.order("Enter Long", strategy.long, qty=order_size)
        current_step := current_step + 1
    if strategy.position_size < 0 and current_step < safety_order_steps
        //label.new(bar_index, high, text=str.tostring(strategy.position_size, format=format.mintick))
        strategy.order("Enter Short", strategy.short, qty=order_size)
        current_step := current_step + 1
    else if current_step >= safety_order_steps
        // Maximum number of safety orders reached, closing position.
        if strategy.position_size > 0
            strategy.close(id="Enter Long")
        if strategy.position_size < 0
            strategy.close(id="Enter Short")
        current_step := 0
        

// Update Current Balance
if strategy.wintrades != strategy.wintrades[1]
    current_balance := strategy.equity
    if current_step >= safety_order_steps
        current_step := 0
if strategy.losstrades != strategy.losstrades[1]
    current_balance := strategy.equity
    if current_step >= safety_order_steps
        current_step := 0

// Take Profit/Stop Loss Type
if tp_sl_type == "Base Value"
    if strategy.openprofit > tpsl*rr_ratio or strategy.openprofit <= -tpsl
        if strategy.position_size > 0
            strategy.close(id="Enter Long")
        if strategy.position_size < 0
            strategy.close(id="Enter Short")
        current_step := current_step + 1
        
if tp_sl_type == "Pips"
    strategy.exit(id="Exit Long", from_entry="Enter Long", profit=long_tp, loss=long_sl, qty_percent = 100)
    strategy.exit(id="Exit Short", from_entry="Enter Short", profit=short_tp, loss=short_sl, qty_percent = 100)

if tp_sl_type == "Opposite Signal"
    strategy.close(id="Enter Long", when = short_condition and strategy.position_size > 0)
    strategy.close(id="Enter Short", when =  long_condition and strategy.position_size < 0)
