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

AlexeyVik

Программист mql4 mql5
Я не это имел ввиду. Разница в том, что так открытые ордера не перебирают:

PHP:
 for (int i = OrdersTotal(); i >= 0; i --)
Перебирают так:

PHP:
 for (int i = OrdersTotal() - 1; i >= 0; i --)
А закрытые почему-то так не перебирают:

PHP:
for (int i = 0; i < OrdersHistoryTotal() - 1; i ++)
А перебирают так:

PHP:
for (int i = 0; i < OrdersHistoryTotal(); i ++)

Ты не там ищешь разницу...
OrdersTotal() возвращает к-во открытых и отложенных ордеров. Но нумерация начинается с нуля. Потому и получается, что 2 открытых ордера имеют индекс 0 и 1 т.е. OrdersTotal()-1
OrdersHistoryTotal() работает так-же, только возвращает к-во ордеров из вкладки "История Счёта" согласно настройкам этой вкладки. Если настроить чтобы показывались ордера только за сегодня то будет количество закрытых сегодня.
И раз уж начали об этом... Если ордер закрыт в 23:59 и не попадает в список истории счёта, то он остаётся недоступным. А юзер существо непредсказуемое, может сделать так, что и в голову тебе прийти не может (из личного опыта), поэтому при поиске ордера из истории надо такой вариант надо учитывать.
Так, вот OrdersTotal()-1 и OrdersHistoryTotal()-1 будет пограмотней, но и лишняя итерация цикла занимает времени < 1 миллисекунды. Многие это считают не критичным и не минусуют 1 из к-ва ордеров.
 

eevviill

Заблокирован
Я не это имел ввиду. Разница в том, что так открытые ордера не перебирают:

PHP:
 for (int i = OrdersTotal(); i >= 0; i --)


Перебирают так:

PHP:
 for (int i = OrdersTotal() - 1; i >= 0; i --)


А закрытые почему-то так не перебирают:

PHP:
for (int i = 0; i < OrdersHistoryTotal() - 1; i ++)


А перебирают так:

PHP:
for (int i = 0; i < OrdersHistoryTotal(); i ++)
Я понял про что ты спрашиваешь.
Всё дело в знаке =
Посмотри. Между эими вариантами нету разницы.
PHP:
for (int i = 0; i < OrdersHistoryTotal(); i ++)
PHP:
for (int i = 0; i <= OrdersHistoryTotal()-1; i ++)
 

hoz

Активный участник
Я понял про что ты спрашиваешь.
Всё дело в знаке =
Посмотри. Между эими вариантами нету разницы.
PHP:
for (int i = 0; i < OrdersHistoryTotal(); i ++)
PHP:
for (int i = 0; i <= OrdersHistoryTotal()-1; i ++)


Точно. Вот я на ровном месте споткнулся :( На таком просто моменте :oops:
 

hoz

Активный участник
И раз уж начали об этом... Если ордер закрыт в 23:59 и не попадает в список истории счёта, то он остаётся недоступным.


Как он не попадёт в список истории, если он уже закрыт? Цикл то не по времени, а по ордерам..
 

AlexeyVik

Программист mql4 mql5
Как он не попадёт в список истории, если он уже закрыт? Цикл то не по времени, а по ордерам..
Я не думал, что надо расписывать досконально...
Открой вкладку "История счёта", клик пкм (правой кнопкой мыши), в контекстном меню лкм "Выбрать период", в появившемся окне выбрать "Сегодня", лкм "ок" Посчитай сколько осталось ордеров...
Потом в какой либо код добавь Comment(OrdersHistoryTotal());
Если после этого, в таком состоянии вкладки "История Счёта" сможешь программно найти ордер который был закрыт вчера...
 

AlexeyVik

Программист mql4 mql5
Я не это имел ввиду. Разница в том, что так открытые ордера не перебирают:

PHP:
 for (int i = OrdersTotal(); i >= 0; i --)
Перебирают так:

PHP:
 for (int i = OrdersTotal() - 1; i >= 0; i --)
А закрытые почему-то так не перебирают:

PHP:
for (int i = 0; i < OrdersHistoryTotal() - 1; i ++)
А перебирают так:

PHP:
for (int i = 0; i < OrdersHistoryTotal(); i ++)
Я понял про что ты спрашиваешь.
Всё дело в знаке =
Посмотри. Между эими вариантами нету разницы.
PHP:
for (int i = 0; i < OrdersHistoryTotal(); i ++)
PHP:
for (int i = 0; i <= OrdersHistoryTotal()-1; i ++)

Василий, а где ты нашёл <= в коде hoz'a?... Я вижу только >= 0
 

hoz

Активный участник
Я не думал, что надо расписывать досконально...
Открой вкладку "История счёта", клик пкм (правой кнопкой мыши), в контекстном меню лкм "Выбрать период", в появившемся окне выбрать "Сегодня", лкм "ок" Посчитай сколько осталось ордеров...
Потом в какой либо код добавь Comment(OrdersHistoryTotal());
Если после этого, в таком состоянии вкладки "История Счёта" сможешь программно найти ордер который был закрыт вчера...


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

hoz

Активный участник
Не нашел, но догадался что так должно было быть.


По ходу нужно и закрытые ордера перебирать от последнего закрытого к первому, а не иначе.. Т.к. те которые закрыты раньше, имеют же не тот " вес ", а нам важнее последние, в принципе. Буду корректировать этот момент.
 

AlexeyVik

Программист mql4 mql5
Абсурдно как-то..
Я-бы не сказал, что это абсурдно... Прикинь сколько ордеров может набраться за 3-4 года... И сколько времени понадобится для перебора всего списка. А если есть желание то поэкспериментируй с направлением сортировки списка. Какой ордер будет иметь какой индекс.
Я это не экспериментировал, мне хватило того, что OrderSelect(0, SELECT_BY_POS, MODE_HISTORY) выбирал не тот ордер который мне был нужен. Я сразу от такого подхода отказался.
 

hoz

Активный участник
Я-бы не сказал, что это абсурдно... Прикинь сколько ордеров может набраться за 3-4 года... И сколько времени понадобится для перебора всего списка. А если есть желание то поэкспериментируй с направлением сортировки списка. Какой ордер будет иметь какой индекс.
Я это не экспериментировал, мне хватило того, что OrderSelect(0, SELECT_BY_POS, MODE_HISTORY) выбирал не тот ордер который мне был нужен. Я сразу от такого подхода отказался.


Тоже верно. Хотя 0 (нуль) как индекс это уж слишком.


Я написал код, чтоб закрывать частично, на разных уровнях ценовых позицию дробя лот. Что-то странно работает. Некоторые ордера как-будто пропускает и они висят мёртвым грузом. Что тут не так? Вроде как всё чётко.

PHP:
//+-------------------------------------------------------------------------------------+
//|TakeProfitLots                                                                       |
//+-------------------------------------------------------------------------------------+
double TakeProfitLots(double lotPrimary, int approach)
{
  double lotDealToClose;                                       // лот для закрытия на данном уровне тейк-профита
  if (approach == 1)
      lotDealToClose = lotPrimary * i_tp1Percent / 100;
        return (LotRound(lotDealToClose));
  if (approach == 2)
      lotDealToClose = lotPrimary * i_tp2Percent / 100;
        return (LotRound(lotDealToClose));
  if (approach == 3)
      lotDealToClose = lotPrimary * i_tp3Percent / 100;
        return (LotRound(lotDealToClose));
}
//+-------------------------------------------------------------------------------------+
//| Проверка объема на корректность и округление                                        |
//+-------------------------------------------------------------------------------------+
double LotRound(double L)
{
  return(MathRound(MathMin(MathMax(L, minLot), maxLot)/lotStep)*lotStep);
}
//+-------------------------------------------------------------------------------------+
//| Определяем количество закрытий ордеров                                              |
//+-------------------------------------------------------------------------------------+
int OrderCloseCount(double ordOpPrice, datetime ordOpTime)
{
  int count = 0;
  
  for (int i = OrdersHistoryTotal() - 1; i >= 0 ; i--)
  {
    if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      if (OrderSymbol() != Symbol()) continue;
          if (OrderOpenPrice() == ordOpPrice && OrderOpenTime() == ordOpTime)
              count++;
  }
  
   return (count);
}
//+-------------------------------------------------------------------------------------+
//| Определяем тейк-профиты                                                             |
//+-------------------------------------------------------------------------------------+
void TakeProfits()
{
  int type;
  double OOP;
  datetime OOT;
  int ticket;
  int counterOfCloses;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--)
  {  
    if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if (OrderSymbol() != Symbol()) continue;
          type = OrderType();
          OOP = OrderOpenPrice();
          OOT = OrderOpenTime();
          i_lot = OrderLots();
          ticket = OrderTicket();
          counterOfCloses = OrderCloseCount(OOP, OOT);
          
          RefreshRates();
          
          if (type == OP_SELL)
          {
           if (i_takeProfit1 > 0)
               if (Ask <= OOP - i_takeProfit1 * pt && counterOfCloses == 0)
                   OrderClose(ticket, TakeProfitLots(i_lot, 1), Ask, i_slippage, Black);
           if (i_takeProfit2 > 0)
               if (Ask <= OOP - i_takeProfit2 * pt && counterOfCloses == 1)
                   OrderClose(ticket, TakeProfitLots(i_lot, 2), Ask, i_slippage, Black);
           if (i_takeProfit3 > 0)
               if (Ask <= OOP - i_takeProfit3 * pt && counterOfCloses == 2)
                  OrderClose(ticket, TakeProfitLots(i_lot, 3), Ask, i_slippage, Black);
          }
          
          if (type == OP_BUY)
          {
           if (i_takeProfit1 > 0)
               if (Bid >= OOP + i_takeProfit1 * pt && counterOfCloses == 0)
                   OrderClose(ticket, TakeProfitLots(i_lot, 1), Bid, i_slippage, Black);
           if (i_takeProfit2 > 0)
               if (Bid >= OOP + i_takeProfit2 * pt && counterOfCloses == 1)
                   OrderClose(ticket, TakeProfitLots(i_lot, 2), Bid, i_slippage, Black);
           if (i_takeProfit3 > 0)
               if (Bid >= OOP + i_takeProfit3 * pt && counterOfCloses == 2)
                   OrderClose(ticket, TakeProfitLots(i_lot, 3), Bid, i_slippage, Black);
          }
  }
}
Касательно переменных объявленных на глобальном уровне, которых тут не видно вот что нужно:

PHP:
extern int i_takeProfit1 = 10;                           // Величина 1-ого тейк-профита
extern int i_takeProfit2 = 20;                           // Величина 2-го тейк-профита
extern int i_takeProfit3 = 25;                            // Величина 3-го тейк-профита
extern int i_tp1Percent = 50;                            // Процент от основного лота для закрытия 1-го тейк- профита
extern int i_tp2Percent = 30;                            // Процент от основного лота для закрытия 2-го тейк-профита
extern int i_tp3Percent = 20;                             // Процент от основного лота для закрытия 3-го тейк-профита
extern int i_slippage = 2;
extern double i_lot = 0.1;
#define SIGNAL_BUY                        0                          // Сигнал на покупку
#define SIGNAL_SELL                       1                          // Сигнал на продажу
#define SIGNAL_NO                        -1                          // Сигнала нет
Это в init:

PHP:
minLot = MarketInfo(Symbol(), MODE_MINLOT);
    maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
    lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
 
Последнее редактирование модератором:

AlexeyVik

Программист mql4 mql5
Ну ты первый закрытый хотел узнать? Смысла не вижу.
Я же тебе предложил поэкспериментировать. Возьми хоть 0 хоть OrdersHistoryTotal()-1 всё равно не всегда получишь нужный результат.
Только не спеши с выводами. Даже если получишь 9 правильных из 10ти это уже не приемлемо. В какой момент будет ошибка я знаю. Теперь узнай ты.
 

hoz

Активный участник
Ну попутно поэкспериментирую. Сейчас ломаю голову над тем кодом, что выше привёл. Абы что происходит вообще.
 

hoz

Активный участник
В общем-то, вопрос с дроблением лота снимаю. Я, всё-таки осилил это дело.

Появился вопрос.

Вот функция для открытия шортовых ордеров. На вид не обращайте внимания, ф-ция написано для отладки..

PHP:
//+-------------------------------------------------------------------------------------+
//| Открытие короткой позиции                                                           |
//+-------------------------------------------------------------------------------------+
bool OpenSell()
{
  int ticket = -1;
  string myNote = "Сов шортанул";
  //int SL = OrderOpenPrice() + i_sl * pt;
  
  while (IsTradeAllowed() == false) Sleep(1000);
  RefreshRates();
  ticket = OrderSend(Symbol(),OP_SELL,i_lot,Bid,3,0,0,myNote,i_myMagic,0,Red);
  if (ticket > 0 && OrderSelect(ticket,SELECT_BY_TICKET) == true)
  {
    IsBuyNow = 0;
    if (i_sl > 0 && OrderStopLoss() == 0)
    {
      if (!OrderModify(ticket,OrderOpenPrice(),NormalizeDouble(OrderOpenPrice() + i_sl * pt,Digits),0,0))
       {
        Print ("Ошибка установки первичного стопа для шортов ", OrderType(), " - ", GetLastError());
        Print("Ask = ", Ask);
        Print("Bid = ", Bid);
        Print("OrderOpenPrice() + i_sl * pt = ", OrderOpenPrice() + i_sl * pt);
       }
    }
  }
  return(true);
}


Хочется сделать код красивее. В функцию модификации ордера вместо:

PHP:
NormalizeDouble(OrderOpenPrice() + i_sl * pt,Digits)

Чтоб было тока переменная типа:

PHP:
NormalizeDouble(SL,Digits)

Ну а SL где-то выше присвоить значение OrderOpenPrice() + i_sl * pt

Если это сделать вверху, то там значения цены открытия ордера ещё нет, и на выходе будет ерунда. Как тогда поступить?
 

alexshell

Элитный участник
В общем-то, вопрос с дроблением лота снимаю. Я, всё-таки осилил это дело.

Появился вопрос.

Вот функция для открытия шортовых ордеров. На вид не обращайте внимания, ф-ция написано для отладки..




Хочется сделать код красивее. В функцию модификации ордера вместо:

PHP:
NormalizeDouble(OrderOpenPrice() + i_sl * pt,Digits)

Чтоб было тока переменная типа:

PHP:
NormalizeDouble(SL,Digits)

Ну а SL где-то выше присвоить значение OrderOpenPrice() + i_sl * pt

Если это сделать вверху, то там значения цены открытия ордера ещё нет, и на выходе будет ерунда. Как тогда поступить?

Вот так:
PHP:
  if (i_sl > 0 && OrderStopLoss() == 0)
    {double SL=OrderOpenPrice() + i_sl * pt;
      if (!OrderModify(ticket,OrderOpenPrice(),NormalizeDouble(SL,Digits),0,0))
       {
        Print ("Ошибка установки первичного стопа для шортов ", OrderType(), " - ", GetLastError());
        Print("Ask = ", Ask);
        Print("Bid = ", Bid);
        Print("OrderOpenPrice() + i_sl * pt = ", OrderOpenPrice() + i_sl * pt);
       }
    }
 
  • Like
Реакции: hoz

AlexeyVik

Программист mql4 mql5
Или вынеси NormalizeDouble во внешнюю функцию
double ND(double X) {return(NormalizeDouble(X, Digits));}
Тогда это будет выглядеть так
ND(OrderOpenPrice() + i_sl * pt)

А если объединишь 2 совета вместе то получится ND(SL)
 

Allis Amazing

Интересующийся
Приветствую всех! Подскажите, ежели кто знает, как может называться функция модификации открытых ордеров, и главное как её отобрать у Совы, что бы не нарушить весь дальнейший ход событий?)
 

AlexeyVik

Программист mql4 mql5
Приветствую всех! Подскажите, ежели кто знает, как может называться функция модификации открытых ордеров, и главное как её отобрать у Совы, что бы не нарушить весь дальнейший ход событий?)

Ты может быть не представляешь сколько вариантов понимания слова "отобрать"?
Если по нашему... "лишить чего-либо, то-есть, отнять у вас и приумножить у нас"... то просто надо найти все строки содержащие OrderModify и их удалить или закомментировать...
 
Верх