首页 / 交易学院 / 小布知识库 / MQL5 标准交易类库:CTrade、CAccountInfo 与 CPositionInfo
MQL5 标准交易类库:CTrade、CAccountInfo 与 CPositionInfo
🤖

MQL5 标准交易类库:CTrade、CAccountInfo 与 CPositionInfo

EA 开发实战 难度 · 进阶 2013 11 分钟阅读
标准类库交易类MQL5

一、标准交易类库能省多少事

早期 EA 要手写交易请求结构体、填十几个字段、处理异步回执,几百行代码还容易错。MQL5 标准库(MQL5\Include\Trade 与 MQL5\Include\Chart 等)把这些封装成了 CTrade、CAccountInfo、CPositionInfo、COrderInfo、CSymbolInfo 等类。用它们,下单、查持仓、校验账户状态都变成一两行调用。本文聚焦交易类。

二、核心类职责

三、CTrade 关键方法

最常用的是市价单与持仓操作。注意 MQL5 交易是异步的:函数返回 true 只代表请求已发出,最终是否成交要看 ResultDeal()。

四、下单前必须做的校验

直接 Buy() 很容易因为“市场关闭”“保证金不足”“止损太近”而失败。标准库提供了下单前的检查点:

CSymbolInfo mysymbol; CAccountInfo myaccount; CTrade mytrade;
mysymbol.Name(_Symbol);
mytrade.SetExpertMagicNumber(EA_Magic);
mytrade.SetDeviationInPoints(dev);

if(!mysymbol.RefreshRates()) { Alert("报价错误"); return; }
if(!(myaccount.TradeAllowed() && myaccount.TradeExpert() && mysymbol.IsSynchronized()))
  { Alert("不可交易"); return; }

double price = NormalizeDouble(mysymbol.Ask(), _Digits);
double sl = NormalizeDouble(mysymbol.Ask() - STP*_Point, _Digits);
if(mytrade.Buy(Lot, _Symbol, price, sl, tp))
   Alert("成交单号:", mytrade.ResultDeal());
else
   Alert("失败:", mytrade.ResultRetcodeDescription());

五、读持仓与读挂单

平仓或改单前,先用 CPositionInfo::Select(_Symbol) 选中当前品种持仓,再用 Volume()/StopLoss()/TakeProfit()/PriceOpen() 读字段。挂单则用 COrderInfo::Select(ticket) 按单号选中。注意一个品种可能同时有多笔挂单,要遍历 OrderGetTicket(j) 逐个处理。

六、常见错误与排查

⚠ 下单失败先查这三处
1) Retcode:每次操作后必须看 ResultRetcodeDescription(),Invalid Stops 常见原因是 SL/TP 距离小于 StopsLevel 或未 NormalizeDouble。2) 异步成交:函数返回 true 不等于已成交,要用 ResultDeal() 或等 OnTrade 确认;价格跳变用 SetDeviationInPoints 容差。3) 市场状态:TradeAllowed()/TradeExpert()/IsSynchronized() 任一为 false 都应中止下单,RefreshRates() 返回 false 说明报价获取失败。

七、CTrade / CPosition / COrder 分工

标准交易类库把交易动作拆清楚:CTrade 负责发单(Buy/Sell/PositionModify),CPosition 负责读当前持仓状态,COrder 负责管挂单。分工后你不必手写一大堆 OrderSend 与状态查询。

用类库最大的好处是「少写易错代码」:下单的异步、重试、错误码处理都被封装,你调一个语义清晰的方法即可,出错时类库也会返回可读的错误。

八、异步下单与 OnTrade 确认

CTrade 默认异步(OrderSendAsync),Send 不等于已成。成交要靠 OnTrade 事件核对真实持仓与历史成交,而不是发完就当真。这是标准库强制你养成的正确习惯。

✦ Send 不等于成
CTrade 异步发单,结果在 OnTrade 里确认。发完立刻读持仓会读到旧状态,这是新手重复开仓的根源。

九、实战:一键平仓与部分平仓

用类库写「平掉当前品种全部持仓」「平掉一半」非常简短:遍历 PositionSelect 后调 PositionClose 或 PositionClosePartial。这类常用动作封装成函数,多个 EA 都能直接复用。

注意部分平仓会改变剩余仓位的开仓价(净额制下是加权平均),平仓后读 POSITION_PRICE_OPEN 要用新值,别缓存旧开仓价。

十、小结

✦ 小结
标准交易类库把交易拆成 CTrade(发单)、CPosition(读持仓)、COrder(管挂单),封装了异步与错误处理的易错细节。牢记 Send 不等于已成、成交在 OnTrade 确认;平仓/部分平仓封装成函数即可多 EA 复用。

常见问题

不是。MQL5 交易请求是异步的,Buy() 返回 true 只表示请求已成功发出。是否真正成交要看 ResultDeal() 是否为有效单号,或在 OnTrade/OnTradeTransaction 里确认。
最常见两个原因:一是 SL/TP 距离小于品种的 StopsLevel(最小止损水平点数);二是价格没用 NormalizeDouble(..., _Digits) 对齐小数位。下单前用 CSymbolInfo::StopsLevel() 检查距离,价格务必标准化。
有必要。下单前必须刷新拿到最新 Ask/Bid,否则可能用陈旧报价下单导致滑点过大或拒绝。同样,TradeAllowed/TradeExpert/IsSynchronized 也应在下单前确认,避免在市场关闭或数据未同步时发单。