Bitte helfen Sie, einen Fehler im Code zu finden, oder bestätigen Sie, dass CopyTicks() nicht korrekt funktioniert.
Problem: Tick-Skipping, wenn mit CopyTicks() kopiert wird
Reihenfolge der Arbeitsschritte:
Code
//+------------------------------------------------------------------+ //| 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) } } } } //+------------------------------------------------------------------+
Nachdem der Expert Advisor funktioniert, erhalten wir die Datei ABL_Colletor.csv (in der Zip-Datei)
Ich speichere Zecken aus dem Terminal
Ich erhalte GAZR-12.21.csv (in zip)
Vergleich der Dateien in GAZR-12.21_mix.csv.xlsx ( in der Zip-Datei)
Ja, in der Tat, mit dem COPY_TICKS_TRADE-Flag, keine Skips, aber ich brauche sowohl Trades und Gebote fragt,
wieder eine Krücke?
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);
Aber 2 große Probleme entstehen sofort.
1. Wie man die Zeit "synchronisiert"
2. So überprüfen Sie ASK und BID auf ihre Korrektheit
Ja, in der Tat, mit dem COPY_TICKS_TRADE-Flag, keine Skips, aber ich brauche sowohl Trades und fragt mit Geboten,
Forum zum Thema Handel, automatische Handelssysteme und Testen von Handelsstrategien
Neuer MetaTrader 5 build 3081: Verbesserungen in MQL5 Services und aktualisiertes Design
fxsaber, 2021.10.19 16:30
Zwei verschiedene Threads (INFO und LAST) werden künstlich zu einem ALL-flow zusammengefasst.
In derselben Millisekunde gab die Börse im INFO-Fluss einen Geldkurs von 36800 an. Und im LAST-flow gab es eine Menge Angebote. Wenn die Zeit in Nanosekunden gemessen würde, wäre der INFO-Preis natürlich später als die Geschäfte.
MT5 benötigt Zeit, um die Streams zusammenzuführen und zu synchronisieren. Aus diesem Grund kann es bei der Erstellung des aktuellen Tickverlaufs zu erheblichen Verzögerungen in Echtzeit kommen. Es können Millisekunden verloren gehen.
Forum zum Thema Handel, automatisierte Handelssysteme und Strategietests
Neuer MetaTrader 5 build 3081: Verbesserungen in MQL5 Services und aktualisiertes Design
fxsaber, 2021.10.19 16:38
Ich denke, wenn Sie den Book-Stream im Terminal überwachen und ihn mit den frischen CopyTicks vergleichen, werden Sie eine Menge Abweichungen feststellen. Im Nachhinein betrachtet, wird es aber ziemlich gut sein.
Die Geschäfte der Börse laufen in einem separaten Strom, ja,
sowie fragen und bieten.
COPY_TICKS_ALL nimmt Stichproben aus diesen beiden Strömen, es ist nur nicht richtig gemacht.
Und diese Probe kann nicht Millisekunden dauern, weil beide Threads "durchgängig" Zeit haben, nicht in getrennten Threads!
Ich habe eine Krücke gebaut, die zu funktionieren scheint.
//+------------------------------------------------------------------+ //| 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); } } } } //+------------------------------------------------------------------+
Sie können es verwenden, wenn jemand Angebote einholen muss.
Schade, dass Nachfragen und Gebote nicht mit der Börse abgeglichen werden können.
Zusammenfassung der Untersuchung von CopyTicks() CopyTicksRange()
Bild 3101, real, Offen
1. Wenn das Kennzeichen COPY_TICKS_ALL verwendet wird, werden Transaktionen übersprungen,
beiVerwendung des FlagsCOPY_TICKS_TRADE- korrekt angezeigt werden.
2. Etwas Unvorstellbares geschieht mit Zitaten (ASK/BID)
Die Geschäfte werden zu Preisen ausgeführt, die nicht existieren
Transaktionen werden zum entgegengesetzten Preis ausgeführt (statt ASK wird BID verwendet)
Überspringen von Zitaten
Das ist eine wichtige Frage:
Wenn es eine große Preisdiskrepanz gibt, was ist dann im Terminal?
Zu welchen Preisen werden wir gehandelt?
Quelldateien im ZIP-Archiv
2. Bei den Kursen ist etwas Unvorstellbares im Gange (ASK/BID)
Die Geschäfte werden zu den falschen Preisen gemacht
Forum zum Thema Handel, automatisierte Handelssysteme und Strategietests
Neuer MetaTrader 5 build 3081: Verbesserungen in MQL5 Services und aktualisiertes Design
fxsaber, 2021.10.19 16:57
Dann weisen Sie MQ nach, dass ihnen die von der Börse übermittelten Daten fehlen!
Tun Sie dies in einem Thread, den die MQs nicht ignorieren, und in der Art des ersten Beitrags in diesem Thread.
Forum zum Thema Handel, automatische Handelssysteme und Testen von Handelsstrategien
Dmitriy Skub, 2015.03.24 09:17
Beginnen wir mit einem einfachen Beispiel - der Lautstärke. Unten sehen Sie ein Bild der entdeckten Störung. Von Zeit zu Zeit gibt es "Doppelgänger" in den Bänden.
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Liebe Moderatoren!
Bitte verschieben Sie die Beiträge aus dem Thema "Clearing auf der merits????*
die nichts mit dem Clearing zu tun haben, hier.