MQL-Programmiererin Anja Vogel

Preismarken Trading

MQL4 + MQL5

MT4 & MT5 Gitter Indikator

Grid Indikator für MT4 und MT5

Chart mit AV_Grid Indikator
Chart mit Indikator AV_Grid, horizontale Linien durchgezogen

Das original Gitter des MT4 und MT5 ist meiner Ansicht nach unbrauchbar, weil die Linien irgendwohin gelegt werden.

Was ich sehen möchte ist ein Gitter, welches Perioden markiert und runde Preise, weswegen ich mein eigenes programmiert habe. Außerdem möchte ich nicht ständig die Einstellungen anpassen müssen, weil zuviele oder zuwenig Linien zu sehen sind. Mein Ziel bei diesem Grid bzw. Gitter ist also, dass es möglichst selbständig gute Abstände berechnet.

Ganz neu ist mein MQL5 Balance und EA Monitor.

Einstellung

Es gibt Haupt- und Zwischenlinien, wobei die Häufigkeit der Hauptlinien festgelegt werden kann, sowie das Erscheinungsbild der 4 Linientypen (2 senkrecht und 2 waagerecht). Für die Häufigkeit erscheint mir 2-fach oder 5-fach als sinnvolle Einstellung.

Alle Linien können in den Hintergrund gelegt werden und die Information kann ausgeblendet werden, so hat man wirklich nur ein Raster im Chart. Selbstverständlich können alle Linien auf die gleiche Farbe und den gleichen Linientyp eingestellt werden. Ich benutze dafür gerne "DimGray" oder "DarkSlateGray" mit Typ "Dot". Dadurch kann man es sich so einstellen, dass es wirklich nicht stört.

Chart mit AV_Grid Indikator
Chart mit Indikator AV_Grid, horizontale Linien gepunktet

AV_Grid.mq5

Download Indikator AV_Grid.mq5 für MT4 und MT5. Hier folgt der Quellcode:

//+------------------------------------------------------------------+
//|                                                      AV_Grid.mq5 |
//|                                       Copyright 2022, Anja Vogel |
//|                                        https://www.anjavogel.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, Anja Vogel"
#property link      "https://www.anjavogel.com"
#define VERSION "1.8"
#property version VERSION
string indicatorName = "AV Grid V" + VERSION;
string indicatorShortname = "Grid " + VERSION;
#property description "Probiere folgende Farbsets für die Linien:"
#property description " "
#property description "a) LightBlue, CadetBlue, DarkGray, DimGray"
#property description "b) Silver, Gray, Silver, Gray"
#property description "c) 4x Gray"
#property description "d) 4x DarkSlateGray"
#property description " "
#property description "Probiere auch Foreground und Background des Charts"
#property description "auf die gleiche Farbe einzustellen, z.B 50,50,50"
#property description "und 4x Hintergrund = false."
#property description " "
#property description "Für ein besonders zurückhaltendes Raster, benutze z.B. "
#property description "4x DarkSlateGray und 4x Hintergrund = true."
#property indicator_chart_window

#property indicator_buffers 1
#property indicator_plots   1

input color infoColor = clrCadetBlue; // Info Schriftfarbe
input int   infoSize = 10; // Info Schriftgröße
input bool  showInfo = true; // Info anzeigen

#ifdef __MQL5__
   input group "::: 1.1) Horizontale Hauptlinie :::"
#endif

input int   every = 2; // Hauptlinie alle x Linien
input color horizontalColor1 = clrCadetBlue; // Farbe
input ENUM_LINE_STYLE horizontalStyle1 = STYLE_DOT; // Linientyp
input int   horizontalWidth1 = 1; // Dicke
input bool  horizontalBackground1 = false; // Hintergrund

#ifdef __MQL5__
    input group "::: 1.2) Horizontale Zwischenlinie :::"
#endif

input color horizontalColor2 = clrLightSlateGray; // Farbe
input ENUM_LINE_STYLE horizontalStyle2 = STYLE_DOT; // Linientyp
input int   horizontalWidth2 = 1; // Dicke
input bool  horizontalBackground2 = true; // Hintergrund

#ifdef __MQL5__
	input group "::: 2.1) Vertikale Hauptlinie :::"
#endif

input color vertikalColor1 = clrDarkGray; // Farbe
input ENUM_LINE_STYLE vertikalStyle1 = STYLE_DOT; // Linientyp
input int   vertikalWidth1 = 1; // Dicke
input bool  vertikalBackground1 = false; // Hintergrund

#ifdef __MQL5__
	input group "::: 2.2) Vertikale Zwischenlinie :::"
#endif

input color vertikalColor2 = clrDimGray; // Farbe
input ENUM_LINE_STYLE vertikalStyle2 = STYLE_DOT; // Linientyp
input int   vertikalWidth2 = 1; // Dicke
input bool  vertikalBackground2 = true; // Hintergrund

input bool develop = false; // Entwickler

string vLabel = "vGrid-";
string hLabel = "hGrid-";

double lastWindowMax = 0.0;
double lastWindowMin = 0.0;
double lastMaxPrice = 0.0;
double lastMinPrice = 0.0;
double center = 0.0;
int    diffDigits  = 0;
double diffStep = 50.0;

long   lastWithInBars = 0;
int    mode = 0;
int    lastMode = 0;
long   pastBars = 1;
int    vLines = 0;

//+------------------------------------------------------------------+
// OnInit()
//+------------------------------------------------------------------+
int OnInit()
{
   diffDigits = _Digits - 2;

   IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortname);
   PlotIndexSetString(0, PLOT_LABEL,       indicatorName);

   EventSetTimer(1); // Timer mit x Sekunden

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
// OnDeinit()
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ObjectDelete(0, "Grid");
   ObjectsDeleteAll(0, hLabel);
   ObjectsDeleteAll(0, vLabel);
   EventKillTimer();
}

//+------------------------------------------------------------------+
// OnTimer()
//+------------------------------------------------------------------+
void OnTimer()
{
   if (MQLInfoInteger(MQL_TESTER)) return;
   
   double maxPrice = ChartGetDouble(0,CHART_PRICE_MAX);
   double minPrice = ChartGetDouble(0,CHART_PRICE_MIN);

   if (maxPrice == 0.0) return;

   if (maxPrice != lastWindowMax || minPrice != lastWindowMin || lastWithInBars != ChartGetInteger(0,CHART_WIDTH_IN_BARS)) {

      if (!calculateLines()) {
         //out("Lösche alle horizontalen Linien wegen neuem Abstand!");
         lastMaxPrice = 0.0;
         lastMinPrice = 0.0;
         ObjectsDeleteAll(0, hLabel);
      }

      // zeichne Linien
      drawHorizontal();
      drawVertical();

      // Nach dem Zeichnen Fenstergröße speichern
      lastWindowMax = maxPrice;
      lastWindowMin = minPrice;

      //if (develop) ChartWrite("Grid", TimeToString(TimeCurrent(),TIME_SECONDS) + " (" + (string)diffStep + ") " + _Symbol + " (" + (string)NormalizeDouble((maxPrice - minPrice) / diffStep, 1) + " Linien|Mode " + (string)mode + "|S." + (string)ChartGetInteger(0,CHART_SCALE,0) + ") "+ DoubleToStr(_Point, _Digits) + " / " + 100*pointToPip(), 15, 25);
      if (develop) ChartWrite("Grid", "V" + VERSION + " " + TimeToString(TimeCurrent(),TIME_SECONDS) + " | " + (string)(diffStep * pointToPip()) + " Pip | " + _Symbol + " | " + getModeName(), 15, 25);
      else if (showInfo) ChartWrite("Grid", (string)(diffStep * pointToPip()) + " Pip | " + _Symbol + " | " + getModeName(), 15, 25);
   }
}
//+------------------------------------------------------------------+
// OnCalculate()
//+------------------------------------------------------------------+
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[])
{
   // siehe OnTimer()

   if (MQLInfoInteger(MQL_TESTER)) {
      // zeichne Linien
      drawHorizontal();
      drawVertical();
       
      ChartWrite("Grid", "(" + (string)diffStep + ") " + _Symbol + " (Mode " + (string)mode + "|S." + (string)ChartGetInteger(0,CHART_SCALE,0) + ")", 15, 25);
   }

   return(rates_total);
}

//+------------------------------------------------------------------+
// horizontale Linien
//+------------------------------------------------------------------+
void drawHorizontal()
{
   double maxPrice = ChartGetDouble(0,CHART_PRICE_MAX);
   double minPrice = ChartGetDouble(0,CHART_PRICE_MIN);

   center = calculateCenter();

   DrawHLine(hLabel, NormalizeDouble(center, _Digits), TimeCurrent(), calculateBold(center)); // wichtigste Linie
   if (develop) ObjectSetInteger(0, hLabel, OBJPROP_COLOR, clrYellow);

   double walk = lastMaxPrice != 0.0 ? lastMaxPrice : center; // starte an der letzen Linie nach oben

   while (walk < maxPrice) {

      if (diffStep > 0) walk += diffStep;
      else walk = maxPrice; // Ausstieg

      DrawHLine(hLabel + DoubleToString(walk, _Digits), NormalizeDouble(walk, _Digits), TimeCurrent(), calculateBold(walk));
      lastMaxPrice = walk;
   }


   walk = lastMinPrice != 0.0 ? lastMinPrice : center; // starte an der letzen Linie nach unten

   while (walk > minPrice) {

      if (diffStep > 0) walk -= diffStep;
      else walk = minPrice; // Ausstieg

      DrawHLine(hLabel + DoubleToString(walk, _Digits), NormalizeDouble(walk, _Digits), TimeCurrent(), calculateBold(walk));
      lastMinPrice = walk;
   }
}

//+------------------------------------------------------------------+
// vertikale Linien
//+------------------------------------------------------------------+
void drawVertical()
{
   double maxPrice = ChartGetDouble(0,CHART_PRICE_MAX);
   double minPrice = ChartGetDouble(0,CHART_PRICE_MIN);

   // Zur Ermittlung der Anzahl der Minuten des jeweiligen Zeitrahmens
   // ist der Wert der Funktion PeriodSeconds durch 60 zu dividieren.
   int seconds  = PeriodSeconds(ChartPeriod(0));      // /60
   int shift = 0;


   pastBars = Bars(NULL, 0) - 2;

   if (MQLInfoInteger(MQL_TESTER) || pastBars < 1) {  // Strategietester
      pastBars = 1;
   }


   if (seconds <= PeriodSeconds(PERIOD_M1)) {         // Tageswechsel & H4, H1-Wechsel
      mode = 1;
      if (ChartGetInteger(0,CHART_SCALE,0) < 1) mode++;
      if (ChartGetInteger(0,CHART_SCALE,0) >= 4) mode--;

   } else if (seconds <= PeriodSeconds(PERIOD_M5)) {  // Tageswechsel & H8, H2-Wechsel
      mode = 2;
      if (ChartGetInteger(0,CHART_SCALE,0) <= 1) mode++;
      if (ChartGetInteger(0,CHART_SCALE,0) >= 4) mode--;

   } else if (seconds <= PeriodSeconds(PERIOD_M15)) { // Tageswechsel, H8-Wechsel
      mode = 3;
      if (ChartGetInteger(0,CHART_SCALE,0) <= 1) mode++;
      if (ChartGetInteger(0,CHART_SCALE,0) >= 4) mode--;

   } else if (seconds <= PeriodSeconds(PERIOD_H1)) {  // Wochenwechsel, Tageswechsel
      mode = 4;
      if (ChartGetInteger(0,CHART_SCALE,0) <= 1) mode++;
      if (ChartGetInteger(0,CHART_SCALE,0) >= 4) mode--;

   } else if (seconds <= PeriodSeconds(PERIOD_H4)) {  // Monatswechsel, Wochenwechsel
      mode = 5;
      if (ChartGetInteger(0,CHART_SCALE,0) <= 1) mode++;
      if (ChartGetInteger(0,CHART_SCALE,0) >= 4) mode--;

   } else if (seconds <= PeriodSeconds(PERIOD_D1)) {  // Quartalswechsel, Monatswechsel
      mode = 6;
      if (ChartGetInteger(0,CHART_SCALE,0) <= 1) mode++;
      if (ChartGetInteger(0,CHART_SCALE,0) >= 4) mode--;

   } else if (seconds <= PeriodSeconds(PERIOD_W1)) {  // Halbjahreswechsel, Quartalswechsel
      mode = 7;
      if (ChartGetInteger(0,CHART_SCALE,0) == 0) mode = 9;
      if (ChartGetInteger(0,CHART_SCALE,0) == 1) mode = 9;
      if (ChartGetInteger(0,CHART_SCALE,0) == 2) mode = 8;
      if (ChartGetInteger(0,CHART_SCALE,0) == 5) mode = 6;

   } else if (seconds > PeriodSeconds(PERIOD_W1)) {   // Jahreswechsel, Halbjahreswechsel
      mode = 8;
      if (ChartGetInteger(0,CHART_SCALE,0) <= 2) mode++;
   } // mode = 9 heißt alle 10 Jahre, alle 5 Jahre

   if (mode < 0) mode = 0;
   if (mode > 9) mode = 9;


   if (lastMode != mode || lastWithInBars != ChartGetInteger(0,CHART_WIDTH_IN_BARS)) {
      out("Lösche vertikalen Linien wegen Mode- oder Breiten-Änderung und zeichne neu!");
      ObjectsDeleteAll(0, vLabel);
      lastMode = mode;
      lastWithInBars = ChartGetInteger(0,CHART_WIDTH_IN_BARS);
   }

   vLines = 0;

   for (shift = 0; shift <= pastBars; shift++) {
      if (vLines > 500) break;

      if (mode == 0) { // H4, H1-Wechsel

         if (TimeHour(Time[shift+1]) != TimeHour(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], (TimeHour(Time[shift]) % 4 == 0));
         }
      }
      else if (mode == 1) { // Tageswechsel & H4, H1-Wechsel

         if (TimeDay(Time[shift+1]) != TimeDay(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], true);
         }
         else if (TimeHour(Time[shift+1]) != TimeHour(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], (TimeHour(Time[shift]) % 4 == 0));
         }
      }
      else if (mode == 2) { // Tageswechsel & H8, H2-Wechsel

         if (TimeDay(Time[shift+1]) != TimeDay(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], true);
         }
         else if (TimeHour(Time[shift+1]) != TimeHour(Time[shift])) {
            if (TimeHour(Time[shift]) % 2 == 0)
               DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], (TimeHour(Time[shift]) % 8 == 0));
         }
      }
      else if (mode == 3) { // Tageswechsel, H8-Wechsel

         if (TimeDay(Time[shift+1]) != TimeDay(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], true);
         }
         else if (TimeHour(Time[shift+1]) != TimeHour(Time[shift])) {
            if (TimeHour(Time[shift]) % 8 == 0)
               DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], false);
         }
      }
      else if (mode == 4) { // Wochenwechsel, Tageswechsel

         if (TimeDayOfWeek(Time[shift+1]) > TimeDayOfWeek(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], true);
         }
         else if (TimeDay(Time[shift+1]) != TimeDay(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], false);
         }
      }
      else if (mode == 5) { // Monatswechsel, Wochenwechsel

         if (TimeDay(Time[shift+1]) > TimeDay(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], true);
         }
         else if (TimeDayOfWeek(Time[shift+1]) > TimeDayOfWeek(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], false);
         }
      }
      else if (mode == 6) { // Quartalswechsel, Monatswechsel

         if (TimeMonth(Time[shift+1]) != TimeMonth(Time[shift])) {
            DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], TimeMonth(Time[shift]) % 3 == 0);
         }
      }
      else if (mode == 7) { // Halbjahreswechsel, Quartalswechsel

         if (TimeMonth(Time[shift+1]) != TimeMonth(Time[shift])) {
            if (TimeMonth(Time[shift]) % 3 == 0)
               DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], TimeMonth(Time[shift]) % 6 == 0);
         }
      }
      else if (mode == 8) { // Jahreswechsel, Halbjahreswechsel

         if (TimeMonth(Time[shift+1]) != TimeMonth(Time[shift])) {
            if (TimeMonth(Time[shift]) % 6 == 0)
               DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], TimeMonth(Time[shift]) % 12 == 0);
         }
      }
      else if (mode == 9) { // alle 10 Jahre, alle 5 Jahre

         if (TimeYear(Time[shift+1]) != TimeYear(Time[shift])) {
            if (TimeYear(Time[shift]) % 5 == 0) DrawVLine(vLabel + TimeToString(Time[shift]), minPrice, Time[shift], TimeYear(Time[shift]) % 10 == 0);
         }
      }
   }
}

