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

hoz

Активный участник
Ну почему-же нельзя?
Вноси во внешние переменные все размеры лотов,
extern double L0 = 0.01, L1 = 0.1, L2 = 0.3; ... потом в int init() присваивай каждому элементу массива значение
LotsArray[0] = L0;
LotsArray[1] = L1;
и.т.д.
Логично. Только вот почему присваиваем каждому элементу массива значение в функции int init() ?
Обычно же, мало кто вообще этой функцией пользуется.
 

AlexeyVik

Программист mql4 mql5
Логично. Только вот почему присваиваем каждому элементу массива значение в функции int init() ?
Обычно же, мало кто вообще этой функцией пользуется.
Ну обычно этим не пользуются по неграмотности.
Можно конечно и в старт запихнуть, но зачем перезаписывать массив теми-же самыми переменными? Достаточно сделать это только один раз при запуске советника.
 

hoz

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

eevviill

Заблокирован
Err1

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


PHP:
////////////////////////////////////////////////////////////////////////
void SSM_Traling_Stop_f()
{
//поиск пиков и низин
for(int i=1;i<Bars;i++)
{
double SSM = iCustom(Symbol(),0,"PBF_Scalper_Show_Me",0,i);
if(SSM!=0)break;
}

int min_SL=MarketInfo(Symbol(),MODE_STOPLEVEL);


for (i=OrdersTotal()-1; i>=0; i--) 
  {
  OrderSelect(i, SELECT_BY_POS); 
  {
  if (OrderMagicNumber()==magic)
  { 
  double point=0.0001;
  if(StringFind(OrderSymbol(), "JPY", 0) != -1) 
  point=0.01;
  if(NormalizeDouble(OrderStopLoss(),Digits)!=NormalizeDouble(SSM-buy_otstup*point,Digits) || NormalizeDouble(OrderStopLoss(),Digits) !=NormalizeDouble(SSM+sell_otstup*point,Digits))
  {
if (OrderType()==OP_BUY &&  Bid>SSM && Bid-SSM>=min_SL*point) OrderModify(OrderTicket(),0,NormalizeDouble(SSM-buy_otstup*point,Digits),OrderTakeProfit(),0,LightBlue);
if (OrderType()==OP_SELL && Ask<SSM && SSM-Ask>=min_SL*point) OrderModify(OrderTicket(),0,NormalizeDouble(SSM+sell_otstup*point,Digits),OrderTakeProfit(),0,OrangeRed);
  }
  }
  } 
  }
}

Всё. Понял. Надо было вместо || поставить &&
 
Последнее редактирование:

AlexeyVik

Программист mql4 mql5
Возникла проблема.
Эта функция подтягивает СЛ по индикатору. Ввёл условие для дальнейшей роботы что СЛ должен не равнятся тому что показывает индикатор. Смотрел через Алерт. При совпадении СЛ и показаний индикатора всё ровно функция пытается установить СЛ на уже установлённом СЛ-е.


PHP:
////////////////////////////////////////////////////////////////////////
void SSM_Traling_Stop_f()
{
//поиск пиков и низин
for(int i=1;i<Bars;i++)
{
double SSM = iCustom(Symbol(),0,"PBF_Scalper_Show_Me",0,i);
if(SSM!=0)break;
}

int min_SL=MarketInfo(Symbol(),MODE_STOPLEVEL);


for (i=OrdersTotal()-1; i>=0; i--) 
  {
  OrderSelect(i, SELECT_BY_POS); 
  {
  if (OrderMagicNumber()==magic)
  { 
  double point=0.0001;
  if(StringFind(OrderSymbol(), "JPY", 0) != -1) 
  point=0.01;
  if(NormalizeDouble(OrderStopLoss(),Digits)!=NormalizeDouble(SSM-buy_otstup*point,Digits) || NormalizeDouble(OrderStopLoss(),Digits) !=NormalizeDouble(SSM+sell_otstup*point,Digits))
  {
if (OrderType()==OP_BUY &&  Bid>SSM && Bid-SSM>=min_SL*point) OrderModify(OrderTicket(),0,NormalizeDouble(SSM-buy_otstup*point,Digits),OrderTakeProfit(),0,LightBlue);
if (OrderType()==OP_SELL && Ask<SSM && SSM-Ask>=min_SL*point) OrderModify(OrderTicket(),0,NormalizeDouble(SSM+sell_otstup*point,Digits),OrderTakeProfit(),0,OrangeRed);
  }
  }
  } 
  }
}
Всё. Понял. Надо было вместо || поставить &&
Привет Василий, попробуй сравнивать не значения, а их разницу с нулём
if(NormalizeDouble(OrderStopLoss() - SSM-buy_otstup*point, Digits) != 0 || ...);
 

hoz

Активный участник
Вот статья: _http://articles.mql4.com/ru/330
Я вот сколько не смотрю на код, вижу что по ходу тут канкретная логическая ошибка.
Суть в том, что Есть 2, например куска кода:
PHP:
//|                                удаление лишних ордеров                                       | 
int cnt_del; 
if(pos_buy==0)
{               
  for (cnt_del=0; cnt_del<OrdersTotal(); cnt_del++) 
  {
    if (!(OrderSelect(cnt_del, SELECT_BY_POS, MODE_TRADES))) continue;     
    if(OrderSymbol()==Symbol())
    {
     if (OrderType()==OP_BUYSTOP && OrderMagicNumber()==MagicNumber2) OrderDelete(OrderTicket()); 
    }
  } 
 }
PHP:
//|                              поиск открытых ордеров по паре                                  |
    int pos_sell=0;
  for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
  { 
   if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
   if (Symbol()==OrderSymbol()
   &&OrderMagicNumber()==MagicNumber1   
   &&(OrderType()==OP_SELL))
   {
    pos_sell=1; break;   
   } 
  }
Сразу видно, что в одном случает автор выходит из цикла как только какой-то из ордеров не выбран, а во-втором случает пропускает эту выборку и дальше проверяет..
Логически абсурдно. А по факту спрашиваю у присуствующих.. Сам не въезжаю.
 
Последнее редактирование модератором:

Abi

Элитный участник
Уважаемые гуру MQL просветите меня тупого:

в советнике есть такое...

в самом начале импортируется виндовая DLL:


Код:
int GMToffset, Myoffset, LoclTime;
 
#import "kernel32.dll"
  void GetLocalTime(int& a0[]);
  int GetTimeZoneInformation(int& a0[]);
#import

потом есть такая функция:


Код:
int AutoGMTOffset() 
{
  int Timezone[43];
  int offset1 = -420;
  int offset2 = GetTimeZoneInformation(Timezone);
  if (offset2 != 0) offset1 = Timezone[0];
  if (offset2 == 2) offset1 += Timezone[42];
  LoclTime = TimeLocal() + 60 * offset1;
  GMToffset = (TimeCurrent() - LoclTime) / 3500;
  Myoffset = + ((TimeLocal() - LoclTime) / 3500);
  return (0); 
}

Понимаю так что в начале у винды запрашивается локальное время и локальная тайм-зона.
=====================================================
Далее пишу построчно как я думаю(наверно неправильно)...

1) инициализируется массив Timezone размером 43 ячейки
2) инициализируется переменная offset1 со значением -420(почему такое значение? откуда? непонятно...)
3) в offset2 заносится значение из виндовой длл (локальная тайм-зона), в каком формате? в часах +3? или +10800 в секундах?
4) и вот тут я уже вообще не понимаю - если offset2 не равен нулю(то есть получается - если я не живу в ЖМТ=0, то offset1 будет равен значению из ячейки 0 массива Timezone - а чему оно равно? мы его что? уже чем то заполнили? когда? чем?
5) тут еще хуже - если offset2 равен 2 то offset1 будет равен... и тут я тоже не понимаю (я не знаю что значит += Timezone[42] - это что, значение offset1 равно самому себе плюс значение из ячейки 42 массива? или как?)
6) переменная LoclTime равна лок.время + offset1 умноженное на 60(чтобы получить часы) - вычисления понятны, не понятно для чего
7) и 8) не понимаю почему делится на 3500 а не на 3600, ведь если хотят получить часы из секунд надо делить на 3600?
и еще - в 8) опять есть такое выражение "= +" это что значит? и равнозначно ли оно предыдущему "+=" как было написано в 5)?

Прошу помощи у гуру - распишите мне тупому построчно (как примерно я выше) что значит каждая строчка в функции...

А то советник работает в тестере, эти значения подставляются из этой функции(для этого она и была написана автором) а на демо-счете не работает, не ставит уровни, не открывает ордера.
 

Ugar

Гуру форума
Вот статья: _http://articles.mql4.com/ru/330
Я вот сколько не смотрю на код, вижу что по ходу тут канкретная логическая ошибка.
Суть в том, что Есть 2, например куска кода:
PHP:
//|                                удаление лишних ордеров                                       | 
int cnt_del; 
if(pos_buy==0)
{               
  for (cnt_del=0; cnt_del<OrdersTotal(); cnt_del++) 
  {
    if (!(OrderSelect(cnt_del, SELECT_BY_POS, MODE_TRADES))) continue;     
    if(OrderSymbol()==Symbol())
    {
     if (OrderType()==OP_BUYSTOP && OrderMagicNumber()==MagicNumber2) OrderDelete(OrderTicket()); 
    }
  } 
 }
PHP:
//|                              поиск открытых ордеров по паре                                  |
    int pos_sell=0;
  for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
  { 
   if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
   if (Symbol()==OrderSymbol()
   &&OrderMagicNumber()==MagicNumber1   
   &&(OrderType()==OP_SELL))
   {
    pos_sell=1; break;   
   } 
  }
Сразу видно, что в одном случает автор выходит из цикла как только какой-то из ордеров не выбран, а во-втором случает пропускает эту выборку и дальше проверяет..
Логически абсурдно. А по факту спрашиваю у присуствующих.. Сам не въезжаю.
В этом никакого абсурда нет. Всё зависит от конкретной ситуации.
для начала нужно разобраться почему ордер может не выбраться. Причина может быть одна, это отсутствие ордера. То есть, пока выполнялся код, какой то ордер закрылся. В итоге реалное количество ордеров не совпадает с значением OrdersTotal();
По этому надо задуматься, а как лучше поступить в каждом конкретном случае, перейти к следующему ордеру или прекратить работу цикла.
Тем не менее ошибка в верхнем коде есть. Перебирать ордера нужно в от последнего к первому. Иначе могут не все ордера удалиться. Ибо нумерация динамическая.
 

vetallic

Местный знаток
народ как правильно придать цветность комментарию?
- а то еле видно светло серым вверху в уголке
{
Comment ("\n","Риск = ", DoubleToStr(Risk,2),", Лот = ",DoubleToStr(Lot,2));
}
спсб...
 

Ugar

Гуру форума
народ как правильно придать цветность комментарию?
- а то еле видно светло серым вверху в уголке
{
Comment ("\n","Риск = ", DoubleToStr(Risk,2),", Лот = ",DoubleToStr(Lot,2));
}
спсб...
Программно, никак. Задать цвет программно можно только у объектов.
А в терминале, жми F8. На вкладке "Цвета", у параметра "Текст" выбери любой цвет.
 

hoz

Активный участник
Вот статья: _http://articles.mql4.com/ru/330
Я вот сколько не смотрю на код, вижу что по ходу тут канкретная логическая ошибка.
Суть в том, что Есть 2, например куска кода:
PHP:
//|                                удаление лишних ордеров                                       | 
int cnt_del; 
if(pos_buy==0)
{               
  for (cnt_del=0; cnt_del<OrdersTotal(); cnt_del++) 
  {
    if (!(OrderSelect(cnt_del, SELECT_BY_POS, MODE_TRADES))) continue;     
    if(OrderSymbol()==Symbol())
    {
     if (OrderType()==OP_BUYSTOP && OrderMagicNumber()==MagicNumber2) OrderDelete(OrderTicket()); 
    }
  } 
 }
PHP:
//|                              поиск открытых ордеров по паре                                  |
    int pos_sell=0;
  for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
  { 
   if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
   if (Symbol()==OrderSymbol()
   &&OrderMagicNumber()==MagicNumber1   
   &&(OrderType()==OP_SELL))
   {
    pos_sell=1; break;   
   } 
  }
Сразу видно, что в одном случает автор выходит из цикла как только какой-то из ордеров не выбран, а во-втором случает пропускает эту выборку и дальше проверяет..
Логически абсурдно. А по факту спрашиваю у присуствующих.. Сам не въезжаю.

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

я понимаю, что какой-то ордер уже к моменту выборки может отсуствовать. Но, скажем так, ордер который уже закрылся был где-то 5-ый из 10. Выборка будет по очереди, если от последнего 10,9, 8, 7, 6 ... вот мы наткнулись на 5-ый.. если продолжим как в первом верхнем варианте, то мы пропустим 5-ую выборку и дальше пойдёт 4,3,2,1 и 0.
Но если мы пойдём по пути второму нижнему, то на 5-ом ордере (если он уже закрыт), будет выход из цикла, так как там стоит оператор break.
Так? Значит всё-таки ошибка это как ни крути..
 

Ugar

Гуру форума
я понимаю, что какой-то ордер уже к моменту выборки может отсуствовать. Но, скажем так, ордер который уже закрылся был где-то 5-ый из 10. Выборка будет по очереди, если от последнего 10,9, 8, 7, 6 ... вот мы наткнулись на 5-ый.. если продолжим как в первом верхнем варианте, то мы пропустим 5-ую выборку и дальше пойдёт 4,3,2,1 и 0.
Но если мы пойдём по пути второму нижнему, то на 5-ом ордере (если он уже закрыт), будет выход из цикла, так как там стоит оператор break.
Так? Значит всё-таки ошибка это как ни крути..
Нет, не может отсутствовать №5 ордер из десяти. Здесь нумерация динамическая. Если из 10 ордеров один отсутствует, не важно какой он был по счёту, то их станет 9. №0...№8. Они всегда по порядку. Значит не станет №9 ордера.
 

hoz

Активный участник
Нет, не может отсутствовать №5 ордер из десяти. Здесь нумерация динамическая. Если из 10 ордеров один отсутствует, не важно какой он был по счёту, то их станет 9. №0...№8. Они всегда по порядку. Значит не станет №9 ордера.

Я так понимаю, если б мы выборку делали с истории к последней позиции, то дыра могла быть.. А раз мы перебираем от последней позиции к самой первой т.е. идёт от настоящего к истории.. то дыр не будет. Верно?
 

Ugar

Гуру форума
Я так понимаю, если б мы выборку делали с истории к последней позиции, то дыра могла быть.. А раз мы перебираем от последней позиции к самой первой т.е. идёт от настоящего к истории.. то дыр не будет. Верно?
По простому. Допустим 5 ордеров, №0-№4. Если удалять в порядке возрастания. Удалили №0, следующим будет удаляться №1.
Стало 4 ордера, №0-№3. То есть бывший №1 стал №0, бывший №2 стал №1.
Так как следующим удаляется №1, то №0 (Бывший №1) будет пропущен.
И так при каждом удалении.
Если же удалять от последнего к первому, никаких сдвигов номеров не будет, а значит все ордера удалятся.
 

hoz

Активный участник
Ugar, по-моему более грамотно будет выборку призвоить по тикету, тогда не нужно будет думать о том, чтоб с конца начинать или первого открытого. Согласен?
 

Ugar

Гуру форума
Ugar, по-моему более грамотно будет выборку призвоить по тикету, тогда не нужно будет думать о том, чтоб с конца начинать или первого открытого. Согласен?
А от куда программа узнает тикеты всех открытых ордеров?
Можно конечно извернуться. Создать массив, длинной равной количеству ордеров. В цикле перебрать ордера по номерам, в любом порядке, записать их тикеты в массив. Потом, ещё в одном цикле, перебирать ячейки массива по номерам, в любом порядке, извлекать тикет. Выбирать ордера по тикету и удалять их.
Только вот, кажется мне, что это как то выглядит через задницу, хотя на самом деле через массив.
 

hoz

Активный участник
А от куда программа узнает тикеты всех открытых ордеров?
Думал я что сказать.. Опыта ещё нет, чтоб ответить сразу. Но выборка по тикету это же дефолтовская функция, зачем так всё усложнять массивами?
Если в документации есть такой вариант выборки, значит должно быть проще по логике.
 

AlexeyVik

Программист mql4 mql5
Думал я что сказать.. Опыта ещё нет, чтоб ответить сразу. Но выборка по тикету это же дефолтовская функция, зачем так всё усложнять массивами?
Если в документации есть такой вариант выборки, значит должно быть проще по логике.
Вот как-раз для определения тикета ордера и перебирают их по порядку. Можно конечно при открытии ордера записать тикет в переменную и потом его использовать, но если открывается не один ордер то заморочек больше чем перебрать открытые ордера и выбрать необходимый.
 

hoz

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

Я попутно смотрю на функцию Кима:
PHP:
void SimpleTrailing(string sy="", int op=-1, int mn=-1) {
  double po, pp;
  int    i, k=OrdersTotal();

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if ((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op)) {
        po=MarketInfo(OrderSymbol(), MODE_POINT);
        if (mn<0 || OrderMagicNumber()==mn) {
          if (OrderType()==OP_BUY) {
            pp=MarketInfo(OrderSymbol(), MODE_BID);
            if (!TSProfitOnly || pp-OrderOpenPrice()>TStop.Buy*po) {
              if (OrderStopLoss()<pp-(TStop.Buy+TrailingStep-1)*po) {
                ModifyOrder(-1, pp-TStop.Buy*po, -1);
              }
            }
          }
          if (OrderType()==OP_SELL) {
            pp=MarketInfo(OrderSymbol(), MODE_ASK);
            if (!TSProfitOnly || OrderOpenPrice()-pp>TStop.Sell*po) {
              if (OrderStopLoss()>pp+(TStop.Sell+TrailingStep-1)*po || OrderStopLoss()==0) {
                ModifyOrder(-1, pp+TStop.Sell*po, -1);
              }
            }
          }
        }
      }
    }
  }
}

Тут у меня вопрос появился.

В данном участке кода:
PHP:
if (!TSProfitOnly || pp-OrderOpenPrice()>TStop.Buy*po)
			  { if (OrderStopLoss()<pp-(TStop.Buy+TrailingStep-1)*po)
!TSProfitOnly означает, что если режим траал только после достижения безубыточности т.е. это траал только в профитной зоне.
Но тут идёт вариант TSProfitOnly со знаком !, т.е. наоборот выходит, что эта функция не включена. А дальше условие, которое как-раз должно соблюдаться, чтоб TSProfitOnly было в TRUE.
Смысл в том, что получается, что переменная TSProfitOnly. А условие с этой переменной есть только для варианта FALSE, а для TRUE условия нет.
 
Последнее редактирование:
Верх