Turning a EA into a indicator.

 

Hello, I am new to programming with MT5 and MetaEditor. With the help of a YT video I was able to create a ORB EA, which exactly does what a ORB indicator does but just as an EA. The original intention of the creator was a EA initiating long and short positions when breaking out of the OR-zone. But because I dont like machines executing for me I tried to figure out how to turn this EA into a indicator. But because of my lack of knowledge regarding programming and how to successfully implement and optimize an indicator, I was not able to convert the EA to an indicator. Thats why I am here. I really hope you guys can help me or link me to something that can help me turning this EA into an indicator. Thank you in advance.

input int RangeStartHour = 3;
input int RangeStartMin = 0;
input int RangeEndHour = 6;
input int RangeEndMin = 0;

datetime rangeTimeStart;
datetime rangeTimeEnd;

double rangeHigh;
double rangeLow;

int OnInit(){

        return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason){

}

void OnTick(){

        calcTimes();
        calcRange();

}

void calcTimes(){
        MqlDateTime dt;
        TimeCurrent(dt);
        dt.sec = 0;

        dt.hour = RangeStartHour;
        dt.min = RangeStartMin;
        rangeTimeStart = StructToTime(dt);

        dt.hour = RangeEndHour;
        dt.min = RangeEndMin;
        rangeTimeEnd = StructToTime(dt);
}

void calcRange(){
        double highs[];
        CopyHigh(_Symbol,PERIOD_M1,rangeTimeStart,rangeTimeEnd,highs);

        double lows[];
        CopyLow(_Symbol,PERIOD_M1,rangeTimeStart,rangeTimeEnd,lows);

        if(ArraySize(highs) < 1 || ArraySize(lows) < 1) return;

        int indexHighest = ArrayMaximum(highs);
        int indexLowest = ArrayMinimum(lows);

        rangeHigh = highs[indexHighest];
        rangeLow = lows[indexLowest];

        string objName = "Range "+TimeToString(rangeTimeStart,TIME_DATE);
        if(ObjectFind(0,objName) < 0){
                ObjectCreate(0,objName,OBJ_RECTANGLE,0,rangeTimeStart,rangeLow,rangeTimeEnd,rangeHigh);
                ObjectSetInteger(0,objName,OBJPROP_FILL,true);
                ObjectSetInteger(0,objName,OBJPROP_COLOR,clrYellow);
        }else{
                ObjectSetDouble(0,objName,OBJPROP_PRICE,0,rangeLow);
                ObjectSetDouble(0,objName,OBJPROP_PRICE,1,rangeHigh);
        }
}
 

Your topic has been moved to the section: Technical Indicators
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893

  • Usually people who can't code don't receive free help on this forum.
  • If you show your attempts and describe your problem clearly, you will most probably receive an answer from the community.
  • To learn MQL programming, you can research the many available Articles on the subject, or examples in the Codebase, as well as reference the online Book and Documentation
  • You also have the option to hire a programmer in the Freelance section.

Here are some references to get you started ...

Articles

Custom Indicators (Part 1): A Step-by-Step Introductory Guide to Developing Simple Custom Indicators in MQL5

Kelvin Muturi Muigua, 2024.05.02 13:26

Learn how to create custom indicators using MQL5. This introductory article will guide you through the fundamentals of building simple custom indicators and demonstrate a hands-on approach to coding different custom indicators for any MQL5 programmer new to this interesting topic.

Articles

Introduction to MQL5 (Part 12): A Beginner's Guide to Building Custom Indicators

Israel Pelumi Abioye, 2025.02.07 13:49

Learn how to build a custom indicator in MQL5. With a project-based approach. This beginner-friendly guide covers indicator buffers, properties, and trend visualization, allowing you to learn step-by-step.
 

It would be tricky to make this without iBarShift, so the indicator would look like this:

#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0

// Input parameters for ORB time window
input int RangeStartHour = 3;    // Range Start Hour
input int RangeStartMin  = 0;   // Range Start Minute
input int RangeEndHour   = 9;   // Range End Hour
input int RangeEndMin    = 0;    // Range End Minute

// Global variables
datetime rangeTimeStart;  // Start of ORB range
datetime rangeTimeEnd;    // End of ORB range

//+------------------------------------------------------------------+
//| Custom indicator initialization function                          |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0, "Range ");
  }

//+------------------------------------------------------------------+
//| Calculate range start/end times                                  |
//+------------------------------------------------------------------+
void calcTimes()
  {
   MqlDateTime dt;
   TimeCurrent(dt);
   dt.sec = 0;

   dt.hour = RangeStartHour;
   dt.min  = RangeStartMin;
   rangeTimeStart = StructToTime(dt);

   dt.hour = RangeEndHour;
   dt.min  = RangeEndMin;
   rangeTimeEnd = StructToTime(dt);
  }


//+------------------------------------------------------------------+
//| Custom indicator iteration function                               |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   ArraySetAsSeries(time, true);
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);

   // Calculate range start/end times
   calcTimes();
   
   // Debug
   //Print("Range: ", TimeToString(rangeTimeStart, TIME_DATE|TIME_MINUTES),
   //      " to ", TimeToString(rangeTimeEnd, TIME_DATE|TIME_MINUTES),
   //      ", Current bar time: ", TimeToString(time[0], TIME_DATE|TIME_MINUTES));

   // Find bar indices for the range
   int range_start_bar = iBarShift(_Symbol, _Period, rangeTimeStart, false); // older bar (higher index when arrays are series based)
   int range_end_bar   = iBarShift(_Symbol, _Period, rangeTimeEnd, false);   // newer bar (lower index when arrays are series based)


   double rangeHigh = -DBL_MAX;
   double rangeLow  = DBL_MAX;
   datetime actualRangeEnd = rangeTimeEnd;


   if(time[0] >= rangeTimeEnd)
     {
      for(int i = range_start_bar; i >= range_end_bar && !IsStopped(); i--)
        {
         if(time[i] >= rangeTimeStart && time[i] <= rangeTimeEnd)
           {
            rangeHigh = MathMax(rangeHigh, high[i]);
            rangeLow  = MathMin(rangeLow, low[i]);
            actualRangeEnd = time[i] + PeriodSeconds(_Period); // end at bar close
           }
        }

      // Check if valid high/low found
      if(rangeHigh == -DBL_MAX || rangeLow == DBL_MAX)
        {
         Print("No valid bars in range. High=", rangeHigh, ", Low=", rangeLow);
         return(rates_total);
        }

      // Draw the rectangle
      string objName = "Range " + TimeToString(rangeTimeStart, TIME_DATE);
      datetime actualRangeStart = time[range_start_bar];

      if(ObjectFind(0, objName) < 0)
        {
         if(!ObjectCreate(0, objName, OBJ_RECTANGLE, 0, actualRangeStart, rangeLow, actualRangeEnd, rangeHigh))
           {
            Print("Failed to create rectangle: Error=", GetLastError());
            return(rates_total);
           }
         ObjectSetInteger(0, objName, OBJPROP_FILL, true);
         ObjectSetInteger(0, objName, OBJPROP_COLOR, clrYellow);
         ObjectSetInteger(0, objName, OBJPROP_BACK, true);
         ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
         ObjectSetInteger(0, objName, OBJPROP_HIDDEN, false);
        }
     }

   return(rates_total);
  }
 
Conor Mcnamara #:

It would be tricky to make this without iBarShift, so the indicator would look like this:

This is exactly what I was trying to achieve, thank you so much. I really appreciate your effort.

I got one question tho. I noticed that in the EA format of the ORB visualization, the rectangle gets drawn live on the chart.

(meaning that when the desired OR time is come the rectangle grows with the creation of this opening range)

Is that in the indicator format not possible or just really hard to achieve?