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
class="c">#include <Trade/Trade.mqh> class="c">// the standard-library trade class
CTrade trade; class="c">// one global instance the whole EA usesThat #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
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.
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.
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.
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.