信号计算器·综合运用
(3/3)·订阅信号前最怕算错仓位比例,这篇把限制、手册与开发细节一次性打通
很多订阅者在切换交易服务器后发现信号列表变了,却仍按旧账户的余额去估复制量,结果跟单手数完全对不上。信号计算器正是为解决这种兼容与比例误判而生,但它本身也有边界,不是打开就能乱填。
◍ 网格单元对象的安全创建流程
在 MT5 自定义表格控件里,每一行其实是一个 CArrayObj 容器,里面塞着若干 CEdit 单元格。创建时第一步不是直接画控件,而是先确认行指针有效:用 CheckPointer 对 m_arr_rows.At(index) 的返回值做 POINTER_INVALID 判定,无效就直接 return(false),避免后续空指针崩在 OnChartEvent 里。 拿到行容器后,用 Total() 取单元格数量跑 for 循环。实测当表格为 10 行 × 8 列时,这段逻辑会迭代 80 次,每次都重新 CheckPointer(m_cell),任一单元格指针异常立即退出,保证半初始化的表格不会挂到图表上。 单元格本体靠 m_cell.Create() 生成,名字拼法为 父名+下划线+行号+下划线+列号,坐标用 x1/y1 和 x1+x2/y2 算出。创建完必须顺手 Text("") 清内容、ReadOnly(true) 锁编辑、Add(m_cell) 挂进公共资源池——三步任意一步返回 false 都整体放弃,外汇与贵金属图表高频刷新下这种失败快速返回能显著降低闪退概率。
CArrayObj *m_arr_cells=m_arr_rows.At(index); if(CheckPointer(m_arr_cells)==POINTER_INVALID) class="kw">return(false); for(class="type">int i=class="num">0;i<m_arr_cells.Total();i++) { CEdit *m_cell=m_arr_cells.At(i); if(CheckPointer(m_cell)==POINTER_INVALID) class="kw">return(false); if(!m_cell.Create(m_chart_id,m_name+"_"+IntegerToString(index)+"_"+IntegerToString(i), m_subwin,x1,y1,x1+x2,y2)) class="kw">return(false); if(!m_cell.Text("")) class="kw">return(false); if(!m_cell.ReadOnly(true)) class="kw">return(false); if(!Add(m_cell)) class="kw">return(false); }
「用脚本看清信号跟单的隐藏限制」
信号计算器真正有用的地方,不是帮你算复制比例,而是让你在调存款和杠杆之前,先看清标的本身有没有交易限制。XAUUSD 在 MT5 里返回的是「no trade restrictions, mode Forex」,而 USDRUR 及 USDRUR_i 返回「there are trade restrictions, mode NO Forex」——这种差别直接决定你改了账户参数也白搭。 下面这段脚本就是干这事的:遍历终端全部符号,按你填的前缀(默认 XAUUSD)抓出匹配项,再读 SYMBOL_TRADE_MODE 判定是否受限。跑完去「Experts」标签页看打印,比肉眼翻市场报价靠谱。 外汇和贵金属杠杆高、点差跳变频繁,跟单前不核实交易模式,可能遇到下不了单却还在扣复制费的情况,属于典型高风险盲区。 代码里 InpSearched 是输入参数,想查别的品种直接改字符串;TERMINAL_LANGUAGE 判断只是切换俄/英提示语,不影响逻辑,可当摆设。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//|符号总数。mq5 class=class="str">"cmt">//|| 版权 © class="num">2016-class="num">2019, Vladimir Karputov | | class=class="str">"cmt">//|http://wmua.ru/slesar/ | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "版权 © class="num">2016-class="num">2019,弗拉基米尔-卡尔普托夫" class="macro">#class="kw">property link "http:class=class="str">"cmt">//wmua.ru/slesar/" class="macro">#class="kw">property version "class="num">1.005" class="macro">#class="kw">property script_show_inputs class=class="str">"cmt">//--- 输入参数 input class="type">class="kw">string InpSearched = "XAUUSD"; class=class="str">"cmt">// 搜索的内容 class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 脚本程序启动功能| class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { class="type">class="kw">string no_rest=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")? "不限制贸易业务": "no trade restrictions"; class="type">class="kw">string rest=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")? "贸易活动受到限制": "there are trade restrictions"; class=class="str">"cmt">//--- class="type">int symbols_total=SymbolsTotal(false); Print("--- START ---"); for(class="type">int i=class="num">0;i<symbols_total; i++) { class="type">class="kw">string name=SymbolName(i,false); if(StringFind(name,InpSearched,class="num">0)>=class="num">0) { class=class="str">"cmt">//--- 已检查交易模式 class="type">long trade_mode=SymbolInfoInteger(name,SYMBOL_TRADE_MODE);
用脚本扫一遍品种的交易权限与计价模式
MT5 里想确认某个品种当前能不能自由开仓、用的是什么保证金计算逻辑,不必手动翻规格窗口,写个脚本批量跑更快。下面这段逻辑核心是先取全部品种数,再逐个用 StringFind 按输入串过滤,比如默认搜 XAUUSD,就把带这串符号名的都拎出来。 过滤命中后,用 SymbolInfoInteger 取 SYMBOL_TRADE_MODE:等于 SYMBOL_TRADE_MODE_FULL 就代表无交易限制,否则就是受限。再取 SYMBOL_TRADE_CALC_MODE,值为 0 时标注为 Forex 计价模式,非 0 则标 NO Forex——贵金属 XAUUSD 在多数券商下 calc mode 非 0,说明它走的是金属类保证金算法而非普通外汇那套。 脚本还做了终端语言判断,俄语环境输出俄文提示,其他环境出英文 'no trade restrictions' 或 'there are trade restrictions'。把 InpSearched 改成 'USD' 这类宽匹配串,一次能扫出几十个关联品种,省去逐个点的麻烦。外汇与贵金属杠杆波动大、强平风险高,脚本只报状态不报方向,真要下单前仍须核对券商实际限制。
class="type">class="kw">string text=""; if(trade_mode==SYMBOL_TRADE_MODE_FULL) text=no_rest; else text=rest; if(SymbolInfoInteger(name,SYMBOL_TRADE_CALC_MODE)==class="num">0) text=text+", mode Forex"; else text=text+", mode NO Forex"; class=class="str">"cmt">//--- Print(name," -> ",text); } } Print("--- END ---"); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//class="macro">#class="kw">property copyright "版权 © class="num">2016-class="num">2019,弗拉基米尔-卡尔普托夫" class="macro">#class="kw">property link "http:class=class="str">"cmt">//wmua.ru/slesar/" class="macro">#class="kw">property version "class="num">1.005" class="macro">#class="kw">property script_show_inputs class=class="str">"cmt">//--- 输入参数 input class="type">class="kw">string InpSearched = "XAUUSD"; class=class="str">"cmt">// 搜索的内容 class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { class="type">class="kw">string no_rest=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")? "不限制贸易业务": "no trade restrictions"; class="type">class="kw">string rest=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")? "贸易活动受到限制": "there are trade restrictions"; class=class="str">"cmt">//--- class="type">int symbols_total=SymbolsTotal(false); Print("--- START ---"); for(class="type">int i=class="num">0; i<symbols_total; i++) { class="type">class="kw">string name=SymbolName(i,false); if(StringFind(name,InpSearched,class="num">0)>=class="num">0) { class=class="str">"cmt">//--- 已检查交易模式 class="type">long trade_mode=SymbolInfoInteger(name,SYMBOL_TRADE_MODE); class="type">class="kw">string text=""; if(trade_mode==SYMBOL_TRADE_MODE_FULL) text=no_rest; else text=rest; if(SymbolInfoInteger(name,SYMBOL_TRADE_CALC_MODE)==class="num">0)
◍ 扫描品种判定外汇计算模式
这段脚本干的事很直接:遍历终端全部可见品种,按输入串(默认 XAUUSD)做子串匹配,命中后读取该品种的 SYMBOL_TRADE_MODE 与 SYMBOL_TRADE_CALC_MODE,把交易限制状态和计价模式打印出来。 核心判定在 SYMBOL_TRADE_CALC_MODE==0 这一行——MT5 里 0 对应外汇保证金计算模式(mode Forex),非 0 则归为 mode NO Forex(如现货、期货或交易所品种)。脚本还顺带用 SYMBOL_TRADE_MODE_FULL 区分有无交易限制。 实测日志给出明确参照:XAUUSD 输出 "no trade restrictions, mode Forex",说明黄金现货在常规账户下走外汇计算且无限制;而 USDRUR / USDRUB_i 显示 "there are trade restrictions, mode NO Forex",即存在交易限制且非外汇计价。外汇与贵金属波动剧烈、杠杆风险高,这类模式差异直接影响仓位与保证金计算,开仓前最好自己跑一遍确认。 把 InpSearched 改成你想查的品种前缀(比如 "EUR" 或 "BTC"),拖进 MT5 脚本执行,终端里就能看到当前 broker 环境下各品种的真实交易属性。
class="macro">#class="kw">property copyright "版权 © class="num">2016-class="num">2019,弗拉基米尔-卡尔普托夫" class="macro">#class="kw">property link "http:class=class="str">"cmt">//wmua.ru/slesar/" class="macro">#class="kw">property version "class="num">1.005" class="macro">#class="kw">property script_show_inputs class=class="str">"cmt">//--- 输入参数 input class="type">class="kw">string InpSearched = "XAUUSD"; class=class="str">"cmt">// 搜索的内容 class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 脚本程序启动功能| class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { class="type">class="kw">string no_rest=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")? "нет ограничений на торговые операции": "no trade restrictions"; class="type">class="kw">string rest=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")? "есть ограничения на торговые операции": "there are trade restrictions"; class=class="str">"cmt">//--- class="type">int symbols_total=SymbolsTotal(false); Print("--- START ---"); for(class="type">int i=class="num">0;i<symbols_total; i++) { class="type">class="kw">string name=SymbolName(i,false); if(StringFind(name,InpSearched,class="num">0)>=class="num">0) { class=class="str">"cmt">//--- 已检查交易模式 class="type">long trade_mode=SymbolInfoInteger(name,SYMBOL_TRADE_MODE); class="type">class="kw">string text=""; if(trade_mode==SYMBOL_TRADE_MODE_FULL) text=no_rest; else text=rest; if(SymbolInfoInteger(name,SYMBOL_TRADE_CALC_MODE)==class="num">0) text=text+", mode Forex"; else text=text+", mode NO Forex"; class=class="str">"cmt">//--- Print(name," -> ",text); } } Print("--- END ---"); }
「用脚本把可交易品种筛出来」
上面这段脚本干一件事:遍历 MT5 终端里全部可见品种,按你填的搜索词(默认 XAUUSD)做子串匹配,命中后打印该品种名以及它的交易限制状态和计价模式。 它先取 SymbolsTotal(false) 拿到品种总数,再用 SymbolName(i,false) 逐个取名字,StringFind 判断有没有包含搜索词。命中后通过 SymbolInfoInteger 读 SYMBOL_TRADE_MODE 和 SYMBOL_TRADE_CALC_MODE:前者区分有无交易限制,后者为 0 时标 "mode Forex",否则标 "mode NO Forex"。 你直接把 InpSearched 改成 "XAG" 或 "BTC",拖进 MT5 脚本区跑一遍,终端日志会列出类似 "XAUUSD -> no trade restrictions, mode Forex" 的行。外汇与贵金属波动剧烈、杠杆风险高,脚本只做品种筛查,不涉及任何方向判断。 这种本地枚举比手动翻市场报价窗口快得多,尤其当你经纪商挂了上百个符号、只想挑出能正常下单的贵金属对时,改一行参数就能复用。
class="macro">#class="kw">property copyright "版权 © class="num">2016-class="num">2019,弗拉基米尔-卡尔普托夫" class="macro">#class="kw">property link "http:class=class="str">"cmt">//wmua.ru/slesar/" class="macro">#class="kw">property version "class="num">1.005" class="macro">#class="kw">property script_show_inputs class=class="str">"cmt">//--- 输入参数 input class="type">class="kw">string InpSearched = "XAUUSD"; class=class="str">"cmt">// 搜索的内容 class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 脚本程序启动功能| class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { class="type">class="kw">string no_rest=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")? "нет ограничений на торговые операции": "no trade restrictions"; class="type">class="kw">string rest=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")? "есть ограничения на торговые операции": "there are trade restrictions"; class=class="str">"cmt">//--- class="type">int symbols_total=SymbolsTotal(false); Print("--- START ---"); for(class="type">int i=class="num">0; i<symbols_total; i++) { class="type">class="kw">string name=SymbolName(i,false); if(StringFind(name,InpSearched,class="num">0)>=class="num">0) { class=class="str">"cmt">//--- 已检查交易模式 class="type">long trade_mode=SymbolInfoInteger(name,SYMBOL_TRADE_MODE); class="type">class="kw">string text=""; if(trade_mode==SYMBOL_TRADE_MODE_FULL) text=no_rest; else text=rest; if(SymbolInfoInteger(name,SYMBOL_TRADE_CALC_MODE)==class="num">0) text=text+", mode Forex"; else text=text+", mode NO Forex"; class=class="str">"cmt">//--- Print(name," -> ",text); } } Print("--- END ---"); }