Creating objects on multiple charts

 

Hi Everyone, 

not entirely how this works since this is my first post:) 

Everything in this EA works fine, i tested it all multiple times. The only issue lies in the createObject. It works fine when i create objects just for one symbol which i make corresponding in the strategy tester although when backtesting on multiple symbols or i dont make the symbol the same in the strategy tester as in the code, the objects no longer appear at all. How can this be solved? Thanks in advance;)

sinput group                              "Hammer"
input double                              hammer_minWicktoWickRatio      = 4;
input double                              hammer_minWicktoBodyRatio      = 4;



//+-------------------------------------------------------------------------------------------------------+
//|  Global Variables                                                                                     |
//+-------------------------------------------------------------------------------------------------------+


string symbol_loop[] = {"GBPJPY"};//,"USDJPY","GBPNZD"};

int maHandle[];
datetime old_time;

//+-------------------------------------------------------------------------------------------------------+
//|  On OnInit                                                                                            |
//+-------------------------------------------------------------------------------------------------------+

int OnInit()
{
   ArrayResize(maHandle, ArraySize(symbol_loop));    
   for(int i = 0; i < ArraySize(symbol_loop); i++){
      maHandle[i] = iMA(symbol_loop[i], PERIOD_CURRENT, 14, 0, MODE_SMA, PRICE_CLOSE);
   }  
    return(INIT_SUCCEEDED);
}


//+-------------------------------------------------------------------------------------------------------+
//|  OnTick                                                                                               |
//+-------------------------------------------------------------------------------------------------------+
void OnTick(){

   datetime GMT = iTime(_Symbol, PERIOD_M15, 1);
   if (GMT > old_time){
      old_time = GMT;

   for (int i = 0; i < ArraySize(symbol_loop); i++){
   string symbol = symbol_loop[i]; 

      //------------------------------------//
      // GENERAL INFO                       //
      //------------------------------------//
      double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
      double contractSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
      double point = tickValue / contractSize;   
      
      int digits = GetDecimalPlaces(symbol);

      double PipValue = point * 10;
            
      
      //------------------------------------//
      // PRICE INFO                         //
      //------------------------------------//
      double Open = open(symbol, 1);
      double Close = close(symbol, 1);
      double Low = low(symbol, 1);
      double High = high(symbol, 1);
      double BodySize = NormalizeDouble(bodySize(symbol, 1, point), 1);
      double UpperWickSize = NormalizeDouble(CalculateUpperWickSize(symbol, 1, PipValue), 1);
      double LowerWickSize = NormalizeDouble(CalculateLowerWickSize(symbol, 1, PipValue), 1);
      double BiggerWickSize = MathMax(UpperWickSize, LowerWickSize);
      double SmallerWickSize = MathMin(UpperWickSize, LowerWickSize);

      double GreaterWicktoSmallerWickRatio = NormalizeDouble(CalculateGreaterWicktoSmallerWickRatio(BiggerWickSize, SmallerWickSize), 1);
      double GreaterWicktoBodyRatio = NormalizeDouble(CalculateGreaterWicktoBodyRatio(BodySize, SmallerWickSize), 1);
      
      //Previous Candlestick
      double PrevBodySize = NormalizeDouble(bodySize(symbol, 2, point), 1);
      double PrevUpperWickSize = NormalizeDouble(CalculateUpperWickSize(symbol, 2, point), 1);
      double PrevLowerWickSize = NormalizeDouble(CalculateLowerWickSize(symbol, 2, point), 1);   
      
      //------------------------------------//
      // INDICATOR INFO                     //
      //------------------------------------//

      double ma[];
      ArraySetAsSeries(ma, true);
      CopyBuffer(maHandle[i], 0, 0, 1, ma);
      double MA_Value = ma[0];


      bool BuyingHammerConfirmed = BuyingHammerSignal(UpperWickSize, LowerWickSize, BodySize, Low, old_time, hammer_minWicktoBodyRatio, hammer_minWicktoWickRatio, High, MA_Value, symbol);
        
      //------------------------------------//
      // POSITION MANAGEMENT                //
      //------------------------------------// 
      
      
            if(BuyingHammerConfirmed==true){
               createObject(old_time, Low, 233, 1, clrGreen, " Doji", symbol);
            }
      }
      } 
}

//+-------------------------------------------------------------------------------------------------------+
//|  Candlesticks                                                                                         |
//+-------------------------------------------------------------------------------------------------------+


//---------------------Buying Candlesticks---------------------

bool BuyingHammerSignal(double pUpperWickSize, double pLowerWickSize, double pBodySize, double pLow, datetime ptime, double phammer_minWicktoBodyRatio, double phammer_minWicktoWickRatio,
                        double pHigh, double pMAValue, string psymbol)
{
    if ((pUpperWickSize * phammer_minWicktoWickRatio) < pLowerWickSize)
    {
        if ((pBodySize * phammer_minWicktoBodyRatio) < pLowerWickSize)
        {
            if (pHigh < pMAValue)
            {
                createObject(ptime, pLow, 233, 1, clrGreen, " Hammer", psymbol);
                return true;
            }
        }
    }
    return false;
}

//+-------------------------------------------------------------------------------------------------------+
//|  EA Candlestick Displays                                                                              |
//+-------------------------------------------------------------------------------------------------------+
void createObject(datetime time, double price, int arrowcode, int direction, color clr, string txt, string psymbol)
{
    string objName = "";
    StringConcatenate(objName, "Signal@", " ", psymbol, " ", time, " at ", DoubleToString(price, _Digits), " (", arrowcode, ")");

    if (ObjectCreate(0, objName, OBJ_ARROW, 0, time, price)){
        ObjectSetInteger(0, objName, OBJPROP_ARROWCODE, arrowcode);
        ObjectSetString(0, objName, OBJPROP_SYMBOL, psymbol);
   
        }
}


//+-------------------------------------------------------------------------------------------------------+
//|  Price Action Neccessities                                                                            |
//+-------------------------------------------------------------------------------------------------------+
double open(string symbol, int shift)
{
    return iOpen(symbol, PERIOD_CURRENT, shift);
}

double close(string symbol, int shift)
{
    return iClose(symbol, PERIOD_CURRENT, shift);
}

double high(string symbol, int shift)
{
    return iHigh(symbol, PERIOD_CURRENT, shift);
}

double low(string symbol, int shift)
{
    return iLow(symbol, PERIOD_CURRENT, shift);
}

double bodySize(string symbol, int shift, double point)
{
    double openPrice = iOpen(symbol, PERIOD_CURRENT, shift);
    double closePrice = iClose(symbol, PERIOD_CURRENT, shift);
    
    double bodySize = MathAbs(closePrice - openPrice);
    double bodySize2 = (bodySize / (point * 10));
    return bodySize2;
}

double CalculateUpperWickSize(string symbol, int shift, double pip)
{
    double highPrice = iHigh(symbol, PERIOD_CURRENT, shift);
    double openPrice = iOpen(symbol, PERIOD_CURRENT, shift);
    double closePrice = iClose(symbol, PERIOD_CURRENT, shift);

    // Calculate the upper wick size
    double upperWick = highPrice - MathMax(openPrice, closePrice);
    double upperWickInPips = upperWick / pip;

    return upperWickInPips;
}

double CalculateLowerWickSize(string symbol, int shift, double pip)
{
    double lowPrice = iLow(symbol, PERIOD_CURRENT, shift);
    double openPrice = iOpen(symbol, PERIOD_CURRENT, shift);
    double closePrice = iClose(symbol, PERIOD_CURRENT, shift);

    // Calculate the upper wick size
    double lowerWick = MathMin(openPrice, closePrice) - lowPrice;
    double lowerWickInPips = lowerWick / pip;

    return lowerWickInPips;
}


double CalculateGreaterWicktoSmallerWickRatio(double biggerWickSize, double smallerWickSize) {
    if(smallerWickSize > 0.0) {
        double ratio = biggerWickSize / smallerWickSize;
        return NormalizeDouble(ratio, 1);
    } else if(smallerWickSize == 0.0) { 
        smallerWickSize = 0.01;
        double ratio = biggerWickSize / smallerWickSize;
        return NormalizeDouble(ratio, 1);
    }
    return 0.0; 
}


double CalculateGreaterWicktoBodyRatio(double bodysize, double smallerWickSize) {
    if (smallerWickSize > 0.0) {
        double ratio = bodysize / smallerWickSize;
        return NormalizeDouble(ratio, 1);
    } else if(smallerWickSize == 0.0) { 
        smallerWickSize = 0.01;
        double ratio = bodysize / smallerWickSize;
        return NormalizeDouble(ratio, 1);
    }
    return 0.0; 
}

int GetDecimalPlaces(const string symbol)
  {
    double tick_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
    int decimal_places = 0;

    while (tick_size < 1.0) {
        tick_size *= 10.0;
        decimal_places++;
    }

    return decimal_places;
  }
 
Hi this EA works fine but it will only create objects for the sole symbol I select in the backtesting settings. Im aware in the CreateObject function, the chart ID ive selected is 0. How do I make this suitable to all symbols in the symbol_loop? Must I loop through the chart ID of all open charts? And if so how can that be achieved?


//+-------------------------------------------------------------------------------------------------------+
//|  Global Variables                                                                                     |
//+-------------------------------------------------------------------------------------------------------+

double symbol_points[];
string symbol_loop[] = {"GBPUSD", "EURUSD"};

datetime old_time;

//+-------------------------------------------------------------------------------------------------------+
//|  Include Files                                                                                        |
//+-------------------------------------------------------------------------------------------------------+

#include <Trade/Trade.mqh>
CTrade trade;

//+-------------------------------------------------------------------------------------------------------+
//|  On OnInit                                                                                            |
//+-------------------------------------------------------------------------------------------------------+

int OnInit()
{


   return(INIT_SUCCEEDED);
}


//+-------------------------------------------------------------------------------------------------------+
//|  OnTick                                                                                               |
//+-------------------------------------------------------------------------------------------------------+
void OnTick(){

   datetime GMT = iTime(_Symbol, PERIOD_M15, 1);
   if (GMT > old_time){
      old_time = GMT;

   for (int i = 0; i < ArraySize(symbol_loop); i++){
   string symbol = symbol_loop[i]; 
   
      double Low = low(symbol, 1);
   
      if(isCandlestickBullish(symbol, 1)){
         createObject(old_time, Low, 233, 1, clrRed, "Testing", symbol); 
      }

   }
   } 
}


bool isCandlestickBullish(string symbol, int shift)
{
    double openPrice = iOpen(symbol, PERIOD_CURRENT, shift);
    double closePrice = iClose(symbol, PERIOD_CURRENT, shift);

    return closePrice > openPrice;
}

bool isPrevCandlestickBullish(string symbol, int shift)
{
    double openPrice = iOpen(symbol, PERIOD_CURRENT, shift);
    double closePrice = iClose(symbol, PERIOD_CURRENT, shift);

    return closePrice > openPrice;
}

