Обучение языку MQL4 под MetaTrader 4📌

От xbms, 13 апреля, 2013 в Уголок Программиста

#5826
11 часов назад, 0ll сказал:

1. Надеюсь запускаете по закрытию бара, а не на каждом тике.

2. Зачем пересчитывать уже закрытые бары в цикле многократно? они уже цвет не поменяют!

Я не большой профи в программировании, к сожалению))). Прошу, если возможно, более подробно расписать, что Вы имели в виду. Я пишу сюда т.к. полагаю, что здесь могут помочь в плане обучения mql4. Если не сложно прямо в коде внесите корректировке, если возможно... Спасибо!!

#5827
48 минут назад, Владимир Стариков сказал:

Если не сложно прямо в коде внесите корректировке, если возможно... Спасибо!!

Пробуйте:

Спойлер

double PercentsBearBars(int Q_bar_,ENUM_TIMEFRAMES tf,bar_color_style bar_color_)
  {
   static datetime dtb;
   static int kf;
   if  ( dtb == iTime(NULL, tf, 1)) return( (kf / Q_bar_)*100 );   // если бар не закрыт - выход
         dtb  = iTime(NULL, tf, 1);
         
   kf=0;
   for(int i=1; i< Q_bar_+1; i++)
     {
      if(bar_color_==full)
        {
         if(iClose(NULL,tf,i)<iOpen(NULL,tf,i)&&
            (ha(tf,3,i)<ha(tf,2,i)))
            kf++;    break;
        }
      if(bar_color_==Jap)
        {
         if(Close <Open)
            kf++;    break;
        }
      if(bar_color_==Ha)
        {
         if(ha(tf,3,i)<ha(tf,2,i))//белая
            kf++;    break;
        }
      if(bar_color_==Elder)
        {
         if(MA(i)<MA(i+1)&&(BB_lines(MODE_MAIN,i)<BB_lines(MODE_MAIN,i+1)))
            kf++;    break;
        }
      if(bar_color_==superfull)
        {
         if(iClose(NULL,tf,i)<iOpen(NULL,tf,i)&&ha(tf,3,i)<ha(tf,2,i)&&
            MA(i)<MA(i+1)&&(BB_lines(MODE_MAIN,i)<BB_lines(MODE_MAIN,i+1)))
            kf++;    break;
        }
     }
   return( (kf / Q_bar_)*100 );
  }

 

 

#5828

Здравствуйте, начал учится писать индикаторы и что идет ни так, хотел попробывать поставить стрелочки на лоями и хаями только вот над хаями не хочет ставить и не пойму почему, подскажите пожалуйста наставьте на путь верный...

 

Спойлер

#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Blue

double buffer1[];
double buffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
  SetIndexBuffer(0, buffer1);
  SetIndexStyle(0, DRAW_ARROW);
  SetIndexArrow(0, 242);
  SetIndexBuffer(1, buffer2);
  SetIndexStyle(1, DRAW_ARROW);
  SetIndexArrow(1, 241);

  return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
void start()
{
  int limit = Bars - IndicatorCounted() + 1;

  for(int i = 0; i < limit - 1; i++)
    {
 //   buffer = 0.5 * (Close[ i ] + Close[i + 1]);
    if(i > 1)
      {
      if((Low [ i ]< Low[+ 1])        // если цена меньше предыдущего бара (i+1)
        && (Low[ i ] < Low[i - 1])   // если цена меньше последующего бара (i-1)
        && (Low[ i ] < Low[+ 2])  // если цена меньше и последующего бара (i+2)
        && (Low[ i ] < Low[- 2]))  // если цена меньше и последующего бара (i-2)
        buffer2 [ i ]= Low[ i ] - 0.00005; // установка символа на мин ценой с отступом (0.00005) пипса
      }
    }
  for(int i = 0; i < limit - 1; i++)
    {
    if(i > 1)
      {
      if((High[ i ] > High[+ 1])        // если цена больше предыдущего бара (i+1)
        && (High[ i ] > High[i - 1])   // если цена больше последующего бара (i-1)
        && (High[ i ] > High[i + 2])  // если цена больше и последующего бара (i+2)
        && (High[ i ] > High[i - 2]))  // если цена больше и последующего бара (i-2)
        buffer1[ i ] = High[ i ] + 0.00005; // установка символа на мах ценой с отступом (0.00005) пипса
      }
    }
    
}

 

Буду очень признателен!!!

Изменено 9 января, 2020 пользователем vikneo

#5829

@vikneo Приветствую! Буду откровенен! Ты вот эту ерунду пытался от компилировать? Под словом ерунда подразумеваю ошибки, а не твою идею.

Изменено 8 января, 2020 пользователем MikR0ReR

#5830

компелятор ошибок не выявляет

 

#5831

в выражениях при прописывании в буферах Low  и High  не копируется [ i ],  простите нашел почему без пробелов не рисует.

Исправлено.

 

Изменено 8 января, 2020 пользователем vikneo

#5832
9 минут назад, vikneo сказал:

компелятор ошибок не выявляет

 

Провокация!

Спойлер

1024041595_.thumb.jpg.88ec09abf3b9ba8463ff44cda2ec0a05.jpg

 

 

3 минуты назад, vikneo сказал:

в выражениях при прописывании в буферах Low  и High  не копируется  ""пытался отредактировать не пишет

 

Не понял!

Изменено 8 января, 2020 пользователем MikR0ReR

#5833
3 часа назад, MikR0ReR сказал:

Не понял!

Форумный движок воспринимает [ i ] (без пробелов) как тэг перехода текста на курсив и сам тэг исчезает из текста, рекомендую для вставки кода использовать специальное поле в меню обозначено знаком "</>"

#5834

помогите разобраться , написал  индикатор в отдельном окне! окно есть,но там пусто и Ошибок нет

#5835

@JAYZER бывает...

#5836

Доброго времени суток, уважаемые форумчане!

В процессе написания советника возникла небольшая заминка. Подскажите как ее лучше разрешить.

Суть вопроса: некоторые сделки серии могут зависнуть на несколько дней, соответственно могут начисляться отрицательные свопы. Вот я и подумал, что неплохо было бы циклом перебрать все открытые ордера, отобрать те у которых OrderSwap < 0 и модифицировать OrderTakeProfit этих ордеров, добавив к ним OrderSwap*(-1). Заминка в том, что OrderTakeProfit это конкретная цена котировки, а OrderSwap это сумма в usd например. Соответственно их нужно привести к единообразию.

Реализовать я думаю следующим образом (схематично):

Если OrderTakeProfit(цена) - OrderOpenPrice(цена) < TP(пункты)

то ModifyOrders: TP(пункты) = (OrderTakeProfit(цена) + OS(цена)-OrderOpenPrice(цена))*Point(цена пункта)

где OS=OrderSwap(usd)*(-1)/Point(цена пункта)

 

Подскажите, я правильно логику описал или что-то напутал при переводе свопа из валюты депозита в пункты а потом в цену.

Изменено 18 января, 2020 пользователем Oleg Petrov

#5837

@Oleg Petrov тут есть тонкости:

MarketInfo( _Symbol, MODE_TICKVALUE ) - Размер минимального изменения цены инструмента в валюте депозита

Point - Возвращает размер пункта текущего инструмента в валюте котировки

OrderSwap (в валюте депозита) / цену пункта (в валюте депозита) = количество пп для модификации (dTP)

Потом TP(новая цена) = OrderTakeProfit(цена) +- dTP ( не перепутать направление!)

Изменено 18 января, 2020 пользователем 0ll

#5838
55 минут назад, 0ll сказал:

@Oleg Petrov тут есть тонкости:

MarketInfo( _Symbol, MODE_TICKVALUE ) - Размер минимального изменения цены инструмента в валюте депозита

Point - Возвращает размер пункта текущего инструмента в валюте котировки

OrderSwap (в валюте депозита) / цену пункта (в валюте депозита) = количество пп для модификации (dTP)

Потом TP(новая цена) = OrderTakeProfit(цена) +- dTP ( не перепутать направление!)

Спасибо за уточнение.

Насколько я понял, моя вышеуказанная логика должна быть скорректирована следующим образом (для покупок):

Если OrderTakeProfit(цена) - OrderOpenPrice(цена) < TP(пункты) и OrderSwap<0

то ModifyOrders: TP(цена) = OrderTakeProfit(цена) + OS(пункты)*Point(цена пункта) //здесь получаем итоговую котировку для ТР

где OS(пункты)=OrderSwap(usd)*(-1)/MarketInfo( _Symbol, MODE_TICKVALUE )  //здесь получаем количество пунктов для корректировки ТР

 

Утром на свежую голову напишу код.

#5839

Получился вот такой код. Компиляция ошибок не выдала.

Спойлер

 


void ModifyOrders1(int otype)
{
   double osp, otp=0;
   double os = 0;
   
   for (int i=OrdersTotal()-1; i>=0; i--)
   {
       if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
       {
           if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == otype && OrderSwap() < 0)
           {
               otp = OrderTakeProfit();
               os = OrderSwap();
           }
       }
   }
   osp = NormalizeDouble(os*(-1) / MarketInfo(Symbol(),MODE_TICKVALUE), Digits);
   
   if (otype == OP_BUY) tp = NormalizeDouble(otp + NormalizeDouble(osp*Point, Digits), Digits); 
   if (otype == OP_SELL) tp = NormalizeDouble(otp - NormalizeDouble(osp*Point, Digits), Digits); 
   
   for (int i=OrdersTotal()-1; i>=0; i--)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
          if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == otype && OrderSwap() < 0)
          {
             if (OrderModify(OrderTicket(), OrderOpenPrice(), 0, tp, 0))
               Print ("Ордера успешно модифицированы");
             else Print ("Ошибка модификации ордеров");  
          }
      }
   }

} 

 

Изменено 19 января, 2020 пользователем 0ll

#5840

@Oleg Petrov Если несколько ордеров, то нужно делать 1 цикл, 2 цикла работать не будет! т.е. сразу снимаете данные ордера и сразу модифицируете ТП.

osp - тип int! все эти заморочки с NormalizeDouble не нужны с пунктами

Это:

if (otype == OP_BUY) tp = NormalizeDouble(otp + NormalizeDouble(osp*Point, Digits), Digits); 
if (otype == OP_SELL) tp = NormalizeDouble(otp - NormalizeDouble(osp*Point, Digits), Digits);

можно заменить (по-желанию) на это:

tp = NormalizeDouble( otp + MathPow(-1,otype)*osp*_Point, Digits ); 

Изменено 19 января, 2020 пользователем 0ll

#5841
5 часов назад, 0ll сказал:

@Oleg Petrov Если несколько ордеров, то нужно делать 1 цикл, 2 цикла работать не будет! т.е. сразу снимаете данные ордера и сразу модифицируете ТП.

@0ll спасибо за комментарии. Правильно ли я понимаю, что для того чтобы использовать 2 цикла нужно применить 2 магика? Или есть еще какой-то вариант.

По моей задумке в советнике первые несколько колен открываются по логике мартингейла и в них выставляется общий ТР с пересчетом по обычному циклу (написан по урокам из этой ветки без проблем), а вот следующие несколько сделок открываются без мартингейла с ТР на разных уровнях. Вот для этой второй части я пишу отдельный цикл для корректировки на своп.

#5842

@Oleg Petrov Не пойму зачем Вам 2 цикла перебора ордеров? Задача по пересчёту ТП и его модификации прекрасно делается в 1 цикле, и наоборот в 2 циклах сделать невозможно.

Как Вы собираетесь первые несколько ордеров сетки в цикле отсортировывать? - мне тоже интересно.

Обычно по сетке считается суммарный своп по всем ордерам и общий ТП сдвигается для коррекции общего свопа.

У Вас ситуация сложнее - только разные магики вводить.

В общем цикл по отдельным ордерам может выглядеть так:

Спойлер

   for (int i=OrdersTotal()-1; i>=0; i--)
   {
       if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
       {
           if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == otype && OrderSwap() < 0)
           {
               otp = OrderTakeProfit();
               os = OrderSwap();
               osp = -os / MarketInfo(_Symbol, MODE_TICKVALUE);
               tp = NormalizeDouble( otp + MathPow(-1,otype)*osp*_Point, Digits );
               if (OrderModify(OrderTicket(), OrderOpenPrice(), 0, tp, 0))
                    Print ("Ордера успешно модифицированы");
               else Print ("Ошибка модификации ордеров"); 
           }
       }
   }

 

 

#5843

@0ll , 2 цикла именно потому что не предполагается одного общего ТР для всех сделок: у первой группы ордеров он общий, а у второй группы ТР индивидуальный для каждого ордера. Соответственно логика модификации для двух групп ордеров отличается.

Реализовать это на мой взгляд можно с помощью счетчиков ордеров Count. Сначала считаются count1 для группы ордеров с общим ТР, потом после достижения count1 максимального ограничения количества ордеров (из настроек советника конечно) начинают считаться count2 с индивидуальными ТР. Ну и магики естественно тоже разные для двух групп.

#5844
3 часа назад, Oleg Petrov сказал:

2 цикла именно потому что не предполагается одного общего ТР для всех сделок

Я именно для этого случая и пишу: только в 1 цикле. Но Ваше право попробовать по своему.

Счётчики для фильтрации ордеров могут отработать не корректно - Брокер может включить частичное исполнение, разные магики - да.

#5845

@0ll , извините если туплю, но у меня сейчас вопрос возник по модификации. Смущает вот что. Допустим запустили мы этот цикл корректировки ТР на своп. Код без ошибок, компиляция прошла успешно. Но после его корректного исполнения (увеличения ТР на величину своп) цикл будет бесконечно повторяться так как первичное условие (OrderSwap < 0) не изменилось. И получается что ТР будет постоянно расти, даже при том условии что минусовое значение свопа не увеличивается. Подскажите как сделать чтобы ТР изменялся только при изменении своп в сторону большего минуса? Или я что-то не так понял?

#5846
В 20.01.2020 в 15:32, Oleg Petrov сказал:

Подскажите как сделать чтобы ТР изменялся только при изменении своп в сторону большего минуса?

Запускать модификацию нужно только после ролловера, 1 раз в сутки. 

У Вас должно быть правило расчёта ТП в момент выставления ордера, Вот его и используйте, без разницы увеличился своп или уменьшился - рассчитали поправку изменили первичный ТП и модифицировали ордер.

#5847

@0ll , это ограничение лучше сделать через жесткую фиксацию разрешенного времени для модификации?

Например: if (TimeHour(TimeCurrent())==1 && TimeMinute(TimeCurrent())==1)  // вроде за минуту должны успеть все ордера модифицироваться

Или есть како-то более надежный способ? (смущает что даже за минуту может произойти несколько модификаций одного ордера)

Хотя если следуя Вашей рекомендации считать модификацию не от последнего ТР а от стартового OpenPrice то возможно зацикливание модификации и не так уж критично. 

Спойлер

   for (int i=OrdersTotal()-1; i>=0; i--)
   {
       if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
       {
           if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == otype && OrderSwap() < 0)
           {                                                                                                       
               oop = OrderOpenPrice();                                                                                                    
               os = OrderSwap();
               osp = -os / MarketInfo(_Symbol, MODE_TICKVALUE);
               tp = NormalizeDouble( oop+ TakeProfit*Point + MathPow(-1,otype)*osp*_Point, Digits );
               if (OrderModify(OrderTicket(), OrderOpenPrice(), 0, tp, 0))
                    Print ("Ордера успешно модифицированы");
               else Print ("Ошибка модификации ордеров"); 
           }
       }
   }

 

 

Изменено 21 января, 2020 пользователем 0ll

#5848
3 часа назад, Oleg Petrov сказал:

Или есть како-то более надежный способ?

да, есть, например:

datetime dtLast = 0; // на глобальном уровне - дата последней модификации

if ( Hour() = 1 && TimeCurrent() - dtLast >= 23*3600 ) // если текущий час = 1 и время от последней модификации >= 23 часов

3 часа назад, Oleg Petrov сказал:

возможно зацикливание модификации

Чтоб не "мучить" брокера пустыми запросами, нужно сделать проверку:

if ( MathAbs( tp - OrderTakeProfit() ) < 3 ) continue;  // если дистанция от нового ТП до старого меньше 3 пипс - следующий ордер (т.е. пропустить модификацию)

if (OrderModify(OrderTicket(), OrderOpenPrice(), 0, tp, 0))
                {    Print ("Ордера успешно модифицированы");

                     dtLast = TimeCurrent();  // здесь можно сохранить текущее - последнее время модификации

                }

Изменено 21 января, 2020 пользователем 0ll

#5849

@0ll Получился вот такой код. Компиляция ошибок не выдала. Но есть предупреждение "possible loss of data due to type conversion " (несоответствие типов) в строке расчета osp. NormalizeDouble с округлением до нуля не помогает. Подскажите плиз как его исправить.

Спойлер

 if (CountTrades()>=1) 
 {
 if (BuyCount()>=1 && SellCount()==0 && Hour()==1 && (TimeCurrent()-dtLast)>=23*3600)
 {
  ModifyOrders(OP_BUY); 
 }
 if (SellCount()>=1 && BuyCount()==0 && Hour()==1 && (TimeCurrent()-dtLast)>=23*3600)
 {
  ModifyOrders(OP_SELL); 
 }
//+------------------------------------------------------------------+
void ModifyOrders(int otype)
{
   int osp;
   double otp = 0;
   double oop = 0;
   double os = 0;   
   for (int i=OrdersTotal()-1; i>=0; i--)
   {
       if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
       {
           if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == otype && OrderSwap() < 0)
           {
               oop = OrderOpenPrice();
               otp = OrderTakeProfit();
               os = OrderSwap();               
           }
       }
   }
   osp = -os/MarketInfo(Symbol(),MODE_TICKVALUE);   
   if (otype == OP_BUY) tp = NormalizeDouble(oop+(TakeProfit*Point)+(osp*Point), Digits); 
   if (otype == OP_SELL) tp = NormalizeDouble(oop-(TakeProfit*Point)-(osp*Point), Digits); 
   
   for (int i=OrdersTotal()-1; i>=0; i--)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
          if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == otype && OrderSwap() < 0)
          {
             if (MathAbs(tp-otp<3)) continue;
             if (OrderModify(OrderTicket(), OrderOpenPrice(), 0, tp, 0))               
               Print ("Ордера успешно модифицированы");
             else Print ("Ошибка модификации ордеров");
               dtLast = TimeCurrent();                            
          }
      }
   }
}   

 

 

#5850
15 часов назад, Oleg Petrov сказал:

расчета osp. NormalizeDouble с округлением до нуля не помогает. Подскажите плиз как его исправить.

Так: osp = (int) -os/MarketInfo(Symbol(),MODE_TICKVALUE); 

Объясню в последний раз алгоритм Вашей реализации с двумя циклами:

1. Первый цикл перебирает все ордера и заканчивается, при этом в переменных oop, otp, os - останутся данные последнего ордера!

2. Вычисляете ТП для последнего ордера

3. Модифицируете ТП всех ордеров по расчётному ТП для последнего ордера.

Если так и задумано, то - ОК.

Для публикации сообщений создайте учётную запись или авторизуйтесь

Перейти к списку тем
Форум · 2.0.20260627.0025