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

MrGreen86

Гуру форума
Наверное на пенсию пора. Заострил внимание на ситуацию работать ночью, а работу днём не проверил.
это окончательный вариант.

я вам настоятельно рекомендую отказать от конструкций типа:
StringToTime(StringConcatenate(startHour, ":", startMinute));
Она дает ошибку при переходе через сутки, при это ошибка плавающая.
А именно в начале следующих суток такая конструкция вам даст время вчерашнего дня. Вот есть использовать полноценную конструкцию:
StringToTime(StringConcatenate(TimeToString(TimeCurrent(),TIME_DATE)," ",startHour, ":", startMinute));
то проблем не будет, так как TimeCurrent это TimeCurrent )))

при этом второй вариант все так же работает в mql5 ;)
 

AlexeyVik

Программист mql4 mql5
я вам настоятельно рекомендую
;)
Не сочтите за грубость, но я достаточно стар, чтобы уже отказаться следовать рекомендациям. Тем-более таким неубедительным и без аргументов. Если вам однажды пришлось нарваться на какую-то ошибку, то это не означает что она будет периодически.
Однажды я получил немалую головную боль с SERIES_LASTBAR_DATE и теперь этим не пользуюсь. Но разговаривая с друзьями меня никто не поддержал, говорят что у них никаких проблем небыло ни разу. Возможно эти проблемы уже пофиксили при очередном обновлении. :D
 

vladradon

Программист
Однажды я получил немалую головную боль с SERIES_LASTBAR_DATE и теперь этим не пользуюсь. Но разговаривая с друзьями меня никто не поддержал, говорят что у них никаких проблем небыло ни разу. Возможно эти проблемы уже пофиксили при очередном обновлении.
Привет! А мне пришлось извращаться (и то не сразу понял, в чем проблем) над простым переводом режима работы в виртуальный (ТП и СЛ), т.к Ask и Bid часто больше положенного количества знаков после запятой выдают - преобразовывать все в int, иначе даже при совпадении значений ТП или СЛ с стопуровнем, перевод не срабатывал, т.к. где-то висели дальние циферки после 5-ти знака.:disappointed:
PHP:
TpBuy=NormalizeDouble(TP,_Digits); SlBuy=NormalizeDouble(SL,_Digits);
 if((int)MarketInfo(_Symbol,MODE_STOPLEVEL)>0)
   {
    VirtualOnly=false;
    for(cnt=0; cnt<OrdersTotal(); cnt++)
      {
       if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==_Symbol)
          if((TpBuy>_Point && (int)(MathAbs(OrderOpenPrice()-TpBuy)/_Point)<=(int)MarketInfo(_Symbol, MODE_STOPLEVEL)) ||
             (SlBuy>_Point && (int)(MathAbs(OrderOpenPrice()-SlBuy)/_Point)<=(int)MarketInfo(_Symbol, MODE_STOPLEVEL)) ||
             (TpBuy>_Point && (int)(MathAbs(Bid-TpBuy)/_Point)<=(int)MarketInfo(_Symbol, MODE_STOPLEVEL)) ||
             (SlBuy>_Point && (int)(MathAbs(Bid-SlBuy)/_Point)<=(int)MarketInfo(_Symbol, MODE_STOPLEVEL)))
            {
             VirtualOnly=true;
             for(int cnt1=0; cnt1<OrdersTotal(); cnt1++)
                if(OrderSelect(cnt1,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==_Symbol && ((!UseCustom && OrderMagicNumber()==MagicNumber) || UseCustom))
                   if(OrderTakeProfit()>_Point || OrderStopLoss()>_Point) t=OrderModify(OrderTicket(),OrderOpenPrice(),0.0,0.0,0,clrPink);
            }
      }
   }
И проверять расчетные ТП и СЛ, чтоб они были больше пойнта.
 

AlexeyVik

Программист mql4 mql5
Привет! А мне пришлось извращаться (и то не сразу понял, в чем проблем) над простым переводом режима работы в виртуальный (ТП и СЛ), т.к Ask и Bid часто больше положенного количества знаков после запятой выдают - преобразовывать все в int, иначе даже при совпадении значений ТП или СЛ с стопуровнем, перевод не срабатывал, т.к. где-то висели дальние циферки после 5-ти знака.:disappointed:
PHP:
TpBuy=NormalizeDouble(TP,_Digits); SlBuy=NormalizeDouble(SL,_Digits); if((int)MarketInfo(_Symbol,MODE_STOPLEVEL)>0)   {    VirtualOnly=false;    for(cnt=0; cnt<OrdersTotal(); cnt++)      {       if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==_Symbol)          if((TpBuy>_Point && (int)(MathAbs(OrderOpenPrice()-TpBuy)/_Point)<=(int)MarketInfo(_Symbol, MODE_STOPLEVEL)) ||             (SlBuy>_Point && (int)(MathAbs(OrderOpenPrice()-SlBuy)/_Point)<=(int)MarketInfo(_Symbol, MODE_STOPLEVEL)) ||             (TpBuy>_Point && (int)(MathAbs(Bid-TpBuy)/_Point)<=(int)MarketInfo(_Symbol, MODE_STOPLEVEL)) ||             (SlBuy>_Point && (int)(MathAbs(Bid-SlBuy)/_Point)<=(int)MarketInfo(_Symbol, MODE_STOPLEVEL)))            {             VirtualOnly=true;             for(int cnt1=0; cnt1<OrdersTotal(); cnt1++)                if(OrderSelect(cnt1,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==_Symbol && ((!UseCustom && OrderMagicNumber()==MagicNumber) || UseCustom))                   if(OrderTakeProfit()>_Point || OrderStopLoss()>_Point) t=OrderModify(OrderTicket(),OrderOpenPrice(),0.0,0.0,0,clrPink);            }      }   }
И проверять расчетные ТП и СЛ, чтоб они были больше пойнта.
В принципе NormalizeDouble работает примерно так-же. Но надо учитывать особенность двоичного представления числа. Не каждое число может быть чётко представлено в двоичном счислении. Отсюда и появляются "хвосты", на которые МТ нормально реагирует игнорируя их. Проблема может возникнуть не от цены Ask или Bid, а от сложения двух таких чисел "с хвостами". Это и может дать неправильный результат сложения. Поэтому и надо нормализовать цены, а вовсе не потому, что Ask или Bid получены "с хвостами".
 

vladradon

Программист
Поэтому и надо нормализовать цены, а вовсе не потому, что Ask или Bid получены "с хвостами".
Если я в режиме реального времени в терминале вижу результаты обработки ордеров, где цены открытия/закрытия содержат по 8 знаков после запятой и это показывает сам МТ, то лучше уж конечное значение после всех расчетов перевести в int для анализа и забыть об этом навсегда.;):D
А в приведенном мной примере (я специально показал нормализацию рассчитанных ТП и СЛ) только 3 других значения (Bid, OrderOpenPrice() и MarketInfo(_Symbol, MODE_STOPLEVEL)) могут как-то сбить алгоритм и он сбивался. Что конкретно сбивало я не выяснял, но вылечил таким способом.
Хотя, если в Comment(NormalizeDouble(Bid,_Digits)) выводишь что-то типа приведенное к определенному числу знаков после запятой, то в визуальном тестировании постоянно выскакивают значения с бОльшим количеством знаков - поэтому и преобразую в стринг DoubleToStr(Bid,_Digits), чтобы глюков не было.
 
Последнее редактирование:

AlexeyVik

Программист mql4 mql5
Если я в режиме реального времени в терминале вижу результаты обработки ордеров, где цены открытия/закрытия содержат по 8 знаков после запятой и это показывает сам МТ, то лучше уж конечное значение после всех расчетов перевести в int для анализа и забыть об этом навсегда.;):D
А в приведенном мной примере (я специально показал нормализацию расчитанных ТП и СЛ) только 3 других значения (Bid, OrderOpenPrice() и MarketInfo(_Symbol, MODE_STOPLEVEL)) могут как-то сбить алгоритм и он сбивался. Что конкретно сбивало я не выяснял, но вылечил таким способом.
Вообще-то проверять вещественные числа на равенство напрямую не рекомендуется именно из-за этих "хвостов". Везде пишут, что правильно проводить проверку нормализованной разницы двух чисел с нулём.
Код:
// Примерно так.
if(NormalizeDouble(Ask-SL_Price, _Digits) >= Step*_Point)
Что из чего вычитать определяется текущей ситуацией.
 

vladradon

Программист
Вообще-то проверять вещественные числа на равенство напрямую не рекомендуется именно из-за этих "хвостов". Везде пишут, что правильно проводить проверку нормализованной разницы двух чисел с нулём.
Код:
// Примерно так.
if(NormalizeDouble(Ask-SL_Price, _Digits) >= Step*Point)
Что из чего вычитать определяется текущей ситуацией.
Я там дополнил в своем предыдущем сообщении об нормализации.
 

AlexeyVik

Программист mql4 mql5
Я там дополнил в своем предыдущем сообщении об нормализации.
Так вот как раз нормализованное вещественное число и не получается представить с абсолютной точностью в двоичной системе счисления. А чтобы визуально это не мешало как раз и пользуются переводом в стринги.
 

vladradon

Программист
Так вот как раз нормализованное вещественное число и не получается представить с абсолютной точностью в двоичной системе счисления. А чтобы визуально это не мешало как раз и пользуются переводом в стринги.
"Перевод в стринги" звучит как оплата по безналу стриптизерше...:D
В любом случае получается, что рассчитывать на нормализацию не приходится и надо как-то выходить из ситуации и здесь я знаю только 2 варианта - преобразовывать в int или string (и потом из string обратно с уже обрезанными значениями).
 
Последнее редактирование:

AlexeyVik

Программист mql4 mql5
"Перевод в стринги" звучит как оплата по безналу стриптизерше...:D
В любом случае получается, что рассчитывать на нормализацию не приходится и надо как-то выходить из ситуации и здесь я знаю только 2 варианта - преобразовывать в int или string (и потом из string обратно с уже обрезанными значениями).
Ну если так тебе кажется надёжней, пусть будет так. Главное чтобы работало.
 

Flank

Новичок форума
Получается, что коммент выводится всегда и не зависит от полученной последней цены открытия и от количества ордеров. А вот если преобразования в строку и сам коммент перенести в конец первого куска кода после всех расчетов, а еще перед этим куском поставить удаление коммента Comment(""); if(oBuy+oSell+sBuy+sSell == 1)... - должно получиться.
Ну, или сделать проверку и заключить преобразование и коммент в кривые скобки:
PHP:
Comment("");
if(FirstOrderOpPR>0.0)
  {
   buyLevel=DoubleToString(FirstOrderOpPR+Delta*_Point,_Digits);
   sellLevel=DoubleToString(FirstOrderOpPR-Delta*_Point,_Digits);
   Comment("Покупаем по: ",buyLevel,"\n", "Продаем по: ",sellLevel,"\n");
  }
А если там продолжение коммента идет, то так:
PHP:
string OpOr="";
if(FirstOrderOpPR>0.0)
  {
   buyLevel=DoubleToString(FirstOrderOpPR+Delta*_Point,_Digits);
   sellLevel=DoubleToString(FirstOrderOpPR-Delta*_Point,_Digits);
   OpOr="Покупаем по: "+buyLevel+"\n"+ "Продаем по: "+sellLevel+"\n";
  }
Comment(OpOr,'Остальной коммент');// Располагаем в конце кода

Спасибо. Сейчас попробуем....
 

st2050

Гуру форума
Код:
Здравствуйте, коллеги.

Покажите пожалуйста как программно (или еще как) поменять название окна графика. Из-за дополнительного текста "offline" табы не вмещаются в монитор.

Пробовал так, но безрезультатно. В интернетах тоже путного не нашел.

Код:
#import "user32.dll"
int      SetWindowTextA(int hWnd,string lpString);

...

int handle=WindowHandle(Symbol(),Period());
SetWindowTextA(handle,"Test");
 

st2050

Гуру форума
В общем пока так

Код:
#import "user32.dll"
int GetTopWindow(int hWnd);
#import
...
void RenameTabs()
{
   long currChart_ID=ChartFirst();
   int hChartParent;
   int _period;
   string _symbol;
   for(int i=0;i<100;i++)
     {
      _period=ChartPeriod(currChart_ID);
      _symbol=ChartSymbol(currChart_ID);
      hChartParent = GetParent(WindowHandle(_symbol,_period));
      StringToLower(_symbol);
      SetWindowTextW(hChartParent,_symbol+" "+getTfAsString(_period));
      currChart_ID=ChartNext(currChart_ID);
      if(currChart_ID==-1) break;
     }
}


Сделал индюшок, переключающий табы на нажатия клавиш A и S, стрелок влево-вправо. Если переключаться клавишами, то переименование работает хорошо, но вот при клике на таб... При наступлении события CHARTEVENT_CHART_CHANGE не переименовывает текущее и ранее открытое окно. Что-то переписывает названия окон после этого.

Понятия не имею как это побороть. Но уже хорошо что листать можно и большинство табов даже в этом случае переименованы. Хотя бы влезает теперь.
 

Вложения

  • ChartSwitcher st2050 v1.mq4
    7,1 КБ · Просмотры: 16

Walt6730

Новичок форума
Вопрос к гуру программирования. Сделал небольшой советник. Поставил на демку Альпари. Поначалу все нормально: открывал и закрывал ордера, как положено. А потом - кранты! Оредра не открывает, а вместо этого матюгается вот такими словами:

OrderSend() error - invalid trade parameters

Что поменялось и где, что он перестал открывать ордера?
 

Walt6730

Новичок форума
Так сложно сказать, какие из параметров перестали работать в функции OrderSend(). Нужно видеть хотя бы строки с ними.

Намек понял ) Вот код:

void BuyPendingOrder43()
{
double price = NormalizeDouble(Close[1] + PriceOffset1*PipValue*Point, NDigits);
double SL = NormalizeDouble(price - StopLoss1*PipValue*Point, NDigits);
if (StopLoss1 == 0) SL = 0;
double TP = NormalizeDouble(price + Takeprofit1*PipValue*Point, NDigits);
if (Takeprofit1 == 0) TP = 0;
int ticket = OrderSend(Symbol(), OP_BUYSTOP, Lots1, price, 4, SL, TP, "My Expert", 1, Blue);
if (ticket == -1)
{
Print("OrderSend() error - ", ErrorDescription(GetLastError()));
}

}
 

vladradon

Программист
Намек понял ) Вот код:
Я так и думал, что отложки. Сразу вариант: если цена ушла выше цены закрытия 1-го бара + заданное смещение, то отложка BUY_STOP не выставится - цена уже проскочила этот уровень. Может цена выставления попадает в расширенный спред. Нужно доп проверки вводить цены выставления ордеров на положение к текущей цене и, желательно, на непопадание в стопуровень относительно текущей цены и других ордеров на графике (в Альпари стопуровень обычно 0, но у многих брокеров он довольно большой и переваливает за 60 пипсов).
 

vladradon

Программист
Набросал по-быстрому. Надеюсь, без ошибок:
PHP:
void BuyPendingOrder43()
  {
   int ticket=0;
   int stoplevel=(int)MarketInfo(_Symbol,MODE_STOPLEVEL);
   double price = NormalizeDouble(Close[1]+PriceOffset1*PipValue*_Point,NDigits);
   double SL=NormalizeDouble(price-StopLoss1*PipValue*_Point,NDigits);
   if(StopLoss1==0) SL=0.0;
   double TP=NormalizeDouble(price+Takeprofit1*PipValue*_Point,NDigits);
   if(Takeprofit1==0) TP=0.0;
   if(stoplevel>0)
     {
      if(SL>0.0 && ((int)(MathAbs(SL-Ask)/_Point)<=stoplevel || (int)(MathAbs(SL-Bid)/_Point)<=stoplevel)) {Print("Error StopLoss"); return;}
      if(TP>0.0 && ((int)(MathAbs(TP-Ask)/_Point)<=stoplevel || (int)(MathAbs(TP-Bid)/_Point)<=stoplevel)) {Print("Error TakeProfit"); return;}
      for(int cnt=0; cnt<OrdersTotal(); cnt++)
         if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES) && OrderSymbol()==_Symbol)
            if((price>0.0 && (int)(MathAbs(OrderOpenPrice()-price)/_Point)<=stoplevel) ||
               (TP>0.0  && ((int)(MathAbs(OrderOpenPrice()-TP)/_Point)<=stoplevel || 
               (int)(MathAbs(Bid-TP)/_Point)<=stoplevel ||
               (int)(MathAbs(Ask-TP)/_Point)<=stoplevel)) ||
               (SL>0.0 && ((int)(MathAbs(OrderOpenPrice()-SL)/_Point)<=stoplevel || 
               (int)(MathAbs(Bid-SL)/_Point)<=stoplevel || 
               (int)(MathAbs(Ask-SL)/_Point)<=stoplevel))) {Print("Error cross other orders"); return;}
      }
   if(price>Ask+stoplevel*_Point) ticket=OrderSend(Symbol(),OP_BUYSTOP,Lots1,price,4,SL,TP,"My Expert",1,Blue);
   if(ticket==-1) Print("OrderSend() error - ",ErrorDescription(GetLastError()));
 }
 
Последнее редактирование:
Верх