Order Types in MT5
MT5 supports six order types, each serving a different purpose:
- Market Orders — Execute immediately at the current price.
ORDER_TYPE_BUYandORDER_TYPE_SELL. - Limit Orders — Execute at a specified price or better.
ORDER_TYPE_BUY_LIMIT(buy below current price) andORDER_TYPE_SELL_LIMIT(sell above current price). - Stop Orders — Execute when price reaches a specified level.
ORDER_TYPE_BUY_STOP(buy above current price) andORDER_TYPE_SELL_STOP(sell below current price). - Stop-Limit Orders — A combination: when price reaches the stop level, a limit order is placed.
ORDER_TYPE_BUY_STOP_LIMITandORDER_TYPE_SELL_STOP_LIMIT.
The CTrade Class
The standard library's CTrade class simplifies order execution:
#include <Trade/Trade.mqh>
CTrade trade;
void OnInit()
{
trade.SetExpertMagicNumber(12345);
trade.SetDeviationInPoints(10); // max allowed slippage
trade.SetTypeFilling(ORDER_FILLING_FOK); // fill or kill
}
// Market orders
trade.Buy(0.1, _Symbol, ask, sl, tp, "Buy signal");
trade.Sell(0.1, _Symbol, bid, sl, tp, "Sell signal");
// Pending orders
trade.BuyLimit(0.1, limitPrice, _Symbol, sl, tp);
trade.SellStop(0.1, stopPrice, _Symbol, sl, tp);
// Close position
trade.PositionClose(_Symbol);
// Modify position SL/TP
trade.PositionModify(ticket, newSL, newTP);
Stop-Loss and Take-Profit
Always set stop-loss on every trade. It is your maximum acceptable loss per trade.
double CalculateSL(ENUM_ORDER_TYPE orderType, double entryPrice,
int slPoints)
{
if(orderType == ORDER_TYPE_BUY)
return NormalizeDouble(entryPrice - slPoints * _Point, _Digits);
else
return NormalizeDouble(entryPrice + slPoints * _Point, _Digits);
}
double CalculateTP(ENUM_ORDER_TYPE orderType, double entryPrice,
int tpPoints)
{
if(orderType == ORDER_TYPE_BUY)
return NormalizeDouble(entryPrice + tpPoints * _Point, _Digits);
else
return NormalizeDouble(entryPrice - tpPoints * _Point, _Digits);
}
Trailing Stop Implementation
A trailing stop moves the stop-loss in the direction of profit, locking in gains:
input int TrailingStop = 50; // Trailing Stop (points)
input int TrailingStep = 10; // Trailing Step (points)
void ManageTrailingStop()
{
if(!PositionSelect(_Symbol)) return;
double currentSL = PositionGetDouble(POSITION_SL);
long posType = PositionGetInteger(POSITION_TYPE);
ulong ticket = PositionGetInteger(POSITION_TICKET);
if(posType == POSITION_TYPE_BUY)
{
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double newSL = bid - TrailingStop * _Point;
// Only move SL up, never down
if(newSL > currentSL + TrailingStep * _Point)
{
double tp = PositionGetDouble(POSITION_TP);
trade.PositionModify(ticket, NormalizeDouble(newSL, _Digits), tp);
}
}
else if(posType == POSITION_TYPE_SELL)
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double newSL = ask + TrailingStop * _Point;
// Only move SL down, never up
if(newSL < currentSL - TrailingStep * _Point || currentSL == 0)
{
double tp = PositionGetDouble(POSITION_TP);
trade.PositionModify(ticket, NormalizeDouble(newSL, _Digits), tp);
}
}
}
Partial Close
Close part of a position to lock in partial profits:
void PartialClose(double closePercent)
{
if(!PositionSelect(_Symbol)) return;
double volume = PositionGetDouble(POSITION_VOLUME);
double closeVolume = NormalizeDouble(volume * closePercent / 100.0, 2);
// Ensure minimum lot size
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
if(closeVolume < minLot) closeVolume = minLot;
// Cannot close more than we have
if(closeVolume >= volume) closeVolume = volume;
ulong ticket = PositionGetInteger(POSITION_TICKET);
trade.PositionClosePartial(ticket, closeVolume);
}
Error Handling
Always check the result of trade operations:
bool OpenBuyPosition(double lots, double sl, double tp)
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(!trade.Buy(lots, _Symbol, ask, sl, tp, "Buy"))
{
Print("Buy failed. Error: ", GetLastError(),
" Retcode: ", trade.ResultRetcode(),
" Comment: ", trade.ResultComment());
return false;
}
Print("Buy opened. Ticket: ", trade.ResultOrder(),
" Price: ", trade.ResultPrice());
return true;
}
Iterating Through Positions
void ListAllPositions()
{
int total = PositionsTotal();
for(int i = 0; i < total; i++)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0)
{
string symbol = PositionGetString(POSITION_SYMBOL);
double profit = PositionGetDouble(POSITION_PROFIT);
long magic = PositionGetInteger(POSITION_MAGIC);
Print("Ticket: ", ticket,
" Symbol: ", symbol,
" Profit: ", DoubleToString(profit, 2),
" Magic: ", magic);
}
}
}