应对交易环境时的典型错误和如何处理这些错误 - 页 3

 
fxsaber:

使用一个简单的例子的正确选择

我认为,如果还没有进入状态,最好是等待命令被考虑。
 
Комбинатор:
我认为,如果订单还没有入仓,就等着入仓好了。

我不明白这个意思。

 
正常订单发送的条件实现方案(无超时)。
static MqlTradeResult LastResult = {0};

void OnTradeTransaction( const MqlTradeTransaction&, const MqlTradeRequest&, const MqlTradeResult &Result )
{ 
  LastResult = Result;
}

// Условный алгоритм реализации штатной OrderSend
bool OrderSend( const MqlTradeRequest &Request, MqlTradeResult &Result )
{  
  bool Res = OrderSendAsync(Request, Result);
  
  if (Res)
  {
    while (LastResult.request_id != Result.request_id)
      OnTradeTransaction(); // условно-схематичный вызов
          
    Result = LastResult;    
    Res = (Result.retcode == TRADE_RETCODE_PLACED) ||
          (Result.retcode == TRADE_RETCODE_DONE) ||
          (Result.retcode == TRADE_RETCODE_DONE_PARTIAL);

    LastResult.request_id = 0;
  }
    
  return(Res);
}


该图显示,在MetaQuotes-Demo中使用OrderSendAsync 下市场订单时,不可能可靠地捕捉到正在下的相应订单,直到订单被执行或拒绝。也就是说,MT5中没有简单的机制来评估其OrderSendAsync的中间结果。

 

似乎是有主题的。

我想指出的是,这个代码。

if ( !OrderSend(request,result) ) PrintFormat("OrderSend error %d",GetLastError());
else Print(result.price);

在DEMO(result=request)上完美无缺地工作。

但在REAL上 - 不可能得到一个结果(结果=0.0)。除非你等待几秒钟。

 
Ivan Ivanov:

似乎是在主题中。

我想指出的是,这种代码。

在DEMO中,它工作得完美无缺(结果=请求)。

但在现实中 - 不可能得到结果(结果=0.0)。除非你等待几秒钟。

数据缺失--日志、OrderSend 后的结构字段值、贸易服务器名称。

 
fxsaber:

简而言之,重点是:如果有市场订单,也要考虑它是一个 "头寸"。用倒逗号,因为它是一个包裹的位置。突出显示的代码通常不会出现在任何地方。但它避免了重新开 仓。这里最有趣的事情是用红色强调的。对这一芯片的需求并不立即显现。

for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  // если мы сюда попадаем при проверке состояния, не запускать стратегию вообще, т.к. это промежуточное состояние.
 
Комбинатор:

在下一个tick上可能不会有交易信号。我自己用的是MT4风格,所以看到这样的 "仓位 "不禁莞尔。

 
fxsaber:

数据缺失--日志、OrderSend后的结构字段值、贸易服务器名称。

//+------------------------------------------------------------------+
//|                                                      TestBUY.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{//--- объявление и инициализация запроса и результата
  MqlTradeRequest request={0};
  MqlTradeResult result={0};
//--- параметры запроса
  request.action =TRADE_ACTION_DEAL;
  request.symbol=_Symbol; 
  request.volume=0.01;
  request.type=ORDER_TYPE_BUY;
  request.price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
  request.deviation=5;
  request.magic=1234;
  request.tp=0.0;
  request.comment=DoubleToString(request.price,_Digits);
//--- отправка запроса
  if ( !OrderSend(request,result) )
    PrintFormat("OrderSend error %d",GetLastError()); // если отправить запрос не удалось, вывести
//--- информация об операции
  PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order," NewOrder");
}


2018.02.20 15:20:35.845 交易订单 #66745055 在市场上购买 0.01 / 0.01 EURUSDeur 在 610.625 ms内完成。

2018.02.20 15:20:35.935 交易交易#5461453 在1.23403买入0.01 EURUSDeur完成(基于订单#66745055)。

2018.02.20 15:20:35.845 TestBUY (EURUSDeur,M15)retcode=10009 deal=0 order=66745055

如果请求被满足(10009),为什么处理=0

 
Ivan Ivanov:

如果请求已经完成(10009),为什么deal=0?

这几乎就是讨论的开始。这些链接有所有的细节。

有一个解决方案可以让OrderSend完美地工作,但那将是广告。

 
fxsaber:

使用一个简单的例子的正确选择

简而言之,重点是:如果有市场订单,也要考虑它是一个 "头寸"。用引号,因为它是一个包裹的位置。突出显示的代码通常不会出现在任何地方。但它避免了重新开 仓。这里最有趣的事情是用红色强调的。这个芯片的必要性并不立即显现。

事情是这样的,有所谓的收盘市场订单。同样的SL/TP。显然,我们不希望将这种市场订单视为 "头寸"。我们也不希望看到我们已经下的那些订单也被关闭。因此,突出显示的条件是适当的过滤器。

for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

SZY在这里 插入这段代码并在演示服务器上 检查结果。

我邀请所有感兴趣的人讨论这个问题。我对这个问题的看法如下。


  1. 我们向服务器发送一个订单。
  2. 一个市场订单的出现,最终可能被取消,但我们是否已经把它算作一个头寸?
for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

如果发现一个没有位置ID的订单(ID为0),这个循环会增加一个位置。

我们又退回了一个职位。

如果订单被服务器取消了怎么办?

...

我认为在计算市场订单时,我们应该返回WRONG_VALUE,例如,如果我们发现一个--头寸不能小于0。这将是一个信号,表明有一个未被记录的市场订单。但不是为了增加职位的数量。