Ваши вопросы по языку MQL4

AlexeyVik

Программист mql4 mql5
вопрос к уважаемым спецам
есть такие части строчки кода
= High[iHighest(Symbol(),0,MODE_HIGH,10,i)];
= Low[iLowest (Symbol(),0,MODE_LOW, 10, i)];
как они работают мне понятно,это нахождение максимального хая и лоу свечи за период (тут 10)
мне интересно (хотелось бы увидеть) можно ли как то эту функцию приспособить например к осциллятору RSI(он ходит как известно в границах 0/100)
т.e. в расчете заменить хай и лоу на значения RSI
как будет это выглядеть (если возможно) подскажите пожалуйста
Если это надо в советнике, то надо заполнять массив в цикле и искать в этом массиве. Но эта овчинка выделки не сто́ит. Проще отсеять во время заполнения массива. А если в индикаторе, то есть варианты…
Например поиск максимального значения в массиве буфера
Код:
int  ArrayMaximum(
   const void&   array[],             // массив для поиска
   int           start=0,             // с какого индекса начинаем поиск
   int           count=WHOLE_ARRAY    // количество проверяемых
   );
 

блондинка

Элитный участник
Если это надо в советнике, то надо заполнять массив в цикле и искать в этом массиве. Но эта овчинка выделки не сто́ит. Проще отсеять во время заполнения массива. А если в индикаторе, то есть варианты…
Например поиск максимального значения в массиве буфера
Код:
int  ArrayMaximum(
   const void&   array[],             // массив для поиска
   int           start=0,             // с какого индекса начинаем поиск
   int           count=WHOLE_ARRAY    // количество проверяемых
   );
спасибо,жалко что нельзя Highest/Lowest использовать,впихнуть индикатор вместо MODE_HIGH/LOW
 

Slava78

Элитный участник
спасибо,жалко что нельзя Highest/Lowest использовать,впихнуть индикатор вместо MODE_HIGH/LOW
Может я не в тему. Не могу понять что именно вам нужно
Код:
buf_up[i] = High[iHighest(s1, 0, MODE_HIGH, period, i)];
buf_dn[i] = Low[iLowest (s1, 0, MODE_LOW,  period, i)];
 
Последнее редактирование:

vladradon

Программист
Если это надо в советнике, то надо заполнять массив в цикле и искать в этом массиве. Но эта овчинка выделки не сто́ит. Проще отсеять во время заполнения массива. А если в индикаторе, то есть варианты…
Например поиск максимального значения в массиве буфера
Код:
int  ArrayMaximum(
   const void&   array[],             // массив для поиска
   int           start=0,             // с какого индекса начинаем поиск
   int           count=WHOLE_ARRAY    // количество проверяемых
   );
Привет! Это для МТ5!
Для МТ4:
C++:
Ищет в одномерном числовом массиве максимальный элемент.
int  ArrayMaximum(
   const void&   array[],             // массив для поиска
   int           count=WHOLE_ARRAY,   // количество проверяемых
   int           start=0              // с какого индекса начинаем поиск
   );
Найди отличие!;)
Меня это не раз в тупик ставило - просто забывал об этой подлянке...


 

AlexeyVik

Программист mql4 mql5
Привет! Это для МТ5!
Для МТ4:
C++:
Ищет в одномерном числовом массиве максимальный элемент.
int  ArrayMaximum(
   const void&   array[],             // массив для поиска
   int           count=WHOLE_ARRAY,   // количество проверяемых
   int           start=0              // с какого индекса начинаем поиск
   );
Найди отличие!;)
Меня это не раз в тупик ставило - просто забывал об этой подлянке...


Ну да, есть такая беда для некоторых. Но я никогда не запоминал какая функция как пишется… Всегда пользуюсь документацией, а там всё написано как должно быть написано и я никогда не попадал в проблему…
 

блондинка

Элитный участник
Может я не в тему. Не могу понять что именно вам нужно
Код:
buf_up[i] = High[iHighest(s1, 0, MODE_HIGH, period, i)];
buf_dn[i] = Low[iLowest (s1, 0, MODE_LOW,  period, i)];
мне хотелось бы находить просто (типа в одну строчку) экстренумы осцилляторов за некоторое количество баров
вот так не работает,но ошибку не пишет
double r1 = iRSI(NULL,0, 14,PRICE_CLOSE,i+1);
double high01 = High[iHighest(r1,0,MODE_HIGH, 10, i+1)];
double low01 = Low[iLowest (r1,0,MODE_LOW, 10, i+1)];
т.е. вместо свечек индикатор не запихнуть
 
Последнее редактирование:

vladradon

Программист
мне хотелось бы находить просто (типа в одну строчку) экстренумы осцилляторов
Привет! В 4-ке это не получится без предварительного считывания данных в заданный массив. Сначала в цикле нужный объем данных по нужному индикатору записываешь в промежуточный (рабочий) массив, и потом в этом массиве ищешь экстремумы.
 

Slava78

Элитный участник
мне хотелось бы находить просто (типа в одну строчку) экстренумы осцилляторов за некоторое количество баров
вот так не работает,но ошибку не пишет
double r1 = iRSI(NULL,0, 14,PRICE_CLOSE,i+1);
double high01 = High[iHighest(r1,0,MODE_HIGH, 10, i+1)];
double low01 = Low[iLowest (r1,0,MODE_LOW, 10, i+1)];
т.е. вместо свечек индикатор не запихнуть
Экстремумы - это фракталы, т.е. слева и справа от него должно быть некоторое количество свечей.
А т.к. у РСИ - это уровни, то соответственно линия должна их пробить(каждая свеча - это определенный уровень)
Код:
   double rsi1=iRSI(NULL,0,RSIPeriod,0,Shift-2);
   double rsi2=iRSI(NULL,0,RSIPeriod,0,Shift-1);
   double rsi3=iRSI(NULL,0,RSIPeriod,0,Shift);
   double rsi4=iRSI(NULL,0,RSIPeriod,0,Shift+1);
   double rsi5=iRSI(NULL,0,RSIPeriod,0,Shift+2);
  
   rsi1<rsi2 && rsi2<rsi3 && rsi3>rsi4 && rsi4>rsi5
 

Вложения

  • Screenshot_5.png
    Screenshot_5.png
    15,1 КБ · Просмотры: 21
Последнее редактирование:

mobidik

-----
Экстремумы - это фракталы, т.е. слева и справа от него должно быть некоторое количество свечей.
А т.к. у РСИ - это уровни, то соответственно линия должна их пробить(каждая свеча - это определенный уровень)
Код:
   double rsi1=iRSI(NULL,0,RSIPeriod,0,Shift-2);
   double rsi2=iRSI(NULL,0,RSIPeriod,0,Shift-1);
   double rsi3=iRSI(NULL,0,RSIPeriod,0,Shift);
   double rsi4=iRSI(NULL,0,RSIPeriod,0,Shift+1);
   double rsi5=iRSI(NULL,0,RSIPeriod,0,Shift+2);
 
   rsi1<rsi2 && rsi2<rsi3 && rsi3>rsi4 && rsi4>rsi5
Слава, и где тут:
экстренумы осцилляторов за некоторое количество баров
уточню: где тут пик за последних, скажем, 100 баров начиная от 321 бара?
 

vladradon

Программист
Экстремумы - это фракталы
Экстремумы - это некие пики/провалы в изменении некого значения в заданном диапазоне значений. Мы можем взять динамически изменяемый по количеству значений массив и находить в нем максимальное и минимальное значение. Для того же RSI можем при выходе за установленные границы, считать максимум/минимум по значениям индикатора, но в расчет брать текущие цены инструмента. И если у индикатора появился выход за заданные границы, то это уже можно считать экстремумом для данного индикатора (имею ввиду стандартизированного, как RSI). Либо начать отсчет в этот момент до выхода из зоны и только тогда вычислить экстремум в диапазоне от точки выхода за границу до точки входа в зону стабильности. Это может работать с дополнительными фильтрами на больших таймфреймах.
 

Вложения

  • RSIEXTR.png
    RSIEXTR.png
    24,6 КБ · Просмотры: 22

Quippy

Прохожий
Всем доброго времени суток. Пишу советника, основанного на стратегии "Стратегия нужный момент".
Возникла большущая загвоздка с алгоритмом на продажу.
Не буду приводить весь код. Приведу лишь фрагменты.
Для начала я написал функцию для подсчета количества ордеров sell:
mql4:
int CountSell()
  {
   int count = 0;

   for(int trade = OrdersTotal() - 1; trade >= 0; trade--)
     {
      if(OrderSelect(trade, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == OP_SELL)
           {
            count++;
           }
        }
     }
   return (count);
  }

Затем, согласно условию, указанному в стратегии, а именно: "Если RSI пересек линию 70, ждём подтверждения от Williams (показатель должен пересечь линию -20). В этот момент цена должна находиться примерно у верхней линии полос Боллиджера, тогда открываем позицию." я написал функцию для открытия ордера на продажу:

функция открытия ордера на продажу:
double diff = MathAbs(PriceHigh - Bid); // разница между значением цены и верхней полосы Боллинджера
 
double fin =  NormalizeDouble(diff,Digits);  

if(CountSell() == 0 && TickRSI < 70 && TickWPR < -20 && (fin <= 0.00016)) //с помощью последнего условия как раз проверяю близость к верхней полосе
     {
   
      ticket = OrderSend(Symbol(),OP_SELL, Lots, Bid, Slippage, 0, 0,"First_expert",Magic, 0, Red);
      if(ticket > 0)
        {
         SL = NormalizeDouble(Bid + StopLoss * Point, Digits);
         TP = NormalizeDouble(Bid - TakeProfit * Point, Digits);

         if(OrderSelect(ticket, SELECT_BY_TICKET))
            OrderModify(ticket, OrderOpenPrice(), SL, TP, 0, Red);
        }
     }

Далее написал код, как мне казалось, исключительно по стратегии : "Затем ждём пробоя средней линии полос Боллинджера, опять же, этот уровень цена должна пройти без лишних колебаний. Если же цена достигла нижней (на сайте указано верхней. Вероятно, опечатка) линии полос Боллинджера, то готовимся закрывать позицию в момент, когда индикатор Вильямса пересечёт уровень -80 снизу вверх."
Закрытие ордера:
   if(CountSell() > 0 && Bid < ((PriceHigh + PriceLow) / 2)) //если есть открытые ордера и пробита средняя линия полос Боллинджера
     {
      RuleCloseSell = true;
     }

   double key = MathAbs(PriceLow - Bid); //разница между ценой и значением нижней полосы
   double final_key = NormalizeDouble(key,Digits);

   if(final_key <= 0.00020 &&  CountSell( ) > 0 && RuleCloseSell == true && TickWPR < -80) //проверка близости к нижней полосе, пробою средней и нужному положению RSI
     {
      RuleCloseSellFinal = true;
     }

   if(RuleCloseSellFinal == true && TickWPR > -80) //если предыдущие условия выполнились и теперь RSI выше -80, то закроем
     {
      OrderClose(OrderTicket(),0.01,PriceBid,Slippage);
     }

Мне казалось, что всё реализовано верно, но на практике, при проверке советника на истории, я получаю ситуацию, когда ордера Sell у меня открываются и тут же закрываются с убытком. Таких открытий/закрытий может быть около десятка за пару минут. Это навело на мысль, что у меня есть косяк в алгоритме.

Буду очень рад советам) Не удивлюсь, если я не понял каких-то основ.
Если нужны какие-то дополнения или где-то непонятен код, то я готов дополнить сведения.
 
Последнее редактирование модератором:

ZenFX

Почетный гражданин
Да в тике функции пади все висят, вот и выполняются пока цена там вокруг условия туда назад бегает. Запретить надо выполнение там ряда функций, если условие отработано. Чот типа того, ну если вообще не глядя ).
 

Slava78

Элитный участник
Всем доброго времени суток. Пишу советника, основанного на стратегии "Стратегия нужный момент".
Возникла большущая загвоздка с алгоритмом на продажу.
Не буду приводить весь код. Приведу лишь фрагменты.
Для начала я написал функцию для подсчета количества ордеров sell:
mql4:
int CountSell()
  {
   int count = 0;

   for(int trade = OrdersTotal() - 1; trade >= 0; trade--)
     {
      if(OrderSelect(trade, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == OP_SELL)
           {
            count++;
           }
        }
     }
   return (count);
  }

Затем, согласно условию, указанному в стратегии, а именно: "Если RSI пересек линию 70, ждём подтверждения от Williams (показатель должен пересечь линию -20). В этот момент цена должна находиться примерно у верхней линии полос Боллиджера, тогда открываем позицию." я написал функцию для открытия ордера на продажу:

функция открытия ордера на продажу:
double diff = MathAbs(PriceHigh - Bid); // разница между значением цены и верхней полосы Боллинджера
 
double fin =  NormalizeDouble(diff,Digits);

if(CountSell() == 0 && TickRSI < 70 && TickWPR < -20 && (fin <= 0.00016)) //с помощью последнего условия как раз проверяю близость к верхней полосе
     {
 
      ticket = OrderSend(Symbol(),OP_SELL, Lots, Bid, Slippage, 0, 0,"First_expert",Magic, 0, Red);
      if(ticket > 0)
        {
         SL = NormalizeDouble(Bid + StopLoss * Point, Digits);
         TP = NormalizeDouble(Bid - TakeProfit * Point, Digits);

         if(OrderSelect(ticket, SELECT_BY_TICKET))
            OrderModify(ticket, OrderOpenPrice(), SL, TP, 0, Red);
        }
     }

Далее написал код, как мне казалось, исключительно по стратегии : "Затем ждём пробоя средней линии полос Боллинджера, опять же, этот уровень цена должна пройти без лишних колебаний. Если же цена достигла нижней (на сайте указано верхней. Вероятно, опечатка) линии полос Боллинджера, то готовимся закрывать позицию в момент, когда индикатор Вильямса пересечёт уровень -80 снизу вверх."
Закрытие ордера:
   if(CountSell() > 0 && Bid < ((PriceHigh + PriceLow) / 2)) //если есть открытые ордера и пробита средняя линия полос Боллинджера
     {
      RuleCloseSell = true;
     }

   double key = MathAbs(PriceLow - Bid); //разница между ценой и значением нижней полосы
   double final_key = NormalizeDouble(key,Digits);

   if(final_key <= 0.00020 &&  CountSell( ) > 0 && RuleCloseSell == true && TickWPR < -80) //проверка близости к нижней полосе, пробою средней и нужному положению RSI
     {
      RuleCloseSellFinal = true;
     }

   if(RuleCloseSellFinal == true && TickWPR > -80) //если предыдущие условия выполнились и теперь RSI выше -80, то закроем
     {
      OrderClose(OrderTicket(),0.01,PriceBid,Slippage);
     }

Мне казалось, что всё реализовано верно, но на практике, при проверке советника на истории, я получаю ситуацию, когда ордера Sell у меня открываются и тут же закрываются с убытком. Таких открытий/закрытий может быть около десятка за пару минут. Это навело на мысль, что у меня есть косяк в алгоритме.

Буду очень рад советам) Не удивлюсь, если я не понял каких-то основ.
Если нужны какие-то дополнения или где-то непонятен код, то я готов дополнить сведения.
Для советника нужны четкие команды, тогда он будет работать. Но не факт, что будет прибыль
 

Вложения

  • WPR_RSI_Bands.mq4
    27,2 КБ · Просмотры: 18

vladradon

Программист
Не удивлюсь, если я не понял каких-то основ.
Все варианты проверок закрытия ордеров должны находиться выше функций открытия по коду (выполняться раньше). В функции закрытия нужно так же выбирать ордер командой OrderSelect и проверять все, как в подсчете количества ордеров, и только потом уже посылать OrderClose.
Параметры RuleCloseSell и RuleCloseSellFinal должны быть прописаны с начальным значением false, в проверках, где они меняют свое значение на true, их тоже нужно проверять на значение false:
C++:
   if(RuleCloseSell == false && CountSell() > 0 && Bid < ((PriceHigh + PriceLow) / 2)) //если есть открытые ордера и пробита средняя линия полос Боллинджера
     {
      RuleCloseSell = true;
     }

   double key = MathAbs(PriceLow - Bid); //разница между ценой и значением нижней полосы
   double final_key = NormalizeDouble(key,Digits);

   if(RuleCloseSellFinal == false && final_key <= 0.00020 &&  CountSell( ) > 0 && RuleCloseSell == true && TickWPR < -80) //проверка близости к нижней полосе, пробою средней и нужному положению RSI
     {
      RuleCloseSell = false;
      RuleCloseSellFinal = true;
     }

   if(RuleCloseSellFinal == true && TickWPR > -80) //если предыдущие условия выполнились и теперь RSI выше -80, то закроем
     {
       //Функция закрытия ордеров со всеми проверками
       //OrderClose(OrderTicket(),0.01,PriceBid,Slippage);
       //Сбрасываем в исходное состояние
      RuleCloseSell = false;
      RuleCloseSellFinal = false;
     }
Возможно, по коду нужно еще проверки и сбросы триггеров делать - это нужно уже весь код гонять.
 

Crik1978

Интересующийся
Всем привет. Нужна помощь: при торговле бинарных опционами при написании советника необходимо указать время в минутах (время экспирации). Отсюда вопрос: можно ли прописать чтобы время задать не в минутах, а при закрытии свечи, т.е. если ордер открывается в 10.20.15 (в 10 часов 20 минут 15 секунд) то время экспирации должно быть 10.25.00 (при закрытии свечи). Получается время экспирации 4 мин 45 сек. Как правильно прописать.
 

vladradon

Программист
Как правильно прописать.
Время экспирации задается для отложенных ордеров. Если нужно закрыть рыночный ордер, то просто при открытии новой свечи запускаем команду закрытия ордера. Набросал варианты для теста.
 

Вложения

  • TimeExpirationBar.mq4
    4 КБ · Просмотры: 7

AlexeyVik

Программист mql4 mql5
Время экспирации задается для отложенных ордеров. Если нужно закрыть рыночный ордер, то просто при открытии новой свечи запускаем команду закрытия ордера. Набросал варианты для теста.
Влад, вопрос не о закрытии, а о бинарных опционах.
Всем привет. Нужна помощь: при торговле бинарных опционами при написании советника необходимо указать время в минутах (время экспирации). Отсюда вопрос: можно ли прописать чтобы время задать не в минутах, а при закрытии свечи, т.е. если ордер открывается в 10.20.15 (в 10 часов 20 минут 15 секунд) то время экспирации должно быть 10.25.00 (при закрытии свечи). Получается время экспирации 4 мин 45 сек. Как правильно прописать.
Нет нельзя.
 

Quippy

Прохожий
Для советника нужны четкие команды, тогда он будет работать. Но не факт, что будет прибыль
Огромное Вам спасибо! Если я всё верно понял, то Вы привели как раз код той стратегии, по которой я пытаюсь написать советника!
 

Crik1978

Интересующийся
Влад, вопрос не о закрытии, а о бинарных опционах.

Нет нельзя.
Всем привет. В гранд капитал есть советник в котором это можно выставить. Код закрыт. Если там это работает, наверное есть какие-то варианты.....
 
Верх