MT5 Awesome Oscillator: Built-in ile Example iCustom Color Buffer Uyumsuzluğu (Tie Case)

MetaTrader 5’in sevimsiz bir huyu var: “aynı indikatör” sandığın iki şey neredeyse tamamen aynı davranır… ta ki nadir bir edge-case çıkıp bütün parite hattını kilitleyene kadar.

Bu yazı, JP225Cash üzerinde kurduğum deterministik benchmark/parite hattında (MQL5 exporter → CPU/GPU parity) yaşadığım çok spesifik bir problemi anlatıyor: Awesome Oscillator (AO) için ana değer buffer’ı (b0) built-in ve iCustom arasında %100 eşleşirken, color buffer (b1) tarafında çok nadiren mismatch oluşuyordu.

Kısaca: Bu bir sayısal drift problemi değildi. Bu bir tie-break (eşitlik) problemiydi.

1) Belirti: b0 aynı, b1 bazen farklı

JP225Cash veri setinde (çok yıllık export aralığı) AO şu şekilde davranıyordu:

  • b0 (AO değeri): built-in ile iCustom arasında %100 aynı
  • b1 (color index): yıllarca veride sadece 2 noktada farklı

Bu “en kötü tür” bug: o kadar nadir ki insanı paranoyaya sürüklüyor, ama o kadar deterministik ki strict pariteyi (eşit mi değil mi) direkt blokluyor. Mismatch olan bar’larda b0 birebir aynıyken renk farklıydı:

  • Built-in b1 = 0
  • iCustom b1 = 1

2) Neden 5 yılda sadece 2 ordinal?

Çünkü mismatch sadece şu durumda ortaya çıkıyordu:

AO[i] == AO[i-1]

AO, hareketli ortalama farkı gibi sürekli değişen bir seri olduğu için genelde her bar’da değişir. Ama bazı çok nadir kombinasyonlarda (median price + MA pencerelerinin hizalanması + fiyat hareketi), ardışık iki bar’da AO değeri tam olarak eşit çıkabiliyor. Bu durum JP225Cash üzerinde multi-year export’ta sadece iki kere gerçekleştiği için mismatch de sadece iki kere göründü.

3) Kök neden: “eşitlik” durumunun farklı yorumlanması

MT5’in örnek indikatörü olan MQL5/Indicators/Examples/Awesome_Oscillator.mq5 color buffer’ı kabaca şu mantıkla üretiyordu:

  • AO[i] > AO[i-1] ise → Green (0)
  • değilse → Red (1)

Bu şu anlama geliyor: AO[i] == AO[i-1] olduğunda örnek implementasyon otomatik olarak Red yazıyor.

Ancak built-in AO tarafında pratikte gördüğüm davranış farklıydı: Eşitlik durumunda built-in AO rengi zorla kırmızıya çekmiyor. Bunun yerine, rengi önceki bar’dan taşıyor (carry-forward / last state).

Yani problem AO’nun değeri değil; “değer değişmiyorsa renk ne olmalı?” sorusunun cevabı:

  • Example iCustom: “eşitse yükselmiyor say → red”
  • Built-in: “eşitse yön değişmedi → önceki rengi koru”

4) Çözüm: Tie case için carry-forward

İlk refleks olarak >= (eşitliği green say) yaklaşımı denedim. Bu güvenilir şekilde built-in davranışıyla örtüşmedi. Doğru çözüm, üç durumu açıkça ayırmaktı:

  • > → green
  • < → red
  • == → önceki rengi taşı (carry-forward)

Uygulanan minimal değişiklik:

diff --git a/MQL5/Indicators/Examples/Awesome_Oscillator.mq5 b/MQL5/Indicators/Examples/Awesome_Oscillator.mq5
index 676b17d..3bf135c 100644
--- a/MQL5/Indicators/Examples/Awesome_Oscillator.mq5
+++ b/MQL5/Indicators/Examples/Awesome_Oscillator.mq5
@@ -115,10 +115,12 @@ int OnCalculate(const int rates_total,
    for(i=start; i<rates_total && !IsStopped(); i++)
      {
       ExtAOBuffer[i]=ExtFastBuffer[i]-ExtSlowBuffer[i];
-      if(ExtAOBuffer[i]>=ExtAOBuffer[i-1])
+      if(ExtAOBuffer[i]>ExtAOBuffer[i-1])
          ExtColorBuffer[i]=0.0; // set color Green
-      else
+      else if(ExtAOBuffer[i]<ExtAOBuffer[i-1])
          ExtColorBuffer[i]=1.0; // set color Red
+      else
+         ExtColorBuffer[i]=ExtColorBuffer[i-1];
      }
 //--- return value of prev_calculated for next call
    return(rates_total);

Bu değişiklikten sonra JP225Cash export aralığında built-in ve iCustom AO çıktıları, color buffer dahil, bütün veri boyunca uyumlu hale geldi.

5) Neden önemli? “Görsel buffer” da bir çıktıdır

Birçok kişi b1 gibi color buffer’ları “UI detayı” olarak görüp önemsemez. Ancak deterministik benchmark/parite sistemlerinde b1 de bir buffer ise:

  • export ediliyorsa
  • karşılaştırılıyorsa
  • rapora giriyorsa

…o zaman semantiği net olmalıdır. Yoksa en küçük edge-case’te strict parity patlar.

6) Source of truth yaklaşımı: built-in değişmez, referansı hizalarsın

Benim sistemimde MQL5 exporter çıktısı “external source of truth” gibi davranıyor ve CPU (NumPy) ile GPU (CuPy/Numba) hesapları bu çıktıya göre doğrulanıyor. Bu durumda kaçınılmaz soru şu:

Built-in ve iCustom farklıysa hangisi “doğru”?

Pratik cevap:

  • Built-in davranışı değiştiremezsin.
  • Repo kontrolündeki iCustom referansı değiştirebilirsin.

Bu yüzden en temiz yaklaşım, bariz şekilde “semantik tie-break farkı” olan noktada iCustom implementasyonunu built-in’e yaklaştırıp tek bir anlam (tek truth) üretmektir. Bu, testi gevşetmek değil; tanımı hizalamaktır.

7) Sonuç

Bu problem float rounding drift değildi. Tolerans işi değildi. ULP policy tartışması da değildi. Tek mesele, bir satırda gizli duran şu soruydu:

“AO değeri değişmiyorsa renk ne olmalı?”

Tie case için carry-forward tanımlanınca built-in ve iCustom çıktıları birleşti ve JP225Cash parite hattı stabil hale geldi.

Evren hâlâ tuhaf, ama en azından AO color buffer artık insanı gaslight etmiyor.


 Paylaş

 Yorumlar (0)

Bu gönderi için henüz yorum yapılmadı. İlk yorumu yapan sen ol.


 Yorum Yap

Bu gönderi hakkında sorularınızı, görüşlerinizi veya eleştirilerinizi benimle paylaşabilirsiniz. Email adresiniz kimseyle paylaşılmayacaktır.