Çok Sayıda Enstrüman Üzerinde Alım Satım Yapan bir Expert Advisor Oluşturma
Giriş
Tek bir grafik üzerinde başlatılan tek bir Expert Advisor'ın aynı anda farklı finansal varlıklarla işlem yapabilmesi için program kodunu uygulamanın teknik yönü. Genel olarak, bu MQL4'te dahi herhangi bir sorun teşkil etmedi. Ancak yalnızca MetaTrader 5 istemci terminalinin ortaya çıkmasıyla birlikte, yatırımcılar nihayet strateji test cihazlarını kullanarak bu tür otomatların çalışmasına ilişkin tam bir analiz yapma fırsatına sahip oldular.
Bu nedenle, şimdi çok para birimli otomatlar her zamankinden daha popüler hale gelecek; dolayısıyla bu tür alım satım sistemlerinin oluşturulmasına ilginin artmasını tahmin edebiliriz. Fakat bu tür robotların uygulanmasındaki ana sorun, program kodundaki boyutlarının en iyi ihtimalle aritmetik bir ilerlemeyle genişlemesi gerçeğidir ve bunun tipik bir programcı tarafından benimsenmesi kolay değildir.
Bu makalede, yapı kusurlarının yok olmasa da en azından minimum düzeye indirildiği basit bir çok para birimli Expert Advisor yazacağız.
1. Basit bir trend takip sistemini uygulama
Aslında, bir Üçlü Üstel Hareketli Ortalama teknik göstergesinin yerleşik bir terminali temelindeki trendi takip ederek, maksimum düzeyde basit bir alım satım sistemi ile başlayabiliriz. Bu, özel herhangi bir yorum gerektirmeyen ve şimdi program kodunda somutlaştıracağımız çok basit bir algoritmadır.
Ancak her şeyden önce, Expert Advisor hakkında en genel çıkarımları yapmak istiyorum. Bu doğrultuda genel düzeyde bildirilen, gelen Expert Advisor parametreleri bloğuyla başlamanın mantıklı olacağını düşünüyorum.
Bu nedenle, öncelikli olarak birlikte çalışacağımız finansal varlıkları seçmeliyiz. Bu, varlık sembollerinin saklanabileceği satır giriş değişkenleri kullanılarak yapılabilir. Şimdi, her bir finansal varlık için, varlık tarafından alım satım işlemlerini devre dışı bırakmaya izin verecek bir trade ban anahtarına sahip olmak güzel olurdu.
Doğal olarak, her varlık, Zararı Durdur, Kar Al, açık pozisyonun hacmi ve kayma gibi bireysel alım satım parametreleriyle ilişkilendirilmelidir. Ve bariz nedenlerden dolayı, her alım satım çipi için Üçlü Üstel Hareketli Ortalama göstergesinin giriş parametreleri ayrı olmalıdır.
Yalnızca bir çip için giriş değişkenlerinin nihai bir bloğu, bu bağımsız değişkenlere uygun olarak gerçekleştirilir. Kalan bloklar yalnızca Expert Advisor'ın giriş parametrelerinin adlarındaki sayılarla farklılık gösterir. Bu örnekte, ideal olarak bu tür blokların sayısı için herhangi bir yazılım sınırlaması olmamasına rağmen, kendimi yalnızca on iki finansal varlıkla sınırladım.
Yalnızca alım satım yapacak bir şeye ihtiyacımız var! Ve en önemlisi bilgisayarımız bu sorunu çözmek için yeterli kaynağa sahip olmalıdır.
input string Symb0 = "EURUSD"; input bool Trade0 = true; input int Per0 = 15; input ENUM_APPLIED_PRICE ApPrice0 = PRICE_CLOSE; input int StLoss0 = 1000; input int TkProfit0 = 2000; input double Lots0 = 0.1; input int Slippage0 = 30;
Artık genel düzeydeki değişkenleri anladığımıza göre, kodun OnTick() işlevi içinde oluşturulması konusuna geçebiliriz. Buradaki en mantıklı seçenek, alım satım sinyallerini almak için algoritmanın ve Expert Advisor'ın gerçek alım satım bölümünün iki özel işleve ayrılması olacaktır.
Ve Expert Advisor aynı anda on iki finansal varlıkla çalıştığı için, OnTick() bloğu içinde bu işlevlerin on iki çağrısı da olmalıdır.
Doğal olarak, bu işlevlerin ilk giriş parametresi, bu alım satım varlıklarının altında listeleneceği benzersiz bir sayı olmalıdır. Bariz nedenlerden dolayı, ikinci giriş parametresi, alım satım amaçlı finansal varlığın satır adı olacaktır.
Üçüncü parametrenin rolü için, alım satımı işlemini çözmek için mantıksal bir değişken belirleyeceğiz. Ardından, alım satım sinyallerini belirleme algoritması için giriş göstergesi sinyallerini ve alım satım işlevi için bekleyen talimatlara olan mesafeyi, pozisyon hacmini ve kaymayı (açık pozisyon fiyatının izin verilen kayması) takip edeceğiz.
Alım satım sinyallerini bir işlevden diğerine aktarmak için, statik diziler değerlerini bir referans yoluyla türeten işlevin parametreleri olarak ayarlanmalıdır. Bu, OnTick() işlevi için önerilen kodun son sürümüdür.
void OnTick() { //--- declare variables arrays for trade signals static bool UpSignal[12], DnSignal[12], UpStop[12], DnStop[12]; //--- get trade signals TradeSignalCounter( 0, Symb0, Trade0, Per0, ApPrice0, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 1, Symb1, Trade1, Per1, ApPrice1, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 2, Symb2, Trade2, Per2, ApPrice2, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 3, Symb3, Trade3, Per3, ApPrice3, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 4, Symb4, Trade4, Per4, ApPrice4, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 5, Symb5, Trade5, Per5, ApPrice5, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 6, Symb6, Trade6, Per6, ApPrice6, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 7, Symb7, Trade7, Per7, ApPrice7, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 8, Symb8, Trade8, Per8, ApPrice8, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter( 9, Symb9, Trade9, Per9, ApPrice9, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter(10, Symb10, Trade10, Per10, ApPrice10, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter(11, Symb11, Trade11, Per11, ApPrice11, UpSignal, DnSignal, UpStop, DnStop); //--- perform trade operations TradePerformer( 0, Symb0, Trade0, StLoss0, TkProfit0, Lots0, Slippage0, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 1, Symb1, Trade1, StLoss1, TkProfit1, Lots1, Slippage1, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 2, Symb2, Trade2, StLoss2, TkProfit2, Lots2, Slippage2, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 3, Symb3, Trade3, StLoss3, TkProfit3, Lots3, Slippage3, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 4, Symb4, Trade4, StLoss4, TkProfit4, Lots4, Slippage4, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 5, Symb5, Trade5, StLoss5, TkProfit5, Lots5, Slippage5, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 6, Symb6, Trade6, StLoss6, TkProfit6, Lots6, Slippage6, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 7, Symb7, Trade7, StLoss7, TkProfit7, Lots7, Slippage7, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 8, Symb8, Trade8, StLoss8, TkProfit8, Lots8, Slippage8, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 9, Symb9, Trade9, StLoss9, TkProfit9, Lots9, Slippage9, UpSignal, DnSignal, UpStop, DnStop); TradePerformer(10, Symb10, Trade10, StLoss10, TkProfit10, Lots10, Slippage10, UpSignal, DnSignal, UpStop, DnStop); TradePerformer(11, Symb11, Trade11, StLoss11, TkProfit11, Lots11, Slippage11, UpSignal, DnSignal, UpStop, DnStop); //--- }
TradeSignalCounter() işlevinin içinde, yalnızca, alım satım sinyallerini hesaplamak için her çipin başlangıcında bir kez ve daha sonra çubuğun her değişiminde Üçlü Üstel Hareketli Ortalama teknik göstergesinin tanıtıcısını elde etmek gerekir.
Koddaki uygulama ile bu nispeten basit şema, küçük ayrıntılarla dolup taşmaya başlar.
bool TradeSignalCounter(int Number, string Symbol_, bool Trade, int period, ENUM_APPLIED_PRICE ApPrice, bool &UpSignal[], bool &DnSignal[], bool &UpStop[], bool &DnStop[]) { //--- check if trade is prohibited if(!Trade)return(true); //--- declare variable to store final size of variables arrays static int Size_=0; //--- declare array to store handles of indicators as static variable static int Handle[]; static int Recount[],MinBars[]; double TEMA[4],dtema1,dtema2; //--- initialization if(Number+1>Size_) // Entering the initialization block only on first start { Size_=Number+1; // For this number entering the block is prohibited //--- change size of variables arrays ArrayResize(Handle,Size_); ArrayResize(Recount,Size_); ArrayResize(MinBars,Size_); //--- determine minimum number of bars, sufficient for calculation MinBars[Number]=3*period; //--- setting array elements to 0 DnSignal[Number] = false; UpSignal[Number] = false; DnStop [Number] = false; UpStop [Number] = false; //--- use array as timeseries ArraySetAsSeries(TEMA,true); //--- get indicator's handle Handle[Number]=iTEMA(Symbol_,0,period,0,ApPrice); } //--- check if number of bars is sufficient for calculation if(Bars(Symbol_,0)<MinBars[Number])return(true); //--- get trade signals if(IsNewBar(Number,Symbol_,0) || Recount[Number]) // Entering the block on bar change or on failed copying of data { DnSignal[Number] = false; UpSignal[Number] = false; DnStop [Number] = false; UpStop [Number] = false; //--- using indicator's handles, copy values of indicator's //--- buffers into static array, specially prepared for this purpose if(CopyBuffer(Handle[Number],0,0,4,TEMA)<0) { Recount[Number]=true; // As data were not received, we should return // into this block (where trade signals are received) on next tick! return(false); // Exiting the TradeSignalCounter() function without receiving trade signals } //--- all copy operations from indicator buffer are successfully completed Recount[Number]=false; // We may not return to this block until next change of bar int Digits_ = int(SymbolInfoInteger(Symbol_,SYMBOL_DIGITS)+4); dtema2 = NormalizeDouble(TEMA[2] - TEMA[3], Digits_); dtema1 = NormalizeDouble(TEMA[1] - TEMA[2], Digits_); //---- determining the input signals if(dtema2 > 0 && dtema1 < 0) DnSignal[Number] = true; if(dtema2 < 0 && dtema1 > 0) UpSignal[Number] = true; //---- determining the output signals if(dtema1 > 0) DnStop[Number] = true; if(dtema1 < 0) UpStop[Number] = true; } //----+ return(true); }
Bu açıdan, TradePerformer() işlevinin kodunun oldukça basit olduğu ortaya çıkıyor:
bool TradePerformer(int Number, string Symbol_, bool Trade, int StLoss, int TkProfit, double Lots, int Slippage, bool &UpSignal[], bool &DnSignal[], bool &UpStop[], bool &DnStop[]) { //--- check if trade is prohibited if(!Trade)return(true); //--- close opened positions if(UpStop[Number])BuyPositionClose(Symbol_,Slippage); if(DnStop[Number])SellPositionClose(Symbol_,Slippage); //--- open new positions if(UpSignal[Number]) if(BuyPositionOpen(Symbol_,Slippage,Lots,StLoss,TkProfit)) UpSignal[Number]=false; //This trade signal will be no more on this bar! //--- if(DnSignal[Number]) if(SellPositionOpen(Symbol_,Slippage,Lots,StLoss,TkProfit)) DnSignal[Number]=false; //This trade signal will be no more on this bar! //--- return(true); }Ancak bunun tek nedeni, alım satım işlemlerinin gerçekleştirilmesi için gerçek komutların dört ek işlevde toplanmış olmasıdır:
BuyPositionClose(); SellPositionClose(); BuyPositionOpen(); SellPositionOpen();
Dört işlevin tümü tamamen benzer şekilde çalışır; bu nedenle kendimizi bunlardan yalnızca birinin incelenmesiyle sınırlayabiliriz:
bool BuyPositionClose(const string symbol,ulong deviation) { //--- declare structures of trade request and result of trade request MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); ZeroMemory(result); //--- check if there is BUY position if(PositionSelect(symbol)) { if(PositionGetInteger(POSITION_TYPE)!=POSITION_TYPE_BUY) return(false); } else return(false); //--- initializing structure of the MqlTradeRequest to close BUY position request.type = ORDER_TYPE_SELL; request.price = SymbolInfoDouble(symbol, SYMBOL_BID); request.action = TRADE_ACTION_DEAL; request.symbol = symbol; request.volume = PositionGetDouble(POSITION_VOLUME); request.sl = 0.0; request.tp = 0.0; request.deviation=(deviation==ULONG_MAX) ? deviation : deviation; request.type_filling=ORDER_FILLING_FOK; //--- string word=""; StringConcatenate(word, "<<< ============ BuyPositionClose(): Close Buy position at ", symbol," ============ >>>"); Print(word); //--- send order to close position to trade server if(!OrderSend(request,result)) { Print(ResultRetcodeDescription(result.retcode)); return(false); } //----+ return(true); }
Temel olarak, bu hemen hemen tüm çok para birimli Expert Advisor'lardır (Exp_TEMA.mq5)!
Göz önünde bulundurulan işlevlerin yanı sıra, bu, iki ek kullanıcı işlevi içerir:
bool IsNewBar(int Number, string symbol, ENUM_TIMEFRAMES timeframe); string ResultRetcodeDescription(int retcode);
Bu işlevlerden ilki, seçilen sembol ve zaman dilimine göre çubuk değişikliği anında true değerini döndürür ve ikincisi, alım satım talebi yapısının alan retcode'undan türetilen alım satım işleminin sonuç koduyla satırı döndürür MqlTradeResult.
Expert Advisor hazır, şimdi teste başlama zamanı! Çok para birimli Expert Advisor testinde, diğer tek para birimli Expert Advisor'ından gözle görülür ciddi bir fark yoktur.
Strateji Test Cihazının "Parametreler" sekmesindeki yapılandırmaları belirleyin:
Şekil 1. Strateji test cihazının "Ayarlar" sekmesi
Gerekirse, "Giriş parametreleri" sekmesindeki giriş parametrelerinin değerlerini ayarlayın:
Şekil 2. Strateji test cihazının "Parametreler" sekmesi
ve ardından "Ayarlar" sekmesindeki Strateji Test Cihazında "Başlat" düğmesine tıklayın:
Şekil 3. Expert Advisor testini çalıştırma
Expert Advisor'ın ilk testinin geçme süresinin, on iki sembolün tümü için geçmişin yüklenmesi nedeniyle çok önemli olduğu ortaya çıkıyor. Strateji test cihazında testi tamamladıktan sonra "Sonuçlar" sekmesini açın:
Şekil 4. Test sonuçları
ve "Grafik" sekmesinin içeriğini kullanarak verilerin bir analizini yapın:
Şekil 5. Denge dinamikleri ve hisse senedi tablosu
ve "Günlük":
Şekil 6. Strateji test cihazı Günlüğü
Doğal olarak, algoritmanın bu Expert Advisor piyasasına giriş ve çıkışlarının özü çok basittir ve ilk rastgele parametreleri kullanırken çok anlamlı sonuçlar beklemek saflık olur. Ancak buradaki amacımız, çok para birimli bir Expert Advisor oluşturmanın temel fikrini mümkün olan en basit şekilde göstermektir.
Bu Expert Advisor'ın optimizasyonu ile çok fazla giriş parametresi nedeniyle bazı aksaklıklar ortaya çıkabilir. Optimizasyonun genetik algoritması, bu parametrelerin çok daha küçük bir miktarını gerektirir; bu nedenle Expert Advisor, TradeN giriş parametrelerinin kalan çipleri devre dışı bırakılarak her bir çip üzerinde ayrı ayrı optimize edilmelidir.
Yaklaşımın özü özetlendiğinde, çok para birimli robot için daha ilginç karar verme algoritmasıyla çalışmaya başlayabilirsiniz.
2. Finansal piyasalardaki rezonanslar ve alım satım sistemlerindeki uygulamaları
Genel olarak, farklı finansal varlıklar arasındaki korelasyonları göz önünde bulundurma fikri yeni değildir ve tam olarak bu tür trendlerin analizine dayanan algoritmayı uygulamak ilginç olacaktır. Bu makalede, "Döviz Spekülatörü" (Rusça) 04, 05, 2001 dergisinde yayınlanan Vasily Yakimkin "Rezonanslar - Yeni Bir Teknik Göstergeler Sınıfı" makalesine dayanan çok para birimli bir otomat uygulayacağım.
Özetle bu yaklaşımın özü aşağıdaki gibidir. Örneğin, EUR / USD üzerinde araştırma yapmak için, yalnızca finansal varlığa ilişkin bazı göstergelerin sonuçlarını değil, aynı zamanda EUR/USD varlıkları - EUR/JPY ve USD/JPY ile ilgili aynı göstergenin sonuçlarını da kullanırız. Ölçümlerin ve hesaplamaların basitliği ve kolaylığı için değerleri aynı değişiklik aralığında normalize edilmiş göstergeyi kullanmak en iyisidir.
Bu gereksinimler göz önünde bulundurulduğunda, bu klasik için tamı tamına uyan stokastik göstergedir. Her ne kadar gerçekte, diğer göstergelerin kullanımında herhangi bir fark olmasa da. Trend yönü olarak, stokastik Stoka değeri ile İşaret sinyal çizgisi arasındaki fark işaretini dikkate alacağız.
Şekil 7. Trend yönünü belirleme
dStoh değişken sembolü için, mevcut trendin yönü için olası kombinasyonların ve yorumlarının tam bir tablosu vardır:
Şekil 8. dStoh değişken sembolü ve trend yönü kombinasyonları
EUR / JPY ve USD / JPY varlıklarının iki sinyalinin zıt değerlere sahip olduğu bir durumda, toplamlarını belirlemeliyiz; bu toplam sıfırdan büyükse her iki sinyali de pozitif, aksi takdirde negatif olarak kabul edin.
Bu nedenle, Uzun Pozisyonları açmak için, trendin büyüdüğü durumu kullanın ve çıkış yapmak için düşüş trendi veya ana varlık EUR / USD göstergesinin sinyallerinin negatif olduğu bir trend kullanın. Ayrıca, ana varlıkta sinyal yoksa ve kalan varlıklar için dStoh değişkeninin toplamı sıfırdan küçükse uzun pozisyondan çıkın. Kısa pozisyonlar için her şey kesinlikle benzerdir yalnızca durum tam tersidir.
En rasyonel çözüm, Expert Advisor'ın tüm analitik kısmını çoklu para birimi göstergesine yerleştirmek ve gösterge arabelleklerinden Expert Advisor için yalnızca alım satım kontrolü için hazır sinyalleri almak olacaktır. Bu gösterge türünün sürümü, piyasa koşullarının görsel bir analizini sağlayan MultiStochastic.mq5 göstergesi tarafından sunulur.
Şekil 9. Çoklu Stokastik Gösterge
Yeşil çubuk, sırasıyla uzun pozisyonların ve kırmızı çubuklar kısa pozisyonların açılmasını ve tutulmasını işaret eder. Grafiğin üst kenarındaki pembe ve açık yeşil noktalar, uzun ve kısa pozisyonlardan çıkan sinyalleri temsil etmektedir.
Bu gösterge, Expert Advisor'da doğrudan sinyal almak için kullanılabilir fakat yine de işini kolaylaştırmak ve tüm gereksiz arabellekleri ve görselleştirme öğelerini kaldırmak daha iyi olacaktır; bu şekilde yalnızca alım satım sinyallerinin sağlanmasında doğrudan ilgili olanlar kalır. MultiStochastic_Exp.mq5 göstergesinde yapılan tam olarak budur.
Bu Expert Advisor'da yalnızca üç çip ile alım satım işlemi yaptım; bu nedenle OnTick() işlevinin kodu son derece basit hale geldi:
void OnTick() { //--- declare variables arrays for trade signals static bool UpSignal[], DnSignal[], UpStop[], DnStop[]; //--- get trade signals TradeSignalCounter(0, Trade0, Kperiod0, Dperiod0, slowing0, ma_method0, price_0, SymbolA0, SymbolB0, SymbolC0, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter(1, Trade1, Kperiod1, Dperiod1, slowing1, ma_method1, price_1, SymbolA1, SymbolB1, SymbolC1, UpSignal, DnSignal, UpStop, DnStop); TradeSignalCounter(2, Trade2, Kperiod2, Dperiod2, slowing2, ma_method2, price_2, SymbolA2, SymbolB2, SymbolC2, UpSignal, DnSignal, UpStop, DnStop); //--- perform trade operations TradePerformer( 0, SymbolA0, Trade0, StopLoss0, 0, Lots0, Slippage0, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 1, SymbolA1, Trade1, StopLoss1, 0, Lots1, Slippage1, UpSignal, DnSignal, UpStop, DnStop); TradePerformer( 2, SymbolA2, Trade2, StopLoss2, 0, Lots2, Slippage2, UpSignal, DnSignal, UpStop, DnStop); //--- }
Ancak, TradeSignalCounter() işlevinin kodu biraz daha karmaşıktır: Gerçek şu ki, çok para birimli gösterge, farklı finansal varlıkların üç zaman serisiyle doğrudan çalışır; bu nedenle, Rates_Total() işlevini kullanarak üç zaman serisinden birinde minimum sayıda yeterlilikleri için çubukların daha güç algılanan bir doğrulamasını uyguluyoruz.
Ayrıca, tüm zaman serilerinde aynı anda bir çubuk değişikliğinin meydana geldiği anın belirlenmesinin doğruluğunu garanti etmek için SynchroCheck() işlevi kullanılarak zaman serilerinin senkronizasyonuna ilişkin ek bir doğrulama yapılır.
bool TradeSignalCounter(int Number, bool Trade, int Kperiod, int Dperiod, int slowing, ENUM_MA_METHOD ma_method, ENUM_STO_PRICE price_, string SymbolA, string SymbolB, string SymbolC, bool &UpSignal[], bool &DnSignal[], bool &UpStop[], bool &DnStop[]) { //--- check if trade is prohibited if(!Trade)return(true); //--- declare variable to store sizes of variables arrays static int Size_=0; //--- declare arrays to store handles of indicators as static variables static int Handle[]; static int Recount[],MinBars[]; //--- double dUpSignal_[1],dDnSignal_[1],dUpStop_[1],dDnStop_[1]; //--- change size of variables arrays if(Number+1>Size_) { uint size=Number+1; //---- if(ArrayResize(Handle,size)==-1 || ArrayResize(Recount,size)==-1 || ArrayResize(UpSignal, size) == -1 || ArrayResize(DnSignal, size) == -1 || ArrayResize(UpStop, size) == -1 || ArrayResize(DnStop, size) == -1 || ArrayResize(MinBars,size) == -1) { string word=""; StringConcatenate(word,"TradeSignalCounter( ",Number, " ): Error!!! Unable to change sizes of variables arrays!!!"); int error=GetLastError(); ResetLastError(); //--- if(error>4000) { StringConcatenate(word,"TradeSignalCounter( ",Number," ): Error code ",error); Print(word); } Size_=-2; return(false); } Size_=int(size); Recount[Number] = false; MinBars[Number] = Kperiod + Dperiod + slowing; //--- get indicator's handle Handle[Number]=iCustom(SymbolA,0,"MultiStochastic_Exp", Kperiod,Dperiod,slowing,ma_method,price_, SymbolA,SymbolB,SymbolC); } //--- check if number of bars is sufficient for calculation if(Rates_Total(SymbolA,SymbolB,SymbolC)<MinBars[Number])return(true); //--- check timeseries synchronization if(!SynchroCheck(SymbolA,SymbolB,SymbolC))return(true); //--- get trade signals if(IsNewBar(Number,SymbolA,0) || Recount[Number]) { DnSignal[Number] = false; UpSignal[Number] = false; DnStop [Number] = false; UpStop [Number] = false; //--- using indicators' handles, copy values of indicator's //--- buffers into static arrays, specially prepared for this purpose if(CopyBuffer(Handle[Number], 1, 1, 1, dDnSignal_) < 0){Recount[Number] = true; return(false);} if(CopyBuffer(Handle[Number], 2, 1, 1, dUpSignal_) < 0){Recount[Number] = true; return(false);} if(CopyBuffer(Handle[Number], 3, 1, 1, dDnStop_ ) < 0){Recount[Number] = true; return(false);} if(CopyBuffer(Handle[Number], 4, 1, 1, dUpStop_ ) < 0){Recount[Number] = true; return(false);} //--- convert obtained values into values of logic variables of trade commands if(dDnSignal_[0] == 300)DnSignal[Number] = true; if(dUpSignal_[0] == 300)UpSignal[Number] = true; if(dDnStop_ [0] == 300)DnStop [Number] = true; if(dUpStop_ [0] == 300)UpStop [Number] = true; //--- all copy operations from indicator's buffers completed successfully //--- unnecessary to return into this block until next bar change Recount[Number]=false; } //----+ return(true); }
Bu Expert Advisor'ın (Exp_ResonanceHunter.mq5) kodunda başka hiçbir radikal ideolojik farklılık yoktur; zira aynı işlevsel bileşenler temelinde derlenmiştir. Bu nedenle iç yapısına daha fazla zaman ayırmanın gerekli olmadığını düşünüyorum.
Sonuç
Bana göre, MQL5'teki çok para birimli Expert Advisor kodu kesinlikle normal bir Expert Advisor koduna benzerdir.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/105
- Ücretsiz ticaret uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz