ФОРТС: баг "exchange/instant" в размещении ордеров для фьючерса на РТС - страница 3

 

На самом деле тут получаются две проблемы:

Проблема 1: Тестер при генерации тиков для РТС не учитывает шаг в 10руб. Но это не критично, т.к. решается округлением.

Проблема 2:  При отправке заявок на открытие позиций с уже округленной ценой, функция OrderSend в некоторых ситуациях "портит" цену, сбрасывая ее на некруглую, и затем "тестовый сервер" типа ее отклоняет с ошибкой [invalid price].  А в каких-то все нормально, критерий не ясен.

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

Сет с настройками для тестирования приложен.

Тестировать нужно на М1 , режим "Все тики".

Так у меня при прогоне за период с 2014-01-06 по 2014-01-30 на склейке "RTS Splice" получается  61% потерянных заявок.

 

Файлы:
Testprobe.zip  117 kb
 
Сергей Лебедев:


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

На самом деле тут получаются две проблемы:

Проблема 1: Тестер при генерации тиков для РТС не учитывает шаг в 10руб. Но это не критично, т.к. решается округлением.

Проблема 2:  При отправке заявок на открытие позиций с уже округленной ценой, функция OrderSend в некоторых ситуациях "портит" цену, сбрасывая ее на некруглую, и затем "тестовый сервер" типа ее отклоняет с ошибкой [invalid price].  А в каких-то все нормально, критерий не ясен.

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

Сет с настройками для тестирования приложен.

Тестировать нужно на М1 , режим "Все тики".

Так у меня при прогоне за период с 2014-01-06 по 2014-01-30 на склейке "RTS Splice" получается  61% потерянных заявок.

 

Да, есть проблема!

Проявляется только в 2014 году. Тестер криво работает.

2016.02.21 22:08:29.031 2014.01.08 12:09:05   CTrade::OrderSend: instant sell 1.00 RTS Splice at 139822 [invalid price]
2016.02.21 22:08:29.031 2014.01.08 12:09:05   failed instant sell 1.00 RTS Splice at 139822 [Invalid price]
2016.02.21 22:08:28.484 2014.01.08 12:08:32   CTrade::OrderSend: instant sell 1.00 RTS Splice at 139787 [invalid price]
2016.02.21 22:08:28.484 2014.01.08 12:08:32   failed instant sell 1.00 RTS Splice at 139787 [Invalid price]
2016.02.21 22:08:28.478 2014.01.08 12:06:05   CTrade::OrderSend: instant buy 1.00 RTS Splice at 139725 [invalid price]
2016.02.21 22:08:28.478 2014.01.08 12:06:05   failed instant buy 1.00 RTS Splice at 139725 [Invalid price]
2016.02.21 22:08:28.474 2014.01.08 12:05:05   CTrade::OrderSend: instant sell 1.00 RTS Splice at 139842 [invalid price]
2016.02.21 22:08:28.474 2014.01.08 12:05:05   failed instant sell 1.00 RTS Splice at 139842 [Invalid price]
2016.02.21 22:08:28.470 2014.01.08 12:04:04   failed instant sell 1.00 RTS Splice at 139651 [Invalid price]
2016.02.21 22:08:28.469 2014.01.08 12:03:15   CTrade::OrderSend: instant buy 1.00 RTS Splice at 139598 [invalid price]
2016.02.21 22:08:28.469 2014.01.08 12:03:15   failed instant buy 1.00 RTS Splice at 139598 [Invalid price]
2016.02.21 22:08:28.469 2014.01.08 12:02:20   CTrade::OrderSend: instant sell 1.00 RTS Splice at 139611 [invalid price]
2016.02.21 22:08:28.469 2014.01.08 12:02:20   failed instant sell 1.00 RTS Splice at 139611 [Invalid price]
2016.02.21 22:08:28.468 2014.01.08 12:01:00   CTrade::OrderSend: instant buy 1.00 RTS Splice at 139579 [invalid price]
2016.02.21 22:08:28.468 2014.01.08 12:01:00   failed instant buy 1.00 RTS Splice at 139579 [Invalid price]
2016.02.21 22:08:28.468 2014.01.08 12:00:59   CTrade::OrderSend: instant buy 1.00 RTS Splice at 139580 [done at 139580]
2016.02.21 22:08:28.468 2014.01.08 12:00:59   order performed buy 1.00 at 139580 [#37 buy 1.00 RTS Splice at 139580]
2016.02.21 22:08:28.468 2014.01.08 12:00:59   deal #37 buy 1.00 RTS Splice at 139580 done (based on order #37)
2016.02.21 22:08:28.468 2014.01.08 12:00:59   instant buy 1.00 RTS Splice at 139580 (139570 / 139580 / 139570)

Вот код для проверки, чуть чуть измененный от предидущего: 

//+------------------------------------------------------------------+
//|                                                TestCtradeBuy.mq5 |
//+------------------------------------------------------------------+

#include <Trade\Trade.mqh>

input double Lot=1.0;

CTrade trade;
double close[],high[],low[];
datetime time[],prevtime;
bool newbarbuy=false;
bool newbarsell=false;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   CopyTime(_Symbol,PERIOD_CURRENT,0,1,time);
   if(time[0]>prevtime)
     {
      newbarbuy=true;
      newbarsell=true;
      prevtime=time[0];
     }

   CopyClose(_Symbol,PERIOD_CURRENT,0,2,close);
   CopyHigh(_Symbol,PERIOD_CURRENT,0,2,high);
   CopyLow(_Symbol,PERIOD_CURRENT,0,2,low);

   if(close[0]<low[1] && newbarbuy)
     {
      trade.Buy(Lot);
      newbarbuy=false;
     }
   if(close[0]>high[1] && newbarsell)
     {
      trade.Sell(Lot);
      newbarsell=false;
     }
     
   Comment(
           "\n ticksise = ",SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE),
           "\n Ask = ",SymbolInfoDouble(_Symbol,SYMBOL_ASK),
           "\n Bid = ",SymbolInfoDouble(_Symbol,SYMBOL_BID),
           "");
  }
//+------------------------------------------------------------------+
 

Sergey Chalyshev, благодарю за содействие.

Несколько  дописал ваш код, что бы продемонстрировать и первую и вторую ошибку.

//+------------------------------------------------------------------+
//|                                                TestCtradeBuy.mq5 |
//+------------------------------------------------------------------+

#include <Trade\Trade.mqh>

input double Lot=1.0;

CTrade trade;
double close[],high[],low[];
datetime time[],prevtime;
bool newbarbuy=false;
bool newbarsell=false;
double newprice;
bool ressend;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   CopyTime(_Symbol,PERIOD_CURRENT,0,1,time);
   if(time[0]>prevtime)
     {
      newbarbuy=true;
      newbarsell=true;
      prevtime=time[0];
     }

   CopyClose(_Symbol,PERIOD_CURRENT,0,2,close);
   CopyHigh(_Symbol,PERIOD_CURRENT,0,2,high);
   CopyLow(_Symbol,PERIOD_CURRENT,0,2,low);

   if(close[0]<low[1] && newbarbuy)
     {
      // Демонстрация первой ошибки
      ressend = trade.Buy(Lot);
      if (ressend == false) {Print ("Демонстрация первой ошибки");}
      // Демонстрация второй ошибки
      newprice = NormalizeDouble(close[0]/10,0)*10;
      ressend = trade.BuyLimit(Lot,newprice);
      if (ressend == false) 
         {Print ("Демонстрация второй ошибки, запрошена цена:" + DoubleToString(newprice,0));}
      newbarbuy=false;
     }
   if(close[0]>high[1] && newbarsell)
     {
      // Демонстрация первой ошибки
      ressend = trade.Sell(Lot);
      if (ressend = false) Print ("Демонстрация первой ошибки");
      // Демонстрация второй ошибки
      newprice = NormalizeDouble(close[0/10],0)*10;
      ressend = trade.SellLimit(Lot,newprice);
      if (ressend = false) 
         {Print ("Демонстрация второй ошибки, запрошена цена:" + DoubleToString(newprice,0));}
      newbarsell=false;
     }
     
   Comment(
           "\n ticksise = ",SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE),
           "\n Ask = ",SymbolInfoDouble(_Symbol,SYMBOL_ASK),
           "\n Bid = ",SymbolInfoDouble(_Symbol,SYMBOL_BID),
           "");
  }
