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

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

#6351
3 часа назад, Владимир Стариков сказал:

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

Что то типа того:

void OnTick()
  {
//---
   double MA0 = iMA(NULL,0,20,0,MODE_SMA,PRICE_CLOSE,0);
   if(Open[0] > MA0 && Bid <= MA0) Print("Время пересечения сверху вниз: ", TimeToString(TimeCurrent(),TIME_SECONDS));
   else if(Open[0] < MA0 && Bid >= MA0) Print("Время пересечения снизу вверх: ", TimeToString(TimeCurrent(),TIME_SECONDS));
   
  }

 

Суть в том, что ты узнаешь значение МА на текущем тике и уже сравниваешь его с ценой Bid, либо любой другой необходимой.

#6352

Возможно ли в OBJ_TRENDBYANGLE получить значение цены третей точки?

ObjectGet(name,OBJPROP_PRICE3)) вернет 0, и ошибка тоже 0. 

 

Хочу нарисовать линию под углом которая будет меняться при изменении маштаба графика по горизонтале и вертикале, поэтому пытаюсь получить третью координату. Возможно знаете лучший способ построить трендовую линию по заданым градусам?

#6353
2 часа назад, ademen сказал:

Возможно ли в OBJ_TRENDBYANGLE получить значение цены третей точки?

Можно через данную функцию

double new_price = ObjectGetValueByShift("Trend",20);

Смещение происходит от текущей цены, т.е. если поставить второй параметр отрицательным, то смещение будет вправо на графике.

#6354
1 час назад, Rever27 сказал:

Можно через данную функцию


double new_price = ObjectGetValueByShift("Trend",20);

Смещение происходит от текущей цены, т.е. если поставить второй параметр отрицательным, то смещение будет вправо на графике.

Спасибо, то что нужно:classic_smile:

 

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

 

1 точка линии (8 бар), показатель верный: 

image.png.32a12a159e42112064e786a37c6bb861.png

1 бар вправо (7 бар)

image.png.015144d4b78cedeea7e4c2e45e701b00.png

2 бар (конец линии):

image.png.d755a2d1845e026b988fe4123d5d34fa.png

 

Проблема именно с OBJ_TRENDBYANGLE, обычная трендовая линия дает верные показатели на любом промежутке

 

@Rever27 сталкивались с таким? В чем может быть моя ошибка?

#6355
19 часов назад, ademen сказал:

сталкивались с таким?

нет, не сталкивался, я трендовой линией не пользуюсь. Перед тем, как скинуть функцию сюда я попробовал сделать сдвиг +10/-10, все вроде работало.

#6356
1 час назад, Rever27 сказал:

Перед тем, как скинуть функцию сюда я попробовал сделать сдвиг +10/-10, все вроде работало.

Обычная трендовая линия и у меня все правильно отображает., проблема именно с линией под наклоном @Rever27 вы проверяли трендовуи или трендовую с наклоном?

#6357
3 минуты назад, ademen сказал:

вы проверяли трендовуи или трендовую с наклоном?

Я нарисовал трендовую по градусам права налево, мне выдало ноль в результатах. Я нарисовал ее слева направо, запросил результаты 10 бара как влево, так и вправо и все выдало нормально. Больше я не экспериментировал

#6358

Всем привет!!!

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

Допустим у меня индикатор показал пин бар на продажу, как мне проверить между хаем и опен свечи или между лоу и опеном на предмет круглой цены между ними?

ыва.jpg

#6359
4 часа назад, hackas сказал:

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

Ничего тут сложного нет, если хорошенько подумать.
Вот один из вариантов реализации:

Ты определяешь для каждой свечи ее круглый уровень. Для этого находишь ровно середину свечи (High+Low)/2 и это значение округляешь за сотых (для пар без JPY). В итоге у тебя на каждой свече будет уровень 1.17, 1.18, 1.19 и т.д.

 

Далее узнается, что полученное значение находится внутри свечи.
После этого берется формула пин бара в интернете, правится по себя. 

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

 

 

RoundLevel PinBar.mq410 скач.

#6360
23 часа назад, Rever27 сказал:

Ничего тут сложного нет, если хорошенько подумать.
Вот один из вариантов реализации:

