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

Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 20): Yeni emir sistemi (III)

MetaTrader 5Ticaret sistemleri | 28 Temmuz 2023, 08:56
309 0
Daniel Jose
Daniel Jose

Giriş

Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 19): Yeni emir sistemi (II) başlıklı bir önceki makalede, yeni emir sisteminin çalışmasını sağlamak amacıyla uyguladığımız kod değişikliklerine odaklanmıştık. Bu değişiklikler uygulandığına göre, artık asıl konuya tam anlamıyla odaklanabiliriz. Hedefimiz, tik değerini bilmek zorunda kalmadan ve böylece x miktarı kadar kâr etmek için Kârı Alın nereye yerleştirileceğini veya y miktarı kadar zarar etmemek için Zararı Durdurun nereye ayarlanacağını hesaplamak zorunda kalmadan ticaret yapılabilmesini sağlayacak şekilde görsel ve anlaşılır bir emir sistemi uygulamaktır.

Böyle bir sistemin oluşturulması, MQL5'e iyi hakim olmanın yanı sıra MetaTrader 5 platformunun gerçekte nasıl çalıştığını ve hangi kaynakları sağladığını anlamayı gerektirir.


1.0. Planlama

1.0.1. Göstergeleri tasarlama

Buradaki fikir (sadece bir fikirden daha fazlası, aslında yapacağımız şey), bu makaledeki sistemin nasıl uygulanacağını göstermektir. Aşağıdaki görüntüde gösterilene benzer bir şey oluşturacağız:

Benim açıklamam olmadan dahi anlaşılması çok kolaydır. Bir kapatma düğmesi, bir değer ve emirleri sürüklemeyi ve yerleştirmeyi kolaylaştırmak için bir nokta vardır. Ancak hepsi bu kadar değildir. Zararı Durdur, Kârı Durdura dönüştüğünde, sistem bunu şu şekilde ele alacaktır:

Böylece, belirli bir pozisyonu ne zaman, ne kadar ve nerede tutmaya değip değmeyeceğini kolayca anlayabiliriz.

Yukarıdaki görseller yalnızca OCO emrinin veya pozisyonunun eşiklerini göstermektedir, ancak açılış fiyatıyla ilgili kısmı da unutmadım, çünkü o da aynı derecede önemlidir.

Bekleyen emirler için şu şekilde görünecektir:

Bir pozisyon için ise biraz farklı görünecektir:

Göze hitap açısından pek iç açıcı değiller... Ancak uygulanacak olan fikir budur. Renklere gelince, ben burada gösterilenleri kullanacağım. Ama siz dilerseniz onları beğeninize göre değiştirebilirsiniz.

Planlamaya devam edersek, temelde her göstergede 5 nesnemiz olacağını fark edebiliriz. Bu, MetaTrader 5'in her gösterge için aynı anda 5 nesneyi işlemesi gerekeceği anlamına gelir. OCO emri durumunda, MetaTrader 5, tıpkı OCO pozisyonunda olduğu gibi, 15 nesneyle ilgilenmek zorunda kalacaktır (bu 15 nesne, emir veya pozisyon başınadır). Bu, 4 bekleyen OCO emrine ve 1 açık OCO pozisyonuna sahip olduğumuzda, MetaTrader 5'in, grafikte yer alacak diğerlerinin yanı sıra, 25 nesneyle ilgilenmesi gerekeceği anlamına gelir. Ve bu, platformda yalnızca bir varlık kullanıyorsanız geçerlidir.

Bunu söylüyorum çünkü ticaret enstrümanına yerleştireceğiniz her emir için gereken olası belleği ve işlem gücünü bilmek önemlidir. Bu, modern bilgisayarlar için bir sorun değildir, ancak donanımdan tam olarak ne talep edileceğini bilmek gerekir. Öncesinde, emrin her noktası için ekranda yalnızca bir nesne mevcuttu. Şimdi her bir noktada 5 nesne olacaktır ve onların bir şekilde birbirlerine bağlı kalması gerekecektir. Bu bağlantı platform tarafından gerçekleştirilecektir, biz ise sadece nasıl bağlanmaları gerektiğini ve her bir nesne tetiklendiğinde ne olması gerektiğini belirteceğiz.


1.0.2. Nesneleri seçme

Bir sonraki konu, kullanacağımız nesnelerin seçimidir. Bu basit bir konu gibi görünebilir, ancak uygulamanın gerçekte nasıl ilerleyeceğini belirleyeceği için çok önemlidir. İlk seçim, nesnelerin ekranda nasıl konumlandırılacağına bağlı olacaktır.

Bunu yapmak için iki yolumuz vardır. Neyse ki, MetaTrader 5 her ikisini de kapsamaktadır: ilki zaman ve fiyat koordinatlarına göre konumlandırmayı kullanmaktadır, ikincisi ise kartezyen X ve Y koordinatlarını kullanmaktadır.

Zaman ve fiyat koordinatlarını kullanan modeli hemen bir kenara bırakacağım. İlk bakışta ideal gibi görünse de, birbirine bağlanacak ve bir arada kalması gerekecek çok sayıda nesneyle uğraştığımızda kullanışlı olmayacaktır. Bu nedenle, kartezyen sistemini kullanmamız gerekecektir.

Önceki makalelerden birinde bu sistemi incelemiş ve nesnelerin nasıl seçileceğini tartışmıştık. Ayrıntılar için Bir grafikte birden fazla gösterge (Bölüm 05): MetaTrader 5'i bir RAD sistemine dönüştürme (I) makalesine bakın.

Planlamayı tamamladık, şimdi kodlamanın kendisine geçebiliriz: her şeyi pratikte uygulama zamanı.


2.0. Uygulama

Amacım sadece sistemi uygulamak değil, içerisinde tam olarak neler olup bittiğini açıklamaktır, böylece siz de ele alınan sistemi temel alarak kendi sisteminizi oluşturabilirsiniz. Ayrıntılar üzerinde yavaş yavaş ilerleyeceğiz. Bu sayede sistemin nasıl oluşturulduğunu daha iyi anlayabileceksiniz. Sistem aynı ilkeleri izlediğinden ve ortak bir koda sahip olduğundan, bekleyen emirlerle ilgili herhangi bir işlevin pozisyonlar için de çalışacağını unutmayın.


2.0.1. Bir arayüz çerçevesi oluşturma

Bu ilk adımın sonucu aşağıdan görülebilir. Kodları geliştirdiğimde ve sizlerle paylaşmaya karar verdiğimde yaşadığım heyecanı sizin de yaşamanız adına sistemin arayüz çerçevesini şimdiden bu şekilde size sunuyorum. Umarım bu, programlamayı öğrenmek ya da bu konuda daha derin bilgi sahibi olmak isteyenler için bir motivasyon kaynağı olur.


Yukarıdaki görüntüye baktığınızda, işlevselliğin şimdiye kadar oluşturulan tüm kodların haricinde, olağan bir şekilde oluşturulduğunu düşünüyor olabilirsiniz. Ancak hayır, şimdiye kadar inşa edilenleri aynen kullanacağız.

Önceki makalede sunulan kodu kullanacağız ve üzerinde bazı değişiklikler yapacağız. Bu amaçla, şimdi koddaki yeniliklere odaklanalım. İlk olarak, üç yeni sınıf ekleyeceğiz.


2.0.1.1. C_Object_Base sınıfı

Yeni bir sınıf oluşturarak başlayacağız - C_Object_Base. Bu, sistemimizdeki en alt sınıftır. Sınıfın ilk kodları aşağıda gösterilmektedir:

class C_Object_Base
{
        public  :
//+------------------------------------------------------------------+
void Create(string szObjectName, ENUM_OBJECT typeObj)
{
        ObjectCreate(Terminal.Get_ID(), szObjectName, typeObj, 0, 0, 0);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_SELECTABLE, false);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_SELECTED, false);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BACK, true);
        ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_TOOLTIP, "\n");
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BACK, false);
        ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_TOOLTIP, "\n");
        PositionAxleY(szObjectName, 9999);
};

// ... The rest of the class code

Hayatımızı çok daha kolaylaştıracak genel bir koda sahip olduğumuza dikkat edin. Aynı sınıfta, standart X ve Y konumlandırma kodlarımız vardır:

void PositionAxleX(string szObjectName, int X)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XDISTANCE, X);
};
//+------------------------------------------------------------------+
virtual void PositionAxleY(string szObjectName, int Y)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y);
};

Y konumlandırma kodu belirli bir nesneye bağlı olacaktır, ancak nesnenin belirli bir kodu olmasa dahi, sınıf genel bir kod olarak hizmet edecektir. Ayrıca nesnenin rengini belirtmenin de genel bir koduna sahibiz:

virtual void SetColor(string szObjectName, color cor)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_COLOR, cor);
}

Ve nesnelerin büyüklüklerini tanımlamanın kodu:

void Size(string szObjectName, int Width, int Height)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XSIZE, Width);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE, Height);
};

C_Object_Base sınıfı ile ilgili şimdilik bu kadar, ancak daha sonra ona geri döneceğiz.


2.0.1.2. C_Object_BackGround sınıfı

Şimdi grafik nesnelerimizi desteklemek için iki sınıf daha oluşturalım. Bunlardan ilki C_Object_BackGround sınıfıdır. Diğer öğeleri içermek için bir arka plan kutusu oluşturur. Kodu oldukça basittir. Aşağıdan tamamını görebilirsiniz:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#include "C_Object_Base.mqh"
//+------------------------------------------------------------------+
class C_Object_BackGround : public C_Object_Base
{
        public:
//+------------------------------------------------------------------+
		void Create(string szObjectName, color cor)
                        {
                                C_Object_Base::Create(szObjectName, OBJ_RECTANGLE_LABEL);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_COLOR, clrNONE);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BGCOLOR, cor);
                        }
//+------------------------------------------------------------------+
virtual void PositionAxleY(string szObjectName, int Y)
                        {
                                int desl = (int)(ObjectGetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE) / 2);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y - desl);
                        }
//+------------------------------------------------------------------+
};

Nesneyi minimum kodla bir araya getirmek için kalıtımı kullandığımıza dikkat edin. Bu şekilde, sınıfın kendisini gerektiği gibi değiştirmesini ve modellemesini sağlarız, böylece daha sonra bu ayarlamaları yapmak zorunda kalmayız. Bu, vurgulanan koddan görülebilir: sınıf sadece Y ekseninin değerini bilerek kendisini otomatik olarak doğru yere konumlandıracaktır - büyüklüğü kontrol edecek ve kendisine ilettiğimiz eksenin ortasında olacak şekilde kendisini konumlandıracaktır.


2.0.1.3. C_Object_TradeLine sınıfı

C_Object_TradeLine sınıfı, daha önce emir fiyatı çizgisinin nerede olduğunu belirtmek için kullanılan yatay çizginin değiştirilmesinden sorumludur. Bu sınıf oldukça ilginçtir, bu yüzden koduna bir göz atalım: aşağıdaki koddan görebileceğimiz gibi private bir statik değişkene sahiptir.

#property copyright "Daniel Jose"
#include "C_Object_BackGround.mqh"
//+------------------------------------------------------------------+
class C_Object_TradeLine : public C_Object_BackGround
{
        private :
                static string m_MemNameObj;
        public  :
//+------------------------------------------------------------------+

// ... Internal class code

//+------------------------------------------------------------------+
};
//+------------------------------------------------------------------+
string C_Object_TradeLine::m_MemNameObj = NULL;
//+------------------------------------------------------------------+

Nasıl bildirileceğini ve nasıl düzgün bir şekilde başlatılacağını görebilmeniz için vurgulanmıştır. Statik değişkenin yapacağı şeyin yerine geçecek bir global değişken oluşturabiliriz, ancak ben kontrolü elimde tutmak istiyorum: bu şekilde her nesne ihtiyaç duyduğu her şeye sahip olacak ve bilgiler içlerinde saklanacaktır. Ve eğer bir nesneyi başka bir nesneyle değiştirmek istersek, bunu da kolayca yapabiliriz.

Dikkat edilmesi gereken bir sonraki şey nesne oluşturma kodudur:

void Create(string szObjectName, color cor)
{
        C_Object_BackGround::Create(szObjectName, cor);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XSIZE, TerminalInfoInteger(TERMINAL_SCREEN_WIDTH));
        SpotLight(szObjectName);
};

Bunu doğru bir şekilde uygulamak için, aslında çizgi görevi görecek bir kutu oluşturduğumuz C_Object_BackGround sınıfını kullanıyoruz. Farklı türde bir nesne kullanılsaydı, sahip olacağımız davranışın aynısını elde edemezdik. İhtiyacımız olan şeyi yapan tek nesne, C_Object_Background sınıfında bulunan nesnedir. Bu nedenle, ihtiyaçlarımıza uyum sağlayacak şekilde onu değiştireceğiz ve böylece bir çizgi oluşturacağız.

Devamında, bir çizgiyi vurgulamaktan sorumlu olan kodu görüyoruz:

void SpotLight(string szObjectName = NULL)
{
        if (szObjectName != NULL) ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE, (szObjectName != NULL ? 4 : 3));
        if (m_MemNameObj != NULL) ObjectSetInteger(Terminal.Get_ID(), m_MemNameObj, OBJPROP_YSIZE, 3);
        m_MemNameObj = szObjectName;
};

Bu kod ilginçtir, çünkü bir çizgiyi vurguladığımızda hangisinin vurgulandığını bilmemiz gerekmez, nesnenin kendisi bunu bizim için yapar. Ve yeni bir çizgi vurgulanmayı hak ettiğinde, vurgulanan çizgi otomatik olarak bu durumunu kaybeder ve yeni çizgi onun yerini alır. Artık hiçbir çizginin vurgulanmaması gerekiyorsa, sadece fonksiyonu çağırırız ve fonksiyon tüm çizgilerden vurgulamayı kaldırır.

Bunu bilerek, yukarıdaki kod aşağıdaki kodla birlikte eski seçim kodunu ortadan kaldırır. Bu şekilde MetaTrader 5, hangi göstergeyi manipüle ettiğimizi bize söyleyecektir.

string GetObjectSelected(void) const { return m_MemNameObj; }

Dikkat etmeye değer başka bir fonksiyon daha vardır. Bu fonksiyon, çizgiyi Y ekseninde konumlandırır:

virtual void PositionAxleY(string szObjectName, int Y)
{
        int desly = (m_MemNameObj == szObjectName ? 2 : 1);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y - desly);
};

BackGround nesnesinde gösterilen fonksiyon gibi, bu fonksiyon da çizginin vurgulanıp vurgulanmadığına bağlı olarak kendisini doğru noktaya ayarlar.

Böylece iki nesnemizi artık tamamlamış olduk. Ancak onları ekranda görebilmemiz için (yukarıda gösterildiği gibi), C_ObjectsTrade sınıfında bazı değişiklikler yapmamız gerekecektir.


2.0.2. C_ObjectsTrade sınıfının değiştirilmesi

Yapılacak değişiklikler ilk bakışta çok karmaşık görünmemektedir, ancak aynı kodu defalarca tekrarlamak biraz göz korkutucu olabiliyor, bu yüzden bundan kaçınmanın bir yolunu bulmaya çalıştım. Çözümü makro kullanmakta buldum, ancak makrolarla dolu bir kodu takip etmenin kafa karıştırıcı olduğunu düşünüyorsanız, makrolardan fonksiyonlara veya prosedürlere geçiş yapmaktan ve ekstrem durumlarda makroları uygun dahili kodlarla değiştirmekten çekinmeyin. Uzun yıllardır bu şekilde yaptığım için ben makro kullanmayı tercih ediyorum.

İlk olarak, bir olay numaralandırması oluşturuyoruz:

enum eEventType {EV_GROUND = 65, EV_LINE};

Nesneler oluşturuldukça, buraya yeni olaylar eklemeliyiz (bu olaylar önemli olmalıdır). Ancak, her nesnenin sadece bir türde olayı olacaktır ve bu olay MetaTrader 5 tarafından oluşturulacaktır. Kodumuz yalnızca olayın düzgün bir şekilde işlenmesini sağlayacaktır.

Bu yapıldıktan sonra, nesnelerin her birine erişim sağlayacak değişkenler oluşturalım:

C_Object_BackGround     m_BackGround;
C_Object_TradeLine      m_TradeLine;

Sınıfın global kapsamındadırlar, ancak özeldirler. Onları kullanan her fonksiyonda bildirebiliriz, ancak tüm sınıf nesnelerle ilgileneceği için bu pek mantıklı değildir.

Bu nedenle, önceki makaledeki kodda ilgili değişikliği yapıyoruz:

inline string MountName(ulong ticket, eIndicatorTrade it, eEventType ev)
{
        return StringFormat("%s%c%c%c%d%c%c", def_NameObjectsTrade, def_SeparatorInfo, (char)it, def_SeparatorInfo, ticket, def_SeparatorInfo, (char)ev);
}

Vurgulanan kısımlar önceki versiyonda mevcut değildi, ancak şimdi MetaTrader 5'in bizi neler olduğu hakkında bilgilendirmesine yardımcı olacaklardır.

Ayrıca, yeni bir fonksiyona sahibiz:

void SetPositionMinimalAxleX(void)
{
        m_PositionMinimalAlxeX = (int)(ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) * 0.2);
}

Nesneler için X ekseninde bir başlangıç noktası oluşturur. Nesnelerin her birinin belirli bir noktası olacaktır, ancak burada onlara bir başlangıç referansı sağlıyoruz. Yukarıdaki koddaki noktayı değiştirerek başlangıç konumunu değiştirebilirsiniz.

Seçim fonksiyonu birçok değişikliğe uğradı, ancak daha sonra biraz daha değişecektir. Fakat şimdilik aşağıda gösterildiği gibidir:

inline void Select(const string &sparam)
{
        ulong tick;
        double price;
        eIndicatorTrade it;
        eEventType ev;
        string sz = sparam;
                                
        if (!GetInfosOrder(sparam, tick, price, it, ev)) sz = NULL;
        m_TradeLine.SpotLight(sz);
}

Değişen bir diğer fonksiyon da göstergeyi oluşturan fonksiyondur:

inline void CreateIndicatorTrade(ulong ticket, double price, eIndicatorTrade it, bool select)
{
        if (price <= 0) RemoveIndicatorTrade(ticket, it); else
        {
                CreateIndicatorTrade(ticket, it, select);
                PositionAxlePrice(price, ticket, it, -1, -1, 0, false);
        }
}

Ancak yukarıdaki kod o kadar da önemli değildir. Gerçekten tüm zor işi yapan şey aşağıdaki kodda gösterilmektedir:

inline void CreateIndicatorTrade(ulong ticket, eIndicatorTrade it)
{
        color cor1, cor2;
        string sz0;
                                
        switch (it)
        {
                case IT_TAKE    :
                        cor1 = clrPaleGreen;
                        cor2 = clrDarkGreen;
                        break;
                case IT_STOP    :
                        cor1 = clrCoral;
                        cor2 = clrMaroon;
                        break;
                case IT_PENDING:
                default:
                        cor1 = clrGold;
                        cor2 = clrDarkGoldenrod;
                        break;
        }                               
        m_TradeLine.Create(MountName(ticket, it, EV_LINE), cor2);
        if (ticket == def_IndicatorTicket0) m_TradeLine.SpotLight(MountName(ticket, IT_PENDING, EV_LINE));
        m_BackGround.Create(sz0 = MountName(ticket, it, EV_GROUND), cor1);
        switch (it)
        {
                case IT_TAKE:
                case IT_STOP:
                        m_BackGround.Size(sz0, 92, 22);
                        break;
                case IT_PENDING:
                        m_BackGround.Size(sz0, 110, 22);
                        break;
        }
}

Bu fonksiyonda, nesnelerin renklerini, büyüklüklerini ve oluşturulma sırasını belirliyoruz. Göstergeye eklenen herhangi bir nesne, her şeyin ortalanması ve her zaman kontrol edilmesi adına bu fonksiyon kullanılarak yerleştirilmelidir. Göstergeler oluşturmak için bir fonksiyon oluşturmaya başlarsanız, bakımı zor ve daha da kötüsü uygun kontrollerden yoksun bir kod elde edersiniz. Her şeyin yolunda olduğunu, çalıştığını düşünebilirsiniz ve bir gerçek hesapta çalıştırırsınız - ancak o zaman gerçekten kontrol edilecektir ve aniden bazı şeylerin düzgün çalışmadığını fark edebilirsiniz. İşte size bir ipucu: fonksiyonları her zaman aynı işi yapan şeyler içerisinde toplayın; ilk başta anlamsız görünse bile, nelerin değiştiğini her zaman kontrol edebileceğiniz için zamanla anlam ifade edecektir.

Değişen ve bahsetmeye değer bir sonraki fonksiyon aşağıda yer almaktadır:

#define macroDelete(A)  {                                                               \
                ObjectDelete(Terminal.Get_ID(), MountName(ticket, A, EV_GROUND));       \
                ObjectDelete(Terminal.Get_ID(), MountName(ticket, A, EV_LINE));         \
                        }
                                        
inline void RemoveIndicatorTrade(ulong ticket, eIndicatorTrade it = IT_NULL)
                        {
                                ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, false);
                                if ((it != NULL) && (it != IT_PENDING) && (it != IT_RESULT)) macroDelete(it)
                                else
                                {
                                        macroDelete(IT_PENDING);
                                        macroDelete(IT_RESULT);
                                        macroDelete(IT_TAKE);
                                        macroDelete(IT_STOP);
                                }
                                ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, true);
                        }
#undef macroDelete

Bu fonksiyon biraz sıkıcıdır. Fonksiyon, oluşturulan nesnelerin her birinin ayrı ayrı seçilebileceği şekilde çalışmalıdır. Ve bu, göstergelerin her biri için geçerli olmalıdır. Bunu bir düşünün. Görevi kolaylaştıran makrolar kullanmasaydık, bu bir kabus olacaktı. Kodun sonunda her gösterge 5 nesneye sahip olacağından, bu fonksiyonu kodlamak son derece yorucu olacaktır. Bir OCO emrindeki her kümenin 3 göstergeye sahip olacağını biliyoruz, bu bizim 15 nesneyle kodlama yapmamıza neden olacaktır ve bu durumda da hata yapma şansı çok yüksek olacaktır (aralarındaki fark sadece adlardır). Böylece, makrolar yardımıyla kod, koddaki vurgulanan kısma indirgenir: neticede yalnızca 5 nesne kodlayacağız. Ancak bu, yukarıda gösterilen sonucu elde etmek için sadece ilk aşamadır.

İlk aşamayı tamamlamak için aynı derecede sıkıcı bir fonksiyonumuz daha vardır. Makrolar kullanmıyor olsaydık, makrolar yerine prosedürler kullanabilirdik. Ama biz bu yolu seçtik.

#define macroSetAxleY(A)        {                                               \
                m_BackGround.PositionAxleY(MountName(ticket, A, EV_GROUND), y); \
                m_TradeLine.PositionAxleY(MountName(ticket, A, EV_LINE), y);    \
                                }
                                                                        
#define macroSetAxleX(A, B)     {                                               \
                m_BackGround.PositionAxleX(MountName(ticket, A, EV_GROUND), B); \
                m_TradeLine.PositionAxleX(MountName(ticket, A, EV_LINE), B);    \
                                }

inline void PositionAxlePrice(double price, ulong ticket, eIndicatorTrade it, int FinanceTake, int FinanceStop, int Leverange, bool isBuy)
                        {
                                double ad;
                                int x, y;
                                
                                ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price, x, y);
                                macroSetAxleY(it);
                                macroSetAxleX(it, m_PositionMinimalAlxeX);
                                if (Leverange == 0) return;
                                if (it == IT_PENDING)
                                {
                                        ad = Terminal.GetAdjustToTrade() / (Leverange * Terminal.GetVolumeMinimal());
                                        ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price + Terminal.AdjustPrice(FinanceTake * (isBuy ? ad : (-ad))), x, y);
                                        macroSetAxleY(IT_TAKE);
                                        macroSetAxleX(IT_TAKE, m_PositionMinimalAlxeX + 120);
                                        ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price + Terminal.AdjustPrice(FinanceStop * (isBuy ? (-ad) : ad)), x, y);
                                        macroSetAxleY(IT_STOP);
                                        macroSetAxleX(IT_STOP, m_PositionMinimalAlxeX + 220);
                                }
                        }
#undef macroSetAxleX
#undef macroSetAxleY

Bir önceki fonksiyonunun sıkıcı olduğunu düşünüyorsanız, bir de buna göz atın. Burada iş iki katına çıkacaktır, ancak vurgulanan kodlar sayesinde bu durum kabul edilebilir hale gelmektedir.

Yapılması gereken başka küçük değişiklikler de vardır, ancak bunlar gerçekten bahsetmeye değmez, bu yüzden bu kodu çalıştırdığımızda, tam olarak beklediğimiz şeyi, yani ekranda görünen göstergeleri elde ediyoruz:


Sonuç

Emirlerin doğrudan grafik üzerinde görüntülenmesi açısından sistemin tamamlanmasına oldukça az bir süre kaldı. Ancak şimdi hepsini bir kerede yapmak zorundayız, çünkü kodun diğer yerlerinde çok önemli değişiklikler yapmak gerekiyor.

Bu nedenle, değişiklikler çok derin olacağından bunu bir sonraki makaleye bırakacağız. Ve eğer bir şeyler ters giderse, sistemi olmasını istediğiniz şekilde değiştirmeyi başarana kadar bir adım geri gidip tekrar deneyebilirsiniz. Bu şekilde, sistemi özelleştirebilir ve rahat edeceğiniz şekilde bırakabilirsiniz. Bir sonraki makalede, sistemi aşağıda gösterildiği gibi yapacağız:


Uygulaması kolay görünüyor, değil mi? Ama inanın bana, yapılması gereken pek çok değişiklik vardır. Bir sonraki makalede görüşmek üzere.

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

Ekli dosyalar |
Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 21): Yeni emir sistemi (IV) Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 21): Yeni emir sistemi (IV)
Sonunda görsel sistem çalışmaya başlayacak... tam olarak tamamlanmış şekilde olmasa da. Burada ana değişiklikleri yapmayı bitireceğiz. Çok sayıda değişiklik olacaktır ve onların hepsi gereklidir. Tüm çalışma oldukça ilginç olacaktır.
Popülasyon optimizasyon algoritmaları: Yapay arı kolonisi (Artificial Bee Colony, ABC) Popülasyon optimizasyon algoritmaları: Yapay arı kolonisi (Artificial Bee Colony, ABC)
Bu makalede, yapay arı kolonisi algoritmasını inceleyeceğiz ve bilgi birikimimizi fonksiyon uzaylarıyla çalışmanın yeni ilkeleriyle destekleyeceğiz. Ayrıca algoritmanın klasik versiyonuna yorumumuzu katarak değiştirilmiş bir versiyonunu uygulayacağız.
Bull’s Power göstergesine dayalı bir ticaret sistemi nasıl geliştirilir? Bull’s Power göstergesine dayalı bir ticaret sistemi nasıl geliştirilir?
En popüler teknik göstergelere dayalı ticaret sistemlerinin nasıl geliştirileceğine ilişkin serimizin yeni makalesine hoş geldiniz. Bu sefer Bull’s Power teknik göstergesini inceleyeceğiz.
Popülasyon optimizasyon algoritmaları: Karınca kolonisi optimizasyonu (Ant Colony Optimization, ACO) Popülasyon optimizasyon algoritmaları: Karınca kolonisi optimizasyonu (Ant Colony Optimization, ACO)
Bu sefer karınca kolonisi optimizasyonu algoritmasını analiz edeceğiz. Bu algoritma çok ilginç ve karmaşıktır. Makalede, yeni bir ACO türü oluşturma girişiminde bulunacağız.