--- applyTo: "**/*.mq5,**/*.mqh" --- # CRITICAL MQL5 Syntax Rules (Mandatory for All MQL5 Code) ## ⚠️ Overview MQL5 is **NOT** standard C++. It has critical syntax differences that cause compilation errors if ignored. These rules are mandatory for all _Thivyam MQL5 development. --- ## 1. Pointer Member Access ❌ → ✅ ### Rule **ALWAYS use dot operator (`.`) for pointer member access** **NEVER use arrow operator (`->`)** ### Why MQL5 parser treats `->` as two separate operators: `-` (minus) and `>` (greater-than), causing parser errors. ### Examples ```mql5 // ✅ CORRECT CObject *ptr = GetObject(); ptr.Method(); ptr.SetValue(10); CZoneState *zone = ctx.Zone(); // Returns pointer zone.IsActive(); // Use dot operator // ❌ WRONG - Causes compilation errors ptr->Method(); // Error: 'operand expected' zone->IsActive(); // Error: 'undeclared identifier' ``` ### Error Messages You'll See - `'>' - operand expected` - `undeclared identifier` - `')' - expression expected` - `'Method' - object pointer expected` --- ## 2. Loop Variable Declaration ❌ → ✅ ### Rule **NEVER declare variables inside for-loop initializers** **ALWAYS declare loop counters BEFORE the for statement** ### Why MQL5 does not support C99/C++11 style variable declaration in for-loop initializers. ### Examples ```mql5 // ✅ CORRECT int i; for(i = 0; i < 10; i++) { Print(i); } // Multiple loops int i, j; for(i = 0; i < rows; i++) { for(j = 0; j < cols; j++) { matrix[i][j] = 0; } } // ❌ WRONG - Causes compilation errors for(int i = 0; i < 10; i++) // Error: undeclared identifier { Print(i); } ``` ### Additional Rules - Use **post-increment** (`i++`) not pre-increment (`++i`) for better compatibility - Avoid `const` on loop bound variables: use `int total` not `const int total` ### Error Messages You'll See - `undeclared identifier` - `'i' - some operator expected` - `expression expected` --- ## 3. Array Declarations ❌ → ✅ ### Rule **Use dynamic arrays (`Type[]`) for array manipulation functions** **Static arrays (`Type[N]`) cannot be used with `ArraySetAsSeries()` and similar functions** ### Why MQL5 distinguishes between static (fixed-size) and dynamic (variable-size) arrays, and many built-in functions only work with dynamic arrays. ### Examples ```mql5 // ✅ CORRECT - Dynamic arrays MqlRates rates[]; ArraySetAsSeries(rates, true); CopyRates(_Symbol, PERIOD_H1, 0, 100, rates); double buffer[]; ArrayResize(buffer, 50); // ❌ WRONG - Static arrays MqlRates rates[100]; ArraySetAsSeries(rates, true); // Error: cannot be used for static allocated array ``` ### Special Cases ```mql5 // CArrayObj from standard library CArrayObj m_array; // ✅ CORRECT - Auto-initializes CArrayObj() { // No initialization needed } // ❌ WRONG - Create() doesn't exist CArrayObj() { m_array.Create(); // Error: undeclared identifier } ``` ### Error Messages You'll See - `cannot be used for static allocated array` - `undeclared identifier` (for `.Create()`) --- ## 4. Function Parameters ❌ → ✅ ### Rule **Avoid `const Type ¶meter` when passing temporary values** **Use pass-by-value (`const Type parameter`) instead** ### Why Temporary values (from ternary operators, function returns) cannot bind to reference parameters in MQL5. ### Examples ```mql5 // ✅ CORRECT void CreateLabel(const string text) { ObjectSetString(0, "label", OBJPROP_TEXT, text); } // Called with ternary expression CreateLabel(minimized ? "" : fullText); // Works fine // ❌ WRONG void CreateLabel(const string &text) // Reference parameter { ObjectSetString(0, "label", OBJPROP_TEXT, text); } CreateLabel(minimized ? "" : fullText); // Error: parameter passed as reference ``` ### When to Use References - Use references for large structures that you DON'T create on-the-fly - Use value parameters for strings and small types ### Error Messages You'll See - `parameter passed as reference, variable expected` --- ## 5. Object Property Constants ❌ → ✅ ### Rule **Property names must match MQL5 documentation exactly** **Common mistakes have similar but incorrect names** ### Critical Property Names | ❌ WRONG | ✅ CORRECT | Object Type | |----------|------------|-------------| | `OBJPROP_FONT_SIZE` | `OBJPROP_FONTSIZE` | All text objects | | `OBJPROP_WIDTH` | `OBJPROP_XSIZE` | Rectangle Label | | `OBJPROP_HEIGHT` | `OBJPROP_YSIZE` | Rectangle Label | | `OBJPROP_ZORDER` | _(doesn't exist)_ | All objects | ### Examples ```mql5 // ✅ CORRECT ObjectSetInteger(0, "label", OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, "rect", OBJPROP_XSIZE, 200); ObjectSetInteger(0, "rect", OBJPROP_YSIZE, 100); // ❌ WRONG ObjectSetInteger(0, "label", OBJPROP_FONT_SIZE, 10); // Underscore ObjectSetInteger(0, "rect", OBJPROP_WIDTH, 200); // Doesn't exist ObjectSetInteger(0, "rect", OBJPROP_HEIGHT, 100); // Doesn't exist ObjectSetInteger(0, "rect", OBJPROP_ZORDER, 0); // Doesn't exist ``` ### Error Messages You'll See - `undeclared identifier` - `cannot convert enum` - `wrong parameters count` --- ## 6. Type Casting ❌ → ✅ ### Rule **Avoid spaces between cast closing paren and pointer asterisk** **Store cast results in intermediate variables to avoid parser confusion** ### Examples ```mql5 // ✅ CORRECT - No space, intermediate variable CObject *obj = m_array.At(i); CH4ZoneContext *ctx = (CH4ZoneContext*)obj; CZoneState *zone = ctx.Zone(); // ❌ WRONG - Space in cast CH4ZoneContext *ctx = (CH4ZoneContext *)obj; // Can confuse parser // ❌ WRONG - Chained operations CZoneState *zone = ((CH4ZoneContext*)m_array.At(i)).Zone(); // Parser errors ``` --- ## 7. Const Correctness ❌ → ✅ ### Rule **MQL5 is stricter about const than C++** **Avoid const on simple local variables and loop bounds** ### Examples ```mql5 // ✅ CORRECT uint total = PositionsTotal(); uint i; for(i = 0; i < total; i++) // ⚠️ POTENTIALLY PROBLEMATIC const uint total = PositionsTotal(); // May cause issues in some contexts // ✅ CORRECT - Use const for true constants const double PI = 3.14159; const int MAX_RETRIES = 3; ``` --- ## 8. Position Functions (CRITICAL) ❌ → ✅ ### Rule **`PositionSelectByIndex()` does NOT exist in MQL5** **Use `PositionGetTicket(index)` or `PositionGetSymbol(index)` instead** ### Why This is a common error from MT4-to-MT5 migration or incorrect examples. The function simply doesn't exist in the MQL5 API. ### Examples ```mql5 // ✅ CORRECT - Method 1: Get ticket first int total = PositionsTotal(); int i; for(i = 0; i < total; i++) { ulong ticket = PositionGetTicket(i); if(ticket == 0) continue; // Now access position properties long magic = PositionGetInteger(POSITION_MAGIC); double volume = PositionGetDouble(POSITION_VOLUME); } // ✅ CORRECT - Method 2: Get symbol (also selects position) for(i = 0; i < total; i++) { string symbol = PositionGetSymbol(i); if(symbol == "") continue; // Access properties for currently selected position } // ❌ WRONG - Function doesn't exist! for(i = 0; i < total; i++) { if(!PositionSelectByIndex(i)) // Compilation error! continue; } ``` ### Error Messages You'll See - `undeclared identifier` (at the function name) - `'i' - some operator expected` (at the parameter) - Error column numbers pointing inside the function call ### Why Errors Are Cryptic Because the compiler doesn't recognize `PositionSelectByIndex`, it tries to parse the entire line as an expression, producing confusing errors about operators and variables. --- ## 9. Quick Reference Checklist Before committing MQL5 code, verify: - [ ] All pointer member access uses `.` not `->` - [ ] All loop variables declared before `for` statement - [ ] NO use of `PositionSelectByIndex()` - use `PositionGetTicket()` instead - [ ] All loop increments use `i++` not `++i` - [ ] Dynamic arrays used with `ArraySetAsSeries()`, `CopyRates()` - [ ] Function parameters avoid `const string &` for temporaries - [ ] Object properties use correct names (verify in docs) - [ ] No `CArrayObj.Create()` calls - [ ] Type casts have no spaces: `(Type*)` not `(Type *)` - [ ] No `OBJPROP_ZORDER`, `OBJPROP_WIDTH`, `OBJPROP_HEIGHT` - [ ] Use `OBJPROP_FONTSIZE` not `OBJPROP_FONT_SIZE` --- ## 10. Compilation Verification Always compile in MetaEditor before considering code complete: ```bash # Windows PowerShell & "C:\Program Files\MetaTrader 5\MetaEditor64.exe" /compile:"path\to\file.mq5" ``` **Expected Result:** 0 errors, 0 warnings --- ## 11. Common Error Patterns If you see these errors, check these causes: | Error Message | Most Likely Cause | Fix | |---------------|-------------------|-----| | `'>' - operand expected` | Using `->` operator | Change to `.` | | `undeclared identifier` (at loop) | Variable declared in for-loop | Declare before loop | | `undeclared identifier` + `operator expected` | Non-existent function like `PositionSelectByIndex()` | Use `PositionGetTicket(i)` | | `cannot be used for static allocated array` | Static array with `ArraySetAsSeries()` | Use dynamic array `[]` | | `parameter passed as reference` | Passing temporary to `&` param | Use value parameter | | `undeclared identifier` (property) | Wrong property name | Check MQL5 docs | --- ## 12. Resources - **MQL5 Documentation:** https://www.mql5.com/en/docs - **Object Properties:** https://www.mql5.com/en/docs/constants/objectconstants/enum_object_property - **Array Functions:** https://www.mql5.com/en/docs/array --- **Last Updated:** 2025-11-03 **Validated Against:** MQL5 Build 3960+