Ты определяешь для каждой свечи ее круглый уровень. Для этого находишь ровно середину свечи (High+Low)/2 и это значение округляешь за сотых (для пар без JPY). В итоге у тебя на каждой свече будет уровень 1.17, 1.18, 1.19 и т.д.

 

Далее узнается, что полученное значение находится внутри свечи.
После этого берется формула пин бара в интернете, правится по себя. 

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

 

 

RoundLevel PinBar.mq4 6 \u043a\u0411 · 1 загрузка

спасибо хоть кто то помог!Все заработало) а как полтиник добавить? и как можно сделать что можно было ставить на пары с JPY или такие как золото,нефть?

#6361
14 часов назад, hackas сказал:

а как полтиник добавить?

Как вариант с костылем, как то так:
roundL = MathCeil((High[i]+Low[i])/2*200)/200;

roundL = MathCeil((High[i]+Low[i])/2*200)/200;

 

14 часов назад, hackas сказал:

и как можно сделать что можно было ставить на пары с JPY или такие как золото,нефть?

Ну логично, что нужно округлить значение до количества необходимых знаков до запятой. У 5 значных пар функция округляет до 2 знаков после запятой, значит для JPY нужно округлить до 0.

roundL = NormalizeDouble((High[i]+Low[i])/2,0);

 

#6362

в общем так сделал

 

input bool    sublevels  = true;

 

int init()

  //if(Digits==2) Dig = ?; // Gold?
  if(Digits==3) Dig = 0;
  if(Digits==4) Dig = 1;
  if(Digits==5) Dig = 2;

  return(0);
}

  double roundLl = NormalizeDouble(((high+low)/2),Dig);
  if(sublevels)
  {
    Dig = Dig+1;
    double Fifty_price = NormalizeDouble(((high+low)/2)/2,Dig);
  }

 

Изменено 29 июня, 2021 пользователем hackas

#6363

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

#6364
3 часа назад, diodio сказал:

Просто у меня стоит фишка не открывать лишние ордера если уже есть один в рынке,

проверяй не просто наличие ордера в рынке, а СКОЛЬКО по времени он уже в рынке. Если больше заданного, то проверяй сигнал.
А лучше проверять сигнал, а потом время жизни существующего ордера(точнее сначала нужно проверять то, что реже проверяется).
Присваивать новый магик- получить проблемы в будущем при сопровождении ордера.

#6365

Всем доброго времени!

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

Например в этой строчке:

 

closed=OrderClose(ticket,(здесь указываем сколько лоту закрыть?),price,Slippage,clrYellow);

 

Уже обыскался, оказывается все просто?

Тогда еще вопрос по ходу, как сделать так чтоб он закрывал каждые допустим 0,02 лоту от ордера 0,1.

Если есть у кого готовый код поделитесь пож-та.

#6366
8 часов назад, diodio сказал:

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

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

Также есть возможность закрытия встречных ордеров OrderCloseBy. Это нужно для перевертывания для экономии на спреде.

 

8 часов назад, diodio сказал:

Тогда еще вопрос по ходу, как сделать так чтоб он закрывал каждые допустим 0,02 лоту от ордера 0,1.

Так и указать во внешних настройках. Я частичное закрытие делаю по проценту от ордера, т.е. у меня есть настройка PartClose = 20%, соответственно она закрывает 20% от него. Если же нужно, чтобы всегда было 0.02 лота в процентах, то либо цифрами 0.02 в настройке, либо можно в глобальной хранить первоначальный лот этого ордера. Все зависит от ситуации.

#6367
13 часов назад, Jadavin сказал:

Коллеги, доброго дня.

Не подскажет ли кто, как можно ввинтить свой индикатор в советник? Прямо в код. Где почитать, если есть на tlap.

https://www.mql5.com/ru/users/godzilla/publications

https://www.mql5.com/ru/articles/1463

https://www.mql5.com/ru/articles/1457

https://www.mql5.com/ru/articles/1456

https://www.mql5.com/ru/articles/1411

 

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

#6368
В 05.07.2021 в 20:56, Rever27 сказал:

Так и указать во внешних настройках. Я частичное закрытие делаю по проценту от ордера, т.е. у меня есть настройка PartClose = 20%, соответственно она закрывает 20% от него. Если же нужно, чтобы всегда было 0.02 лота в процентах, то либо цифрами 0.02 в настройке, либо можно в глобальной хранить первоначальный лот этого ордера. Все зависит от ситуации.

Есть функция, при условии которой происходит закрытие, вот эта функция:

input int           PartTakeProfit   = 50;        // Тейк частичного закрытия
.......................
  
//+----------------------------------------------------------------------------+
void CloseOrderPart()
  {
   int cnt = OrdersTotal();

   for(int w=0; w<cnt; w++)
     {
      if(!(OrderSelect(w, SELECT_BY_POS, MODE_TRADES)))
         continue;
      if(OrderSymbol() != Symbol())
         continue;
      if(OrderType() == OP_BUY)
        {
         if(Bid-OrderOpenPrice() > PartTakeProfit*Point)
           {
            ClosePosition();
           }
        }
      if(OrderType() == OP_SELL)
        {
         if(OrderOpenPrice()-Ask > PartTakeProfit*Point)
           {
            ClosePosition();
           }
        }
     }
  }

Лотность выставляю 0,1 и частичное закрытие по 0,02 тогда в идеале происходить должно 5 раз, значит эту функцию я немного исправляю и вручную ставлю изменения на закрытие 5 раз, т.е. хочу чтоб закрытие происходило каждые 5 пунктов, пишу так:

input int           PartTakeProfit   = 50;        // Тейк частичного закрытия
.............................

//+----------------------------------------------------------------------------+
void CloseOrderPart()
  {
   int cnt = OrdersTotal();

   for(int w=0; w<cnt; w++)
     {
      if(!(OrderSelect(w, SELECT_BY_POS, MODE_TRADES)))
         continue;
      if(OrderSymbol() != Symbol())
         continue;
      if(OrderType() == OP_BUY)
        {
         if(
         Bid-OrderOpenPrice() > PartTakeProfit*Point 
      || Bid-OrderOpenPrice() >= (PartTakeProfit*2)*Point
      || Bid-OrderOpenPrice() >= (PartTakeProfit*3)*Point
      || Bid-OrderOpenPrice() >= (PartTakeProfit*4)*Point
      || Bid-OrderOpenPrice() >= (PartTakeProfit*5)*Point
           )
           {
            ClosePosition();
           }
        }
      if(OrderType() == OP_SELL)
        {
         if(
         OrderOpenPrice()-Ask > PartTakeProfit*Point
      || OrderOpenPrice()-Ask >= (PartTakeProfit*2)*Point
      || OrderOpenPrice()-Ask >= (PartTakeProfit*3)*Point
      || OrderOpenPrice()-Ask >= (PartTakeProfit*4)*Point
      || OrderOpenPrice()-Ask >= (PartTakeProfit*5)*Point
           )
           {
            ClosePosition();
           }
        }
     }
  }

Будет работать при таком изменении?

Изменено 9 июля, 2021 пользователем diodio

#6369
6 часов назад, diodio сказал:

Будет работать при таком изменении?

Не знаю, проверь в тестере.

Вообще, выглядит как какое то извращение. 

Как альтернатива, если тебе нужно каждый раз закрывать ордер 5 раз, то не проще ли последовательно открыть 5 ордеров с лотом 0.02 и каждому назначить свой ТП?

 

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

 

Третий вариант, это сканировать закрытые ордера и находить последний закрывшийся, брать цену его закрытия и от нее уже рассчитывать 5 пунктов.

 

В общем экспериментируй.

#6370
Цитата

 

Доброго дня, появился запрос на получения профита последней сделки. Накидал код, но получил результат не последней а первой сделки в истории. Что же не так?

 

Цитата

double FindLastOrderProfit()
 {
    int oldticket; 
    double oldorderProfit = 0; 
    int ticket = 0;
   
    for(int cnt=OrdersTotal(); cnt>=0; cnt--)
       {  
        if(OrderSelect(cnt, SELECT_BY_POS, MODE_HISTORY))
          {
           if(OrderSymbol()== Symbol() && OrderMagicNumber() == Magic)
             {                                                                 
              oldticket = OrderTicket();
              if(oldticket > ticket)
                {
                 ticket = oldticket;
                 oldorderProfit = OrderProfit(); 
                }}}}
    return(oldorderProfit);
 }

Решил: OrdersTotal() заменил на OrdersHistoryTotal()  :)

 

Изменено 15 июля, 2021 пользователем Ar4i

#6371
2 часа назад, Ar4i сказал:

Решил: OrdersTotal() заменил на OrdersHistoryTotal()

Так Вы найдете последний ордер по времени открытия. Не факт, что он будет последний по времени ЗАКРЫТИЯ.
Логичнее проверять не OIrderTicket(), а OrderCloseTime()

#6372

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


2021.08.09 21:23:25.213    2021.02.04 14:06:40  Trailing-Stop GBPUSD,H1: OrderModify error 1 - при перемещении стоп-лосса ордера на селл
2021.08.09 21:23:26.185    2021.02.04 15:00:00  Trailing-Stop GBPUSD,H1: OrderModify error 4051 - при перемещении стоп-лосса ордера на бай

Что я не так делаю? 
НА ПОКУПКУ.
for (int ii = OrdersTotal()-1; ii>=0; ii--)   //Берем все ордера
            {
            if (OrderSelect(ii, SELECT_BY_POS, MODE_TRADES))   //Берем i-ый ордер
               {
                if (OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)   //Если символ соответствует текущему, а магическое число - наше
                   {
                   if (OrderType()==OP_BUY)   //Если тип ордера - На покупку
                      {
                         if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble (L-ot*Point(),Digits()),0,0))                    
                            Print ("ОРДЕР НА ПОКУПКУ НЕ МОДИФИЦИРОВАН!");                                               
                      }   
                   }   
               }
            }

НА ПРОДАЖУ.
for (int ii = OrdersTotal()-1; ii>=0; ii--)   //Берем все ордера
            {
            if (OrderSelect(ii, SELECT_BY_POS, MODE_TRADES))   //Берем i-ый ордер
               {
                if (OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)   //Если символ соответствует текущему, а магическое число - наше
                   {
                   if (OrderType()==OP_SELL)   //Если тип ордера - На продажу
                      {
                         if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble (H+ot*Point(),Digits()),0,0))                    
                         Print ("ОРДЕР НА ПРОДАЖУ НЕ МОДИФИЦИРОВАН!");
                      }   
                   }   
               }
            }

 

#6373
4 часа назад, Vovan777 сказал:

Подскажите пожалуйста, почему при модификации ордера выскакивают две ошибки, и ордера не модифицируются. 

Ошибка №1 связана с тем, что ты пытаешься модифицировать СЛ по той же цене, что и сейчас. Терминалу нет смысла делать такую модификацию и он высылает эту ошибку. Перед модификацией нужно сравнивать текущий СЛ с новым.

Ошибка 4051 вообще может не относится к этой части кода, она у меня ни разу не всплывала при модификации ордера.

 

Прикладываю свой кусок кода для модификации и проверки. Работает уже много лет стабильно.

modif check.mq46 скач.

#6374

Всем доброго времени! 

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

void CloseOrder()
  {
   int totalord = OrdersTotal();
   int counted=0;

   for(int findfive=0; findfive < totalord; findfive++)
     {
      if(OrderSelect(findfive,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol() == Symbol() && (OrderMagicNumber() == 777 || OrderMagicNumber() == 555))
            counted++;
            
         if (counted == 1 && totalord == counted) 
     {
       if(OrderType() == OP_BUY) bool buyb = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage);
       if(OrderType() == OP_SELL) bool sells = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage);
     }   
        }
     }
  }

..... а не закрывает((

Помогите)

Изменено 13 августа, 2021 пользователем diodio

#6375
3 часа назад, diodio сказал:

а не закрывает((

во- первых посмотри журнал- может там есть ошибки
 

 

3 часа назад, diodio сказал:
 if (counted == 1 && totalord == counted)

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

Нужно убедиться, что ордер с магиками 555 или 777 и нашим символом только один?
Или нужно понять, что у нас в рынке всего один ордер?

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

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