2026-04-23 21:40:38 +00:00
# MQL5 Conventions - TSN Ecosystem
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
> Standards and best practices for writing MQL5 code in the TSN ecosystem
2026-04-23 21:22:52 +00:00
---
2026-04-23 21:40:38 +00:00
## Table of Contents
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
1. [Naming ](#naming )
2. [File Structure ](#file-structure )
3. [Code Style ](#code-style )
4. [EA Structure ](#ea-structure )
5. [Comments and Documentation ](#comments-and-documentation )
6. [Language ](#language )
2026-04-23 21:22:52 +00:00
---
2026-04-23 21:40:38 +00:00
## Naming
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
### Classes
- **Prefix:** `C`
- **Type:** `PascalCase`
- **Examples:** `CMyClass` , `CIndicator` , `COrderBlock` , `CRiskManagement`
2026-04-23 21:22:52 +00:00
```mql5
class CStrategy {
2026-04-23 21:40:38 +00:00
// implementation
2026-04-23 21:22:52 +00:00
};
```
### Interfaces
2026-04-23 21:40:38 +00:00
- **Prefix:** `I`
- **Type:** `PascalCase`
- **Examples:** `IStrategy` , `INotifiable`
2026-04-23 21:22:52 +00:00
```mql5
interface IStrategy {
void OnTick();
};
```
2026-04-23 21:40:38 +00:00
### Structures
- **Prefix:** None
- **Type:** `PascalCase`
- **Examples:** `Bar` , `OrderData` , `SignalInfo`
2026-04-23 21:22:52 +00:00
```mql5
struct OrderData {
ulong ticket;
double price;
datetime time;
};
```
2026-04-23 21:40:38 +00:00
### Unions
- **Prefix:** None
- **Type:** `PascalCase`
2026-04-23 21:22:52 +00:00
```mql5
union DataValue {
double dval;
int ival;
};
```
2026-04-23 21:40:38 +00:00
### Functions
- **Prefix:** None
- **Type:** `PascalCase`
- **Examples:** `CalculateSma()` , `GetSupportLevel()` , `ApplyRiskManagement()`
2026-04-23 21:22:52 +00:00
```mql5
double CalculateSma(const double &series[], int period) {
2026-04-23 21:40:38 +00:00
// implementation
2026-04-23 21:22:52 +00:00
}
```
2026-04-23 21:40:38 +00:00
### Member Variables (Class)
- **Prefix:** `m_`
- **Type:** `snake_case`
- **Examples:** `m_period` , `m_buffer` , `m_is_active`
2026-04-23 21:22:52 +00:00
```mql5
class CIndicator {
private:
int m_period;
double m_buffer[];
bool m_is_active;
};
```
2026-04-23 21:40:38 +00:00
### Global Variables
- **Prefix:** `g_`
- **Type:** `snake_case`
- **Examples:** `g_risk` , `g_order_block` , `g_bar_manager`
2026-04-23 21:22:52 +00:00
```mql5
CRiskManagement* g_risk;
COrderBlockTick g_ob;
CBarManager g_bar_manager;
```
2026-04-23 21:40:38 +00:00
### Local Variables
- **Prefix:** None
- **Type:** `snake_case`
- **Examples:** `current_price` , `support_level` , `trade_signal`
2026-04-23 21:22:52 +00:00
```mql5
void OnTick() {
double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
int period = 14;
bool is_valid = true;
}
```
2026-04-23 21:40:38 +00:00
### Input Parameters
- **Prefix:** `Inp`
- **Type:** `PascalCase`
- **Examples:** `InpPeriod` , `InpStopLoss` , `InpTakeProfitRatio`
2026-04-23 21:22:52 +00:00
```mql5
input int InpPeriod = 14;
input double InpStopLoss = 50.0;
input string InpTelegramToken = "your_token";
```
2026-04-23 21:40:38 +00:00
### Constants \ Defines \ Enums
- **Type:** `UPPER_SNAKE_CASE`
- **Examples:** `MAX_ITERATIONS` , `DEFAULT_PERIOD` , `VERSION_NUMBER`
2026-04-23 21:22:52 +00:00
```mql5
const int DEFAULT_PERIOD = 20;
const double MAX_SPREAD = 0.5;
#define VERSION_NUMBER 100
enum ENUM_RISK_TYPE
{
RISK_TYPE_PERCENTAGE,
RISK_TYPE_MONEY
};
```
2026-04-23 21:40:38 +00:00
### Context Resolution
In case libraries like winapi or internal class/global functions conflict with native functions, it is recommended to use `::` to indicate to the compiler that it should call the native function. For library functions like kernel32, for example `GetLastError()` , you can resolve the context as `kernel32::GetLastError()`
2026-04-23 21:22:52 +00:00
---
2026-04-23 21:40:38 +00:00
## File Structure
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
### Recommended Hierarchy for EAs
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
For **simple or moderately complex ** EAs, it is recommended to divide them into the following files:
2026-04-23 21:22:52 +00:00
```
EA_Name/
2026-04-23 21:40:38 +00:00
├── Global.mqh (Global initialization - ALWAYS FIRST)
├── Defines.mqh (Includes and global variables)
├── Functions.mqh (Helper functions)
├── Main.mqh (Main logic/classes)
└── EA_Name.mq5 (Main event)
2026-04-23 21:22:52 +00:00
```
2026-04-23 21:40:38 +00:00
### Include Order
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
**Always** include `Global.mqh` first to avoid "Invalid Pointer" errors in global instances:
2026-04-23 21:22:52 +00:00
```mql5
// Defines.mqh
2026-04-23 21:40:38 +00:00
#include "Global.mqh" // ALWAYS FIRST
2026-04-23 21:22:52 +00:00
#include <TSN\\MQLArticles\\Strategy\\Main.mqh>
#include "Functions.mqh"
#include "Main.mqh"
```
```mql5
// EA_Name.mq5
2026-04-23 21:40:38 +00:00
#include "Defines.mqh" // Already contains Global.mqh
2026-04-23 21:22:52 +00:00
```
---
2026-04-23 21:40:38 +00:00
## Code Style
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
### MQL5 IDE Configuration
2026-04-23 21:22:52 +00:00
**Tools → Options → Stylizer:**
2026-04-23 21:40:38 +00:00
| Option | Value |
2026-04-23 21:22:52 +00:00
|--------|-------|
2026-04-23 21:40:38 +00:00
| Style | MetaQuotes |
| Replace tabs with spaces | Yes |
| Remove empty lines | No |
| Insert spaces after comma/semicolon | Yes |
| Insert spaces around operators | Yes |
2026-04-23 21:22:52 +00:00
**Tools → Options → General:**
2026-04-23 21:40:38 +00:00
| Option | Value |
2026-04-23 21:22:52 +00:00
|--------|-------|
2026-04-23 21:40:38 +00:00
| Tab (characters) | 2 |
| Insert spaces | Yes |
| Insert () and {} ) ] " ' | Yes |
| Highlight paired parentheses | Yes |
| Highlight current line | Yes |
| Enable clipboard history | Yes |
| Auto name list | Yes |
| Auto indent | Yes |
| Auto parameters | Yes |
| Line numbers | Yes |
### Keyboard Shortcuts
- **Format code:** `CTRL + ,` , use it always when you finish coding something
- **Insert function/class/general section/include header:** `CTRL + .` , use before defining a class or defines\enums\structs, functions:
2026-04-23 21:22:52 +00:00
```mql5
//+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
#include "Defines.mqh"
//+------------------------------------------------------------------+
//| Defines |
//+------------------------------------------------------------------+
#define MAX_POINTS (10)
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CRect
{
public:
CRect() {}
~CRect() {}
void Draw();
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CRect::Draw
{
2026-04-23 21:40:38 +00:00
// Logic....
2026-04-23 21:22:52 +00:00
}
```
2026-04-23 21:40:38 +00:00
### Section Separation and Internal Comments
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
Use `//---` to divide logical sections within code blocks:
2026-04-23 21:22:52 +00:00
```mql5
void OnInit() {
2026-04-23 21:40:38 +00:00
//--- Initialization
2026-04-23 21:22:52 +00:00
g_risk = new CRiskManagement();
g_ob.init(Symbol(), PERIOD_H1);
//---
2026-04-23 21:40:38 +00:00
return INIT_SUCCEEDED;
2026-04-23 21:22:52 +00:00
}
}
```
2026-04-23 21:40:38 +00:00
Use `//` to comment certain parts. Also, if the text is no longer visible in a single line and requires HSCROLL, then place it above:
2026-04-23 21:22:52 +00:00
```mql5
void OnInit() {
2026-04-23 21:40:38 +00:00
//--- Initialization
g_risk = new CRiskManagement(); // Dynamic instance of CRiskManagement (Short text here)
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
// ............................................................ Very long text above (approx covers 60-70%)
2026-04-23 21:22:52 +00:00
g_ob.init(Symbol(), PERIOD_H1);
//---
2026-04-23 21:40:38 +00:00
return INIT_SUCCEEDED;
2026-04-23 21:22:52 +00:00
}
}
```
2026-04-23 21:40:38 +00:00
### Complete Visual Separation
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
For important sections, use the complete header:
2026-04-23 21:22:52 +00:00
```mql5
//+------------------------------------------------------------------+
//| Global variables |
//+------------------------------------------------------------------+
CRiskManagement* g_risk;
COrderBlockTick g_ob;
//+------------------------------------------------------------------+
2026-04-23 21:40:38 +00:00
//| Main Signal Processing Function |
2026-04-23 21:22:52 +00:00
//+------------------------------------------------------------------+
2026-04-23 21:40:38 +00:00
void ProcessSignals() {
// logic
2026-04-23 21:22:52 +00:00
}
```
2026-04-23 21:40:38 +00:00
## EA Structure
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
### Recommended Flow
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
1. **Global.mqh ** - Initial configuration (BarManager, base libraries)
2. **Defines.mqh ** - Includes and global variables
3. **Functions.mqh ** - Helper functions
4. **Main.mqh ** - Strategy logic (classes)
5. **EA.mq5 ** - EA events
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
### Example: Global.mqh
2026-04-23 21:22:52 +00:00
```mql5
//+------------------------------------------------------------------+
//| Global.mqh |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, nique_372"
#property link "https://www.mql5.com/es/users/nique_372"
#property strict
2026-04-23 21:40:38 +00:00
// Base libraries that require immediate initialization
2026-04-23 21:22:52 +00:00
#include <TSN\\TimeUtils\\TimeUtils.mqh>
#include <TSN\\ICTLibrary\\Core.mqh>
//---
2026-04-23 21:40:38 +00:00
// Configure Bar Manager (critical to avoid Invalid Pointer)
2026-04-23 21:22:52 +00:00
CBarManager* p_bar_manager;
2026-04-23 21:40:38 +00:00
void InitGlobal() {
2026-04-23 21:22:52 +00:00
p_bar_manager = new CBarManager(_Symbol, _Period);
if (p_bar_manager == NULL) {
2026-04-23 21:40:38 +00:00
Print("Error: Could not initialize Bar Manager");
2026-04-23 21:22:52 +00:00
}
}
```
2026-04-23 21:40:38 +00:00
### Example: Defines.mqh
2026-04-23 21:22:52 +00:00
```mql5
//+------------------------------------------------------------------+
//| Defines.mqh |
//+------------------------------------------------------------------+
2026-04-23 21:40:38 +00:00
#include "Global.mqh" // FIRST
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
// Extra dependencies, although global should generally include what's necessary
2026-04-23 21:22:52 +00:00
#include <TSN\\MQLArticles\\Strategy\\Main.mqh>
//---
2026-04-23 21:40:38 +00:00
// Global variables
2026-04-23 21:22:52 +00:00
CRiskManagement* g_risk;
COrderBlockTick g_ob;
CStrategy* g_strategy;
//---
2026-04-23 21:40:38 +00:00
// Parameters
2026-04-23 21:22:52 +00:00
input int InpPeriod = 20;
input double InpRiskPercentage = 2.0;
input bool InpUseTelegram = true;
```
2026-04-23 21:40:38 +00:00
### Example: Main.mqh
2026-04-23 21:22:52 +00:00
```mql5
//+------------------------------------------------------------------+
//| Main.mqh |
//+------------------------------------------------------------------+
2026-04-23 21:40:38 +00:00
#include "Defines.mqh" // or Functions.mqh if applicable
2026-04-23 21:22:52 +00:00
class CMyStrategy : public CStrategy {
private:
int m_period;
double m_rsi_threshold;
public:
CMyStrategy(int InpPeriod, double InpThreshold) :
m_period(InpPeriod),
m_rsi_threshold(InpThreshold) {
}
void OnTick() override {
//---
2026-04-23 21:40:38 +00:00
// Logic
2026-04-23 21:22:52 +00:00
}
};
```
2026-04-23 21:40:38 +00:00
### Example: EA.mq5
2026-04-23 21:22:52 +00:00
```mql5
//+------------------------------------------------------------------+
//| MyTradingEA.mq5 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, nique_372"
2026-04-23 21:40:38 +00:00
#include "Main.mqh" // Contains Global.mqh
2026-04-23 21:22:52 +00:00
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
2026-04-23 21:40:38 +00:00
InitGlobal();
2026-04-23 21:22:52 +00:00
g_risk = new CRiskManagement(InpRiskPercentage);
g_strategy = new CMyStrategy(InpPeriod, 30.0);
if (g_risk == NULL || g_strategy == NULL) {
2026-04-23 21:40:38 +00:00
Print("Error in initialization");
2026-04-23 21:22:52 +00:00
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
g_strategy.OnTick();
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
delete g_strategy;
delete g_risk;
}
```
---
2026-04-23 21:40:38 +00:00
## Comments and Documentation
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
### Function Headers
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
In the TSN ecosystem, the documentation method varies depending on complexity and whether it's a product:
1. If it's a product, it's generally documented in the repository wiki (this also applies to free repositories)
2. If there's no wiki, it's generally documented in the code itself
2026-04-23 21:22:52 +00:00
```mql5
//+------------------------------------------------------------------+
2026-04-23 21:40:38 +00:00
//| Description.... |
2026-04-23 21:22:52 +00:00
//| Inputs: |
2026-04-23 21:40:38 +00:00
//| - series: double array where the series is located |
//| - period: calculation period |
//| Output: |
2026-04-23 21:22:52 +00:00
//| - Sma |
2026-04-23 21:40:38 +00:00
//| Notes: |
//| - Period must be greater than 0 |
2026-04-23 21:22:52 +00:00
//+------------------------------------------------------------------+
2026-04-23 21:40:38 +00:00
double CalculateSma(const double &series[], int period) {
2026-04-23 21:22:52 +00:00
double sum = 0.0;
for (int i = 0; i < period; i++) {
sum += series[i];
}
return sum / period;
}
2026-04-23 21:40:38 +00:00
And if it's on the wiki, a similar style to the MQL5 Docs is followed - one page per function... and what it receives, etc.
2026-04-23 21:22:52 +00:00
```
2026-04-23 21:40:38 +00:00
### File Header mqh (in case of EA, additional properties such as description, icon, etc. can be added)
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
Always include at the beginning:
2026-04-23 21:22:52 +00:00
2026-04-30 16:07:39 +00:00
```mql5
2026-04-23 21:22:52 +00:00
//+------------------------------------------------------------------+
2026-04-28 02:13:14 +00:00
//| <FILE_NAME>|
//| Copyright <YEAR>, <YOUR NAME>|
//| <URL> |
2026-04-23 21:22:52 +00:00
//+------------------------------------------------------------------+
2026-04-28 02:13:14 +00:00
#property copyright "Copyright <YEAR>, <YOUR NAME>"
#property link "<URL>"
2026-04-23 21:22:52 +00:00
#property strict
2026-04-30 16:07:16 +00:00
#ifndef REPONAME_PATHTOFILE
#define REPONAME_PATHTOFILE
#endif REPONAME_PATHTOFILE
2026-04-23 21:22:52 +00:00
```
2026-04-28 02:13:14 +00:00
**Placeholder Descriptions**
- **FILE_NAME**: Name of the mqh file
- **YEAR**: Current year
- **YOUR NAME**: Name of the code writer\org
- **URL**: Creator's URL, e.g.: [Website, MQL5 Profile, Personal Website, Github, etc..]
All these fields are defined before creating the file, some when creating the project, others in the file itself.
2026-04-23 21:22:52 +00:00
---
2026-04-23 21:40:38 +00:00
## Language
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
### Current Recommendation
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
**Spanish** is recommended for code internal to the TSN ecosystem, but with considerations:
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
- **Public variables/libraries:** Consider English for greater reach (this depends on your knowledge of that language)
- **Complex comments:** Spanish for clarity
- **Class/function names:** Consistency in the project
2026-04-23 21:22:52 +00:00
---
2026-04-23 21:40:38 +00:00
## Historical Note
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
**Important:** Some repositories in the TSN ecosystem (especially the older ones) **do not exactly follow ** these conventions. This is because they were developed before formal standards were implemented.
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
- Old code: ~50-70% adherence to conventions
- Recent code: ~90%+ adherence
2026-04-23 21:22:52 +00:00
2026-04-23 21:40:38 +00:00
There is a progressive migration to these conventions.
2026-04-23 21:22:52 +00:00
---
2026-04-23 21:40:38 +00:00
**Questions or suggestions?** Open an issue or contact [@nique_372 ](https://www.mql5.com/es/users/nique_372 )