MT4多开 - MT4点差获取用MarketInfo函数轻松实现_完整EA代码示例与调试要点

MarketInfo函数的基本用法与参数解析
MarketInfo是MQL4中一个功能强大的函数,专门用来获取市场相关的各种信息,比如点差、最小手数、保证金要求等。它的语法结构其实很简单,就是MarketInfo(品种名称, 参数类型)。其中,品种名称是一个字符串,比如"EURUSD"或"GBPJPY",而参数类型则是一个预定义的常量,用来指定你想获取哪种信息。
要获取点差,我们就用MODE_SPREAD这个常量。
举个最直接的例子,如果你在代码里写int spread = MarketInfo("EURUSD", MODE_SPREAD);,那么spread这个变量就会被赋值为当前欧元兑美元的点差值,单位是点数。这里要注意,点差通常以平台的最小价格变动单位来计量,比如外汇中通常就是1个点。不同平台可能点差显示方式有细微差别,但MQL4的MarketInfo返回的就是标准点数,直接用就行。
说实话,这个函数用起来特别顺手,不需要你自己去计算买卖价差。你可能会想,那为什么不直接用Ask和Bid报价相减呢?其实也可以,但MarketInfo更规范,而且返回的是整数,方便后续逻辑处理。比如你在写一个自动交易策略时,想根据点差大小动态调整开仓条件,用MarketInfo就比手动计算快得多。
实际使用中,我建议你把品种名称也做成变量,而不是硬编码。比如用Symbol()函数获取当前图表品种,这样代码就能适应不同品种。写法大概是int spread = MarketInfo(Symbol(), MODE_SPREAD);,这样无论你切换到哪个品种,都能自动获取对应点差,灵活性大大提高。
短线交易者为何更倾向“当日有效”
如果你是一个偏爱短线交易、比如做日内交易或者剥头皮策略的交易者,那么“当日有效”通常会更适合你。短线交易的核心在于捕捉当日的价格波动,你的分析和判断都是基于当前的盘面状态。比如你看到1小时图表上形成了一个明显的阻力位,认为价格会在当日多次测试这个位置,于是设置了一个sell limit挂单。这种情况下,如果价格当天没有触及这个位置,说明你的判断可能已经失效,第二天市场结构可能完全不同,继续保留这个挂单的意义不大。
说实话,短线交易中市场噪音很多,价格在一天内可能反复震荡,但趋势方向却可能随时改变。如果你设置了“直至取消”的挂单,很可能在第二天开盘时因为一个跳空或者新的消息而意外成交,但这个成交已经脱离了你的初始分析框架。我认识的一位交易者就吃过这个亏:他基于某个技术形态设置了做空挂单,但当天没有成交,第二天市场因为突发利好大幅高开,他的挂单直接以更低的价格成交了,结果亏损惨重。
另外,短线交易者通常需要频繁调整策略,每天收盘后都会复盘并制定第二天的计划。如果挂单默认是“直至取消”,你可能会忘记删除前一天未成交的订单,导致第二天开市后出现不必要的干扰。选择“当日有效”可以强制你在每个交易日结束后重新审视市场,重新评估入场点,这种习惯其实有助于提升交易纪律。
当然,选择“当日有效”也有一个缺点:如果你在尾盘看到一个很好的挂单机会,但当天时间所剩无几,挂单可能还没成交就被收盘取消了。这种情况下,你可以考虑将有效期改为“直至取消”,但一定要在第二天开盘前重新评估是否保留。说实话,短线交易的核心是灵活性和时效性,所以“当日有效”更符合这种节奏。
处理DLL参数传递与内存管理
DLL函数调用中,参数传递是最容易踩坑的地方。特别是字符串参数,因为MQL4的string类型在内部是Unicode编码,而很多DLL函数期望的是ANSI编码或者宽字符编码。如果你直接传递一个MQL4字符串给DLL,可能会导致乱码甚至程序崩溃。解决方法是,在MQL4中先使用StringConvert或StringSetCharacter函数将字符串转换为合适的格式,或者干脆在DLL端设计函数时,接受字符数组指针而不是字符串对象。我个人的做法是,在编写DLL时,所有字符串参数都定义为LPWSTR(宽字符指针),然后在MQL4中传递时,使用StringInit函数初始化一个足够大的数组,再用StringToCharArray转换后传递指针地址。
内存管理是另一个大问题。DLL内部分配的内存,通常需要由DLL自己负责释放,或者由调用方按照约定进行释放。在MQL4中,你无法直接调用C++的delete或free函数,所以最好让DLL提供专门的内存释放函数。
举个例子,如果DLL里的一个函数返回一个动态分配的double数组指针,那么DLL里应该还有一个FreeDoubleArray函数,让你在MQL4中使用完数组后调用它来释放内存。我见过不少新手因为这个疏忽导致内存泄漏,EA运行时间一长,MT4就变得异常卡顿。
对于数值类型参数,比如int、double、bool,传递起来就比较简单。MQL4和大多数DLL都使用相同的二进制表示,所以直接传值就行。但要注意,如果你需要传递数组或结构体,情况就复杂了。数组参数通常需要传递指针和数组长度,结构体则要保证内存对齐方式一致。我建议,如果可能的话,尽量把复杂数据结构序列化成简单类型(比如把结构体成员拆成多个参数),或者使用二进制数据流传递。说实话,这些细节虽然繁琐,但只要多试几次,积累一些经验后,就会觉得没那么难了。
完整EA代码示例与调试要点
下面给出一个完整的EA代码框架,你可以直接复制到MetaEditor中使用。注意:这只是核心逻辑部分,你需要补全EA的初始化函数和反初始化函数。实际上,OnTick函数才是核心,其他部分可以留空。代码中我加入了详细的注释,metatrader4下载方便你理解每一行的作用。
//+------------------------------------------------------------------+ //| WeeklyClose.mq4 | //+----------------------------------MT4指标窗口高度调好重启失效模板保存是正解_点差设置对回测结果的真实影响--------------------------------+ input int CloseHour = 21; // 平仓小时 input int CloseMinute = 55; // 平仓分钟 input int CloseDay = 5; // 平仓星期(5=周五) void OnTick() { if(TimeDayOfWeek(TimeCurrent()) == CloseDay && Hour() >= CloseHour && Minute() >= CloseMinute) { for(int i = OrdersTotal()-1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderType() == OP_BUY) OrderClose(OrderTicket(), OrderLots(), Bid, 100, clrNONE); if(OrderType() == OP_SELL) OrderClose(OrderTicket(), OrderLots(), Ask, 100, clrNONE); if(OrderType() > OP_SELL) OrderDelete(OrderTicket()); } } } }
调试这个EA时,建议先在模拟账户上跑一周测试。你可以故意把时间调快,比如设置CloseHour为当前小时减1,然后观察EA是否在正确的时间触发平仓。另外要注意,EA必须加载到一个图表上才能运行,随便加载到哪个货币对的图表都行,因为它会扫描整个账户的所有订单,而不是只处理当前图表的订单。
如果你发现EA没有按预期工作,最常见的原因是时间设置错误。建议先输出当前服务器时间到日志,用Print函数打印TimeCurrent()的值,确认你的时间判断是否正确。还有一个常见问题:有些经纪商的周末收盘时间不是周五,而是周六凌晨,这时候你要把CloseDay设置为6代表星期六。总之,一定要根据自己平台的实际收盘时间进行调整。