Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri - sayfa 70

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Değiştirme takvimi nasıl belirlenir?

fxsaber , 2018.02.08 12:39

 void OnTick ()
{  
   const long Chart = ChartID ();
   string PrevSymbol = _Symbol ;
   ENUM_TIMEFRAMES PrevTF = _Period ;
    
   while (! IsStopped ())
  {
     if ((PrevSymbol != ChartSymbol (Chart)) || (PrevTF != ChartPeriod (Chart))) // ноль указывать НЕЛЬЗЯ!
    {      
      PrevSymbol = ChartSymbol (Chart);
      PrevTF = ChartPeriod (Chart);
      
       Alert (PrevSymbol + " " + EnumToString (PrevTF));      
    }
    
     Sleep ( 0 );
  }
}

Bazı işlevlerde boş bir ChartID giriş parametresi, değerlerin yeniden hesaplanmasına neden olmaz. Mevcut grafik için güncel verilere ihtiyacınız varsa, tam teşekküllü bir kimlik kullanmanız gerekir.

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

POSITION_TICKET != POSITION_IDENTIFIER

fxsaber , 2018.02.12 20:14

bulgular

Bunun, komisyoncu hackinin özellikleri değil, MT5'in normal davranışı olduğunu düşünürsek, o zaman

  • ORDER_STATE_PARTIAL geçmiş siparişlere sahip değil.
  • Doldurulan siparişler her zaman ORDER_STATE_FILLED durumuna sahiptir.
  • Kısmi uygulama durumunda, işlem sunucusu tarafından ilgili yeni piyasa emirleri oluşturulur (ORDER_REASON_CLIENT - orijinal emir otomatik olarak verilse bile (EXPERT)).
  • Eski canlı sipariş (bilet değişmez) azaltılmış bir hacimle (ORDER_VOLUME_CURRENT) asılı kalır.
  • Aynı zamanda, eski canlı sipariş ORDER_STATE_PARTIAL durumunu alır. Aslında bu işaret, ORDER_VOLUME_CURRENT ve ORDER_VOLUME_INITIAL karşılaştırmasının sonucudur.
  • Açılan tüm pozisyonlar ID == OrderTicket alır. Nerede OrderTicket - ticaret sunucusu tarafından oluşturulan biletler.
  • Bir ticaret anlaşmasının her zaman tam olarak bir geçmiş emri vardır ve durumu ORDER_STATE_FILLED'dir.
  • Gerçekleştirilen her geçmiş siparişin tam olarak bir ticareti vardır.
  • Yürütülen herhangi bir sipariş için ORDER_VOLUME_INITIAL, yürütüldüğü hacme eşittir. Onlar. tam yürütmeden sonra orijinal yırtık sipariş bile, ORDER_VOLUME_INITITAL tarafından oluşturulan anlaşmanın hacmine eşittir.
  • Orijinal emrin (kısmen uygulanan) zamanı değişmez ve işlem zamanına eşit değildir.
  • Geçmiş tablo, fırsatlara göre değil, sipariş zamanına (ORDER_TIME_SETUP) göre sıralanır. Bu nedenle, DEAL_TIME tarihinden itibaren HistorySelect yaparsanız, ilgili sırayı geçmiş tabloya alamayabilirsiniz.
  • HistorySelectByPosition her zaman gerekli anlaşma/sipariş kümesini döndürür.
  • Herhangi bir ticaret işlemi için kayma miktarını hesaplayabilirsiniz.

Dezavantajları

  • ORDER_REASON_PARTIAL, DEAL_REASON_PARTIAL ve POSITION_REASON_PARTIAL eksik. Aynı zamanda, karşılık gelen numaralandırmalarda bu bayraklar REASON_EXPERT'den hemen sonra yerleştirilmelidir.
  • Limit emirlerin kısmi ifasında karşılık gelen piyasa emirleri, doğası gereği negatif kaymaya sahip olabilir. Görünüşe göre bu sadece emir türünde bir hata ve aslında piyasa emri yok - sadece MT5 içinde yaratılıyor ve dışarı çıkmıyor.

ZY Tamamen doğrulanmış hipotez

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

POSITION_TICKET != POSITION_IDENTIFIER

Pavel Kolchin , 2018.02.12 13:31

(Emin değilim, pozisyonların kısmen kapanmasına benzeterek kontrol etmek zor)

