Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 1800

 

Что такое DecreaseFactor в стандартном советнике МТ на машках?

lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
 
Nerd Trader #:

Странно, сейчас кнопки есть. А нагромождение кода, потому что это черновик. В общем я уже сделал рабочий вариант, осталось последнее - удаление кнопок, тут опять эта херота началась: в ф-ции удаления не находит ни один из 4-ех объектов.

По клику на кнопке создаются все линии:

Если кнопка отжата - удаляем:

Какая дичь написана, вы уж извините.

 
Artyom Trishkin #:

А не нужно смотреть события. Они вообще в тестере не работают. Нужно смотреть состояние.

UPD. Не скромно конечно, но если бы хоть раз послушали мои подсказки, то давно бы уже всё сделали. Правильно и без костылей многоэтажных.

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

Mihail Matkovskij #:

Для использования дебага в тестере учись писать на MQL5. Там всё работает. 

Никакого переименования объекта не существует. Думай об этом как о замене существующего объекта новым объектом.

Быть такого не может. Твой код напоминает беспорядочное нагромождение всего. Возможно, поэтому, у тебя и лаги возникают с кнопками. Как я тебе уже говорил, начни с простого. Не усложняй ничего. И постепенно усложняй когда простое начнет работать и ты будешь в нем уверен.

И как мне состояния посмотреть если они запускаются по событию (по клику)? Да но я пишу на mql4, это одно и тоже что сказать "учись писать на c# там дебаг работает".

"Правильно и без костылей многоэтажных. " - так скрытие объектов это и есть костыли.

В общем всё сделал, всё работает https://gist.github.com/satorkain/0cf7a8df8ec1f4b3191defd04c94a418
По клику на кнопке создаются все линии сразу, тут же скрываются и остётся только одна в зависимости от расположения панели кнопок. Далее линии скрываются/показываются в зависимости от расположения курсора относительно цены.

З.Ы

Если бы не кривой mql4, то не пришлось бы придумывать этот бред со скрытием объектов, всё должно было работать и в первый раз с удалением/переименованием объектов.

stop order button (public).mq4
stop order button (public).mq4
  • gist.github.com
GitHub Gist: instantly share code, notes, and snippets.
 
Nerd Trader #:

И как мне состояния посмотреть если они запускаются по событию (по клику)? Да но я пишу на mql4, это одно и тоже что сказать "учись писать на c# там дебаг работает".

"Правильно и без костылей многоэтажных. " - так скрытие объектов это и есть костыли.

В общем всё сделал, всё работает https://gist.github.com/satorkain/0cf7a8df8ec1f4b3191defd04c94a418
По клику на кнопке создаются все линии сразу, тут же скрываются и остётся только одна в зависимости от расположения панели кнопок. Далее линии скрываются/показываются в зависимости от расположения курсора относительно цены.

З.Ы

Если бы не кривой mql4, то не пришлось бы придумывать этот бред со скрытием объектов, всё должно было работать и в первый раз с удалением/переименованием объектов.

Сокрытие объекта - это как раз-таки рекомендованный разработчиком метод. И есть для этого специальное свойство. Чтобы посмотреть состояние, нужно посмотреть на свойство кнопки "Состояние".

Кривое тут - ваша логика и подмена понятий - вы за костыль принимаете рекомендованные разработчиком средства, а постоянное прожорливое создание/удаление объекта принимаете за чистый код, но именно он и является лютым костылём в обход рекомендуемого быстрого способа.

Кстати, чтобы быстро сделать объект поверх всех остальных, нужно сделать его невидимым, и сразу же видимым - это переопределит его расположение в списке объектов, и он станет наверху.

ЗЫ. И даже там, на гите, вы опубликовали код на троечку с минусом. Абсолютно неустойчивый к ошибкам. Стоит только одной линии не быть созданной, всё у вас рухнет. Это сразу же в глаза бросилось. Линии создаёте в обработчике событий - зачем? OnInit() вам для чего? Создали, проверили успешность - выставили флаг и скрыли. В OnDeinit() удалили созданные своей программой объекты. Для этого ещё и префикс имени нужен.

В обработчике событий только показываете и скрываете - никаких построений не должно быть. Для вашего случая - точно.

Мне было бы стыдно на гите такое публиковать в публичном доступе. Но это мне.

А вам? Нормально, что этим могут воспользоваться люди?

 
Artyom Trishkin #:

Сокрытие объекта - это как раз-таки рекомендованный разработчиком метод. И есть для этого специальное свойство. Чтобы посмотреть состояние, нужно посмотреть на свойство кнопки "Состояние".

Кривое тут - ваша логика и подмена понятий - вы за костыль принимаете рекомендованные разработчиком средства, а постоянное прожорливое создание/удаление объекта принимаете за чистый код, но именно он и является лютым костылём в обход рекомендуемого быстрого способа.

Кстати, чтобы быстро сделать объект поверх всех остальных, нужно сделать его невидимым, и сразу же видимым - это переопределит его расположение в списке объектов, и он станет наверху.

ЗЫ. И даже там, на гите, вы опубликовали код на троечку с минусом. Абсолютно неустойчивый к ошибкам. Стоит только одной линии не быть созданной, всё у вас рухнет. Это сразу же в глаза бросилось. Линии создаёте в обработчике событий - зачем? OnInit() вам для чего? Создали, проверили успешность - выставили флаг и скрыли. В OnDeinit() удалили созданные своей программой объекты. Для этого ещё и префикс имени нужен.

В обработчике событий только показываете и скрываете - никаких построений не должно быть. Для вашего случая - точно.

Мне было бы стыдно на гите такое публиковать в публичном доступе. Но это мне.

А вам? Нормально, что этим могут воспользоваться люди?

Прожорливость создавать по мере необходимости 1 линию из 4? :) А что если линий 200? Экономично будет их создать по вашей логике все сразу? А как было задумано разработчиками, это известно только им самим, причем задумано весьма не интуитивно. Как бы ничего невероятного или нелогичного не требовалось. Ну вот откуда мне было знать, что работать с объектами надо только так и не как иначе? Может быть из учебника по mql4? Сомневаюсь что там этот момент объясняется.

Оно хотя бы работает как было задумано :) Там в названии в скобочках (public) то есть он ещё не полный, но да, проверки на создание объектов нет, исправим.   И я выложил на гите только потому что не мог вспомнить paste bin. Стыдится? Гит в том числе и был придуман для того, чтобы люди учились, обменивались опытом, делились кодом, рабочим или нет, без разницы, любой может сделать форк и внести изменения если его что-то не устраивает.

Вот пожалуйста, 250 объектов создали и храним их в памяти на протяжении всей работы эксперта. Ну ладно, спасибо, буду знать.  Про это я и говорю "не интуитивная логика". В учебнике например про OnInit() можно вычитать только, что ф-ция обрабатывается при инициализации советника/индикатора.

 
Nerd Trader #:


Открою тебе один секрет. Ты можешь создать хоть 1000 объектов и больше, если у тебя не "калькулятор". Но это под силу и ему. Калькулятор, это комп. с ОЗУ 4GB. Всё что ниже, это "бабушкины счёты"... :) Так что создавай объекты хоть все сразу, хоть по одному. Без разницы. Но без фанатизма.

Таким образом, всё у всех получается, если делать с умом!...

 
Nerd Trader #:

Прожорливость создавать по мере необходимости 1 линию из 4? :) А что если линий 200? Экономично будет их создать по вашей логике все сразу? А как было задумано разработчиками, это известно только им самим, причем задумано весьма не интуитивно. Как бы ничего невероятного или нелогичного не требовалось. Ну вот откуда мне было знать, что работать с объектами надо только так и не как иначе? Может быть из учебника по mql4? Сомневаюсь что там этот момент объясняется.

Оно хотя бы работает как было задумано :) Там в названии в скобочках (public) то есть он ещё не полный, но да, проверки на создание объектов нет, исправим.   И я выложил на гите только потому что не мог вспомнить paste bin. Стыдится? Гит в том числе и был придуман для того, чтобы люди учились, обменивались опытом, делились кодом, рабочим или нет, без разницы, любой может сделать форк и внести изменения если его что-то не устраивает.

Вот пожалуйста, 250 объектов создали и храним их в памяти на протяжении всей работы эксперта. Ну ладно, спасибо, буду знать.  Про это я и говорю "не интуитивная логика". В учебнике например про OnInit() можно вычитать только, что ф-ция обрабатывается при инициализации советника/индикатора.

Можно создать одновременно объектов столько, сколько нужно. Пока МТ был не совсем развит в плане создания отрисовки индикаторных буферов, приходилось рисовать 400 видимых свечей трендовыми линиями, на одну свечу нужно 5 линий, 400*5=2000, плюс по одному объекту на каждую и прочие. Итого получалось около 2500 объектов. Работало без тупизма.

Вы не совсем понимаете логику работы с объектами, но спорить умеете. Лучше делать наоборот.

 
Nerd Trader #:

Прожорливость создавать по мере необходимости 1 линию из 4? :) А что если линий 200? Экономично будет их создать по вашей логике все сразу? А как было задумано разработчиками, это известно только им самим, причем задумано весьма не интуитивно. Как бы ничего невероятного или нелогичного не требовалось. Ну вот откуда мне было знать, что работать с объектами надо только так и не как иначе? Может быть из учебника по mql4? Сомневаюсь что там этот момент объясняется.

Оно хотя бы работает как было задумано :) Там в названии в скобочках (public) то есть он ещё не полный, но да, проверки на создание объектов нет, исправим.   И я выложил на гите только потому что не мог вспомнить paste bin. Стыдится? Гит в том числе и был придуман для того, чтобы люди учились, обменивались опытом, делились кодом, рабочим или нет, без разницы, любой может сделать форк и внести изменения если его что-то не устраивает.

Вот пожалуйста, 250 объектов создали и храним их в памяти на протяжении всей работы эксперта. Ну ладно, спасибо, буду знать.  Про это я и говорю "не интуитивная логика". В учебнике например про OnInit() можно вычитать только, что ф-ция обрабатывается при инициализации советника/индикатора.

Добро. Попробую по-русски простыми словами.

Вы собрались на рыбалку.

  1. Дома открыли кладовку, почесали затылок и закрыли.
  2. Приехали на рыбалку и вам нужна удочка
  3. Поехали домой в кладовку за удочкой
  4. Приехали на рыбалку, закинули удочку и поймали рыбу, и тут вам потребовался сачок
  5. Поехали домой в кладовку за сачком
  6. Приехали на рыбалку, подцепили сачком пойманную и плавающую на крючке рыбу, и вам потребовалась ёмкость для складывания пойманной рыбы
  7. Поехали домой за ..... Мне продолжать?

А можно сразу же из кладовки (OnInit) взять всё необходимое для рыбалки, порыбачить без беготни и, вернувшись домой, сложить всё в кладовку и холодильник (OnDeinit).

Знать вы могли об этом здесь на форуме. Просто иногда нужно слушать и слышать что вам говорят.

А то получается, вопрос задали, получили ответ, сказали - фигня, и делаете так как вам кажется.

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

Вы в курсе, что в программировании самое простое - это печатать код? А львиную долю разработки занимает обдумывание логики.

 

Извините, что поднимаю вопрос второй раз. 

но есть проблема. которую пока не могу решить, а именно

открытие серии ордеров (один за другим) на одной свече.

Мне нужно, чтобы советник не мог открыть новый ордер на той же самой свече.

думал решить через Sleep() но Макар сказал что процесс лучше не останавливать.

проблема.

код сейчас выглядит так:

// Параметры советника
input string  sParametersEA = "";     // Параметры советника
input double  Lot           = 0.01;   // Количество лотов
input int     StopLoss      = 30;     // Уровень убытка
input int     TakeProfit    = 30;     // Уровень прибыли
input int     Slippage      = 3;      // Проскальзование (в пунктах)
input int     Magic         = 1;      // Индентификатор советника
input double  K_Martin1     = 2.0;    // Множитель мартин 1
input double  K_Martin2     = 2.0;    // Множитель мартин 2
input double  K_Martin3     = 2.0;    // Множитель мартин 3
input int     OrdersClose   = 5;      // Ограничение лотности мартин1
input int     OrdersClose2  = 5;      // Ограничение лотности мартин2
input int     DigitsLot     = 2;      // Точность лотности
// Параметры индикатора
input string  sParametersMA = "";     // Параметры индикатора
input int     PeriodMA      = 14;     // Период мувинга
input int     MovingShift   = 1;      // Сдвиг мувинга
// Глобальные переменные
string AC;
datetime Start;
double dMA;
double MaxMartinLot;
double MaxMartinLot2;
//+-----------------------------------------------------------------------------------------------+
int OnInit()
  {
Start          = TimeCurrent();
MaxMartinLot   = Lot*MathPow(1.4,OrdersClose);
MaxMartinLot2  = Lot*MathPow(K_Martin2,OrdersClose2);
AC             = StringConcatenate(" ", AccountCurrency());
return(INIT_SUCCEEDED);
  }
//+-----------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+-----------------------------------------------------------------------------------------------+
void OnTick()
  {
// Получим значение индикатора
   dMA = iMA(Symbol(), 0,PeriodMA, MovingShift, MODE_SMA, PRICE_CLOSE, 0); // MODE_SMA - простое усреднение , значение 0. PRICE_CLOSE- цена закрытия, значение 0.

// Если нет открытых ордеров, то входим в условие
      if(CountOrders()==0)
     {
// Если появился сигнал на покупку, то откроем ордер на покупку
      if(bSignalBuy() == true)
         vOrderOpenBuy();

// Если появился сигнал на продажу, то откроем ордер на продажу
      if(bSignalSell() == true)
         vOrderOpenSell();
     }
   }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция проверки открытых оредров |
