轻松快捷开发 MetaTrader 程序的函数库 (第 二十七部分) :操控交易请求 - 下挂单·进阶篇
🛠️

轻松快捷开发 MetaTrader 程序的函数库 (第 二十七部分) :操控交易请求 - 下挂单·进阶篇

(2/3)· 从品种规格冲突到挂单错误自愈,手把手把延后请求写进函数库

含代码示例实战向 第 2/3 篇
很多人在 EA 初始化时直接给交易对象填默认值,结果下挂单被服务器以“不支持的订单到期类型”打回。问题不在策略,而在函数库没按品种规格纠正参数。本文顺着这个坑,把挂单延后请求补完。

「交易诊断字段与集合 ID 的硬编码约定」

在自建 EA 的调试面板里,先把俄语/英语双语标签写死成常量数组,是定位撤单与重发逻辑最快的办法。上面这段就列出了总交易尝试次数、请求 ID、服务端返回码、两种挂单请求类型等 7 个诊断项,MT5 终端里直接打印就能看到每次发单的来龙去脉。 集合列表用 16 进制宏隔离数据域:历史 0x777A、实时 0x777B、事件 0x777C、账户 0x777D、品种 0x777E。改这些值时注意别和平台内部对象 ID 撞车,否则 Collection 操作会静默失败。 挂单请求分两类——错误触发型(宏值 1)和主动请求型(宏值 2),对应枚举 ENUM_PENDING_REQUEST_TYPE 里的 PENDING_REQUEST_TYPE_ERROR 与 PENDING_REQUEST_TYPE_REQUEST。外汇与贵金属杠杆高,重发机制若不分清来源,可能在滑点行情里叠出双倍仓位,概率上偏向放大回撤。 SYMBOLS_COMMON_TOTAL 写死为 1000,意味着默认遍历池上限千个品种;做跨市场扫描时若券商符号数超这个值,要改宏重新编译,否则漏掉的品种不会报警。

MQL5 / C++
class="macro">#define COLLECTION_HISTORY_ID(0x777A)     class=class="str">"cmt">// Historical collection list ID
class="macro">#define COLLECTION_MARKET_ID(0x777B)     class=class="str">"cmt">// Market collection list ID
class="macro">#define COLLECTION_EVENTS_ID(0x777C)     class=class="str">"cmt">// Event collection list ID
class="macro">#define COLLECTION_ACCOUNT_ID(0x777D)     class=class="str">"cmt">// Account collection list ID
class="macro">#define COLLECTION_SYMBOLS_ID(0x777E)     class=class="str">"cmt">// Symbol collection list ID
class=class="str">"cmt">//--- Data parameters for file operations
class=class="str">"cmt">//--- Symbol parameters
class="macro">#define CLR_DEFAULT(0xFF000000) class=class="str">"cmt">// Default class="type">class="kw">color
class="macro">#define SYMBOLS_COMMON_TOTAL(class="num">1000)       class=class="str">"cmt">// Total number of working symbols
class=class="str">"cmt">//--- Pending request type IDs
class="macro">#define PENDING_REQUEST_ID_TYPE_ERR(class="num">1)       class=class="str">"cmt">// Type of a pending request created based on the server class="kw">return code
class="macro">#define PENDING_REQUEST_ID_TYPE_REQ(class="num">2)       class=class="str">"cmt">// Type of a pending request created by request
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Pending request type                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_PENDING_REQUEST_TYPE
  {
   PENDING_REQUEST_TYPE_ERROR=PENDING_REQUEST_ID_TYPE_ERR,   class=class="str">"cmt">// Pending request created based on the class="kw">return code or error
   PENDING_REQUEST_TYPE_REQUEST=PENDING_REQUEST_ID_TYPE_REQ, class=class="str">"cmt">// Pending request created by request
  };

◍ 把成交与有效期类型翻成可读日志

在 MT5 的 EA 调试里,交易请求结构体 MqlTradeRequest 里的填充方式(ENUM_ORDER_TYPE_FILLING)和挂单有效期(ENUM_ORDER_TYPE_TIME)都是以枚举值存在的。直接 Print 出来只是 ORDER_FILLING_IOC 这种机器字串,肉眼排查报错时很费劲。 下面两段函数就是把枚举映射成文字:OrderTypeFillingDescription 覆盖 FOK / IOC / RETURN 以及 WRONG_VALUE 四种情况,OrderTypeTimeDescription 覆盖 GTC / DAY / SPECIFIED / SPECIFIED_DAY 四种情况,未知值则退回 EnumToString 原样输出。 真正把信息聚合到日志的是 PrintRequestDescription。它把动作、魔法码、订单类型、品种、手数、挂单价、SL/TP、偏差、填充与有效期等 14 个字段用换行拼成一段 datas 文本。你在策略测试器里跑一遍,日志里就能看到每笔下单的完整中文(或终端语言)描述,而不是对着枚举猜。 外汇与贵金属杠杆高,这类日志只用于定位请求构造错误,不预示任何成交优劣。

MQL5 / C++
class="type">class="kw">string OrderTypeFillingDescription(class="kw">const ENUM_ORDER_TYPE_FILLING type)
  {
   class="kw">return
     (
       type==ORDER_FILLING_FOK     ?  CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER_FILLING_FOK)  :
       type==ORDER_FILLING_IOC     ?  CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER_FILLING_IOK)  :
       type==ORDER_FILLING_RETURN ?  CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER_FILLING_RETURN):
       type==WRONG_VALUE           ? "WRONG_VALUE"  :  EnumToString(type)
     );
  }
class="type">class="kw">string OrderTypeTimeDescription(class="kw">const ENUM_ORDER_TYPE_TIME type)
  {
   class="kw">return
     (
       type==ORDER_TIME_GTC           ?  CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER_TIME_GTC)          :
       type==ORDER_TIME_DAY           ?  CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER_TIME_DAY)          :
       type==ORDER_TIME_SPECIFIED     ?  CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER_TIME_SPECIFIED)    :
       type==ORDER_TIME_SPECIFIED_DAY ?  CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER_TIME_SPECIFIED_DAY):
       type==WRONG_VALUE              ? "WRONG_VALUE"  :  EnumToString(type)
     );
  }
class="type">void PrintRequestDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="type">class="kw">string datas=
     (
       " - "+RequestActionDescription(request)+"\n"+
       " - "+RequestMagicDescription(request)+"\n"+
       " - "+RequestOrderDescription(request)+"\n"+
       " - "+RequestSymbolDescription(request)+"\n"+
       " - "+RequestVolumeDescription(request)+"\n"+
       " - "+RequestPriceDescription(request)+"\n"+
       " - "+RequestStopLimitDescription(request)+"\n"+
       " - "+RequestStopLossDescription(request)+"\n"+
       " - "+RequestTakeProfitDescription(request)+"\n"+
       " - "+RequestDeviationDescription(request)+"\n"+
       " - "+RequestTypeDescription(request)+"\n"+
       " - "+RequestTypeFillingDescription(request)+"\n"+
       " - "+RequestTypeTimeDescription(request)+"\n"+

把交易请求拆成可读字符串

在 MT5 的 EA 调试里,直接 Print 一个 MqlTradeRequest 结构只会得到内存地址,看不出到底发了什么单。上面这组函数把请求对象逐个字段转成中文(或本地化)描述串,拼进 datas 变量后一次性打印,省去你手动对照结构体成员。 RequestActionDescription 用三元运算符把 action 枚举映射成文本:TRADE_ACTION_DEAL 对应市价成交,TRADE_ACTION_PENDING 对应挂单,SLTP 改止损止盈,MODIFY 改单,REMOVE 删挂单,CLOSE_BY 对冲平仓,其余归为未知动作。这样日志里一眼能看出这笔请求想干什么。 RequestOrderDescription 对 order 字段做了防护:只有 request.order>0 才输出具体 ticket,否则返回「未设置」。外汇与贵金属杠杆高,误把未初始化订单号当有效参数发回去,可能触发异常成交,这类边界判断在实盘代码里不能省。 RequestVolumeDescription 里 DigitsLots(request.symbol) 取该品种手数精度,dg 为 0 时强制 dgl=1,避免 0 位小数导致体积显示为空。复制这段代码到你的 CTrade 封装类,开 MT5 用 EURUSD 跑一笔 0.01 手市价单,日志会输出带「动作 / 魔术码 / 订单号 / 品种 / 手数」的分段信息,验证字段解析是否对齐。

MQL5 / C++
   " - "+RequestExpirationDescription(request)+"\n"+
   " - "+RequestCommentDescription(request)+"\n"+
   " - "+RequestPositionDescription(request)+"\n"+
   " - "+RequestPositionByDescription(request)
   );
  Print("================== ",CMessage::Text(MSG_LIB_TEXT_REQUEST_DATAS)," ==================\n",datas,"\n");
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the executed action type description                       |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestActionDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="type">int code_descr=
    (
     request.action==TRADE_ACTION_DEAL      ?  MSG_LIB_TEXT_REQUEST_ACTION_DEAL      :
     request.action==TRADE_ACTION_PENDING   ?  MSG_LIB_TEXT_REQUEST_ACTION_PENDING   :
     request.action==TRADE_ACTION_SLTP      ?  MSG_LIB_TEXT_REQUEST_ACTION_SLTP      :
     request.action==TRADE_ACTION_MODIFY    ?  MSG_LIB_TEXT_REQUEST_ACTION_MODIFY    :
     request.action==TRADE_ACTION_REMOVE    ?  MSG_LIB_TEXT_REQUEST_ACTION_REMOVE    :
     request.action==TRADE_ACTION_CLOSE_BY  ?  MSG_LIB_TEXT_REQUEST_ACTION_CLOSE_BY  :
     MSG_LIB_TEXT_REQUEST_ACTION_UNCNOWN
    );
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_ACTION)+": "+CMessage::Text(code_descr);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the magic number value description                         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestMagicDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_ORD_MAGIC)+": "+(class="type">class="kw">string)request.magic;
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the order ticket value description                         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestOrderDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_ORDER)+": "+(request.order>class="num">0 ? (class="type">class="kw">string)request.order : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the trading instrument name description                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestSymbolDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_SYMBOL)+": "+request.symbol;
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the request volume description                             |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestVolumeDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="type">int dg=(class="type">int)DigitsLots(request.symbol);
   class="type">int dgl=(dg==class="num">0 ? class="num">1 : dg);

「交易请求里各价格字段的回显写法」

在 MT5 的 CTrade 封装逻辑里,把 MqlTradeRequest 结构体转成可读字符串时,价格类字段不能硬编码小数位,必须按品种动态取精度。上面这组函数就演示了 volume、price、stoplimit、sl、tp 五类数值怎么回显。 核心区别在于:手数 volume 用的是独立变量 dgl(可能是账户小数位设置),而 price / stoplimit / sl / tp 全部走 SymbolInfoInteger(request.symbol, SYMBOL_DIGITS) 强转 int 后交给 DoubleToString。欧元兑美元这类 5 位报价品种,SL 写 1.08523 就不会被截成 1.09。 deviation 字段直接强转 string,不调精度函数——它本身是整型点数偏差,硬套 DoubleToString 反而多此一举。type 则委托给 OrderTypeDescription 做枚举翻译,不在本层拼字符串。 开 MT5 把这段塞进你的调试面板,挂一单 XAUUSD 观察 sl 回显位数:若 SYMBOL_DIGITS 返回 2,1.23456 的止损会显示成 1.23,贵金属报价跳变快时这种截断可能让你误判实际风险。

MQL5 / C++
class="type">class="kw">string RequestPriceDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_PRICE)+": "+(request.price>class="num">0 ? DoubleToString(request.price,(class="type">int)SymbolInfoInteger(request.symbol,SYMBOL_DIGITS)) : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class="type">class="kw">string RequestStopLimitDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_STOPLIMIT)+": "+(request.stoplimit>class="num">0 ? DoubleToString(request.stoplimit,(class="type">int)SymbolInfoInteger(request.symbol,SYMBOL_DIGITS)) : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class="type">class="kw">string RequestStopLossDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_SL)+": "+(request.sl>class="num">0 ? DoubleToString(request.sl,(class="type">int)SymbolInfoInteger(request.symbol,SYMBOL_DIGITS)) : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class="type">class="kw">string RequestTakeProfitDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_TP)+": "+(request.tp>class="num">0 ? DoubleToString(request.tp,(class="type">int)SymbolInfoInteger(request.symbol,SYMBOL_DIGITS)) : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class="type">class="kw">string RequestDeviationDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_DEVIATION)+": "+(class="type">class="kw">string)request.deviation;
  }
class="type">class="kw">string RequestTypeDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_TYPE)+": "+OrderTypeDescription(request.type);
  }

◍ 把交易请求字段翻成可读文本

在 MT5 的 EA 调试里,直接打印 MqlTradeRequest 结构往往是一串看不懂的数字和枚举。下面这组函数把常用字段接上本地化文案,返回「字段名: 值」格式,方便写日志或弹窗。 RequestTypeFillingDescription 取 type_filling 的填充方式说明;RequestTypeTimeDescription 取 type_time 的挂单生命周期说明;RequestExpirationDescription 判断 expiration 大于 0 才格式化为时间字符串,否则标「未设置」。 RequestCommentDescription 对 comment 做了空串和 NULL 双判断,避免老版本终端把未赋值注释当成乱码输出;RequestPositionDescription 与 RequestPositionByDescription 则分别处理持仓单号和对冲反向单号,ticket 为 0 时统一回退到「未设置」文案。 复制进你的 include 工具类,调用时传入 request 引用即可在专家日志里看到结构化输出,省去手动解析枚举的功夫。外汇与贵金属杠杆高,日志仅辅助排查,不构成任何方向判断。

