Библиотеки: Frames

 

Frames:

Чтение фреймов из mqd-файлов результатов Оптимизации.

Автор: fxsaber

 
Этот пример существенно дополняет Документацию по фреймам, поэтому здесь

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Тестирование стратегий по расписанию с автоподстановкой результата в советника

Slava, 2013.04.10 15:04

Вот пример. В OnTester советник отсылает 2 фрейма - история сделок и история, на которой он работал.

double OnTester()
  {
   BalanceInTime balance[];
   double        balance_current=TesterStatistics(STAT_INITIAL_DEPOSIT);
   uint          data_count=0;
   MqlRates      rates[];
//---
   CopyRates(Symbol(),Period(),D'2010.12.01 0:00',D'2013.01.01 0:00',rates);
//--- запросим всю торговую историю
   HistorySelect(0,TimeCurrent());
   uint deals_total=HistoryDealsTotal();
   if(deals_total!=257)
     {
      if(deals_total>0)
        {
         ulong ticket=0;
         ArrayResize(balance,deals_total);
         //--- собираем данные о сделках
         for(uint i=0; i<deals_total; i++)
           {
            if((ticket=HistoryDealGetTicket(i))>0)
              {
               long   entry =HistoryDealGetInteger(ticket,DEAL_ENTRY);
               double profit=HistoryDealGetDouble(ticket,DEAL_PROFIT);
               if(entry==DEAL_ENTRY_OUT || entry==DEAL_ENTRY_INOUT)
                  balance_current+=profit;
               balance[data_count].date=HistoryDealGetInteger(ticket,DEAL_TIME);
               balance[data_count].entry=(ENUM_DEAL_ENTRY)entry;
               balance[data_count].price=HistoryDealGetDouble(ticket,DEAL_PRICE);
               balance[data_count].balance=balance_current;
               data_count++;
              }
           }
         if(data_count<deals_total)
            ArrayResize(balance,data_count);
        }
      FrameAdd(MQL5InfoString(MQL5_PROGRAM_NAME),1,data_count,balance);
      //---
      FrameAdd(MQL5InfoString(MQL5_PROGRAM_NAME),2,ArraySize(rates),rates);
     }
//---
   return(double(deals_total));
  }

В OnTesterDeinit приём и обработка всех фреймов первого и второго типа

void OnTesterDeinit()
  {
   string        name;
   ulong         pass;
   long          id;
   double        value;
   int           handle,i;
   BalanceInTime balance[];
   MqlRates      rates[];
//---
   FrameFirst();
   FrameFilter("",1);
   while(FrameNext(pass,name,id,value,balance))
     {
      handle=FileOpen(name+"_"+string(id)+"_"+IntegerToString(pass,5,'0')+".txt",FILE_WRITE|FILE_CSV|FILE_ANSI);
      if(handle!=INVALID_HANDLE)
        {
         for(i=0; i<ArraySize(balance); i++)
            FileWrite(handle,balance[i].date,EnumToString(balance[i].entry),DoubleToString(balance[i].price,5),DoubleToString(balance[i].balance,2));
         FileClose(handle);
        }
     }
//---
   FrameFirst();
   FrameFilter("",2);
   while(FrameNext(pass,name,id,value,rates))
     {
      handle=FileOpen(name+"_"+string(id)+"_"+IntegerToString(pass,5,'0')+".txt",FILE_WRITE|FILE_CSV|FILE_ANSI);
      if(handle!=INVALID_HANDLE)
        {
         for(i=0; i<ArraySize(rates); i++)
            FileWrite(handle,rates[i].time,DoubleToString(rates[i].open,5),DoubleToString(rates[i].high,5),DoubleToString(rates[i].low,5),DoubleToString(rates[i].close,5),string(rates[i].tick_volume));
         FileClose(handle);
        }
     }
//---
  }

И пояснение к нему

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

Slava, 2019.04.18 07:44

OnTesterPass вызывается, когда пришёл хотя бы один фрейм. Может прийти пачка фреймов. Поэтому в OnTesterPass надо принимать фреймы в цикле, а не по одному. Но если "после последнего раза - ни разу", то OnTesterPass не вызывается.

Оптимизация прекращается, когда пришёл последний результат. Фреймы могут поступить позднее, особенно если в фрейме передаётся большое количество данных или если передаётся сразу несколько фреймов на один проход. Поэтому в OnTesterDeinit, которая запускается по завершению оптимизации нужно организовывать приём оставшихся фреймов.  Тоже в цикле.

Это - нормальная здоровая логика.

Я несколько раз давал примеры приёма фреймов именно в OnTesterDeinit, а не только в OnTesterPass. И именно приём сложных фреймов разных типов


FrameFilter предназначен для сложных фреймов. OnTesterPass реагирует только на один фрейм из прохода. Поэтому рекомендовал бы использовать только по подному фрейму на проход.

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