MQL5 언어를 처음부터 자가 학습 - 페이지 71

 
MrBrooklin :

이고르, MQL5 언어를 배우고자 하는 열망은 사라지지 않고 오히려 심화될 뿐이다. 내가 왜 그렇게 멍청하고 이 루프 연산자로 간단한 것을 이해할 수 없는지 깨집니다. 가장 중요한 것은 코드가 루프 연산자 없이 완벽하게 작동하지만 루프가 있으면 완전히 마비된다는 것입니다. 나는 여전히 진실에 다가갈 것이다. 사실, 독학할 시간이 훨씬 줄어들었습니다. 검역이 끝났고 직장에서 언어를 공부하는 드문 순간이 있습니다. 나는 주로 저녁과 밤늦게까지 언어를 다룹니다.

마지막으로 Trailing Stop 코드 작성을 직접 진행하려면 2가지 작업을 완전히 이해하고 해결해야 합니다.

  1. for 루프 연산자 를 사용하여 모든 기호의 모든 열린 위치를 반복하는 코드를 작성하고, 없는 경우 09:00:00에서 09:01:00 사이의 시간 간격으로 Buy 위치를 열고 강제로 닫습니다. 23:50:00에 거래일 동안 손절매가 작동하지 않는 경우. 앞서 쓴 것처럼 for 루프 연산자가 없으면 모든 것이 완벽하게 작동합니다. 이제 동일한 결과를 얻고 싶지만 루프가 있습니다.
  2. 09:00:00부터 09:01:00까지의 시간 간격에 나타나는 첫 번째 눈금 에서 위치를 여는 방향 을 결정하는 2개의 함수를 작성하십시오. 첫 번째 눈금이 올라가면 매수 포지션이 열리고 첫 번째 눈금이 내려가면 매도 포지션이 열립니다. 이것은 전략이 아니라 무작위 조건을 사용하지 않기 위한 나의 "위시리스트" 입니다.
안부 인사를 전합니다. 블라디미르.

블라디미르, 당신은 일종의 정글로 올라가고 있습니다. 당신은 템플릿을 받았습니다: https://www.mql5.com/ru/forum/352460/page58#comment_18726492 당신은 그것을 무시하고 당신의 마음으로 진행하기로 결정했습니다. 이 길은 어렵고 몇 년이 걸릴 수 있습니다. 그 과정에서 C, C++, Rust, C#, 다형성, 상속, 포인터 역참조, 동적 유형 캐스팅을 배우지만 목표는 이미 결정했습니다. 확인하거나 이동합니다. 목적지까지 최단 경로로 이동해야 합니다. 후행을 원하면 후행을 작성하십시오. 이를 위해 C 및 C++를 배울 필요가 없습니다. 이것은 원하는 경우 나중에 모두 선택 사항입니다.

for 루프의 상황이 예시적입니다. 이것은 사이트에 적용해야 하는 강력한 디자인입니다. 네팅과 보조 알고리즘이 있습니다. 그러므로 위치의 열거도 없고 마술도 없으며 따라서 이 주기도 없습니다. 당연히 그것 없이는 모든 것이 당신을 위해 작동하고주기와 함께 기름을 얻습니다. 그러나 당신은 완고하게 그것을 사용하려고 노력합니다. 분명히 이것은 그 자체로 끝입니다. 가능한 한 모든 것과 모든 사람을 가능한 한 많이 사용하는 것입니다.

 
Vasiliy Sokolov :

블라디미르, 당신은 일종의 정글로 올라가고 있습니다. 당신은 템플릿을 받았습니다: https://www.mql5.com/ru/forum/352460/page58#comment_18726492 당신은 그것을 무시하고 당신의 마음으로 진행하기로 결정했습니다. 이 길은 어렵고 몇 년이 걸릴 수 있습니다. 그 과정에서 C, C++, Rust, C#, 다형성, 상속, 포인터 역참조, 동적 유형 캐스팅을 배우지만 목표는 이미 결정했습니다. 확인하거나 이동합니다. 목적지까지 최단 경로로 이동해야 합니다. 후행을 원하면 후행을 작성하십시오. 이를 위해 C 및 C++를 배울 필요가 없습니다. 이것은 원하는 경우 나중에 모두 선택 사항입니다.

for 루프의 상황이 예시적입니다. 이것은 사이트에 적용해야 하는 강력한 디자인입니다. 네팅과 보조 알고리즘이 있습니다. 그러므로 위치의 열거도 없고 마술도 없으며 따라서 이 주기도 없습니다. 당연히 그것 없이는 모든 것이 당신을 위해 작동하고주기와 함께 기름을 얻습니다. 그러나 당신은 완고하게 그것을 사용하려고 노력합니다. 분명히 이것은 그 자체로 끝입니다. 가능한 한 모든 것과 모든 사람을 가능한 한 많이 사용하는 것입니다.

안녕하세요 바실리님!

항상 제 시간에 주제에 연결하고 올바른 길로 인도해 주셔서 감사합니다. 이제 모든 것을 정리하겠습니다.

  1. 템플릿은 친절하게 제게 제공했을 때 정확히 Expert Advisor에 삽입되었습니다. 특별히 감사합니다!
  2. 내 어리석음에 나는 Trailin Stop이 있는 Expert Advisor가 전략 테스터 에서 확인되어야 한다고 결정했지만, 적어도 하나의 포지션을 자동으로 열지 않고 이것을 하는 방법을 생각하지 못했습니다. 그래서 정글은 '본격 어드바이저'를 쓰면서 등장했다. 어드바이저에는 그런 전략이 없어서 따옴표로 묶었습니다. 난 그냥 임의 의 조건을 사용하여 위치를 여는 것을 원하지 않았습니다.
  3. 당신을 제외한 어떤 대담도 이 상황에서 위치를 열거하는 데 for 루프가 필요하지 않다고 제안했습니다. 내 말은, 나는 오랫동안 추측하고 물을 수 있었다 - 사이클이 전혀 필요합니까? 필요하지 않은 것으로 나타났습니다. 다시 한 번 팁 감사합니다!
  4. 마지막으로 후행 정지의 직접 쓰기로 진행하면서 이미 시작된 것을 중간에 종료하지 않으 려면 네팅을 여는 방향을 결정하는 2개의 함수 코드를 작성하면 됩니다. 매수 또는 매도 포지션 .
  5. 네, 독학이 시작되고 있다는 점에 전적으로 동의합니다. 하지만 내가 미지의 구불구불한 길을 걷고 있다는 점을 감안한다면 조금이나마 여유를 가질 수 있기를 바란다.
  6. 독학 기간 내내 엄청난 양의 정보를 얻었고 이제는 이를 합리화할 뿐만 아니라 실제로 적용해보려고 노력하고 있습니다. 이를 위해 저는 CodeBase의 고문을 고용하여 완료했으며 현재 2주 동안 한 외환 딜러의 데모 계정에 있었습니다. 결과는 정확히 그에게 기대했던 것입니다. 실계좌를 넣는 순간이 멀지 않았다. 이것은 이미 플러스입니다!
  7. 나는 자기 학습의 속도를 쫓는 것이 아닙니다. 왜냐하면. 나는 이전에 정보의 과잉으로 인해 주기적으로 혼미가 발생한다고 썼습니다.
  8. 전체 기간에 걸쳐 자율 학습은 코드를 컴파일한 후 나타나는 영어 단어와 구문을 점차적으로 암기하기 시작했습니다. 저는 구글 번역을 거의 보지 않습니다. 이것은 또한 자기 학습의 긍정적인 순간이기도 합니다.
  9. 나는 트레일링 스톱에 대한 완전한 준비가 형성되면 정확히 Expert Advisor에 이미 작성한 모든 것을 게시 할 것입니다. 토요일에 끝내도록 노력하겠습니다 . 이 순간부터 후행 정지 코드 작성에 대한 주요 작업이 시작됩니다.

Vasily, 나는 지도와 건설적인 비판에 매우 감사드립니다! 또한 MQL5 프로그래밍 언어를 처음부터 자가 학습하는 데 도움을 준 이 주제의 모든 참가자에게도 깊은 감사를 전합니다.

자기 학습은 계속됩니다. 계속(계속).

안부 인사를 전합니다. 블라디미르.

 
Андрей :

좋은 오후에요 여러분!

나는 조금 추가하고 싶었습니다. 주제는 흥미 롭습니다. " MQL5 언어 를 완전히 처음부터 스스로 배우기"라는 아이디어는 완전히 사실이 아닌 것 같습니다. 사람이 프로그래밍에서 0이면 그는 먼저 프로그래밍 방법을 배워야 합니다. 목표가 처음부터 MQL로 프로그래밍하는 방법을 배우는 것이라면, 먼저 최소한 C로 프로그래밍하는 방법을 배워야 하고, 그런 다음 MQL이 본질적으로 C이지만 전문화되어 있기 때문에 MQL 로 작성하는 방법을 배워야 합니다. 특정 작업을 위해 날카롭게 된 사람은 주기가 어떻게 작동하는지 이해하지 못하지만 이미 모든 프로그램에서 작성하려고 합니다. 러시아어를 몰라도 페냐를 배우려는 것과 같으니...

또 다른 점은 C는 프로그래밍 학습에 가장 친숙한 언어가 아니며 단순하지만 너무 간결하여 초보자가 알고리즘, 데이터 유형, 부울 대수에 대한 기본 개념 없이 코드를 읽고 이해하기 어렵다는 것입니다. C에서 연속 3개의 문자는 다른 언어에서 여러 줄의 의미를 전달할 수 있습니다.

처음부터 간단히 프로그래밍하는 방법을 배우려면 컴퓨터와 하나의 언어(어느 것이든 상관 없음)로 말하는 방법을 배우기 위해 가장 쉬운 풀이 책인 Pascal부터 시작하는 것이 좋습니다. (편안한 2-3 주), 그 다음 C (여기서, 파스칼 후, 근면으로 최대 주, 구문을 마스터, 나는 언어의 기본 지식에 대해 이야기하고 있습니다!) 그리고 나서 다음과 같은 전문 언어를 취하십시오. MQL은 MQL이 C이기 때문에 몇 가지 문제가 있지만 단순화도 있습니다. 한 작업에서 날카롭게 되고 컴파일러는 명백한 자체를 알고 있기 때문입니다. 그리고 C는 차례로 RAR에 의해 압축된 그런 파스칼이지만 파스칼은 거의 영어입니다 =).

이제 주기:

내가 프로그래밍을 배울 때 대수학의 합과의 유비가 나를 도왔습니다. 여기서 n의 초기 값, n의 최종 값 및 계산을 위한 이 n이 있는 공식이 표시됩니다.

안녕 안드레이! 나는 기본적으로 당신의 의견에 전적으로 동의합니다. 나는 그것을 가지고 있지도 않고 그것을 가져본 적도 없습니다. 그러나 그들이 말했듯이 모스크바는 즉시 건설되지 않았습니다! 조언과 조언 감사합니다!

안부 인사를 전합니다. 블라디미르.

 
Roman Shiredchenko :

네. 동의합니다 - 그의 코드도 윙윙 거리고 있습니다! 당신은 처음부터 자신을 감습니다. 서두르지 않고 침착하게 코드를 이해하면 됩니다. 여기 에 모든 것이 기본입니다 - 우리는 선택하고 트롤링합니다. (훨씬 쉽습니다 - 필수 위치를 선택하는 주제 ... :-))

또한 포함된 파일 - 이는 해당 파일이 함수 형태로 유형 코드에 위치한다는 것을 의미합니다.

코드와 링크에 대해 Roman에게 감사드립니다! 차분하게 코드를 이해하고 절대 서두르지 않습니다!

안부 인사를 전합니다. 블라디미르.

 

좋은 하루와 좋은 분위기 모두!

계속해서 MQL5 프로그래밍 언어를 공부하고 있습니다. 오늘 약속한 대로 모든 사람이 후행 중지를 작성하도록 설계된 Expert Advisor 템플릿 의 코드를 볼 수 있도록 게시합니다. EA 템플릿 코드가 상당히 번거로워 댓글을 최대한 줄여야 했습니다. 프로그래밍 학교 1학년 학생이 액세스할 수 있는 프레젠테이션에서 각 코드 행에 대한 자세한 설명이 포함된 Expert Advisor의 전체 버전은 나중에 Trailing_Stop.mq5 라는 작업 이름을 가진 파일 형식으로 게시됩니다. 사이트에서 또 다른 "풋웨어"를 생산하지 않기 위해.

코드를 게시하기 전에 전략 테스터 에서 EA를 테스트했습니다. 문제가 확인되지 않았습니다. EA는 상계 포지션 회계 시스템을 사용합니다. 이 회계 시스템은 동일한 기호(금융 상품)에 대한 계정에 한 번에 하나의 미결 위치 만 있을 수 있음을 의미합니다.

현재 Expert Advisor는 다음을 수행할 수 있습니다.

  1. 설치할 거래 계정을 확인하십시오. 어드바이저가 데모 계정에 설치된 경우 작업을 계속할 수 있는 권한이 메시지 창에 나타납니다. 실제 계정 에 고문을 설치하려고 시도하면 메시지 창에 작업을 계속할 수 없다는 경고가 표시되고 그 후 거래 터미널 의 작업 창에서 자동으로 삭제됩니다.
  2. 거래일 정확히 오전 9시에 한 번. 모스크바 시간에 따라 첫 번째 눈금이 지시되는 방향으로 한 위치를 자동으로 엽니다. 예를 들어 오전 9시에 모스크바 시간으로 첫 번째 눈금이 위쪽으로 향하게 됩니다. 즉, BUY 위치가 열리고 첫 번째 눈금이 아래로 내려가면 SELL 위치가 열립니다.
  3. 손절매 크기를 설정합니다.
  4. 로트 크기를 설정합니다.
  5. 후행 정지가 작동하는 데 필요한 다른 매개변수를 설정하십시오.

또한 EA에는 Vasily Sokolov가 친절하게 제공한 사전 설치된 템플릿이 있으며, 이 템플릿은 자가 학습 과정에서 코드로 채워집니다.

경고!!!

Expert Advisor는 데모 계정 및 교육 목적으로만 자율 학습 계획에 따라 개발되었습니다! 실제 계정으로 거래하고 수익을 내기 위한 것이 아닙니다!

안부 인사를 전합니다. 블라디미르.

 //+------------------------------------------------------------------+
//|                                                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 позиции
  {
//---
   ;
  }
//+------------------------------------------------------------------+
 

좋은 하루와 좋은 분위기 모두!

계속해서 MQL5 프로그래밍 언어를 공부하고 있습니다. 어제 저는 매수 및 매도 포지션에 대해 손절매 를 손익분기점으로 이동하는 코드를 작성했습니다. 지금까지 자세한 설명 없이 코드를 게시하고 있습니다. 프로그래밍 학교 1학년 학생이 액세스할 수 있는 프레젠테이션에서 코드의 각 줄에 대한 자세한 설명이 포함된 Expert Advisor의 전체 버전은 나중에 작업 이름 Trailing_Stop.mq5 의 파일 형식으로 게시됩니다. . 코드를 게시하기 전에 전략 테스터 에서 EA를 테스트했습니다. 문제가 확인되지 않았습니다.

안부 인사를 전합니다. 블라디미르.

 //+------------------------------------------------------------------+
//| Устанавливает 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 :

좋은 하루와 좋은 분위기 모두!

계속해서 MQL5 프로그래밍 언어를 공부하고 있습니다. 오늘 약속한 대로 모든 사람이 후행 중지를 작성하도록 설계된 Expert Advisor 템플릿 의 코드를 볼 수 있도록 게시합니다. EA 템플릿 코드가 상당히 번거로워 댓글을 최대한 줄여야 했습니다. 프로그래밍 학교 1학년 학생이 액세스할 수 있는 프레젠테이션에서 각 코드 행에 대한 자세한 설명이 포함된 Expert Advisor의 전체 버전은 나중에 Trailing_Stop.mq5 라는 작업 이름을 가진 파일 형식으로 게시됩니다. 사이트에서 또 다른 "풋웨어"를 생산하지 않기 위해.

...

아주 잘. 주요 아이디어가 올바르게 캡처되었습니다. 특히 개발 프로세스가 마음에 들었습니다.

브루클린 씨 :

좋은 하루와 좋은 분위기 모두!

계속해서 MQL5 프로그래밍 언어를 공부하고 있습니다. 어제 저는 매수 및 매도 포지션에 대해 손절매 를 손익분기점으로 이동하는 코드를 작성했습니다. ...

저것들. 모든 것이 정확합니다. 한 곳에서 급하게 문제를 한 번에 해결할 필요가 없습니다. 그리고 당신이 한 것처럼 점차적으로 그것을하십시오. 먼저 OnTick 기능의 주요 로직과 OpenBUY, OpenSELL, TickUP, TickDown과 같은 주요 기능을 설명합니다.

그런 다음 해당 기본 코드가 디버깅, 컴파일되고 해당 기능 내에서 작동하면 다른 기능을 설명하기 시작합니다. 이것은 다음 날 또는 심지어 일주일 동안 수행할 수 있습니다. 이 경우 메인 코드는 변경할 필요가 없습니다. 왜, 나는 당신이 이미 그것을보고 있다고 생각합니다.

이제 이러한 개발 스타일을 연마해야 합니다. 계속해서 기능을 작성하고 기존 코드에 기능을 추가하십시오. 기존 프로그램이 올바르게 작동해야 합니다. 난이도가 증가하지 않아야 합니다 . 추가한 함수는 간단하고 명확한 결과를 반환해야 합니다. 그들의 이름은 매우 간단하고 명확해야 합니다. 만약 그렇게 할 수 없다면, 아마도 그 이유는 문제를 해결하기 위해 하나의 함수가 아니라 두 개, 세 개까지 작성해야 하기 때문일 것입니다. 처음에는 애플리케이션의 일반적인 프레임워크를 정의하기 어려울 것입니다. 따라서 경험이 많은 동료들에게 조언을 구하는 것이 좋습니다. 시간이 지남에 따라 이러한 템플릿을 직접 개발하는 방법을 배우게 됩니다.

함수가 할당된 작업을 해결하려면 시간이 지남에 따라 이러한 함수 내에서 점점 더 많은 언어 구성을 사용해야 합니다. 그런 다음 점차적으로 가장 중요하게는 언어 구성에 대한 지식을 유기적으로 확장하고 루프, 배열을 배우고 포인터로 작업할 것입니다.

사실, 아직 다루지 않은 내용을 통합하지 않았지만 프로그래밍에서 가장 어려운 것을 이미 배웠습니다. 통합하려면 이것을 여러 번 반복해야합니다. 그러면 근본적으로 새로운 것은 없으며 모든 것이 동일합니다. 일반 템플릿 -> 기능 이름 및 해당 매개변수에 대한 설명 -> 이러한 기능의 내용 작성 -> 중앙 블록에 이러한 기능 배열. 모두. 기술을 향상하고 일관성을 유지하는 것만 남아 있습니다. 루프 및 배열과 같이 사용하기 시작할 다양한 추가 구성은 세부 사항일 뿐이며 때로는 영리하게 수행되지만 세부 사항에 불과합니다.

 
그건 그렇고, 프로그램의 전체 크기에주의하십시오. 이미 중요합니다. 잘 지내고 있나요? 그건 그렇고, 초보자는 더 이상 그런 양의 코드를 작성할 수 없습니다. 변수가 혼란스러워지기 시작하고, 괄호의 중첩이 스케일을 벗어나고, 컴파일 오류가 비가 온 후에 버섯처럼 나타나기 시작합니다. 이 크기의 프로그램을 컴파일한 후에는 실패하기 시작하고 아무도 무엇이 잘못되었는지 이해할 수 없습니다. 그리고 모든 것이 어떤 이유로 당신을 위해 작동합니다), 기능 측면에서 구조적으로 어떤 일이 어떻게 일어나고 있는지 명확합니다. 한 마디로 아름다움.
 

완벽함에는 제한이 없으므로 코드에 몇 가지 설명을 더 삽입하겠습니다.

 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();
}

중요하지 않은 두 곳을 노란색으로 강조 표시했습니다.

1) 코드는 첫 번째 if와 다음 else에서 반복됩니다. 차이점은 마지막 줄과 최종 조치(OpenBUY, OpenSell)에만 있습니다.

2) else 블록에 들어가는 조건이 명확하지 않습니다. 풍요로움 때문일까요?? 조회되지 않습니다. 사실, 그들은 마지막 줄에만 의존합니다:

TickUP()==(price+point)

이것은 여기에 기능이 없다는 확실한 신호입니다.

포지션을 여는 시간이 지정된 시간과 일치하면 true를 반환하는 함수를 작성해야 합니다(조금 후에 작성하겠습니다)

 
Vasiliy Sokolov :

아주 잘. 주요 아이디어가 올바르게 캡처되었습니다. 특히 개발 프로세스가 마음에 들었습니다.

저것들. 모든 것이 정확합니다. 한 곳에서 급하게 문제를 한 번에 해결할 필요가 없습니다. 그리고 당신이 한 것처럼 점차적으로 그것을하십시오. 먼저 OnTick 기능의 주요 로직과 OpenBUY, OpenSELL, TickUP, TickDown과 같은 주요 기능을 설명합니다.

그런 다음 해당 기본 코드가 디버깅, 컴파일되고 해당 기능 내에서 작동하면 다른 기능을 설명하기 시작합니다. 이것은 다음 날 또는 심지어 일주일 동안 수행할 수 있습니다. 이 경우 메인 코드는 변경할 필요가 없습니다. 왜, 나는 당신이 이미 그것을보고 있다고 생각합니다.

이제 이러한 개발 스타일을 연마해야 합니다. 계속해서 기능을 작성하고 기존 코드에 기능을 추가하십시오. 기존 프로그램이 올바르게 작동해야 합니다. 난이도가 증가하지 않아야 합니다 . 추가한 함수는 간단하고 명확한 결과를 반환해야 합니다. 그들의 이름은 매우 간단하고 명확해야 합니다. 만약 그렇게 할 수 없다면, 아마도 그 이유는 문제를 해결하기 위해 하나의 함수가 아니라 두 개, 세 개까지 작성해야 하기 때문일 것입니다.

함수가 할당된 작업을 해결하려면 시간이 지남에 따라 이러한 함수 내에서 점점 더 많은 언어 구성을 사용해야 합니다. 그런 다음 점차적으로 가장 중요하게는 언어 구성에 대한 지식을 유기적으로 확장하고 루프, 배열을 배우고 포인터로 작업할 것입니다.

안녕하세요 바실리님! 적시에 조언과 지원을 해주셔서 대단히 감사합니다. 함수의 역할과 프로그램 코드 구성 원칙에 대한 귀하의 메시지는 MQL5 프로그래밍 언어를 배우는 데 많은 도움이 되었습니다.

  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/ru/forum/352460/page29#comment_18641729
  4. https://www.mql5.com/ru/forum/352460/page52#comment_18694985

이제 머리에 있는 정보가 이미 구조화된 형태를 취했을 때 나뿐만 아니라 다른 프로그래머가 작성한 코드를 훨씬 더 쉽게 인식할 수 있습니다. 이 주제가 모든 초보자가 MQL5 프로그래밍 언어를 처음부터 배우는 데 좋은 도움이 되기를 바랍니다.

안부 인사를 전합니다. 블라디미르.