![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Здравствуйте Cameofx,
Спасибо за любезный ответ.
Эта система кодирования очень проста и легка.
Все делается вручную в MetaEditor.
На самом деле, система разрабатывается для разработки больших программ легко и с высокой скоростью.
Система должна быть также гибкой и надежной.
С наилучшими пожеланиями!
Ais, Спасибо за ваш ответ. Я многому научился из ваших постов :)
Cameo
Привет, друзья!
Одна вещь из прошлого висит надо мной день за днем.
Это документация к AIS5 Trade Machine.
Я вернусь, как только Бог решит.
Пока!
Привет, Айс.
Твоего отсутствия будет очень не хватать. Берегите себя.
Мы рады твоему возвращению.
Твой друг, Будь здоров
Здравствуйте, Ais
Я не могу найти четкого ответа ни в книге, ни на форуме. В схеме релейной логики ворота AND будут работать так же, как в приведенном выше примере. Только когда есть два "истинных" входа, будет "истинный" выход. Только тогда управление будет продолжаться.После вашего возвращения, извините, что сразу же обременяю вас новыми вопросами. Дело не конкретно в вашей системе, у меня такая проблема почти со всеми программами. Это связано с определяемыми пользователем функциями. Как пользовательская функция получает свое определение.
Например:
Жду вашего ответа. Заранее благодарю.
Спасибо
Hello Huckleberry
Давайте уточним эту часть кода.
1. Вероятно, основные трудности:
1.1. все люди думают и действуют по-разному;
1.2. Мне нравится использовать строго ограниченное количество типов данных;
1.3. Мне нравится использовать только "стандартные" типы данных:
1.3.1. "int",
1.3.2. "double",
1.3.3. "string";
1.4. Я использую другие типы данных только в особых случаях;
1.5. Я обозначаю тип элементов моей программы маленькой буквой в первой позиции имен:
1.5.1. "i" для типа данных "int",
1.5.2. "d" для типа данных "double",
1.5.3. "s" для типа данных "string",
1.5.4. "r" для "неопределенного" типа данных;
1.6. эта техника программирования помогает мне контролировать приведение типов;
1.7. предопределенные функции и константы могут иметь также следующие типы данных:
1.7.1. "bool",
1.7.2. "color",
1.7.3. "datetime";
1.8. Я всегда пытаюсь привести эти типы к типу "int";
1.9. на сегодняшний день приведение данных обычно неявное;
1.10. некоторые основные приемы моего программирования:
1.10.1. Мне нравилось использовать пару констант "TRUE" и "EMPTY" вместо пары констант "TRUE" и "FALSE";
1.10.2. в операторах "if" иногда я использовал "1" и "0" вместо "TRUE" и "FALSE";
1.10.3. Я использовал константу "EMPTY" с отрицательным значением "-1" для обозначения недопустимых результатов для беззнаковых элементов данных;
1.10.4. в будущем я буду использовать тип "bool" с префиксом "b" в именах.
2. Мы должны знать следующие типы данных MQL4:
2.1. "int" - это <!>signed</!> long 4-байтовое целое число со значениями от -2147483648 до 2147483647;
2.2. "datetime" - это <!>unsigned</!> long 4-byte integer number with values from 0 to 4294967295;
2.3. присваивая значения "datetime" переменным "int", мы получаем корректные результаты примерно до 2038.01.01.
3. О функции "iTime ( symbol, timeframe, shift )" необходимо знать следующее:
3.1. эта функция всегда возвращает значение типа "datetime";
3.2. существует 2 различных случая возврата:
3.2.1. "0", если локальная история пуста;
3.2.2. время открытия бара, обозначенное "shift" во всех остальных случаях;
3.3. "iTime ( 0, 0, 0 )" возвращает время открытия для нулевого бара текущего графика;
3.4. если нулевой бар один и тот же, "iTime ( 0, 0, 0 )" возвращает то же значение;
3.5. Когда текущий нулевой бар завершен, этот бар стал баром номер 1 и начинается формирование нового нулевого бара;
3.6. "iTime ( 0, 0, 0 )" возвращает новое значение;
3.7. таким образом, значение "iTime ( 0, 0, 0 )" меняется при смене нулевого бара.
4. Мы предотвратили работу с пустой историей в программном блоке "2.2.3.1. Проверка исторических данных".
5. При успешном закрытии ордера в функции "iTryClose" присваиваем "iTradeBarTime = iTime ( 0, 0, 0 ) ;".
6. В функции "iSignalOpen" проверяем, если "iTradeBarTime == iTime ( 0, 0, 0 ) )".
7. Если это так и повторная торговля запрещена по значению "iTradeBarOnce = 1 ;", то запрещаем сигналу открываться по значению "EMPTY".
.
Будьте здоровы
Здравствуйте Айс
Спасибо за ваш ответ. Я изучу этот вопрос и скоро вернусь.
Ваше здоровье
Здравствуйте, Айс,
Извините за мой медленный ответ. В понедельник я вернулся на работу по своей обычной специальности. Времени в эти дни немного меньше. Времени на учебу тоже меньше.
Как я уже говорил ранее в этой теме, мне нравится разбирать все до мелочей. Как одна звездочка обеспечивает питание другой и так далее. Поэтому я обнаружил, что контроль в программе очень увлекателен. Пожалуйста, поймите, что я выражаю вам должное уважение за терпение и знания, которые вы предоставили, но у меня есть вопросы, почему необходим блок 2.2.3.1.
Как может iBaseLag + iBaseBar быть выражением?
Я так понял, что iBaseLag и iBaseBar находятся в пределах параметров iHighest и iLowest. Если они не являются явными числами,
как можно определить, какое именно число это будет. iBaseLag - 20, что представляет 20 баров, используемых для расчета среднего.
iBaseBar представляет, с какого бара должно начинаться усреднение. Бары с 1 по 20, в данном случае нулевой бар не рассматривается.
Я позволил себе сократить программу на /* 2.2.3.1*/. Протестировал программу и обнаружил те же результаты. При работе программы в реальных торговых условиях это может быть не очень хорошей идеей.
Каково ваше мнение, пожалуйста?
Кроме того, ваше объяснение блока 2.1.2 внесло ясность в мою путаницу. iTime возвращает время открытия нулевого бара.
iTradeBarTime также является типом datetime. Программа знает, на каком баре произошла сделка, поэтому на каждом баре только одна сделка. ... . iTradeBarOnce == 1
Спасибо.
Буду изучать дальше в ближайшие дни. Но можно ли использовать блок reservered 2.1.1 для функции, которая бы обеспечивала дополнительные позиции к существующим позициям. Пример: существующий лонг, затем добавление трех или более лонгов?
С функциями, которые уже есть в программе, будут ли конфликты с дополнительными позициями?
Еще раз спасибо за все. Оставайтесь здоровыми
Будь здоров
Здравствуйте, Гекльберри,
Давайте внимательно посмотрим на основную часть программы, включая блок 2.2.3.1..:
////////////////////////////////////////////////////////////////////< 14> // < 2.2.3. Code : Special : Start > //< > int start () // - i 9 l - o //< > { //< > // < 2.2.3.1. History data inspection 4 >`````````````````````````//< > static int iTrigger = 0 ; if ( iTrigger == 0 ) { //< > if ( ( iTime ( 0 , 0 , 0 ) == 0 ) //< > || ( iBars ( 0 , 0 ) < iBaseLag + iBaseBar ) ) //< > return ; else iTrigger = 1 ; } //< > // </2.2.3.1. History data inspection 4 >`````````````````````````//< > // //< > // < 2.2.3.2. Main routine 3 >````````````````````````````````````//< > int iTicket = iGetTicket () ; //< > // //< > if ( iTicket < 0 ) iTryOpen () ; //< > else iTryClose () ; //< > // </2.2.3.2. Main routine 3 >````````````````````````````````````//< > // //< > // < 2.2.3.3. Exception handler 2 >```````````````````````````````//< > int iTrap = GetLastError () ; //< > if ( iTrap > 0 ) Alert ( "Exception " , iTrap ) ; //< > // </2.2.3.3. Exception handler 2 >```````````````````````````````//< > } //< > // </2.2.3. Code : Special : Start > //< > ////////////////////////////////////////////////////////////////////< 0>
1. блок 2.2.3.1., самый первый блок программы, представляет собой простой триггер:
1.1. "static int iTrigger" хранит собственное значение все время жизни программы, такой вот "static";
1.2. изначально "iTrigger == 0";
1.3. оператор "if ( iTrigger == 0 )" выполняется на каждом тике;
1.4. в первый раз, когда "iTrigger == 0", проверка исторических данных выполняется внутри блока {...};
1.5. если исторические данные неверны, выполняется оператор "return;";
1.6. это означает, что выполнение главной функции "start ()" закончилось;
1.7. на следующем тике снова выполняется оператор "if ( iTrigger == 0 )";
1.8. если данные истории верны, то выполняется оператор "iTrigger = 1 ;";
1.9. тогда выполнение основной функции "start ()" продолжается;
1.10. на следующем тике снова выполняется оператор "if ( iTrigger == 0 )";
1.11. значение "iTrigger" сейчас и в будущем всегда будет "== 1", так как оно статично;
1.12. поэтому в будущем проверка исторических данных всегда будет пропускаться;
1.13. таков простой триггер;
2. проверка исторических данных состоит из двух частей:
2.1. проверить, пуста ли локальная история "iTime ( 0, 0, 0 ) == 0";
2.2. проверить, достаточен ли размер локальной истории для вычисления "iATR ( 0, 0, iBaseLag, iBaseBar )", где:
2.2.1. "iBaseBar" - начальный бар для "iATR";
2.2.2. "iBaseLag" - количество усредняющих баров для "iATR";
2.2.3. "iBaseLag + iBaseBar" - обычное выражение, результатом всегда является сумма "iBaseLag" и "iBaseBar";
2.2.4. другими словами выражение "iBaseLag + iBaseBar" эквивалентно сумме "iBaseLag" и "iBaseBar";
2.2.5. на входе программы в блоке 1.1.1. мы можем задать любые значения для "iBaseLag" и "iBaseBar";
2.2.6. пусть мы задали "iBaseLag = 100 ;" и "iBaseBar = 7 ;";
2.2.7. тогда корректное вычисление "iATR ( 0, 0, iBaseLag, iBaseBar )" будет возможно, если размер локальной истории равен 107 или больше, так как номер последнего бара для вычисления - #106, а бар всегда считается нулевым.
В любую программу можно добавить любое количество функций, блок 2.1.1 просто демонстрирует пример возможной реализации.
Предоставление дополнительных позиций потребует гораздо более сложного кода анализа и управления позициями, чем функция 2.1.4.
Но все возможно.
С уважением,
Здравствуйте, Ais
Спасибо за быстрый ответ. Я могу понять многое из того, что вы изложили. Особенно в отношении функции iATR. Вы говорите, что использование выражения iBaseLag + iBasebar, само по себе, является допустимой частью формулы. У меня сложилось впечатление, что они должны быть в параметрах определенной функции, иначе они не допускаются. Это для проверки размера локальной истории, достаточно ли баров для продолжения. Это то, на что вы указываете? Так много дополнительных шагов, но необходимых для достижения цели. Шагов, которые можно было бы пропустить или принять как должное.
Я еще поразмышляю над остальным. Спасибо за ваше время.
Будь здоров
Hello Huckleberry
MQL4 - очень дружелюбная среда, особенно по сравнению, например, с Си или ассемблерами.
Требования к различным проверкам и прочим ухищрениям значительно снижены.
Но внедрение в среду разработки максимально возможных проверок всегда снижает производительность.
Так или иначе, программист всегда несет ответственность за плохое поведение программы.
Поэтому для меня избыточная перепроверка лучше, чем, например, элементарное повреждение границ.
Спасибо