//+-------------------------------------------------------------------------------------------------------+
//|  EA Candlestick Displays                                                                              |
//+-------------------------------------------------------------------------------------------------------+
void createObject(datetime time, double price, int arrowcode, int direction, color clr, string txt, string psymbol)
{
    string objName = "";
    StringConcatenate(objName, "Signal@", " ", psymbol, " ", time, " at ", DoubleToString(price, _Digits), " (", arrowcode, ")");

    if (ObjectCreate(0, objName, OBJ_ARROW, 0, time, price))
    {
        ObjectSetInteger(0, objName, OBJPROP_ARROWCODE, arrowcode);
        ObjectSetInteger(0, objName, OBJPROP_COLOR, clr);
        ObjectSetString(0, objName, OBJPROP_SYMBOL, psymbol);
        if (direction > 0)
            ObjectSetInteger(0, objName, OBJPROP_ANCHOR, ANCHOR_TOP);
        if (direction < 0)
            ObjectSetInteger(0, objName, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
    }

    string objectNameDesc = objName + txt;
    if (ObjectCreate(0, objectNameDesc, OBJ_TEXT, 0, time, price))
    {
        ObjectSetString(0, objectNameDesc, OBJPROP_TEXT, " " + txt);
        ObjectSetInteger(0, objectNameDesc, OBJPROP_COLOR, clr);
        if (direction > 0)
            ObjectSetInteger(0, objectNameDesc, OBJPROP_ANCHOR, ANCHOR_TOP);
        if (direction < 0)
            ObjectSetInteger(0, objectNameDesc, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
    }
}


double low(string symbol, int shift)
{
    return iLow(symbol, PERIOD_CURRENT, shift);
}
 

To be able to add graphical objects for other symbols (i.e. other charts), you would need to ...

  1. Scan all open charts, using ChartFirst and ChartNext to find the one you wish to use (i.e. the desired symbol, time-frame, etc.). There may be more than one or none at all.
  2. If none exist, then you would have to open up a new chart for the desired symbol.
  3. Once you have identified the desired chart id, then you can add graphical objects to that chart.
However, doing this in the Strategy Tester may be tricky. I've never tested such functionality under the Strategy Tester. Also, it would only work in Visual Mode obviously.
     
    Fernando Carreiro #:

    To be able to add graphical objects for other symbols (i.e. other charts), you would need to ...

    1. Scan all open charts, using ChartFirst and ChartNext to find the one you wish to use (i.e. the desired symbol, time-frame, etc.). There may be more than one or none at all.
    2. If none exist, then you would have to open up a new chart for the desired symbol.
    3. Once you have identified the desired chart id, then you can add graphical objects to that chart.
    However, doing this in the Strategy Tester may be tricky. I've never tested such functionality under the Strategy Tester. Also, it would only work in Visual Mode obviously.

      How can I confirm whether a chart has been opened? I included the following code in an EA which shows trades are being opened close yet the first value returns 12345 and the next -1. Does that mean if though trades are being places and i can see them in the visualize section the chart isnt actually open?

            long chartID1 = ChartFirst();
            long chartID2 = ChartNext(chartID1);
            
            Print(chartID1);
            Print(chartID2);

      Even when adding the following function, the values of the charts opened return the same value suggesting something is wrong:

      void OpenChartsForSymbols()
      {
         for (int i = 0; i < ArraySize(symbol_loop); i++)
         {
            string symbol = symbol_loop[i];
            int timeframe = PERIOD_M15; // Adjust the timeframe as needed
      
            // Check if the chart is already open for the symbol and timeframe
            long chartID = ChartID();
            
            if (chartID == 0)
            {
               // The chart is not open, so open it
               chartID = ChartOpen(symbol, timeframe);
               if (chartID <= 0)
               {
                  // Handle any errors that occurred during chart opening
               }
            }
         }
      }

      Finally ive used this code from the MQL5 documentation for looping the chartID, will this be effective?

      long currChart,prevChart=ChartFirst(); 
         int i=0,limit=100; 
         Print("ChartFirst =", ChartSymbol(prevChart)," ID =",prevChart); 
         while(i<limit)// We have certainly not more than 100 open charts 
           { 
            currChart=ChartNext(prevChart); // Get the new chart ID by using the previous chart ID 
            if(currChart<0) break;          // Have reached the end of the chart list 
            Print(i,ChartSymbol(currChart)," ID =",currChart); 
            prevChart=currChart;// let's save the current chart ID for the ChartNext() 
            i++;// Do not forget to increase the counter 
      Files: