AlgoPro UniversityCourse home
Part 9 · Lesson

Placing orders with CTrade

Include Trade.mqh, meet the CTrade class, place Buy/Sell with stop-loss and take-profit, close the opposite position first, and enforce one-position-at-a-time — the full executable EA.

You can send orders in raw MQL5 by filling in an MqlTradeRequest struct and calling OrderSend — but it is fiddly and error-prone. MetaQuotes ships a standard-library class that wraps all of it: CTrade. It is the professional default, and it turns "place a buy with a stop and target" into a single readable line.

Include it and instantiate it

mql5Bringing CTrade into your EA
class="c">#include <Trade/Trade.mqh>   class="c">// the standard-library trade class

CTrade trade;                 class="c">// one global instance the whole EA uses

That #include pulls in the Trade.mqh header shipped with MT5. CTrade trade; creates one object; you configure it once in OnInit and call its methods from OnTick.

Configure it in OnInit

mql5Stamp your magic number and set slippage tolerance
input ulong MagicNumber      = class="n">8080;   class="c">// this EA's signature on its orders
input ulong MaxSlippagePoints = class="n">20;    class="c">// max deviation we accept, in points

int OnInit()
{
   trade.SetExpertMagicNumber(MagicNumber);       class="c">// tag every order as ours
   trade.SetDeviationInPoints(MaxSlippagePoints); class="c">// tolerate small price moves
   trade.SetTypeFillingBySymbol(_Symbol);         class="c">// pick a valid fill policy
   class="c">// ... (create MA handles as before) ...
   return(INIT_SUCCEEDED);
}

Buy and Sell with a stop and a target

The two methods you will use constantly are trade.Buy() and trade.Sell(). Each takes a volume and, optionally, symbol, price, stop-loss, take-profit and a comment. Passing price 0.0 means "at market". The stop and target are absolute *prices*, so we convert our pip inputs into price levels off the correct side of the market — buy off the ask, sell off the bid.

mql5Opening a long and a short, with SL and TP
input double Lots           = class="n">0.10;   class="c">// trade size
input double StopLossPips   = class="n">40;     class="c">// stop distance in pips
input double TakeProfitPips = class="n">80;     class="c">// target distance in pips

class="c">// One pip as a price offset (handles class="n">3/class="n">5-digit brokers).
double PipSize()
{
   return((_Digits == class="n">3 || _Digits == class="n">5) ? class="n">10 * _Point : _Point);
}

void OpenLong()
{
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double sl  = ask - StopLossPips   * PipSize();
   double tp  = ask + TakeProfitPips * PipSize();
   class="c">// Buy(volume, symbol, price, sl, tp, comment)
   if(!trade.Buy(Lots, _Symbol, ask, sl, tp, class="s">"MA cross long"))
      Print(class="s">"Buy failed: ", trade.ResultRetcodeDescription());
}

void OpenShort()
{
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double sl  = bid + StopLossPips   * PipSize();
   double tp  = bid - TakeProfitPips * PipSize();
   if(!trade.Sell(Lots, _Symbol, bid, sl, tp, class="s">"MA cross short"))
      Print(class="s">"Sell failed: ", trade.ResultRetcodeDescription());
}

Close what you hold

On a cross, a trend-follower flips: close any short before going long, and vice-versa. CTrade makes closing trivial with trade.PositionClose(_Symbol), which closes the open position on that symbol. Combined with the HasOpenPosition helper from the indicators lesson, this gives us clean one-position-at-a-time behaviour.

mql5Read our current direction, then flip cleanly
class="c">// Returns +class="n">1 if we hold a long, -class="n">1 for a short, class="n">0 for flat (this EA only).
int CurrentDirection()
{
   for(int i = PositionsTotal() - class="n">1; i >= class="n">0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket == class="n">0) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol)     continue;
      if(PositionGetInteger(POSITION_MAGIC)  != MagicNumber) continue;
      long type = PositionGetInteger(POSITION_TYPE);
      return(type == POSITION_TYPE_BUY ? class="n">1 : -class="n">1);
   }
   return(class="n">0);
}

The full executable EA

Here is the complete OnTick that ties the signal engine to the order engine. On a bullish cross it closes any short and opens a long — but only if it is not already long. The mirror logic handles the bearish cross. This is a real, coherent Expert Advisor.

mql5OnTick — signal wired to execution, one position at a time
void OnTick()
{
   class="c">// class="n">1. Only act on a new bar.
   datetime t = iTime(_Symbol, _Period, class="n">0);
   if(t == lastBarTime) return;
   lastBarTime = t;

   class="c">// class="n">2. Read the last two closed MA values.
   double fast[], slow[];
   if(!ReadMAs(fast, slow)) return;

   bool crossUp   = (fast[class="n">1] <= slow[class="n">1]) && (fast[class="n">0] > slow[class="n">0]);
   bool crossDown = (fast[class="n">1] >= slow[class="n">1]) && (fast[class="n">0] < slow[class="n">0]);

   int dir = CurrentDirection();   class="c">// +class="n">1 long, -class="n">1 short, class="n">0 flat

   class="c">// class="n">3. Bullish cross: go long (flip out of any short first).
   if(crossUp && dir <= class="n">0)
   {
      if(dir < class="n">0) trade.PositionClose(_Symbol);   class="c">// close the short
      OpenLong();
   }
   class="c">// class="n">4. Bearish cross: go short (flip out of any long first).
   else if(crossDown && dir >= class="n">0)
   {
      if(dir > class="n">0) trade.PositionClose(_Symbol);    class="c">// close the long
      OpenShort();
   }
}

The EA is complete. But "it compiles and trades on demo" is the *start* of the real work, not the end. The final lesson takes this exact EA into the Strategy Tester — to measure it, optimise it honestly, and only then think about going live.