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

 
А как вы отнесётесь к такому варианту:
if (err==146)
{
while (IsTradeContextBusy())
{
if (IsTradeAllowed()) break;
else
Sleep(1000*1,1);
}}
Мне кажется это более быстрое решение.Я работаю так . Прокоментируйте.
Спасибо.
 
Red.Line писал (а): Спасибо за полезную тему, хотя я и о горелых пирогах, но все же может кто-то сталкивался с проблемой складирования и выборок из больших массивов данных в мкл. Мкл и базы данных? Никто в этом направлении не думал?
Конечно простое решение, но кое что.. https://forum.mql4.com/ru/9377
 
zhuki:
А как вы отнесётесь к такому варианту:
if (err==146)
{
  while (IsTradeContextBusy())
  {
    if (IsTradeAllowed()) break;
    else 
    Sleep(1000*1,1);
  }
}
Мне кажется это более быстрое решение.Я работаю так . Прокоментируйте.
Спасибо.

Нормально отнесусь. С пониманием. Пауза меньше, работает быстрее... Но есть в Вашем варианте неоправданная избыточность.

Функция IsTradeContextBusy возвращает флаг занятости торгового потока. До 195-го билда этой функции вообще не было. И мы пользовались функцией IsTradeAllowed, которая возвращает признак того, что эксперту разрешено торговать и торговый поток свободен.

Разрешение торговать эксперту даётся установкой галочки "Разрешить советнику торговать" в диалоговом окне настройки свойств советника (клавиша F7).

К ошибке 146 (Торговый поток занят) разрешение советнику торговать не имеет отношения. Поэтому рассмотрим свойства функции IsTradeAllowed в части, относящейся только к торговому потоку.

Итак, торговый поток свободен, функция IsTradeAllowed возвращает True. Торговый поток занят, функция IsTradeAllowed возвращает False. Теперь рассмотрим значения, возвращаемые функцией IsTradeContextBusy. Торговый поток свободен, функция IsTradeContextBusy возвращает False. Торговый поток занят, функция IsTradeContextBusy возвращает True. Мы видим, что для одних и тех же состояний торгового потока значения функций IsTradeAllowed и IsTradeContextBusy противоположны. Более того, эти функции относительно состояния торгового потока не дополняют друг друга, а дублируют. Поэтому одну из них можно исключить. Какую? Функция IsTradeAllowed, как я уже упоминал, кроме флага состояния торгового потока ещё возвращает флаг разрешения советнику торговать, который в данной ситуации, то есть в обработке ошибки 146 (Торговый поток занят), нам не нужен. Следовательно, необходимым и достаточным будет использование только одной функции IsTradeContextBusy. Если выполнить вышеуказанные сокращения, то Ваш код сведётся к моему:

if (err==146) while (IsTradeContextBusy()) Sleep(1000*1,1);
с единственной разницей в размере паузы. Но это уже дело вкуса, личных предпочтений, торгового стиля и прочего. Можно поставить паузу 0,1 сек. Непринципиально... Просто я предпочитаю 11 сек.
 
Благодарю за развёрнутый ответ,про флаг не знал видимо где то упустил в описании.Но для точности я всё таки предпочитаю между всеми видами торговых операций делать паузу от 5 сек до освобождения потока,думаю это корректно и при нескольких экспертах правильно и безопасно. Спасибо.
 

В функции SetOrder обнаружились две ошибки:

  1. Некорректное использования функции MarketInfo. Её следовало вызывать ПОСЛЕ проверки параметра sy, а не ДО.
  2. Неправильно работала корректировка уровней установки ордеров. Кроме того, не корректировались ценовые уровни стопов и тейков. Теперь это всё исправлено и отлично работает. Я это дело долго проверял тестовым скриптом, который выложу немного позже.

Внимание! Пост с функцией SetOrder для онлайн-торговли исправлен. Функция получилась немного длиннее. В пост целиком не входила, поэтому её пришлось вынести в прицеп.

 

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

1. В первых строках кода объявление локальных переменных и инициализация некоторых из них. Например, в lsComm записывается наименование эксперта и наименование тайфрейма, возвращаемое функцией GetNameTF. Кстати, на таких функциях, как GetNameOP, GetNameTF, Message и других мелких я сам останавливаться не буду, только если по ним у кого-то возникнут вопросы.

string   lsComm=WindowExpertName()+" "+GetNameTF(Period());

2. Проверка принятых параметров. Если sy пустая, то она инициализируется наименованием текущего инструмента. По типу операции инициализируется переменная для цвета значка на графике. Если ненулевой срок истечения ордера меньше текущего времени, то он обнуляется.

if (sy=="" || sy=="0") sy=Symbol();
msl=MarketInfo(sy, MODE_STOPLEVEL);
if (op==OP_BUYLIMIT || op==OP_BUYSTOP) clOpen=clOpenBuy; else clOpen=clOpenSell;
if (ex>0 && ex<TimeCurrent()) ex=0;

3. Тело цикла торговых попыток, количество которых ограничено значением глобальной переменной NumberOfTry. Дальше идут операции, выполняемые внутри главного цикла функции SetOrder.

for (it=1; it<=NumberOfTry; it++)

4. Если функция SetOrder выполняется не в тестере, то реализуется возможность прервать её работу. Тут же выполняется цикл ожидания освобождения торгового потока. Обновляются переменные рыночного окружения и фиксируется текущее время.

if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) {
  Print("SetOrder(): Остановка работы функции");
  break;
}
while (!IsTradeAllowed()) Sleep(5000);
RefreshRates();
ot=TimeCurrent();

5. Отправка запроса на торговый сервер. Если тикет положительный, то завершение работы функции SetOrder.

ticket=OrderSend(sy, op, ll, pp, Slippage, sl, tp, lsComm, mn, ex, clOpen);
if (ticket>0) {
  if (UseSound) PlaySound(NameFileSound); break;
 

6. При отрицательном тикете выполняется обработка ошибок исполнения.
7. При ошибках 128 (Истек срок ожидания совершения сделки), 142 (Ордер поставлен в очередь) и 143 (Ордер принят дилером к исполнению) выполняется пауза, длительностью 66 секунд. После паузы с помощью функции ExistOrders (на ней остановимся чуть позже) проверяется, а не установился ли ордер в промежутке времени между запросом к серверу и текущим моментом. Если ордер был установлен, то выход из функции.

err=GetLastError();
if (err==128 || err==142 || err==143) {
  Sleep(1000*66);
  if (ExistOrders(sy, op, mn, ot)) {
    if (UseSound) PlaySound(NameFileSound); break;
  }
  Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
  continue;
}

8. В локальных переменных запоминаются размер пункта и цены Bid и Ask.

mp=MarketInfo(sy, MODE_POINT);
pa=MarketInfo(sy, MODE_ASK);
pb=MarketInfo(sy, MODE_BID);

9. При ошибке 130 (Неправильные стопы) по возможности выполняется корректировка ценовых уровней установки ордера, стопа и тейка.

// Неправильные стопы
if (err==130) {
  switch (op) {
    case OP_BUYLIMIT:
      if (pp>pa-msl*mp) pp=pa-msl*mp;
      if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
      if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
      break;
    case OP_BUYSTOP:
      if (pp<pa+(msl+1)*mp) pp=pa+(msl+1)*mp;
      if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
      if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
      break;
    case OP_SELLLIMIT:
      if (pp<pb+msl*mp) pp=pb+msl*mp;
      if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
      if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
      break;
    case OP_SELLSTOP:
      if (pp>pb-msl*mp) pp=pb-msl*mp;
      if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
      if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
      break;
  }
  Print("SetOrder(): Скорректированы ценовые уровни");
}

10. В протокол выводятся сведения, которые могут впоследствии помочь решить проблему или найти ошибку.

Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
Print("Ask=",pa,"  Bid=",pb,"  sy=",sy,"  ll=",ll,"  op=",GetNameOP(op),
      "  pp=",pp,"  sl=",sl,"  tp=",tp,"  mn=",mn);
if (pa==0 && pb==0) Message("SetOrder(): Проверьте в обзоре рынка наличие символа "+sy);

11. Ну и в конце выполняется обработка прочих ошибок. Одни натыкаются на длительную паузу (5 минут), другие блокируют работу советника, третьи разрешают продолжить торговые попытки и т.д.

Всё! Конец описания!

 

Функция ExistOrders().

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

  • sy - Накладывает ограничение на наименование инструмента. По умолчанию параметр равен "" - отсутствие ограничений, то есть любой инструмент. Если передать NULL, то отбор ордеров будет ограничен текущим инструментом.
  • op - Накладывает ограничение на тип ордера. По умолчанию ограничение отсутствует, то есть проверяется наличие ордера любого типа. Допустимые значения параметра -1, OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT и OP_SELLSTOP.
  • mn - Накладывает ограничение на идентификационное ("магическое") число ордера. По умолчанию ограничение отсутствует, то есть проверяется наличие ордера с любым магическим числом.
  • ot - Накладывает ограничение на время установки ордера. Проверяется. чтобы ордер был установлен позже значения данного параметра. По умолчанию ограничение отсутствует, то есть проверяется наличие ордера с любым временем установки.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 12.03.2008                                                     |
//|  Описание : Возвращает флаг существования ордеров.                         |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любой ордер)                    |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//|    ot - время открытия             ( 0   - любое время установки)          |
//+----------------------------------------------------------------------------+
bool ExistOrders(string sy="", int op=-1, int mn=-1, datetime ot=0) {
  int i, k=OrdersTotal(), ty;
 
  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      ty=OrderType();
      if (ty>1 && ty<6) {
        if ((OrderSymbol()==sy || sy=="") && (op<0 || ty==op)) {
          if (mn<0 || OrderMagicNumber()==mn) {
            if (ot<=OrderOpenTime()) return(True);
          }
        }
      }
    }
  }
  return(False);
}
 

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

1. Проверить наличие любого ордера

ExistOrders();

2. Проверить наличие любого ордера по инструменту текущего графика

ExistOrders(NULL);

3. Проверить наличие ордера BuyLimit по любому инструменту

ExistOrders("", OP_BUYLIMIT);

4. Проверить наличие ордера SellStop с магиком 123456 по EURUSD

ExistOrders("EURUSD", OP_SELLSTOP, 123456);

5. Проверить наличие любого ордера с временем установки не ранее 2-х часов назад

ExistOrders("", -1, -1, TimeCurrent()-2*60*60);
В прицепе скрипт для тестирования функции ExistOrders. Первые 4 примера в скрипте закомментированы.

Файлы:
 

Внимание! В посте от 12.03.2008 07:24 я заменил вложение SetOrder.mq4

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