MQL5 dilini sıfırdan kendi kendine öğrenme - sayfa 72

 
Vasiliy Sokolov :

Mükemmelliğin sınırı olmadığı için, koda birkaç yorum daha ekleyeceğim:

Önemsiz iki yeri sarı renkle vurguladım.

1) Lütfen kodun ilk if ve sonrakinde tekrarlandığını unutmayın. Fark sadece son satırda ve son işlemdedir (OpenBUY, OpenSell).

2) else bloğuna girme koşulları açık değildir. Bolluktan mı kaynaklanıyor?? görüntülenmez. Aslında, yalnızca son satıra bağlıdırlar:

Bu, burada bir özelliğin eksik olduğuna dair kesin bir işarettir.

Bir pozisyon açma zamanı belirtilene karşılık geliyorsa true döndüren bir fonksiyon yazmanız gerekiyor (biraz sonra yazacağım)

Evet Vasily haklısın fonksiyon yazmak gerçekten gerekliydi.

Saygılarımla, Vladimir.

 
Vasiliy Sokolov :
Bu arada, programınızın genel boyutuna dikkat edin. Zaten önemli. Nasılsınız? Bu arada, yeni başlayan biri artık böyle bir kod hacmi yazamaz: değişkenler karışmaya başlar, köşeli parantezler ölçek dışına çıkar, derleme hataları yağmurdan sonra mantar gibi görünmeye başlar. Bu boyutta bir program derledikten sonra başarısız olmaya başlarlar ve kimse neyin yanlış olduğunu anlayamaz. Ve her şey bir nedenden dolayı sizin için çalışıyor) ve ne olduğu ve nasıl olduğu işlevler açısından yapısal olarak açıktır. Tek kelimeyle güzellik.

Teşekkürler Vasili! İşte çalışmanızın büyük bir kısmı çünkü. takip eden durdurma şablonu sizin tarafınızdan sağlandı. Sadece fonksiyonları kodla doldurmam gerekiyor. Şimdi bir trol üzerinde çalışıyorum. Zaten bir şeyler yapıldı, ancak danışmanın son halini herkesin görebileceği şekilde sunmak için hala çözmem gereken noktalar var.

Saygılarımla, Vladimir.

 

Birkaç özellik ekledim. Bu kodu aldım:

 //+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick ()
  {
//--- Зададим условия для открытия позиций BUY и SELL   
   double price= SymbolInfoDouble ( Symbol (), SYMBOL_ASK );
   double point= SymbolInfoDouble ( Symbol (), SYMBOL_POINT );
   int digits=( int ) SymbolInfoInteger ( Symbol (), SYMBOL_DIGITS );
   price= NormalizeDouble (price,digits);
   //-- Если открытой позиции нет и время для открытия позволяет,
   //-- открывает BUY или SELL в зависимости от положения тика
   if (IsMainPositionOpen() == false && IsTimeForOpen())
   {
       if (TickUP()==(price+point))
         OpenBUY();
       if (TickDOWN()==(price-point))
         OpenSELL();
   }
   //-- Если наступило время закрытия позиции, закрываем все
   if (IsTimeForClose())
      CloseALL();

//+------------------------------------------------------------------+
//| Шаблон трейлинг стопа предоставленный Василием Соколовым         |
//+------------------------------------------------------------------+

//-- Выбираем позиции по текущему символу. Если позиции нет и выбирать нечего, то выходим!
   if (! PositionSelect ( Symbol ()))
       return ;
//-- Стоп-лосс длинной позиции переставляем в безубыток и тралим его
   if ( PositionGetInteger ( POSITION_TYPE ) == POSITION_TYPE_BUY )
     {
      SetBreakevenForBuyPosition(); // установить безубыток для Buy позиции
      TrailingStopLossForBuyPosition(); // перетащить Stop Loss для Buy позиции
     }
//-- Стоп-лосс короткой позиции переставляем в безубыток и тралим его
   else
       if ( PositionGetInteger ( POSITION_TYPE ) == POSITION_TYPE_SELL )
        {
         SetBreakevenForSellPosition(); // установить безубыток для Sell позиции
         TrailingStopLossForSellPosition(); // перетащить Stop Loss для Sell позиции
        }
  }
  
//+------------------------------------------------------------------+
//| Возвращает истину, если позиция торгового эксперта уже открыта.  |
//| Возвращает ложь в противном случае.                              |
//+------------------------------------------------------------------+  
bool IsMainPositionOpen()
{
   //-- Если позиций нет - то и у эксперта позиции нет, возвращаем ложь.
   if ( PositionSelect ( Symbol ()) == false )
       return false ;
   //-- Позиция есть и ее мэджик совпадает с мэджиком эксперта - возвращаем истину
   if ( PositionGetInteger ( POSITION_MAGIC ) == Magic_Number)
       return true ;
   //-- Позиция есть но ее мэджик не совподает с мэджиком эксперта -
   //-- это чья-то другая позиция, позвращаем ложь
   else
       return false ;
}
//+------------------------------------------------------------------+
//| Возвращает истину, если текущее время попадает в диапазон        |
//| разрешенного времени для открытия позиции. В противном случае    |
//| возвращает ложь.                                                 |
//+------------------------------------------------------------------+  
bool IsTimeForOpen()
  {
   MqlDateTime time_current,time_open,time_open1;
   TimeToStruct ( TimeCurrent (),time_current);
   TimeToStruct (( D'1970.01.01 09:00:00' ),time_open);
   TimeToStruct (( D'1970.01.01 09:01:00' ),time_open1);
   if (time_current.hour == time_open.hour &&
      time_current.min >= time_open.min &&
      time_current.min < time_open1.min
      )
       return true ;
   else
       return false ;
   }
//+------------------------------------------------------------------+
//| Возвращает истину, если текущее время попадает в диапазон        |
//| времени для закрытия позиции. В противном случае возвращает ложь.|                                                 |
//+------------------------------------------------------------------+     
bool IsTimeForClose()
{
   MqlDateTime time_current,time_open,time_open1,time_close;
   TimeToStruct(TimeCurrent(),time_current);
   TimeToStruct((D'1970.01.01 23:50:00'), time_close);
   if(time_current.hour==time_close.hour && 
      time_current.min==time_close.min)
      return true;
   else
      return false;
}
Sihirle çalışmak benim için hala net değil. Netleştirmede anlamsızdır. Her durumda, yalnızca bir işlevde yapıldığından bu kontrolü kolayca kaldırabilirsiniz.
Dosyalar:
MrBrooklin.mq5  38 kb
 

onInit bloğu da aşırı tasarlanmış ve hala tam olarak doğru yazılmamış. İlk olarak, sayıları değil tanımlayıcıları yazmaya çalışmanız gerekir. Döndürme -1 değil ve INIT_FAILED 0 değil, INIT_SUCCEEDED. İkincisi, anahtar burada gereksizdir. Ya if ya da geçiş yazmanız gerekir. Önce bir şey yazın, çünkü diğeri tereyağı yağı.

Üçüncüsü, hesap türü için tüm seçenekleri kontrol etmeniz gerekir. Demo var, gerçek var. Bir de Yarışma var. Ancak üçüncü bir hesap olmasa bile, diğer tüm seçenekleri yakalayacak bir saplama olmalıdır:

 int OnInit ()
  {
//--- Определим тип счёта на который устанавливаем советник: демо или реальный счет
   ENUM_ACCOUNT_TRADE_MODE account_type=( ENUM_ACCOUNT_TRADE_MODE ) AccountInfoInteger ( ACCOUNT_TRADE_MODE );
//--- теперь превратим значение перечисления в понятный вид
   string trade_mode;               //создадим переменную для торгового режима
   ACCOUNT_TRADE_MODE_CONTEST
   if (account_type== ACCOUNT_TRADE_MODE_REAL ) //если торговый режим счёта - реальный
     {
       //--- выводим окно сообщений на торговом терминале и закрываем советник
       MessageBox ( "Работа на реальном счете запрещена, выходим!" , "Советник запущен на реальном счете" );
       return ( INIT_FAILED ); //возвращаем для функции OnInit ненулевое значение означающее "неудачная инициализация"
     }
   if (account_type== ACCOUNT_TRADE_MODE_DEMO ) //если торговый режим счёта - демо
     {
       //--- выводим окно сообщений на торговом терминале и продолжаем работу советника
       MessageBox ( "Работа на демо-счете разрешена!" , "Советник запущен на демо-счете" );
      trade_mode= "Счёт REAL" ;
       return ( INIT_SUCCEEDED ); //возвращаем для функции OnInit нулевое значение означающее "удачная инициализация"
     }
//-- Заглушка на случай непредвиденных вариантов. Всегда должна быть даже если варианта явно два.
   else
   {
       MessageBox ( "Неизвестный тип счета. Работа невозможна!" );
       return ( INIT_FAILED ); //возвращаем для функции OnInit нулевое значение означающее "удачная инициализация"
   }
  }
 

Pekala, pastadaki kiraz: yorumlar. Fonksiyonları yazdığımızda, çok fazla alan var, elin kendisi gerekli kod parçalarını yorumlarla sağlamak için uzanıyor:

 //+------------------------------------------------------------------+
//| Возвращает истину, если позиция торгового эксперта уже открыта.  |
//| Возвращает ложь в противном случае.                              |
//+------------------------------------------------------------------+  
bool IsMainPositionOpen()
{
   //-- Если позиций нет - то и у эксперта позиции нет, возвращаем ложь.
   if ( PositionSelect ( Symbol ()) == false )
       return false ;
   //-- Позиция есть и ее мэджик совпадает с мэджиком эксперта - возвращаем истину
   if ( PositionGetInteger ( POSITION_MAGIC ) == Magic_Number)
       return true ;
   //-- Позиция есть но ее мэджик не совподает с мэджиком эксперта -
   //-- это чья-то другая позиция, позвращаем ложь
   else
       return false ;
}

Aynı kod, bazı ana işlevlerin gövdesine "aynı anda" yazıldığında, olabildiğince kısa ve yorumsuz hale gelir:

 if ( PositionSelect ( Symbol ())== false
       && PositionGetInteger ( POSITION_MAGIC )!=Magic_Number
      && time_current.hour==time_open.hour
      && time_current.min>=time_open.min
      && time_current.min<time_open1.min
      && (TickUP()==(price+point)))
     {OpenBUY();}

Bu nedenle, daha fazla fonksiyon yazın, sizi gerekli yorumları yazmaya teşvik ederler ve kodu daha ayrıntılı hale getirseler de daha anlaşılırdırlar.

Üçüncü nokta: buraya yazıyorsunuz:

//+------------------------------------------------------------------+
/ | Expert initialization function                                   |
//+------------------------------------------------------------------+
/* Функция инициализации советника OnInit с типом данных int. Если возвращаемое значение для функции
   return(-1), то это "неудачная инициализация". Если возвращаемое значение для функции return(0), то
   это "удачная инициализация". INIT_SUCCEEDED означает, что инициализация прошла успешно и дальше
   можно продолжать тестирование эксперта. Этот код означает то же самое, что и нулевое значение, т.е.
   "удачная инициализация".
*/
int OnInit ()
  {
  ...
  }

Neden başka bir yorum türü ekleyesiniz? Sadece blokta olanı yorumunuzla değiştirin:

 //+------------------------------------------------------------------------------------------------------+
//| Функция инициализации советника OnInit с типом данных int. Если возвращаемое значение для функции    |
//| return(-1), то это "неудачная инициализация". Если возвращаемое значение для функции return(0), то   |
//| это "удачная инициализация". INIT_SUCCEEDED означает, что инициализация прошла успешно и дальше      |
//| можно продолжать тестирование эксперта. Этот код означает то же самое, что и нулевое значение, т.е.  |
//| "удачная инициализация".                                                                             |
//+------------------------------------------------------------------------------------------------------+
int OnInit ()
  {
  ...
  }

Unutmayın, yorumlar sizin için, siz yorumlar için değil. Eskileri silin ve yerine kendinizinkini ekleyin. Biçime bağlı kalın - işlevin başlığında, bu işlevin ne yaptığını ve hangi durumlarda hangi değerlerin döndüğünü yorumlarda kısaca ama açıkça belirtin.

 

Bu arada, bir pozisyonun kapanma koşulları zamanla ayrı bir fonksiyona ayrılınca, yanlış yazıldığı ortaya çıktı:

 //+------------------------------------------------------------------+
//| Возвращает истину, если текущее время попадает в диапазон        |
//| времени для закрытия позиции. В противном случае возвращает ложь.|                                                 |
//+------------------------------------------------------------------+     
bool IsTimeForClose()
{
   MqlDateTime time_current,time_open,time_open1,time_close;
   TimeToStruct ( TimeCurrent (),time_current);
   TimeToStruct (( D'1970.01.01 23:50:00' ), time_close);
   if (time_current.hour==time_close.hour && 
      time_current.min==time_close.min)
       return true ;
   else
       return false ;
}

Dahili içeriği kodunuzdan aldım. Pozisyonun sadece bir dakika içinde kapatılacağı açıktır. 23:50'de. Bu kod çalışacaktır, ancak 23:50'de bir şeyler ters giderse, pozisyon 23:51'de asılı kalacaktır. Yani en azından şunu yazmalısın:

time_current.min>=time_close.min)

Ve bu bile ideal değil. Daha güçlü bir çözüm, ticaret modlarını kullanmaktır. Ancak, bu bir sonraki beceri seviyesidir. Şimdiye kadar bu tasarım işe yarayacak.

 
MrBrooklin :

Merhaba Vasili! Zamanında tavsiye ve desteğiniz için çok teşekkür ederiz. İşlevlerin rolü ve program kodu oluşturma ilkeleri hakkındaki mesajlarınız MQL5 programlama dilini öğrenmemde bana çok yardımcı oldu:

  1. https://www.mql5.com/en/forum/352460/page28#comment_18636493
  2. https://www.mql5.com/ru/forum/352460/page28#comment_18637800
  3. https://www.mql5.com/en/forum/352460/page29#comment_18641729
  4. https://www.mql5.com/en/forum/352460/page52#comment_18694985

Artık kafadaki bilgiler zaten yapılandırılmış bir şekil aldığında, sadece benim tarafımdan değil, diğer programcılar tarafından da yazılan kodu algılamak çok daha kolay. Bu konunun tüm yeni başlayanlar için MQL5 programlama dilini sıfırdan öğrenmelerine yardımcı olacağını umuyorum.

Saygılarımla, Vladimir.

Aferin. İyi kodlayıcıların genellikle iyi algoritmaları vardır ve görevleri vardır ve onların kalecileri vardır... Her şey doğru hedeflerle ve doğru görevlerle başlar. Hemen bir ev inşa edebilir ve sonra su bulabilirsiniz. Önce su bulabilir ve yakındaki suyu dikkate alarak bir ev inşa edebilirsiniz. Hedefler/amaçlar ve problem ifadeleri olasılıklardandır.... Hemen algoritmaya geçersiniz.... Ama genel olarak, çok eşit!

 
Vasiliy Sokolov :

Bu arada, bir pozisyonun kapanma koşulları zamanla ayrı bir fonksiyona ayrılınca, yanlış yazıldığı ortaya çıktı:

Dahili içeriği kodunuzdan aldım. Pozisyonun sadece bir dakika içinde kapatılacağı açıktır. 23:50'de. Bu kod çalışacaktır, ancak 23:50'de bir şeyler ters giderse, pozisyon 23:51'de asılı kalacaktır. Yani en azından şunu yazmalısın:

Ve bu bile ideal değil. Daha güçlü bir çözüm, ticaret modlarını kullanmaktır. Ancak, bu bir sonraki beceri seviyesidir. Şimdiye kadar bu tasarım işe yarayacak.

Vasily, sen harika bir öğretmensin!

Herhangi bir kitapçıkta veya ders kitabında böyle bir açıklama bulamazsınız. Önerdiğiniz her şeyi, danışmanın son versiyonunda kesinlikle uygulayacağım.

Saygılarımla, Vladimir.

 

Konudan biraz sapacağım ve hayatımdan bir öğretmen (öğretmen) hakkında bir hikaye anlatacağım. Enstitümüzde, uzmanlık devam ederken, harika bir insan öğretti. O zamanlar mantığın cebirini inceliyorduk. Birçok öğrenci 1+1'in nasıl 1'e eşit olduğunu uzun süre anlayamadı. 1x1 ise, elbette 1'e eşit olacaktır. Ve işte sana!!! Bu öğretmen basit örneklerle bize mantıklı bir "VEYA"nın ne olduğunu ve bir ömür boyu hatırladığı mantıklı bir "VE" nin ne olduğunu açıklamıştır.

Düşünün, öğretmen, sabahları dersler için enstitüye gelmeniz gerektiğini söylüyor. Enstitüye troleybüs veya tramvay ile ulaşabilirsiniz. Durağa geldiniz, ancak ne troleybüs (koşul yanlış veya 0 ile aynı) ne de tramvay (koşul yanlış veya 0 ile aynı). Doğal olarak enstitüye gelemeyeceksiniz (koşul yanlış veya 0 ile aynı). 0+0=0 kontrol ediliyor. Harika! Bir durağa geldiyseniz ve bir troleybüs ( gerçek durum veya 1 ile aynı), VEYA bir tramvay ( gerçek durum veya 1 ile aynı), VEYA bir troleybüs ve tramvay birlikteyse, o zaman kesinlikle enstitüye varacaksınız. ve koşul doğru veya 1 ile aynı! Kontrol ediyoruz: 1+0=1 , 0+1=1 ve 1+1=1 . Her şey uyuyor!

Aynı örnekleri bir troleybüs ve tramvay ile kullanarak bize mantıklı VE'nin ne olduğunu anlattı.

Bir öğretmenin yeteneğinin gücü işte bu anlama gelir! Hayatımın geri kalanı için hatırlıyorum!

Saygılarımla, Vladimir.

 
Valeriy Yastremskiy :

Aferin. İyi kodlayıcıların genellikle iyi algoritmaları vardır ve görevleri vardır ve onların kalecileri vardır... Her şey doğru hedeflerle ve doğru görevlerle başlar. Hemen bir ev inşa edebilir ve sonra su bulabilirsiniz. Önce su bulabilir ve yakındaki suyu dikkate alarak bir ev inşa edebilirsiniz. Hedefler/amaçlar ve problem ifadeleri olasılıklardandır.... Hemen algoritmaya geçersiniz.... Ama genel olarak, çok eşit!

Valery, bu konuya ve yapıcı diyaloga katıldığınız için teşekkür ederiz.

Saygılarımla, Vladimir.