Racking my brain...

 

Hope all is well. I've been working on this for a few days(total newbie to MT4).  Whenever it runs it closes seconds right after.

Any help is greatly appreciated!

// Define input variables
input int EMA_Period = 8;  // EMA period
input int RSI_Period = 14; // RSI period
input double Lots = 0.1;   // Lot size for orders
input int MinBarsBeforeClose = 5; // Minimum bars to wait before closing the trade
input double MinPipsBeforeClose = 10; // Minimum pip distance before allowing close

// Global variables to store entry prices and entry bar numbers
double BuyEntryPrice = 0;
double SellEntryPrice = 0;
int BuyEntryBar = 0;
int SellEntryBar = 0;

// Function to calculate EMA
double GetEMA(int period, int shift) {
    return iMA(NULL, 0, period, 0, MODE_EMA, PRICE_CLOSE, shift);
}

// Function to calculate RSI
double GetRSI(int period, int shift) {
    return iRSI(NULL, 0, period, PRICE_CLOSE, shift);
}

// Pips to price conversion helper
double PipsToPrice(double pips) {
    double point = MarketInfo(Symbol(), MODE_POINT);
    return pips * point;
}

// Buy condition function
bool BuyCondition() {
    double previousClose = Close[1];
    double ema = GetEMA(EMA_Period, 1);
    double rsi = GetRSI(RSI_Period, 0);
    double rsi2BarsAgo = GetRSI(RSI_Period, 2);

    return (previousClose > ema                    // Previous bar close above EMA
            && High[0] > previousClose             // Current bar crosses above previous bar's close
            && rsi < 50                            // RSI is below 50
            && rsi > rsi2BarsAgo);                 // RSI is greater than 2 bars ago
}

// Sell condition function (opposite of Buy)
bool SellCondition() {
    double previousClose = Close[1];
    double ema = GetEMA(EMA_Period, 1);
    double rsi = GetRSI(RSI_Period, 0);
    double rsi2BarsAgo = GetRSI(RSI_Period, 2);

    return (previousClose < ema                    // Previous bar close below EMA
            && Low[0] < previousClose              // Current bar crosses below previous bar's close
            && rsi > 50                            // RSI is above 50
            && rsi < rsi2BarsAgo);                 // RSI is less than 2 bars ago
}

// Close long position conditions
bool CloseBuyCondition() {
    double currentClose = Close[0];
    double ema = GetEMA(EMA_Period, 0);
    double rsi = GetRSI(RSI_Period, 0);

    // Ensure a minimum pip distance before allowing close
    if (MathAbs(currentClose - BuyEntryPrice) < PipsToPrice(MinPipsBeforeClose)) return false;

    return (currentClose < ema                      // Price closes below the 8-period EMA
            || rsi > 60);                           // RSI greater than 60
}

// Close short position conditions
bool CloseSellCondition() {
    double currentClose = Close[0];
    double ema = GetEMA(EMA_Period, 0);
    double rsi = GetRSI(RSI_Period, 0);

    // Ensure a minimum pip distance before allowing close
    if (MathAbs(currentClose - SellEntryPrice) < PipsToPrice(MinPipsBeforeClose)) return false;

    return (currentClose > ema                      // Price closes above the 8-period EMA
            || rsi < 40);                           // RSI less than 40
}

// Main EA function
void OnTick() {
    // Check if there are no open orders
    if (OrdersTotal() == 0) {
        if (BuyCondition()) {
            // Open a Buy order
            BuyEntryPrice = Close[0];  // Store entry price
            BuyEntryBar = Bars;        // Store entry bar number
            int buyTicket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, 0, 0, "Buy Order", 0, 0, Green);

            // Check if the Buy order was successful
            if (buyTicket < 0) {
                Print("Error opening Buy order: ", GetLastError());
            }
        }
        if (SellCondition()) {
            // Open a Sell order
            SellEntryPrice = Close[0];  // Store entry price
            SellEntryBar = Bars;        // Store entry bar number
            int sellTicket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 3, 0, 0, "Sell Order", 0, 0, Red);

            // Check if the Sell order was successful
            if (sellTicket < 0) {
                Print("Error opening Sell order: ", GetLastError());
            }
        }
    }

    // Check for existing Buy orders to close
    for (int i = 0; i < OrdersTotal(); i++) {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
            if (OrderType() == OP_BUY && (Bars - BuyEntryBar >= MinBarsBeforeClose) && CloseBuyCondition()) {
                if (!OrderClose(OrderTicket(), OrderLots(), Bid, 3, Blue)) {
                    Print("Error closing Buy order: ", GetLastError());
                }
            }

            if (OrderType() == OP_SELL && (Bars - SellEntryBar >= MinBarsBeforeClose) && CloseSellCondition()) {
                if (!OrderClose(OrderTicket(), OrderLots(), Ask, 3, Blue)) {
                    Print("Error closing Sell order: ", GetLastError());
                }
            }
        }
    }
}
 
  1. Why did you post your MT4 question in the MT5 General section instead of the MQL4 section, (bottom of the Root page)?
              General rules and best pratices of the Forum. - General - MQL5 programming forum? (2017)
    Next time, post in the correct place. I have moved this thread.

  2. double PipsToPrice(double pips) {
        double point = MarketInfo(Symbol(), MODE_POINT);
        return pips * point;
    }

    PIP, Point, or Tick size are all different in general.
              Ticks, PIPs or points in the GUI. Make up your mind. - MQL4 programming forum #1 (2014)
              Percentage in point - Wikipedia

    Unless you manually adjust your SL/TP for each separate symbol, using Point means code breaks on 4 digit brokers (if any still exists), exotics (e.g. USDZAR where spread is over 500 points), and metals. Compute what a logical PIP is and use that, not points.
              How to manage JPY pairs with parameters? - MQL4 programming forum (2017)
              Slippage defined in index points - Expert Advisors and Automated Trading - MQL5 programming forum (2018)

  3.     if (OrdersTotal() == 0) {
    

    Magic number only allows an EA to identify its trades from all others. Using OrdersTotal/OrdersHistoryTotal (MT4) or PositionsTotal (MT5), directly and/or no Magic number/symbol filtering on your OrderSelect / Position select loop means your code is incompatible with every EA (including itself on other charts and manual trading.)
              Symbol Doesn't equal Ordersymbol when another currency is added to another seperate chart . - MQL4 programming forum (2013)
              PositionClose is not working - MQL5 programming forum (2020)
              MagicNumber: "Magic" Identifier of the Order - MQL4 Articles (2006)
              Orders, Positions and Deals in MetaTrader 5 - MQL5 Articles (2011)
              Limit one open buy/sell position at a time - General - MQL5 programming forum (2022)

    You need one Magic Number for each symbol/timeframe/strategy.
         Trade current timeframe, one strategy, and filter by symbol requires one MN.
         If trading multiple timeframes, and filter by symbol requires use a range of MN (base plus timeframe).
              Why are MT5 ENUM_TIMEFRAMES strange? - General - MQL5 programming forum - Page 2 #11 (2020)

  4.     // Check for existing Buy orders to close
        for (int i = 0; i < OrdersTotal(); i++) {
            if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
    

    In the presence of multiple orders (one EA multiple charts, multiple EAs, manual trading), while you are waiting for the current operation (closing, deleting, modifying) to complete, any number of other operations on other orders could have concurrently happened and changed the position indexing and order count:

    1. For non-FIFO (non-US brokers), (or the EA only opens one order per symbol), you can simply count down, in an index loop, and you won't miss orders. Get in the habit of always counting down.
                Loops and Closing or Deleting Orders - MQL4 programming forum (2012)

    2. For In First Out (FIFO rules — US brokers), and you (potentially) process multiple orders per symbol, you must find the earliest order (count up), close it, and on a successful operation, reprocess all positions (from zero).
                CloseOrders by FIFO Rules - Strategy Tester - MQL4 programming forum - Page 2 #16 (2019)
                MetaTrader 5 platform beta build 2155: MQL5 scope, global Strategy Tester and built-in Virtual Hosting updates - Best Expert Advisors - General - MQL5 programming forum #1.11 (2019)

    and check OrderSelect in case other positions were deleted.
              What are Function return values ? How do I use them ? - MQL4 programming forum
              Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles

    and if you (potentially) process multiple orders, must call RefreshRates() after server calls if you want to use, on the next order / server call, the Predefined Variables (Bid/Ask.) Or instead, be direction independent and just use OrderClosePrice().