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

Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 17): İnternetteki verilere erişme (III)

MetaTrader 5Örnekler | 2 Haziran 2023, 16:35
316 0
Daniel Jose
Daniel Jose

Giriş

Bir önceki "Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 16): İnternetteki verilere erişme (II)” makalesinde, Uzman Danışmanda kullanılmak üzere web üzerinden veri yakalama sürecindeki sorunlardan bahsettik ve bu sorunlar için her birinin artıları ve eksileri olan üç olası çözümü tartıştık.

Doğrudan Uzman Danışman aracılığıyla veri yakalama olan ilk çözümde, uzak sunucunun yavaş yanıt vermesi durumunda oluşabilecek sorundan ve bunun ticaret sistemi üzerinde yaratabileceği sonuçlardan bahsettik.

İkinci çözümde, Uzman Danışmanın istemci, komut dosyasının sunucu ve nesnenin de kanal olarak görev yaptığı istemci-sunucu modeline dayalı bir kanal uyguladık. Bu model, zaman dilimini değiştirmeye karar verdiğimiz ana kadar iyi performans göstermektedir, ancak o noktada uğraştırıcı olmaktadır. Bu gerçeğe rağmen, sunulan en iyi sistemdir, çünkü istemci-sunucu modelinin kullanılması, Uzman Danışmanın uzak sunucuyu beklememesine olanak sağlar. Uzman Danışman, bilginin nereden geldiğine bakılmaksızın nesnede bulunan verileri okuyacaktır.

Üçüncü ve son çözümde, bir hizmet kullanarak istemci-sunucu sistemini iyileştirdik. Böylece, üzerinde oldukça az çalışılmış olan bir MetaTrader 5 platform özelliğini kullanmaya başladık: terminalin global değişkenleri. Bu çözüm, komut dosyaları kullanan modelin en büyük dezavantajı olan zaman dilimini değiştirme sorununu çözdü. Ancak şimdi yeni bir sorunumuz var: terminalin global değişkenler sistemi sadece double türünün kullanımına izin vermektedir. Birçok kişi bundan nasıl kaçınılacağını bilmemektedir ve bu nedenle MetaTrader 5 tarafından sağlanan kanal aracılığıyla bir metin parçası gibi çeşitli bilgileri iletmektedirler.

Bu makalede, bu sınırlamayı nasıl aşacağımızı göreceğiz. Ancak mucizeler beklemeyin, çünkü sistemin istediğiniz şekilde çalışmasını sağlamak çok fazla çalışma gerektirecektir.

Hadi işe koyulalım, bu kez alternatif bir sistem geliştireceğiz.


1. Planlama

Bildiğimiz üzere, MetaTrader 5 tarafından sağlanan kanal sisteminde yalnızca double türü değişkenleri kullanabiliyoruz. Bu tür 8 bayttan oluşmaktadır. Bunun çok faydalı bir bilgi olmadığını düşünebilirsiniz. Şuna değinelim:

Birçok kişi bu kavramı unutmuş olsa da bilgisayar sistemleri baytlarla çalışır. Bu konuyu anlamak önemli ve gereklidir. Her bayt ise 8 bitten oluşur. 1 bit, bir bilgisayar sisteminde mümkün olan en küçük sayıdır. Dilde bulunan en küçük ve en basit tür, tek bitten oluşan boolean türüdür. Bu, temellerin en basitidir.

Dolayısıyla, ne kadar karmaşık olursa olsun, herhangi bir bilgi 1 bayt içerisinde yer alacaktır. Yine, bilgi ne kadar karmaşık olursa olsun, her zaman 8 bitten oluşan 1 bayt içerisinde olacaktır. 2 baytı birleştirdiğimizde sistemdeki ilk bileşik kümeyi elde ederiz. İlk küme WORD, ikinci küme 2 WORD olacak şekilde DWORD ve üçüncü küme de 2 DWORD olacak şekilde QWORD olarak bilinir. Bu, tüm modern dillerin ana dili olan assembly dilinde kullanılan terminolojidir, bu nedenle çoğu sistem aynı türleri kullanır. Tek fark bu türlerin nasıl adlandırıldığıdır.

Umarım bu noktaya kadar olan mantığı takip edebilmişsinizdir. Yeni başlayanlar için işleri kolaylaştırmak adına aşağıdaki görüntülere bir göz atalım:

          

                         

Yukarıdaki görüntüler şu anda mevcut olan ana türleri göstermektedir, bunlar 1 ile 64 bit arasını kapsamaktadır. "Bu açıklamaya neden ihtiyacım var?" diye düşünüyor olabilirsiniz. Bu bilgiyi bilmek, bu makale boyunca ne yapacağımızı anlamak için önemlidir, çünkü farklı iç özelliklere sahip bilgileri aktarabilmek için bu türleri kullanacağız.

Bu türlerin her biri kullanılan dile bağlı olarak farklı adlar alabilir, MQL5 söz konusu olduğunda aşağıdaki tabloda gösterilmektedir:

Ad Bayt sayısı Assembly diline dayalı ad (yukarıdaki görüntüler) 
bool   Sadece 1 bit kullanır; bir bayt 8 bool değerine sahip olabilir  Sadece 1 bit kullanır; bir bayt 8 bool değerine sahip olabilir
char 1
 Byte
short 2  Word
int  4  DWord
long 8  QWord

Bu tablo işaretli tamsayıları kapsamaktadır, MQL5'te daha fazla ayrıntı için tamsayı türlerine bakın, diğer adlar orada tanımlanmaktadır. Reel türler ise tamsayı türleriyle bazı benzerliklere sahiptir, ancak kendi iç formatları vardır. Bir örneği doubledır. Reel türler aşağıdaki tabloda gösterilmektedir:

Ad Bayt sayısı Assembly diline dayalı ad (yukarıdaki görüntüler) 
float 4  DWord
double 8  QWord

Dikkat edilmesi gereken ilginç bir nokta, hem reel hem de tamsayı modellerinin aynı veritabanını ancak farklı uzunluklarda kullanmasıdır. Şimdi asıl ilgilendiğimiz noktaya geldik. Mantığı anlarsanız, sonunda aşağıdaki görüntüde görülebilen sonuca varabilirsiniz:

QWORD 8 bayttır, dolayısıyla double, 8 bayt bilgiyi koymaya olanak sağlar. Örneğin, 8 yazdırılabilir karakteri bir terminal global değişkenine koyabilirsiniz ve aşağıda gösterildiği gibi hizmet ile Uzman Danışman arasındaki iletişimin sonucunu elde edersiniz.

Buradaki fikrin anlaşıldığını düşünüyorum. Önemli ayrıntı şu ki, mesaj 8'den fazla yazdırılabilir karaktere sahipse, parçalara bölünmesi gerekecektir. Ancak bilginin çok hızlı bir şekilde, yani 1 döngü içerisinde iletilmesi gerekiyorsa, mesajı bir döngüde iletmek için gerektiği kadar global terminal değişkeni kullanmamız gerekecektir. Daha sonra orijinal mesajı elde etmek için uygun şekilde birleştirilmeleri gerekir. Ancak paketler halinde iletilebiliyorsa, sunucu için bir form oluşturmamız gerekecektir, böylece hizmet, bu durumda Uzman Danışman olan istemcinin mesajı okuyacağını ve bir sonraki bloğu bekleyeceğini bilir.

Bu tür bir sorunun birkaç çözümü vardır. Bu çözümleri anlamak veya uygulamak istiyorsanız, her şeyi sıfırdan oluşturmanız gerekmez - TCP/IP veya UDP gibi ağ iletişim protokollerindekiyle aynı modellemeyi kullanabilir ve global terminal değişkenleriyle fikri bilgi aktarım sistemine uyarlayabilirsiniz. Protokollerin nasıl çalıştığını anladığınızda, bu görev artık karmaşık olmaktan çıkacak, kullandığınız dile ilişkin beceri ve bilgi meselesi haline gelecektir. Bu, ele alınması gereken her tür durum ve sorun için ayrı ayrı çalışmayı hak eden çok geniş bir konudur.


2. Uygulama

Artık kullanacağımız fikri anladığımıza göre, sistemin hizmet ve Uzman Danışman arasında nasıl bilgi aktaracağını test etmek için bir ilk uygulama yapabiliriz. Ancak yalnızca yazdırılabilir karakterleri ileteceğiz.

2.1. Temel model

Bir önceki makaledeki sistemi kullanacağız ve header dosyasından başlayarak dosyaları düzenleyeceğiz. Yeni içeriği aşağıdaki kodda tam olarak gösterilmektedir:

//+------------------------------------------------------------------+
#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#define def_GlobalNameChannel   "InnerChannel"
//+------------------------------------------------------------------+
union uDataServer
{
        double  value;
        char    Info[sizeof(double)];
};
//+------------------------------------------------------------------+

Bu header temeldir. Global terminal değerinin bildirimini içermektedir. Ayrıca yeni bir yapıya, bir birliğe sahiptir. Birliğin yapıdan farkı, yapının serpiştirme olmadan verilerin kombinasyonu olması, birleştirmenin ise daha küçük veriler daha büyük verilerin içerisinde olacak şekilde her zaman serpiştirmeyi kullanmasıdır. Yukarıdaki durumda, içerisinde 8 bayt bulunan bir double türü değere sahibiz. Ancak sizeof türünde uzunluk yakalamak için bir sistem kullandığıma dikkat edin, böylece gelecekte daha büyük bir double türü değere sahip olursak, ki bu pek olası değildir, bu kod otomatik olarak ona uyum sağlayacaktır.

Sonuç olarak, aşağıdakini elde edeceğiz:

Bunun yukarıdakine benzediğine dikkat edin, ancak birliğin yaptığı da budur.

Düzenlenecek bir sonraki kod, istemciye karşılık gelen Uzman Danışmandır. Kodun tamamı aşağıdan görülebilir:

#property copyright "Daniel Jose"
#property description "Testing internal channel\nvia terminal global variable"
#property version "1.04"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
int OnInit()
{
        EventSetTimer(1);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        uDataServer loc;
        
        if (GlobalVariableCheck(def_GlobalNameChannel))
        {
                GlobalVariableGet(def_GlobalNameChannel, loc.value);
                Print(CharArrayToString(loc.Info, 0, sizeof(uDataServer)));
        }
}
//+------------------------------------------------------------------+

Burada, uchar dizisini dizgeye dönüştürmek için CharArrayToString fonksiyonunu kullandığımıza dikkat edin. Ancak, terminalin global değişkeninden alınabilecek tek olası değer olduğu için hala double türü değer aldığımızı unutmayın. Bunun aksine, MQL5'teki dizge C/C++’takiyle aynı prensipleri izler, dolayısıyla kendi karakterimizi oluşturmak dışında herhangi bir karakter kullanamayız. Ama bu başka bir hikaye. Burada, bunun nasıl yapılacağına ilişkin ayrıntılara girmeyeceğiz: 8 bayt sınırını aşmak için modelleme veri sıkıştırması kullanmak isteyebilirsiniz.

Ancak yine de sunucu görevi görecek bir programa ihtiyacımız vardır. Bizim durumumuzda sunucu bir hizmettir. Sistemi test etmek için gerekli kod aşağıdadır:

//+------------------------------------------------------------------+
#property service
#property copyright "Daniel Jose"
#property version   "1.03"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
void OnStart()
{
        uDataServer loc;
        char car = 33;
        
        while (!IsStopped())
        {
                if (!GlobalVariableCheck(def_GlobalNameChannel)) GlobalVariableTemp(def_GlobalNameChannel);
                for (char c0 = 0; c0 < sizeof(uDataServer); c0++)
                {
                        loc.Info[c0] = car;
                        car = (car >= 127 ? 33 : car + 1);
                }
                GlobalVariableSet(def_GlobalNameChannel, loc.value);
                Sleep(1000);
        }
}
//+------------------------------------------------------------------+

Oldukça basit ama son derece etkili ve işlevseldir.

Programı platformda başlatarak aşağıdaki sonucu elde ediyoruz:


Aptalca ve anlamsız görünebilir, ancak biraz yaratıcılıkla birileri bu sistemi yeterince kullanışlı hale getirebilir ve başkalarının hayal bile edemeyeceği şeyleri yapmasına olanak sağlayabilir.

Bunu daha iyi ifade etmek adına, sistemde değişiklik yaparak merak ve ilgi uyandıracak çok basit bir şey gösterelim. Böyle bir iletişim sistemi için ne tür bir egzotik işlevselliğin bulunabileceğini bir düşünün.


2.2. Etiket değişimi

Etiket değişimi, istemci ile sunucu arasında bilgi alışverişidir; burada sunucu istemcinin hangi bilgiyi almak istediğini bilir ve böylece sunucu bu bilgiyi üretmeye veya aramaya başlayabilir.

Konsepti anlamak oldukça basittir. Ancak, özellikle yalnızca 8 baytın mevcut olduğu veri modelleme söz konusu olduğunda ve kanaldaki tüm bilgileri aktarmamız gerektiğinde, uygulanması oldukça zor olabilir.

2.2.1. İstemci-sunucu iletişimi testi

Aşağıda tam haliyle görülen hizmetin koduna bir göz atalım:

#property service
#property copyright "Daniel Jose"
#property version   "1.03"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
void OnStart()
{
        uDataServer loc, loc1, loc2;
        char car = 33;
        
        while (!IsStopped())
        {
                if (!GlobalVariableCheck(def_GlobalValueInChannel))
                {
                        GlobalVariableTemp(def_GlobalValueInChannel);
                        GlobalVariableTemp(def_GlobalMaskInfo);
                        GlobalVariableTemp(def_GlobalPositionInfos);
                }
                for (char c0 = 0; c0 < sizeof(uDataServer); c0++)
                {
                        loc.Info[c0] = car;
                        car = (car >= 127 ? 33 : car + 1);
                }
                GlobalVariableSet(def_GlobalValueInChannel, loc.value);
                GlobalVariableGet(def_GlobalMaskInfo, loc1.value);
                GlobalVariableGet(def_GlobalPositionInfos, loc2.value);
                Print(CharArrayToString(loc1.Info, 0, sizeof(uDataServer)), "   ",loc2.Position[0], "    ", loc2.Position[1]);
                Sleep(1000);
        }
}
//+------------------------------------------------------------------+

Yeni hizmet (sunucu) kodundaki bazı kısımlara dikkat edin. Şimdi bir yerine üç değişkene sahibiz. İstemci (bu durumda Uzman Danışman) ve sunucu (bu durumda hizmet) arasında iletişime olanak sağlayacak yeterince büyük bir kanal oluşturmak için çalışırlar. Şu satıra dikkat edin:

Print(CharArrayToString(loc1.Info, 0, sizeof(uDataServer)), "   ",loc2.Position[0], "    ", loc2.Position[1]);

Bunlar istemci tarafından yayınlanan verilerdir. 3 farklı bilgiyi aktarmak için 2 değişken kullandığımızı görüyoruz. Ama bu nasıl mümkün olabilir? Bunu anlamak için, aşağıda tam haliyle gösterilen header koduna bakmamız gerekiyor.

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#define def_GlobalValueInChannel        "Inner Channel"
#define def_GlobalMaskInfo                      "Mask Info"
#define def_GlobalPositionInfos         "Positions Infos"
//+------------------------------------------------------------------+
union uDataServer
{
        double  value;
        uint    Position[2];
        char    Info[sizeof(double)];
};
//+------------------------------------------------------------------+

Bu birlik içerisindeki her bir değişkenin diğerinden izole olduğunu düşünebilirsiniz. Bu makalenin başına gitmenizi tavsiye ediyorum, çünkü farklı adlara sahip değişkenlerimiz olmasına rağmen, onlar burada 8 bayt genişliğinde tek bir değişken olarak ele alınmaktadır. Daha net hale getirmek için, neler olduğunu doğru bir şekilde yansıtan aşağıdaki görüntüye bir göz atalım:

Bu şema uDataServer'da ne olduğunu göstermektedir.

Size çok karmaşık geliyorsa, programlamada çok faydalı olduklarından gerçekte nasıl çalıştıklarını anlamak için birliklerle denemeler yapmanızı tavsiye ederim.

Şimdi sisteme geri dönelim. Yapılması gereken bir sonraki şey, istemci - Uzman Danışman - için kod oluşturmaktır. Aşağıdan tam haliyle görülebilir:

#property copyright "Daniel Jose"
#property description "Testing internal channel\nvia terminal global variable"
#property version "1.04"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
enum eWhat {DOW_JONES, SP500};
input eWhat     user01 = DOW_JONES;     //Search
//+------------------------------------------------------------------+
int OnInit()
{
        EventSetTimer(1);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        uDataServer loc;
        
        SetFind();
        if (GlobalVariableCheck(def_GlobalValueInChannel))
        {
                GlobalVariableGet(def_GlobalMaskInfo, loc.value);
                Print(CharArrayToString(loc.Info, 0, sizeof(uDataServer)), "  ", GlobalVariableGet(def_GlobalValueInChannel));
        }
}
//+------------------------------------------------------------------+
inline void SetFind(void)
{
        static int b = -1;
        uDataServer loc1, loc2;
        
        if ((GlobalVariableCheck(def_GlobalValueInChannel)) && (b != user01))
        {
                b = user01;
                switch (user01)
                {
                        case DOW_JONES  :
                                StringToCharArray("INDU:IND", loc1.Info, 0, sizeof(uDataServer));
                                loc2.Position[0] = 172783;
                                loc2.Position[1] = 173474;
                                break;
                        case SP500              :
                                StringToCharArray("SPX:IND", loc1.Info, 0, sizeof(uDataServer));
                                loc2.Position[0] = 175484;
                                loc2.Position[1] = 176156;
                                break;
                }
                GlobalVariableSet(def_GlobalMaskInfo, loc1.value);
                GlobalVariableSet(def_GlobalPositionInfos, loc2.value);
        }
};
//+------------------------------------------------------------------+

Bu Uzman Danışmanda bilgi ilettiğimizi ve aldığımızı, yani hizmetin nasıl çalışması gerektiğini kontrol edebileceğimizi unutmayın. Bir değişkende, hizmetin ne araması gerektiğini belirten küçük bir dizge, diğerinde ise 2 adres noktası iletiyoruz.

Yanıt olarak hizmet bilgi geri döndürecektir. Ancak bu ilk noktayı anlamak için aşağıdaki videoda gösterilen sonuca bakalım:



2.2.2. Pratik bir versiyon oluşturma

Artık sistemin nasıl çalıştığını gördüğümüze göre, gerçekten işlevsel bir şey yapabiliriz. Bu kez web sunucusundan bilgiler toplayacağız. Ancak bunun için, neler olup bittiğinin iyi bir şekilde anlaşılmasını sağlayacak birkaç değişiklik yapmamız gerekiyor. Bazen, aslında analizde çöp kullanmamıza rağmen güncellenmiş veriler aldığımızı zannedebiliriz. Kendinizi böyle bir riske maruz bırakmamak adına programlama aşamasında çok dikkatli olmalısınız. Bu yüzden mümkün olduğu kadar çok test ekleyin ve sistemin çalışırken tespit edebileceği herhangi bir garip etkinliği rapor etmesini sağlayın.

Unutmayın: Bilgi, yalnızca ona güvenirseniz sizin için yararlı olacaktır.

İlk olarak, header dosyasını şu şekilde düzenleyelim:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#define def_GlobalValueInChannel        "Inner Channel"
#define def_GlobalMaskInfo              "Mask Info"
#define def_GlobalPositionInfos         "Positions Infos"
//+------------------------------------------------------------------+
#define def_MSG_FailedConnection        "BAD"
#define def_MSG_FailedReturn            "FAILED"
#define def_MSG_FailedMask              "ERROR"
#define def_MSG_FinishServer            "FINISH"
//+------------------------------------------------------------------+
union uDataServer
{
        double  value;
        uint            Position[2];
        char            Info[sizeof(double)];
};
//+------------------------------------------------------------------+

Vurgulanan kısımlar, bazı garip faaliyetleri bildirmek için kullanacağımız kodlardır. En fazla 8 karakter kullanmalısınız, ancak aynı zamanda piyasa tarafından meydana getirilmesi pek muhtemel olmayan bir sekans oluşturmalısınız ki bu da kolay bir şey değildir. Her şey yolunda görünse bile, piyasanın sunucu hata mesajları olarak kullanacağınız sekansla eşleşen bir değer üretme riski her zaman vardır. Sadece bu amaç için bir terminal global değişkeni de kullanabilirsiniz, bu da olası kombinasyonların sayısını artıracak ve böylece çok daha fazlasını iletebileceksiniz. Ancak mümkün olduğunca az global terminal değişkeni kullanmak istedim. Bununla birlikte, gerçek bir durumda, bu konu hakkında düşünürdüm ve muhtemelen sadece hataların veya anormal faaliyetlerin belirtilmesi ve raporlanması için bir değişken kullanırdım.

Bir sonraki kod, Uzman Danışmanın tam kodudur.

#property copyright "Daniel Jose"
#property description "Testing internal channel\nvia terminal global variable"
#property version "1.04"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
enum eWhat {DOW_JONES, SP500};
input eWhat     user01 = DOW_JONES;             //Search
//+------------------------------------------------------------------+
int OnInit()
{
        EventSetTimer(1);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        ClientServer();
}
//+------------------------------------------------------------------+
inline void ClientServer(void)
{
        uDataServer loc1, loc2;
        string          sz0;
        
        SetFind();
        if (GlobalVariableCheck(def_GlobalValueInChannel))
        {
                GlobalVariableGet(def_GlobalMaskInfo, loc1.value);
                loc2.value = GlobalVariableGet(def_GlobalValueInChannel);
                sz0 = CharArrayToString(loc2.Info, 0, sizeof(uDataServer));
                if (sz0 == def_MSG_FailedConnection) Print("Failed in connection."); else
                if (sz0 == def_MSG_FailedReturn) Print("Error in Server Web."); else
                if (sz0 == def_MSG_FailedMask) Print("Bad Mask or position."); else
                if (sz0 == def_MSG_FinishServer) Print("Service Stop."); else
                Print(CharArrayToString(loc1.Info, 0, sizeof(uDataServer)), "  ", loc2.value);
        }
}
//+------------------------------------------------------------------+
inline void SetFind(void)
{
        static int b = -1;
        uDataServer loc1, loc2;
        
        if ((GlobalVariableCheck(def_GlobalValueInChannel)) && (b != user01))
        {
                b = user01;
                switch (user01)
                {
                        case DOW_JONES  :
                                StringToCharArray("INDU:IND", loc1.Info, 0, sizeof(uDataServer));
                                loc2.Position[0] = 172783;
                                loc2.Position[1] = 173474;
                                break;
                        case SP500              :
                                StringToCharArray("SPX:IND", loc1.Info, 0, sizeof(uDataServer));
                                loc2.Position[0] = 175487;
                                loc2.Position[1] = 176159;
                                break;
                }
                GlobalVariableSet(def_GlobalMaskInfo, loc1.value);
                GlobalVariableSet(def_GlobalPositionInfos, loc2.value);
        }
};
//+------------------------------------------------------------------+

Vurgulanan satırlar çok önemlidir ve neler olup bittiğini gerçekten bilmek istediğimiz için iyi bir şekilde düşünülmelidir. Gördüğümüz üzere, kullanıcıya header dosyasında oluşturulan sekansların sunduğundan daha fazla ayrıntı anlatabiliriz, böylece çözümü programlamak ve sürdürmek daha kolay olur. Kodun geri kalanı pek değişmedi. Aşağıdaki hizmet koduna bakalım.

#property service
#property copyright "Daniel Jose"
#property version   "1.03"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
void OnStart()
{
        uDataServer loc1, loc2;
        
        while (!IsStopped())
        {
                if (!GlobalVariableCheck(def_GlobalValueInChannel))
                {
                        GlobalVariableTemp(def_GlobalValueInChannel);
                        GlobalVariableTemp(def_GlobalMaskInfo);
                        GlobalVariableTemp(def_GlobalPositionInfos);
                }
                GlobalVariableGet(def_GlobalMaskInfo, loc1.value);
                GlobalVariableGet(def_GlobalPositionInfos, loc2.value);
                if (!_StopFlag)
                {
                        GlobalVariableSet(def_GlobalValueInChannel, GetDataURL(
                                                                                "https://tradingeconomics.com/stocks",
                                                                                100,
                                                                                "<!doctype html>",
                                                                                2,
                                                                                CharArrayToString(loc1.Info, 0, sizeof(uDataServer)),
                                                                                loc2.Position[0],
                                                                                loc2.Position[1],
                                                                                0x0D
                                                                               )
                                        );
                        Sleep(1000);
                }
        }
        GlobalVariableSet(def_GlobalValueInChannel, Codification(def_MSG_FinishServer));
}
//+------------------------------------------------------------------+
double GetDataURL(const string url, const int timeout, const string szTest, int iTest, const string szFind, int iPos, int iInfo, char cLimit)
{
        string          headers, szInfo = "";
        char                    post[], charResultPage[];
        int                     counter;
   
        if (WebRequest("GET", url, NULL, NULL, timeout, post, 0, charResultPage, headers) == -1) return Codification(def_MSG_FailedConnection);
        for (int c0 = 0, c1 = StringLen(szTest); (c0 < c1) && (!_StopFlag); c0++) if (szTest[c0] != charResultPage[iTest + c0]) return Codification(def_MSG_FailedReturn);
        for (int c0 = 0, c1 = StringLen(szFind); (c0 < c1) && (!_StopFlag); c0++) if (szFind[c0] != charResultPage[iPos + c0]) return Codification(def_MSG_FailedMask);
        if (_StopFlag) return Codification(def_MSG_FinishServer);
        for (counter = 0; charResultPage[counter + iInfo] == 0x20; counter++);
        for (;charResultPage[counter + iInfo] != cLimit; counter++) szInfo += CharToString(charResultPage[counter + iInfo]);
        
        return StringToDouble(szInfo);
}
//+------------------------------------------------------------------+
inline double Codification(const string arg)
{
        uDataServer loc;
        StringToCharArray(arg, loc.Info, 0, sizeof(uDataServer));
        
        return loc.value;
}
//+------------------------------------------------------------------+

Vurgulanan satır da önemlidir - hizmet artık çalışmadığı konusunda uyarı verecektir.

Böylece, bu sistemi çalıştırdığımızda aşağıdaki sonucu elde edeceğiz:


Sonuç

Umarım MetaTrader 5 platformunda internetteki verileri araştırma, arama ve kullanma fikrini açıklayabilmişimdir. Bu konunun ilk başta, özellikle programlama konusunda kapsamlı bilgisi olmayanlar için çok net olmayabileceğini biliyorum, ancak zamanla, disiplinle üzerinde çalışarak, bu materyalin çoğunda ustalaşacaksınız. Burada bildiklerimin en azından bir kısmını paylaşmaya çalıştım. İlginiz için teşekkür ederim. Bir sonraki makalede görüşmek üzere.

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

Ekli dosyalar |
Servi0o_-_EA.zip (10.71 KB)
Standard Deviation göstergesine dayalı bir ticaret sistemi nasıl geliştirilir? Standard Deviation göstergesine dayalı bir ticaret sistemi nasıl geliştirilir?
MetaTrader 5 işlem platformunda kullanılmak üzere en popüler teknik göstergelere dayalı ticaret sistemleri geliştirdiğimiz serimizin yeni makalesindeyiz. Bu yeni makalede, Standard Deviation göstergesine dayalı bir ticaret sisteminin nasıl tasarlanacağını öğreneceğiz.
Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 16): İnternetteki verilere erişme (II) Sıfırdan bir ticaret Uzman Danışmanı geliştirme (Bölüm 16): İnternetteki verilere erişme (II)
İnternetten Uzman Danışmana verilerin nasıl alınacağı o kadar net değildir. MetaTrader 5'in sunduğu tüm olanakları anlamadan bunu yapabilmek zordur.
Chaikin Oscillator göstergesine dayalı bir ticaret sistemi nasıl geliştirilir? Chaikin Oscillator 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 yeni makalede, Chaikin Oscillator göstergesine dayalı bir ticaret sisteminin nasıl geliştirileceğini öğreneceğiz.
Veri Bilimi ve Makine Öğrenimi (Bölüm 06): Gradyan İniş Veri Bilimi ve Makine Öğrenimi (Bölüm 06): Gradyan İniş
Gradyan iniş, sinir ağlarının ve çeşitli makine öğrenimi algoritmalarının eğitiminde önemli bir rol oynamaktadır - hızlı ve akıllı bir algoritmadır. Etkileyici bir şekilde çalışmasına rağmen, birçok veri bilimci tarafından hala yanlış anlaşılmaktadır. Bu makalemizde onu detaylıca inceleyerek daha iyi anlayacağız.