MT5でのデリバティブ市場の相場

 

モデレーターの皆様へ

トピック「メリットでクリア????*」からの投稿を移動してください。

クリアリングとは関係なく、ここで

Форум трейдеров - MQL5.community
Форум трейдеров - MQL5.community
  • www.mql5.com
MQL5: форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
 

コードのバグを見つけるか、CopyTicks()が正しく動作していないことを確認 するのにご協力ください。

問題:CopyTicks()でコピーすると、ティックスキップする。

の順序で操作します。

コード

//+------------------------------------------------------------------+
//|                                                ABL_Collector.mq5 |
//|                                     Copyright 2021, prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, prostotrader"
#property link      "https://www.mql5.com"
#property version   "1.00"
//---
input string StTime =  "07:00:00";  //Начало сбора тиков
input string EndTime = "23:50:00";  //Конец сбора тиков
//---
struct MARKET_DATA
  {
   int               cnt;
   datetime          time[];
   ulong             time_msc[];
   double            ask[];
   double            bid[];
   double            last[];
   long              volume[];
   string            flags[];
   ulong             mem_time;
   int               skip_cnt;
   MqlTick           ticks[];
  } m_data;
int f_handle;
datetime start_time, end_time;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   m_data.cnt = 0;
   m_data.mem_time = 0;
   ArrayResize(m_data.time, 5000000, 5000000);
   ArrayResize(m_data.time_msc, 5000000, 5000000);
   ArrayResize(m_data.ask, 5000000, 5000000);
   ArrayResize(m_data.bid, 5000000, 5000000);
   ArrayResize(m_data.last, 5000000, 5000000);
   ArrayResize(m_data.volume, 5000000, 5000000);
   ArrayResize(m_data.flags, 5000000, 5000000);
   f_handle = FileOpen("ABL_Colletor.csv", FILE_WRITE|FILE_CSV);
   if(f_handle == INVALID_HANDLE)
     {
      Alert("Не создан *.CSV файл!");
      return(INIT_FAILED);
     }
   else
     {
      FileWrite(f_handle, "Symbol: ", Symbol());
      FileWrite(f_handle, "Tick num", "Date", "Tick time", "ASK", "BID", "LAST", "VOLUME", "Tick Flags");
     }
   start_time = StringToTime(StTime);
   end_time = StringToTime(EndTime);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(f_handle != INVALID_HANDLE)
     {
      ulong a_time = m_data.time_msc[0];
      for(int i = 0; i<m_data.cnt; i++)
        {
         if(a_time != m_data.time_msc[i])
           {
            FileWrite(f_handle, "");
            a_time = m_data.time_msc[i];
           }
         FileWrite(f_handle, IntegerToString(i + 1),
                   TimeToString(m_data.time[i], TIME_DATE),
                   TimeToString(m_data.time[i], TIME_SECONDS) + "." + StringFormat("%03i", m_data.time_msc[i]%1000),
                   DoubleToString(m_data.ask[i], Digits()),
                   DoubleToString(m_data.bid[i], Digits()),
                   DoubleToString(m_data.last[i], Digits()),
                   string(m_data.volume[i]),
                   m_data.flags[i]);

        }
     }
   ArrayResize(m_data.time, 0, -1);
   ArrayResize(m_data.time_msc, 0, -1);
   ArrayResize(m_data.ask, 0, -1);
   ArrayResize(m_data.bid, 0, -1);
   ArrayResize(m_data.last, 0, -1);
   ArrayResize(m_data.volume, 0, -1);
   ArrayResize(m_data.flags, 0, -1);
  }
//+------------------------------------------------------------------+
//| Expert fill data function                                        |
//+------------------------------------------------------------------+
void FillData(const int skip, const int t_cnt)
  {
   string c_flags;
   m_data.skip_cnt = 0;                                                      //Обнуляем счетчик тиков с одним временем (последним)
   for(int i = skip; i < t_cnt; i++)
     {
      c_flags = "";
      m_data.ask[m_data.cnt] = m_data.ticks[i].ask;                                              //Сохраняем значения
      m_data.bid[m_data.cnt] = m_data.ticks[i].bid;
      m_data.last[m_data.cnt] = m_data.ticks[i].last;
      m_data.volume[m_data.cnt] = long(m_data.ticks[i].volume_real);
      m_data.time[m_data.cnt] = m_data.ticks[i].time;
      m_data.time_msc[m_data.cnt] = m_data.ticks[i].time_msc;
      //Собираем все флаги
      if((m_data.ticks[i].flags&TICK_FLAG_ASK) == TICK_FLAG_ASK)
         c_flags += " TICK_FLAG_ASK,";    
      if((m_data.ticks[i].flags&TICK_FLAG_BID) == TICK_FLAG_BID)
         c_flags += " TICK_FLAG_BID,";
      if((m_data.ticks[i].flags&TICK_FLAG_LAST) == TICK_FLAG_LAST)
         c_flags += " TICK_FLAG_LAST,";
      if((m_data.ticks[i].flags&TICK_FLAG_BUY) == TICK_FLAG_BUY)
         c_flags += " TICK_FLAG_BUY,";
      if((m_data.ticks[i].flags&TICK_FLAG_SELL) == TICK_FLAG_SELL)
         c_flags += " TICK_FLAG_SELL,";
      if((m_data.ticks[i].flags&TICK_FLAG_VOLUME) == TICK_FLAG_VOLUME)
         c_flags += " TICK_FLAG_VOLUME,";
      int f_len = StringLen(c_flags);                                                          //Кастрируем последнюю запятую в строке
      if(f_len > 1)
        {
         StringSetCharacter(c_flags, f_len - 1, ushort(" "));
         StringTrimRight(c_flags);
        }
      m_data.flags[m_data.cnt] = c_flags + " (" + string(m_data.ticks[i].flags) + ")";         //Записываем флаги
      m_data.cnt++;                                                                            //Увеличиваем счетчик всех записей
      if(m_data.mem_time == ulong(m_data.ticks[i].time_msc))
         m_data.skip_cnt++;                                                  //Увеличиваем счетчик тиков с последним (одинаковым) временем
     }
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime cur_time = TimeTradeServer();                                 //Берем текущее время сервера
   if((cur_time >=start_time)&&(cur_time<end_time))                       //Проверка времени торговли
     {
      int result = 0;
      if(m_data.mem_time == 0)                                             //Проверка на 1-ю запись
        {
         result = CopyTicks(Symbol(), m_data.ticks, COPY_TICKS_ALL, 0, 20); //Копируем последние 20 тиков
         if(result >= 1)
           {
            m_data.mem_time = ulong(m_data.ticks[result-1].time_msc);        //Запоминаем время последнего тика
            FillData(0, result);                                             //Сохраняем данные
           }
        }
      else  //Последующие записи
        {
         result = CopyTicks(Symbol(), m_data.ticks, COPY_TICKS_ALL, m_data.mem_time, 1000); //Копируем тики с запомненного времени
         if(result >= 1)                                                                    //плюс последующие тики (если есть)
           {
            if(m_data.mem_time < ulong(m_data.ticks[result-1].time_msc))    //Проверяем, изменилось ли время последнего тика
              {
               m_data.mem_time = ulong(m_data.ticks[result-1].time_msc);     //Запоминаем время последнего тика
               FillData(m_data.skip_cnt, result);                            //Сохраняем данные, минус уже сохраненные с
              }                                                               //предыдущим последнем временем (m_data.skip_cnt)
           }
        }
     }
  }
//+------------------------------------------------------------------+

Expert Advisorが動作した後、ABL_Colletor.csvというファイル(zipファイル内)を取得します。

ターミナルからティックを保存しています

GAZR-12.21.csv zip形式)を取得しました。

GAZR-12.21_mix.csv.xlsx(ZIPファイル)のファイルを比較します。

ファイル:
Files_lost.zip  74 kb
 
では、何が問題なのでしょうか?見積もり内容に矛盾はないか?
 
