English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
preview
Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 12): Zaman ve ticaret (I)

Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 12): Zaman ve ticaret (I)

MetaTrader 5Ticaret sistemleri | 30 Ocak 2023, 17:14
336 0
Daniel Jose
Daniel Jose

Giriş

Bant okuma, bazı yatırımcılar tarafından ticaretin çeşitli aşamalarında kullanılan bir ticaret yöntemidir. Bu yöntem son derece etkilidir ve doğru kullanıldığında, iyi bilinen fiyat hareketi analizi (saf mum gözlemi) kullanılarak elde edilebilecek olandan çok daha güvenli ve tutarlı bir şekilde istikrarlı kârlar elde edilmesine olanak sağlar. Ancak, bant okumanın şu anda sunulan şekliyle kullanımı, sürekli dikkat yoğunluğu gerektiren çok karmaşık ve yorucu bir süreçtir. Ve zamanla kaçınılmaz olarak piyasayı incelerken hatalar yapmaya başlarız.

Bant okumayla ilgili en büyük sorun, analiz etmemiz gereken bilgi miktarıdır. Bant okuma için tipik bir kullanım durumuna bakalım:


Asıl sorun şu ki, analiz sırasında hem fiyata ve hem de ona ne olduğuna bakmamız gerekiyor, ancak bu değerleri mini sözleşmelerde kontrol etmek çok pratik değildir. Bu nedenle, genellikle mini sözleşmelerde emir akışına bakmayız, bunun yerine piyasayı hareket ettiren sözleşmeler olduğu için tam sözleşmeleri gözlemlemeyi tercih ederiz. Gerçekte olan budur, dolayısıyla sistem aşağıdaki gibi görünür. Yorumlaması ve takip etmesi biraz daha kolaydır.


Ancak bu durumda bile bant okuma analizi oldukça zor ve sıkıcıdır. Stop emirleri aktifleştiğinde durum daha da zorlaşır, ekrandaki bilgiler çok hızlı bir şekilde kayacağından fiyat hareketinin bir kısmı kaçırılabilir.


Planlama

Neyse ki, MetaTrader 5 platformunun mini sözleşmeler için dahi olmak üzere alternatif bir sistemi vardır, bu da izlemeyi çok daha verimli ve kolay hale getirir. Mini sözleşmelerle çalışırken nasıl göründüğüne bir göz atalım:

Gördüğünüz gibi yorumlama çok daha basittir. Ancak, az önce bahsettiğimiz nedenlerden dolayı, tam sözleşmeleri kullanmak daha uygundur, o da şu şekilde görünecektir:


İşlemlere ilişkin verilerin alış ve satış fiyatı hareketlerinin gürültüsü içerisinde gösterildiğine dikkat edin. İşlemler burada daireler olarak gösterilmektedir. Kırmızılar satış işlemlerini, maviler alış işlemlerini ve yeşiller de doğrudan emirleri ifade etmektedir. Analizin kendisi için gerekli olmayan bilgilere sahip olmamızın yanı sıra, başka bir sorunumuz daha vardır: verilerin sunulduğu pencere, ticaret işlemlerini gerçekleştirdiğimiz grafikten ayrıdır, ki bu da bizi iki ekrana bakmaya zorlamaktadır. Bir yandan bu bir avantajdır, ancak bazı durumlarda işleri büyük ölçüde karmaşıklaştırır. Dolayısıyla önerim, işlem verilerini doğrudan ticaret yaptığımız grafik üzerinde görmemizi sağlayacak (aynı zamanda MetaTrader 5 platformunun sunduğu şekilde okunması da kolay olacak) bir sistem oluşturmaktır.


Uygulama

Yapacağımız ilk şey, tam sözleşme varlığına erişebilmemiz için C_Terminal sınıfını düzenlemektir. Bu, aşağıdaki kod parçalarını ekleyerek yapılır:

void CurrentSymbol(void)
{
        MqlDateTime mdt1;
        string sz0, sz1, sz2;
        datetime dt = TimeLocal();
                
        sz0 = StringSubstr(m_Infos.szSymbol = _Symbol, 0, 3);
        m_Infos.szFullSymbol = _Symbol;
        m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));
        if ((sz0 != "WDO") && (sz0 != "DOL") && (sz0 != "WIN") && (sz0 != "IND")) return;
        sz2 = (sz0 == "WDO" ? "DOL" : (sz0 == "WIN" ? "IND" : sz0));
        sz1 = (sz2 == "DOL" ? "FGHJKMNQUVXZ" : "GJMQVZ");
        TimeToStruct(TimeLocal(), mdt1);
        for (int i0 = 0, i1 = mdt1.year - 2000;;)
        {
                m_Infos.szSymbol = StringFormat("%s%s%d", sz0, StringSubstr(sz1, i0, 1), i1);
                m_Infos.szFullSymbol = StringFormat("%s%s%d", sz2, StringSubstr(sz1, i0, 1), i1);
                if (i0 < StringLen(sz1)) i0++; else
                {
                        i0 = 0;
                        i1++;
                }
                if (macroGetDate(dt) < macroGetDate(SymbolInfoInteger(m_Infos.szSymbol, SYMBOL_EXPIRATION_TIME))) break;
        }
}

// ... Class code ...

inline string GetFullSymbol(void) const { return m_Infos.szFullSymbol; }


Vurgulanan satırları ekleyerek, zaman ve ticaret sistemimizde kullanacağımız varlığa erişebiliriz. Şimdi ise sistemimizi destekleyecek nesne sınıfını oluşturmaya geçelim. Bu sınıf birçok ilginç fonksiyon içerecektir. İlk olarak, göstergemizi içerecek bir alt pencere oluşturalım. Bunu yapmak kolaydır, ancak pratik nedenlerden dolayı halihazırda kullandığımız alt pencere sistemini kullanmayacağız. Belki gelecekte bunu değiştiririz, ancak şimdilik zaman ve ticaret göstergesi alt penceremizi mevcut gösterge alt penceremizden farklı olarak ele alacağız. Tabi bu amaçla birkaç hazırlık çalışması yapmamız gerekecek.

Göstergemiz için farklı bir ada sahip olmak adına yeni bir destek dosyası oluşturalım. Dosyaların üstünde dosyalar oluşturmak yerine, daha zarif bir şey yapalım. Daha fazla olanağa sahip olmak için destek dosyasını şu şekilde düzenleyelim:

#property copyright "Daniel Jose 07-02-2022 (A)"
#property version   "1.00"
#property description "This file only serves as supporting indicator for SubWin"
#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
input string user01 = "SubSupport";             //Short Name
//+------------------------------------------------------------------+
int OnInit()
{
        IndicatorSetString(INDICATOR_SHORTNAME, user01);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
{
        return rates_total;
}
//+------------------------------------------------------------------+


Kaynak dosyada yapılması gereken değişiklikler yukarıda vurgulanmaktadır. Şimdi Uzman Danışman kodumuzda değişiklikler yapmamız gerekiyor. Yeni bir sınıf oluşturacağız:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#include "C_Terminal.mqh"
//+------------------------------------------------------------------+
class C_FnSubWin
{
        private :
                string  m_szIndicator;
                int             m_SubWin;
//+------------------------------------------------------------------+
                void Create(const string szIndicator)
                        {
                                int i0;
                                m_szIndicator = szIndicator;
                                if ((i0 = ChartWindowFind(Terminal.Get_ID(), szIndicator)) == -1)
                                        ChartIndicatorAdd(Terminal.Get_ID(), i0 = (int)ChartGetInteger(Terminal.Get_ID(), CHART_WINDOWS_TOTAL), iCustom(NULL, 0, "::" + def_Resource, szIndicator));
                                m_SubWin = i0;
                        }
//+------------------------------------------------------------------+
        public  :
//+------------------------------------------------------------------+
                C_FnSubWin()
                        {
                                m_szIndicator = NULL;
                                m_SubWin = -1;
                        }
//+------------------------------------------------------------------+
                ~C_FnSubWin()
                        {
                                Close();
                        }
//+------------------------------------------------------------------+
                void Close(void)
                        {
                                if (m_SubWin >= 0) ChartIndicatorDelete(Terminal.Get_ID(), m_SubWin, m_szIndicator);
                                m_SubWin = -1;
                        }
//+------------------------------------------------------------------+
inline int GetIdSubWinEA(const string szIndicator = NULL)
                        {
                                if ((szIndicator != NULL) && (m_SubWin < 0)) Create(szIndicator);
                                return m_SubWin;
                        }
//+------------------------------------------------------------------+
inline bool ExistSubWin(void) const { return m_SubWin >= 0; }
//+------------------------------------------------------------------+
};
//+------------------------------------------------------------------+


Bu sınıf, C_SubWindow'un yerini almaktadır, böylece artık bu sınıf, grafik üzerinde alt pencerelerin oluşturulmasını destekleyecek sınıf olacaktır. Bu sınıfın nasıl çalıştığını anlamak adına aşağıdaki yeni C_SubWindow sınıfına hızlıca bir göz atalım:

#include "C_ChartFloating.mqh"
#include <NanoEA-SIMD\Auxiliar\C_FnSubWin.mqh>
//+------------------------------------------------------------------+
class C_SubWindow : public C_ChartFloating
{
//+------------------------------------------------------------------+
        private :
                C_FnSubWin      m_fnSubWin;
//+------------------------------------------------------------------+
        public  :
//+------------------------------------------------------------------+
                ~C_SubWindow()
                        {
                                Close();
                        }       
//+------------------------------------------------------------------+
                void Close(void)
                        {
                                m_fnSubWin.Close();
                                CloseAlls();
                        }
//+------------------------------------------------------------------+
inline int GetIdSubWinEA(void)
                        {
                                return m_fnSubWin.GetIdSubWinEA("SubWinSupport");
                        }
//+------------------------------------------------------------------+
inline bool ExistSubWin(void) const { return m_fnSubWin.ExistSubWin(); }
//+------------------------------------------------------------------+
};
//+------------------------------------------------------------------+


Sınıfın, şablonları desteklemek için kullanılacak göstergenin tanımını içerdiğine dikkat edin (kodda vurgulanmaktadır). Şimdi işin biraz daha dikkat isteyen kısmı geliyor. SubWinSupport’tan farklı bir ad kullanırsak, C_FnSubWin sınıfı farklı bir gösterge arayacaktır. Gösterge dosyaları oluşturmaktan kaçınmak için işte bu numarayı kullanacağız. C_FnSubWin sınıfına başka bir amaç için kullanılması gereken göstergenin kısa adının ne olması gerektiğini basitçe söyleyeceğiz. Böylece, yalnızca Uzman Danışman alt penceresi oluşturmak için kullanılan gereksiz alt pencere veya gösterge dosyalarıyla sınırlı kalmayacağız.

Artık C_TimeAndTrade sınıfını oluşturmaya başlayabiliriz.


C_TimesAndTrade sınıfı

C_TimesAndTrade nesne sınıfı, her biri belirli bir şeyden sorumlu olan birkaç küçük kod parçasından oluşur. Aşağıdaki kod, Uzman Danışmanın bu sınıf için çağırdığı ilk şeydir:

void Init(const int iScale = 2)
{
        if (!ExistSubWin())
        {
                CreateCustomSymbol();
                CreateChart();
        }
        ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_CHART_SCALE, (iScale > 5 ? 5 : (iScale < 0 ? 0 : iScale)));
}

Bu kod, destek alt penceresinin var olup olmadığını kontrol edecektir. Mevcut değilse, kod bir tane oluşturacaktır. Şimdi, sınıfın ilk destek koduna daha yakından bakalım:

inline void CreateCustomSymbol(void)
{
        m_szCustomSymbol = "_" + Terminal.GetFullSymbol();
        SymbolSelect(Terminal.GetFullSymbol(), true);
        SymbolSelect(m_szCustomSymbol, false);
        CustomSymbolDelete(m_szCustomSymbol);
        CustomSymbolCreate(m_szCustomSymbol, StringFormat("Custom\\Robot\\%s", m_szCustomSymbol), Terminal.GetFullSymbol());
        CustomRatesDelete(m_szCustomSymbol, 0, LONG_MAX);
        CustomTicksDelete(m_szCustomSymbol, 0, LONG_MAX);
        SymbolSelect(m_szCustomSymbol, true);
};

Bu kod bir özel sembol oluşturacak ve içerisindeki tüm verileri sıfırlayacaktır. Sembolün içeriğinin oluşturacağımız alt pencerede görüntülenmesini sağlamak adına öncelikle ilgili sembolün Piyasa Gözlemine eklenmesi gerekir. Bu, aşağıdaki satırla yapılır:

SymbolSelect(m_szCustomSymbol, true);

Özel sembol şu konumda oluşturulacaktır: Custom\Robot\<Sembol adı>. Başlangıç verileri orijinal sembol tarafından sağlanacaktır. Bu, aşağıdaki kod parçasıyla elde edilir:

CustomSymbolCreate(m_szCustomSymbol, StringFormat("Custom\\Robot\\%s", m_szCustomSymbol), Terminal.GetFullSymbol());

Temel olarak, hepsi bu kadar. Sınıfı Uzman Danışmana ekleyelim ve çalıştıralım:

// ... Expert Advisor code

#include <NanoEA-SIMD\Tape Reading\C_TimesAndTrade.mqh>

// ... Expert Advisor code

input group "Times & Trade"
input   int     user041 = 2;    //Escala
//+------------------------------------------------------------------+
C_TemplateChart Chart;
C_WallPaper     WallPaper;
C_VolumeAtPrice VolumeAtPrice;
C_TimesAndTrade TimesAndTrade;
//+------------------------------------------------------------------+
int OnInit()
{
// ... Expert Advisor code

        TimesAndTrade.Init(user041);
        
        OnTrade();
        EventSetTimer(1);
   
        return INIT_SUCCEEDED;
}


Sonuç aşağıdaki gibidir:


Ve tam da beklendiği gibi oldu. Şimdi, gerçekleştirilen işlemlerin değerlerini _DOLH22 grafiğine ekleyelim. Bu grafik, zaman ve ticaret sisteminin grafiksel gösterimini sağlamak adına gerçekleştirilen tüm işlemleri yansıtacaktır. Sunum, kullanımı kolay olduğu için mumlar halinde olacaktır. Bunu yapmak için öncesinde sembolü bağlayıp senkronize etmemiz gerekiyor. Bu, aşağıdaki fonksiyon kullanılarak yapılır.

inline void Connect(void)
{
        switch (m_ConnectionStatus)
        {
                case 0:
                        if (!TerminalInfoInteger(TERMINAL_CONNECTED)) return; else m_ConnectionStatus = 1;
                case 1:
                        if (!SymbolIsSynchronized(Terminal.GetFullSymbol())) return; else m_ConnectionStatus = 2;
                case 2:
                        m_LastTime = TimeLocal();
                        m_MemTickTime = macroMinusMinutes(60, m_LastTime) * 1000;
                        m_ConnectionStatus = 3;
                default:
                        break;
        }
}

Fonksiyon, terminalin bağlı olup olmadığını kontrol eder ve ardından sembolü senkronize eder. Devamında, değerleri yakalamaya ve ekranda görüntülemeye başlayabiliriz. Ancak bunun için de başlatma kodunda küçük bir değişiklik yapmamız gerekiyor. Değişiklik aşağıdaki kodda vurgulanmaktadır:

void Init(const int iScale = 2)
{
        if (!ExistSubWin())
        {
                CreateCustomSymbol();
                CreateChart();
                m_ConnectionStatus = 0;
        }
        ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_CHART_SCALE, (iScale > 5 ? 5 : (iScale < 0 ? 0 : iScale)));
}

Şimdi yakalama fonksiyonuna bakabiliriz.

inline void Update(void)
{
        MqlTick Tick[];
        MqlRates Rates[def_SizeBuff];
        int i0, p1, p2 = 0;
        int iflag;

        if (m_ConnectionStatus < 3) return;
        if ((i0 = CopyTicks(Terminal.GetFullSymbol(), Tick, COPY_TICKS_ALL, m_MemTickTime, def_SizeBuff)) > 0)
        {
                for (p1 = 0, p2 = 0; (p1 < i0) && (Tick[p1].time_msc == m_MemTickTime); p1++);
                for (int c0 = p1, c1 = 0; c0 < i0; c0++)
                {
                        if (Tick[c0].volume == 0) continue;
                        iflag = 0;
                        iflag += ((Tick[c0].flags & TICK_FLAG_BUY) == TICK_FLAG_BUY ? 1 : 0);
                        iflag -= ((Tick[c0].flags & TICK_FLAG_SELL) == TICK_FLAG_SELL ? 1 : 0);
                        if (iflag == 0) continue;
                        Rates[c1].high = Tick[c0].ask;
                        Rates[c1].low = Tick[c0].bid;
                        Rates[c1].open = Tick[c0].last;
                        Rates[c1].close = Tick[c0].last + ((Tick[c0].volume > 200 ? 200 : Tick[c0].volume) * (Terminal.GetTypeSymbol() == C_Terminal::WDO ? 0.02 : 1.0) * iflag);
                        Rates[c1].time = m_LastTime;
                        p2++;
                        c1++;
                        m_LastTime += 60;
                }
                CustomRatesUpdate(m_szCustomSymbol, Rates, p2);
                m_MemTickTime = Tick[i0 - 1].time_msc;
        }
}

Yukarıdaki fonksiyon, tüm işlem tiklerinin yakalanmasına ve her birinin alış veya satış tiki olup olmadığının kontrol edilmesine olanak sağlar. Eğer tikler alış veya satış fiyatı değişiklikleriyle ilgiliyse, yani hacim yoksa, kaydedilmezler. Aynı şey, yerel fiyat hareketine neden olan ancak genel fiyat hareketini etkilemeyen doğrudan emir tikleri için de geçerlidir; çünkü sadece doğrudan emri yerine getirmek için fiyatı belirli bir değere zorlayan piyasa oyuncuları vardır ve ardından kısa bir süre sonra fiyat serbestçe hareket etmeye devam eder. Alış ve satış fiyatının değişimiyle ile ilgili olan bu tikler, genel sistemde ikincil öneme sahip olduklarından, bir sonraki makalede ele alacağımız başka bir versiyonda kullanılacaktır. İşlem türünü kontrol ettikten sonra, sırada anlaşılması önemli olan bir dizi kod satırı vardır. Aşağıda yer alan bu satırlar, analiz sisteminden geçen ve kaydedilmesi gereken her tik için bir mum oluşturur.

Rates[c1].high = Tick[c0].ask;
Rates[c1].low = Tick[c0].bid;
Rates[c1].open = Tick[c0].last;
Rates[c1].close = Tick[c0].last + ((Tick[c0].volume > 200 ? 200 : Tick[c0].volume) * (Terminal.GetTypeSymbol() == C_Terminal::WDO ? 0.02 : 1.0) * iflag);
Rates[c1].time = m_LastTime;

Mumun yüksek ve düşük değerleri, tikin işlem gördüğü sıradaki spreadi temsil eder, yani alış ve satış fiyatı arasındaki değer oluşturulan mumun gölgesi olacaktır. Mumun açılış değeri ise işlemin gerçekleştiği fiyattır. Şimdi vurgulanan kod satırına yakından bakalım. Hacme sahip tik varlığında, bu satır, ölçeğin taşmaması için o hacme küçük bir ayarlama yapar. Analiz edeceğiniz varlığa bağlı olarak değerleri kendinize uygun şekilde ayarlayabilirsiniz.

Şimdi son ayrıntıya geldik - zaman. Her mum bir dakikaya karşılık gelecektir, çünkü bu sürenin altında değerler çizmek mümkün değildir. Devamında her bir mum bir dakika boyunca ilgili konumunda kalacaktır. Bu, gerçek zaman değildir, sanal zamandır. İşlem zamanını grafik zamanıyla karıştırmayın: işlemler milisaniyeler içerisinde gerçekleşebilir, ancak grafikteki bilgiler grafiğin ölçeğinde, yani her bir dakika için, çizilecektir. Başka herhangi bir değer de kullanabilirdik, ancak bu değer mümkün olan en küçük değer olduğundan programlamayı büyük ölçüde basitleştirmektedir. Sistemin sonucu aşağıda görülebilir:

Artık okumanın oldukça rahat ve yorumlamanın da basit olduğunu görüyoruz. Ekran görüntüsünün alındığı sırada emir bandı çok yavaş olsa da, fikrin anlaşılması için yeterli olduğunu düşünüyorum.

Bu sistemle ilgili son bilgiler aşağıda gösterilmektedir:

Sistemde görülebilecek dört farklı konfigürasyon olduğuna dikkat edin. Onlara neden ihtiyacımız var? Bunu bir sonraki makalede detaylı olarak konuşacağız. Şu anda yoğun kullanım için bile yeterli olabilecek çalışan bir zaman ve ticaret sistemine sahibiz. Ancak tam olarak neler olup bittiğini ve dört mum formasyonunun oluşmasına neyin neden olduğunu anlarsanız, bu sistemden çok daha fazla yararlanabilirsiniz ve kim bilir, belki de bu gösterge ana göstergeniz olur...


Sonuç

Bu makalemizde, bant okuma analizi için Uzman Danışmanımızda kullanılmak üzere bir zaman ve ticaret sistemi oluşturduk. MetaTrader 5'te bulunan alternatif sistemle aynı analiz hızını bize sağlayacaktır. Bunu, çok fazlaca sayı ve değeri okuyup anlamaya çalışmak yerine bir grafik sistemi oluşturarak başardık. Bir sonraki makalemizde ise eksik olan bilgileri yerine koyarak sistemimizi tamamlayacağız.



MetaQuotes Ltd tarafından Portekizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/pt/articles/10410

Ekli dosyalar |
EA_-_Times_e_Trade.zip (5982.95 KB)
Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 13): Zaman ve ticaret (II) Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 13): Zaman ve ticaret (II)
Bu makalemizde de piyasayı değerlendirmede önemli kolaylık sağlayan zaman ve ticaret sistemini oluşturmaya devam ediyoruz. Bir önceki "Zaman ve ticaret (I)" makalesinde, piyasada gerçekleştirilen işlemleri mümkün olan en hızlı şekilde yorumlayabilmek amacıyla alternatif bir grafik sistemini ele almıştık.
MQL5'te matrisler ve vektörlerle çalışma MQL5'te matrisler ve vektörlerle çalışma
Matematik problemlerinin verimli bir şekilde çözülebilmesi adına MQL5’e matrisler ve vektörler eklendi. Yeni türler, matematiksel gösterime yakın, öz ve anlaşılır kodlar yazmak için yerleşik metotlar sağlar. Diziler iyidir, ancak matrisler çok daha iyidir çünkü matrislerin çok daha verimli olduğu birçok durum vardır.
MFI göstergesine dayalı bir ticaret sistemi nasıl geliştirilir? MFI göstergesine dayalı bir ticaret sistemi nasıl geliştirilir?
En popüler teknik göstergelere dayalı ticaret sistemleri tasarladığımız makale serimizin bu yeni makalesinde de Money Flow Index (MFI) teknik göstergesini ele alacağız. Onu ayrıntılı olarak inceleyeceğiz ve MetaTrader 5'te kullanılmak üzere MQL5 dili aracılığıyla ona dayalı basit bir ticaret sistemi geliştireceğiz.
Accumulation/Distribution (AD) göstergesine dayalı bir ticaret sistemi nasıl geliştirilir? Accumulation/Distribution (AD) göstergesine dayalı bir ticaret sistemi nasıl geliştirilir?
En popüler teknik göstergelere dayalı ticaret sistemleri geliştirdiğimiz serimizin yeni makalesine hoş geldiniz. Bu makalemizde Accumulation/Distribution (AD) göstergesini inceleyeceğiz. Birkaç basit stratejiyi kullanarak MQL5 dilinde ona dayalı bir ticaret sisteminin nasıl geliştirileceğini öğreneceğiz.