324 lines
9.6 KiB
TeX
324 lines
9.6 KiB
TeX
\section{MQL5 Programming Fundamentals}
|
|
|
|
MQL5 (MetaQuotes Language 5) is the programming language for developing Expert Advisors, indicators, and scripts in MetaTrader 5. Understanding MQL5 fundamentals is essential for implementing profitable trading algorithms.
|
|
|
|
\subsection{Program Structure}
|
|
|
|
An MQL5 Expert Advisor follows a specific structure:
|
|
|
|
\begin{lstlisting}[style=mql5style, caption=Basic MQL5 EA Structure]
|
|
//+------------------------------------------------------------------+
|
|
//| MyExpert.mq5 |
|
|
//| Copyright 2024, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
#include <Trade\Trade.mqh>
|
|
|
|
// Input parameters
|
|
input double LotSize = 0.1;
|
|
input int MagicNumber = 12345;
|
|
|
|
// Global variables
|
|
CTrade trade;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
trade.SetExpertMagicNumber(MagicNumber);
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
// Trading logic here
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
// Cleanup code
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsection{Key Components}
|
|
|
|
\subsubsection{Property Directives}
|
|
Property directives define metadata about the EA:
|
|
\begin{itemize}
|
|
\item \texttt{\#property copyright}: Copyright information
|
|
\item \texttt{\#property version}: Version number
|
|
\item \texttt{\#property strict}: Enables strict type checking
|
|
\end{itemize}
|
|
|
|
\subsubsection{Input Parameters}
|
|
Input parameters allow users to configure the EA without modifying code:
|
|
\begin{lstlisting}[style=mql5style]
|
|
input int RSI_Period = 14;
|
|
input double LotSize = 0.1;
|
|
input bool UseStopLoss = true;
|
|
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{Includes}
|
|
Standard libraries provide essential functionality:
|
|
\begin{lstlisting}[style=mql5style]
|
|
#include <Trade\Trade.mqh> // Trading functions
|
|
#include <Indicators\Trend.mqh> // Trend indicators
|
|
#include <Indicators\Volumes.mqh> // Volume indicators
|
|
\end{lstlisting}
|
|
|
|
\subsection{Core Functions}
|
|
|
|
\subsubsection{OnInit()}
|
|
Called once when the EA is loaded. Used for:
|
|
\begin{itemize}
|
|
\item Initializing indicators
|
|
\item Setting up trade objects
|
|
\item Validating parameters
|
|
\item Allocating resources
|
|
\end{itemize}
|
|
|
|
\begin{lstlisting}[style=mql5style, caption=OnInit Example]
|
|
int OnInit()
|
|
{
|
|
// Create indicator handle
|
|
rsiHandle = iRSI(_Symbol, PERIOD_H1, 14, PRICE_CLOSE);
|
|
if(rsiHandle == INVALID_HANDLE)
|
|
{
|
|
Print("Error creating RSI indicator");
|
|
return(INIT_FAILED);
|
|
}
|
|
|
|
// Configure trade object
|
|
trade.SetExpertMagicNumber(MagicNumber);
|
|
trade.SetDeviationInPoints(10);
|
|
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{OnTick()}
|
|
Called on every price tick. Contains the main trading logic:
|
|
\begin{lstlisting}[style=mql5style, caption=OnTick Example]
|
|
void OnTick()
|
|
{
|
|
// Check for new bar (optional optimization)
|
|
static datetime lastBarTime = 0;
|
|
datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
|
|
if(currentBarTime == lastBarTime)
|
|
return; // Same bar, skip processing
|
|
lastBarTime = currentBarTime;
|
|
|
|
// Get indicator values
|
|
double rsi[];
|
|
ArraySetAsSeries(rsi, true);
|
|
if(CopyBuffer(rsiHandle, 0, 0, 2, rsi) <= 0)
|
|
return;
|
|
|
|
// Trading logic
|
|
if(rsi[0] < 30 && rsi[1] >= 30)
|
|
{
|
|
// Buy signal
|
|
trade.Buy(LotSize, _Symbol);
|
|
}
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{OnDeinit()}
|
|
Called when the EA is removed. Used for cleanup:
|
|
\begin{lstlisting}[style=mql5style]
|
|
void OnDeinit(const int reason)
|
|
{
|
|
// Release indicator handles
|
|
if(rsiHandle != INVALID_HANDLE)
|
|
IndicatorRelease(rsiHandle);
|
|
|
|
// Delete chart objects
|
|
ObjectsDeleteAll(0, "MyPrefix");
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsection{Indicator Management}
|
|
|
|
\subsubsection{Creating Indicators}
|
|
Indicators are created using built-in functions:
|
|
\begin{lstlisting}[style=mql5style]
|
|
int rsiHandle = iRSI(_Symbol, PERIOD_H1, 14, PRICE_CLOSE);
|
|
int emaHandle = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_EMA, PRICE_CLOSE);
|
|
int volumeHandle = iVolumes(_Symbol, PERIOD_CURRENT, VOLUME_TICK);
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{Reading Indicator Values}
|
|
Use \texttt{CopyBuffer()} to retrieve indicator data:
|
|
\begin{lstlisting}[style=mql5style]
|
|
double rsi[];
|
|
ArraySetAsSeries(rsi, true); // Index 0 = most recent
|
|
if(CopyBuffer(rsiHandle, 0, 0, 3, rsi) > 0)
|
|
{
|
|
double currentRSI = rsi[0];
|
|
double previousRSI = rsi[1];
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsection{Trading Operations}
|
|
|
|
\subsubsection{CTrade Class}
|
|
The \texttt{CTrade} class provides a high-level interface for trading:
|
|
\begin{lstlisting}[style=mql5style]
|
|
CTrade trade;
|
|
|
|
// Configure
|
|
trade.SetExpertMagicNumber(12345);
|
|
trade.SetDeviationInPoints(10);
|
|
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
|
|
|
// Open positions
|
|
trade.Buy(0.1, _Symbol, 0, 0, 0, "Buy Order");
|
|
trade.Sell(0.1, _Symbol, 0, 0, 0, "Sell Order");
|
|
|
|
// Close positions
|
|
trade.PositionClose(_Symbol);
|
|
|
|
// Modify positions
|
|
trade.PositionModify(_Symbol, newSL, newTP);
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{Position Management}
|
|
Check and manage existing positions:
|
|
\begin{lstlisting}[style=mql5style]
|
|
// Check if position exists
|
|
bool hasPosition = PositionSelect(_Symbol);
|
|
|
|
if(hasPosition)
|
|
{
|
|
// Get position details
|
|
double profit = PositionGetDouble(POSITION_PROFIT);
|
|
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
|
|
|
// Close if profit target reached
|
|
if(profit > 100)
|
|
trade.PositionClose(_Symbol);
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsection{Price and Symbol Information}
|
|
|
|
\subsubsection{Getting Prices}
|
|
\begin{lstlisting}[style=mql5style]
|
|
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
|
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
|
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{Historical Data}
|
|
Access bar data:
|
|
\begin{lstlisting}[style=mql5style]
|
|
double close = iClose(_Symbol, PERIOD_H1, 0); // Current bar
|
|
double high = iHigh(_Symbol, PERIOD_H1, 0);
|
|
double low = iLow(_Symbol, PERIOD_H1, 0);
|
|
double open = iOpen(_Symbol, PERIOD_H1, 0);
|
|
datetime time = iTime(_Symbol, PERIOD_H1, 0);
|
|
long volume = iVolume(_Symbol, PERIOD_H1, 0);
|
|
\end{lstlisting}
|
|
|
|
\subsection{Time Management}
|
|
|
|
\subsubsection{Current Time}
|
|
\begin{lstlisting}[style=mql5style]
|
|
datetime currentTime = TimeCurrent(); // Server time
|
|
datetime localTime = TimeLocal(); // Local time
|
|
|
|
MqlDateTime timeStruct;
|
|
TimeToStruct(currentTime, timeStruct);
|
|
int hour = timeStruct.hour;
|
|
int dayOfWeek = timeStruct.day_of_week;
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{Session Detection}
|
|
\begin{lstlisting}[style=mql5style]
|
|
bool IsAsianSession()
|
|
{
|
|
MqlDateTime timeStruct;
|
|
TimeToStruct(TimeCurrent(), timeStruct);
|
|
return (timeStruct.hour >= 0 && timeStruct.hour < 8);
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsection{Error Handling}
|
|
|
|
Always check for errors:
|
|
\begin{lstlisting}[style=mql5style]
|
|
if(!trade.Buy(0.1, _Symbol))
|
|
{
|
|
int error = GetLastError();
|
|
Print("Trade failed. Error: ", error);
|
|
Print("Description: ", trade.ResultRetcodeDescription());
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\subsection{Best Practices}
|
|
|
|
\begin{enumerate}
|
|
\item \textbf{Always validate indicator handles}: Check for \texttt{INVALID_HANDLE}
|
|
\item \textbf{Use ArraySetAsSeries()}: Makes array indexing intuitive (0 = most recent)
|
|
\item \textbf{Check CopyBuffer() return values}: Ensure data was copied successfully
|
|
\item \textbf{Release resources}: Free indicator handles in \texttt{OnDeinit()}
|
|
\item \textbf{Handle errors gracefully}: Check return values and log errors
|
|
\item \textbf{Optimize OnTick()}: Use new bar detection to avoid redundant processing
|
|
\item \textbf{Use Magic Numbers}: Identify trades from your EA
|
|
\item \textbf{Validate stop levels}: Check minimum stop distance requirements
|
|
\end{enumerate}
|
|
|
|
\subsection{Common Patterns}
|
|
|
|
\subsubsection{New Bar Detection}
|
|
\begin{lstlisting}[style=mql5style]
|
|
static datetime lastBarTime = 0;
|
|
datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
|
|
if(currentBarTime == lastBarTime)
|
|
return; // Same bar
|
|
lastBarTime = currentBarTime;
|
|
// Process new bar
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{Crossover Detection}
|
|
\begin{lstlisting}[style=mql5style]
|
|
double current = indicator[0];
|
|
double previous = indicator[1];
|
|
|
|
// Bullish crossover
|
|
bool bullishCross = (previous < level) && (current > level);
|
|
|
|
// Bearish crossover
|
|
bool bearishCross = (previous > level) && (current < level);
|
|
\end{lstlisting}
|
|
|
|
\subsubsection{Position Tracking}
|
|
\begin{lstlisting}[style=mql5style]
|
|
bool hasPosition = false;
|
|
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
|
{
|
|
if(PositionGetSymbol(i) == _Symbol)
|
|
{
|
|
hasPosition = true;
|
|
break;
|
|
}
|
|
}
|
|
\end{lstlisting}
|
|
|
|
These fundamentals form the foundation for all Expert Advisors examined in this paper. Understanding these concepts is crucial for implementing and modifying trading algorithms effectively.
|