Полезные функции от KimIV - страница 12

 

Функция IndexByTicket().

Возвращает индекс (порядковый номер в общем списке установленных ордеров или открытых позиций) ордера или позиции по тикету. Если функция IndexByTicket() не сможет найти ордер или позицию с нужным тикетом, то она вернёт -1. Ограничить перечень проверяемых ордеров или позиций можно параметрами функции:

  • sy - Наименование инструмента. Если задать этот параметр, то функция проверит ордера и позиции только заданного инструмента. NULL означает текущий инструмент, а "" (по умолчанию) - любой инструмент.
  • op - Торговая операция, тип отложенного ордера или позиции. Допустимые значения: OP_BUY, OP_BUYLIMIT, OP_BUYSTOP, OP_SELL, OP_SELLLIMIT, OP_SELLSTOP или -1. Значение по умолчанию -1 - означает любой ордер или позицию.
  • mn - Идентификатор ордера или позиции (MagicNumber). Значение по умолчанию -1 - любой магик.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 20.04.2007                                                     |
//|  Описание : Возвращает индекс ордера или позиции по тикету                 |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    ti - тикет ордера, позиции                                              |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любая позиция)                  |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//+----------------------------------------------------------------------------+
int IndexByTicket(int ti, string sy="", int op=-1, int mn=-1) {
  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)) {
        if ((mn<0 || OrderMagicNumber()==mn) && OrderTicket()==ti) return(i);
      }
    }
  }
  return(-1);
}
 

Функцию IndexByTicket() я писал в заказном советнике. Помню, что без неё никак не обойтись было, а иначе зачем бы я стал её писать? Но вот как она там использовалась, и зачем я её писал в принципе, убей не помню :-) Искать исходник советника влом. Их сотни.

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


Короткое объявление.

Функции SelectByTicket() и SelectByTicketFromHistory() я упразднил. Сам я их использовать больше не буду, поэтому не вижу смысла опубликовывать. Желающим подискутировать на эту тему всегда рад. Покажу все свои заблуждения AS IS.

 

Функция NumberOfOrders().

Эта функция возвращает количество ордеров и функционально полностью перекрывает ExistOrders(). Для того, чтобы заменить функцию ExistOrders() функцией NumberOfOrders(), необходимо и достаточно проверять возвращаемое значение на то, чтобы оно было больше нуля. Ограничить перечень проверяемых ордеров можно параметрами функции:

  • sy - Наименование инструмента. Если задать этот параметр, то функция проверит ордера только заданного инструмента. NULL означает текущий инструмент, а "" (по умолчанию) - любой инструмент.
  • op - Тип отложенного ордера. Допустимые значения: OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT, OP_SELLSTOP или -1. Значение по умолчанию -1 - означает любой ордер.
  • mn - Идентификатор ордера (MagicNumber). Значение по умолчанию -1 - любой магик.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 28.11.2006                                                     |
//|  Описание : Возвращает количество ордеров.                                 |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любой ордер)                    |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//+----------------------------------------------------------------------------+
int NumberOfOrders(string sy="", int op=-1, int mn=-1) {
  int i, k=OrdersTotal(), ko=0, ot;

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      ot=OrderType();
      if (ot>1 && ot<6) {
        if ((OrderSymbol()==sy || sy=="") && (op<0 || ot==op)) {
          if (mn<0 || OrderMagicNumber()==mn) ko++;
        }
      }
    }
  }
  return(ko);
}
 

Примеры использования функции NumberOfOrders().

  1. Получить общее количество всех ордеров
    NumberOfOrders();
  2. Получить количество ордеров, выставленных по текущему инструменту
    NumberOfOrders(NULL);
  3. Получить количество ордеров BuyLimit по любому инструменту
    NumberOfOrders("", OP_BUYLIMIT);
  4. Получить количество ордеров SellStop с магиком 123456 по EURUSD
    NumberOfOrders("EURUSD", OP_SELLSTOP, 123456);
  5. Получить количество ордеров с магиком 2345 по текущему инструменту
    NumberOfOrders(NULL, -1, 2345);

В аттаче опять-таки рабочий скрипт с вышеуказанными примерами.

Файлы:
 
KimIV:

Функция NumberOfOrders().

Эта функция возвращает количество ордеров и функционально полностью перекрывает ExistOrders(). Для того, чтобы заменить функцию ExistOrders() функцией NumberOfOrders(), необходимо и достаточно проверять возвращаемое значение на то, чтобы оно было больше нуля. Ограничить перечень проверяемых ордеров можно параметрами функции:

  • sy - Наименование инструмента. Если задать этот параметр, то функция проверит ордера только заданного инструмента. NULL означает текущий инструмент, а "" (по умолчанию) - любой инструмент.
  • op - Тип отложенного ордера. Допустимые значения: OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT, OP_SELLSTOP или -1. Значение по умолчанию -1 - означает любой ордер.
  • mn - Идентификатор ордера (MagicNumber). Значение по умолчанию -1 - любой магик. еСО

Запутался я немного. Почему-то, мне видится некоторое противоречие. Вот здесь:

"...необходимо и достаточно проверять возвращаемое значение на то, чтобы оно было больше нуля."

Если проверять "это и только это", то функция на количество ордеров теряет смысл!

Я вот почему стал вникать. Вставил эту фукнцию в свой эксперт. Задал в параметрах m=1, и условие на открытие позиций -

if (NumberOfOrders("", -1, MagicNumber)<m) {//если открытых позиций МЕНЬШЕ m

Но эксперт, словно, не видит этого ограничения! И открывает ордера по каждому сигналу ещё и ещё...

В чём тут может быть дело?

 
rid писал (а):
Запутался я немного. Почему-то, мне видится некоторое противоречие. Вот здесь:
"...необходимо и достаточно проверять возвращаемое значение на то, чтобы оно было больше нуля."
Если проверять "это и только это", то функция на количество ордеров теряет смысл!

хм... Похоже, что Вы не обратили внимание на объём возвращаемой информации каждой из функций ExistOrders() и NumberOfOrders(). Функция ExistOrders() возвращает лишь информацию о существовании ордеров, а функция NumberOfOrders() возвращает информацию о количестве ордеров. Информация о количестве ордеров содержит в себе информацию о существовании ордеров. Когда нужно ответить на вопрос, есть ордер или нет, то информация о их количестве является избыточной. Поэтому я и говорил, что для замены функции ExistOrders() функцией NumberOfOrders() необходимо и достаточно проверять значение, возвращаемое функцией NumberOfOrders() на то, чтобы оно было больше нуля. Ведь понятно, что если это значение равно нулю, то ордеров нет, а если оно больше нуля, то ордера есть. Функцию ExistOrders() можно применять тогда, когда не нужна информация о количестве ордеров, а функцию NumberOfOrders() можно применять тогда, когда информация о количестве ордеров НЕ нужна и тогда, когда она нужна. В этом смысле функция NumberOfOrders() полностью заменяет функцию ExistOrders().

rid:

Я вот почему стал вникать. Вставил эту фукнцию в свой эксперт. Задал в параметрах m=1, и условие на открытие позиций -

if (NumberOfOrders("", -1, MagicNumber)<m) {//если открытых позиций МЕНЬШЕ m

Но эксперт, словно, не видит этого ограничения! И открывает ордера по каждому сигналу ещё и ещё...

В чём тут может быть дело?

Так... а здесь Вы, похоже путаете позиции с ордерами. Для меня это разные вещи. Что такое позиции? Это торговые операции OP_BUY и OP_SELL, а ордера в моём понимании - это торговые операции OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT и OP_SELLSTOP. Позиции я открываю, а ордера я устанавливаю. А Вы что открывали? Функция NumberOfOrders() предназначена для работы с ордерами.
 

Благодарю. Всё понял . И по первому вопросу, и по второму.

Иначе говоря "расширенная" функция NumberOfOrders() по сути, уже включает в себя функцию IndexByTicket()

Да, действительно. Я открывал OP_BUY и OP_SELL !

Осталось привести пример следующей вашей функции, кот. работает именно с позициями. (не с ордерами)

Помнится, где-то на форуме Вы уже её выкладывали. Не могу найти что-то.

 
rid писал (а):
Осталось привести пример следующей вашей функции, кот. работает именно с позициями. (не с ордерами)

С функциями для ордеров я закончил. Дальше будут функции для позиций. Около 30 шт.


rid писал (а):
Помнится где-то на форуме Вы уже её выкладывали. Не могу найти что-то.

поиск

 

Уважаемый Игорь, прошу у вас помощи! Мне необходимо дописать советника так, что бы он мог брать позиции по нескольким инструментам. Работают 2 советника, стандартный MACD и Ema, каждый по 6 позициям, но поза только одна открывается... Я читал ваши комментарии относительно этого, но т.к. я плохо разбираюсь в языке, не могу понять куда что дописывать... Если вам не трудно, то помогите... скопировал советника Ema... Спасибо!



//+------------------------------------------------------------------+
//| Parabolic.mq4 |
//| Виталик |
//| wwwita@mail.ru |
//+------------------------------------------------------------------+
extern double Lots=0.1;
extern double Pip=5;
extern double MoveBack=3;
extern int chk=0;
extern double SL=20;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
double hi=High[1];
double lo=Low[1];
double EMA, EMA1, EMA2, EMA3;
int cnt=0, ticket, total;
EMA=iMA(0,0,5,0,MODE_EMA,PRICE_MEDIAN,1);
EMA1=iMA(0,0,10,0,MODE_EMA,PRICE_MEDIAN,1);
EMA2=iMA(0,0,5,0,MODE_EMA,PRICE_MEDIAN,0);
EMA3=iMA(0,0,10,0,MODE_EMA,PRICE_MEDIAN,0);
total=OrdersTotal();
if(total<1)
{
if(AccountFreeMargin()<(1000*Lots))
{
Print("У вас нет денег. Свободные средства = ", AccountFreeMargin());
return(0);
}
if(((EMA>EMA1) && (EMA2<EMA3)) || ((EMA<EMA1) && (EMA2>EMA3)))
{
chk=1;
Print("Позиция возможна!");
}
if(chk==1)
{
if(EMA3-EMA2>2*Point && Bid>=(lo+MoveBack*Point))
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,0,
"EMA position:",16385,0,Red);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("Открыт ордер SELL : ",OrderOpenPrice());
chk=0;
}
else
{
Print("Ошибка открытия SELL ордера : ",GetLastError());
return(0);
}
}
if(EMA2-EMA3>2*Point && Ask<=(hi-MoveBack*Point))
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,0,
"EMA position:",16385,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("Открыт ордер BUY : ",OrderOpenPrice());
chk=0;
}
else
{
Print("Ошибка открытия BUY ордера : ",GetLastError());
return(0);
}
}
}
return(0);
}
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL && // это открытая позиция? OP_BUY или OP_SELL
OrderSymbol()==Symbol()) // инструмент совпадает?
{
if(OrderType()==OP_BUY) // открыта длинная позиция
{
// проверим, может уже пора закрываться?
if(Bid>=(OrderOpenPrice()+Pip*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // закрываем позицию
return(0); // выходим
}
if(Bid<=(OrderOpenPrice()-SL*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // закрываем позицию
return(0); // выходим
}
}
else // иначе это короткая позиция
{
// проверим, может уже пора закрываться?
if(Ask<=(OrderOpenPrice()-Pip*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // закрываем позицию
return(0); // выходим
}
if(Ask>=(OrderOpenPrice()+SL*Point))
{
chk=0;
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // закрываем позицию
return(0); // выходим
}
}
}
}
return(0);
}
//+------------------------------------------------------------------+
 

Игорь, я в 'Библиотека функций для работы с INI-файлами.' задавал Вам вопрос, но ответа так и не поступило :(

Причина обращения: