Help Needed for Order Execution

 

(Rewriting this post to make it more clear)

Hello, I am developing my first EA with the strategy of: for buy orders and sell orders are vice versa

1. EMA9 and price are both above EMA225;

2. a pullback happened and price went below EMA9, then price crosses again and close above EMA9 (the Close [1]). Then enter on the open of the next candle (candle [0]) if

3. The Stochastic is on the same direction i.e. rising with K line above D line and K line above 20.


The major problems I'm having right now are:

1. The backtest is not giving me any trades. Are the conditions too strict? Are they contradicting? I have separated the EMA part and the Stochastic part and they both worked on their own, but zero result when combined.

2. In the EMA condition only test, buy orders were also executed when EMA9 was below EMA225.


What I'm thinking is that the candle crossing EMA9 part is causing problems making the condition too strict maybe? Cuz I would still enter a buy trade as long conditon 1 && 3 are valid, even K line crosses D line or the 20 line after a few candles and vice versa. So the close[1] might not be too accurate and too strict here? I am satisfied to place a trade as long it comes back above the EMA9.


Attached is an example of the supposed trade. Blue line is the 225 period EMA and yellow is the 9 period EMA, with Stochastic at the bottom.

double EMA9 = iMA(NULL,0,9,0,MODE_EMA,PRICE_CLOSE,0);
double EMA225 = iMA(NULL,0,225,0,MODE_EMA,PRICE_CLOSE,0);
double K533 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_MAIN,0);
double D533 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0);

double ATR9 = iATR(NULL,0,9,0);


int barsTotal;



//+------------------------------------------------------------------+
int OnInit()
  {
   Alert ("EA 1833 is on");
   
   barsTotal = iBars(NULL,0);
   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Alert("EA 1833 is off");
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   int bars = iBars(NULL,0);
   if (barsTotal != bars && OrdersTotal() == 0)
      {
      barsTotal = bars;
      
            
      //FOR BUY ORDERS
      if (EMA9 > EMA225 && Close[2] < EMA9 && Close[1] > EMA9) 
       {
        if (K533 > D533 && K533 > 20)
         {
         Print("Executing Buy Order");         
         executeBuy();
         }
      //FOR SELL ORDERS      
         else if(EMA9 < EMA225 && Close[2] > EMA9 && Close[1] < EMA9)
           { 
            if(K533 < D533 && K533 < 80)
            {
             Print("Executing Sell Order");         
             executeSell();
            } 
           }
        }
      
      }
}   





int Magic = 3333;

//---------BUY ORDER------------------------
int executeBuy()
{
   double entry = Ask;
   entry = NormalizeDouble(entry,_Digits);
   
   int shift = iLowest(NULL,0,MODE_LOW,5,1);
   double LowInLastFive = iLow(NULL,0,shift);
   
   double SL = (LowInLastFive - ATR9);
   SL = NormalizeDouble(SL,_Digits);
   double SLpips = (entry - SL) / GetPipValue();
   
   double TP = entry + SLpips * 1.3 * GetPipValue();
   TP = NormalizeDouble(TP,_Digits);
   
   double RiskPrc = 0.02;
     
      return OrderSend(NULL,OP_BUY,0.02,entry,0,SL,TP,NULL,Magic,0,clrGreen);
}
   


//-----SELL ORDER-------------------------------
int executeSell()
{
   double entry = Bid;
   entry = NormalizeDouble(entry,_Digits);
   
   int shift = iHighest(NULL,0,MODE_HIGH,5,1);
   double HighInLastFive = iHigh(NULL,0,shift);
   
   double SL = (HighInLastFive + ATR9);
   SL = NormalizeDouble(SL,_Digits);
   double SLpips = (SL - entry)/ GetPipValue();
   
   double TP = entry - SLpips *1.3 * GetPipValue();
   TP = NormalizeDouble(TP,_Digits);
   
   double RiskPrc = 0.02;
      
      return OrderSend(NULL,OP_SELL,0.02,entry,0,SL,TP,NULL,Magic,0,clrRed);
}



double GetPipValue()
{
   if(_Digits >=4)
   {
      return 0.0001;
   }
   else
   {
      return 0.01;
   }
}

Thanks everyone in advance!

Files:
example.PNG  24 kb
 

Your most obvious mistake is here:

Forum on trading, automated trading systems and testing trading strategies

Help Needed for Order Execution

masterpotato, 2024.04.11 05:09

double EMA9 = iMA(NULL,0,9,0,MODE_EMA,PRICE_CLOSE,0);
double EMA225 = iMA(NULL,0,225,0,MODE_EMA,PRICE_CLOSE,0);
double K533 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_MAIN,0);
double D533 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0);

double ATR9 = iATR(NULL,0,9,0);
        

These are global variables that are initialized (take a value) only once when attaching an advisor.

https://www.mql5.com/en/docs/basis/variables/global

Global variables are initialized only once after the program is loaded into the client terminal memory and before the first handling of the Init event.

Check out the documentation at the link in the quote.

 
Vladislav Boyko #:

Your most obvious mistake is here:

These are global variables that are initialized (take a value) only once when attaching an advisor.

Check out the documentation at the link in the quote.

I thought global variables meant I can access it throughout the program? So i guess i will need to put them under OnTick? and inside all the custom functions below? Sorry if it sounds stupid I'm very new to coding this is my first EA.
 

Forum on trading, automated trading systems and testing trading strategies

Help Needed for Order Execution

masterpotato, 2024.04.11 05:09

int OnInit()
  {
   Alert ("EA 1833 is on");
   
   barsTotal = iBars(NULL,0);
   
   return(INIT_SUCCEEDED);
  }

This should not be done in OnInit(), since the data may not be ready yet.

Also, for the current timeframe, you can use the predefined Bars variable instead of iBars() (this would be more correct, although it is unlikely to affect the result):

https://docs.mql4.com/series/ibars

Note

For the current chart, the information about the amount of bars is in the Bars predefined variable.

 
masterpotato #:
I thought global variables meant I can access it throughout the program? So i guess i will need to put them under OnTick? and inside all the custom functions below? Sorry if it sounds stupid I'm very new to coding this is my first EA.

If you want the variables to be global, then you can declare them at the global level, but you need to assign the value in OnTick (or another function that is called from OnTick).

Currently, your indicator values are calculated only once when you attach the advisor to the chart and do not change again. Since you calculate them in the initialization of global variables.

 
Vladislav Boyko #:

This should not be done in OnInit(), since the data may not be ready yet.

Also, for the current timeframe, you can use the predefined Bars variable instead of iBars() (this would be more correct, although it is unlikely to affect the result):

PM'd you
 
Vladislav Boyko #:

If you want the variables to be global, then you can declare them at the global level, but you need to assign the value in OnTick (or another function that is called from OnTick).

Currently, your indicator values are calculated only once when you attach the advisor to the chart and do not change again. Since you calculate them in the initialization of global variables.

omg it worked...it is now executing orders. thanks a lot! 

However, the problem of only sending buy orders still persists. there was 0 short orders but all were long orders

 
masterpotato #:

However, the problem of only sending buy orders still persists. there was 0 short orders but all were long orders

By the fact that you check this condition inside this if

Forum on trading, automated trading systems and testing trading strategies

Help Needed for Order Execution

masterpotato, 2024.04.11 05:09

void OnTick()
{
   int bars = iBars(NULL,0);
   if (barsTotal != bars && OrdersTotal() == 0)
      {
      barsTotal = bars;
      
            
      //FOR BUY ORDERS
      if (EMA9 > EMA225 && Close[2] < EMA9 && Close[1] > EMA9) 
       {
        if (K533 > D533 && K533 > 20)
         {
         Print("Executing Buy Order");         
         executeBuy();
         }
      //FOR SELL ORDERS      
         else if(EMA9 < EMA225 && Close[2] > EMA9 && Close[1] < EMA9)
           { 
            if(K533 < D533 && K533 < 80)
            {
             Print("Executing Sell Order");         
             executeSell();
            } 
           }
        }
      
      }
}   
 
Vladislav Boyko #:

By the fact that you check this condition inside this if

I see! all the silly problems...

thank you!

 
Vladislav Boyko #:
This should not be done in OnInit(), since the data may not be ready yet.

The reasons are described by William Roeder in point 1:

Forum on trading, automated trading systems and testing trading strategies

Experts: A Code block to detect A "New Candle/Bar" using bars history (very effective way)

William Roeder, 2024.04.11 15:43

    1. Don't try to use any price (or indicator) or server related functions in OnInit (or on load or in OnTimer before you've received a tick), as there may be no connection/chart yet:
      1. Terminal starts.
      2. Indicators/EAs are loaded. Static and globally declared variables are initialized. (Do not depend on a specific order.)
      3. OnInit is called.
      4. For indicators OnCalculate is called with any existing history.
      5. Human may have to enter password, connection to server begins.
      6. New history is received, OnCalculate called again.
      7. A new tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent, account information and prices are valid.

    2. Unlike indicators, EAs are not reloaded on chart change, so you must reinitialize them, if necessary.
                external static variable - MQL4 programming forum #2 (2013)

  1. You can't know when a candle closes. Only when a new tick arrives that starts a new bar is the old bar closed, and that tick could arrive almost at the end of a bar's duration.

    For a new bar test, Bars is unreliable (a refresh/reconnect can change number of bars on chart), volume is unreliable (miss ticks), Price is unreliable (duplicate prices and The == operand. - MQL4 programming forum.) Always use time.
              MT4: New candle - MQL4 programming forum #3 (2014)
              MT5: Accessing variables - MQL4 programming forum #3 (2022)

    I disagree with making a new bar function, because it can only be called once per tick (second call returns false). A variable can be tested multiple times.
              Running EA once at the start of each bar - MQL4 programming forum (2011)

 
masterpotato: (Rewriting this post to make it more clear)

double EMA9 = iMA(NULL,0,9,0,MODE_EMA,PRICE_CLOSE,0);
double EMA225 = iMA(NULL,0,225,0,MODE_EMA,PRICE_CLOSE,0);
double K533 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_MAIN,0);
double D533 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0);
double ATR9 = iATR(NULL,0,9,0);
int OnInit()

Those are not assignments; they are initialization of a common (globally declared), or static variable(s) with a constant. They work exactly the same way in MT4/MT5/C/C++.

  1. They are initialized once on program load.

  2. They don't update unless you assign to them.

  3. In C/C++ you can only initialize them with constants, and they default to zero. In MTx you should only initialize them with constants. There is no default in MT5, or MT4 with strict (which you should always use).

    MT4/MT5 actually compiles with non-constants, but the order that they are initialized is unspecified and Don't try to use any price (or indicator) or server related functions in OnInit (or on load or in OnTimer before you've received a tick), as there may be no connection/chart yet:

    1. Terminal starts.
    2. Indicators/EAs are loaded. Static and globally declared variables are initialized. (Do not depend on a specific order.)
    3. OnInit is called.
    4. For indicators OnCalculate is called with any existing history.
    5. Human may have to enter password, connection to server begins.
    6. New history is received, OnCalculate called again.
    7. A new tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent, account information and prices are valid.

  4. Unlike indicators, EAs are not reloaded on chart change, so you must reinitialize them, if necessary.
              external static variable - MQL4 programming forum #2 (2013)

Reason: