刚接触MT4编程不久,在写一个简单的网格策略EA时,遇到了点差和滑点的问题,想请教一下论坛里的前辈们。先说说我的理解,不知道对不对。
我原本以为点差就是买入价和卖出价之间的固定差值,比如EURUSD在平台显示1.1050/1.1052,那点差就是2个点。但实际测试中发现,当市场波动剧烈时,这个差值会突然变大,比如变成5个点甚至更多。我写EA时用了MarketInfo(Symbol(), MODE_SPREAD)来获取当前点差,但在开仓时总是对不上。比如我设定当价格突破某个均线时开仓,条件满足后,用OrderSend函数发送订单,结果成交价和预期的买入价差了3-4个点,有时候甚至更多。这让我很困惑:MarketInfo获取的点差是实时的吗?为什么开仓时点差会变化?还是说我获取点差的时机不对?
关于滑点,我本来以为就是设置一个允许的偏差值,比如在OrderSend里设置slippage为3,意思是成交价和请求价相差不超过3个点就能接受。但我发现实际情况复杂得多。有一次我设置slippage=5,结果订单成交在比当前买价高8个点的地方。平台客服说是市场流动性不足导致的,可我在策略测试回测里明明跑得很好,实盘却完全不一样。后来我查了资料,说滑点不仅和网络延迟有关,还和经纪商的订单执行模式有关。但我的问题是:在EA代码里,到底该怎么处理滑点?是不是应该在不滑点的情况下才开仓?比如用while循环不断检查当前价格和请求价的差值,如果超过某个阈值就取消订单?但这样会不会导致无限循环,或者错过行情?
还有一个更具体的问题。我在写一个追踪止损的EA时,需要不断修改止损价。我用OrderModify函数修改止损,但经常提示138号错误(重报价)。我查了文档,说这是因为价格已经变化,需要重新请求。但我已经设置了slippage参数,为什么还会这样?是不是修改止损时也要考虑点差?比如我要把止损设在当前买价下方20个点,但实际成交价是卖价,中间有个点差,导致我计算的止损位置不对。我尝试用Ask和Bid来区分多空单的止损,但依然出现滑点。比如多单止损应该基于Bid,但我在修改时用的是MarketInfo获取的Bid,结果订单修改时提示价格无效,可能是因为点差突然扩大,导致Bid和Ask的差值超过了我的预期。
论坛里有人提到用RefreshRates()函数来刷新价格,我试过了,但效果不明显。还有人说要在开仓前检查点差是否在可接受范围内,比如if(MarketInfo(Symbol(), MODE_SPREAD) < 20)才允许开仓。但这样会不会太保守,导致在点差大的时候错过机会?或者反过来,点差小的时候开仓,但成交时点差又变了?
我现在写的EA核心逻辑很简单:当价格突破布林带上轨时做空,突破下轨时做多,止损设在突破点反向20个点,止盈设在反向40个点。但在实盘测试中,经常出现开仓后立即触发止损的情况,我怀疑就是点差和滑点导致的。比如价格刚突破上轨1.1050,我以1.1052开空单,但实际成交在1.1055,然后价格回落到1.1050,我的止损设在1.1052(基于原始开仓价),结果马上被止损出局。这让我很崩溃。
希望有经验的前辈能指点一下,在编写EA时到底该如何正确处理点差和滑点?特别是针对网格类、突破类策略,有没有什么标准化的处理模式?比如是否应该在开仓时强制设置一个比当前价更严格的slippage?或者用OrderSelect和OrderClosePrice来获取实际成交价后,再动态调整后续的止损?另外,有没有办法在代码里实时监测点差的变化,当点差超过某个阈值时暂停交易?或者说,点差和滑点问题本质上是经纪商的选择问题,和代码关系不大?
先谢谢了。代码我贴一部分在下面,方便前辈们指出问题:
if(OrdersTotal()==0 && Bid < LowerBand)
{
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, Ask - StopLoss*Point, Ask + TakeProfit*Point);
if(ticket < 0) Print("开仓错误: ", GetLastError());
}
if(OrdersTotal()>0)
{
for(int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS))
{
if(OrderType()==OP_BUY)
{
double newSL = Bid - TrailingStop*Point;
if(OrderStopLoss() < newSL)
{
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
}
}
}
这段代码在回测里表现尚可,实盘就各种问题。尤其是OrderModify的138错误,几乎每次追踪止损都会出现。恳请指教。
我原本以为点差就是买入价和卖出价之间的固定差值,比如EURUSD在平台显示1.1050/1.1052,那点差就是2个点。但实际测试中发现,当市场波动剧烈时,这个差值会突然变大,比如变成5个点甚至更多。我写EA时用了MarketInfo(Symbol(), MODE_SPREAD)来获取当前点差,但在开仓时总是对不上。比如我设定当价格突破某个均线时开仓,条件满足后,用OrderSend函数发送订单,结果成交价和预期的买入价差了3-4个点,有时候甚至更多。这让我很困惑:MarketInfo获取的点差是实时的吗?为什么开仓时点差会变化?还是说我获取点差的时机不对?
关于滑点,我本来以为就是设置一个允许的偏差值,比如在OrderSend里设置slippage为3,意思是成交价和请求价相差不超过3个点就能接受。但我发现实际情况复杂得多。有一次我设置slippage=5,结果订单成交在比当前买价高8个点的地方。平台客服说是市场流动性不足导致的,可我在策略测试回测里明明跑得很好,实盘却完全不一样。后来我查了资料,说滑点不仅和网络延迟有关,还和经纪商的订单执行模式有关。但我的问题是:在EA代码里,到底该怎么处理滑点?是不是应该在不滑点的情况下才开仓?比如用while循环不断检查当前价格和请求价的差值,如果超过某个阈值就取消订单?但这样会不会导致无限循环,或者错过行情?
还有一个更具体的问题。我在写一个追踪止损的EA时,需要不断修改止损价。我用OrderModify函数修改止损,但经常提示138号错误(重报价)。我查了文档,说这是因为价格已经变化,需要重新请求。但我已经设置了slippage参数,为什么还会这样?是不是修改止损时也要考虑点差?比如我要把止损设在当前买价下方20个点,但实际成交价是卖价,中间有个点差,导致我计算的止损位置不对。我尝试用Ask和Bid来区分多空单的止损,但依然出现滑点。比如多单止损应该基于Bid,但我在修改时用的是MarketInfo获取的Bid,结果订单修改时提示价格无效,可能是因为点差突然扩大,导致Bid和Ask的差值超过了我的预期。
论坛里有人提到用RefreshRates()函数来刷新价格,我试过了,但效果不明显。还有人说要在开仓前检查点差是否在可接受范围内,比如if(MarketInfo(Symbol(), MODE_SPREAD) < 20)才允许开仓。但这样会不会太保守,导致在点差大的时候错过机会?或者反过来,点差小的时候开仓,但成交时点差又变了?
我现在写的EA核心逻辑很简单:当价格突破布林带上轨时做空,突破下轨时做多,止损设在突破点反向20个点,止盈设在反向40个点。但在实盘测试中,经常出现开仓后立即触发止损的情况,我怀疑就是点差和滑点导致的。比如价格刚突破上轨1.1050,我以1.1052开空单,但实际成交在1.1055,然后价格回落到1.1050,我的止损设在1.1052(基于原始开仓价),结果马上被止损出局。这让我很崩溃。
希望有经验的前辈能指点一下,在编写EA时到底该如何正确处理点差和滑点?特别是针对网格类、突破类策略,有没有什么标准化的处理模式?比如是否应该在开仓时强制设置一个比当前价更严格的slippage?或者用OrderSelect和OrderClosePrice来获取实际成交价后,再动态调整后续的止损?另外,有没有办法在代码里实时监测点差的变化,当点差超过某个阈值时暂停交易?或者说,点差和滑点问题本质上是经纪商的选择问题,和代码关系不大?
先谢谢了。代码我贴一部分在下面,方便前辈们指出问题:
if(OrdersTotal()==0 && Bid < LowerBand)
{
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, Ask - StopLoss*Point, Ask + TakeProfit*Point);
if(ticket < 0) Print("开仓错误: ", GetLastError());
}
if(OrdersTotal()>0)
{
for(int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS))
{
if(OrderType()==OP_BUY)
{
double newSL = Bid - TrailingStop*Point;
if(OrderStopLoss() < newSL)
{
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
}
}
}
这段代码在回测里表现尚可,实盘就各种问题。尤其是OrderModify的138错误,几乎每次追踪止损都会出现。恳请指教。
专注交易策略编程实现,分享MQL开发技巧与代码优化方案