Igor, las ganas de aprender el lenguaje MQL5 no se pierden, al contrario, sólo aumentan. Estoy desgarrado, por qué soy tan tonto y no puedo entender cosas simples con este operador de bucle. Lo principal es que sin el operador de bucle el código funciona perfectamente, pero con el bucle es un completo desastre. De todos modos, llegaré al fondo del asunto. Sin embargo, tengo mucho menos tiempo para el autoaprendizaje desde que el periodo de cuarentena ha terminado y tengo raros momentos en el trabajo en los que puedo estudiar el idioma. La mayoría de las veces estudio el idioma por la tarde y a última hora de la noche.
Necesito resolver 2 tareas para finalmente llegar a escribir el código del Trailing Stop:
Necesito escribir un código con el uso del operador de bucle for para buscar todas las posiciones abiertas para todos los símbolos, y si no hay ninguna, entonces abrir una posición de compra entre las 09:00:00 y las 09:01:00, y cerrarla por fuerza a las 23:50:00, si durante el día de negociación no se activó un stop loss. Sin el operador de bucle for, como he escrito antes, todo funciona perfectamente. Ahora quiero conseguir el mismo resultado, pero con el uso del bucle.
Escriba 2 funciones que determinen la dirección de apertura de la posición por el primer tick que aparezca en el marco temporal desde las 09:00:00 hasta las 09:01:00. Si el primer tick es alcista, se debe abrir una posición de compra; si el primer tick es bajista, se debe abrir la posición de venta correspondiente. No es una estrategia, es sólo mi "deseo" de no usar la condición aleatoria.
Atentamente, Vladimir.
Vladimir, te estás metiendo en cosas raras. Te han dado una plantilla: https://www.mql5.com/ru/forum/352460/page58#comment_18726492 La has ignorado y has decidido seguir adelante con tu ingenio. Este camino es difícil y puede llevar años. En su camino, estudie C, C++, Rust, C#, polimorfismo, herencia, desreferenciación de punteros, conversión de tipos dinámicos: Comprueba o conduce. Debes tomar el camino más corto hacia el objetivo. Si quiere que se le ponga un final, escríbalo. No es necesario estudiar C y C++ para hacerlo. Todo esto como optativa si te apetece.
La situación del bucle for es ilustrativa. Es una construcción poderosa que debe aplicarse en el lugar adecuado. Tienes una red y un algoritmo auxiliar. Por eso no hay enumeración de posiciones, no hay magos, así que no tienes este bucle. Por supuesto, todo funcionará sin él, pero el bucle sólo te hace sentir como aceite. Pero te empeñas en utilizarlo, parece ser un fin en sí mismo: utilizar la mayor cantidad posible de todo y de todos, para tener algo en reserva.
Vladimir, te estás metiendo en un pequeño berenjenal. Te dieron una plantilla: https://www.mql5.com/ru/forum/352460/page58#comment_18726492 La ignoraste y decidiste seguir adelante con tu mente. Este camino es difícil y puede llevar años. En su camino, estudie C, C++, Rust, C#, polimorfismo, herencia, desreferenciación de punteros, conversión de tipos dinámicos: Comprueba o conduce. Debes tomar el camino más corto hacia el objetivo. Si quiere que se le ponga un final, escríbalo. No es necesario estudiar C y C++ para hacerlo. Todo esto como optativa si te apetece.
La situación del bucle for es ilustrativa. Es una construcción poderosa que debe aplicarse en el lugar adecuado. Tienes una red y un algoritmo auxiliar. Por eso no hay enumeración de posiciones, no hay magos, por lo que no se tiene este bucle. Naturalmente, todo funcionará sin él, pero el bucle sólo produce aceite. Pero usted se obstina en utilizarlo, por lo que parece ser un fin en sí mismo: puede utilizar la mayor cantidad posible de todo y de cualquier cosa que tenga en stock.
¡Hola Vasily!
Gracias por unirte oportunamente al tema y orientarme en el camino correcto como siempre. Ahora permítanme explicar todo en un orden:
Una plantilla en el Asesor Experto fue insertada exactamente cuando usted me la ha proporcionado amablemente, ¡por lo que quiero expresar mi gratitud!
Decidí que había que probar un EA con Trailin Stop en el probador de estrategias, pero no sabía cómo hacerlo sin abrir automáticamente al menos una posición. Por eso empecé a sentirme ansioso al escribir un Asesor Experto "completo". Lo pongo entre comillas porque mi Asesor Experto no tiene una estrategia como tal. Simplemente no quería utilizar la condición aleatoria para abrir una posición.
Ninguno de los interlocutores del Asesor Experto, excepto tú, sugirió que el bucle for para buscar posiciones en esta situación no es necesario. La culpa es mía, yo mismo podría haberlo adivinado hace tiempo y haber preguntado: ¿era realmente necesario un bucle? Resultó que no. Gracias de nuevo por el consejo.
Para finalmente pasar a escribir el trailing stop y no abandonar el proceso a mitad de camino, sólo necesito escribir el código de 2 funciones que determinan la dirección de apertura de una posición de compra o venta neta.
Sí, estoy completamente de acuerdo contigo en que el autoaprendizaje empieza a alargarse. Pero si se tiene en cuenta que sigo un camino inexplorado y torcido, espero que sea posible hacer un descuento.
Durante todo el periodo de autoestudio he obtenido una gran cantidad de información y ahora estoy intentando no sólo ordenarla sino también utilizarla en la práctica. Para ello descargué un Asesor Experto de CodeBase, lo desarrollé y lo utilicé durante quince días en una cuenta demo de un operador de Forex. El resultado es exactamente lo que esperaba. Pronto empezaré a usarlo en una cuenta real. Esto ya es una ventaja.
No persigo la velocidad de autoestudio porque ya he escrito antes que el exceso de información de vez en cuando viene el estupor.
Durante todo el período de auto-estudio poco a poco comenzó a memorizar palabras y frases en inglés que aparecen después del código de compilación. Ahora miro en Google Translate con menos frecuencia. Este es también un momento positivo en el autoaprendizaje.
Voy a publicar todo lo que he escrito en el Asesor de Expertos exactamente cuando una pieza completa para un trailing stop está listo. Intentaré terminarlo el sábado. Aquí es donde comenzará el trabajo principal de escribir el código del trailing stop.
Vasily, te agradezco enormemente la orientación y la crítica constructiva. También expreso mi agradecimiento a todos los participantes de este tema que me ayudan en mi autoestudio del lenguaje de programación MQL5 desde cero.
Si quisiera añadir algo interesante, creo que la idea de "autoformación en MQL5 desde cero" no es del todo correcta. Si una persona es un 0 en programación, tiene que aprender a programar primero. Si el objetivo es aprender a programar en MQL desde cero, una persona debe primero aprender aprogramar en C, al menos lo más básico, y luego aprender a escribir en MQL, porque MQL es de hecho C, pero está especializado para una determinada tarea, una persona no entiende cómo funcionan los bucles, y ya tratando de escribir programas. Es como intentar aprender latín sin saber ruso...
Otra cosa es que C no es un lenguaje muy amigable para aprender a programar, es sencillo, pero es demasiado conciso, es difícil para un principiante leer y entender el código sin tener conocimientos básicos de algoritmos, tipos de datos, álgebra booleana... En C tres caracteres seguidos pueden significar varias cadenas en otro lenguaje.
¡Para aprender a programar simplemente desde cero, para la base, para aprender a hablar con un ordenador en un (no importa qué) lenguaje, yo recomendaría comenzar con Pascal, el libro más fácil para empezar con él (2-3 semanas a gusto), a continuación, C (allí después de Pascal max semana con diligencia, dominar la sintaxis, me refiero a las habilidades básicas del lenguaje!) y luego tomar lenguajes especializados como MQL, porque MQL es C, que tiene un pequeño giro y simplificación, ya que está diseñado para una sola tarea y el compilador sabe lo obvio. Y C a su vez es una especie de Pascal comprimido en RAR, pero Pascal es casi inglés =).
Ahora sobre los bucles:
Cuando aprendí a programar, me ayudó la analogía con las sumas en álgebra, donde se especifica el valor inicial de n, el valor final de n y la fórmula con ese n a calcular.
Hola Andrey! Estoy completamente de acuerdo contigo sobre la base. No lo tengo y nunca lo he tenido. Pero, como dice el refrán, Moscú no se construyó de una vez. Gracias por sus consejos y sugerencias.
Sí, estoy de acuerdo: ¡sus códigos también son buenos! Te estás alterando por nada. Tómate tu tiempo para ordenar el código sin prisas y ya está. Todo es elemental aquí - seleccionar y arrastrar: (cuánto más fácil - sólo su tema de elegir la posición NEED... :-))
Además, incluir archivos - significa que están en su código como funciones también y eso es todo.
Gracias, Roman, por los códigos y los enlaces. ¡Estoy tratando los códigos con calma y seguramente no me apresuro a ninguna parte!
Sigo estudiando el lenguaje de programación MQL5 . Hoy, como prometí, estoy publicando para que todos vean el código de la plantilla del Asesor Experto diseñada para escribir un punto final. Debido al hecho de que el código de la plantilla de EA resultó ser bastante engorroso, tuvimos que reducir los comentarios tanto como fuera posible. La versión completa del Asesor Experto con comentarios detallados sobre cada línea de código, en una presentación accesible para un estudiante de 1.° grado de una escuela de programación, se publicará más adelante en forma de archivo con el nombre de trabajo Trailing_Stop.mq5 para que para no producir otro "footcloth" en el sitio.
Antes de publicar el código, el EA se probó en el probador de estrategias . No se han identificado problemas. El EA utiliza un sistema de contabilidad de posición de compensación. Este sistema de contabilidad implica que en un momento solo puede haber una posición abierta en la cuenta para el mismo símbolo (instrumento financiero).
Por el momento, el EA tiene la capacidad de:
Verifique la cuenta comercial en la que está planeado instalarlo. Si el asesor está instalado en una cuenta de demostración, aparecerá el permiso para continuar trabajando en la ventana del mensaje. Si se intenta instalar el asesor en una cuenta real , aparecerá una advertencia en la ventana del mensaje sobre la imposibilidad de continuar el trabajo, luego de lo cual se eliminará automáticamente de la ventana de trabajo de la terminal comercial .
Una vez al día de negociación exactamente a las 9:00 a. m. según la hora de Moscú, abre automáticamente una posición en la dirección hacia la que se dirigirá el primer tick. Por ejemplo, si a las 9:00 a.m. Hora de Moscú, el primer tick se dirigirá hacia arriba, lo que significa que se abrirá una posición de COMPRA, si el primer tick es hacia abajo, se abrirá una posición de VENTA.
Establecer el tamaño de stop loss.
Establecer el tamaño del lote.
Establezca otros parámetros que serán necesarios para que funcione el trailing stop.
Además, el EA tiene una plantilla preinstalada, proporcionada amablemente por Vasily Sokolov, que se completará con el código durante el proceso de autoaprendizaje.
¡¡¡UNA ADVERTENCIA!!!
¡El Asesor Experto se desarrolla de acuerdo con el plan de autoaprendizaje para una cuenta de demostración y solo con fines educativos! ¡No está diseñado para operar en una cuenta real y obtener ganancias!
Saludos cordiales, Vladímir.
//+------------------------------------------------------------------+//| 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 мин. советник принудительно закроет эту позицию.
ВАЖНО!!! Советник создан для демо-счёта исключительно в учебных целях!
Не предназначен для торговли на реальном счёте и извлечения прибыли!*///--- Создадим входные параметры советникаinputushort BreakevenLevel= 100 ; //Уровень перестановки Stop Loss в безубытокinputushort TrailingStop= 10 ; //Шаг трейлинг стопаinputushort SL= 200 ; //Стоп-лоссinputdouble Lot= 0.1 ; //Лотinputlong Magic_Number= 3215 ; //Магический номер//+------------------------------------------------------------------+//| Expert initialization function |//+------------------------------------------------------------------+/* Функция инициализации советника OnInit с типом данных int. Если возвращаемое значение для функции
return(-1), то это "неудачная инициализация". Если возвращаемое значение для функции return(0), то
это "удачная инициализация". INIT_SUCCEEDED означает, что инициализация прошла успешно и дальше
можно продолжать тестирование эксперта. Этот код означает то же самое, что и нулевое значение, т.е.
"удачная инициализация".
*/intOnInit ()
{
//--- Определим тип счёта на который устанавливаем советник: демо или реальный счетENUM_ACCOUNT_TRADE_MODE account_type=( ENUM_ACCOUNT_TRADE_MODE ) AccountInfoInteger ( ACCOUNT_TRADE_MODE );
//--- теперь превратим значение перечисления в понятный видstring trade_mode; //создадим переменную для торгового режима/* Создадим оператор-переключатель switch, который cравнивает значение выражения с константами во всех
вариантах case и передает управление оператору с соответствующим значением выражения.*/switch (account_type)
{
caseACCOUNT_TRADE_MODE_DEMO : //если ключевое слово ACCOUNT_TRADE_MODE_DEMO
trade_mode= "Счёт DEMO" ; //значит торговый режим счёта - демоbreak ; //оператор break прекращает выполнение ближайшего оператора switchcaseACCOUNT_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 |//+------------------------------------------------------------------+voidOnDeinit ( constint reason)
{
//--- сообщим код завершения работы экспертаPrint ( __FILE__ , ": Код причины деинициализации = " ,reason);
}
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick ()
{
//--- Зададим время открытия и закрытия позиции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 позиции
}
//-- Стоп-лосс короткой позиции переставляем в безубыток и тралим егоelseif ( PositionGetInteger ( POSITION_TYPE ) == POSITION_TYPE_SELL )
{
SetBreakevenForSellPosition(); // установить безубыток для Sell позиции
TrailingStopLossForSellPosition(); // перетащить Stop Loss для Sell позиции
}
}
//+------------------------------------------------------------------+//| Timer function |//+------------------------------------------------------------------+voidOnTimer ()
{
//---
}
//+------------------------------------------------------------------+//| Buy Position Open function |//+------------------------------------------------------------------+//--- Создадим функцию для открытия позиции Buy и назовём её OpenBUYvoid 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 и назовём её OpenSELLvoid 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 |//+------------------------------------------------------------------+//--- Создадим функцию для закрытия всех позиций и назовем её CloseALLvoid 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 позиции
{
//---
;
}
//+------------------------------------------------------------------+
Sigo estudiando el lenguaje de programación MQL5. Ayer escribí el código de Stop Loss en el punto de equilibrio para las posiciones de venta y compra. Estoy pegando el código sin ningún comentario todavía. Publicaré la versión completa del Asesor Experto con una descripción detallada de cada línea de código, en una forma accesible para los alumnos de 1er año de la escuela de programación, más adelante en el archivo con el título de trabajo Trailing_Stop.mq5. Antes de publicar el código, comprobamos el rendimiento del Asesor Experto en el probador de estrategias. No se ha encontrado ningún problema.
Saludos, Vladimir.
//+------------------------------------------------------------------+//| Устанавливает sl позиции BUY в безубыток |//+------------------------------------------------------------------+void SetBreakevenForBuyPosition() // функция "Установить безубыток для позиции Buy"
{
//--- Создадим запрос на сервер и получим ответ с результатомMqlTradeRequest request={0};
MqlTradeResult result={0};
//--- Запустим цикл перебора всех открытых позицийfor(int i=PositionsTotal()-1; i>=0; i--)
{
//--- параметры позиции Buyulong 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); // тип позиции//--- выводим информацию о позиции BuyPrintFormat("#%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 в безубыток для позиции Buyif(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--)
{
//--- параметры позиции Sellulong 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); // тип позиции//--- выводим информацию о позиции SellPrintFormat("#%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 в безубыток для позиции Sellif(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);
}
}
}
//+------------------------------------------------------------------+
Sigo estudiando el lenguaje de programación MQL5. Hoy, como prometí, pego el código de la plantilla de mi Asesor Experto diseñada para escribir un trailing stop. Debido a que el código de la plantilla EA es bastante engorroso, he tenido que acortar al máximo los comentarios. La versión completa del Asesor Experto con comentarios detallados sobre cada línea del código, en una forma accesible para un estudiante de primer grado de la escuela de programación, se publicará más tarde como un archivo con el nombre de trabajo Trailing_Stop.mq5, para evitar crear otro estropicio en el sitio web.
...
Muy bien. La idea principal está bien captada. Me gusta especialmente el proceso de desarrollo:
MrBrooklin:
¡Buen día y buen humor a todos!
Sigo estudiando el lenguaje de programación MQL5. Ayer escribí el código para el Stop Loss en el punto de equilibrio para las posiciones de compra y venta.
Es decir, todo es correcto. No es necesario resolver el problema de una vez en un solo lugar. Deberías resolverlo poco a poco, como lo has hecho tú. Primero, describe la lógica básica en la función OnTick y las funciones básicas como OpenBUY, OpenSELL, TickUP, TickDown.
Luego, cuando este código básico está depurado, compilado y funciona dentro de sus posibilidades, se empieza a describir las demás funciones. Esto puede hacerse al día siguiente o incluso a la semana. Esto significa que no hay que cambiar el código principal. Creo que puedes ver por qué.
Ahora hay que perfeccionar esta forma de desarrollo: seguir escribiendo funciones, vinculando la funcionalidad a través de ellas al código existente. El programa existente debería funcionar correctamente. La complejidad no debería aumentar. Las funciones que se añadan deben devolver resultados sencillos y claros. Sus nombres deben ser tan sencillos como claros para usted. Si no puede hacerlo, puede ser porque necesita escribir no una, sino dos o incluso tres funciones para resolver el problema. Al principio, el marco general de la aplicación será difícil de definir. Por eso es mejor que pidas consejo a colegas más experimentados. Con el tiempo, aprenderás a desarrollar esas plantillas por tu cuenta.
A medida que pase el tiempo,tendrá que utilizar más y más construcciones del lenguaje dentro de las funciones para que se adapten a sus necesidades.En este punto, ampliarás gradualmente, y sobre todo de forma orgánica, tus conocimientos sobre las construcciones del lenguaje, aprenderás los bucles, las matrices e incluso a trabajar con punteros.
De hecho, ya ha aprendido la parte más difícil de la programación, aunque todavía no ha consolidado el material que ha aprendido. Lo único que tienes que hacer ahora es repetirlo muchas veces para consolidarlo. A partir de aquí no habrá nada fundamentalmente nuevo, todo es lo mismo: Plantilla general -> Descripción de los nombres de las funciones y sus parámetros-> Escritura del contenido de estas funciones -> Disposición de estas funciones en la unidad central. Eso es todo. Lo único que queda es perfeccionar la habilidad y ser constante. Varias construcciones adicionales que se empiezan a utilizar, como los bucles y las matrices, son sólo detalles, a veces muy bien hechos, pero nada más que detalles.
Por cierto, presta atención al tamaño total de tu programa. Ya es bastante importante. ¿Qué te parece? Por cierto, un novato no puede escribir un código de tamaño tan grande: las variables comienzan a confundirse, los paréntesis se hacen demasiado grandes, los errores de compilación comienzan a arrastrarse como hongos después de la lluvia. Después de la compilación, un programa de tal tamaño empieza a tener fallos y nadie puede entender qué es lo que está mal. Y todo funciona en su código por alguna razón), y está claro en las funciones lo que está pasando y cómo. En una palabra, es una belleza.
Como la perfección no tiene límites, añadiré algunos comentarios más sobre el código:
voidOnTick()
{
//--- Зададим время открытия и закрытия позиции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();
}
He resaltado en amarillo dos lugares no triviales.
1) Observa que el código se repite en el primer if y en el siguiente else. La única diferencia está en la última línea y la acción final (OpenBUY, OpenSell).
2) Las condiciones para entrar en el otro bloque no son obvias. No son visibles debido a la abundancia de "bichos". De hecho, sólo dependen de la última línea:
TickUP()==(price+point)
Esto es una señal segura de que aquí falta una función.
Tenemos que escribir una función que devuelva true si el tiempo de apertura de la posición se corresponde con el dado (lo escribiré más adelante)
Muy bien. El punto principal se capta correctamente. Me gustó especialmente el proceso de desarrollo:
Es decir, todo está bien. No hay que resolver el problema de una vez en un solo lugar. Hazlo gradualmente, como lo has hecho. Primero, describe la lógica básica en la función OnTick y las funciones básicas como OpenBUY, OpenSELL, TickUP, TickDown.
Luego, cuando este código básico está depurado, compilado y funciona dentro de sus posibilidades, se empieza a describir las demás funciones. Esto puede hacerse al día siguiente o incluso a la semana. Esto significa que no tienes que cambiar el código principal. Creo que puedes ver por qué.
Ahora hay que perfeccionar esta forma de desarrollo: seguir escribiendo funciones, vinculando la funcionalidad a través de ellas al código existente. El programa existente debería funcionar correctamente. La complejidad no debería aumentar. Las funciones que se añadan deben devolver resultados sencillos y claros. Sus nombres deben ser tan sencillos como claros para usted. Si no puede hacerlo, es posible que tenga que escribir no una, sino dos o incluso tres funciones para resolver el problema.
Para que una función pueda realizar las tareas que se le han encomendado, con eltiempo tendrá que utilizar más y más construcciones del lenguaje dentro de dichas funciones. Es entonces cuando poco a poco, y sobre todo de forma orgánica, ampliarás tus conocimientos sobre las construcciones del lenguaje, aprenderás los bucles, las matrices e incluso trabajarás con punteros.
¡Hola, Vasily! Muchas gracias por sus oportunas sugerencias y apoyo. Tus comentarios sobre el papel de las funciones y los principios de construcción del código del programa me han ayudado mucho en el aprendizaje del lenguaje de programación MQL5:
Ahora que la información en mi cabeza está estructurada, es más fácil entender el código escrito no sólo por mí, sino también por otros programadores. Espero que este tema sea una buena ayuda para aquellos que están empezando a aprender el lenguaje de programación MQL5 desde cero.
Igor, las ganas de aprender el lenguaje MQL5 no se pierden, al contrario, sólo aumentan. Estoy desgarrado, por qué soy tan tonto y no puedo entender cosas simples con este operador de bucle. Lo principal es que sin el operador de bucle el código funciona perfectamente, pero con el bucle es un completo desastre. De todos modos, llegaré al fondo del asunto. Sin embargo, tengo mucho menos tiempo para el autoaprendizaje desde que el periodo de cuarentena ha terminado y tengo raros momentos en el trabajo en los que puedo estudiar el idioma. La mayoría de las veces estudio el idioma por la tarde y a última hora de la noche.
Necesito resolver 2 tareas para finalmente llegar a escribir el código del Trailing Stop:
Vladimir, te estás metiendo en cosas raras. Te han dado una plantilla: https://www.mql5.com/ru/forum/352460/page58#comment_18726492 La has ignorado y has decidido seguir adelante con tu ingenio. Este camino es difícil y puede llevar años. En su camino, estudie C, C++, Rust, C#, polimorfismo, herencia, desreferenciación de punteros, conversión de tipos dinámicos: Comprueba o conduce. Debes tomar el camino más corto hacia el objetivo. Si quiere que se le ponga un final, escríbalo. No es necesario estudiar C y C++ para hacerlo. Todo esto como optativa si te apetece.
La situación del bucle for es ilustrativa. Es una construcción poderosa que debe aplicarse en el lugar adecuado. Tienes una red y un algoritmo auxiliar. Por eso no hay enumeración de posiciones, no hay magos, así que no tienes este bucle. Por supuesto, todo funcionará sin él, pero el bucle sólo te hace sentir como aceite. Pero te empeñas en utilizarlo, parece ser un fin en sí mismo: utilizar la mayor cantidad posible de todo y de todos, para tener algo en reserva.
Vladimir, te estás metiendo en un pequeño berenjenal. Te dieron una plantilla: https://www.mql5.com/ru/forum/352460/page58#comment_18726492 La ignoraste y decidiste seguir adelante con tu mente. Este camino es difícil y puede llevar años. En su camino, estudie C, C++, Rust, C#, polimorfismo, herencia, desreferenciación de punteros, conversión de tipos dinámicos: Comprueba o conduce. Debes tomar el camino más corto hacia el objetivo. Si quiere que se le ponga un final, escríbalo. No es necesario estudiar C y C++ para hacerlo. Todo esto como optativa si te apetece.
La situación del bucle for es ilustrativa. Es una construcción poderosa que debe aplicarse en el lugar adecuado. Tienes una red y un algoritmo auxiliar. Por eso no hay enumeración de posiciones, no hay magos, por lo que no se tiene este bucle. Naturalmente, todo funcionará sin él, pero el bucle sólo produce aceite. Pero usted se obstina en utilizarlo, por lo que parece ser un fin en sí mismo: puede utilizar la mayor cantidad posible de todo y de cualquier cosa que tenga en stock.
¡Hola Vasily!
Gracias por unirte oportunamente al tema y orientarme en el camino correcto como siempre. Ahora permítanme explicar todo en un orden:
Vasily, te agradezco enormemente la orientación y la crítica constructiva. También expreso mi agradecimiento a todos los participantes de este tema que me ayudan en mi autoestudio del lenguaje de programación MQL5 desde cero.
El autoaprendizaje continúa. Continuará.
Saludos, Vladimir.
¡Buenas tardes a todos!
Si quisiera añadir algo interesante, creo que la idea de "autoformación en MQL5 desde cero" no es del todo correcta. Si una persona es un 0 en programación, tiene que aprender a programar primero. Si el objetivo es aprender a programar en MQL desde cero, una persona debe primero aprender aprogramar en C, al menos lo más básico, y luego aprender a escribir en MQL, porque MQL es de hecho C, pero está especializado para una determinada tarea, una persona no entiende cómo funcionan los bucles, y ya tratando de escribir programas. Es como intentar aprender latín sin saber ruso...
Otra cosa es que C no es un lenguaje muy amigable para aprender a programar, es sencillo, pero es demasiado conciso, es difícil para un principiante leer y entender el código sin tener conocimientos básicos de algoritmos, tipos de datos, álgebra booleana... En C tres caracteres seguidos pueden significar varias cadenas en otro lenguaje.
¡Para aprender a programar simplemente desde cero, para la base, para aprender a hablar con un ordenador en un (no importa qué) lenguaje, yo recomendaría comenzar con Pascal, el libro más fácil para empezar con él (2-3 semanas a gusto), a continuación, C (allí después de Pascal max semana con diligencia, dominar la sintaxis, me refiero a las habilidades básicas del lenguaje!) y luego tomar lenguajes especializados como MQL, porque MQL es C, que tiene un pequeño giro y simplificación, ya que está diseñado para una sola tarea y el compilador sabe lo obvio. Y C a su vez es una especie de Pascal comprimido en RAR, pero Pascal es casi inglés =).
Ahora sobre los bucles:
Cuando aprendí a programar, me ayudó la analogía con las sumas en álgebra, donde se especifica el valor inicial de n, el valor final de n y la fórmula con ese n a calcular.
Hola Andrey! Estoy completamente de acuerdo contigo sobre la base. No lo tengo y nunca lo he tenido. Pero, como dice el refrán, Moscú no se construyó de una vez. Gracias por sus consejos y sugerencias.
Saludos, Vladimir.
Sí, estoy de acuerdo: ¡sus códigos también son buenos! Te estás alterando por nada. Tómate tu tiempo para ordenar el código sin prisas y ya está. Todo es elemental aquí - seleccionar y arrastrar: (cuánto más fácil - sólo su tema de elegir la posición NEED... :-))
Además, incluir archivos - significa que están en su código como funciones también y eso es todo.
Gracias, Roman, por los códigos y los enlaces. ¡Estoy tratando los códigos con calma y seguramente no me apresuro a ninguna parte!
Sinceramente, Vladimir.
Buen día y buen humor a todos!
Sigo estudiando el lenguaje de programación MQL5 . Hoy, como prometí, estoy publicando para que todos vean el código de la plantilla del Asesor Experto diseñada para escribir un punto final. Debido al hecho de que el código de la plantilla de EA resultó ser bastante engorroso, tuvimos que reducir los comentarios tanto como fuera posible. La versión completa del Asesor Experto con comentarios detallados sobre cada línea de código, en una presentación accesible para un estudiante de 1.° grado de una escuela de programación, se publicará más adelante en forma de archivo con el nombre de trabajo Trailing_Stop.mq5 para que para no producir otro "footcloth" en el sitio.
Antes de publicar el código, el EA se probó en el probador de estrategias . No se han identificado problemas. El EA utiliza un sistema de contabilidad de posición de compensación. Este sistema de contabilidad implica que en un momento solo puede haber una posición abierta en la cuenta para el mismo símbolo (instrumento financiero).
Por el momento, el EA tiene la capacidad de:
Además, el EA tiene una plantilla preinstalada, proporcionada amablemente por Vasily Sokolov, que se completará con el código durante el proceso de autoaprendizaje.
¡¡¡UNA ADVERTENCIA!!!
¡El Asesor Experto se desarrolla de acuerdo con el plan de autoaprendizaje para una cuenta de demostración y solo con fines educativos! ¡No está diseñado para operar en una cuenta real y obtener ganancias!
Saludos cordiales, Vladímir.
¡Buen día y buen humor a todos!
Sigo estudiando el lenguaje de programación MQL5. Ayer escribí el código de Stop Loss en el punto de equilibrio para las posiciones de venta y compra. Estoy pegando el código sin ningún comentario todavía. Publicaré la versión completa del Asesor Experto con una descripción detallada de cada línea de código, en una forma accesible para los alumnos de 1er año de la escuela de programación, más adelante en el archivo con el título de trabajo Trailing_Stop.mq5. Antes de publicar el código, comprobamos el rendimiento del Asesor Experto en el probador de estrategias. No se ha encontrado ningún problema.
Saludos, Vladimir.
¡Buen día y buen humor a todos!
Sigo estudiando el lenguaje de programación MQL5. Hoy, como prometí, pego el código de la plantilla de mi Asesor Experto diseñada para escribir un trailing stop. Debido a que el código de la plantilla EA es bastante engorroso, he tenido que acortar al máximo los comentarios. La versión completa del Asesor Experto con comentarios detallados sobre cada línea del código, en una forma accesible para un estudiante de primer grado de la escuela de programación, se publicará más tarde como un archivo con el nombre de trabajo Trailing_Stop.mq5, para evitar crear otro estropicio en el sitio web.
...
Muy bien. La idea principal está bien captada. Me gusta especialmente el proceso de desarrollo:
¡Buen día y buen humor a todos!
Sigo estudiando el lenguaje de programación MQL5. Ayer escribí el código para el Stop Loss en el punto de equilibrio para las posiciones de compra y venta.
Es decir, todo es correcto. No es necesario resolver el problema de una vez en un solo lugar. Deberías resolverlo poco a poco, como lo has hecho tú. Primero, describe la lógica básica en la función OnTick y las funciones básicas como OpenBUY, OpenSELL, TickUP, TickDown.
Luego, cuando este código básico está depurado, compilado y funciona dentro de sus posibilidades, se empieza a describir las demás funciones. Esto puede hacerse al día siguiente o incluso a la semana. Esto significa que no hay que cambiar el código principal. Creo que puedes ver por qué.
Ahora hay que perfeccionar esta forma de desarrollo: seguir escribiendo funciones, vinculando la funcionalidad a través de ellas al código existente. El programa existente debería funcionar correctamente. La complejidad no debería aumentar. Las funciones que se añadan deben devolver resultados sencillos y claros. Sus nombres deben ser tan sencillos como claros para usted. Si no puede hacerlo, puede ser porque necesita escribir no una, sino dos o incluso tres funciones para resolver el problema. Al principio, el marco general de la aplicación será difícil de definir. Por eso es mejor que pidas consejo a colegas más experimentados. Con el tiempo, aprenderás a desarrollar esas plantillas por tu cuenta.
A medida que pase el tiempo,tendrá que utilizar más y más construcciones del lenguaje dentro de las funciones para que se adapten a sus necesidades.En este punto, ampliarás gradualmente, y sobre todo de forma orgánica, tus conocimientos sobre las construcciones del lenguaje, aprenderás los bucles, las matrices e incluso a trabajar con punteros.
De hecho, ya ha aprendido la parte más difícil de la programación, aunque todavía no ha consolidado el material que ha aprendido. Lo único que tienes que hacer ahora es repetirlo muchas veces para consolidarlo. A partir de aquí no habrá nada fundamentalmente nuevo, todo es lo mismo: Plantilla general -> Descripción de los nombres de las funciones y sus parámetros-> Escritura del contenido de estas funciones -> Disposición de estas funciones en la unidad central. Eso es todo. Lo único que queda es perfeccionar la habilidad y ser constante. Varias construcciones adicionales que se empiezan a utilizar, como los bucles y las matrices, son sólo detalles, a veces muy bien hechos, pero nada más que detalles.
Como la perfección no tiene límites, añadiré algunos comentarios más sobre el código:
He resaltado en amarillo dos lugares no triviales.
1) Observa que el código se repite en el primer if y en el siguiente else. La única diferencia está en la última línea y la acción final (OpenBUY, OpenSell).
2) Las condiciones para entrar en el otro bloque no son obvias. No son visibles debido a la abundancia de "bichos". De hecho, sólo dependen de la última línea:
Esto es una señal segura de que aquí falta una función.
Tenemos que escribir una función que devuelva true si el tiempo de apertura de la posición se corresponde con el dado (lo escribiré más adelante)
Muy bien. El punto principal se capta correctamente. Me gustó especialmente el proceso de desarrollo:
Es decir, todo está bien. No hay que resolver el problema de una vez en un solo lugar. Hazlo gradualmente, como lo has hecho. Primero, describe la lógica básica en la función OnTick y las funciones básicas como OpenBUY, OpenSELL, TickUP, TickDown.
Luego, cuando este código básico está depurado, compilado y funciona dentro de sus posibilidades, se empieza a describir las demás funciones. Esto puede hacerse al día siguiente o incluso a la semana. Esto significa que no tienes que cambiar el código principal. Creo que puedes ver por qué.
Ahora hay que perfeccionar esta forma de desarrollo: seguir escribiendo funciones, vinculando la funcionalidad a través de ellas al código existente. El programa existente debería funcionar correctamente. La complejidad no debería aumentar. Las funciones que se añadan deben devolver resultados sencillos y claros. Sus nombres deben ser tan sencillos como claros para usted. Si no puede hacerlo, es posible que tenga que escribir no una, sino dos o incluso tres funciones para resolver el problema.
Para que una función pueda realizar las tareas que se le han encomendado, con eltiempo tendrá que utilizar más y más construcciones del lenguaje dentro de dichas funciones. Es entonces cuando poco a poco, y sobre todo de forma orgánica, ampliarás tus conocimientos sobre las construcciones del lenguaje, aprenderás los bucles, las matrices e incluso trabajarás con punteros.
¡Hola, Vasily! Muchas gracias por sus oportunas sugerencias y apoyo. Tus comentarios sobre el papel de las funciones y los principios de construcción del código del programa me han ayudado mucho en el aprendizaje del lenguaje de programación MQL5:
Ahora que la información en mi cabeza está estructurada, es más fácil entender el código escrito no sólo por mí, sino también por otros programadores. Espero que este tema sea una buena ayuda para aquellos que están empezando a aprender el lenguaje de programación MQL5 desde cero.
Saludos, Vladimir.