310 lines
9.5 KiB
Markdown
310 lines
9.5 KiB
Markdown
# EA Tutorials
|
|
|
|
in this tutorial we cover this titles step by step:
|
|
|
|
1. Create new Expert Advisor
|
|
2. Variables
|
|
3. Functions
|
|
4. Control Structures
|
|
5. Read Indicator Data
|
|
6. Open Trades
|
|
7. Modify Trades
|
|
8. Close Trades
|
|
|
|
## Create new Expert Advisor
|
|
|
|
in meta editor (f4, tools > meta editor), click on new and select expert adviser.
|
|
|
|
as you know all mql programs runing based on event handlers.
|
|
|
|
there are three main event handlers, which used in an EA:
|
|
|
|
- OnInit // runs each time tf changes, or ea attached ...
|
|
- OnDeinit // runs when ea removed from chart ...
|
|
- OnTick // most important function, all of business logics implemented here ...
|
|
|
|
you can see all of it's documents on proppered file.
|
|
|
|
the main feature of an EA in MQL, is there are some features which helps us. such as notification of signals and auto trading abbility.
|
|
|
|
## Variables
|
|
|
|
usually used to store some values of specific Data Types.
|
|
so this is much better to see supported datat types in documentations.
|
|
|
|
for using variables, you had to define a variable, also you can set init value of it's supported data type.
|
|
each variable must be specific it's own data type.
|
|
|
|
each variable defined by assign a name to it.
|
|
|
|
so by using this name you can assign value to it or read it assigned value ...
|
|
|
|
## Functions
|
|
|
|
in programming, a function can get some params and do some actions on them and return a result.
|
|
doing some actions is the permanent part of it's definition.
|
|
this means a function can only do a simple action and not have any params, and not have any return type.
|
|
|
|
each function must contain a unioque name.
|
|
|
|
in scope of project you can call a function by providing it's name and passing required params and also gives it's result.
|
|
|
|
## Control Structures
|
|
|
|
conditional operators gives an expression and determines it's result is true or false.
|
|
there are many commands in programming which used a conditional expression to act based on it's result.
|
|
by this way you can make your own business logic to control programming flow, or data flow or anything you want.
|
|
|
|
most commonly used conditional command is if command, which used like this syntax:
|
|
|
|
```mq4
|
|
//
|
|
if (conditional_expression) {
|
|
//
|
|
// Blocks of code which run when conditional expression is true ...
|
|
} else {
|
|
//
|
|
// Blocks of code which run when conditional expression is false ...
|
|
}
|
|
|
|
//
|
|
also we can make loops in programing, a loop is a code blocks which runs until a condition happens.
|
|
there are many type of loops in programming languages.
|
|
|
|
most commonly used loops is create using for command by following this syntax:
|
|
|
|
for (int i; i <= 6; i++) {
|
|
//
|
|
// Loop Code Block ...
|
|
Print("Loop Itrator: ", i);
|
|
}
|
|
```
|
|
|
|
## Read Indicator Data
|
|
|
|
in this example we specially use RSI indicator.
|
|
but you can replace this by any other indicator you want, strusture is same;
|
|
|
|
RSI Indicator provide a value for each candle and draw a line. this value is between 0 and 100;
|
|
|
|
**Note** each standard indicator in MQL has a related function, which is usually starts with i{IndicatorName}, such as iRSI, iIchimoku and etc.
|
|
this functions, return specific values related to Indicator Data.
|
|
by calling this functions you can capture Indicator data for specific types of inputs.
|
|
|
|
there are some standard inputs which usually used as params in iFunctions which i describe them in following:
|
|
|
|
- Symbol: reffer to which symbol you need to inject it's data from indicator. (_Symbol)
|
|
- Period: reffer to which Time Frame you need to inject symbol's data on it from indicator (CURRENT_PERIOD).
|
|
- ...
|
|
|
|
as i described before all candle related data, or indicators data, usually stores in Buffers.
|
|
by calling iFunctions, you retrieve an integer result, which it's an index number that point to a Buffer.
|
|
for using it's value, you had to create a Buffer on top of it.
|
|
|
|
```mq4
|
|
//
|
|
// here we define a pointer to iFunction buffer ...
|
|
// for reading values, each time we need we had to define
|
|
// a global pointer and then fill it on Init handler ...
|
|
int rsiPointer = iRSI(_Symbol, _Period, 14, PRICE_CLOSE);
|
|
|
|
//
|
|
// define a dynamic size array, which calls Buffer ...
|
|
double rsiBuffer[];
|
|
|
|
//
|
|
// fill defined Buffer by iFunction Pointer ...
|
|
CopyBuffer(rsiPointer, 0, 1, 1, s);
|
|
```
|
|
|
|
**Note** there are some different ways in MQL4 and MQL5 to read the Pointer value. as i think this above described method is for MQL5, since in MQL4 for each bar_index, you shoud to call the iFunction once, by passing the bar to it ...
|
|
|
|
## Open Trades
|
|
|
|
as i described before, one of the main features an EA Programs, which used commonly is to Open Trade positions and specific conditions.
|
|
|
|
imagine that we want to send signal for Long and Short positions, based on rsi value.
|
|
the condition is when rsi value at the current candle is abopve than 70, means Bullish Signal, and otherwise if it is below than 30 means Bearish Signal.
|
|
|
|
we can handle this in OnTick event handler like this:
|
|
|
|
```mq4
|
|
//
|
|
// Prepare RSI Buffer ...
|
|
double rsi[];
|
|
CopyBuffer(rsiPointer, 0, 1, 1, rsi);
|
|
|
|
//
|
|
// Prepare Signal Conditions ...
|
|
if (rsi[0] > 70) {
|
|
//
|
|
// Bullish Signal ...
|
|
} else if (rsi[0] < 30) {
|
|
//
|
|
// Bearish Signal ...
|
|
}
|
|
```
|
|
|
|
we need to open position based on above Trading Conditions.
|
|
|
|
at the first step we have to include Trade library in our EA Project.
|
|
|
|
```mq4
|
|
//
|
|
// here we include header file ...
|
|
#include <Trade/Trade.mqh>
|
|
|
|
...
|
|
|
|
//
|
|
// now we have to define an instance of CTrade class to manipulate Positions ...
|
|
CTrade trader;
|
|
...
|
|
```
|
|
|
|
after create CTrade instance, we have to use it in right way and right place to manipulate positions:
|
|
|
|
```mq4
|
|
//
|
|
// Prepare Signal Conditions ...
|
|
if (rsi[0] > 70) {
|
|
//
|
|
// Bearish Signal ...
|
|
trader.Sell(0.001, _Symbol);
|
|
} else if (rsi[0] < 30) {
|
|
//
|
|
// Bullish Signal ...
|
|
trader.Buy(0.01. _Symbol);
|
|
}
|
|
```
|
|
|
|
in above example, we just open positions and there is no access to them for manipulate them.
|
|
we have to specify unique id to each position and store them somewhere in our EA to next times we have to manage or manipulate positions, simply reffer to them ...
|
|
|
|
```mq4
|
|
//
|
|
// Prepare Signal Conditions ...
|
|
if (rsi[0] > 70) {
|
|
//
|
|
// Bearish Signal ...
|
|
trader.Sell(0.001, _Symbol);
|
|
ulong ticket = trader.ResultOrder();
|
|
} else if (rsi[0] < 30) {
|
|
//
|
|
// Bullish Signal ...
|
|
// we can provide tp and sl on positions ...
|
|
trader.Buy(0.01. _Symbol);
|
|
ulong ticket = trader.ResultOrder();
|
|
}
|
|
```
|
|
|
|
we can simply check ticket as a global variable and then before opening new position, check it's value and then provide business logic ...
|
|
|
|
## Modify Trades
|
|
|
|
before do any manipulation on a position, we have to select the position itself ...
|
|
|
|
PositionSelectByTicket is a Method which used to select a position by providing it's ticket id.
|
|
this returns a boolean value which determines position selected correctly or not ...
|
|
|
|
[here](https://www.mql5.com/en/docs/constants/tradingconstants/positionproperties) are some resources related to position.
|
|
|
|
for modifying an specific position, we have to use this function like following:
|
|
|
|
```mq4
|
|
//
|
|
// assume that this value filled on opening a position ...
|
|
ulong positionTicket;
|
|
|
|
//
|
|
// validate position selectedsuccessfully, then try
|
|
// to manipulate it ...
|
|
if (PositionSelectByTicket(positionTicket)) {
|
|
//
|
|
// Do what ever we want to modify on popsition ...
|
|
|
|
//
|
|
// reading some Position info ...
|
|
double positionPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
|
double positionTP = PositionGetDouble(POSITION_TP);
|
|
double positionSL = PositionGetDouble(POSITION_SL);
|
|
|
|
//
|
|
// detect Position Type ...
|
|
// POSITION_TYPE_BUY
|
|
// POSITION_TYPE_SELL
|
|
int positionType = PositionGetInteger(POSITION_TYPE);
|
|
|
|
//
|
|
// Check Position has SL ...
|
|
if (positionSL == 0) {
|
|
//
|
|
// here we calculate and define SL and TP for position ...
|
|
double sl = 0;
|
|
double tp = 0;
|
|
|
|
//
|
|
// then we use PositionModify method to apply our changes on specified Position ...
|
|
trader.PositionModify(positionTicket, sl, tp);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Close Trades
|
|
|
|
some times we need to conditionally close an open position. maybe some times we got a reversal signal or anything else, based on our EA Business Logic.
|
|
for this we can also check positionTicket must be greater than zero.
|
|
|
|
in following code, we update above sample to add supports for close last open position, before opening another one ...
|
|
|
|
```mq4
|
|
//
|
|
// Prepare Signal Conditions ...
|
|
if (rsi[0] > 70) {
|
|
//
|
|
// close last open position ...
|
|
// this condition means there are an open position ...
|
|
if (positionTicket > 0 && PositionSelectByTicket(positionTicket)) {
|
|
//
|
|
// retrieve Position Type ...
|
|
int positionType = PositionGetInteger(POSITION_TYPE);
|
|
if (positionType == POSITION_TYPE_BUY) {
|
|
//
|
|
// Close Position ...
|
|
trade.PositionClose(positionTicket);
|
|
|
|
//
|
|
positionTicket = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bearish Signal ...
|
|
trader.Sell(0.001, _Symbol);
|
|
positionTicket = trader.ResultOrder();
|
|
} else if (rsi[0] < 30) {
|
|
//
|
|
// close last open position ...
|
|
// this condition means there are an open position ...
|
|
if (positionTicket > 0 && PositionSelectByTicket(positionTicket)) {
|
|
//
|
|
// retrieve Position Type ...
|
|
int positionType = PositionGetInteger(POSITION_TYPE);
|
|
if (positionType == POSITION_TYPE_SELL) {
|
|
//
|
|
// Close Position ...
|
|
trade.PositionClose(positionTicket);
|
|
|
|
//
|
|
positionTicket = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bullish Signal ...
|
|
// we can provide tp and sl on positions ...
|
|
trader.Buy(0.01. _Symbol);
|
|
positionTicket = trader.ResultOrder();
|
|
}
|
|
```
|