//+------------------------------------------------------------------+


Направил заявку в Сервис Декс, #1414248.

 
Сергей Лебедев:

Sergey Chalyshev, благодарю за содействие.

Несколько  дописал ваш код, что бы продемонстрировать и первую и вторую ошибку.


Направил заявку в Сервис Декс, #1414248.

 Пожалуйста укажите временной интервал тестирования, настройки тестирования и полный лог-файл этого теста в котором есть ошибки.

Добавлено: явная ошибка:

   if(close[0]>high[1] && newbarsell)
     {
      // Демонстрация первой ошибки
      ressend = trade.Sell(Lot);
      if (ressend = false) Print ("Демонстрация первой ошибки");
      // Демонстрация второй ошибки
      newprice = NormalizeDouble(close[0/10],0)*10;
      ressend = trade.SellLimit(Lot,newprice);
      if (ressend = false) 
         {Print ("Демонстрация второй ошибки, запрошена цена:" + DoubleToString(newprice,0));}
      newbarsell=false;
     }
 

Настройки тестирования: инструмент "RTS Splice" у брокера Открытие, или "@RTS" у брокера БКС .

Интервал: с 2014-01-06 по 2014-01-30, либо любой иной за 2014г. Период: М1. Режим: "Все тики" . 

Лог-файл получается очень большой, т.к. советник генерит множество сделок.

 

Karputov Vladimir 2016.02.22 07:28 

Добавлено: явная ошибка:

Согласен - во втором абзаце поспешил и не там поставил делитель.  

Правильный код: 

   if(close[0]>high[1] && newbarsell)
     {
      // Демонстрация первой ошибки
      ressend = trade.Sell(Lot);
      if (ressend = false) Print ("Демонстрация первой ошибки");
      // Демонстрация второй ошибки
      newprice = NormalizeDouble(close[0]/10,0)*10;
      ressend = trade.SellLimit(Lot,newprice);
      if (ressend = false)
         {Print ("Демонстрация второй ошибки, запрошена цена:" + DoubleToString(newprice,0));}
      newbarsell=false;
     }

 
Сергей Лебедев:

Лог-файл получается очень большой, т.к. советник генерит множество сделок.

Ничего страшного. Закиньте его в облако (OneDrive - например) и откройте доступ.
 

Ужас.

Простите, прочитал только 1-ю страницу. Мое неквалифицированное мнение такое:

1. МТ5 для ФОРТС не предназначен.

2. Квик или Альфа для ФОРТС гораздо лучше. Даже с учетом квиковских недомерков QPILE и QLUA. В Альфе вообще API.

3. МТ5 не дает всей необходимой информации о рынке. В нем этого просто нет.

Про тестирование вообще не понял. Тестер, какой вам нужен, пишется максимум за пару дней в любой среде от Ексел до С++, включая коннект с БД и любую обработку данных тестирования, какая взбредет в голову и возможностью все это моментально переделать. И учтите, что тестер при этом работает именно так, как вам нужно.

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

 

ну и чем закончилось-то выясненние?

///

у меня почему-то на RTS-Splice и RTS-3.17 если прогонять на периоде 15дек-15 марта, Каждый тик на основе реальных тиков, то получает РАЗНЫЙ Баланс в итоге... В журнале ошибок нет

 
Ничем, Сервис-деск так ничего и не ответил, как и тех-поддержка Открытия. Пришлось в коде сделать ловушку для таких ошибок и функционал повторного перевыставления заявок - это позволило снизить долю потерянных сигналов с ~30% до ~1-2%.