OrderSend()问题 - 页 5

 

显然,我没有很清楚地解释前面的问题。让我再试一次。

在去年,ENUM_ORDER_TYPE_FILLING 枚举值列表的描述至少被改变了三次。 以前的描述看起来如下

enum_order_type_filling

识别器

描述

订单_灌装_福克

一笔交易只能以指定的数量和等于或优于订单中指定的价格执行。如果目前市场上没有足够的供应来满足该订单符号,那么该订单将不会被执行。这种填充类型用于SYMBOL_TRADE_EXECUTION_INSTANT 执行模式 SYMBOL_TRADE_EXECUTION_REQUEST

订单_填充_ioc

在订单规定的交易量范围内,以市场上可获得的最大交易量并以等于或优于订单规定的价格执行交易的协议。在这种情况下,将不会为缺乏的数量下达额外的订单。这种填充类型只能在执行模式SYMBOL_TRADE_EXECUTION_MARKET SYMBOL_TRADE_EXECUTION_EXCHANGE 中使用,具体取决于交易服务器上的设置。

订单_填充_返回

同意在订单规定的数量范围内,以市场上最大的交易量,并以等于或优于订单规定的价格执行交易。在这种情况下,我们将以该订单中规定的价格为所缺的数量发出一个额外的订单。这种填充类型只用于挂单(TRADE_ACTION_PENDING

我们不难看出,ORDER_FILLING_RETURN和挂单之间 存在着一对一的对应关系,即 ORDER_FILLING_RETURN只能应用于挂单,所有 挂单的type_filling 字段只能用ORDER_FILLING_RETURN 的值填充。

对于市场订单(action==TRADE_ACTION_DEAL),根据服务器端设置的执行模式,type_filling 字段应该已经填写。

因此,我们有一定的范式:如果有一个挂单,ORDER_FILLING_RETURN;如果有一个市场订单,ORDER_FILLING_FOK或ORDER_FILLING_IOC(取决于模式)

现在,一切都被颠覆了一下,即。

enum_order_type_filling

识别器

描述

订单_灌装_福克

这种订单填充政策意味着订单只能被填充到指定的数量。如果目前市场上没有足够的金融工具的数量,订单将不会被执行。所需的数量可以从目前市场上的几个报价中编制出来。

订单_填充_ioc

表示同意在订单规定的数量内执行市场上的最大交易量。如果不可能完全执行,订单将被填充到可用的量,而未填充的量将被取消。

订单_填充_返回

这种模式只用于ORDER_TYPE_BUY_LIMIT和ORDER_TYPE_SELL_LIMIT订单。在部分执行的情况下,剩余数量的限价单不会被删除,而是仍然有效。

对于ORDER_TYPE_BUY_STOP_LIMIT和ORDER_TYPE_SELL_STOP_LIMIT订单,激活时将创建相应的ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT限价订单,其执行类型为ORDER_FILLING_RETURN。

只对市场订单 使用ORDER_FILLING_FOK和ORDER_FILLING_IOC的限制已经消失 同时, 根据服务器上设置的执行模式,对 市场订单 使用ORDER_FILLING_FOK和ORDER_FILLING_IOC 没有限制。 使用ORDER_FILLING_RETURN 有一个限制,即只能使用限价和止损订单

所以我的问题是:对所有订单(包括市场和挂单使用ORDER_FILLING_FOK和 ORDER_FILLING_IOC,包括限价和止损订单是否可以接受 有谁搞清楚了这些变化?

 

标准库有 这种方法(示意图)。

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   return(true);
  }

在这里,如果持仓量大于进行交易的最大数量,就会连续尝试部分平仓

在成功调用OrderSend() 函数后,设置了 一个延迟秒数,然后在do-while循环的主体中调用PositionSelect() 函数。也就是说,如果服务器成功地接受了一个市场订单,一秒钟就足以更新基础终端中的未平仓头寸数据,并在下一次迭代中获得更新的头寸数据(在我们的例子中是头寸量)。但在两年前,同一方法在调用PositionSelect() 函数之前的延迟时间是3秒。因此,问题是。

在所有情况下,一秒钟 是否足以确保 在成功调用OrderSend() 后,终端数据库能保证收到更新的头寸数据(从而使剩余的头寸量在终端侧得到正确处理)?在这种情况下,应保证终端数据库在多长的时间内能收到更新的位置数据?

 

冠军赛有这样的规定。

交易条件将尽可能地接近真实

  • 交易请求的处理时间从2秒到7秒
在一个经纪商的真实情况下(提款后),处理过程变得约3秒(打开-关闭-修改).立即切换到NDD.到目前为止很满意。
 
Karlson:

冠军赛有这样的规定。

交易条件将尽可能地接近真实

  • 处理时间为2至7秒

好的,谢谢你的提示!事实证明,在成功调用OrderSend() 函数后,一秒钟的时间不足以终端数据库收到更新的位置数据?

从这个结论可以看出,我所引用的标准库方法根本不能保证位置会被逆转而不是被关闭。即,如果PositionClose()方法将下一次迭代延迟一秒,而交易请求的处理时间可能会延长2-7倍,我们不能排除在新的迭代过程中,PositionSelect() 函数会从基础终端接收之前的 仓位状态数据,并用相同的订单轰击服务器,这种情况下的总成交量将大于初始 仓位的成交量

那为什么PositionClose()方法会有一秒钟的延迟,如果它允许翻转头寸而不是关闭它?而这与"尽可能接近真实的交易条件"不一致?

总的来说,我需要更多的信息,在成功调用OrderSend() 函数后,终端数据库保证在多长时间内收到更新的头寸数据,以及标准PositionClose()方法中一秒钟 的延迟是什么原因。

 
让我们从以下事实开始
if(PositionSelect(symbol))

并不保证任何事情。它不能被使用。

其次,对终端数据的更新没有提供任何保证。 你必须自己设置一个人为的TradeContextBusy,并等待所有的订单被处理。
你不能立即动手,一头扎进MQL5。没有时间保证。

 

sergeev:

начнем с того, что

if(PositionSelect(symbol))

并不保证任何事情。它不能被应用。

其次,终端数据的更新没有保证--你必须自己组织一个人为的TradeContextBusy,并等待所有的订单被处理。
你不能直接和直接使用MQL5。没有时间保证。

是的,我得继续思考。事实证明,我应该以库中的标准方法为例进行回收。

你能告诉我,如果一个交易出现在历史上,与

拒绝接受

市场退出

这是否意味着终端数据库中的所有 信息已经自动改变(更新到当前状态)?或者该交易可能已经出现在历史中,但有关头寸的信息仍然不会被更新?换句话说,这个问题很有意思:历史上的交易信息和相应头寸的信息是否同时发生变化?或者,在这种情况下,交易和头寸也会在终端异步更新?我没能在Rosh的文章中找到它--据我理解,那里描述了终端基础更新和交易请求结果 返回之间的异步。

 

正如你所注意到的,终端中的数据交换模式是异步的。

所以在交易时(检索订单/交易/仓位的属性),我们需要分析数据检索的成功率。而在出现任何错误(false/0)的情况下,终止对交易逻辑的分析。

所有已执行的和未确认的OrdSend订单都应被记住,并等待订单的出现,如果之前的发送还没有答案,则阻止新订单的发送。

而且,举例来说,最好用一个结构来取代PositionSelect

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

一般来说,交易 逻辑必须是异步的。由于终端是异步的,MT-服务器和流动性提供者的服务器也是异步的。

检查同步的任务完全由MQL程序员决定。

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Типы торговых операций - Документация по MQL5
 

我在上次的冠军赛中使用这个答案没有问题。

https://www.mql5.com/ru/forum/4342#comment_88688

Дублирование запросов на открытие позиций.
Дублирование запросов на открытие позиций.
  • www.mql5.com
Дублирование запросов на открытие позиций.
 
sergeev:

而且,举例来说,最好用结构体取代PositionSelect

for(int i=PositionsTotal()-1;i>=0;i--) 
{
  if(PositionGetSymbol(i)==Symbol())
  {
    ....
  }

如果不难,请解释一下,使用PositionsTotal()+PositionGetSymbol()使用PositionSelect() 有什么优势?这三个函数都在访问同一个终端基座,PositionGetSymbol() 和PositionSelect()函数可能失败。也就是说,如果该位置存在于终端基地,PositionSelect()函数和建议的结构都可能失败。你仍然要检查错误代码。

你的结构有什么特点/可靠性?我还是搞不清楚。

Документация по MQL5: Торговые функции / PositionSelect
Документация по MQL5: Торговые функции / PositionSelect
  • www.mql5.com
Торговые функции / PositionSelect - Документация по MQL5
 

我在绞尽脑汁......停止器就是不设置......还有很多错误。这是实验中剩下的东西,它不会再工作了

void OnTick(){ if(PositionsTotal()<1){OPEN();}}

bool OPEN(){
             MqlTradeRequest request;
             MqlTradeResult result;
             

             request.symbol       = _Symbol;
             request.action       = TRADE_ACTION_DEAL;
             request.type_filling = ORDER_FILLING_FOK;
             request.deviation    = 100;
             request.volume       = NormalizeDouble(2,2);
             request.type         = ORDER_TYPE_BUY;
             request.price        = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
             request.tp           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) + 500*_Point,_Digits);
             request.sl           = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK) - 500*_Point,_Digits);

             OrderSend(request,result);     
                        
             if(result.retcode==10009 || result.retcode==10008)  Print("Succsesful open");
             else                                               Print("Error open: ",DoubleToString(GetLastError(),0),"  response code: ",result.retcode);
    
   return(true);}

如果你这样做了,就不会有任何错误,但仍然没有设置止损。

MqlTradeRequest request={0};MqlTradeResult result={0};