//+-----------------------------------------------------------------------------------------------+
int CountOrders() 
  {
   int cnt=0;
   int i=OrdersTotal()-1;
   for(int pos=i;pos>=0;pos--)
     {
      if(OrderSelect(pos, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderSymbol()==_Symbol)
           {
            if(OrderMagicNumber()==Magic) cnt++;
           }
        }
     }
   return(cnt);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция поиска сигнала на покупку |
//+-----------------------------------------------------------------------------------------------+
bool bSignalBuy()
  {
   if(dMA > Open[1] && dMA < Close[1])  //Open[1] и Close[1]- цены открытия и закрытия каждого бара текущего графика.
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция поиска сигнала на продажу |
//+-----------------------------------------------------------------------------------------------+
bool bSignalSell()
  {
   if(dMA < Open[1] && dMA > Close[1])
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                            Функция открытия ордера на покупку |
//+-----------------------------------------------------------------------------------------------+
void vOrderOpenBuy()
  {
// Тикет ордера
   int iOTi = 0;   

   iOTi = OrderSend(Symbol(), OP_BUY, LOT(), Ask, Slippage, 0, 0, "", Magic, 0, clrNONE);
   
// Проверим открылся ли ордер
   if(iOTi > 0)
// Есди да, то выставим уровни убытка и прибыли
      vOrderModify(iOTi);
   else
// Если нет, то получим ошибку
      vError(GetLastError());
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                            Функция открытия ордера на продажу |
//+-----------------------------------------------------------------------------------------------+
void vOrderOpenSell()
  {
// Тикет ордера  
   int iOTi = 0;   
//Print(bCheckOrders());
   iOTi = OrderSend(Symbol(), OP_SELL, LOT(), Bid, Slippage, 0, 0, "", Magic, 0, clrNONE);

// Проверим открылся ли ордер
   if(iOTi > 0)
// Есди да, то выставим уровни убытка и прибыли
      vOrderModify(iOTi);
   else
// Если нет, то получим ошибку
      vError(GetLastError());
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                                    Функция модификации ордера |
//+-----------------------------------------------------------------------------------------------+
void vOrderModify(int iOTi)
  {
   int    iOTy = -1;    // Тип ордера
   double dOOP = 0;     // Цена открытия ордера
   double dOSL = 0;     // Стоп Лосс
   int    iMag = 0;     // Идентификатор советника
   double dSL  = 0;     // Уровень убытка
   double dTP  = 0;     // Уровень прибыли

// Выберем по тикету открытый ордер, получим некоторые значения
   if(OrderSelect(iOTi, SELECT_BY_TICKET, MODE_TRADES))
     {
      iOTy = OrderType();
      dOOP = OrderOpenPrice();
      dOSL = OrderStopLoss();
      iMag = OrderMagicNumber();
     }

// Если ордер открыл данный советник, то входим в условие
   if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMag)
     {
// Если Стоп Лосс текущего ордера равен нулю, то модифицируем ордер
      if(dOSL == 0)
        {
         if(iOTy == OP_BUY)
           {
            dSL = NormalizeDouble(dOOP - StopLoss * Point, Digits);
            dTP = NormalizeDouble(dOOP + TakeProfit * Point, Digits);

            bool bOM = OrderModify(iOTi, dOOP, dSL, dTP, 0, clrNONE);
           }

         if(iOTy == OP_SELL)
           {
            dSL = NormalizeDouble(dOOP + StopLoss * Point, Digits);
            dTP = NormalizeDouble(dOOP - TakeProfit * Point, Digits);

            bool bOM = OrderModify(iOTi, dOOP, dSL, dTP, 0, clrNONE);
           }
        }
     }
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                                      Функция обработки ошибок |
//+-----------------------------------------------------------------------------------------------+
void vError(int iErr)
  {
   switch(iErr)
     {
      case 129:   // Неправильная цена
      case 135:   // Цена изменилась
      case 136:   // Нет цен
      case 138:   // Новые цены
         Sleep(1000);
         RefreshRates();
         break;

      case 137:   // Брокер занят
      case 146:   // Подсистема торговли занята
         Sleep(3000);
         RefreshRates();
         break;
     }
  }
//+-----------------------------------------------------------------------------------------------+
double LOT()
{
   int n=0;
   int m=0;
   int v=0;
   double OL=Lot;
   for (int j = OrdersHistoryTotal()-1; j >= 0; j--)
   {
      if (OrderSelect(j, SELECT_BY_POS,MODE_HISTORY))
      {
         if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
         {
            if (OrderProfit()>0) 
            {

               if (n==0) OL=NormalizeDouble(OrderLots()+K_Martin1,DigitsLot);
               n++;
               
               if ((OL>=MaxMartinLot)&& (m==0)) OL=NormalizeDouble(OrderLots()*K_Martin2,DigitsLot);
               m++;
               
               if ((OL>=MaxMartinLot2) && (v==0)) OL=NormalizeDouble(OrderLots()*K_Martin3,DigitsLot);
               v++;
            }
            else
            {
               if (n==0) {return(Lot);}
               else {return(OL);}
            }
         }
      }
   }
   
   return(OL);
}
 
законопослушный гражданин #:

Мне нужно, чтобы советник не мог открыть новый ордер на той же самой свече.

void OnTick()
  {
  datetime cTime;
  static datetime time = 0;

  cTime = iTime(NULL, PERIOD_CURRENT, 0);

  if (time != cTime)
    time = cTime;
  else
    return;

// Получим значение индикатора
   dMA = iMA(Symbol(), 0,PeriodMA, MovingShift, MODE_SMA, PRICE_CLOSE, 0); // MODE_SMA - простое усреднение , значение 0. PRICE_CLOSE- цена закрытия, значение 0.

// Если нет открытых ордеров, то входим в условие
      if(CountOrders()==0)
     {
// Если появился сигнал на покупку, то откроем ордер на покупку
      if(bSignalBuy() == true)
         vOrderOpenBuy();

// Если появился сигнал на продажу, то откроем ордер на продажу
      if(bSignalSell() == true)
         vOrderOpenSell();
     }
   }
Причина обращения: