轻松快捷开发 MetaTrader 程序的函数库 (第 三十一部分) :延后交易请求 - 在特定条件下开仓·进阶篇
(2/3)· 手敲条件判断容易漏单?用二维数组把价格、时间等触发逻辑一次性封装进交易库
◍ 挂单按品种属性触发的枚举映射
在 MT5 的挂单激活条件体系里,有一组枚举专门绑定到「品种自身属性」而非价格或指标。它们把 Pending 订单的激活源直接挂到交易品种的运行参数上,常见于期货与债券类工具,外汇和贵金属盘面上多数仅作底层支持、并不常用。 下面这段代码列出了从时间类到数值类的完整映射。例如 PEND_REQ_ACTIVATE_BY_SYMBOL_START_TIME 对应 MSG_SYM_PROP_START_TIME,含义是按品种交易开始日激活(期货常用);PEND_REQ_ACTIVATE_BY_SYMBOL_TRADE_STOPS_LEVEL 对应 MSG_SYM_PROP_TRADE_STOPS_LEVEL,是按当前收盘价最小止损距离(点数)激活。 双精度类里值得盯的是日内极值:PEND_REQ_ACTIVATE_BY_SYMBOL_BIDHIGH / BIDLOW 绑定当日 Bid 最高与最低,ASKHIGH / ASKLOW 同理对应 Ask,LASTHIGH / LASTLOW 抓 Last 成交价的日内边界。量能方面 VOLUME_REAL 及 VOLUMEHIGH_REAL / VOLUMELOW_REAL 分别盯日成交量与日内量能上下沿。 债券与期权线也不能忽略:OPTION_STRIKE 绑行权价,TRADE_ACCRUED_INTEREST 绑应计利息,TRADE_FACE_VALUE 绑票面值,TRADE_LIQUIDITY_RATE 绑流动性比率(可作保证金的资产占比)。外汇贵金属交易者若拿这套做跨品种监控,需明白杠杆与跳空带来的高风险,参数误用可能倾向触发非预期挂单。
PEND_REQ_ACTIVATE_BY_SYMBOL_START_TIME = MSG_SYM_PROP_START_TIME, class=class="str">"cmt">// Activate by an instrument trading start date(usually used for futures) PEND_REQ_ACTIVATE_BY_SYMBOL_EXPIRATION_TIME = MSG_SYM_PROP_EXPIRATION_TIME, class=class="str">"cmt">// Activate by an instrument trading completion date(usually used for futures) PEND_REQ_ACTIVATE_BY_SYMBOL_TRADE_STOPS_LEVEL = MSG_SYM_PROP_TRADE_STOPS_LEVEL, class=class="str">"cmt">// Activate by the minimum indent from the current close price(in points) for setting Stop orders PEND_REQ_ACTIVATE_BY_SYMBOL_TRADE_FREEZE_LEVEL = MSG_SYM_PROP_TRADE_FREEZE_LEVEL, class=class="str">"cmt">// Activate by trade operation freeze distance(in points) class=class="str">"cmt">//--- class="type">class="kw">double PEND_REQ_ACTIVATE_BY_SYMBOL_BIDHIGH = MSG_SYM_PROP_BIDHIGH, class=class="str">"cmt">// Activate by a maximum Bid of the day PEND_REQ_ACTIVATE_BY_SYMBOL_BIDLOW = MSG_SYM_PROP_BIDLOW, class=class="str">"cmt">// Activate by a minimum Bid of the day PEND_REQ_ACTIVATE_BY_SYMBOL_ASKHIGH = MSG_SYM_PROP_ASKHIGH, class=class="str">"cmt">// Activate by a maximum Ask of the day PEND_REQ_ACTIVATE_BY_SYMBOL_ASKLOW = MSG_SYM_PROP_ASKLOW, class=class="str">"cmt">// Activate by a minimum Ask of the day PEND_REQ_ACTIVATE_BY_SYMBOL_LASTHIGH = MSG_SYM_PROP_LASTHIGH, class=class="str">"cmt">// Activate by the maximum Last of the day PEND_REQ_ACTIVATE_BY_SYMBOL_LASTLOW = MSG_SYM_PROP_LASTLOW, class=class="str">"cmt">// Activate by the minimum Last of the day PEND_REQ_ACTIVATE_BY_SYMBOL_VOLUME_REAL = MSG_SYM_PROP_VOLUME_REAL, class=class="str">"cmt">// Activate by Volume of the day PEND_REQ_ACTIVATE_BY_SYMBOL_VOLUMEHIGH_REAL = MSG_SYM_PROP_VOLUMEHIGH_REAL, class=class="str">"cmt">// Activate by a maximum Volume of the day PEND_REQ_ACTIVATE_BY_SYMBOL_VOLUMELOW_REAL = MSG_SYM_PROP_VOLUMELOW_REAL, class=class="str">"cmt">// Activate by a minimum Volume of the day PEND_REQ_ACTIVATE_BY_SYMBOL_OPTION_STRIKE = MSG_SYM_PROP_OPTION_STRIKE, class=class="str">"cmt">// Activate by an option execution price PEND_REQ_ACTIVATE_BY_SYMBOL_TRADE_ACCRUED_INTEREST = MSG_SYM_PROP_TRADE_ACCRUED_INTEREST, class=class="str">"cmt">// Activate by an accrued interest PEND_REQ_ACTIVATE_BY_SYMBOL_TRADE_FACE_VALUE = MSG_SYM_PROP_TRADE_FACE_VALUE, class=class="str">"cmt">// Activate by a face value – initial bond value set by an issuer PEND_REQ_ACTIVATE_BY_SYMBOL_TRADE_LIQUIDITY_RATE = MSG_SYM_PROP_TRADE_LIQUIDITY_RATE class=class="str">"cmt">// Activate by a liquidity rate – the share of an asset that can be used for a margin
挂单激活的事件与品种属性触发维度
在 MQL5 的挂单请求库里,激活条件可以拆成两条线:一条盯品种属性,一条盯账户事件。前者覆盖掉期、会话成交量、会话高低价等十几类符号级数据,后者只认持仓与挂单状态变化。 品种属性触发里,多头掉期 PEND_REQ_ACTIVATE_BY_SYMBOL_SWAP_LONG 对应 MSG_SYM_PROP_SWAP_LONG,空头掉期同理;会话类则从当前会话总成交量 MSG_SYM_PROP_SESSION_VOLUME 一直到会话限价最小值 MSG_SYM_PROP_SESSION_PRICE_LIMIT_MIN,共 13 个枚举项,基本把日内会话统计维度拉满了。 事件触发枚举 ENUM_PEND_REQ_ACTIVATE_BY_EVENT 目前列了 4 个有效值:未设置、持仓开仓、持仓平仓、挂单放置。实战中若想让 EA 在自身平仓后自动挂反向单,就绑 PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED。外汇与贵金属波动剧烈,这类自动链单逻辑可能放大滑点与隔夜风险,上 MT5 策略测试器跑历史会话数据前先确认品种支持对应属性。
PEND_REQ_ACTIVATE_BY_SYMBOL_SWAP_LONG = MSG_SYM_PROP_SWAP_LONG, class=class="str">"cmt">// Activate by a class="type">long swap value PEND_REQ_ACTIVATE_BY_SYMBOL_SWAP_SHORT = MSG_SYM_PROP_SWAP_SHORT, class=class="str">"cmt">// Activate by a class="type">short swap value PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_VOLUME = MSG_SYM_PROP_SESSION_VOLUME, class=class="str">"cmt">// Activate by a summary volume of the current session deals PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_TURNOVER = MSG_SYM_PROP_SESSION_TURNOVER, class=class="str">"cmt">// Activate by a summary turnover of the current session PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_INTEREST = MSG_SYM_PROP_SESSION_INTEREST, class=class="str">"cmt">// Activate by a summary open interest PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_BUY_ORDERS_VOLUME = MSG_SYM_PROP_SESSION_BUY_ORDERS_VOLUME, class=class="str">"cmt">// Activate by the current volume of Buy orders PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_SELL_ORDERS_VOLUME= MSG_SYM_PROP_SESSION_SELL_ORDERS_VOLUME, class=class="str">"cmt">// Activate by the current volume of Sell orders PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_OPEN = MSG_SYM_PROP_SESSION_OPEN, class=class="str">"cmt">// Activate by an open price of the current session PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_CLOSE = MSG_SYM_PROP_SESSION_CLOSE, class=class="str">"cmt">// Activate by a close price of the current session PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_AW = MSG_SYM_PROP_SESSION_AW, class=class="str">"cmt">// Activate by an average weighted session price PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_PRICE_SETTLEMENT = MSG_SYM_PROP_SESSION_PRICE_SETTLEMENT, class=class="str">"cmt">// Activate by a settlement price of the current session PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_PRICE_LIMIT_MIN = MSG_SYM_PROP_SESSION_PRICE_LIMIT_MIN, class=class="str">"cmt">// Activate by a minimum session price PEND_REQ_ACTIVATE_BY_SYMBOL_SESSION_PRICE_LIMIT_MAX = MSG_SYM_PROP_SESSION_PRICE_LIMIT_MAX, class=class="str">"cmt">// Activate by a maximum session price }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Possible criteria for activating requests by events | class=class="str">"cmt">//+------------------------------------------------------------------+ enum ENUM_PEND_REQ_ACTIVATE_BY_EVENT { PEND_REQ_ACTIVATE_BY_EVENT_EMPTY = MSG_LIB_PROP_NOT_SET, class=class="str">"cmt">// Value not set PEND_REQ_ACTIVATE_BY_EVENT_POSITION_OPENED = MSG_EVN_STATUS_MARKET_POSITION, class=class="str">"cmt">// Position opened PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED = MSG_EVN_STATUS_HISTORY_POSITION, class=class="str">"cmt">// Position closed PEND_REQ_ACTIVATE_BY_EVENT_PENDING_ORDER_PLASED = MSG_EVN_PENDING_ORDER_PLASED, class=class="str">"cmt">// Pending order placed
「挂单激活事件里的账户与成交类枚举」
在 MT5 的挂单请求激活机制里,有一部分枚举专门绑定账户资金和成交状态变化,用来决定挂单是否在对应事件发生时被激活。下面这段映射把 PEND_REQ_ACTIVATE_BY_EVENT_* 常量逐一对应到具体的事件消息码,覆盖从挂单删除到分红、税务的完整清单。
账户侧事件占比明显偏高:光是佣金相关就拆出日常佣金、月佣、代理日佣、代理月佣 4 种,分别映射到 MSG_EVN_ACCOUNT_COMISSION_DAILY 与 MSG_EVN_ACCOUNT_COMISSION_MONTHLY 等。这说明经纪商在日终和月终结算时触发的挂单激活逻辑,是实盘里最容易被忽略的一类定时唤醒。
成交侧只列了 MSG_EVN_BUY_CANCELLED 和 MSG_EVN_SELL_CANCELLED 两个取消事件,没有正常成交事件——意味着依赖「成交取消」去反手挂单的策略,只能在撤单动作上接钩子,而不能指望成交本身来激活。外汇与贵金属品种受经纪商结算规则影响大,这类事件触发存在滑点和延迟,属高风险操作环境。
PEND_REQ_ACTIVATE_BY_EVENT_PENDING_ORDER_REMOVED = MSG_EVN_PENDING_ORDER_REMOVED, class=class="str">"cmt">// Pending order removed PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_CREDIT = MSG_EVN_ACCOUNT_CREDIT, class=class="str">"cmt">// Accruing credit(class="num">3) PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_CHARGE = MSG_EVN_ACCOUNT_CHARGE, class=class="str">"cmt">// Additional charges PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_CORRECTION = MSG_EVN_ACCOUNT_CORRECTION, class=class="str">"cmt">// Correcting entry PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_BONUS = MSG_EVN_ACCOUNT_BONUS, class=class="str">"cmt">// Charging bonuses PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_COMISSION = MSG_EVN_ACCOUNT_COMISSION, class=class="str">"cmt">// Additional commissions PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_COMISSION_DAILY = MSG_EVN_ACCOUNT_COMISSION_DAILY, class=class="str">"cmt">// Commission charged at the end of a day PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_COMISSION_MONTHLY = MSG_EVN_ACCOUNT_COMISSION_MONTHLY, class=class="str">"cmt">// Commission charged at the end of a trading month PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_COMISSION_AGENT_DAILY = MSG_EVN_ACCOUNT_COMISSION_AGENT_DAILY, class=class="str">"cmt">// Agent commission charged at the end of a trading day PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_COMISSION_AGENT_MONTHLY = MSG_EVN_ACCOUNT_COMISSION_AGENT_MONTHLY, class=class="str">"cmt">// Agent commission charged at the end of a month PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_INTEREST = MSG_EVN_ACCOUNT_INTEREST, class=class="str">"cmt">// Accruing interest on free funds PEND_REQ_ACTIVATE_BY_EVENT_BUY_CANCELLED = MSG_EVN_BUY_CANCELLED, class=class="str">"cmt">// Canceled buy deal PEND_REQ_ACTIVATE_BY_EVENT_SELL_CANCELLED = MSG_EVN_SELL_CANCELLED, class=class="str">"cmt">// Canceled sell deal PEND_REQ_ACTIVATE_BY_EVENT_DIVIDENT = MSG_EVN_DIVIDENT, class=class="str">"cmt">// Accruing dividends PEND_REQ_ACTIVATE_BY_EVENT_DIVIDENT_FRANKED = MSG_EVN_DIVIDENT_FRANKED, class=class="str">"cmt">// Accrual of franked dividend PEND_REQ_ACTIVATE_BY_EVENT_TAX = MSG_EVN_TAX class=class="str">"cmt">// Tax accrual
◍ 挂单按账户与持仓事件触发的枚举映射
在 MQL5 里,挂单可以绑定到一类「账户或交易事件」上,当事件发生时才被激活。下面这组枚举把具体事件常量映射到对应的消息标识,写 EA 时用它们能精确控制挂单何时进场。 注意区分净仓模式(netting)与对冲模式:像 PEND_REQ_ACTIVATE_BY_EVENT_POSITION_REVERSED_BY_MARKET 只在净仓账户里由反向市价单触发反转,而对冲账户不会走这条路径。 部分成交类事件也很细——挂单部分激活、持仓部分平仓、被反向单部分平掉,都有独立常量。若你的风控逻辑依赖「部分成交后补挂」,必须分开监听 MSG_EVN_ACTIVATED_PENDING_PARTIALLY 与 MSG_EVN_POSITION_OPENED_PARTIALLY,二者触发语义不同。 修改挂单价格或止损也会产生激活事件:MSG_EVN_MODIFY_ORDER_PRICE 与 MSG_EVN_MODIFY_ORDER_PRICE_SL 可用来在价格/止损被改动后自动唤醒另一张条件单。外汇与贵金属波动剧烈,这类自动链动逻辑须先在策略测试器用历史数据验证,实盘存在滑点和事件丢失的可能风险。
PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_BALANCE_REFILL = MSG_EVN_BALANCE_REFILL, class=class="str">"cmt">// Replenishing account balance PEND_REQ_ACTIVATE_BY_EVENT_ACCOUNT_BALANCE_WITHDRAWAL = MSG_EVN_BALANCE_WITHDRAWAL, class=class="str">"cmt">// Withdrawing funds from an account PEND_REQ_ACTIVATE_BY_EVENT_PENDING_ORDER_ACTIVATED = MSG_EVN_ACTIVATED_PENDING, class=class="str">"cmt">// Pending order activated by price PEND_REQ_ACTIVATE_BY_EVENT_PENDING_ORDER_ACTIVATED_PARTIAL= MSG_EVN_ACTIVATED_PENDING_PARTIALLY, class=class="str">"cmt">// Pending order partially activated by price PEND_REQ_ACTIVATE_BY_EVENT_POSITION_OPENED_PARTIAL = MSG_EVN_POSITION_OPENED_PARTIALLY, class=class="str">"cmt">// Position opened partially PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED_PARTIAL = MSG_EVN_POSITION_CLOSED_PARTIALLY, class=class="str">"cmt">// Position closed partially PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED_BY_POS = MSG_EVN_POSITION_CLOSED_BY_POS, class=class="str">"cmt">// Position closed by an opposite one PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED_PARTIAL_BY_POS = MSG_EVN_POSITION_CLOSED_PARTIALLY_BY_POS, class=class="str">"cmt">// Position partially closed by an opposite one PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED_BY_SL = MSG_EVN_POSITION_CLOSED_BY_SL, class=class="str">"cmt">// Position closed by StopLoss PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED_BY_TP = MSG_EVN_POSITION_CLOSED_BY_TP, class=class="str">"cmt">// Position closed by TakeProfit PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED_PARTIAL_BY_SL = MSG_EVN_POSITION_CLOSED_PARTIALLY_BY_SL, class=class="str">"cmt">// Position closed partially by StopLoss PEND_REQ_ACTIVATE_BY_EVENT_POSITION_CLOSED_PARTIAL_BY_TP = MSG_EVN_POSITION_CLOSED_PARTIALLY_BY_TP, class=class="str">"cmt">// Position closed partially by TakeProfit PEND_REQ_ACTIVATE_BY_EVENT_POSITION_REVERSED_BY_MARKET = MSG_EVN_POSITION_REVERSED_BY_MARKET, class=class="str">"cmt">// Position reversal by a new deal(netting) PEND_REQ_ACTIVATE_BY_EVENT_POSITION_REVERSED_BY_PENDING = MSG_EVN_POSITION_REVERSED_BY_PENDING, class=class="str">"cmt">// Position reversal by activating a pending order(netting) PEND_REQ_ACTIVATE_BY_EVENT_POSITION_REVERSED_BY_MARKET_PARTIAL = MSG_EVN_POSITION_REVERSE_PARTIALLY, class=class="str">"cmt">// Position reversal by partial market order execution(netting) PEND_REQ_ACTIVATE_BY_EVENT_POSITION_VOLUME_ADD_BY_MARKET = MSG_EVN_POSITION_VOLUME_ADD_BY_MARKET, class=class="str">"cmt">// Added volume to a position by a new deal(netting) PEND_REQ_ACTIVATE_BY_EVENT_POSITION_VOLUME_ADD_BY_PENDING = MSG_EVN_POSITION_VOLUME_ADD_BY_PENDING, class=class="str">"cmt">// Added volume to a position by activating a pending order(netting) PEND_REQ_ACTIVATE_BY_EVENT_MODIFY_ORDER_PRICE = MSG_EVN_MODIFY_ORDER_PRICE, class=class="str">"cmt">// Order price change PEND_REQ_ACTIVATE_BY_EVENT_MODIFY_ORDER_PRICE_SL = MSG_EVN_MODIFY_ORDER_PRICE_SL class=class="str">"cmt">// Changing order and StopLoss price
正文
PEND_REQ_ACTIVATE_BY_EVENT_MODIFY_ORDER_PRICE_TP = MSG_EVN_MODIFY_ORDER_PRICE_TP, <span class="comment">// Order and TakeProfit price change</span> PEND_REQ_ACTIVATE_BY_EVENT_MODIFY_ORDER_PRICE_SL_TP = MSG_EVN_MODIFY_ORDER_PRICE_SL_TP, <span class="comment">// Changing order, StopLoss and TakeProfit price</span> PEND_REQ_ACTIVATE_BY_EVENT_MODIFY_ORDER_SL_TP = MSG_EVN_MODIFY_ORDER_SL_TP, <span class="comment">// Changing order's StopLoss and TakeProfit price</span> PEND_REQ_ACTIVATE_BY_EVENT_MODIFY_ORDER_SL = MSG_EVN_MODIFY_ORDER_SL, <span class="comment">// Modify StopLoss order</span> PEND_REQ_ACTIVATE_BY_EVENT_MODIFY_
「把比较符号翻成可读字符串」
这段 default 分支是枚举转字符串函数的兜底逻辑,当传入的比较运算符不在已处理范围内时,直接回退到 " != " 输出。 它出现在关系运算符映射的末尾,保证任意未枚举值都不会让函数返回空或崩溃,而是给出一个明确的非等于标记。 在 MT5 里把这段贴进自定义指标或脚本,编译后可用 Print() 验证:传入未定义枚举值应得到字符串「 != 」,外汇与贵金属行情判断属高风险,输出仅作逻辑核对。
class="kw">default : class="kw">return " != "; } } class=class="str">"cmt">//+------------------------------------------------------------------+