Initial Commit ...
This commit is contained in:
@@ -0,0 +1,309 @@
|
||||
# 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();
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user