//+------------------------------------------------------------------+
// getModeName()
//+------------------------------------------------------------------+
string getModeName()
{
   switch(mode) {
      case 0: return "H4 + H1"; 
      case 1: return "D + H1";
      case 2: return "D + H2"; 
      case 3: return "D + H8";
      case 4: return "W + D";
      case 5: return "MN + W";
      case 6: return "MN3 + MN";
      case 7: return "MN6 + MN3";
      case 8: return "Y + MN6"; 
      case 9: return "Y10 + Y5";
   }
   return "-";
}

//+------------------------------------------------------------------+
// Berechne einen guten Preis-Abstand
//+------------------------------------------------------------------+
bool calculateLines()
{
   double maxPrice = ChartGetDouble(0,CHART_PRICE_MAX);
   double minPrice = ChartGetDouble(0,CHART_PRICE_MIN);
   double oldDiffStep = diffStep;

   diffDigits  = _Digits - 2;

   switch (diffDigits) {

      case 1: // 3 Nachkommastellen
         diffStep = 1.0;

         if ((maxPrice - minPrice) / diffStep <= 3) {
            diffStep = 0.5;
            if ((maxPrice - minPrice) / diffStep <= 3) {
               diffStep = 0.25;
               if ((maxPrice - minPrice) / diffStep <= 3) {
                  diffStep = 0.1;
                  if ((maxPrice - minPrice) / diffStep <= 3) {
                     diffStep = 0.05;
                     if ((maxPrice - minPrice) / diffStep <= 3) {
                        diffStep = 0.025;
                        if ((maxPrice - minPrice) / diffStep <= 3) {
                           diffStep = 0.01;
                        }
                     }
                  }
               }
            }
         }
         if ((maxPrice - minPrice) / diffStep >= 9) {
            diffStep = 2.5;
            if ((maxPrice - minPrice) / diffStep >= 9) {
               diffStep = 5.0;
               if ((maxPrice - minPrice) / diffStep >= 9) {
                  diffStep = 10.0;
                  if ((maxPrice - minPrice) / diffStep >= 9) {
                     diffStep = 25.0;
                     if ((maxPrice - minPrice) / diffStep >= 9) {
                        diffStep = 50.0;
                     }
                  }
               }
            }
         }
         break;

      case 2: // 4 Nachkommastellen
         diffStep = 0.1;

         if ((maxPrice - minPrice) / diffStep <= 3) {
            diffStep = 0.05;
            if ((maxPrice - minPrice) / diffStep <= 3) {
               diffStep = 0.025;
               if ((maxPrice - minPrice) / diffStep <= 3) {
                  diffStep = 0.01;
                  if ((maxPrice - minPrice) / diffStep <= 3) {
                     diffStep = 0.005;
                  }
               }
            }
         }
         if ((maxPrice - minPrice) / diffStep >= 9) {
            diffStep = 0.25;
            if ((maxPrice - minPrice) / diffStep >= 9) {
               diffStep = 0.5;
               if ((maxPrice - minPrice) / diffStep >= 9) {
                  diffStep = 1.0;
                  if ((maxPrice - minPrice) / diffStep >= 9) {
                     diffStep = 5.0;
                  }
               }
            }
         }
         break;

      case 3: // 5 Nachkommastellen
         diffStep = 0.01;

         if ((maxPrice - minPrice) / diffStep <= 3) {
            diffStep = 0.005;
            if ((maxPrice - minPrice) / diffStep <= 3) {
               diffStep = 0.0025;
               if ((maxPrice - minPrice) / diffStep <= 3) {
                  diffStep = 0.001;
                  if ((maxPrice - minPrice) / diffStep <= 3) {
                     diffStep = 0.0005;
                  }
               }
            }
         }
         if ((maxPrice - minPrice) / diffStep >= 9) {
            diffStep = 0.025;
            if ((maxPrice - minPrice) / diffStep >= 9) {
               diffStep = 0.05;
               if ((maxPrice - minPrice) / diffStep >= 9) {
                  diffStep = 0.1;
                  if ((maxPrice - minPrice) / diffStep >= 9) {
                     diffStep = 0.25;
                  }
               }
            }
         }
         break;

      default: // 2 Nachkommastellen

         diffStep = 100;

         if ((maxPrice - minPrice) / diffStep <= 3) {
            diffStep = 50;
            if ((maxPrice - minPrice) / diffStep <= 3) {
               diffStep = 25;
               if ((maxPrice - minPrice) / diffStep <= 3) {
                  diffStep = 10;
                  if ((maxPrice - minPrice) / diffStep <= 3) {
                     diffStep = 5;
                     if ((maxPrice - minPrice) / diffStep <= 3) {
                        diffStep = 2.5;
                        if ((maxPrice - minPrice) / diffStep <= 3) {
                           diffStep = 1;
                        }
                     }
                  }
               }
            }
         }
         if ((maxPrice - minPrice) / diffStep >= 9) {
            diffStep = 250;
            if ((maxPrice - minPrice) / diffStep >= 9) {
               diffStep = 500;
               if ((maxPrice - minPrice) / diffStep >= 9) {
                  diffStep = 1000;
                  if ((maxPrice - minPrice) / diffStep >= 9) {
                     diffStep = 2500;
                     if ((maxPrice - minPrice) / diffStep >= 9) {
                        diffStep = 5000;
                        if ((maxPrice - minPrice) / diffStep >= 9) {
                           diffStep = 10000;
                        }
                     }
                  }
               }
            }
         }
   }

   if (oldDiffStep != diffStep) {
      return false; // neu zeichnen
   }
   return true; // alles gut
}

//+------------------------------------------------------------------+
// Berechne, ob die Preis-Linie eine Hauptlinie ist
//+------------------------------------------------------------------+
bool calculateBold(double walk)
{
   bool st = false;

   if (diffStep >= 1) st = ((int)MathAbs(walk-center) % (int)(every * diffStep)) == 0 ? true : false;
   // (walk - center) % (every * diffStep)
   if (diffStep < 1) st = (int)(MathRound(10000 * MathAbs(walk-center))) % (int)(MathRound(10000 * every * diffStep)) == 0 ? true : false;

   return st;
}

//+------------------------------------------------------------------+
// Berechne die erste Linie, von der aus nach oben und unten gezeichnet wird
//+------------------------------------------------------------------+
double calculateCenter()
{
   double maxPrice = ChartGetDouble(0,CHART_PRICE_MAX);
   double minPrice = ChartGetDouble(0,CHART_PRICE_MIN);
   double existingCenter = ObjectGetDouble(0, hLabel, OBJPROP_PRICE); // gibt es die wichtigste Linie schon?

   if (existingCenter > 0) center = existingCenter;

   if (center == 0.0) {
      center = NormalizeDouble((maxPrice + minPrice)/2, diffDigits); // Forex

      if (diffStep >= 1) {
         center = (int)center - ((int)center % (int)(diffStep*2)); // Rest abziehen z.B. für DAX
      }
      if (diffStep <= 0.25) { // && diffStep >= 0.005
         center = diffStep * (int)MathRound(1/diffStep * center); // Korrektur für z.B 0.77400 und 0.77900
      }

      if (diffStep < 0.01) {
         center = NormalizeDouble(center, 2); // 0.001 bis 0.005

      } else if (diffStep < 0.1) {
         center = NormalizeDouble(center, 1); // 0.01 bis 0.05

      } else if (diffStep < 1.0) {
         center = NormalizeDouble(center, 0); // 0.1 bis 0.5
      }

      if (diffStep == 2.5) {
         center = (int)center - ((int)center % 5); // XAUUSD
      }
   }
   //if (existingCenter != center) out((string)existingCenter + " center " + (string)center);

   return center;
}

//+------------------------------------------------------------------+
// Zeichne horizontale Linie
//+------------------------------------------------------------------+
void DrawHLine(string label, double price, datetime timeShift, bool strong = false)
{
   if (price == 0.0 && label == hLabel) return;

   /*if (ObjectFind(0, label) >= 0) { // dauert länger
      return;
   }*/

   ObjectCreate(0, label, OBJ_HLINE, 0, timeShift, NormalizeDouble(price, _Digits));
   ObjectSetInteger(0, label, OBJPROP_HIDDEN, !develop);
   ObjectSetInteger(0, label, OBJPROP_SELECTABLE, false);
   ObjectSetString(0, label, OBJPROP_TOOLTIP, DoubleToString(price, _Digits));

   if (strong) {
      ObjectSetInteger(0, label, OBJPROP_STYLE, horizontalStyle1);
      ObjectSetInteger(0, label, OBJPROP_WIDTH, horizontalWidth1);
      ObjectSetInteger(0, label, OBJPROP_COLOR, horizontalColor1);
      ObjectSetInteger(0, label, OBJPROP_BACK, horizontalBackground1);
   } else {
      ObjectSetInteger(0, label, OBJPROP_STYLE, horizontalStyle2);
      ObjectSetInteger(0, label, OBJPROP_WIDTH, horizontalWidth2);
      ObjectSetInteger(0, label, OBJPROP_COLOR, horizontalColor2);
      ObjectSetInteger(0, label, OBJPROP_BACK, horizontalBackground2);
   }
   // Strategietester zu unruhig
   if (MQLInfoInteger(MQL_TESTER)) {
      ObjectSetInteger(0, label, OBJPROP_BACK, true);
   }
}

//+------------------------------------------------------------------+
// Zeichne vertikale Linie
//+------------------------------------------------------------------+
void DrawVLine(string label, double price, datetime timeShift, bool strong = false)
{
   /*if (ObjectFind(0, label) >= 0) { // dauert länger
      return;
   }*/
   vLines++;

   ObjectCreate(0, label, OBJ_VLINE, 0, timeShift, price);
   ObjectSetInteger(0, label, OBJPROP_HIDDEN, !develop);
   ObjectSetInteger(0, label, OBJPROP_SELECTABLE, false);

   if (strong) {
      ObjectSetInteger(0, label, OBJPROP_STYLE, vertikalStyle1);
      ObjectSetInteger(0, label, OBJPROP_WIDTH, vertikalWidth1);
      ObjectSetInteger(0, label, OBJPROP_COLOR, vertikalColor1);
      ObjectSetInteger(0, label, OBJPROP_BACK,  vertikalBackground1);
   } else {
      ObjectSetInteger(0, label, OBJPROP_STYLE, vertikalStyle2);
      ObjectSetInteger(0, label, OBJPROP_WIDTH, vertikalWidth2);
      ObjectSetInteger(0, label, OBJPROP_COLOR, vertikalColor2);
      ObjectSetInteger(0, label, OBJPROP_BACK,  vertikalBackground2);
   }

   if (TimeMinute(timeShift) == 0 && TimeHour(timeShift) == 0) {
      ObjectSetString(0, label, OBJPROP_TOOLTIP, TimeToString(timeShift, TIME_DATE));
   } else {
      ObjectSetString(0, label, OBJPROP_TOOLTIP, TimeToString(timeShift, TIME_DATE | TIME_MINUTES));
   }
}

//+------------------------------------------------------------------+
// Schreibe Information
//+------------------------------------------------------------------+
void ChartWrite(string name,
                string comment,
                int    x_distance,
                int    y_distance)
{
   // Label bereits vorhanden?
   if (ObjectFind(0, name) < 0) {

      // erstellen
      if (!ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0)) {
         return;
      }
      ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSetInteger(0, name, OBJPROP_FONTSIZE, infoSize);
      ObjectSetString(0,  name, OBJPROP_FONT, "Lucida Console");
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x_distance);
      ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y_distance);
   }

   // aktualisieren
   ObjectSetInteger(0, name, OBJPROP_COLOR, infoColor);
   ObjectSetString(0,  name, OBJPROP_TEXT, comment);
}

//+------------------------------------------------------------------+
// pointToPip()
//+------------------------------------------------------------------+
// Wenn 1-, 2- oder 0-stellig quotiert wird, ist 1 Pip = 1.0
// Wenn 3- quotiert wird, ist 1 Pip = 0.01 
// Wenn 5- oder 4-stellig quotiert wird, ist 1 Pip = 0.0001
//+------------------------------------------------------------------+
double pointToPip()
{
   if (_Digits <= 2) return 1.0;
   if (_Digits == 3) return 0.01;
   return 0.0001;
}

//+------------------------------------------------------------------+
// Logge Information, nur wenn eingeschaltet (gut bei Nutzung in mehreren Charts)
//+------------------------------------------------------------------+
void out(string text)
{
   if (develop) Print(_Symbol, " ----------- ", text, " ----------- ");
}
//+------------------------------------------------------------------+

#ifdef __MQL5__

int TimeDay(datetime date) {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.day);
}

int TimeDayOfWeek(datetime date) {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.day_of_week);
}

int TimeDayOfYear(datetime date) {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.day_of_year);
}

int TimeHour(datetime date) {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.hour);
}

int TimeMinute(datetime date) {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.min);
}

int TimeMonth(datetime date) {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.mon);
}

int TimeSeconds(datetime date) {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.sec);
}

int TimeYear(datetime date) {
   MqlDateTime tm;
   TimeToStruct(date,tm);
   return(tm.year);
}

#define DEFINE_TIMESERIE(NAME,FUNC,T)                                                                         \
  class CLASS##NAME                                                                                           \
  {                                                                                                           \
  public:                                                                                                     \
    static T Get(const string Symb,const int TimeFrame,const int iShift)                                      \
    {                                                                                                         \
      T tValue[];                                                                                             \
                                                                                                              \
      return((Copy##FUNC((Symb == NULL) ? _Symbol : Symb, _Period, iShift, 1, tValue) > 0) ? tValue[0] : -1); \
    }                                                                                                         \
                                                                                                              \
    T operator[](const int iPos) const                                                                        \
    {                                                                                                         \
      return(CLASS##NAME::Get(_Symbol, _Period, iPos));                                                       \
    }                                                                                                         \
  };                                                                                                          \
                                                                                                              \
  CLASS##NAME NAME;

DEFINE_TIMESERIE(Volume, TickVolume,long)
DEFINE_TIMESERIE(Time, Time, datetime)
DEFINE_TIMESERIE(Open, Open, double)
DEFINE_TIMESERIE(High, High, double)
DEFINE_TIMESERIE(Low, Low, double)
DEFINE_TIMESERIE(Close, Close, double)

#endif // __MQL5__

//+------------------------------------------------------------------+

Externe Links

Bevor ich mein eigenes Grid gebaut habe, war das folgende bei mir im MT4 im Einsatz:

MQL4 AlterGrid v2 Indikator

Möchtest du MQL programmieren lernen? Dieser Kurs macht wirklich Spaß und kostet nur einen Euro. Mein Prädikat: ausgezeichnet und auch nicht langweilig mit Vorwissen:

MQL5 Einsteigerkurs
MQL4 Einsteigerkurs