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

 
MrBrooklin :

Igor, MQL5 dilini öğrenme arzusu kaybolmaz, aksine sadece yoğunlaşır. Sadece neden bu kadar aptal olduğumu ve bu döngü operatörüyle basit şeyleri anlayamadığım beni kırıyor. Ana şey, kodun bir döngü operatörü olmadan mükemmel şekilde çalışmasıdır, ancak bir döngü ile bu tam bir stupordur. Yine de gerçeğe ulaşacağım. Doğru, kendi kendine çalışma için zaman çok daha az hale geldi, çünkü. karantina bitti ve işte dil çalışmak için nadir anlar var. Çoğunlukla akşamları ve gece geç saatlere kadar dille ilgileniyorum.

Sonunda doğrudan İzleyen Durdurma kodunu yazmaya devam etmek için 2 görevi tam olarak anlamam ve çözmem gerekiyor:

  1. Tüm sembollerdeki tüm açık pozisyonları yinelemek için for döngüsü operatörünü kullanarak bir kod yazın ve hiçbiri yoksa, 09:00:00 ile 09:01:00 arasındaki zaman aralığında bir Buy pozisyonu açın ve onu zorla kapatın. 23:50:00'de, stop-loss'un işlem günü içinde çalışmaması durumunda. For döngüsü operatörü olmadan, daha önce yazdığım gibi, her şey mükemmel çalışıyor. Şimdi aynı sonucu elde etmek istiyorum, ancak bir döngü ile.
  2. 09:00:00 ile 09:01:00 arasındaki zaman aralığında beliren ilk tik işaretine pozisyonun açılma yönünü belirleyen 2 fonksiyon yazınız. İlk tik yukarı ise, bir Alış pozisyonu, ilk tik aşağı ise sırasıyla bir Satış pozisyonu açılmalıdır. Bu bir strateji değil, rastgele koşulu kullanmamak için sadece "İstek Listem" .
Saygılarımla, Vladimir.

Vladimir, bir tür ormana tırmanıyorsun. Size bir şablon verildi: https://www.mql5.com/ru/forum/352460/page58#comment_18726492 Onu görmezden geldiniz ve aklınızla ilerlemeye karar verdiniz. Bu yol zordur ve yıllar alabilir. Yol boyunca, C, C++, Rust, C#, polimorfizm, kalıtım, işaretçi referanssızlaştırma, dinamik tip döküm öğrenin - ancak zaten hedefe karar verdiniz: kontrol edin veya gidin. Hedefe giden en kısa rotayı kullanmanız gerekir. Takip etmek istiyorsanız - takip edin. Bunun için C ve C++ öğrenmenize gerek yok. İstenirse, bunların hepsi daha sonra seçmeli olarak.

For döngüsündeki durum örnek niteliğindedir. Bu, siteye uygulanması gereken güçlü bir tasarımdır. Ağınız ve yardımcı bir algoritmanız var. Bu nedenle, konumların sayımı yoktur, büyü yoktur ve bu nedenle bu döngü yoktur. Doğal olarak, onsuz her şey sizin için çalışır ve döngü ile yağ elde edilir. Ama inatla onu hatasız kullanmaya çalışıyorsunuz, görünüşe göre bu başlı başına bir amaç: her şeyi ve herkesi olabildiğince yedekte, ne olursa olsun kullanmak.

 
Vasiliy Sokolov :

Vladimir, bir tür ormana tırmanıyorsun. Size bir şablon verildi: https://www.mql5.com/ru/forum/352460/page58#comment_18726492 Onu görmezden geldiniz ve aklınızla ilerlemeye karar verdiniz. Bu yol zordur ve yıllar alabilir. Yol boyunca, C, C++, Rust, C#, polimorfizm, kalıtım, işaretçi referanssızlaştırma, dinamik tip döküm öğrenin - ancak zaten hedefe karar verdiniz: kontrol edin veya gidin. Hedefe giden en kısa rotayı kullanmanız gerekir. Takip etmek istiyorsanız - takip yazın. Bunun için C ve C++ öğrenmenize gerek yok. İstenirse, tüm bunlar daha sonra seçmeli olarak.

For döngüsündeki durum örnek niteliğindedir. Bu, siteye uygulanması gereken güçlü bir tasarımdır. Ağınız ve yardımcı bir algoritmanız var. Bu nedenle, konumların sayımı yoktur, büyü yoktur, dolayısıyla bu döngü yoktur. Doğal olarak, onsuz her şey sizin için çalışır ve döngü ile yağ elde edilir. Ama inatla onu hatasız kullanmaya çalışıyorsunuz, görünüşe göre bu başlı başına bir amaç: her şeyi ve herkesi olabildiğince yedekte, ne olursa olsun kullanmak.

Merhaba Vasili!

