Using the examples provided in the MQL5 source tree, I found one which traded using a moving average.
…\MQL5\Experts\Examples\Moving Average\Moving Average.mq5
I took this and played around with it in order to further understand the mechanics of the provided MQL5 object hierarchy.
The idea is simple: Apply a simple moving average to the chart in order to average out the noise and see an overall trend.
By shifting the moving average horizontally to the right, when price action crosses the average it signals a reverse in trend.
When a new bar is opened (ie: on the first tick of the new bar the tick volume in the bar is 1), we look at what happened in the previous bar.
If price crosses the trend moving upwards, this is a signal to go long.
// the previous bar opened below the average and closed above the average
if (rates[0].open < ma[0] && rates[0].close > ma[0])
order = ORDER_TYPE_BUY; // price crosses up - go long
If price crosses the trend moving downwards, this is a signal to go short.
// the previous bar opened above the average and closed below the average
if (rates[0].open > ma[0] && rates[0].close < ma[0])
order = ORDER_TYPE_SELL; // price crosses down - go short
I keep track of whether I have opened my first position. Once this has happened I double my lot size. The reason for this is so that when the trend reverses, I will enter an opposite position for double the number of lots; this will exit my previous position and enter a new position in the opposite direction.
#include <Trade\Trade.mqh>
input double LotSize = 1; // Number of lots to order
input int MovingPeriod = 12; // Moving average period
input int MovingShift = 6; // Moving average shift
int MovingAvg = 0;
MqlRates rates[2];
double ma[1];
bool tradedFirstLot = false;
double NumLots = LotSize;
int OnInit()
{
if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
printf("Trading not allowed");
return -1;
}
MovingAvg = iMA(_Symbol, _Period, MovingPeriod, MovingShift, MODE_SMA, PRICE_CLOSE);
if (MovingAvg == INVALID_HANDLE)
{
printf("Error creating MA indicator");
return -1;
}
return 0;
}
//--------------------------------------------------------------------------
void OnTick()
{
// copy rates starting from the latest, going back 2 periods
if (CopyRates(_Symbol, _Period, 0, 2, rates) != 2)
{
Print("CopyRates of ",_Symbol," failed, no history");
return;
}
// go trading only for first tick of new bar
if (rates[1].tick_volume > 1)
return;
// get current moving average
if (CopyBuffer(MovingAvg, 0, 0, 1, ma) != 1)
{
Print("CopyBuffer from iMA failed, no data");
return;
}
// calculate whether price has crossed the moving average
ENUM_ORDER_TYPE order;
if (rates[0].open < ma[0] && rates[0].close > ma[0])
order = ORDER_TYPE_BUY; // price crosses up - go long
else
if (rates[0].open > ma[0] && rates[0].close < ma[0])
order = ORDER_TYPE_SELL; // price crosses down - go short
else
return; // price moving sideways
CTrade trade;
trade.PositionOpen(_Symbol,
order,
NumLots,
SymbolInfoDouble(_Symbol,
order == ORDER_TYPE_SELL
? SYMBOL_BID
: SYMBOL_ASK),
0, // no stop loss
0); // no take profit
if (!tradedFirstLot)
{
// once we have a position on, we need to double the lot size so that
// our next order closes the first position and then opens the new one
tradedFirstLot = true;
NumLots *= 2;
}
}
//--------------------------------------------------------------------------
void OnDeinit(const int reason)
{
}
//--------------------------------------------------------------------------