ソースコードにエラーは見当たりません。COPY_TICKS_ALLを別の値に置き換えれば、スキップせずに動作すると推測されます。
 
Mihail Marchukajtes #:
では、何が問題なのでしょうか?見積もり内容に矛盾はないか?

存在する。

端末内に物理的に引用符が存在するが、すべてを 取得することはできない(COPY_TICKS_ALL)

 
fxsaber #:
ソースコードにエラーは見当たりません。COPY_TICKS_ALLを別の値に置き換えれば、隙間なく動作するのでは?

今試してみますが、COPY_TICKS_ALLでも 動作するはずです。

 

はい、確かにCOPY_TICKS_TRADEフラグで、スキップは ありませんが、私は取引と入札の両方の質問が必要です。

また松葉杖か?

result = CopyTicks(Symbol(), m_data.ticks, COPY_TICKS_TRADE, m_data.mem_time, 1000);
//плюс
result = CopyTicks(Symbol(), m_data.ticks, COPY_TICKS_INFO, m_data.mem_time, 1000);

しかし、すぐに2つの大きな問題が発生します。

1.時刻を「同期」させる方法

2.ASKとBIDが正しいかどうかを確認する方法

 
prostotrader #:

はい、確かにCOPY_TICKS_TRADEフラグで、スキップは ありませんが、私は入札でトレードとアスクの両方が必要です。

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

MetaTrader 5の新ビルド3081:MQL5サービスの改善とデザインの更新

fxsaber, 2021.10.19 16:30

2つの異なるスレッド(INFOとLAST)を人工的に1つのALL-flowに結合しています。

同じミリ秒に取引所はINFOフローで36800の買値を提示した。そして、LAST-FLOWでは多くの案件がありました。もし時間がナノ秒単位で計測されるなら、INFO-priceはdealより遅くなることは明らかです。


MT5では、ストリームのマージと同期に時間をかけています。このため、現在のティック履歴を構築する際に、リアルタイムで非常に大きなラグが発生することがあります。ミリ秒が失われる可能性があります。

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

MetaTrader 5の新ビルド3081:MQL5サービスの改善とデザインの更新

fxsaber, 2021.10.19 16:38

ターミナルでBook-streamを監視して、新鮮なCopyTicksと比較すれば、いろいろと矛盾が生じると思います。とはいえ、今にして思えば、かなりまともなものでしょう。

 
fxsaber #:

取引所からの取引は、別の流れになりますね。

のように、質問と入札をしてください。

COPY_TICKS_ALLはこれら2つのストリームからサンプリングしていますが、正しく実行されていないだけです。

そして、そのサンプルは、両方のスレッドが別々のものではなく、「ストレートスルー」の時間を持つので、ミリ秒を取ることはできません!

松葉杖を作ったが、うまくいったようだ。

//+------------------------------------------------------------------+
//|                                                ABL_Collector.mq5 |
//|                                     Copyright 2021, prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, prostotrader"
#property link      "https://www.mql5.com"
#property version   "1.00"
//---
input string StTime =  "07:00:00";  //Начало сбора тиков
input string EndTime = "23:50:00";  //Конец сбора тиков
//---
struct MARKET_DATA
{
   datetime time;
   ulong    time_msc;
   double   ask;
   double   bid;
   double   last;
   long     volume;
   string   flags;
};
struct A_DATA
{
  int         cnt;
  ulong       m_time_info;
  ulong       m_time_trade;
  int         s_cnt_info;
  int         s_cnt_trade;
  MqlTick     ticks_trade[];
  MqlTick     ticks_info[];
  MARKET_DATA m_data[];
}a_data;
  
int f_handle;
datetime start_time, end_time;
//+------------------------------------------------------------------+
//| Expert Array fast sort function                                  |
//+------------------------------------------------------------------+
void ArrayFastSort(MARKET_DATA &array[], const int size)
{
   ulong msc_val;
   MARKET_DATA temp;
   MARKET_DATA tmp_arr[];
   ArrayResize(tmp_arr, size, size);
   for(int i = 0; i < size; i++)
   {
     tmp_arr[i] = array[i];   
   }
   int n[] = {9,5,3,2,1};
   int i, j, z, y;
   for(z = 0;z < 5;z++)
   {
     y = n[z];
     for(i = y;i < size;i++)
     {
       msc_val = tmp_arr[i].time_msc;
       temp = tmp_arr[i];
       for(j = i - y; j >= 0 && msc_val < tmp_arr[j].time_msc; j -= y)
       {
         tmp_arr[j + y] = tmp_arr[j];
       }
       tmp_arr[j + y] = temp;
     }
  }
  for(i = 0; i < size; i++)
  {
    msc_val = tmp_arr[i].time_msc;
    for(j = 0; j < size; j++)
    {
      if(array[j].time_msc == 0) continue;
      if(msc_val == array[j].time_msc)
      {
        tmp_arr[i] = array[j];
        array[j].time_msc = 0;
        break;
      }
    }   
  }
  for(i = 0; i < size; i++)
  {
    array[i] = tmp_arr[i];   
  }
}
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   a_data.cnt = 0;
   a_data.m_time_info = 0;
   a_data.m_time_trade = 0;
   ArrayResize(a_data.m_data, 5000000, 5000000);
   f_handle = FileOpen("ABL_Colletor.csv", FILE_WRITE|FILE_CSV);
   if(f_handle == INVALID_HANDLE)
     {
      Alert("Не создан *.CSV файл!");
      return(INIT_FAILED);
     }
   else
     {
      FileWrite(f_handle, "Symbol: ", Symbol());
      FileWrite(f_handle, "Tick num", "Date", "Tick time", "ASK", "BID", "LAST", "VOLUME", "Tick Flags");
     }
   start_time = StringToTime(StTime);
   end_time = StringToTime(EndTime);
   int result = CopyTicks(Symbol(), a_data.ticks_info, COPY_TICKS_ALL, 0, 1);
   if(result >= 1)
   {
     a_data.m_time_info = a_data.ticks_info[0].time_msc;
     a_data.m_time_trade = a_data.ticks_info[0].time_msc;
   }
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
  if(f_handle != INVALID_HANDLE)
  {
    ArrayFastSort(a_data.m_data, a_data.cnt);
    ulong a_time = a_data.m_data[0].time_msc;
    for(int i = 0; i < a_data.cnt; i++)
    {
      if(a_time != a_data.m_data[i].time_msc)
      {
        FileWrite(f_handle, "");
        a_time = a_data.m_data[i].time_msc;
      }
      FileWrite(f_handle, IntegerToString(i + 1),
                TimeToString(a_data.m_data[i].time, TIME_DATE),
                TimeToString(a_data.m_data[i].time, TIME_SECONDS) + "." + StringFormat("%03i", a_data.m_data[i].time_msc%1000),
                DoubleToString(a_data.m_data[i].ask, Digits()),
                DoubleToString(a_data.m_data[i].bid, Digits()),
                DoubleToString(a_data.m_data[i].last, Digits()),
                string(a_data.m_data[i].volume),
                a_data.m_data[i].flags);

    }
  }
  ArrayResize(a_data.m_data, 0, -1);
  Print("Collect ticks DONE!");
}
//+------------------------------------------------------------------+
//| Expert fill data function                                        |
//+------------------------------------------------------------------+
void FillData(const int skip, const int t_cnt, ulong &mem_time, int &skip_cnt, MqlTick &ticks[])
{
  string c_flags;
  skip_cnt = 0;
  for(int i = skip; i < t_cnt; i++)
  {
    c_flags = "";
    a_data.m_data[a_data.cnt].ask = ticks[i].ask;                                           
    a_data.m_data[a_data.cnt].bid = ticks[i].bid;
    a_data.m_data[a_data.cnt].last = ticks[i].last;
    a_data.m_data[a_data.cnt].volume = long(ticks[i].volume_real);
    a_data.m_data[a_data.cnt].time = ticks[i].time;
    a_data.m_data[a_data.cnt].time_msc = ticks[i].time_msc;
//---
    if((ticks[i].flags&TICK_FLAG_ASK) == TICK_FLAG_ASK)
      c_flags += " TICK_FLAG_ASK,";    
    if((ticks[i].flags&TICK_FLAG_BID) == TICK_FLAG_BID)
      c_flags += " TICK_FLAG_BID,";
    if((ticks[i].flags&TICK_FLAG_LAST) == TICK_FLAG_LAST)
      c_flags += " TICK_FLAG_LAST,";
    if((ticks[i].flags&TICK_FLAG_BUY) == TICK_FLAG_BUY)
      c_flags += " TICK_FLAG_BUY,";
    if((ticks[i].flags&TICK_FLAG_SELL) == TICK_FLAG_SELL)
      c_flags += " TICK_FLAG_SELL,";
    if((ticks[i].flags&TICK_FLAG_VOLUME) == TICK_FLAG_VOLUME)
      c_flags += " TICK_FLAG_VOLUME,";
    int f_len = StringLen(c_flags); 
    if(f_len > 1)
    {
       StringSetCharacter(c_flags, f_len - 1, ushort(" "));
       StringTrimRight(c_flags);
    } 
    a_data.m_data[a_data.cnt].flags = c_flags + " (" + string(ticks[i].flags) + ")"; 
    a_data.cnt++;                                                                    
    if(mem_time == ulong(ticks[i].time_msc)) skip_cnt++;    
  }
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
  datetime cur_time = TimeTradeServer();                            
  if((cur_time >=start_time)&&(cur_time<end_time))                  
  {
      int result = 0;
      result = CopyTicks(Symbol(), a_data.ticks_info, COPY_TICKS_INFO, a_data.m_time_info, 1000);
      if(result >= 1)
      {
        if(a_data.m_time_info < ulong(a_data.ticks_info[result -1].time_msc))
        {
          a_data.m_time_info = a_data.ticks_info[result -1].time_msc;
          FillData(a_data.s_cnt_info, result, a_data.m_time_info, a_data.s_cnt_info, a_data.ticks_info);
        }
      }
      result = CopyTicks(Symbol(), a_data.ticks_trade, COPY_TICKS_TRADE, a_data.m_time_trade, 1000);
      if(result >= 1)
      {
        if(a_data.m_time_trade < ulong(a_data.ticks_trade[result -1].time_msc))
        {
          a_data.m_time_trade = a_data.ticks_trade[result -1].time_msc;
          FillData(a_data.s_cnt_trade, result, a_data.m_time_trade, a_data.s_cnt_trade, a_data.ticks_trade);
        }
    }
  }
}
//+------------------------------------------------------------------+