Her zamanki gibi konuya zamanında bağlanıp beni doğru yola yönlendirdiğiniz için teşekkür ederim. Şimdi her şeyi sıraya koyacağım:

  1. Şablon, tam olarak siz bana sağladığınızda Expert Advisor'a eklendi, bunun için özel teşekkürler!
  2. Aptallığımda, strateji test cihazında Trailin Stop ile Expert Advisor'ın kontrol edilmesi gerektiğine karar verdim, ancak bunu otomatik olarak en az bir pozisyon açmadan nasıl yapacağımı düşünmedim. Bu yüzden orman, "tam teşekküllü" bir Uzman Danışman yazarak ortaya çıktı. Danışmanın böyle bir stratejisi olmadığı için tırnak içinde yazdım. Bir pozisyon açmak için rastgele koşulu kullanmak istemedim.
  3. Sizin dışınızda muhatapların hiçbiri bu durumda pozisyonları numaralandırmak için for döngüsünün gerekli olmadığını önermedi. Canım, uzun süre tahmin edebilir ve sorabilirdim - bir döngüye hiç ihtiyaç var mı? Bunun gerekli olmadığı ortaya çıktı. Bahşiş için tekrar teşekkürler!
  4. Sonunda, bir takip eden stopun doğrudan yazılmasına devam etmek ve aynı zamanda daha önce başlamış olanın yarısından çıkmamak için , net bir Alış veya Satış pozisyonu açma yönünü belirleyen 2 fonksiyonun kodunu yazmam gerekiyor. .
  5. Evet, kendi kendine eğitimin sürüklenmeye başladığı konusunda size tamamen katılıyorum. Ama benim için bilinmeyen ve dolambaçlı bir yolda yürüdüğümü hesaba katarsak, umarım bunu da hesaba katabiliriz.
  6. Kendi kendine çalışma döneminin tamamı boyunca çok miktarda bilgi aldım ve şimdi sadece onu düzene sokmaya değil, aynı zamanda pratikte uygulamaya da çalışıyorum. Bunu yapmak için CodeBase'de bir danışman tuttum, sonlandırdım ve iki haftadır bir forex satıcısının demo hesabındayım. Sonuç tam olarak ondan beklenen şeydi. Gerçek bir hesap açtığım an çok uzak değil. Bu zaten bir artı!
  7. Kendi kendine öğrenme hızının peşinde değilim çünkü. Daha önce, bilgi bolluğundan, periyodik olarak bir sersemliğin ortaya çıktığını yazmıştım.
  8. Tüm dönem boyunca, kendi kendine öğrenme, kodu derledikten sonra ortaya çıkan İngilizce kelimeleri ve cümleleri yavaş yavaş ezberlemeye başladı. Google Translate'e nadiren bakarım. Bu aynı zamanda kendi kendine öğrenmede olumlu bir andır.
  9. Expert Advisor'da zaten yazdığım her şeyi, tam olarak takip eden durak için tam hazırlık oluştuğunda yayınlayacağım. Cumartesi günü bitirmeye çalışacağım . Bu andan itibaren, sondaki durma kodunu yazma konusundaki ana çalışma başlayacaktır.

Vasily, rehberlik ve yapıcı eleştiri için çok minnettarım! Ayrıca , MQL5 programlama dilini sıfırdan kendi kendime öğrenmemde ellerinden geldiğince yardımcı olan bu konudaki tüm katılımcılara derin şükranlarımı sunarım.

Kendi kendine öğrenme devam ediyor. Devam edecek (devam edecek).

Saygılarımla, Vladimir.

 
Андрей :

Herkese iyi günler!

Biraz eklemek istedim, konu ilginç, bana öyle geliyor ki, bir kişi programlamada 0 ise, " MQL5 dilini tamamen sıfırdan kendi kendine öğrenme" fikri tamamen doğru değil, o zaman önce programlamayı öğrenmesi gerekir. Amaç MQL'de sıfırdan nasıl programlanacağını öğrenmekse, o zaman önce en azından temel olarak C'de nasıl programlanacağını öğrenmeniz ve ardından MQL esasen C olduğu için MQL'de nasıl yazılacağını öğrenmeniz gerekir. belirli bir görev için keskinleştirilmiş kişi, döngülerin nasıl çalıştığını anlamıyor, ancak zaten tüm programlarda yazmaya çalışıyor. Rusça bilmeden Fenya öğrenmeye çalışmak gibi...

Başka bir şey de, C'nin programlama öğrenmek için en kolay dil olmamasıdır, basittir, ancak çok özlüdür, yeni başlayanlar için algoritmalar, veri türleri, Boole cebri hakkında temel kavramlara sahip olmadan kodu okuması ve anlaması zordur. C'de arka arkaya üç karakter, başka bir dilde birkaç satırın anlamını taşıyabilir.

Temel olarak sıfırdan programlamayı öğrenmek, bir bilgisayarla (hangisi olduğu önemli değil) bir dilde konuşmayı öğrenmek için, çözmeye başlamak için en kolay kitap olan Pascal ile başlamanızı tavsiye ederim. (2-3 hafta rahat), sonra C (burada, pascal'dan sonra, özenle maksimum bir hafta, sözdizimine hakim olun, dilin temel bilgisinden bahsediyorum!) ve ancak o zaman aşağıdaki gibi özel dilleri alın. MQL, çünkü MQL, C olduğu için, bir görevde keskinleştirildiğinden ve derleyici bariz olanı bildiğinden, birkaç sıkıntısı ama aynı zamanda basitleştirmeleri de var. Ve sırayla C, RAR tarafından sıkıştırılmış böyle bir pascaldır, ancak Pascal neredeyse İngilizcedir =).

Şimdi döngüler için:

Programlamayı öğrenirken, cebirdeki toplam ile analoji bana yardımcı oldu, burada n'nin başlangıç değeri, n'nin son değeri ve hesaplama için bu n ile formül gösterilir.

Merhaba Andrey! Size temelde tamamen katılıyorum. Bende yok ve hiç olmadı. Ama dedikleri gibi, Moskova hemen inşa edilmedi! Tavsiyeniz ve ipuçlarınız için teşekkür ederiz!

Saygılarımla, Vladimir.

 
Roman Shiredchenko :

Evet. Katılıyorum - onun kodları da çalıyor ! Kendinizi sıfırdan kuruyorsunuz. Kodu acele etmeden sakince anlayın ve hepsi bu. Burada her şey basit - seçtik ve trolledik: (çok daha kolay - sadece GEREKLİ pozisyonu seçme konunuz ... :-))

Ek olarak, dahil edilen dosyalar - bu, onların tür kodunuzda işlevler biçiminde de bulundukları anlamına gelir ve hepsi bu.

Kodlar ve bağlantılar için teşekkürler Roman! Kodları sakince anlıyorum ve kesinlikle acelem yok!

Saygılarımla, Vladimir.

 

Herkese iyi günler ve iyi bir ruh hali!

MQL5 programlama dilini öğrenmeye devam ediyorum. Bugün, söz verdiğim gibi, son durak yazmak için tasarlanmış Expert Advisor şablonunun kodunu herkesin görmesi için gönderiyorum. EA şablon kodunun oldukça hantal olması nedeniyle, yorumları olabildiğince azaltmak zorunda kaldık. Bir programlama okulunun 1. sınıfındaki bir öğrencinin erişebileceği bir sunumda, her kod satırı hakkında ayrıntılı yorumlar içeren Expert Advisor'ın tam sürümü, daha sonra Trailing_Stop.mq5 çalışma adıyla bir dosya biçiminde yayınlanacaktır. sitede başka bir "ayak bezi" üretmemek için.

Kodu yayınlamadan önce EA, strateji test cihazında test edildi. Herhangi bir sorun tespit edilmedi. EA, bir netleştirme pozisyonu muhasebe sistemi kullanır. Bu muhasebe sistemi, aynı sembol (finansal araç) için hesapta aynı anda yalnızca bir açık pozisyon olabileceğini ima eder.

Şu anda, EA şunları yapabilir:

  1. Yüklemenin planlandığı ticaret hesabını kontrol edin. Danışman bir demo hesabına kuruluysa, mesaj penceresinde çalışmaya devam etme izni görünecektir. Danışmanı gerçek bir hesaba kurma girişiminde bulunulursa, mesaj penceresinde çalışmaya devam etmenin imkansızlığı hakkında bir uyarı belirecek ve ardından işlem terminalinin çalışma penceresinden otomatik olarak silinecektir.
  2. Ticaret gününde bir kez tam 9:00'da. Moskova saatine göre, ilk tik işaretinin yönlendirileceği yönde otomatik olarak bir pozisyon açın. Örneğin, sabah 9:00'da ise Moskova saatinde, ilk tik yukarı doğru yönlendirilecek, yani bir AL pozisyonu açılacak, ilk tik aşağıdaysa bir SATIŞ pozisyonu açılacaktır.
  3. Durdurma kaybı boyutunu ayarlayın.
  4. Parti boyutunu ayarlayın.
  5. Takip eden durdurmanın çalışması için gerekli olacak diğer parametreleri ayarlayın.

Ek olarak, EA, Vasily Sokolov tarafından sağlanan ve kendi kendine öğrenme sürecinde kodla doldurulacak önceden yüklenmiş bir şablona sahiptir.

BİR UYARI!!!

Expert Advisor, bir demo hesabı için kendi kendine çalışma planına göre ve yalnızca eğitim amaçlı geliştirilmiştir! Gerçek bir hesapta işlem yapmak ve kar etmek için tasarlanmamıştır!

Saygılarımla, Vladimir.

 //+------------------------------------------------------------------+
//|                                                Trailing_Stop.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright    "Copyright 2020, MetaQuotes Software Corp."
#property link          "https://www.mql5.com"
#property description "Советник создан для демо-счёта исключительно в учебных целях!"
#property description "Не предназначен для торговли на реальном счёте и извлечения прибыли!"
#property version      "1.00"
/* Краткое описание советника Trailing_Stop. Код советника разрабатывается в соответствии с
   планом самообучения языку программирования MQL5. В советнике применена неттинговая система
   учёта позиций. Эта система учета подразумевает, что в один момент времени на счете может быть
   только одна открытая позиция по одному и тому же символу (финансовому инструменту). Алгоритм
   работы советника прост: один раз в торговый день ровно в 9 ч. 00 мин. по московскому времени
   будет открываться одна позиция в ту сторону, куда будет направлен первый тик. Например, если
   первый тик будет направлен вверх, то значит откроется позиция BUY, если первый тик будет вниз,
   то значит откроется позиция SELL. У открытой позиции сразу будет устанавливаться ордер Stop Loss
   фиксированного размера для минимизации потерь в том случае, если цена финансового инструмента
   станет двигаться в убыточном направлении. Если цена инструмента достигнет этого уровня, то
   позиция полностью закроется автоматически. Если цена финансового инструмента будет двигаться
   в прибыльном направлении, то тогда автоматически включится в работу Trailing_Stop (Трейлинг Стоп).
   Схема работы Трейлинг Стоп:
   1. С приходом новых котировок советник проверяет, прибыльна ли открытая позиция.
   2. Как только прибыль (в пунктах) станет равной либо большей той величины, которая указана во
      входном параметре советника "Уровень перестановки Stop Loss в безубыток", автоматически
      поступит команда для перемещения ордера Stop Loss на тот уровень цены, по которому открылась
      существующая позиция, т.е. в безубыток.
   3. Если цена и дальше продолжит движение с увеличением прибыльности позиции, то при превышении
      величины, указаной во входном параметре советника "Уровень перестановки Stop Loss в безубыток"
      на величину, которая указана во входном параметре "Шаг трейлинг стопа", Stop Loss вслед за
      текущей ценой автоматически переместится с уровня безубытка на величину этого шага.
   4. Если прибыльность позиции уменьшится, то модификации ордера происходить не будет. Таким
      образом, будет автоматически фиксироваться прибыль торговой позиции.
   Если в течении торгового дня открытая позиция не закроется по Stop Loss или Trailing_Stop, то в
   23 ч. 50 мин. советник принудительно закроет эту позицию.

   ВАЖНО!!! Советник создан для демо-счёта исключительно в учебных целях!
            Не предназначен для торговли на реальном счёте и извлечения прибыли!*/

//--- Создадим входные параметры советника
input ushort BreakevenLevel= 100 ; //Уровень перестановки Stop Loss в безубыток
input ushort TrailingStop= 10 ;     //Шаг трейлинг стопа
input ushort SL= 200 ;             //Стоп-лосс
input double Lot= 0.1 ;             //Лот
input long    Magic_Number= 3215 ;   //Магический номер
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
/* Функция инициализации советника OnInit с типом данных int. Если возвращаемое значение для функции
   return(-1), то это "неудачная инициализация". Если возвращаемое значение для функции return(0), то
   это "удачная инициализация". INIT_SUCCEEDED означает, что инициализация прошла успешно и дальше
   можно продолжать тестирование эксперта. Этот код означает то же самое, что и нулевое значение, т.е.
   "удачная инициализация".
*/
int OnInit ()
  {
//--- Определим тип счёта на который устанавливаем советник: демо или реальный счет
   ENUM_ACCOUNT_TRADE_MODE account_type=( ENUM_ACCOUNT_TRADE_MODE ) AccountInfoInteger ( ACCOUNT_TRADE_MODE );
//--- теперь превратим значение перечисления в понятный вид
   string trade_mode;               //создадим переменную для торгового режима
   /* Создадим оператор-переключатель switch, который cравнивает значение выражения с константами во всех
      вариантах case и передает управление оператору с соответствующим значением выражения.*/
   switch (account_type)
     {
       case ACCOUNT_TRADE_MODE_DEMO : //если ключевое слово ACCOUNT_TRADE_MODE_DEMO
         trade_mode= "Счёт DEMO" ;     //значит торговый режим счёта - демо
         break ;                     //оператор break прекращает выполнение ближайшего оператора switch
       case ACCOUNT_TRADE_MODE_REAL : //если ключевое слово ACCOUNT_TRADE_MODE_REAL
         trade_mode= "Счёт REAL" ;     //значит торговый режим счёта - реальный
         break ;                     //оператор break прекращает выполнение ближайшего оператора switch
     }
   if (account_type== ACCOUNT_TRADE_MODE_REAL ) //если торговый режим счёта - реальный
     {
       //--- выводим окно сообщений на торговом терминале и закрываем советник
       MessageBox ( "Работа на реальном счете запрещена, выходим!" , "Советник запущен на реальном счете" );
       return (- 1 ); //возвращаем для функции OnInit ненулевое значение означающее "неудачная инициализация"
     }
   if (account_type== ACCOUNT_TRADE_MODE_DEMO ) //если торговый режим счёта - демо
     {
       //--- выводим окно сообщений на торговом терминале и продолжаем работу советника
       MessageBox ( "Работа на демо-счете разрешена!" , "Советник запущен на демо-счете" );
       return ( 0 ); //возвращаем для функции OnInit нулевое значение означающее "удачная инициализация"
     }
   return ( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason)
  {
//--- сообщим код завершения работы эксперта
   Print ( __FILE__ , ": Код причины деинициализации = " ,reason);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick ()
  {
//--- Зададим время открытия и закрытия позиции
   MqlDateTime time_current,time_open,time_open1,time_close;
   TimeToStruct ( TimeCurrent (),time_current);
   TimeToStruct (( D'1970.01.01 09:00:00' ),time_open);
   TimeToStruct (( D'1970.01.01 09:01:00' ),time_open1);
   TimeToStruct (( D'1970.01.01 23:50:00' ),time_close);
//--- Зададим условия для открытия позиций 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);
   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();}
   else
     {
       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
         && (TickDOWN()==(price-point)))
        {OpenSELL();}
     }
   if (time_current.hour==time_close.hour && time_current.min==time_close.min)
      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 позиции
        }
  }

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer ()
  {
//---

  }
//+------------------------------------------------------------------+
//| Buy Position Open function                                       |
//+------------------------------------------------------------------+

//--- Создадим функцию для открытия позиции Buy и назовём её OpenBUY
void OpenBUY()
  {
//--- Создадим запрос на сервер и получим ответ с результатом
   MqlTradeRequest request= { 0 };
   MqlTradeResult result= { 0 };
//--- Создадим переменные необходимые для работы с сервером
   double price= SymbolInfoDouble ( Symbol (), SYMBOL_ASK );
   double point= SymbolInfoDouble ( Symbol (), SYMBOL_POINT );
   int digits=( int ) SymbolInfoInteger ( Symbol (), SYMBOL_DIGITS );
   request.action= TRADE_ACTION_DEAL ;
   request.symbol= Symbol ();
   request.volume=Lot;
   request.deviation= 2 ;
   request.magic=Magic_Number;
   request.type= ORDER_TYPE_BUY ;
   request.price= NormalizeDouble (price,digits);
   /*Создадим запрос на торговый сервер request.sl, в котором укажем, где должен находиться уровень
     стоп лосс относительно цены, по которой открылась позиция "BUY". Уровень SL должен находиться
     ниже цены, поэтому пишем price-SL*point. Для нормализации уровня SL применим функцию преобразования
     данных NormalizeDouble, где обязательно умножим уровень SL на point (размер одного пункта) и укажем
     digits(количество знаков после запятой).
   */
   request.sl= NormalizeDouble (price-SL*point,digits);
   if (! OrderSend (request,result))
       PrintFormat ( "OrderSend error %d" , GetLastError ());
   PrintFormat ( "retcode=%u  deal=%I64u  order=%I64u" ,result.retcode,result.deal,result.order);
  }
//+------------------------------------------------------------------+
//| Sell Position Open function                                      |
//+------------------------------------------------------------------+

//--- Создадим функцию для открытия позиции Sell и назовём её OpenSELL
void OpenSELL()
  {
//--- Создадим запрос на сервер и получим ответ с результатом
   MqlTradeRequest request= { 0 };
   MqlTradeResult result= { 0 };
//--- Создадим переменные необходимые для работы с сервером
   double price= SymbolInfoDouble ( Symbol (), SYMBOL_ASK );
   double point= SymbolInfoDouble ( Symbol (), SYMBOL_POINT );
   int digits=( int ) SymbolInfoInteger ( Symbol (), SYMBOL_DIGITS );
   request.action= TRADE_ACTION_DEAL ;
   request.symbol= Symbol ();
   request.volume=Lot;
   request.deviation= 2 ;
   request.magic=Magic_Number;
   request.type= ORDER_TYPE_SELL ;
   request.price= NormalizeDouble (price,digits);
   /*Точно также создадим запрос на торговый сервер request.sl, в котором укажем, где должен
     находиться уровень стоп лосс относительно цены, по которой открылась позиция "SELL".
     Уровень SL теперь должен находиться выше цены, поэтому пишем price+SL*point. Снова для
     нормализации уровня SL применим функцию преобразования данных NormalizeDouble, где обязательно
     умножим уровень SL на point (размер одного пункта) и укажем digits(количество знаков после запятой).
   */
   request.sl= NormalizeDouble (price+SL*point,digits);
   if (! OrderSend (request,result))
       PrintFormat ( "OrderSend error %d" , GetLastError ());
   PrintFormat ( "retcode=%u  deal=%I64u  order=%I64u" ,result.retcode,result.deal,result.order);
  }
//+------------------------------------------------------------------+
//| All Position Close function                                      |
//+------------------------------------------------------------------+

//--- Создадим функцию для закрытия всех позиций и назовем её CloseALL
void CloseALL()
  {
//---  Создадим запрос на сервер и получим ответ с результатом
   MqlTradeRequest request;
   MqlTradeResult   result;
//--- перебираем все открытые позиции
   for ( int i= PositionsTotal ()- 1 ; i>= 0 ; i--)
     {
       //--- определяем параметры
       ulong   ticket= PositionGetTicket (i);                                             // тикет позиции
       string symbol= PositionGetString ( POSITION_SYMBOL );                               // символ
       int     digits=( int ) SymbolInfoInteger (symbol, SYMBOL_DIGITS );                     // количество знаков после запятой
       ulong   magic= PositionGetInteger ( POSITION_MAGIC );                               // MagicNumber позиции
       double volume= PositionGetDouble ( POSITION_VOLUME );                               // объем позиции
       ENUM_POSITION_TYPE type=( ENUM_POSITION_TYPE ) PositionGetInteger ( POSITION_TYPE ); // тип позиции
       //--- выводим информацию о позиции
       PrintFormat ( "#%I64u %s  %s  %.2f  %s [%I64d]" ,
                  ticket,
                  symbol,
                   EnumToString (type),
                  volume,
                   DoubleToString ( PositionGetDouble ( POSITION_PRICE_OPEN ),digits),
                  magic);
       //--- если MagicNumber совпадает
       if (magic==Magic_Number)
        {
         //--- обнуляем значения запроса на сервер и результата ответа
         ZeroMemory (request);
         ZeroMemory (result);
         //--- устанавливаем параметры операции
         request.action   = TRADE_ACTION_DEAL ;   // тип торговой операции (немедленное исполнение)
         request.position =ticket;               // тикет позиции
         request.symbol   =symbol;               // символ
         request.volume   =volume;               // объём позиции
         request.deviation= 2 ;                   // допустимое отклонение от цены
         request.magic    =Magic_Number;         // MagicNumber позиции
         if (type== POSITION_TYPE_BUY )             // если тип позиции "покупка"
           {
             //--- запрашиваем лучшее предложение цены на "продажу" по текущему символу
            request.price= SymbolInfoDouble (symbol, SYMBOL_BID );
             //--- запрашиваем тип рыночного ордера на "продажу" и закрываем позицию встречным ордером
            request.type = ORDER_TYPE_SELL ;
           }
         else // в противном случае
           {
             //--- запрашиваем лучшее предложение цены на "покупку" по текущему символу
            request.price= SymbolInfoDouble (symbol, SYMBOL_ASK );
             //--- запрашиваем тип рыночного ордера на "покупку" и закрываем позицию встречным ордером
            request.type = ORDER_TYPE_BUY ;
           }
         //--- выводим информацию о закрытии
         PrintFormat ( "Close #%I64d %s %s" ,ticket,symbol, EnumToString (type));
         //--- отправляем запрос
         if (! OrderSend (request,result))
             PrintFormat ( "OrderSend error %d" , GetLastError ());   // если отправить запрос не удалось, выводим код ошибки
         //--- информация об операции
         PrintFormat ( "retcode=%u  deal=%I64u  order=%I64u" ,result.retcode,result.deal,result.order);
         //---
        }
     }
  }
//+------------------------------------------------------------------+
//| Tick Up function                                                 |
//+------------------------------------------------------------------+
double TickUP()
  {
//---
   double price= SymbolInfoDouble ( Symbol (), SYMBOL_ASK );
   double point= SymbolInfoDouble ( Symbol (), SYMBOL_POINT );
   int digits=( int ) SymbolInfoInteger ( Symbol (), SYMBOL_DIGITS );
   double price1= NormalizeDouble (price+point,digits);
   return (price1);
  }
//+------------------------------------------------------------------+
//| Tick DOWN function                                               |
//+------------------------------------------------------------------+
double TickDOWN()
  {
//---
   double price= SymbolInfoDouble ( Symbol (), SYMBOL_ASK );
   double point= SymbolInfoDouble ( Symbol (), SYMBOL_POINT );
   int digits=( int ) SymbolInfoInteger ( Symbol (), SYMBOL_DIGITS );
   double price2= NormalizeDouble (price-point,digits);
   return (price2);
  }
  
//+------------------------------------------------------------------+
//| Шаблон трейлинг стопа предоставленный Василием Соколовым         |
//+------------------------------------------------------------------+
  
//+------------------------------------------------------------------+
//| Устанавливает sl позиции BUY в безубыток                         |
//+------------------------------------------------------------------+
void SetBreakevenForBuyPosition() // установить безубыток для Buy позиции
  {
//---
   ;
  }
//+------------------------------------------------------------------+
//| Тралит стоп-лосс позиции BUY вслед за ценой                      |
//+------------------------------------------------------------------+
void TrailingStopLossForBuyPosition() // перетащить Stop Loss для Buy позиции
  {
//---
   ;
  }
//+------------------------------------------------------------------+
//| Устанавливает sl позиции SELL в безубыток                        |
//+------------------------------------------------------------------+
void SetBreakevenForSellPosition() // установить безубыток для Sell позиции
  {
//---
   ;
  }
//+------------------------------------------------------------------+
//| Тралит стоп-лосс позиции SELL вслед за ценой                     |
//+------------------------------------------------------------------+
void TrailingStopLossForSellPosition() // перетащить Stop Loss для Sell позиции
  {
//---
   ;
  }
//+------------------------------------------------------------------+
 

Herkese iyi günler ve iyi bir ruh hali!

MQL5 programlama dilini öğrenmeye devam ediyorum. Dün Al ve Sat pozisyonları için zararı durdurmayı başabaşa taşıma kodunu yazdım. Kodu ayrıntılı yorum yapmadan gönderiyorum. Bir programlama okulunun 1. sınıfındaki bir öğrencinin erişebileceği bir sunumdaki her bir kod satırının ayrıntılı bir açıklamasıyla Uzman Danışmanın tam sürümü daha sonra Trailing_Stop.mq5 çalışma adıyla bir dosya biçiminde yayınlanacaktır. . Kodu yayınlamadan önce EA, strateji test cihazında test edildi. Herhangi bir sorun tespit edilmedi.

Saygılarımla, Vladimir.

 //+------------------------------------------------------------------+
//| Устанавливает sl позиции BUY в безубыток                         |
//+------------------------------------------------------------------+
void SetBreakevenForBuyPosition() // функция "Установить безубыток для позиции Buy"
  {
//---  Создадим запрос на сервер и получим ответ с результатом
   MqlTradeRequest request={ 0 };
   MqlTradeResult result={ 0 };
//--- Запустим цикл перебора всех открытых позиций
   for ( int i= PositionsTotal ()- 1 ; i>= 0 ; i--)
     {
       //--- параметры позиции Buy
       ulong   ticket= PositionGetTicket (i);                         // тикет позиции
       string symbol= PositionGetString ( POSITION_SYMBOL );           // символ
       int     digits=( int ) SymbolInfoInteger (symbol, SYMBOL_DIGITS ); // количество знаков после запятой
       ulong   magic= PositionGetInteger ( POSITION_MAGIC );             // MagicNumber позиции
       double volume= PositionGetDouble ( POSITION_VOLUME );           // объем позиции
       double sl= PositionGetDouble ( POSITION_SL );                   // Stop Loss позиции
       ENUM_POSITION_TYPE type=( ENUM_POSITION_TYPE ) PositionGetInteger ( POSITION_TYPE );   // тип позиции
       //--- выводим информацию о позиции Buy
       PrintFormat ( "#%I64u %s  %s  %.2f  %s  sl: %s  tp: %s  [%I64d]" ,
                  ticket,
                  symbol,
                   EnumToString (type),
                  volume,
                   DoubleToString ( PositionGetDouble ( POSITION_PRICE_OPEN ),digits),
                   DoubleToString (sl,digits),
                  magic);
       //--- если MagicNumber совпадает
       if (magic==Magic_Number)
        {
         double point= SymbolInfoDouble (symbol, SYMBOL_POINT );
         double price= SymbolInfoDouble ( Symbol (), SYMBOL_ASK );
         double price_open= PositionGetDouble ( POSITION_PRICE_OPEN );
         double price_breakeven= NormalizeDouble (price_open+BreakevenLevel*point,digits);
         //--- зададим условие переноса Stop Loss в безубыток для позиции Buy
         if (type== POSITION_TYPE_BUY && price==price_breakeven)
           {
            sl= NormalizeDouble (price_open,digits);
           }
         //--- обнуляем значения запроса и результата
         ZeroMemory (request);
         ZeroMemory (result);
         //--- устанавливаем параметры операции
         request.action= TRADE_ACTION_SLTP ; // тип торговой операции
         request.position=ticket;           // тикет позиции
         request.symbol=symbol;             // символ
         request.sl=sl;                     // Stop Loss позиции
         request.magic=Magic_Number;       // MagicNumber позиции
         //--- выводим информацию о модификации
         PrintFormat ( "Modify #%I64d %s %s" ,ticket,symbol, EnumToString (type));
         //--- отправка запроса
         if (! OrderSend (request,result)) // если отправить запрос не удалось
             PrintFormat ( "OrderSend error %d" , GetLastError ()); // выводим код ошибки
         //--- информация об операции
         PrintFormat ( "retcode=%u  deal=%I64u  order=%I64u" ,result.retcode,result.deal,result.order);
        }
     }
  }
//+------------------------------------------------------------------+
//| Устанавливает sl позиции SELL в безубыток                        |
//+------------------------------------------------------------------+
void SetBreakevenForSellPosition() // функция "Установить безубыток для позиции Sell"
  {
//---  Создадим запрос на сервер и получим ответ с результатом
   MqlTradeRequest request={ 0 };
   MqlTradeResult result={ 0 };
//--- Запустим цикл перебора всех открытых позиций
   for ( int i= PositionsTotal ()- 1 ; i>= 0 ; i--)
     {
       //--- параметры позиции Sell
       ulong   ticket= PositionGetTicket (i);                         // тикет позиции
       string symbol= PositionGetString ( POSITION_SYMBOL );           // символ
       int     digits=( int ) SymbolInfoInteger (symbol, SYMBOL_DIGITS ); // количество знаков после запятой
       ulong   magic= PositionGetInteger ( POSITION_MAGIC );             // MagicNumber позиции
       double volume= PositionGetDouble ( POSITION_VOLUME );           // объем позиции
       double sl= PositionGetDouble ( POSITION_SL );                   // Stop Loss позиции
       ENUM_POSITION_TYPE type=( ENUM_POSITION_TYPE ) PositionGetInteger ( POSITION_TYPE );   // тип позиции
       //--- выводим информацию о позиции Sell
       PrintFormat ( "#%I64u %s  %s  %.2f  %s  sl: %s  tp: %s  [%I64d]" ,
                  ticket,
                  symbol,
                   EnumToString (type),
                  volume,
                   DoubleToString ( PositionGetDouble ( POSITION_PRICE_OPEN ),digits),
                   DoubleToString (sl,digits),
                  magic);
       //--- если MagicNumber совпадает
       if (magic==Magic_Number)
        {
         double point= SymbolInfoDouble (symbol, SYMBOL_POINT );
         double price= SymbolInfoDouble ( Symbol (), SYMBOL_BID );
         double price_open= PositionGetDouble ( POSITION_PRICE_OPEN );
         double price_breakeven= NormalizeDouble (price_open-BreakevenLevel*point,digits);
         //--- зададим условие переноса Stop Loss в безубыток для позиции Sell
         if (type== POSITION_TYPE_SELL && price==price_breakeven)
           {
            sl= NormalizeDouble (price_open,digits);
           }
         //--- обнуляем значения запроса и результата
         ZeroMemory (request);
         ZeroMemory (result);
         //--- устанавливаем параметры операции
         request.action= TRADE_ACTION_SLTP ; // тип торговой операции
         request.position=ticket;           // тикет позиции
         request.symbol=symbol;             // символ
         request.sl=sl;                     // Stop Loss позиции
         request.magic=Magic_Number;       // MagicNumber позиции
         //--- выводим информацию о модификации
         PrintFormat ( "Modify #%I64d %s %s" ,ticket,symbol, EnumToString (type));
         //--- отправка запроса
         if (! OrderSend (request,result)) // если отправить запрос не удалось
             PrintFormat ( "OrderSend error %d" , GetLastError ()); // выводим код ошибки
         //--- информация об операции
         PrintFormat ( "retcode=%u  deal=%I64u  order=%I64u" ,result.retcode,result.deal,result.order);
        }
     }
  }
//+------------------------------------------------------------------+
 
MrBrooklin :

Herkese iyi günler ve iyi bir ruh hali!

MQL5 programlama dilini öğrenmeye devam ediyorum. Bugün, söz verdiğim gibi, son durak yazmak için tasarlanmış Expert Advisor şablonunun kodunu herkesin görmesi için gönderiyorum. EA şablon kodunun oldukça hantal olması nedeniyle, yorumları olabildiğince azaltmak zorunda kaldık. Bir programlama okulunun 1. sınıfındaki bir öğrencinin erişebileceği bir sunumda, her kod satırı hakkında ayrıntılı yorumlar içeren Expert Advisor'ın tam sürümü, daha sonra Trailing_Stop.mq5 çalışma adıyla bir dosya biçiminde yayınlanacaktır. sitede başka bir "ayak bezi" üretmemek için.

...

Çok iyi. Ana fikir doğru bir şekilde yakalanmıştır. Özellikle geliştirme sürecini beğendim:

BayBrooklin :

Herkese iyi günler ve iyi bir ruh hali!

MQL5 programlama dilini öğrenmeye devam ediyorum. Dün Al ve Sat pozisyonları için zararı durdurmayı başabaşa taşıma kodunu yazdım. ...

Onlar. Her şey doğru. Tek bir yere baskın yaparak sorunu bir kerede çözmenize gerek yok. Ve yaptığınız gibi yavaş yavaş yapın. Öncelikle OnTick işlevindeki ana mantığı ve OpenBUY, OpenSELL, TickUP, TickDown gibi ana işlevleri açıklıyorsunuz.

Ardından, bu ana kod hata ayıklandığında, derlendiğinde ve yetenekleri dahilinde çalıştığında, diğer işlevleri tanımlamaya başlarsınız. Bu, ertesi gün, hatta bir hafta yapılabilir. Bu durumda, ana kodun değiştirilmesi gerekmez. Neden, bence zaten görüyorsun.

Şimdi bu geliştirme tarzını geliştirmeniz gerekiyor: işlevler yazmaya devam edin, bunlar aracılığıyla mevcut koda işlevsellik ekleyin. Mevcut program düzgün çalışmalıdır. Zorluk artmamalı . Eklediğiniz işlevler basit ve net sonuçlar vermelidir. İsimleri sizin için çok basit ve anlaşılır olmalıdır. Bunu yapamıyorsanız, belki de nedeni, sorunu çözmek için tek bir fonksiyon değil iki hatta üç fonksiyon yazmanız gerektiğidir. İlk başta, uygulamanın genel çerçevesini tanımlamak zor olacaktır. Bu nedenle, daha deneyimli yoldaşlardan tavsiye almak daha iyidir. Zamanla, bu tür şablonları kendiniz geliştirmeyi öğreneceksiniz.

Fonksiyonun kendisine atanan görevleri çözmesi için, zaman içinde bu tür fonksiyonların içinde daha fazla dil yapısı kullanmanız gerekecektir. Sonra yavaş yavaş ve en önemlisi organik olarak dil yapıları bilginizi genişletecek, döngüleri, dizileri öğrenecek ve hatta işaretçilerle çalışacaksınız.

Aslında, kapsanan materyali henüz konsolide etmemiş olsanız da, programlamadaki en zor şeyi zaten öğrendiniz. Birleştirmek için bunu birçok kez tekrarlamak kalır. O zaman temelde yeni bir şey olmayacak, her şey aynı: Genel şablon -> İşlev adlarının ve parametrelerinin açıklaması -> Bu işlevlerin içeriklerinin yazılması -> bu işlevlerin merkezi blokta düzenlenmesi. Herşey. Sadece beceriyi geliştirmek ve tutarlı olmak için kalır. Benzer döngüler ve diziler kullanmaya başlayacağınız çeşitli ek yapılar sadece ayrıntılardır, bazen akıllıca yapılır, ancak ayrıntılardan başka bir şey değildir.

 
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.
 

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

 void OnTick ()
  {
//--- Зададим время открытия и закрытия позиции
   MqlDateTime time_current,time_open,time_open1,time_close;
   TimeToStruct ( TimeCurrent (),time_current);
   TimeToStruct (( D'1970.01.01 09:00:00' ),time_open);
   TimeToStruct (( D'1970.01.01 09:01:00' ),time_open1);
   TimeToStruct (( D'1970.01.01 23:50:00' ),time_close);
//--- Зададим условия для открытия позиций 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);
   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();}
   else
     {
       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
         && (TickDOWN()==(price-point)))
        {OpenSELL();}
     }
   if (time_current.hour==time_close.hour && time_current.min==time_close.min)
      CloseALL();
}

Ö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:

TickUP()==(price+point)

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)

 
Vasiliy Sokolov :

Çok iyi. Ana fikir doğru bir şekilde yakalanmıştır. Özellikle geliştirme sürecini beğendim:

Onlar. Her şey doğru. Tek bir yere baskın yaparak sorunu bir kerede çözmenize gerek yok. Ve yaptığınız gibi yavaş yavaş yapın. Öncelikle OnTick işlevindeki ana mantığı ve OpenBUY, OpenSELL, TickUP, TickDown gibi ana işlevleri açıklıyorsunuz.

Ardından, bu ana kod hata ayıklandığında, derlendiğinde ve yetenekleri dahilinde çalıştığında, diğer işlevleri tanımlamaya başlarsınız. Bu, ertesi gün, hatta bir hafta yapılabilir. Bu durumda, ana kodun değiştirilmesi gerekmez. Neden, bence zaten görüyorsun.

Şimdi bu geliştirme tarzını geliştirmeniz gerekiyor: işlevler yazmaya devam edin, bunlar aracılığıyla mevcut koda işlevsellik ekleyin. Mevcut program düzgün çalışmalıdır. Zorluk artmamalı . Eklediğiniz işlevler basit ve net sonuçlar vermelidir. İsimleri sizin için çok basit ve anlaşılır olmalıdır. Bunu yapamıyorsanız, belki de nedeni, sorunu çözmek için tek bir fonksiyon değil iki hatta üç fonksiyon yazmanız gerektiğidir.

Fonksiyonun kendisine atanan görevleri çözmesi için, zaman içinde bu tür fonksiyonların içinde daha fazla dil yapısı kullanmanız gerekecektir. Sonra yavaş yavaş ve en önemlisi organik olarak dil yapıları bilginizi genişletecek, döngüleri, dizileri öğrenecek ve hatta işaretçilerle çalışacaksınız.

Merhaba Vasili! Zamanında tavsiye ve desteğiniz için çok teşekkür ederim. İş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/ru/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. Umarım bu konu tüm yeni başlayanlar için MQL5 programlama dilini sıfırdan öğrenmek için iyi bir yardımcı olur.

Saygılarımla, Vladimir.

Neden: