![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
You are missing trading opportunities:
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
Registration
Log in
You agree to website policy and terms of use
If you do not have an account, please register
I've wrote an Expert Advisor to execute a simple two moving average crossover strategy, as follows:
- When the fast moving average crosses the the slow MA up: go long;
- When the slow moving average crosses the fast MA down: go short;
- When price reaches take profit price: close position.
Notes about EA development and demo account testing:
- My broker doesn't accept hedge accounts, so only netting mode is available. As my strategy requires that multiple EAs with different moving average periods run at the same time, I've had to manage positions internally so one EA doesn't mess with the other's positions;
- As a consequence of the issue noted above, take profit can't be managed the usual way (modifying a position), so when the take profit price is reached, the EA sends a closing order.
- This EA has been extensively backtested and run on demo account, which demonstrated that it works perfectly.
Notes about EA real account testing:
- I've tested it twice on my real account, and it opens the position just as expected, but when the moving average crosses back, it doesn't reverse the position;
- I've run two identical EAs (just as I did in my demo account) with different parameters and both showed the above noted behavior;
- It seems it doesn't even try to send the order (see log below);
- I didn't have the chance to check if the take profit routine worked well though, as the prices didn't moved towards trigger price;
- The EA is running at a virtual machine hosted at Amazon, so no power or connection problems take place;
- Margin deposit requirements are properly met;
- My broker says there's nothing wrong with my account.
Instrument specs:
- Symbol: WDOG17 (future contract of 10,000.00 USD quoted in BRL);
- Digits: 3;
- Tick size: 0.5;
- Tick value: 5.00 BRL;
- Execution type: Exchange;
- GTD mode: Today.
EA code:
//Application details-----------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
//Moving-Averages-Crossover version 1.00
//The algorithm buys de asset whenever the fast moving average crosses the slow moving average up and sell whe
//n the opposite happens. Position exit can take place either by a moving average crossover to the opposite di
//rection or by take profit, if set. The user must provide the moving averages calculation periods, methods an
//d applied price, as well as position size and take profit levels. Version built on 2016-11-19.
//Moving-Averages-Crossover version 1.01
//The algorithm was optimized to run simultaneously with other EAs, even in netting mode. It's orders are inde
//pendently placed and executed, disregarding manual orders and other's EAs orders. Version built on 2016-12-2
//2.
#property copyright "Rafael Pereira Gonçalves"
#property version "1.01"
//------------------------------------------------------------------------------------------------------------
//Include-----------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
#include <Trade/Trade.mqh>;
//------------------------------------------------------------------------------------------------------------
//Input-------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
input ulong expertAdvisorID = 1; //Expert Advisor ID
input int fastMAPeriod = 10; //Fast Moving Average Period (Integer)
input int slowMAPeriod = 12; //Slow Moving Average Period (Integer)
input ENUM_MA_METHOD fastMAMethod = MODE_SMA; //Fast Moving Average Calculation Method
input ENUM_MA_METHOD slowMAMethod = MODE_SMA; //Slow Moving Average Calculation Method
input ENUM_APPLIED_PRICE fastMAPrice = PRICE_CLOSE; //Fast Moving Average Applied Price
input ENUM_APPLIED_PRICE slowMAPrice = PRICE_CLOSE; //Slow Moving Average Applied Price
input double lotSize = 1; //Net Position Size (Integer)
input double takeProfit = 0.001; //Take Profit (Decimal; "0" to Disable)
input string startTrading = "09:00:00"; //Start Trading Time (HH:MM:SS)
input string stopTrading = "17:50:00"; //Stop Trading Time (HH:MM:SS)
input int maxSlippage = 0; //Maximum Slippage (Integer)
//------------------------------------------------------------------------------------------------------------
//Global variables--------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
double fastMABuffer[];
double slowMABuffer[];
int fastMAHandle;
int slowMAHandle;
datetime lastBarTime;
int position = 0; //-1 is short, 0 is neutral and 1 is long
double takeProfitPrice;
bool takeProfitState = 0; //0 is inactive, 1 is active
bool timeSpanGo;
MqlRates currentBarInfo[];
MqlTradeRequest tradeRequest;
//------------------------------------------------------------------------------------------------------------
//Classes-----------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
CTrade Trade;
//------------------------------------------------------------------------------------------------------------
//OnInit event handler----------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
int OnInit()
{
//Set expert advisor magic number
Trade.SetExpertMagicNumber(expertAdvisorID);
//Set trade request constant values
tradeRequest.action = TRADE_ACTION_DEAL;
tradeRequest.deviation = maxSlippage;
tradeRequest.sl = 0;
tradeRequest.symbol = _Symbol;
tradeRequest.tp = 0;
tradeRequest.type_filling = ORDER_FILLING_FOK;
//Get initial bar opening time
ArraySetAsSeries(currentBarInfo, true);
CopyRates(_Symbol, PERIOD_CURRENT, 0, 3, currentBarInfo);
lastBarTime = currentBarInfo[0].time;
//Initialize indicators
fastMAHandle = iMA(_Symbol, _Period, fastMAPeriod, 0, fastMAMethod, fastMAPrice);
slowMAHandle = iMA(_Symbol, _Period, slowMAPeriod, 0, slowMAMethod, slowMAPrice);
ArraySetAsSeries(fastMABuffer, true);
ArraySetAsSeries(slowMABuffer, true);
return(0);
}
//------------------------------------------------------------------------------------------------------------
//OnDeinit event handler--------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
void OnDeinit(const int reason)
{
//Deinitialize indicators, clear indicator buffer and send notification
IndicatorRelease(fastMAHandle);
IndicatorRelease(slowMAHandle);
ArrayFree(fastMABuffer);
ArrayFree(slowMABuffer);
SendNotification("Expert Advisor has been deinitialized");
}
//------------------------------------------------------------------------------------------------------------
//OnTick event handler----------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
void OnTick() {
//Detect new bar
CopyRates(_Symbol, PERIOD_CURRENT, 0, 3, currentBarInfo);
if(currentBarInfo[0].time != lastBarTime) {
lastBarTime = currentBarInfo[0].time;
timeSpanGo = 0;
//Check if timespan is go for trading
if(TimeToString(currentBarInfo[0].time, TIME_SECONDS) >= startTrading &&
TimeToString(currentBarInfo[0].time, TIME_SECONDS) <= stopTrading) {
timeSpanGo = 1;
//Get latest indicator values
CopyBuffer(fastMAHandle, 0, 0, 3, fastMABuffer);
CopyBuffer(slowMAHandle, 0, 0, 3, slowMABuffer);
//Test whether to go long or not
if(position != 1 && fastMABuffer[1] > slowMABuffer[1] && fastMABuffer[2] <= slowMABuffer[2]) {
double volume = 1;
MqlTradeResult tradeResult;
tradeRequest.comment = StringFormat("Open Long (%d)", expertAdvisorID);
//Modify volume to close short position, if any
if(position == -1) {
volume = 2;
tradeRequest.comment = StringFormat("Close Short/Open Long (%d)", expertAdvisorID);
}
//Open long position
tradeRequest.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
tradeRequest.type = ORDER_TYPE_BUY;
tradeRequest.volume = lotSize * volume;
if(!OrderSend(tradeRequest, tradeResult)) {
PrintFormat("Failed to place '%s' order. Error code: %d", tradeRequest.comment, GetLastError());
SendNotification("Expert Advisor has just failed to place an order, please check your positions manually");
} else {
do Sleep(10); while(tradeResult.deal == 0);
takeProfitPrice = floor((tradeResult.price * (1 + takeProfit)) * 2) / 2;
position = 1;
takeProfitState = 1;
}
}
//Test whether to go short or not
else if(position != -1 && fastMABuffer[1] < slowMABuffer[1] && fastMABuffer[2] >= slowMABuffer[2]) {
double volume = 1;
MqlTradeResult tradeResult;
tradeRequest.comment = StringFormat("Open Short (%d)", expertAdvisorID);
//Modify volume to close long position, if any
if(position == 1) {
volume = 2;
tradeRequest.comment = StringFormat("Close Long/Open Short (%d)", expertAdvisorID);
}
//Open short position
tradeRequest.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
tradeRequest.type = ORDER_TYPE_SELL;
tradeRequest.volume = lotSize * volume;
if(!OrderSend(tradeRequest, tradeResult)) {
PrintFormat("Failed to place '%s' order. Error code: %d", tradeRequest.comment, GetLastError());
SendNotification("Expert Advisor has just failed to place an order, please check your positions manually");
} else {
do Sleep(10); while(tradeResult.deal == 0);
takeProfitPrice = ceil((tradeResult.price * (1 - takeProfit)) * 2) / 2;
position = -1;
takeProfitState = 1;
}
}
}
}
//Check for take profit
if(takeProfitState == 1 && timeSpanGo == 1) {
if(position == 1 && SymbolInfoDouble(_Symbol, SYMBOL_BID) >= takeProfitPrice) {
MqlTradeResult tradeResult;
tradeRequest.price = takeProfitPrice;
tradeRequest.type = ORDER_TYPE_SELL;
tradeRequest.volume = lotSize;
tradeRequest.comment = StringFormat("Close Long by Take Profit (%d)", expertAdvisorID);
if(!OrderSend(tradeRequest, tradeResult)) {
PrintFormat("Failed to place '%s' order. Error code: %d", tradeRequest.comment, GetLastError());
SendNotification("Expert Advisor has just failed to place an order, please check your positions manually");
} else {
position = 0;
takeProfitState = 0;
}
}
if(position == -1 && SymbolInfoDouble(_Symbol, SYMBOL_ASK) <= takeProfitPrice) {
MqlTradeResult tradeResult;
tradeRequest.price = takeProfitPrice;
tradeRequest.type = ORDER_TYPE_BUY;
tradeRequest.volume = lotSize;
tradeRequest.comment = StringFormat("Close Short by Take Profit (%d)", expertAdvisorID);
if(!OrderSend(tradeRequest, tradeResult)) {
PrintFormat("Failed to place '%s' order. Error code: %d", tradeRequest.comment, GetLastError());
SendNotification("Expert Advisor has just failed to place an order, please check your positions manually");
} else {
position = 0;
takeProfitState = 0;
}
}
}
}
The log:
Below there's a piece of the log where I tested two EAs with different moving average periods. Note that around 15:30:00 and 14:00:00 both positions should be closed due to the moving averages crossing back, but nothing happens.
[log begin]
PF 0 09:37:42.035 Terminal MetaTrader 5 Terminal x64 build 1495 started ('x broker')
CL 0 09:37:42.036 Terminal Windows Server 2012 R2 Standard (x64 based PC), IE 11.00, RDP, UAC, Intel Xeon E5-2676 v3 @ 2.40GHz, RAM: 393 / 1023 Mb, HDD: 10444 / 30367 Mb, GMT-03:00
EE 0 09:37:42.036 Terminal C:\'default path...'
RD 0 09:38:09.684 Network 'xxxxxx': authorized on x server through MetaTrader 5 Access Server 2 (ping: 3.75 ms)
PF 0 09:38:09.684 Network 'xxxxxx': previous successful authorization performed from 'xxx.xx.xx.xxx' on 2017.01.04 09:29:34
FG 0 09:38:09.696 Network 'xxxxxx': terminal synchronized with 'x broker'
QM 0 09:38:09.696 Network 'xxxxxx': trading has been enabled - netting mode
NE 0 09:38:18.721 Experts automated trading is enabled
DQ 0 09:38:30.332 Experts expert Moving-Averages-Crossover (WDOG17,M5) loaded successfully
CJ 0 09:39:54.769 Experts expert Moving-Averages-Crossover (WDOG17,M5) loaded successfully
IF 0 12:52:38.706 Network 'xxxxxx': scanning network for access points
KN 0 12:52:38.926 Network 'xxxxxx': scanning network finished
HK 0 13:09:52.225 Trades 'xxxxxx': exchange buy 1.00 WDOG17 at market
KL 0 13:09:52.248 Trades 'xxxxxx': exchange buy 1.00 WDOG17 at market placed for execution in 23.323 ms (Order received. Sending to OMS.)
EP 0 13:09:52.334 Trades 'xxxxxx': deal #24936683 buy 1.00 WDOG17 at 3250.500 done (based on order #20123664)
OR 0 13:09:53.735 Notifications notification 'added order #20123664 buy 1.00 WDOG17 at market, Open Long' sent to 'xxxxxx
HL 0 13:09:53.941 Notifications notification 'deal #24936683 buy 1.00 WDOG17 at 3250.500 done, based on order #20123664 buy 1.00 WDOG17 at market' sent to 'xxxxxx'
CG 0 14:35:01.673 Trades 'xxxxxx': exchange buy 1.00 WDOG17 at market
RP 0 14:35:01.689 Trades 'xxxxxx': exchange buy 1.00 WDOG17 at market placed for execution in 16.329 ms (Order received. Sending to OMS.)
EM 0 14:35:01.718 Trades 'xxxxxx': deal #24950576 buy 1.00 WDOG17 at 3249.000 done (based on order #20127352)
HO 0 14:35:02.598 Notifications notification 'added order #20127352 buy 1.00 WDOG17 at market, Open Long' sent to 'xxxxxx'
JL 0 14:35:02.808 Notifications notification 'deal #24950576 buy 1.00 WDOG17 at 3249.000 done' sent to 'xxxxxx'
RF 0 16:45:44.023 Experts expert Moving-Averages-Crossover (WDOG17,M5) removed
OH 0 16:45:56.023 Experts expert Moving-Averages-Crossover (WDOG17,M5) removed
[log end]
I tried to provide all possible information, but let me know if you need more details to help me.
So, what am I missing here?