Реквоты и функция OrderSend ...

 

Вот я при открытии позиции делаю обновленеи котировок. То есть использую саму актульную цену в терминале

RefreshRates();

И говорю что допустимое отклонение от запрашиваемой актуальной цены Ask будет 500 пунктов:

PosTicket = OrderSend(Symbol(), OP_BUY, NormalizeDouble(PosLots, 2), Ask, 500, 0, 0, Comments, PosId, 0, Green);

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

Или я не правильно понимаю механизм реквотирования и исполнения приказов?

 
Тоже сталкивался с таким, иногда даже на спокойном рынке,  при при вполне достаточном слипаже (10-15) появляются реквоты, особенно если попытка открыться происходит по "удачной" для меня цене.....
 
elritmo:

Это что реквоты такие что не находится цена от моей запрашиваемой отличающаяся на 500 пунктов.

Или я не правильно понимаю механизм реквотирования и исполнения приказов?


А как в журнале ругается: реквоты?
 
Максимальное отклонение не действует, если на сервер приходит явно и сильно устаревшая заявка (что часто бывает на сильных движениях).

В этом случае торговый сервер сам безусловно отдает реквот даже без транслировании заявки дилеру. То есть, сервер получает устаревшую цену в торговой заявке и говорит клиенту:
"Дружище, ты пришел с совсем непонятной ценой. Я не буду тебе слать прямой отказ, но вот тебе текущие цены - подумай еще раз и прими новое решение".
Фактически максимально допустимый слиппаж (допустимое отклонение) в функции OrderSend не более 5 пунктов (или 1-2 спреда). БОльшее значение все равно не будет принято во внимание на торговом сервере при анализе цен.

при при вполне достаточном слипаже (10-15) появляются реквоты, особенно если попытка открыться происходит по "удачной" для меня цене
Реквот при слиппаже 10 однозначно означает реально устаревшую (но "удачную" для трейдера) цену. Как раз описываемый мною случай.
 

А чем дополнить код, что-б на такой "ответ сервера" всё равно открыть?
пример плиз...

И что правильней использовать:
- макс. 5 пип или 2*спред

 
kombat:

А чем дополнить код, что-б на такой "ответ сервера" всё равно открыть?
пример плиз...

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

И что правильней использовать:
- макс. 5 пип или 2*спред

Не имеет значения. Важен сам принцип - "трейдеру никогда не позволят совершить ошибку, приняв заявку по устаревшей/ошибочной цене с огромный допустимым отклонением". Можно грубо считать, что плавающий граничный предел допустимого (принимаемого во внимание) отклонения около двух спредов. То есть, если даже на спокойном рынке получится расхождение с текущей рыночной ценой больше пары спредов (уровень плавающий, приведен для примера), то реквот будет вне зависимости от уровня проскальзывания.

Уточню, что речь идет именно об Instant Execution запросах и не касается срабатывания отложенных ордеров или стопов на гепах.
 

Понятно, значит следует указывать отклонение цены не больше 10 пунктов. И обрабатывать код ошибки который возвращает OrderSend

Если код ошибки означает что ордер не открылся (или закрылся) из-за того что цена ушла от запрашиваемой больше 5 пунктов

и предложена новая цена, то попытаться открыть на следующем тике (или закрыть позицию).

 
kombat писал (а):
А чем дополнить код, что-б на такой "ответ сервера" всё равно открыть?
пример плиз...

Рекомендую свою функцию. Общий срок разработки этой функции - более двух лет. Так что она проверена на многочисленных демо-счетах и само собой на реальных.

//+----------------------------------------------------------------------------+
//|  Открытие позиции                                                          |
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (NULL - текущий символ)                 |
//|    op - операция                                                           |
//|    ll - лот                                                                |
//|    sl - уровень стоп                                                       |
//|    tp - уровень тейк                                                       |
//|    mn - MagicNumber                                                        |
//+----------------------------------------------------------------------------+
void OpenPosition(string sy, int op, double ll, double sl=0, double tp=0, int mn=0) {
  color  clOpen;
  double pp, pAsk, pBid;
  int    dg, err, it, ticket;
  string lsComm=WindowExpertName()+" "+GetNameTF(Period());
 
  if (sy=="" || sy=="0") sy=Symbol();
  if (op==OP_BUY) clOpen=clOpenBuy; else clOpen=clOpenSell;
  for (it=1; it<=NumberOfTry; it++) {
    if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) break;
    while (!IsTradeAllowed()) Sleep(5000);
    RefreshRates();
    dg=MarketInfo(sy, MODE_DIGITS);
    pAsk=MarketInfo(sy, MODE_ASK);
    pBid=MarketInfo(sy, MODE_BID);
    if (op==OP_BUY) pp=pAsk; else pp=pBid;
    pp=NormalizeDouble(pp, dg);
    ticket=OrderSend(sy, op, ll, pp, Slippage, sl, tp, lsComm, mn, 0, clOpen);
    if (ticket>0) {
      if (UseSound) PlaySound(NameFileSound); break;
    } else {
      err=GetLastError();
      if (err==128 || err==142 || err==143) {
        Sleep(1000*75);
        if (ExistPositions(sy, op, mn)) {
          if (UseSound) PlaySound(NameFileSound); break;
        }
      }
      // Вывод сообщения об ошибке
      Print("Error(",err,") opening position: ",ErrorDescription(err),", try ",it);
      Print("Ask=",pAsk," Bid=",pBid," sy=",sy," ll=",ll," op=",GetNameOP(op),
            " pp=",pp," sl=",sl," tp=",tp," mn=",mn);
      if (pAsk==0 && pBid==0) Message("Проверьте в Обзоре рынка наличие символа "+sy);
      // Реакция на ошибку
      if (err==2 || err==64 || err==65 || err==133) {
        gbDisabled=True; break;
      }
      if (err==4 || err==131 || err==132) {
        Sleep(1000*300); break;
      }
      if (err==140 || err==148 || err==4110 || err==4111) break;
      if (err==141) Sleep(1000*100);
      if (err==145) Sleep(1000*10);
      if (err==146) while (IsTradeContextBusy()) Sleep(1000*11);
      if (err!=135) Sleep(1000*10);
    }
  }
}
 

Дополнительные необходимые функции

//+----------------------------------------------------------------------------+
//|  Возвращает флаг существования позиций                                     |
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любая позиция)                  |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//+----------------------------------------------------------------------------+
bool ExistPositions(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=="") {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (op<0 || OrderType()==op) {
            if (mn<0 || OrderMagicNumber()==mn) return(True);
          }
        }
      }
    }
  }
  return(False);
}
 
//+----------------------------------------------------------------------------+
//|  Возвращает наименование торговой операции                                 |
//|  Параметры:                                                                |
//|    op - идентификатор торговой операции                                    |
//+----------------------------------------------------------------------------+
string GetNameOP(int op) {
  switch (op) {
    case OP_BUY      : return("Buy");
    case OP_SELL     : return("Sell");
    case OP_BUYLIMIT : return("Buy Limit");
    case OP_SELLLIMIT: return("Sell Limit");
    case OP_BUYSTOP  : return("Buy Stop");
    case OP_SELLSTOP : return("Sell Stop");
    default          : return("Unknown Operation");
  }
}
 
//+----------------------------------------------------------------------------+
//|  Возвращает наименование таймфрейма                                        |
//|  Параметры:                                                                |
//|    TimeFrame - таймфрейм (количество секунд)      (0 - текущий ТФ)         |
//+----------------------------------------------------------------------------+
string GetNameTF(int TimeFrame=0) {
  if (TimeFrame==0) TimeFrame=Period();
  switch (TimeFrame) {
    case PERIOD_M1:  return("M1");
    case PERIOD_M5:  return("M5");
    case PERIOD_M15: return("M15");
    case PERIOD_M30: return("M30");
    case PERIOD_H1:  return("H1");
    case PERIOD_H4:  return("H4");
    case PERIOD_D1:  return("Daily");
    case PERIOD_W1:  return("Weekly");
    case PERIOD_MN1: return("Monthly");
    default:         return("UnknownPeriod");
  }
}

kombat писал (а):
И что правильней использовать:
- макс. 5 пип или 2*спред

Я использую 3 пункта. Максимальное проскальзывание, с каким я встречался на спокойном рынке на реальном счёте - это 7 пунктов (это было один раз за два года реальной торговли на двух счетах).

 

Игорь, спасибо!
Ни на йоту не сомневаюсь в отработке кода временем. ;)))

Тут нечто другое, точнее другая плоскость.
Начну от Адама...
Мне без разницы по какой цене откроется позиция! если я решил её открыть...
(как и заметил выше Ренат, это для исполнения ИЕ)

Посему был уверен что слиппаж в моих скриптах 100 пип позволит мне открыть
любой скачек на любой болтанке, будь то 1 пип или 10 или даже 50, не суть...
Главное открыться! :)

Мне точность "скока вешать в граммах" в 99% случаев не нужна.
Вот почему и спросил, как и чем дополнить код простого, например этого скрипта:

// Скрипт для окрытия BUY
#property show_inputs
extern double lots=1.0;
extern int StopLoss=100;
extern int TakeProfit=100;
void start()
{  int ticket;
   double loss=0; if(StopLoss>0) loss=Ask-StopLoss*Point;
   double profit=0; if(TakeProfit>0) profit=Ask+StopLoss*Point;
   ticket=OrderSend(Symbol(),OP_BUY,lots,Ask,100,loss,profit,"",0,0,CLR_NONE);
   if (ticket<1) Print ("Error = ",GetLastError());
}
//-----------------------------------------------------------+
Тем самым приблизив исполнение по ИЕ к исполнению по "by market" . ..

 
kombat писал (а):
Мне точность "скока вешать в граммах" в 99% случаев не нужна.
Вот почему и спросил, как и чем дополнить код простого, например этого скрипта:
Вы ведь не смотрели, не вникали в суть кода моей функции. А там есть количество торговых попыток NumberOfTry. По-моему, как раз то, что Вам нужно. Ставите NumberOfTry=100 или 500. Рано или поздно сделка будет совершена. Я использую NumberOfTry=5. Таких случаев, чтобы советник не совершил сделку, очень мало. В основном это потеря связи. А для отработки реквотов NumberOfTry=5 вполне достаточно.
Причина обращения: