MQL5 CTrade Class Guide: Buy, PositionClose & PositionModify Signatures
Master the MQL5 CTrade standard library class. Inspect exact function signatures for CTrade::Buy, PositionClose, and PositionModify, with parameter tables, return code checks, and production-ready EA order execution patterns.
What this MQL5 guide covers
CTrade simplifies MQL5 order routing by wrapping low-level MqlTradeRequest and OrderSend into clean object-oriented method calls.
CTrade::Buy accepts volume, symbol, execution price, stop-loss, take-profit, and order comments with sensible defaults.
PositionClose supports both symbol-based closing on netting accounts and ticket-based closing on hedging accounts.
Always inspect trade.ResultRetcode() and trade.ResultRetcodeDescription() to detect requotes, invalid stops, and volume limits.
CTrade::Buy Method Signatures and Parameter Specifications
The CTrade class resides in the standard library header <Trade\Trade.mqh>. It provides overloaded implementations of the Buy method to open long market positions or place pending buy orders.
The primary market buy signature requires volume as the first parameter. If symbol is omitted or set to NULL, CTrade automatically uses the current chart symbol (_Symbol). When execution price is 0.0, the current Ask price is retrieved automatically by the terminal.
| Parameter | Type | Default | Description |
|---|---|---|---|
| volume | double | Required | Trade volume in lots (must conform to symbol lot step) |
| symbol | const string | NULL | Symbol name. NULL or "" resolves to chart symbol _Symbol |
| price | double | 0.0 | Open price. 0.0 resolves to current SymbolInfoDouble(symbol, SYMBOL_ASK) |
| sl | double | 0.0 | Stop loss price level (must satisfy symbol stop level distance) |
| tp | double | 0.0 | Take profit price level (must satisfy symbol stop level distance) |
| comment | const string | "" | Custom string comment attached to the resulting deal and order |
PositionClose and PositionModify Signatures
Closing and adjusting existing positions requires different signatures depending on whether your MetaTrader 5 account is configured for Netting (one position per instrument) or Hedging (multiple independent tickets per instrument).
CTrade::PositionClose provides two distinct overloads: passing a symbol string closes the aggregated position on netting accounts, while passing a ulong position ticket closes that exact position in hedging mode.
CTrade::PositionModify updates the stop-loss and take-profit of an active position. On hedging accounts, specify the position ticket as the first parameter; on netting accounts, passing the symbol string is supported.
| Method | Parameters | Return Type | Account Mode |
|---|---|---|---|
| PositionClose(symbol, deviation) | const string symbol, ulong deviation=ULONG_MAX | bool | Netting (or single position) |
| PositionClose(ticket, deviation) | ulong ticket, ulong deviation=ULONG_MAX | bool | Hedging (by ticket ID) |
| PositionModify(ticket, sl, tp) | ulong ticket, double sl, double tp | bool | Hedging (by position ticket) |
| PositionModify(symbol, sl, tp) | const string symbol, double sl, double tp | bool | Netting (by symbol string) |
Return Code Verification and Execution Diagnostics
A boolean return value of true from CTrade::Buy indicates the trade server accepted the request, but live algorithms must still verify the execution result using ResultRetcode().
A return code of TRADE_RETCODE_DONE (10009) or TRADE_RETCODE_PLACED (10008) confirms full execution. Codes such as 10016 (Invalid stops), 10014 (Invalid volume), and 10004 (Requote) require programmatic recovery.
- ResultRetcode(): Returns uint numeric response code from the trading server.
- ResultRetcodeDescription(): Human-readable text describing the execution outcome.
- ResultOrder(): Ticket number of the newly placed order.
- ResultDeal(): Ticket number of the completed deal recorded in trade history.
Implementation details & mechanics
Core implementation pattern
Instantiate CTrade and set trading context: configure trade.SetExpertMagicNumber(MagicNumber), trade.SetDeviationInPoints(DeviationPoints), and trade.SetTypeFillingBySymbol(_Symbol). To enter a long position, compute normalized Ask price, calculate stop-loss and take-profit using SymbolInfoDouble(_Symbol, SYMBOL_POINT), and invoke trade.Buy(lots, _Symbol, ask, sl, tp, "Pineify CTrade").
Error handling & safety rules
For position modifications, retrieve the open position ticket via PositionGetTicket() or PositionSelectByTicket(), verify that the proposed new SL adheres to SYMBOL_TRADE_STOPS_LEVEL, and call trade.PositionModify(ticket, newSL, newTP). To exit completely, call trade.PositionClose(ticket) on hedging accounts or trade.PositionClose(_Symbol) on netting accounts, verifying that trade.ResultRetcode() equals TRADE_RETCODE_DONE.
MQL5 Code Implementation Code
//+------------------------------------------------------------------+
//| CTradeClassGuideEA.mq5 |
//| Copyright 2026, Pineify Guides Series |
//| https://pineify.app |
//+------------------------------------------------------------------+
#property copyright "Pineify Guides Series"
#property link "https://pineify.app/mql5/ctrade-class-guide"
#property version "1.00"
#property strict
// Include standard trade library
#include <Trade\Trade.mqh>
//--- Input parameters
input group "--- Order Settings ---"
input double InpLotSize = 0.10; // Lot volume
input int InpStopLossPoints = 250; // Stop Loss in points
input int InpTakeProfitPoints= 500; // Take Profit in points
input ulong InpSlippagePoints = 20; // Max slippage in points
input ulong InpMagicNumber = 101001; // EA Magic Number
//--- Global trade instance
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Configure CTrade instance
trade.SetExpertMagicNumber(InpMagicNumber);
trade.SetDeviationInPoints(InpSlippagePoints);
trade.SetTypeFillingBySymbol(_Symbol);
trade.SetAsyncMode(false); // Synchronous execution for deterministic confirmation
Print("CTrade initialized successfully. Magic: ", InpMagicNumber);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Helper: Open a long position using CTrade::Buy |
//+------------------------------------------------------------------+
bool OpenBuyOrder(double lots, int slPoints, int tpPoints, const string comment="Pineify Buy")
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double sl = (slPoints > 0) ? NormalizeDouble(ask - slPoints * point, digits) : 0.0;
double tp = (tpPoints > 0) ? NormalizeDouble(ask + tpPoints * point, digits) : 0.0;
// Call CTrade::Buy signature: (volume, symbol, price, sl, tp, comment)
if(trade.Buy(lots, _Symbol, ask, sl, tp, comment))
{
uint retcode = trade.ResultRetcode();
if(retcode == TRADE_RETCODE_DONE || retcode == TRADE_RETCODE_PLACED)
{
PrintFormat("Buy success! Order Ticket: %I64u, Deal: %I64u, Price: %.*f",
trade.ResultOrder(), trade.ResultDeal(), digits, ask);
return true;
}
PrintFormat("Buy returned true but retcode is %u (%s)",
retcode, trade.ResultRetcodeDescription());
return false;
}
PrintFormat("CTrade::Buy failed! Retcode: %u (%s)",
trade.ResultRetcode(), trade.ResultRetcodeDescription());
return false;
}
//+------------------------------------------------------------------+
//| Helper: Modify position stop loss and take profit |
//+------------------------------------------------------------------+
bool ModifyPositionSLTP(ulong ticket, double newSL, double newTP)
{
if(!trade.PositionModify(ticket, newSL, newTP))
{
PrintFormat("PositionModify failed for ticket %I64u: %u (%s)",
ticket, trade.ResultRetcode(), trade.ResultRetcodeDescription());
return false;
}
PrintFormat("Position %I64u modified successfully to SL: %f, TP: %f",
ticket, newSL, newTP);
return true;
}
//+------------------------------------------------------------------+
//| Helper: Close position safely |
//+------------------------------------------------------------------+
bool CloseSpecificPosition(ulong ticket)
{
if(!trade.PositionClose(ticket))
{
PrintFormat("PositionClose failed for ticket %I64u: %u (%s)",
ticket, trade.ResultRetcode(), trade.ResultRetcodeDescription());
return false;
}
PrintFormat("Position %I64u closed successfully", ticket);
return true;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Example demonstration check: only open one test position
if(PositionsTotal() == 0)
{
OpenBuyOrder(InpLotSize, InpStopLossPoints, InpTakeProfitPoints, "Pineify CTrade Demo");
}
}
Copy this code into MetaEditor, save it in your MQL5 folder (Experts, Scripts, or Include), and compile with F7.
Generate custom MQL5 code with Pineify AI
Describe the trade execution, indicator calculations, risk management, or data processing logic you need. Pineify produces clean, typed MQL5 source code ready to compile in MetaEditor.
Frequently Asked Questions
Related MQL5 pages
Technical references
Risk and testing note
Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.