较热63.7

从入门到放弃再到搞定:MQL4数组操作与数据排序

Exness 推荐平台

入金门槛低,出金到账快,支持多种账户类型

FSA(塞舌尔)/FCA(英国) / CySEC(塞浦路斯) · 最低入金 $130
MeadowScribe
MeadowScribe 楼主
7 天前 507 5 1分钟 新汇友(注册会员) Lv.1 主题3 帖数8 积分1217 汇币844
1楼
说实话,我接触MQL4数组那会儿,差点就真“放弃”了。不是策略写不出来,而是每次想对历史数据进行排序,就卡在ArraySort的默认行为上。那时候我正琢磨怎么把欧美近300根K线的收盘价提取出来,按波动幅度排个序,找出最活跃的交易时段。结果写出来的代码,排序倒是排了,但价格和对应的K线时间对不上号——我拿到的是一串孤零零的价格,完全不知道哪根K线是哪天哪时的。那感觉就像你手里有一叠外汇牌价,但日期全被水泡花了。
后来我仔细翻了官方文档,才发现问题出在ArraySort只能对一维数组排序,而且默认是升序。你想啊,我把价格和时间分别存在两个数组里,价格一排序,时间数组纹丝不动,对应关系全乱套了。这是第一个坑: ArraySort不会自动同步关联数组 。我见过不少人,包括我自己,一开始都栽在这上面。解决方案其实有两种思路,各有取舍。
第一种方案,也是最直观的,就是构建一个二维数组,把价格和时间打包进去。用ArraySort直接按第一维排序,但问题是,MQL4的ArraySort对多维数组的支持有限,它只按第一个维度排序,而且如果你把时间戳放在第二列,排序后时间跟着价格走,这个倒是能解决同步问题。但坑在于,二维数组在内存里是线性存储的,如果你数组规模大,比如处理10000根K线,排序速度会明显下降,尤其是在VPS上跑EA的时候,每次Tick都要重新排序,那延迟感真的让人抓狂。我试过用这种方式优化一个黄金策略的回测数据,结果单次排序耗时从0.02秒涨到0.15秒,虽然看着不多,但高频调用下就卡顿了。
第二种方案,也是我现在主力用的,就是自定义索引数组 。不直接排序价格数组,而是创建一个索引数组,比如Index[0]=0, Index[1]=1...然后写一个简单的冒泡排序或者快速排序算法,比较的是价格,但交换的是索引。这样价格数组保持原样,索引数组告诉你哪根K线排在最前面。优点很突出:不用动原始数据,内存占用小,而且你可以随时按多个维度排序,比如先按波动率,再按时间。缺点就是得自己写排序逻辑,代码量稍微多一点,但也就十几行的事。我之前写过一个双指标排序的EA,用这个方案处理镑美的日内高低点,速度比二维数组方案快了将近一倍,而且逻辑清晰,调试起来也省心。
踩过的坑里,还有一个特别隐蔽的:ArrayResize。如果你在循环里频繁调整数组大小,比如每次Tick都根据新的K线数量重新分配数组,那内存碎片化严重,MT4的终端会越来越卡。我一开始没注意,结果EA跑了两天,VPS上的内存占用从200MB飙到1.2GB,最后直接崩溃。后来我改成预先分配足够大的数组,再用一个计数器记录实际使用长度 ,才彻底解决。这个习惯现在成了我写所有MQL4代码的默认操作。
说到排序本身,还有个细节值得提。默认的ArraySort是升序,如果你要找最大波动,得用ArraySort + ArraySetAsSeries配合,或者干脆自己写个降序比较。我后来发现,用自定义索引数组的话,降序就简单了,只要把比较条件反过来就行。而且你可以顺便输出前N个结果,比如找出波动率最大的前5根K线,这样对后续的入场时机判断特别有帮助。我在做黄金交易时段分析时,就是用这个方法,先提取过去一周的M15数据,排序后看到伦敦开盘那根K线波动率总是排在前三,然后我就把EA的入场窗口限定在那段时间,胜率确实提升了不少。
最后想说,MQL4数组这块,别怕动手写底层逻辑。那些现成的库函数看着方便,但真正适合自己的场景还是要自定义。我自己经历过从“放弃”到“搞定”的过程,现在看到ArraySort反而有种亲切感。不知道你们平时处理排序的时候,是直接用默认函数还是自己写算法?有没有遇到什么更奇葩的坑,比如数组越界或者类型转换问题?欢迎聊聊,说不定能帮到后来人。
1 回复 复制 众裁0
#1
竹影扫阶
竹影扫阶 #2· 4 天前
4 天前
2楼
说到ArraySort不同步关联数组这个坑,我也栽过,后来干脆用自定义索引排序,价格和时间各存各的,索引一换全对上了,回调测速也没拖后腿。
回复 复制 众裁0
4 天前 #2
MossyMeadow
MossyMeadow #3· 3 天前
3 天前
3楼
说到ArraySort只能排一维数组,我一开始也是硬用二维数组硬扛,结果回测时卡得想砸键盘。不过我遇到的情况是,后来改成索引排序后,虽然逻辑对了,但冒泡排序在5000根K线上还是慢,最后换了快速排序才稳下来。
回复 复制 众裁0
3 天前 #3
ShortSniperp
ShortSniperp #4· 3 天前
3 天前
4楼
排序不同步这个坑我踩过,现在用结构体数组存价格+时间,ArraySort虽然只能排一维,但结构体里装个比较函数就搞定。我自己也试过索引法,处理黄金H1数据时,结构体方案在VPS上跑更快,延迟低了近一半。
回复 复制 众裁0
3 天前 #4
努力的实践者
努力的实践者 #5· 3 天前
3 天前
5楼
看了你那个ArraySort不同步的坑,索引数组方案确实稳,不过我自己也试过,排序耗时在VPS上还得看数据量,建议加个缓存逻辑别每次Tick全排。
回复 复制 众裁0
3 天前 #5
VelocityX27
VelocityX27 #6· 3 天前
3 天前
6楼
看了你用索引数组解决ArraySort不同步的坑,学到关键一点是排序前先想清楚数据结构和调用频率。我自己也常处理纽美M1数据,发现与其纠结排序算法,不如在数据准备阶段直接按时间戳预建索引,后续排序成本能降不少,VPS上跑EA尤其明显。
回复 复制 众裁0
3 天前 #6
THE END
本帖内容仅供学习交流,不构成任何投资建议。外汇交易存在高风险,请谨慎参与。汇友之家合作的各家经纪商均为持有正规外汇牌照的经纪商,我们不参与经纪商的任何经营活动。经纪商在经营过程中可能出现破产清算、资不抵债、跑路或躲避责任等情况,这些问题汇友之家无法控制,亦不承诺任何经纪商资金的绝对安全。请知悉!
← 上一帖 MT5对冲账户EA配置详解正确打开方式(附实操步骤) 下一帖 → 新手求助:EA一个月亏了怎么办