見積もりを集める必要がある人がいる場合に使えます。

AsksとBidをExchangeと照合できないのが残念

 

CopyTicks()CopyTicksRange() の調査をまとめると。

ビルド3101、リアル、オープン

1.COPY_TICKS_ALLフラグが使用されている場合、トランザクションのスキップが 発生します。

COPY_TICKS_TRADE フラグを使用 した場合、正しく表示 されます。

2.引用元: 想像を絶することが起こる(ASK/BID)

存在しない価格で取引が成立してしまう


取引は反対価格で行われる(ASKの代わりにBIDを使用する)

引用符のスキップ

大きな疑問があります。

価格に大きな開きがある場合、端末には何が入っているのでしょうか?

どのような価格で取引されているのでしょうか?

ZIP アーカイブのソースファイル


ファイル:
 
prostotrader #:

2.引用元: 想像を絶する何かが起きている(ASK/BID)

取引は間違った価格で行われる

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

MetaTrader 5の新ビルド3081:MQL5サービスの改善とデザインの更新

fxsaber, 2021.10.19 16:57

それなら、MQが取引所から流されるデータを見逃しているという証拠を突きつけてくださいよ。

MQが無視しないスレッドで、そのスレッドの最初の書き込みの要領でやってください。

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

CopyTicks」のテスト

ドミトリー・スクブ 2015.03.24 09:17

まずは簡単なものから、音量。以下は、検出された不具合の写真です。定期的に巻末に「替え玉」を用意しています。

理由: