Kütüphaneler: OnTickMulti - sayfa 5

 
Stanislav Korotky #:

Test senaryosunun tam anlamıyla işlevsel olması için pratik bir senaryoyu anlamam gerekiyor: sadece milisaniye hassasiyetinde zamanları çakışan tiklere göre işlem mi yapıyoruz?

Hayır. Hedef, tüm semboller için her zaman güncel bir ortam sağlamaktır. Benim örneğimde, OnTimer'da güncellik koşulu her zaman karşılanır. Pozisyon açma işlemi sadece bir gösterim amaçlıdır.
 
fxsaber #:
Hayır. Amaç, tüm sembollere göre her zaman güncel bir ortam sağlamak. Benim örneğimde, OnTimer'da güncellik koşulu her zaman karşılanır. Pozisyon açma işlemi sadece bir gösterim amaçlıdır.

Tamam.

OnTickMulti olayındaki uygulamanın nerede bir tik “kaybettiği”, başka bir deyişle, SymbolInfoTick'in beklenen fiyatları döndürmemesi nasıl oluyor (daha önce, göstergeden gelen özel olayların işlenmesinden kaynaklanan bir gecikme olabileceğini varsaymıştım) - Deneyin saflığı için casus gösterge olmadan test ederdim - en azından aynı zaman damgası için normal OnTick'ten tüm sembollere SymbolInfoTick/CopyTicks'i kullanırdım.

OnTimer'a gelince, bu konuda bazı sorularım var (yanlışım varsa düzeltin lütfen):

void OnTimer()
{
  if (TimeMsc++ == 1759280400081) // 01.10.2025 01:00:00.081
    PositionOpen();
}

İşleyicinin bir milisaniyeden daha hızlı çalışacağına dair bir garantimiz yok, bu nedenle sayacın basitçe artırılması, başlangıçtaki senkronizasyonun korunacağını garanti etmez, yani sunucu zamanıyla eşleştirme, her seferinde (pozisyon açıldıktan sonra veya artırımdan daha karmaşık diğer hesaplamalar yapıldıktan sonra, eğer varsa) anında doğru bir şekilde yapılmalıdır. Başka bir deyişle, çok sayıda pozisyon açılması gerektiğinde, burada sunulan bu rafine yaklaşım işe yaramayacaktır.

Ayrıca, başlangıç senkronizasyonu (sayaçın başlatılması) da bence %100 kusursuz değil.

ulong TimeMsc = TimeTradeServer() * 1000 + (inTimer && EventSetMillisecondTimer(1));

Diyelim ki test ortamında sunucu saati gerçekten milisaniye olmadan başlıyor, ama böyle bir kod çevrimiçi ortamda nasıl çalışacak? Ve neden 1 milisaniye ekliyoruz? Ben yine de sunucu saatini tiklerden alırdım.

Bunlar titizlik değil, sadece “güncellik koşulunun her zaman yerine getirilmesi” konusundaki şüphelerim.

 
Stanislav Korotky #:

Sayıcının basit bir artış, başlangıçtaki senkronizasyonun korunacağını garanti etmez

Test ortamında çalışır.

Peki bu kod çevrimiçi ortamda nasıl çalışacak?

Çevrimiçi ortamda böyle bir sorun yoktur, çünkü terminale gelen tüm veriler gösterge niteliğindedir: gecikmeler nedeniyle güncel değildir.

Peki neden 1 milisaniye ekliyoruz?

Çünkü ilk OnTimer, hemen değil, belirlenen aralıkta çağrılacaktır.

 
Stanislav Korotky #:

OnTickMulti olayındaki uygulamanın nerede bir tik "kaybettiği" ya da başka bir deyişle, SymbolInfoTick'in neden beklenen fiyatları döndürmediği henüz belirsiz

OnTickMulti kesinlikle bu durumla ilgisi yok, çünkü standart SymbolInfoTick işlevi bazı semboller için doğru tik değerini döndürürken, diğer semboller için döndürmüyor.


Bunun tek nedeni, tiklerin gönderilme sırasıdır.

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi ile ilgili forum

Kütüphaneler: OnTickMulti

fxsaber, 30.09.2025 09:24

Aynı zamanlı tikler aynı anda gelmez. Hepsi sırayla gelir. Ve eğer EURUSD'deki daha geç zamanlı tik ilk olarak geldiyse, o anda ikinci olarak gelecek olan GBPUSD'deki aynı zamanlı tik hakkında hiçbir şey bilinmez. Bu nedenle, ilk EURUSD tikinin geldiği anda, ikinci GBPUSD tiki henüz mevcut değildir; bunun yerine, bir önceki GBPUSD tikine ait veriler mevcuttur.
 
fxsaber #:

Çünkü ilk OnTimer, hemen değil, belirlenen aralıkta çağrılacaktır.

Tüm verileri güncellemenin hızlı bir yolunu buldum.

#include <fxsaber\OnTickMulti\OnTickMulti.mqh> // https://www.mql5.com/tr/code/47647

#include <MT4Orders.mqh> // https://www.mql5.com/tr/code/16006

void PositionOpen()
{
  for (uint i = ArraySize(OnTickMultiObject.Symbols); (bool)i--;)
  {
    const string SymbName = OnTickMultiObject.Symbols[i];
    
    OrderSend(SymbName, OP_BUY, 1, SymbolInfoDouble(SymbName, SYMBOL_ASK), 0, 0, 0);
  }
}

long CurrentTime = 0;

// Çok karakterli OnTick.
void OnTickMulti( const string &Symb, const uint &Index )
{  
  MqlTick Tick;
  
  if (SymbolInfoTick(Symb, Tick) && (Tick.time_msc > CurrentTime))
  {
    CurrentTime = Tick.time_msc;
    
    EventSetMillisecondTimer(1);
  }  
}

void OnTimer()
{
  if (CurrentTime == 1759280400081) // 01.10.2025 01:00:00.081
    PositionOpen();
    
  EventKillTimer();
}

Bu mekanizma, normal modda bile (OnTickMulti olmadan tek para birimli modda) yalnızca güncel verilerle çalışmaya olanak tanır. Örneğin, EURUSD için aynı zamana sahip birkaç tik vardır. Güncelleme, bu dizideki en son tik olan güncel tikle çalışmaya olanak tanır.


Not: Bu, özel semboller oluşturmanın bir başka nedenidir — aynı zamana sahip dizilerden sadece son tik'i geçmişe kaydetmek. Bu durumda, tek para birimi modunda güncelleme her zaman sağlanacaktır.

Библиотеки: TicksShort
Библиотеки: TicksShort
  • 2025.09.26
  • www.mql5.com
Статьи и техническая библиотека по автоматическому трейдингу: Библиотеки: TicksShort
 
Rorschach #:

Ancak açılış fiyatları da aynı, her ne kadar tüm hisse senetlerinin açılış saatleri aynı olsa da.

Ve bu davranış nedeniyle bazı sistemleri düzgün bir şekilde test etmek imkânsız hale geliyor.

Açılış fiyatları modundaki test aracını hatırladım. İşin püf noktası, ismine rağmen test aracının bu modda 1 değil, 4 OHLC tik'i üretmesidir; oysa isimden sezgisel olarak 1 tik beklenir. Bu 4 kontrol noktasından, uzman danışmanlar için sadece ilk O alınır ve OnTick çağrılır; göstergeler için ise ek olarak HLC veya LHC (çubuğun yönüne bağlı olarak) için ilgili fiyatların tikleriyle birlikte OnCalculate 3 kez çağrılır. Bu üç ek nokta için zamanlar, yapay olarak çubuğun son üç saniyesine eşit olarak alınır. Sonuç olarak, casus gösterge semboller için tek bir olay yerine birkaç olay gönderir. Muhtemelen, açılış fiyatları modunu kullananların bunu dikkate alması gerekir.

Ayrıca (kitaptaki benzer casus göstergeme hata ayıklama ekleyerek) bir artefakt gözlemliyorum: önceki çubuğa ait ek sembolün tik olayı nedense yeni çubukta tekrarlanıyor, ancak daha sonra casusun OnCalculate işlevi çağrılıyor ve güncellenmiş fiyatla yeni ek sembol tikine ilişkin olay geliyor. Sonuç olarak, ek sembollerde güncel fiyata sahip olmak için olayların kendisinde zaman damgası bulunmalı ve daha önce işlenmiş olaylar tekrar işlenmemelidir. Ben bunu gönderim sırasında şu şekilde yapıyorum:

int OnCalculate(const int rates_total, const int prev_calculated, const int, const double &price[])
{
   MqlTick tick;
   SymbolInfoTick(_Symbol, tick);
   EventChartCustom(Chart, Message, Index, (double)tick.time_msc, NULL);
  
   return rates_total;
}

Ve alırken de (burada tek bir ek sembol örneği gösterilmiştir, çok sayıda sembol için timestamp[] dizisi gereklidir!):

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
   if(id == CHARTEVENT_CUSTOM + Message)
   {
      static long timestamp;
      long event = (long)dparam;
      if(event > timestamp)
      {
         OnSymbolTick((int)lparam);
         timestamp = event;
      }
   }
}

Aynı milisaniye değerine sahip tikler varsa, sistem son tik yerine ilk tikle işlem yapar.

 
Rorschach #:
Senkronizasyonun en basit yolu
Zaman serilerinin senkronizasyonunun iyi araştırılmış bir konu olduğunu ve hazır algoritmaların mevcut olduğunu düşünmüştüm, internete baktım ama hiçbir şey bulamadım