Back to MetaTrader 5 MQL5 for CFD Traders
Part 2

Arrays, Structures, and Objects

MqlRates, MqlTradeRequest, dynamic arrays, and just enough OOP to read the standard library.

Intermediate10 min readBeginner → AdvancedLesson 09 / 17
Try it in MetaEditor
MqlRates, a custom struct, and dynamic arrays

Save as MQL5/Scripts/Lesson9Structures.mq5. It copies bars into a struct array, builds a custom struct, and sizes a dynamic array — the patterns behind every EA that follows.

//+------------------------------------------------------------------+
//| Lesson 9 - MqlRates, custom structs, dynamic arrays              |
//+------------------------------------------------------------------+
#property copyright "Strategist Academy"
#property version   "1.00"

// A tiny value object - MQL5 lets you group related fields like this.
struct Level
{
   double price;
   string label;
   bool   isSupport;
};

void OnStart()
{
   int bars = 50;

   // --- MqlRates: one struct per bar ---------------------------------
   MqlRates rates[];
   ArraySetAsSeries(rates, true);            // 0 = newest

   int copied = CopyRates(_Symbol, _Period, 0, bars, rates);
   if(copied != bars)
   {
      Print("CopyRates returned ", copied, " of ", bars, ". Error: ", GetLastError());
      return;
   }

   double hi = rates[1].high;
   double lo = rates[1].low;                 // bar 0 is still forming
   for(int i = 2; i < bars && !IsStopped(); i++)
   {
      hi = MathMax(hi, rates[i].high);
      lo = MathMin(lo, rates[i].low);
   }

   Print("Newest completed bar close: ", DoubleToString(rates[1].close, _Digits));
   Print("Bar time: ", TimeToString(rates[1].time, TIME_DATE | TIME_MINUTES));

   // --- Custom struct -------------------------------------------------
   Level levels[2];
   levels[0].price     = hi;
   levels[0].label     = "50-bar high";
   levels[0].isSupport = false;
   levels[1].price     = lo;
   levels[1].label     = "50-bar low";
   levels[1].isSupport = true;

   for(int i = 0; i < 2; i++)
      Print(levels[i].label, ": ", DoubleToString(levels[i].price, _Digits),
            "   support=", levels[i].isSupport ? "yes" : "no");

   // --- Dynamic array -------------------------------------------------
   double closes[];
   ArrayResize(closes, bars);
   for(int i = 0; i < bars; i++)
      closes[i] = rates[i].close;

   Print("closes[0] (newest) = ", DoubleToString(closes[0], _Digits));
   Print("closes[", bars - 1, "] (oldest) = ", DoubleToString(closes[bars - 1], _Digits));
   Print("Series order set on rates? ", ArrayGetAsSeries(rates) ? "yes" : "no");
}
To run it
  1. 1. Open MetaEditor from MT5 (press F4), and pick the folder this program belongs in — Experts, Indicators, or Scripts.
  2. 2. Create a new file, paste this over it, then press F7 to compile. Fix anything the Errors tab reports.
  3. 3. Back in MT5, drag it onto a chart — or open the Strategy Tester if it is an Expert Advisor.

Structures you will meet constantly

MQL5 ships a set of structs that are the API's currency. Learn these five and most of the documentation becomes readable:

  • MqlRates — one bar: time, open, high, low, close, tick_volume, spread, real_volume.
  • MqlTick — one tick: bid, ask, last, volume, time_msc, flags.
  • MqlTradeRequest — the order you want to send.
  • MqlTradeResult — what the server actually did.
  • MqlDateTime — a broken-out calendar time.

You can also declare your own with struct — handy for grouping a price with a label, as in this lesson.

Dynamic arrays and ArrayResize

Declare an empty array with double arr[]; and size it with ArrayResize(arr, n). Many API functions resize for you — CopyRates does — but if you are building one yourself, resize first.

ArraySetAsSeries decides your indexing

Call it before copying if you want index 0 to be the newest bar. Call it after and you have already filled the array in the other order. Getting this wrong produces an indicator that appears to work but is shifted or reversed — check it first when values look off.

Classes, briefly

MQL5 supports classes: private/public sections, constructors, destructors, inheritance. You do not need to write one to be productive, but you do need to read them, because the entire standard library (CTrade, CPositionInfo, CSymbolInfo) is class-based. Instantiate, call a method, move on.

Strings are objects, not char arrays

Unlike C, MQL5 strings handle their own memory. Concatenate with +, compare with == or StringCompare, and do not worry about buffers.

What you just did

Lesson 09 of 17 in MetaTrader 5 MQL5 for CFD Traders. When you have run the examples or read the section, tick it off and move to the next lesson.