Complete MQL5 guide & code

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 educational EA order-execution examples.

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>. Buy requests a market long position. Pending orders use separate methods such as BuyLimit, BuyStop or OrderOpen.

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.

ParameterTypeDefaultDescription
volumedoubleRequiredTrade volume in lots (must conform to symbol lot step)
symbolconst stringNULLSymbol name. NULL selects the chart symbol _Symbol
pricedouble0.0Open price. 0.0 resolves to current SymbolInfoDouble(symbol, SYMBOL_ASK)
sldouble0.0Stop loss price level (must satisfy symbol stop level distance)
tpdouble0.0Take profit price level (must satisfy symbol stop level distance)
commentconst string""Custom string comment attached to the resulting deal and order

PositionClose and PositionModify Signatures

Both symbol and ticket overloads are available. Account mode changes the position selected by a symbol: netting has one aggregated position per instrument, while hedging can have several.

PositionClose(symbol) targets the symbol position in netting, and the lowest-ticket position for that symbol in hedging. PositionClose(ticket) targets the specified ticket. Check ownership before either request.

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.

MethodParametersReturn TypeAccount Mode
PositionClose(symbol, deviation)const string symbol, ulong deviation=ULONG_MAXboolNetting; lowest ticket in hedging
PositionClose(ticket, deviation)ulong ticket, ulong deviation=ULONG_MAXboolEither mode, specified ticket
PositionModify(ticket, sl, tp)ulong ticket, double sl, double tpboolEither mode, specified ticket
PositionModify(symbol, sl, tp)const string symbol, double sl, double tpboolNetting; lowest ticket in hedging

Return Code Verification and Execution Diagnostics

A true return from CTrade::Buy means the structures passed checks, not proof of a completed trade. Inspect ResultRetcode, ResultDeal and the resulting account state.

TRADE_RETCODE_DONE (10009) reports request completion; TRADE_RETCODE_PLACED (10008) reports an order placed, not a full fill. DONE_PARTIAL (10010) requires handling remaining volume. 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

Configure CTrade magic, deviation and symbol filling in OnInit. The demonstration is disabled by default; enabling AllowDemoOrder on a demo account permits one buy attempt per EA initialization while the account has no positions. It is a method-call example, not an entry strategy. The SL/TP inputs are points, not pips.

Error handling & safety rules

ModifyPositionSLTP and CloseSpecificPosition are illustrative helpers, not automatically triggered exits. They select the ticket, verify symbol/magic ownership and check the server result. The sample does not implement full tick-grid, volume-step, margin, stop/freeze-level or partial-fill recovery logic; test those for the broker and use account-state reconciliation before retrying.

MQL5 Code Implementation

//+------------------------------------------------------------------+
//|                                            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 bool AllowDemoOrder=false; // Explicit demo-only, one-attempt method example
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 request; still inspect server result

   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)
        {
         PrintFormat("Buy request completed. 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(!PositionSelectByTicket(ticket) || PositionGetString(POSITION_SYMBOL)!=_Symbol ||
      PositionGetInteger(POSITION_MAGIC)!=(long)InpMagicNumber) return false;
   if(!trade.PositionModify(ticket, newSL, newTP) || trade.ResultRetcode()!=TRADE_RETCODE_DONE)
     {
      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(!PositionSelectByTicket(ticket) || PositionGetString(POSITION_SYMBOL)!=_Symbol ||
      PositionGetInteger(POSITION_MAGIC)!=(long)InpMagicNumber) return false;
   if(!trade.PositionClose(ticket) || trade.ResultRetcode()!=TRADE_RETCODE_DONE)
     {
      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()
  {
   static bool attempted=false;
   if(!AllowDemoOrder || attempted || AccountInfoInteger(ACCOUNT_TRADE_MODE)!=ACCOUNT_TRADE_MODE_DEMO) return;
   if(PositionsTotal() == 0)
     {
      attempted=true; // Do not retry an ambiguous or rejected request automatically.
      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 generates editable MQL5 source code. Review its logic, request a syntax check, and compile and test the final file in MetaEditor.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.