English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Bulanık Mantık Kullanarak Gösterge Oluşturmanın Basit Örneği

Bulanık Mantık Kullanarak Gösterge Oluşturmanın Basit Örneği

MetaTrader 5Ticaret | 15 Aralık 2021, 11:06
110 0
Максим Востров
Максим Востров

Giriş

Finansal piyasaların analizi için çeşitli yöntemlerin kullanılması, son yıllarda yatırımcılar arasında giderek daha popüler hale geliyor. Ben de katkıda bulunmak ve birkaç düzine kod satırı yazarak iyi bir göstergenin nasıl yapılacağını göstermek istiyorum. Ayrıca, size bulanık mantığın temellerini kısaca açıklayacağım.

Bu konuya ilgi duyan ve daha derinlemesine araştırmak isteyen herkes aşağıdaki eserleri okuyabilir:

1.  Leonenkov А. "Fuzzy Simulation in MATLAB and fuzzyTECH" (Rusça).
2.  Bocharnikov V."Fuzzy Technology: Mathematical Background. Simulation Practice in Economics" (Rusça).
3.  S.N. Sivanandam, S. Sumathi, S.N. Deepa. Introduction to Fuzzy Logic using MATLAB.
4.  C. Kahraman. Fuzzy Engineering Economics with Applications (Studies in Fuzziness and Soft Computing).


1. Fuzzy Logic Basics

"...biraz daha...", "...çok hızlı...", "...neredeyse hiçbir şey..." gibi basit ifadelerin anlamlarını bilgisayarlarımıza nasıl açıklayabiliriz? Aslında, bu, bulanık küme teorisi öğelerini veya daha doğrusu "üyelik işlevleri" olarak adlandırılanları kullanarak oldukça mümkündür. А. Leonenkov'un kitabından bir örnek verelim:

"Sıcak kahve" ifadesinin üyelik işlevini tanımlayalım: Kahve sıcaklığı 0 ila 100 santigrat derece aralığında kabul edilmelidir; zira 0 derecenin altındaki sıcaklıklarda buza dönüşürken, 100 derecenin üzerindeki sıcaklıklarda buharlaşacaktır. 20 derecelik bir sıcaklığa sahip bir fincan kahvenin sıcak olarak adlandırılamayacağı oldukça açıktır; yani "sıcak" kategorisindeki üyelik işlevi 0'a eşit iken, 70 derecelik bir sıcaklığa sahip bir fincan kahve ise kesinlikle "sıcak" kategorisine aittir ve bu nedenle, bu durumda işlev değeri 1'e eşittir.

Bu iki sınır değer arasındakisıcaklık değerlerine gelince; durum o kadar da kesin değil. Bazıları 55 derece sıcaklıktaki bir fincan kahveyi "sıcak" olarak değerlendirirken, diğerleri "çok sıcak olmadığını" söyleyebilir. "Bulanıklık" budur.

Yine de üyelik işlevinin yaklaşık görünümünü hayal edebiliriz: "Tekdüze artan":


Yukarıdaki şekil "parçalı doğrusal" üyelik işlevini göstermektedir.

Dolayısıyla, işlev aşağıdaki analitik ifade ile tanımlanabilir:


Göstergemiz için bu tür işlevleri kullanacağız.


2. Üyelik İşlevi

Şu veya bu şekilde, herhangi bir teknik göstergenin görevi, mevcut piyasa durumunun (düz, yükseliş trendi, düşüş trendi) belirlenmesi ve ayrıca piyasaya giriş/çıkış sinyallerinin oluşturulmasıdır. Bu, üyelik işlevlerinin yardımıyla nasıl yapılabilir? Yeterince kolay.

Her şeyden önce, sınır koşullarını tanımlamamız gerekir. Şu sınır koşullarını alalım: «%100 yükseliş trendi» için, tipik fiyata (H+L+C)/3 göre 2. döneme sahip EMA'nın 8, 0,08, SMA, Açılış, parametrelerine sahip Zarflar üst sınırı ile geçişi olacakken, «%100 düşüş trendi» için Zarflar alt sınırı ile aynı EMA'nın geçişi olacaktır. Bu koşullar arasında yer alan her şey düz kabul edilecektir. 32, 0,15, SMA, Close parametrelerine sahip bir zarf daha ekleyelim. 

Sonuç olarak, iki özdeş üyelik işlevi elde edeceğiz. Sırasıyla her iki işlev de 1'e eşit olduğunda al sinyali etkinleşecek, her iki işlev de -1'e eşit olduğunda sat sinyali etkinleşecektir. -1 ile 1 aralığında grafikler oluşturmak uygun olduğu için ortaya çıkan grafik iki işlevin aritmetik ortalaması F(x)= (f1(x)+f2(x))/2 olarak elde edilecektir.

Bu, grafikte şu şekilde görünür:


Bu durumda üyelik işlevi aşağıdaki grafiksel gösterime sahip olacaktır:


Analitik olarak şu şekilde yazılabilir:

,

Burada a ve b sırasıyla üst ve alt zarf çizgileridir, х ise EMA(2)'nin bir değeridir.

Tanımlanan işlev ile artık gösterge kodunu yazmaya geçebiliriz.


3. Program Kodunu Oluşturma

Öncelikli olarak, neyi ve nasıl çizeceğimizi belirlemeliyiz.

Üyelik işlevi hesaplama sonuçları, sırasıyla kırmızı ve mavi çizgi olarak görüntülenecektir.

Aritmetik ortalama, sıfır çizgisinden bir histogram olarak görüntülenecek ve ortaya çıkan işlev değerine bağlı olarak beş renkten birinde boyanacaktır:

Bunun için DRAW_COLOR_HISTOGRAM çizim stili kullanılacaktır.

Değerleri 1 veya -1'e eşit olan histogram çubuklarının üzerine al/çık sinyalleri olarak mavi ve kırmızı dikdörtgenler çizelim.

Şimdi MetaEditor'u çalıştırma ve başlama zamanı. Yeni->Özel Gösterge->Sonraki... "Parametreler" alanını doldurun:


 Arabellekleri oluşturun:


"Bitir" düğmesine tıkladıktan sonra bir kaynak kodu alıyoruz ve bunu geliştirmeye başlıyoruz.

İlk olarak, arabellek sayısını tanımlayalım. Bunlardan yedi tanesi Sihirbaz tarafından zaten oluşturulmuştur (5'i veri için, 2'si renk için). Bu 5 tane daha gerekli.

#property indicator_minimum -1.4 // Setting fractional values
#property indicator_maximum 1.4  // Expert Advisors wizard ignores fractional parts for some reason
#property indicator_buffers 12   // Changing the value from 7 to 12 (5 more buffers have been added)
Giriş parametrelerini düzenleyelim:
input string txt1="----------";
input int                  Period_Fast=8;
input ENUM_MA_METHOD        Method_Fast = MODE_SMA; /*Smoothing method*/ //moving average smoothing method 
input ENUM_APPLIED_PRICE    Price_Fast  = PRICE_CLOSE;
input double               Dev_Fast=0.08;
input string txt2="----------";
input int                  Period_Slow=32;
input ENUM_MA_METHOD        Method_Slow = MODE_SMA;
input ENUM_APPLIED_PRICE    Price_Slow  = PRICE_CLOSE;
input double               Dev_Slow=0.15;  /*Deviation parameter*/
input string txt3="----------";
input int                  Period_Signal=2;
input ENUM_MA_METHOD        Method_Signal = MODE_EMA;
input ENUM_APPLIED_PRICE    Price_Signal  = PRICE_TYPICAL;
input string txt4="----------";

Bildirilen değişkeni takip eden açıklamalar çok kullanışlıdır. Açıklamaların metni, gösterge parametreleri penceresine eklenir.

Liste oluşturma olanağı da çok kullanışlıdır:


Gösterge tanıtıcıları ve arabellekler için değişkenleri ayırma:

int Envelopes_Fast;     // Fast envelope
int Envelopes_Slow;     // Slow envelope
int MA_Signal;          // Signal line

double Env_Fast_Up[];   // Fast envelope upper border
double Env_Fast_Dn[];   // Fast envelope lower border

double Env_Slow_Up[];   // Slow envelope upper border
double Env_Slow_Dn[];   // Slow envelope lower border

double Mov_Sign[];      // Signal line

Şimdi, OnInit() işlevine gidin.

İşe biraz güzellik katalım: Gösterge adını belirtin ve fazladan ondalık sıfırları kaldırın:

IndicatorSetInteger(INDICATOR_DIGITS,1); // setting display accuracy, we do not need some outstanding accuracy values 
string name;                           // indicator name 
StringConcatenate(name, "FLE ( ", Period_Fast, " , ", Dev_Fast, " | ", Period_Slow, " , ", Dev_Slow, " | ", Period_Signal, " )"); 
IndicatorSetString(INDICATOR_SHORTNAME,name);

ve eksik arabellekleri ekleyin:

SetIndexBuffer(7,Env_Fast_Up,INDICATOR_CALCULATIONS);
SetIndexBuffer(8,Env_Fast_Dn,INDICATOR_CALCULATIONS);
SetIndexBuffer(9,Env_Slow_Up,INDICATOR_CALCULATIONS);
SetIndexBuffer(10,Env_Slow_Dn,INDICATOR_CALCULATIONS);
SetIndexBuffer(11,Mov_Sign,INDICATOR_CALCULATIONS); 

INDICATOR_HESAPLAMALAR parametresi, arabellek verilerinin yalnızca ara hesaplamalar için gerekli olduğu anlamına gelir. Bu, grafikte gösterilmeyecektir.

Renk arabelleklerini içeren göstergelerin nasıl bildirildiğine dikkat edin:

SetIndexBuffer(4,SignalBuffer1,INDICATOR_DATA);      // All indicator buffers at first 
SetIndexBuffer(5,SignalBuffer2,INDICATOR_DATA);      // as this is Color Histogram2, then it has 2 data buffers
SetIndexBuffer(6,SignalColors,INDICATOR_COLOR_INDEX);// the color buffer comes next.

Tanıtıcıları doldurma:

Envelopes_Fast = iEnvelopes(NULL,0,Period_Fast,0,Method_Fast,Price_Fast,Dev_Fast);
Envelopes_Slow = iEnvelopes(NULL,0,Period_Slow,0,Method_Slow,Price_Slow,Dev_Slow);
MA_Signal      = iMA(NULL,0,Period_Signal,0,Method_Signal,Price_Signal);

OnInit() işlevi ile yapılan tüm işler tamamlandı.

Şimdi üyelik işlevi değerini hesaplayacak işlevi oluşturalım:

double Fuzzy(double x,double a, double c)
{
double F;
     if (a<x)          F=1;                 // 100% uptrend
else if (x<=a && x>=c)  F=(1-2*(a-x)/(a-c));// Flat
else if (x<c)           F=-1;               // 100% downtrend
return (F);
}

Hazırlıklar tamamlandı. Değişkenler ve arabellekler bildirildi, tanıtıcılar atandı.

Şimdi OnCalculate() temel işlevine geçme zamanı.

İlk önce, gerekli göstergelerin değerlerini ara belleklere yazalım. CopyBuffer() işlevini kullanın:

CopyBuffer(Envelopes_Fast,  // Indicator handle
           UPPER_LINE,      // Indicator buffer
           0,              // The point to start 0 - from the very beginning
           rates_total,    // How many to be copied - All 
           Env_Fast_Up);   // The buffer the values are written in
// - the rest are done in a similar way
CopyBuffer(Envelopes_Fast,LOWER_LINE,0,rates_total,Env_Fast_Dn);
CopyBuffer(Envelopes_Slow,UPPER_LINE,0,rates_total,Env_Slow_Up);
CopyBuffer(Envelopes_Slow,LOWER_LINE,0,rates_total,Env_Slow_Dn);
CopyBuffer(MA_Signal,0,0,rates_total,Mov_Sign);

 Buraya hesaplama optimizasyonu için kodu eklemeliyiz (yalnızca son çubuğu yeniden hesaplama işlemi gerçekleştirilir):

// declaring start variable for storing the index of the bar, recalculation of the indicator buffers will be
// carried out from.

int start;              
if (prev_calculated==0// in case no bars have been calculated
    {
    start = Period_Slow; // not all indicators have been calculated up to this value, therefore, there is no point in executing the code
    }
else start=prev_calculated-1;

for (int i=start;i<rates_total;i++)
      {
      // All remaining code will be written here
      }

Çok fazla kod kalmadı.

X, a, b parametrelerini ayarlama, üyelik işlevi değerini hesaplama işlemini gerçekleştirme ve uygun arabelleğe yazma:
double x = Mov_Sign[i]; // Signal
// Setting the first membership function parameters:
double a1 = Env_Fast_Up[i]; // Upper border
double b1 = Env_Fast_Dn[i];
// setting the first membership function value and writing it to the buffer
Rule1Buffer[i] = Fuzzy(x,a1,b1);
// Setting the second membership function parameters:
double a2 = Env_Slow_Up[i]; // Upper border
double b2 = Env_Slow_Dn[i];
// setting the second membership function value and writing it to the buffer
Rule2Buffer[i] = Fuzzy(x,a2,b2);

İki gösterge çizgisi oluşturuldu.

Şimdi ortaya çıkan değeri hesaplayalım.

ResultBuffer[i] = (Rule1Buffer[i]+Rule2Buffer[i])/2;

Daha sonra histogram çubuklarını uygun renklerle boyamalıyız: Elimizde beş renk olduğu için ResultColors[i] 0 ila 4 arasında herhangi bir değer alabilir.

Genel olarak, olası renk sayısı 64'tür. Dolayısıyla, bu, kişinin yaratıcı yeteneklerini uygulaması için mükemmel bir fırsat.

for (int ColorIndex=0;ColorIndex<=4;ColorIndex++) 
    { 
    if (MathAbs(ResultBuffer[i])>0.2*ColorIndex && MathAbs(ResultBuffer[i])<=0.2*(ColorIndex+1)) 
        { 
        ResultColors[i] = ColorIndex; 
        break; 
        } 
    }

O zaman, sinyal dikdörtgenlerini çizmeliyiz. DRAW_COLOR_HISTOGRAM2 çizim stilini kullanacağız.

Bu, bir histogram çubuğu içeren iki veri arabelleğine ve aralarında oluşturulmuş bir renk arabelleğine sahiptir.

Veri arabelleği değerleri her zaman aynı olacaktır: Sırasıyla al sinyali için 1,1 ve 1,3, sat sinyali için -1,1 ve -1,3.

EMPTY_VALUE, sinyalin olmadığı anlamına gelecektir.

      if (ResultBuffer[i]==1)
        {
        SignalBuffer1[i]=1.1;
        SignalBuffer2[i]=1.3;
        SignalColors[i]=1;
        }
      else if (ResultBuffer[i]==-1)
        {
        SignalBuffer1[i]=-1.1;
        SignalBuffer2[i]=-1.3;
        SignalColors[i]=0;
        }
      else
        {
        SignalBuffer1[i]=EMPTY_VALUE;
        SignalBuffer2[i]=EMPTY_VALUE;
        SignalColors[i]=EMPTY_VALUE;
        }

"Derle" seçeneğine tıklayın ve işte!



Sonuç

Başka ne eklenebilir? Bu makalede bulanık mantığa en temel yaklaşıma değindim.

Burada çeşitli denemeler için yeterince alan var. Örneğin, aşağıdaki işlevi kullanabiliriz:


Bunun için analitik ifadeyi yazmanızın ve uygun koşulları bulmanızın zor olmayacağını düşünüyorum.

İyi şanslar!

MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/178

Ekli dosyalar |
Standart Kitaplık Sınıflarını kullanarak kendi Piyasa İzlemenizi oluşturun Standart Kitaplık Sınıflarını kullanarak kendi Piyasa İzlemenizi oluşturun
Yeni MetaTrader 5 istemci terminali ve MQL5 Dili, yatırımcıya görsel bilgi sunmak için yeni fırsatlar sunar. Bu makalede, grafik üzerinde rastgele seçilmiş metin bilgilerinin görüntülenmesini düzenlemeye ilişkin tüm işleri yürüten evrensel ve genişletilebilir bir sınıflar kümesi öneriyoruz. Piyasa İzleme göstergesi örneği sunulmuştur.
MQL5 Sihirbazı: Programlamadan Expert Advisor'lar Oluşturma MQL5 Sihirbazı: Programlamadan Expert Advisor'lar Oluşturma
Programlama için zaman kaybetmeden bir alım satım stratejisi denemek ister misiniz? MQL5 Sihirbazı'nda alım satım sinyallerinin türünü seçebilir, takip eden pozisyonlar ve para yönetimi modülleri ekleyebilirsiniz; böylelikle işiniz biter! Kendi modül uygulamalarınızı oluşturun veya İşler hizmeti aracılığıyla talimat verin ve yeni modüllerinizi mevcut olanlarla birleştirin.
Ek Arabellekler Kullanmadan Ara Hesaplamalar için Fiyat Serilerinin Ortalamasını Alma Ek Arabellekler Kullanmadan Ara Hesaplamalar için Fiyat Serilerinin Ortalamasını Alma
Bu makale, en basit ve tek tür sınıflarda paketlenmiş geleneksel ve sıra dışı ortalama alma algoritmaları hakkındadır. Bunlar, göstergelerin neredeyse tüm gelişmelerinde evrensel kullanım için tasarlanmıştır. Umarım önerilen sınıflar, özel ve teknik göstergelerin 'hantal' çağrılarına iyi bir alternatif olur.
Büyüyen Nöral Gaz: MQL5'te Uygulama Büyüyen Nöral Gaz: MQL5'te Uygulama
Makalede, Büyüyen nöral gaz (GNG) olarak adlandırılan uyarlanabilir kümeleme algoritmasını uygulayan bir MQL5 programının nasıl geliştirileceğine ilişkin bir örnek gösterilmektedir. Bu makale, dil belgelerini incelemiş ve nöroinformatik alanına ilişkin belirli programlama becerilerine ve temel bilgilere sahip kullanıcılara yöneliktir.