Работа эксперта в режиме свопирования методом переоткрытия позиций - страница 3

 
granit77:
KimIV писал (а): .. Торговый сервер съест такой большой тейк или отвергнет?
Демо Альпари ест ТП=2000, СЛ=2000 без вопросов.
Ну про SL не знаю а TP=2000 Альпари на микро точно глотает.
 
В моем ДЦ(не имею права обсуждать каком) тоже работают по такой схеме.
НО! Magic там после переустановки ордеров остается. Т.е. я хочу сказать, что это НЕ глюк сервера,
в сервере заложена возможность сохранения Magic при такой схеме работы!
Возможно: или автор ошибается или стоит обратиться в ДЦ с проблемой(мож они забыли что включить).
Если же ДЦ специально это сделал(т.е. рубит долгосрочную механическую торговлю),
может лучше задуматься о целесообразности работы с этим ДЦ?
 
Вот, это обнадеживающий пост. Значит дело, скорее всего, в настройках отдельно взятого торгового сервера.
 
Вот как я себе представляю работу эксперта в таком режиме, то есть как и говорил, работа с применением записи в файл.

1. При открытии позиции записываем тикет позиции/ордера в массив:

void OpenOrder(string sym, int cmd, double Vol, double Price, int Slip, double SL, double TP, string Com, int Mag, datetime exp, color arr)
{
 if(!IsTradeContextBusy() && AccountFreeMarginCheck(sym, cmd, Vol) > 0) 
  {
   int ticket = OrderSend(sym, cmd, Vol, Price, Slip, SL, TP, Com, Mag, exp, arr);
   if(ticket > 0)
    {
     // Если успешно открыта позиция/установлен ордер, то записываем его тикет в массив
      int i = 0;
      while(i < TotalOrd && TicketPos[i] != -1)
       i++;
      if(TicketPos[i] == -1)
        TicketPos[i] = ticket;
    // Записываем массив в файл
      WriteTicketsInFile();     
     }
   }
 }
2. Запись в файл при помощи функции:
//+------------------------------------------------------------------+
//| Запись в файл массива с номерами тикетов                         |
//+------------------------------------------------------------------+
void WriteTicketsInFile()
{
// ---  Создание файла
  int handle = FileOpen(TicketsFileName, FILE_BIN|FILE_WRITE);
  if(handle < 1)
    {
      Print("Не удалось открыть файл ",TicketsFileName," для записи!");
      return(-1);
     }
// --- Файл создан      
   LastRefresh = TimeCurrent();
   FileWriteInteger(handle, LastRefresh, LONG_VALUE); // Записываем последнее время обновления
   FileWriteInteger(handle, TotalOrd, LONG_VALUE);  // Записываем общее количество тикетов
   for(int i = 0; i < TotalOrd; i++)
    FileWriteInteger(handle, TicketPos[i], LONG_VALUE);
   FileClose(handle);
   return(0);
 }
3. На каждом тике проверяем закрытие позиций. Если имеются закрытые позиции, то удаляем их из массива, а результат по сделкам записываем в другой файл. Это сделано для того, чтобы впоследствии можно было посчитать прибыль именно по данному эксперту, ведь в истории мы не сможем определить их по магику (Хотя можно просто записывать тикеты позиций, а потом по истории сканировать)
//+------------------------------------------------------------------+
//| Нахождение отработавших ордеров/позиций                          |
//+------------------------------------------------------------------+
void FindCloseOrders()
{
// --- Находим отработавшие ордера
 for(int i = 0; i < TotalOrd; i++)
  if(TicketPos[i] != -1)
   {
     if(OrderSelect(TicketPos[i], SELECT_BY_TICKET))
      if(OrderCloseTime() != 0)
     // Ордер прекратил свое существование, выводим информацию о нем в файл
       {
         WriteCloseInFile();
         TicketPos[i] = -1;
        }
    } 
// ---
 }
 
// Конвертируем число в формат Excel - точки в разделителях дробной части заменяем на запятые  
string DoubleToExcel(double Num, int Precision)
{
  string S = DoubleToStr(Num, Precision);
  int index = StringFind(S, ".", 0);
  if(index > -1)
    return(StringSetChar(S, index, ','));
  return(S);  
 } 
 
//+------------------------------------------------------------------+
//| Запись в файл времени закрытия сделки и ее результата            |
//+------------------------------------------------------------------+
void WriteCloseInFile()
{
// ---  Открытие файла
   int handle = FileOpen(TransactionsFileName, FILE_BIN|FILE_WRITE|FILE_READ);
   if(handle < 1)
    {
      handle = FileOpen(TransactionsFileName, FILE_BIN|FILE_WRITE);
      if(handle < 1)
       {
         Print("Не удалось открыть файл ",TransactionsFileName," для записи!");
         return(0);
        }
     }
    else
     {
       int size = FileSize(handle);              
       FileSeek(handle, size, SEEK_SET);
       if(size == 0)
        {
          string S = "Время закрытия;Своп;Прибыль"+CharToStr(13)+CharToStr(10);
          FileWriteString(handle, S, StringLen(S));  
         }
      } 
// --- Файл открыт для дозаписи или создан      
   string Writing = TimeToStr(OrderCloseTime())+"; "+DoubleToExcel(OrderSwap(), 2)+"; "
                    +DoubleToExcel(OrderProfit(), 2)+CharToStr(13)+CharToStr(10);   
   FileWriteString(handle, Writing, StringLen(Writing));
   FileClose(handle);
   return(0);
 }
4. Так как в файл с тикетами записано последнее время обновления, то мы можем сравнивать его с текущим. Если последнее обновление было в прошлые сутки, то исполняем функцию RollOver. Здесь просто по истории находим свои тикеты и ищем среди открытых позиции с такими же стопом и профитом. Обновляем массив тикетов и записываем в файл новые "свои" позиции:
//+-------------------------------------------------------------------------+
//| Обновляем информацию по тикетам при переоткрытии их диллинговым центром |
//+-------------------------------------------------------------------------+
void RollOver()
{
  for(int i = 0; i < TotalOrd; i++)
   if(TicketPos[i] != -1)
    { 
      if(OrderSelect(i, SELECT_BY_TICKET))
       if(OrderCloseTime() != 0) // Выбран ли ордер из истории или из текущих позиций?
         {
           double SL = OrderStopLoss();
           double TP = OrderTakeProfit();
           bool Res = False;
           for(int k = 0; k < OrdersTotal(); k++)
            if(OrderSelect(k, SELECT_BY_POS, MODE_TRADES))
         // Позиция признается своей, если у нее совпадают профит, стоп и открыта она после начала текущего дня    
             if(OrderOpenTime() > DayBegin && OrderStopLoss() == SL && OrderTakeProfit() == TP)
               {
                TicketPos[i] = OrderTicket();
                Res = True;
                }
           if(!Res)
             TicketPos[i] = -1; // Позиция не найдена. Считается, что была закрыта по профиту или стопу    
          }
     }
  // Записываем новые тикеты в файл 
  WriteTicketsInFile();  
 }
Все эти функции проверил на простейшем советнике - вход по пересечении средних. Тестировал на фунте. Советник в прикрепленном файле.

P. S. Хоть разработчики и утверждают, что брокер не может увидеть магик позиции, все-таки можно предположить, что некоторые брокеры не стесняются его добывать, ведь он хранится на сервере. Так что вышеизложенный подход не позволит по магику определить активность советника, так как магик не используется. Хотя такая работа не очень удобна по сравнению с классическим методом с магиками.
Файлы:
rollover.zip  3 kb