Her şey şu şekilde çalışır:

1) bekleyen emir kısmen tetiklendi - Position_ID = Order_Ticket1 ile bir pozisyon açıldı

2) emrin geri kalanı yeni bir Order_Ticket2 emrine dönüştürülür ve aynı Order_Ticket ile geçmişte 2 emir olamayacağı için yeni Order_Ticket2 != Order_Ticket1'in yürütülmesini bekler.

3) emrin geri kalanı dolduruldu - Position_ID = Order_Ticket2 ile bir pozisyon açıldı

tarihte iki emir var, terminalde iki pozisyon var, her şey uyuyor

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

"Bir tüccar için LifeHack: Tanımlar üzerinde ForEach'i yoğurmak (#define)" makalesinin tartışılması

fxsaber , 2018.02.14 10:54

Performans ölçümü

 #define BENCH(A)                                                              \
{                                                                             \
   const ulong StartTime = GetMicrosecondCount ();                              \
  A;                                                                          \
   Print ( "Time[" + #A + "] = " + ( string )( GetMicrosecondCount () - StartTime)); \
}

double GetAsk()
{
   static MqlTick tick = { 0 };
  
   return ( SymbolInfoTick ( Symbol (),tick) ? tick.ask : 0 );
}

#define AMOUNT 1 e6

void OnStart ()
{
   double Sum = 0 ;
  
  BENCH( for ( int i = 0 ; i < AMOUNT; i++) Sum += GetAsk())
  BENCH( for ( int i = 0 ; i < AMOUNT; i++) Sum += SymbolInfoDouble ( _Symbol , SYMBOL_ASK ))
  
   Print (Sum);
}


Sonuç

 Time [ for (inti= 0 ;i<AMOUNT;i++)Sum+=GetAsk()] = 78952
Time [ for (inti= 0 ;i<AMOUNT;i++)Sum+= SymbolInfoDouble ( _Symbol , SYMBOL_ASK )] = 162606

Kesinlikle yanılmışım! SymbolInfoDouble, SymbolInfoTick'ten iki kat daha yavaştır.

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

"Bir tüccar için LifeHack: Tanımlar üzerinde ForEach'i yoğurmak (#define)" makalesinin tartışılması

fxsaber , 2018.02.14 11:58

beceriksiz. Test Cihazında Sonuç

 2017.09 . 01 00 : 00 : 10    Time [ for (inti= 0 ;i<AMOUNT;i++)Sum+=GetAsk()] = 87424
2017.09 . 01 00 : 00 : 10    Time [ for (inti= 0 ;i<AMOUNT;i++)Sum+= SymbolInfoDouble ( _Symbol , SYMBOL_ASK )] = 83410

Performansın gerekli olduğu durumlarda (Optimizer), SymbolInfoDouble kullanmak daha iyidir. Gerçekte, önemli değil.


ЗЫ Fonksiyonların hızının ölçülmesi performansın önemli olduğu bir ortamda ölçülmelidir - Tester.

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Hatalar, hatalar, sorular

fxsaber , 2018.02.12 23:10

İki ticaret demo sunucusunda ellerimle bir SATIN AL pozisyonu açıyorum


RoboForex-MetaTrader 5

2018.02.13 00:02:08.424 '8520459': market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': accepted market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': deal #90389019 buy 1.00 GBPUSD at 1.38387 done (based on order #107426544)
2018.02.13 00:02:10.101 '8520459': order #107426544 buy 1.00 / 1.00 GBPUSD at 1.38387 done in 1683.949 ms


FXOpen-MT5

2018.02.13 00:00:25.780 '18000903': market buy 1.00 GBPUSD
2018.02.13 00:00:25.912 '18000903': accepted market buy 1.00 GBPUSD
2018.02.13 00:00:25.922 '18000903': market buy 1.00 GBPUSD placed for execution
2018.02.13 00:00:25.942 '18000903': order #896454 buy 1.00 / 1.00 GBPUSD at market done in 154.252 ms
2018.02.13 00:00:25.942 '18000903': deal #80559 buy 1.00 GBPUSD at 1.38387 done (based on order #896454)

Aynı renkteki satırlar aynı anlama gelir. Ancak farklı sıralarda gittikleri açıkça görülmektedir. Robo için, işlemin yürütülmesinden sonra emrin yerine getirildiğine dair bir mesaj gelir. Ve açık için - ÖNCE! Bu nedenle OrderSend şans getirir, ancak henüz bir anlaşma yoktur. Onlar. OrderSend'i geçmişle senkronize etmiyoruz

FXOpen-MT5 için kod

 #define PRINT(A) Print ( #A + " = " + ( string )(A))

void OnStart ()
{
   MqlTradeRequest Request = { 0 };
  
  Request.action = TRADE_ACTION_DEAL ;
  Request.symbol = _Symbol ;
  Request.volume = 1 ;
  Request.type_filling = ORDER_FILLING_IOC ;
  
   MqlTradeResult Result;
  
  PRINT( OrderSend (Request, Result));
  PRINT(Result.deal);
}


Sonuç

 OrderSend (Request,Result) = true
Result.deal = 0


Bu durum aşağıdaki açıklamaya sahiptir.

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Hatalar, hatalar, sorular

Raşid Umarov , 2018.02.15 06:25

Harici bir alım satım sistemine bir emir gönderilirse, MetaTrader 5 alım satım sunucusu ondan bir cevap beklemez ve talebin sonucunu derhal "sipariş verildi" olarak döndürür. Bu nedenle, tamamlanan anlaşma hakkında henüz bir bilgi olmadığı için OrderSend her zaman anlaşma=0 döndürür. OnTrade veya OnTradeTransaction'da yakalayın.

Bir ticaret olayı dinleyicisi örneği , MOEX Moskova Borsası için bir ticaret robotu oluştururken nereden başlamalı makalesinde verilmiştir - TradeTransactionListener.mq5

OrderSend - bir piyasa işlemi yapmak için bir emir gönderdi. Sipariş verildi - bunun için Result.order'ı tanımanız gerekiyor. Ancak hiç kimse bir anlaşma (lar) beklemiyor - birçoğu olabilir ve bunların uygulanması için toplam süre genellikle tanımlanmamıştır.

Aracı tarafındaki belirli çıktı uygulamasına bağlıdır. Genellikle tanımlanmamıştır.

Bu nedenle, kodunuzu test etmek için FXOpen-MT5'te bir demo hesabı kullanmanızı şiddetle tavsiye ederim, çünkü. diğer demolardan oldukça farklı duruyor.


Örneğin, böyle bir ticaret mantığıyla MQL5'te bir komut dosyası yazmaya çalışmanızı öneririm (MQL4 stili sadece anlamın hızlı bir şekilde gösterilmesi içindir)

 void OnStart ()
{
   OrderCloseBy ( OrderSend ( _Symbol , OP_BUY , 1 , Ask , 0 , 0 , 0 ), OrderSend ( _Symbol , OP_SELL , 1 , Bid , 0 , 0 , 0 ));
}

Hiç de kolay değil. Ayrıca, kısmi yürütme için söz konusu demo sunucusunu tavsiye ederim.

 
fxsaber :
MT5'teki en yaygın hatalardan biri için açıklamanın yapıldığı bir gönderi kaldırıldı.
Silinenler arasında yok. Garip. tekrar yayınlayabilir misin?
 
fxsaber :

Gönderi harikaydı. Kaldırılmasını beklemiyordum. Kaldırılma sebebini öğrenmek istiyorum. Çünkü yeniden uzaklaştırmayla karşılaşmak mazoşizmdir.

Diyorum ki - uzak olanlar arasında değil. Bir aksaklık olmuş olabilir mi?
 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Sipariş numaralandırma döngüsünün organizasyonu

fxsaber , 2018.02.16 09:40

MT5'te her şey yolunda değil. Sorunu gösteren bir örnek

 // Пример неправильного считывания торгового окружения на каждом тике
// Скрипт эмулирует два тика ТС, которая должна открыть одну позицию, если ее нет.

#include <Trade/Trade.mqh>

// Возвращает количество позиций по символу
int GetAmountPositions( const string Symb )
{
   int Res = 0 ;
  
   // Этот MQL5-код с ошибкой
   for ( int i = PositionsTotal () - 1 ; i >= 0 ; i--)
     if ( PositionGetSymbol (i) == Symb)
      Res++;

/*
   // В MT4 такой код выполняется без ошибки
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
      Res++;
*/       
   return (Res);
}

// Пример OnTick
void ExampleOnTick()
{
   static CTrade Trade;
  
   // Если нет позиции, открываем
   if (!GetAmountPositions( _Symbol ))
    Trade.Buy( 1 );    
}

// Эмуляция прихода двух Tick-событий
void OnStart ()
{
  ExampleOnTick(); 
  
   Sleep ( 10 ); // Между двумя тиками ~10 мс.
  
  ExampleOnTick();
}

Ne dersiniz, bu betiği pozisyonsuz bir sembol üzerinde çalıştırırsanız sonuç ne olur?

Doğru cevap: Bir veya iki pozisyon açılacaktır.

Bunun olmasının nedeni. İlk EmirGönder'den sonra bir piyasa emri belirir ve gerçekleşmeden önce yeni bir işaret gelirse henüz pozisyon yoktur ve ikinci EmirGönder verilir.

Bu bağlamda, görünüşte normal olan MT5 şablonu düzgün çalışmayacak ve sonuç olarak , kod tabanındaki MT5 Uzman Danışmanlarının çoğu çalışmayacaktır . Aynı zamanda, neredeyse aynı MT4 şablonu sorunsuz bir şekilde sürmeye devam edecektir.

İlk bakışta iyi bir fikir olan PositionsTotal, MT5'in piyasa siparişleri için OrdersTotal'ı da analiz etme ihtiyacı nedeniyle bir şekilde gölgede kalıyor.

Dikkat olmak!

 
fxsaber :

Bu bağlamda, görünüşte normal olan MT5 şablonu düzgün çalışmayacak ve sonuç olarak , kod tabanındaki MT5 Uzman Danışmanlarının çoğu çalışmayacaktır .

Bu ifadenin bir kanıtı olarak, MT5 kod tabanından hemen hemen her Expert Advisor'ı alabilirsiniz. Bir şey aramayalım, hemen şu anda en güncel Expert Advisor'ı alalım. KB'de kapsamlı MT5 yayıncılık deneyimine sahip bir yazar tarafından yazılmış olması güzel.

Kaynak kodunda böyle satırlar var (yorumlarımı vurguladım)

 //+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick ()
  {
//....
   int total= 0 ; // для расчета количества открытых советником позиций
//....
//--- main cycle
   for ( int i= PositionsTotal ()- 1 ;i>= 0 ;i--)
       if (m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if (m_position. Symbol ()==m_symbol.Name() && m_position.Magic()==m_magic)
           {
            total++; // расчет количества открытых позиций
//....
   if (total== 0 ) // Если нет открытых советником позиций
     {
       if (! RefreshRates ())
        {
         PrevBars= iTime ( 1 );
         return ;
        }
       //--- open BUY 
       if (MACD_MAIN_2>MACD_SIGNAL_2 && MACD_MAIN_4<MACD_SIGNAL_4) // Сигнал на покупку
        {
         double sl=(InpStopLoss!= 0 )?m_symbol. Ask ()-ExtStopLoss: 0.0 ;
         double tp=(InpTakeProfit!= 0 )?m_symbol. Ask ()+ExtTakeProfit: 0.0 ;
         OpenBuy(sl,tp); // Отправка маркет-ордера на покупку
         return ;
        }
       //--- open SELL
       if (MACD_MAIN_2<MACD_SIGNAL_2 && MACD_MAIN_4>MACD_SIGNAL_4) // Сигнал на продажу
        {
         double sl=(InpStopLoss!= 0 )?m_symbol. Bid ()+ExtStopLoss: 0.0 ;
         double tp=(InpTakeProfit!= 0 )?m_symbol. Bid ()-ExtTakeProfit: 0.0 ;
         OpenSell(sl,tp); // Отправка маркет-ордера на продажу
        }
     }
   return ;
  }

Açıklanan özdeş bir durum elde ediyoruz

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri

fxsaber , 2018.02.16 19:52

İlk EmirGönder'den sonra bir piyasa emri belirir ve gerçekleşmeden önce yeni bir işaret gelirse henüz pozisyon yoktur ve ikinci EmirGönder verilir.

İlk bakışta iyi bir fikir olan PositionsTotal, MT5'in piyasa siparişleri için OrdersTotal'ı da analiz etme ihtiyacı nedeniyle bir şekilde gölgede kalıyor.

Bu, genel durumda danışmanın bir yerine iki, üç vb. pozisyon açacağı anlamına gelir. Kenelerin ne sıklıkta geleceğine ve piyasa emirlerinin ne kadar süreyle uygulanacağına bağlı olarak.


Kod tabanındaki hemen hemen tüm MT5 Expert Advisor'lar MT5 şablonu ile aynı mantığa göre yazıldığından, içerdiği hatanın aynısına sahiptirler. Bu, ne yazık ki KB'deki neredeyse tüm MT5 Uzman Danışmanları için geçerlidir.

MACD EA
MACD EA
  • oylar: 4
  • 2018.02.15
  • Vladimir Karputov
  • www.mql5.com
При поступлении сигнала противоположная позиция закрывается. Также советник может закрывать половину позиции (параметр Profit for closing half of the position), может переводить позицию в безубыток (параметр Breakeven). Размер открываемой позиции может задавать вручную (параметр Lots) или в процентах риска от свободной маржи (параметр Risk in...
 

Netleştirmede, aynı sembol üzerinde aynı anda açık bir pozisyon ve herhangi bir yöndeki birkaç piyasa emri olabilir. Örneğin, bir AL pozisyonu ve bir AL emri. Doğru, böyle bir demo hesabı bulamadım, çünkü kural her yerde uyumsuz olarak uygulandı

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

Hatalar, hatalar, sorular

fxsaber , 2018.02.14 08:58

Tüm OnTradeTransaction olayları, OrderSend'in tamamlanmasından sonra gerçekleşir.

danışman

 void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest &, const MqlTradeResult & )
{ 
   static bool FirstRun = true ;  
   static ulong StartTime;
  
   if (FirstRun)
  {
    StartTime = GetMicrosecondCount ();
    
    FirstRun = false ;
  }

   Print ( EnumToString (Trans.type));
   Print (( GetMicrosecondCount () - StartTime) / 1000 );    
}

Eller bir ticaret emri gönderir.

Kayıt

2018.02.14 09:41:46.671 '8854170': instant sell 1.00 EURUSD at 1.23673
2018.02.14 09:41:46.853 '8854170': accepted instant sell 1.00 EURUSD at 1.23673
2018.02.14 09:41:46.853 '8854170': deal #192088422 sell 1.00 EURUSD at 1.23673 done (based on order #208541700)
2018.02.14 09:41:46.853 '8854170': order #208541700 sell 1.00 / 1.00 EURUSD at 1.23673 done in 190.608 ms


Uzman Danışman sonucu

 2018.02 . 14 09 : 41 : 46.853 TRADE_TRANSACTION_ORDER_ADD
2018.02 . 14 09 : 41 : 46.853 0
2018.02 . 14 09 : 41 : 46.853 TRADE_TRANSACTION_DEAL_ADD
2018.02 . 14 09 : 41 : 46.853 1
2018.02 . 14 09 : 41 : 46.853 TRADE_TRANSACTION_ORDER_DELETE
2018.02 . 14 09 : 41 : 46.853 1
2018.02 . 14 09 : 41 : 46.853 TRADE_TRANSACTION_HISTORY_ADD
2018.02 . 14 09 : 41 : 46.853 2
2018.02 . 14 09 : 41 : 46.853 TRADE_TRANSACTION_REQUEST
2018.02 . 14 09 : 41 : 46.853 2


Hem zaman sütunundan hem de EA'nın sayısal göstergelerinden , bir ticaret emrinin yürütülme süresinin, OnTradeTransaction olaylarının sırasını hiçbir şekilde etkilemediği açıkça görülmektedir. Tüm uyumsuzluklar cehenneme gider! Bunu batırmayı başardılar. 1755 oluşturun.

Örneğin, Terminal'de OrderSendAsync piyasa emri verirken, bir an bile piyasa emri görünmez. Belki de geliştiriciler bunu biraz hızlandırmak için yapmaya karar verdiler.

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

"MetaTrader 5'te bir ticaret stratejisinin optimizasyonunu görselleştirme" makalesinin tartışılması

fxsaber , 2018.02.22 08:39

Çerçeve modunda OnInit, OnDeinit, OnTick, OnTrade, OnTradeTransaction ve OnTimer yok sayılır. Yalnızca OnChartEvent saban sürer.

Tabii ki, OnChartEvent istisnası nedeniyle, içinde çerçeve modu bayrağının varlığı için zorunlu bir kontrol yapılması gerekir.