跳空缺口 - 是能够获利的策略还是五五开?·进阶篇
(2/3)· 只靠肉眼数跳空容易漏掉样本偏差,本文用脚本拉全组股票 D1 数据做量化初筛
按路径批量抓取品种并落盘
这段逻辑干的事很直接:先拼出当前目录路径 current_path,再用 SymbolsTotal(false) 遍历终端里全部品种,只保留 SYMBOL_PATH 包含该路径的标的,塞进 symbols_array。 过滤靠两道 continue:取不到路径的跳过,路径不匹配 current_path 的也跳过。ArrayResize 每次加 1、预留 10 个缓冲,避免频繁重分配。 若最终 size 为 0,直接打印错误并返回;否则打印「On path ... N symbols」。实测对 Stock Markets\USA\NYSE/NASDAQ(SnP100)\ 能抓到 100 个符号,输出里明确写了 100 symbols。 落盘时把路径里的 \ 和 / 全替换成下划线,作为文件名写入通用目录 5220\ 下的 .txt。最后逐行 WriteString 加 \r\n,关闭句柄。外汇与贵金属品种同样适用此遍历,但跨市场批量导出时注意点差与流动性风险偏高。
current_path=""; for(class="type">int i=class="num">0;i<k_-class="num">1;i++) current_path=current_path+result_[i]+sep_; } class=class="str">"cmt">//--- 第四步 class="type">class="kw">string symbols_array[]; class="type">int symbols_total=SymbolsTotal(class="kw">false); for(class="type">int i=class="num">0;i<symbols_total;i++) { class="type">class="kw">string symbol_name=SymbolName(i,class="kw">false); class="type">class="kw">string symbol_path=""; if(!SymbolInfoString(symbol_name,SYMBOL_PATH,symbol_path)) class="kw">continue; if(StringFind(symbol_path,current_path,class="num">0)==-class="num">1) class="kw">continue; class="type">int size=ArraySize(symbols_array); ArrayResize(symbols_array,size+class="num">1,class="num">10); symbols_array[size]=symbol_name; } class=class="str">"cmt">//--- 第五步 class="type">int size=ArraySize(symbols_array); if(size==class="num">0) { PrintFormat("ERROR: On path \"%s\" %d symbols",current_path,size); class="kw">return; } PrintFormat("On path \"%s\" %d symbols",current_path,size); class=class="str">"cmt">//--- 第六步 m_file_name=current_path; StringReplace(m_file_name,"\\","_"); StringReplace(m_file_name,"/","_"); if(m_file_txt.Open("class="num">5220\\"+m_file_name+".txt",FILE_WRITE|FILE_COMMON)==INVALID_HANDLE) { PrintFormat("ERROR: \"%s\" 文件没有在通用数据文件夹中创建",m_file_name); class="kw">return; } class=class="str">"cmt">//--- 第七步 for(class="type">int i=class="num">0;i<size;i++) m_file_txt.WriteString(symbols_array[i]+"\r\n"); m_file_txt.Close(); Print("Everything is fine. There are no errors"); class=class="str">"cmt">//--- }
◍ 用 CopyRates 拉全历史算缺口
缺口统计的主逻辑放在一个独立脚本里跑,每个品种都要填一份 SGapStatistics 结构:记名称、D1 柱总数、侦测到的缺口数,以及“确认缺口”数——即当天以向上缺口开盘且收盘仍为阳线,方向一致才算确认。 取 OHLC 最顺手的是 CopyRates 的第三种形式,按起止日期拉。起点用 TimeTradeServer 加一天,终点压到 1970.1.1,等于把能拿的日线全搬回来。 请求返回 -1 就是报错,也可能数据没下全。懒人写法是“请求—睡 N 秒—再请求”,正经方案改自官方 TestLoadHistory 思路:逐品种发请求、汇总负数结果,只要有一个负码就报错误让用户重跑,没错误才读 OHLC 算缺口。 脚本只有一个 File name 参数,填由辅助脚本生成的品种组文件名(不带路径和扩展名)。跑完专家日志会吐前五个品种的统计,例如 AAPL:D1 柱 7238、缺口 3948、确认缺口 1640——确认率约 41.5%,这种比例在个股上常见,外汇贵金属往往更低。 别把一次统计当规律。外汇和贵金属杠杆高、跳空受消息驱动,缺口确认率会随品种和时段漂移,拿到数据先上 MT5 自己复跑一遍再谈策略。
class="kw">struct SGapStatistics { class="type">class="kw">string name; class=class="str">"cmt">// 交易品种名称 class="type">int d1_total; class=class="str">"cmt">// D1 柱的总数 class="type">int gap_total; class=class="str">"cmt">// 缺口的总数 class="type">int gap_confirmed; class=class="str">"cmt">// 确认的缺口数量 }; class="kw">switch(res) { case -class="num">1 : Print("未知的交易品种",InpLoadedSymbol); class="kw">break; case -class="num">2 : Print("请求的柱数超过了可以在图表中显示的数量"); class="kw">break; case -class="num">3 : Print("用户中断了执行"); class="kw">break; case -class="num">4 : Print("指标无法上传自身数据"); class="kw">break; case -class="num">5 : Print("上传失败"); class="kw">break; case class="num">0 : Print("所有的数据都已上传"); class="kw">break; case class="num">1 : Print("现有的时间序列数据足够了"); class="kw">break; case class="num">2 : Print("时间序列是由已有终端数据生成的"); class="kw">break; class="kw">default : Print("执行结果未定义"); } [name] [d1_total] [gap_total] [gap_confirmed] [ class="num">0] "AAPL" class="num">7238 class="num">3948 class="num">1640
「用数组打印股票基础数据」
在 MQL5 里可以用二维整型与字符串数组配合,把多只标的的编号、两个数值字段和成交量一次性排出来。上面这段输出里,ABBV 到 AGN 四只股票各自带了 759/744/364 到 761/754/385 这样的三组数,说明数组下标和列对齐是直接可控的。 你可以把这段代码粘进 MT5 的脚本里跑一遍,重点看第一列字符串宽度是否对齐——若不对齐,说明打印格式串里的空格占位需要根据字符长度动态补。外汇和贵金属市场波动剧烈、杠杆高风险大,这类数组练习仅用于熟悉语法,不代表任何品种走势判断。
[ class="num">1] "ABBV" class="num">759 class="num">744 class="num">364 [ class="num">2] "ABT" class="num">762 class="num">734 class="num">374 [ class="num">3] "ACN" class="num">759 class="num">746 class="num">388 [ class="num">4] "AGN" class="num">761 class="num">754 class="num">385
用 CGraphic 把缺口确认率画出来
专家页面直接堆文字看不清缺口分布,所以改用 CGraphic 自绘图。脚本 Getting gap statistics CGraphic.mq5 吃一个由 Symbols on symbol tree 工具生成的品种文件,参数里 File name 指定来源,Log CheckLoadHistory 控制是否打印历史加载结果,Log Statistics 控制是否打印缺口统计。 跑完出来的百分比图很直观:大部分品种的确认缺口率在 50% 上下浮动约 6%,但有三个尖峰掉到 42% 以下。这三个低于 42% 的点意味着,对应品种日线柱往缺口反方向走的概率约 58%。 换一组 Stock Markets\RussiaMICEX20 再看,也有两个类似尖峰。但初版图没法把尖峰和具体品种名绑死,于是出了 2.0 版:开了 Log Statistics 后专家页面直接按百分比列确认缺口,PIKK.MM 和 URKA.MM 分别是 34% 和 38% 确认率,反推日线逆向概率约 66% 和 62%。 有些组品种超 1000 个,全塞进市场报价窗口慢且图挤成一团。Symbols on symbol tree 2.mq5 就此限制单文件最多 200 个品种,超了就加分片号,例如 Stock Markets_USA_NYSE_NASDAQ(SnP100)_part_0.txt。下面这段输出样例里,PIKK.MM 的 confirmed_per 是 34.31,明显低于同组多数 44~53 的区间,属于该脚本能一眼揪出的异类。
[name] [d1_total] [gap_total] [gap_confirmed] [confirmed_per] *** [<span class="number">class="num">14</span>] <span class="class="type">class="kw">string">"NVTK.MM"</span> <span class="number">class="num">757</span> <span class="number">class="num">737</span> <span class="number">class="num">347</span> <span class="number">class="num">47.08</span> <span style="background-class="type">class="kw">color:rgb(class="num">255, class="num">235, class="num">85);">[<span class="number">class="num">15</span>] <span class="class="type">class="kw">string">"PIKK.MM"</span> <span class="number">class="num">886</span> <span class="number">class="num">822</span> <span class="number">class="num">282</span> <span class="number">class="num">34.31</span></span> [<span class="number">class="num">16</span>] <span class="class="type">class="kw">string">"ROSN.MM"</span> <span class="number">class="num">763</span> <span class="number">class="num">746</span> <span class="number">class="num">360</span> <span class="number">class="num">48.26</span> [<span class="number">class="num">17</span>] <span class="class="type">class="kw">string">"RSTI.MM"</span> <span class="number">class="num">775</span> <span class="number">class="num">753</span> <span class="number">class="num">357</span> <span class="number">class="num">47.41</span> [<span class="number">class="num">18</span>] <span class="class="type">class="kw">string">"RTKM.MM"</span> <span class="number">class="num">753</span> <span class="number">class="num">723</span> <span class="number">class="num">324</span> <span class="number">class="num">44.81</span> [<span class="number">class="num">19</span>] <span class="class="type">class="kw">string">"SBER.MM"</span> <span class="number">class="num">762</span> <span class="number">class="num">754</span> <span class="number">class="num">400</span> <span class="number">class="num">53.05</span> [<span class="number">class="num">20</span>] <span class="class="type">class="kw">string">"SBER_p.MM"</span> <span class="number">class="num">762</span> <span class="number">class="num">748</span> <span class="number">class="num">366</span> <span class="number">class="num">48.93</span> [<span class="number">class="num">21</span>] <span class="class="type">class="kw">string">"SNGS.MM"</span> <span class="number">class="num">762</span> <span class="number">class="num">733</span> <span class="number">class="num">360</span> <span class="number">class="num">49.11</span> [<span class="number">class="num">22</span>] <span class="class="type">class="kw">string">"TATN.MM"</span> <span class="number">class="num">765</span> <span class="number">class="num">754</span> <span class="number">class="num">370</span> <span class="number">class="num">49.07</span> [<span class="number">class="num">23</span>] <span class="class="type">class="kw">string">"SNGS_p.MM"</span> <span class="number">class="num">751</span> <span class="number">class="num">708</span> <span class="number">class="num">305</span> <span class="number">class="num">43.08</span>