[SERVICE DESK] Zamanlayıcıda kıdemli TF'nin zamanı alınırken hata oluştu! - sayfa 7

 
Ihor Herasko :

Evet öyle. OnInit()'te, sonucu kontrol etmeden gerekli TF'lere bir çağrı yaparsınız (orada buna güvenemezsiniz) ve zaten OnCalculate'de IsTFDataReady() işlevini çağırırsınız. İstenen tüm TF'ler için true değeri döndürülür döndürülmez, gösterge algoritmasını yürütmeye başlayabilirsiniz.

Tamam, halledildi. Ancak açıkça belge eklemeniz gerekir, aksi takdirde hızlı zamanlayıcı geliştiricilerin birçok sorusuna neden olur.

 
Ihor Herasko :

Genel olarak, bir terminal bağlantısının varlığının çok önemli olduğu ne tür bir görev çözülüyor? Anladığım kadarıyla, bir gösterge bir veri görselleştirme aracıdır. Mevcut olan veriler. Yeni veriler geldiğinde, görselleştirmeyi güncelleyecektir. Ondan, verilerin alaka düzeyinin kontrolü gerekli olmamalıdır. Bu terminalin görevidir.

Görev, eski TF'lerin verilerini olabildiğince çabuk elde etmektir. Vitaly Gorbunov , IsConnected()'i hatırlattı.

 
Alexey Kozitsyn :

Peki, e-may... Bu analiz aşamasını çoktan geçtik. Kendi günlüğünüzü görün:

müteakip. Önce bağlantıyı kontrol edelim. Bağlantı kurulur kurulmaz, zamanı alırız. Lütfen bana açıklayın, neden önce 4066 hatası döndürülüyor ve sonra döndürülmüyor!? Son aramadan bu yana 20ms içinde ne değişti?

Hata 4066, veri olmadığını, bir güncelleme isteğinin gönderildiğini gösterir.

Bir istek gönderildikten sonra başka bir istek gönderilmez, bu nedenle 4066 hatası oluşmaz. Bu zaten birçok kez tartışıldı.

Göstergedeki zamanlayıcıyı neden başlatıyorsunuz? Yani Küçük. MT4'te göstergelerin ön uç iş parçacığında çalıştığını anlamalısınız. Tüm Windows mesajları arayüz akışından geçer

 
Slava :

Hata 4066, veri olmadığını, bir güncelleme isteğinin gönderildiğini gösterir.

Bir istek gönderildikten sonra başka bir istek gönderilmez, bu nedenle 4066 hatası oluşmaz. Bu zaten birçok kez tartışıldı.

Göstergedeki zamanlayıcıyı neden başlatıyorsunuz? Yani Küçük. MT4'te göstergelerin ön uç iş parçacığında çalıştığını anlamalısınız. Tüm Windows mesajları arayüz akışından geçer

Tartışmaya katıldığınıza sevindim.

Ben forumdaki ilk gün değilim + burada forumda ilk gün olmayan birkaç kişi konuştu. Kimse şunu söylemedi:

Bir istek gönderildikten sonra başka bir istek gönderilmez, bu nedenle 4066 hatası oluşmaz. Bu zaten birçok kez tartışıldı.

Teşekkürler, bileceğiz. Bunu kılavuzda görmek isterim. Hatanın yalnızca OnTick()/OnCalculate() olayı geldiğinde kesin olarak "ayarlandığı" ortaya çıktı?

Göstergedeki zamanlayıcıyı neden başlatıyorsunuz? Yani Küçük.

Birkaç karakterden veri almanız gerekiyor. Mümkün olduğunca hızlı. Ne yazık ki, ne MT4 ne de MT5 herhangi bir sembol için fiyat teklifi varış olaylarının alınmasını uygulamamaktadır (böyle bir güncellemeye abone olmak imkansızdır), bu nedenle (bildiğim kadarıyla) tek çıkış yolu zamanlayıcıda gerekli sembolleri yoklamaktır.

MT4'te göstergelerin ön uç iş parçacığında çalıştığını anlamalısınız. Tüm Windows mesajları arayüz akışından geçer

Tamam, gidelim ve sonra ne olacak? Bunun neden kötü / iyi / zamanlayıcı ile çalışmayı nasıl etkilediğini daha ayrıntılı olarak açıklayabilir misiniz?
 

Birçok kez tartışıldı. "4066 hatası" sorgusu başına 12 sayfa

Ve OnInit'te bir istek göndermeniz ve OnCalculate'de analiz etmeniz doğru bir şekilde tavsiye edildi.

Milisaniye zamanlayıcı ne için? Eylemlerinizle istemci terminalinin normal şekilde yükselmesini engelliyorsunuz. Zamanlayıcınıza müdahale eden Windows mesajları değil, zamanlayıcınız herkese müdahale ediyor. Bir kez daha: MT4 İSTEMCİ TERMİNALİNDEKİ GÖSTERGELER ARAYÜZ AKIŞINDA ÇALIŞIYOR.

 
Slava :

Birçok kez tartışıldı. "4066 hatası" sorgusu başına 12 sayfa

Anladım, teşekkürler. Ancak OnCalculate() veya OnTick() ile çalışmakta hiçbir sorun yoktur, sorun OnTimer()'dadır. Ve "4066 zamanlayıcı hatası" isteği için yalnızca bu dalın sonuçları düşüyor :(

Ve OnInit'te bir istek göndermeniz ve OnCalculate'de analiz etmeniz doğru bir şekilde tavsiye edildi.

Tavsiyeyi dinledim, ancak bu, belgelerde yazılmayan zamanlayıcı ile çalışma özelliklerini ortadan kaldırmıyor.

Milisaniye zamanlayıcı ne için? Eylemlerinizle istemci terminalinin normal şekilde yükselmesini engelliyorsunuz. Zamanlayıcınıza müdahale eden Windows mesajları değil, zamanlayıcınız herkese müdahale ediyor. Bir kez daha: MT4 İSTEMCİ TERMİNALİNDEKİ GÖSTERGELER ARAYÜZ AKIŞINDA ÇALIŞIYOR.

Bir kez daha, birkaç karakterden olabildiğince çabuk bilgi almak için bir milisaniye zamanlayıcı! Onlar. algoritma şu şekildedir: gösterge yüklenir, daha yüksek zaman dilimlerinin verilerini mümkün olan en kısa sürede alır, ardından gerekli sembollerin tekliflerini bir milisaniyelik zamanlayıcıda izler. Bir zamanlayıcı yerine izleme sorununu bir şekilde çözmek mümkün müdür?

Burada yazılanları özetleyelim , yanlışım varsa düzeltin:

1. Görev: bir zamanlayıcı aracılığıyla birkaç sembolden alıntı alın:

Uygulama: Yüksek frekanslı bir zamanlayıcı ile çalışırken, terminali yüklerken, OnCalculate() işlevinde IsConnected()'in sunucuyla bağlantı kurmasını beklemeniz gerekir, ancak bundan sonra zamanlayıcıya erişebilirsiniz;

2. Görev: göstergenin başlamasından sonra mümkün olan en kısa sürede daha yüksek zaman dilimlerinin verilerini almak (gösterge hızlı bir zamanlayıcı kullanır);

Uygulama: önce, OnInit()'te gerekli veriler için bir istek yaparız, sonra OnCalculate()'de IsConnected() bağlantısının kurulmasını bekleriz, sonra zaten daha yüksek TF'lerin verilerini OnCalculate()'de de alırız;

3. Yüksek frekanslı bir zamanlayıcı çalıştırmak arayüz akışını yavaşlatır ve sonuç olarak bilgisayar hiç çalıştırılmaya değmez mi? O zaman 1. sorun nasıl çözülür?

4. Görev: kıdemli TF'lerin güncel verilerini yüklemek.

Uygulama: bunun için yüksek frekanslı bir zamanlayıcı kullanmayın, çünkü veri alma işlevleri böyle bir zamanlayıcıda çalışmak üzere tasarlanmadı mı? Yalnızca OnCalculate()'i mi kullanıyoruz?

5. Bir 4066 hatası alınır ve ardından temizlenirse, OnCalculate() içindeki her bir onay işaretinde ayarlanıyor mu?

6. MT5'teki OnTimer() bir arabirim iş parçacığında çalışmıyor mu?

@Slava lütfen nokta nokta da cevaplayın;

 

1. Kural olarak, OnCalculate'e yapılan ikinci çağrıda IsConnected durumuna sahip olursunuz. Terminalin başlamasından hemen sonraki ilk arama, geçmiş verilerin bir kısmının gelmesi üzerine ikinci arama

2. Hızlı zamanlayıcıyı kullanmayın. İlk olarak, sizin için hangi zamanlamanın kabul edilebilir olduğunu değerlendirin. 100 milisaniye veya 500 olabilir. İlk başta ikinci bir zamanlayıcı tanıtmamız tesadüf değildi, SetMillisecondsTimer ancak 3 veya 4 yıl sonra ilk beşe (!) girdi. Ancak ilk beşin farklı bir mimarisi var.

3.1. Kendinize mesaj kuyruklarının anında çözümlenmesini sağlayabilecek güçlü bir bilgisayar edinin.

3.2. Milisaniye zamanlayıcısını hemen değil, yalnızca ilk OnCalculate'den sonra başlatın. Bunun yerine, şu şekilde: İlk OnCalculate'de, ortamı analiz edebilmeniz için ikinci bir zamanlayıcı başlatın (ve aniden bağlantı veya bir gün izin yok). Ve ancak o zaman, tüm verilerin yüklendiğine, bir bağlantı olduğuna ve her şeyin yolunda olduğuna ikna olduğunuzda, ikinci zamanlayıcıyı öldürün ve milisaniye zamanlayıcıyı başlatın. Sonra sakince dar ön kapıdan süzülürsünüz. En iyi durumda (ve yüzde 99'u olacak), başlangıçta 2 ila 5 saniye kaybedersiniz

4. Bir zamanlayıcınız olabilir. Ancak hemen değil (bkz. 3.2). Ve bence gözler için 50 milisaniye yeterli. HFT sağlamıyorsunuz, değil mi?

5. 4066, yalnızca bir başkasının sembol periyoduna ilişkin ilk veri talebinde görünür. Aynı dönem sembolü 4066'nın bir sonraki isteğinde, artık almayacaksınız

6. MT5'te göstergeler ayrı bir sembol işleme iş parçacığında sayılır. Bu nedenle, bu sembol üzerinde birden fazla grafiğiniz varsa (veya bu sembol üzerinde başka göstergeler varsa), onları yavaşlatabilirsiniz. Ama yine de, bu bir arayüz akışı değil.

 
Slava :

1. Kural olarak, OnCalculate'e yapılan ikinci çağrıda IsConnected durumuna sahip olursunuz. Terminalin başlamasından hemen sonraki ilk arama, geçmiş verilerin bir kısmının gelmesi üzerine ikinci arama

2. Hızlı zamanlayıcıyı kullanmayın. İlk olarak, sizin için hangi zamanlamanın kabul edilebilir olduğunu değerlendirin. 100 milisaniye veya 500 olabilir. İlk başta ikinci bir zamanlayıcı tanıtmamız tesadüf değildi, SetMillisecondsTimer ancak 3 veya 4 yıl sonra ilk beşe (!) girdi. Ancak ilk beşin farklı bir mimarisi var.

3.1. Kendinize mesaj kuyruklarının anında çözümlenmesini sağlayabilecek güçlü bir bilgisayar edinin.

3.2. Milisaniye zamanlayıcısını hemen değil, yalnızca ilk OnCalculate'den sonra başlatın. Bunun yerine, şu şekilde: İlk OnCalculate'de, ortamı analiz edebilmeniz için ikinci bir zamanlayıcı başlatın (ve aniden bağlantı veya bir gün izin yok). Ve ancak o zaman, tüm verilerin yüklendiğine, bir bağlantı olduğuna ve her şeyin yolunda olduğuna ikna olduğunuzda, ikinci zamanlayıcıyı öldürün ve milisaniye zamanlayıcıyı başlatın. Sonra sakince dar ön kapıdan süzülürsünüz. En iyi durumda (ve yüzde 99'u olacak), başlangıçta 2 ila 5 saniye kaybedersiniz

4. Bir zamanlayıcınız olabilir. Ancak hemen değil (bkz. 3.2). Ve bence gözler için 50 milisaniye yeterli. HFT sağlamıyorsunuz, değil mi?

5. 4066, yalnızca bir başkasının sembol periyoduna ilişkin ilk veri talebinde görünür. Aynı dönem sembolü 4066'nın bir sonraki isteğinde, artık almayacaksınız

6. MT5'te göstergeler ayrı bir sembol işleme iş parçacığında sayılır. Bu nedenle, bu sembol üzerinde birden fazla grafiğiniz varsa (veya bu sembol üzerinde başka göstergeler varsa), onları yavaşlatabilirsiniz. Ama yine de, bu bir arayüz akışı değil.

1. Tam olarak olan budur;

2. Sorun burada. Ne kadar hızlı o kadar iyi. Ve değerlendirme yapıldı. Gösterge, arbitraj için yazılmıştır (daha doğrusu, arbitraj konusu üzerine araştırma), yani. her milisaniye önemlidir ve teklif ne kadar hızlı alınırsa o kadar iyidir;

3.1. Ve şimdi sistem oldukça güçlü: 8600k işlemci, SSD'deki terminaller, 16GB DDR4 RAM;

3.2. Vay... iyi, not edildi;

4. Büyük olasılıkla tahkim görevi HFT'ye atıfta bulunur;

5. Başlangıçta, bu sadece can sıkıcıydı. Hata almaya devam etseydim ve verilerin henüz hazır olmadığını bilseydim, bu dal olmazdı;

6. Anlaşıldı.

Detaylı cevap için teşekkürler.

 
Igor Makanu :

zorlaştırmıyorsa, işte konunun konusu - eski TF'den tarihin doğru yüklenmesi, işte gösterge: genç TF'nin çubuklarında eski TF'den "Masha çizmeniz gerekiyor", yaptı 5 dakika içinde, %98 tam olarak doğru çalışacak, bu kodda %2 "tuzaklar" hangi hatalara neden olacak?

Evet, sadece konu başlığında. Ve burada, sonuçta, her şey zaten demonte.

İlk olarak, diğer TF'lerin/sembollerin zaman serilerine herhangi bir erişimden önce, verilerin mevcut olup olmadığını kontrol ettiğinizden emin olun (yukarıdaki IsTFDataReady() işlevine bakın). Yukarıdaki kodda, yalnızca CopyClose'dan elde edilen sonuca göre yönlendirilirsiniz. Ama geçmiş yükleme hakkında hiçbir şey bilmiyor. Bu nedenle ilk başta - verilerin kullanılabilirliğine ikna olmak ve ancak o zaman onları talep etmek.

İkincisi, bir işlevi başka bir işleve argüman olarak çağırmak her zaman haklı değildir. Ve bu durumda, temelde kabul edilemez. Sonuçta, iBar'ları aramanın sonucunun da kontrol edilmesi gerekiyor. Böylece önce iBars çağrılır, sonuç önbelleğe alınır ve kontrol edilir ve ardından CopyClose()'a yalnızca alınan değer iletilir.

Üçüncüsü, CopyClose'u çağırdıktan sonra, istenen tüm verilerin alındığına dair bir kontrol yoktur. Sonuçta, işlev 1 veya 2 çubuk döndürebilir, ancak talep edildi, örneğin 10. Böyle bir sonucu bir hataya bağlardım.

Dördüncüsü, yaklaşımın fikrinde bir hata var. Döngü, başka bir zaman çerçevesinin çubuklarıyla çalıştığını varsayar, ancak aynı zamanda, hesaplamalar, değeri geçerli zaman çerçevesine atıfta bulunan Rate_total değişkeni ile karıştırılır. Şu veya bu durumda kullandığım iki olası yaklaşım var:

  1. Mevcut zaman çerçevesinin çubukları arasında dolaşın ve veri istemeden önce, mevcut zaman çerçevesinin çubuk indeksini başka bir zaman çerçevesinin çubuk indeksine dönüştürün (bu yaklaşım aşağıdaki kodda kullanılır).
  2. Başka bir TF'nin çubukları arasında dolaşın. Ancak, mevcut TF'nin diğerine göre küçük olduğu durum için ek bir döngü eklemeniz gerekir. Sonuçta, mevcut zaman çerçevesinin birkaç çubuğu, eski zaman çerçevesinin bir çubuğuna karşılık gelecektir.

MT4 için doğru kodla ilgileniyor

Listelenen dört nokta ışığında şöyle bir şey (kontrol etmedim, dizimin üzerinde yaptım ama anlamı açık olmalı):

   if (!IsTFDataReady(TimeFrame))
       return 0 ;

   int i,limit;

   static int nOldBars = 0 ;
   int nBars = iBars ( _Symbol , TimeFrame);
   if (nBars == 0 )
       return 0 ;
      
   if (nOldBars == 0 || nBars - nOldBars > 1 )
   {
       if (nBars < MAPeriod)
      {
         Comment ( "Большой период МА!!!, в истории доступно " , nBars, " баров" );
         return 0 ;
      }
      
      limit = nBars - fmin (MAPeriod, nBars);
   }
   else
      limit = nBars - nOldBars;   // здесь всегда будет 0 или 1
   
   nOldBars = nBars;
   datetime dtTime = iTime ( NULL , TimeFrame, limit);
   if (dtTime == 0 )
       return 0 ;

   limit = iBarShift ( NULL , PERIOD_CURRENT , dtTime);

// основной цикл расчета индикатора
   for (i = limit; i >= 0 && ! IsStopped (); i--)
   {
       int nOtherTFBarIndex = iBarShift ( NULL , TimeFrame, time[i]);
       if (nOtherTFBarIndex < 0 || nOtherTFBarIndex >= nBars)
         continue ;
      
      BufMA[i] = iMA ( _Symbol ,TimeFrame,MAPeriod, 0 , MODE_SMA , PRICE_CLOSE ,nOtherTFBarIndex);
   }
//---
   return rates_total;

Bu arada, kontrol ettim:


 
Ihor Herasko :

Evet, sadece konu başlığında. Ve burada, sonuçta, her şey zaten demonte.

İlk olarak, diğer TF'lerin/sembollerin zaman serilerine herhangi bir erişimden önce, verilerin mevcut olup olmadığını kontrol ettiğinizden emin olun (yukarıdaki IsTFDataReady() işlevine bakın). Yukarıdaki kodda, yalnızca CopyClose'dan elde edilen sonuca göre yönlendirilirsiniz. Ama geçmiş yükleme hakkında hiçbir şey bilmiyor. Bu nedenle ilk başta - verilerin kullanılabilirliğine ikna olmak ve ancak o zaman onları talep etmek.

İkincisi, bir işlevi başka bir işleve argüman olarak çağırmak her zaman haklı değildir. Ve bu durumda, temelde kabul edilemez. Sonuçta, iBar'ları aramanın sonucunun da kontrol edilmesi gerekiyor. Böylece önce iBars çağrılır, sonuç önbelleğe alınır ve kontrol edilir ve ardından CopyClose()'a yalnızca alınan değer iletilir.

Üçüncüsü, CopyClose'u çağırdıktan sonra, istenen tüm verilerin alındığına dair bir kontrol yoktur. Sonuçta, işlev 1 veya 2 çubuk döndürebilir, ancak talep edildi, örneğin 10. Böyle bir sonucu bir hataya bağlardım.

Dördüncüsü, yaklaşımın fikrinde bir hata var. Döngü, başka bir zaman çerçevesinin çubuklarıyla çalıştığını varsayar, ancak aynı zamanda, hesaplamalar, değeri geçerli zaman çerçevesine atıfta bulunan Rate_total değişkeni ile karıştırılır. Şu veya bu durumda kullandığım iki olası yaklaşım var:

  1. Mevcut zaman çerçevesinin çubukları arasında dolaşın ve veri istemeden önce, mevcut zaman çerçevesinin çubuk indeksini başka bir zaman çerçevesinin çubuk indeksine dönüştürün (bu yaklaşım aşağıdaki kodda kullanılır).
  2. Başka bir TF'nin çubukları arasında dolaşın. Ancak, mevcut TF'nin diğerine göre küçük olduğu durum için ek bir döngü eklemeniz gerekir. Sonuçta, mevcut zaman çerçevesinin birkaç çubuğu, eski zaman çerçevesinin bir çubuğuna karşılık gelecektir.

Listelenen dört nokta ışığında şöyle bir şey (kontrol etmedim, dizimin üzerinde yaptım ama anlamı açık olmalı):

Bu arada, kontrol ettim:


1. evlat edinildi! teşekkür etmek!

2. altın sözler! Eskiden böyle yazardım ama zamanla başkalarının kompaktlık peşinde koşan kodlarını okuyarak... "Kısalık yeteneğin kardeşidir" konusuna daha çok önem veririm .... ve ortaya çıkan hataları aramak için zaman harcarım.

4. "kısalık yeteneğin kardeşidir"... Haklısınız!

3. İlginç bir analiz anı, CopyClose()'un döndürdüğü şeydir, kendim kontrol ettim, eğer istenen TF için .hst dosyası yoksa, CopyClose() asla 2048'den fazla döndürmez - yani. bu indirilebilecek maksimum değer mi?