MQL5 / C++
class="type">class="kw">string RequestTypeFillingDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_TYPE_FILLING)+": "+OrderTypeFillingDescription(request.type_filling);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the request order lifetime type description                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestTypeTimeDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_TYPE_TIME)+": "+OrderTypeTimeDescription(request.type_time);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the request order expiration time description              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestExpirationDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_EXPIRATION)+": "+(request.expiration>class="num">0 ? TimeToString(request.expiration) : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the request order comment description                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestCommentDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_COMMENT)+": "+(request.comment!="" && request.comment!=NULL ? "\""+request.comment+"\"" : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the request position ticket description                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestPositionDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_POSITION)+": "+(request.position>class="num">0 ? (class="type">class="kw">string)request.position : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Return the request opposite position ticket description           |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string RequestPositionByDescription(class="kw">const class="type">MqlTradeRequest &request)
  {
   class="kw">return CMessage::Text(MSG_LIB_TEXT_REQUEST_POSITION_BY)+": "+(request.position_by>class="num">0 ? (class="type">class="kw">string)request.position_by : CMessage::Text(MSG_LIB_PROP_NOT_SET));
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

处理无买卖价品种与延后请求骨架

部分品种图表以 Last 价构建,盘中可能缺失 Ask 或 Bid 其一。CSymbol 抽象类里需先判定图表构建类型:基于 Last 时再探测 Ask/Bid 是否存在,为零则回退 Last 价,否则取真实报价。这一改动让函数库在贵金属某些交叉盘上不再因取价失败而中断。 时间方法返回类型由 datetime 改为 ulong,以毫秒精度传递;同时新增三个探测方法。原出价三方法补上“是否为零”的判断,逻辑变成:出价图表直接返回,Last 图表下出价为零取 Last,否则取 Bid。 魔幻数字中若嵌了延后请求 ID,原先在日志里不显示。在 EventModify / EventOrderPlaced / EventOrderRemoved / EventPositionClose / EventPositionOpen 五个文件里,把单字符串替换成双字符串,就把延后 ID 描述带进日志了。 TradeObj.mqh 公开段挂了几个返回 MqlTradeRequest 字段说明的方法,直接调服务函数;开仓方法补了订单填充类型参数,声明和实现都要同步改。CPendingReq 私密段加 m_type 存延后请求类型,公开段加返回服务器代码、属性说明、Type() 虚函数和整对象日志输出。 Compare() 原来只按 request ID 比,现在引入 mode:0 比 ID,非 0 比类型。构造函数里按服务器返回码定类型——大于 0 是服务器错误生成,等于 0 是程序请求生成。 CTrading 私密和公开开仓都加了填充类型参数;RequestErrorsCorrecting() 补了到期类型纠正应对“无效订单到期日期”。全局把 Ask()/Bid() 搜替换成 AskLast()/BidLast(),下挂单私密方法里接了创建延后请求模块,新对象属性直接打印日志便于调试。 CEngine 发交易请求的方法定义里也加了填充类型参数,默认 -1 时从品种对象取实际值。这些就是本轮剔除交易类缺陷、铺延后请求底子的全部改动,外汇与贵金属杠杆高,改完请在 MT5 用真实点差环境跑一轮挂单回测验证取价回退是否生效。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//| Methods of a simplified access to the order object properties&nbsp;&nbsp;  |</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//--- Integer properties</span>
&nbsp;&nbsp; <span class="keyword">class="type">long</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Status(<span class="keyword">class="type">void</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="kw">const</span> { <span class="keyword">class="kw">return</span> <span class="keyword">this</span>.GetProperty(SYMBOL_PROP_STATUS);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp; <span class="keyword">class="type">int</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IndexInMarketWatch(<span class="keyword">class="type">void</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="kw">const</span> { <span class="keyword">class="kw">return</span> (<span class="keyword">class="type">int</span>)<span class="keyword">this</span>.GetProperty(SYMBOL_PROP_INDEX_MW);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp; <span class="keyword">class="type">bool</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IsCustom(<span class="keyword">class="type">void</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="kw">const</span> { <span class="keyword">class="kw">return</span> (<span class="keyword">class="type">bool</span>)<span class="keyword">this</span>.GetProperty(SYMBOL_PROP_CUSTOM);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
把重复劳动交给小布
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到品种规格与挂单报错的自检提示,你专注决策逻辑即可。

常见问题

交易类构造函数里硬写了默认值,部分品种规格并不支持,请求带着无效数据发出就会触发该错误,需在请求中按品种规格显式指定正确值。
能在日志里完整打印挂单请求的所有参数,方便排查延后请求在重试或纠错时的实际取值,测试更直观。
可以,小布盯盘对应品种页内置了规格与报错自检,能提示到期类型等参数是否越界,减少手动翻规格的时间。
同值 ID 会让对象识别与集合管理混淆,本文提到 COLLECTION_HISTORY_ID 与 CList 类型撞值,应在自定义库里避开这类复用。
传 -1 表示沿用按品种规格预设的正确默认,只有显式传其他值才覆盖,无效时仍由交易类纠错,兼顾自动与灵活。