Обновленный билд 195 от 29 августа: исправления и улучшения - страница 2

 
Кстати у меня во время теста на короткое время самопризвольно включаются линии как будто включен ордер и стоп. Хотя сделок в данный момент не совершаю. Правда изменений со счетом не происходит.

Попробуйте приостановить в этот момент тестирование и посмотрите внимательнее - в чем дело.


И еще по поводу соединительных линий - они по идее должны нести информационную нагрузку, типа синяя положительный профит, красная - отрицательный, а так чередовать их для красоты или типа бай или сел - это и так видно по стрелкам. Хотя по новым стрелкам толком кроме цвета не видно.

Синяя линия - это BUY, красная - SELL. Если угол наклона синей линии положительный, то сделка прошла в прибыль, если отрицательный - в убыток. Очень удобно оценивать результат.


Что-то как-то в последнем варианте много эффектов, но пользователское удобство несколько упало. И глюков много.
А можно ли отключать соединительные линии?

К сожалению, нет. Кстати, лучше всего новые стрелки выглядят на графике Bar, а не Candle.
 
Спасибо за замечания, сделанные выше - сегодня все перепроверять будем.

Если можете в чем-то помочь деталями, выскажитесь, пожалуйста.
 
Если можете в чем-то помочь деталями, выскажитесь, пожалуйста.


Интерфейс тестера несколько жирноват.

Нет никакой необходимости иметь строку названий EA и инструмента длиной во весь экран. Для того, чтобы заполнить пустоту, поля содержат неважную информацию, такую как копирайт, забавный 'Euro vs US Dollar' или расшифровка режима тестирования, которая вполне может быть вынесена во всплывающую подсказку.

Поле слева и кнопки управления справа неоправданно велики. Элементы управления хаотичны и не сгруппированы. ComboBox используется там, где можно было бы обойтись RadioButton, например, при выборе режима и периода.

Вообще, окно управления тестера выглядит, как заготовка, сделанная программистами при его создании только для того, чтобы протестировать работоспособность самого тестера. По мере развития интерфейс оброс деталями по экстенсивному принципу простого добавления снизу/сбоку.

В результате тестер занимает треть экрана в полноэкраном режиме. Многовато будет.
 
Вот код как у меня была сделана визуализация, точнее та часть которая формировала график и где можно было сдвигать хоть по одному бару, хоть по многу, хоть в режиме таймера.
Только добавьте, если кто будет смотреть в WinUser32.mqh
int GetAsyncKeyState(int nVirtKey);
и переименуйте его в as_WinUser32
Далее там открывался автономный файл и кнопками на дополнительной клавиатуре через NumLock можно было все двигать и торговать.
Но если нужно, я думаю разработчик тестера разберется.
На график кидалось мышкой, и данные формировались до этой точки.

//-----------------------------------
#include <as_WinUser32.mqh>
//-----------------------------------
//периоды и символ
int      m_period;
int      m_period_m;
string   symbol_m;
//файловые указатели
int      o_handle;
int      o_sm;
//начальные 
int      td,id,i0;
int      tm_start;
//ключи,время,цена
int      f=0,fm=0,fk=0,fi=0;
int      tm;
double   cm;
//Таймер
int      tmr=0,tmrp; 
int      ftmr,tmc,tm0,tmn;
int      tmr_a=2000;
//********************************************************************
int init()
  {
      td=TimeOnDropped();
      //Comment("td = ",TimeToStr(td,TIME_DATE|TIME_MINUTES));
      m_period = Period();
      //m_period_m = m_period+1; 
      symbol_m = Symbol();
      tm_start = Time[Bars-100];
      id=iBarShift(symbol_m, m_period,td);
      
      ObjectCreate("VLDATA",0,0,td,0);
      ObjectSet("VLDATA",OBJPROP_STYLE,STYLE_DOT);
      ObjectSet("VLDATA",OBJPROP_COLOR,Blue);
   }
//*********************************************************************
int start()
  {
//-----------------Начальные данные-----------------------------
    o_handle=FileOpenHistory("ah_"+symbol_m+m_period+".hst",FILE_BIN|FILE_WRITE);
    if(o_handle < 0) return(-1);
    copy_title_proc(o_handle);
    
    for(int i=Bars-1; i>=id; i--)
    {
      write_bars_hst(i);
    }
    
    i0=id;
    tm=Time[i0];
    cm=Close[i0];
    GlobalVariableSet("gfm",0);  
    GlobalVariableSet("gtm",tm); 
    GlobalVariableSet("gcm",cm); 

    int hwnd=WindowHandle("ah_"+symbol_m,m_period);        
    if (hwnd!=0) PostMessageA(hwnd,WM_COMMAND,33324,0);  
    
    Comment("tm = ", TimeToStr(tm,TIME_DATE|TIME_MINUTES),"\n","cm = ",cm);
//-------------------Эмуляция-----------------------------------------
    int ibar;
    int nn=0;

    while(IsStopped()==false)
    {
     //--------------------------------------------
     
      if (f==0 && fk==0 && GetAsyncKeyState(102)!=0) {f=1; fk=1; tmr=1000;}
      if (f==0 && fk==0 && GetAsyncKeyState(100)!=0) {f=2; fk=2; tmr=1000;}
      if (f==0 && fk==0 && GetAsyncKeyState(105)!=0) {f=3; fk=3; tmr=1000;}
      if (f==0 && fk==0 && GetAsyncKeyState(103)!=0) {f=4; fk=4; tmr=1000;}
      if (f==3 || f==4) nn++;
      if (fi==0 && fk==0 && GetAsyncKeyState(99)!=0)  {fi=1; fk=8; tmr=tmr_a;}
      if (GetAsyncKeyState(97)!=0) {fi=0; f=0; af_Timer(0);} 
      
      if (f==0 && fk==0 && GetAsyncKeyState(111)!=0) {f=5; fk=5;}
      if (f==0 && fk==0 && GetAsyncKeyState(106)!=0) {f=6; fk=6;}
      if (f==5 && tmr>100) {tmr-=100; f=0; tmr_a=tmr;}
      if (f==6) {tmr+=100; f=0; tmr_a=tmr;}
      
      if (fk==1 && GetAsyncKeyState(102)==0) fk=0;
      if (fk==2 && GetAsyncKeyState(100)==0) fk=0;
      if (fk==3 && GetAsyncKeyState(105)==0) fk=0;
      if (fk==4 && GetAsyncKeyState(103)==0) fk=0;
      if (fk==8 && GetAsyncKeyState( 99)==0) fk=0;
      if (fk==5 && GetAsyncKeyState(111)==0) fk=0;
      if (fk==6 && GetAsyncKeyState(106)==0) fk=0;
      
      if (fk==0 && fi==0) af_Timer(0);
      
      if (fi==1) {if (af_Timer(tmr)==1) fi=2;}
      
      if ((f==1 || f==3 || fi==2) && i0>0) 
      {
         i0--;
         write_bars_hst(i0); 
         tm=Time[i0];
         cm=Close[i0];
         GlobalVariableSet("gtm",tm); 
         GlobalVariableSet("gcm",cm);
      }
      
      if (f==2 || f==4) 
      {
         i0++;
         write_bars_hst_null(); 
         tm=Time[i0];
         cm=Close[i0];
         GlobalVariableSet("gtm",tm); 
         GlobalVariableSet("gcm",cm);
      }  
   
   //--------------------------Trade--------------------------------  
    
      if (fm==0 && fk==0 && GetAsyncKeyState(104)!=0) {fm=1; fk=104;}
      if (fm==0 && fk==0 && GetAsyncKeyState( 98)!=0) {fm=2; fk= 98;}
      if (fm==0 && fk==0 && GetAsyncKeyState(101)!=0) {fm=3; fk=101;}
      if (GetAsyncKeyState(96)!=0) fm=10;
    
      if (fk==104 && GetAsyncKeyState(104)==0) fk=0;
      if (fk== 98 && GetAsyncKeyState( 98)==0) fk=0;
      if (fk==101 && GetAsyncKeyState(101)==0) fk=0;
      
      if (fm==1) 
      {
         GlobalVariableSet("gfm",1);  
         GlobalVariableSet("gtm",tm); 
         GlobalVariableSet("gcm",cm); 
      }
    
      if (fm==2) 
      {
         GlobalVariableSet("gfm",2);  
         GlobalVariableSet("gtm",tm); 
         GlobalVariableSet("gcm",cm); 
      }
      
      if (fm==3) 
      {
         GlobalVariableSet("gfm",3);  
         GlobalVariableSet("gtm",tm); 
         GlobalVariableSet("gcm",cm); 
      }
      
      if (fm==10) 
      {
         GlobalVariableSet("gfm",10);  
         GlobalVariableSet("gtm",tm); 
         GlobalVariableSet("gcm",cm); 
      } 
      
      //--------------------------------------------------------------------------   
      if (fi!=0 && tmrp!=tmr) {GlobalVariableSet("gtmr",tmr); tmrp=tmr;}
      if (fi==0 && tmrp!=0) {GlobalVariableSet("gtmr",0); tmrp=0;}
    //------------------------------hwnd------------------------------------------
      
      if (f==1 || f==2 || ((f==3 || f==4) && nn==10) || fi==2 || fm!=0)
      {
        hwnd=WindowHandle("ah_"+symbol_m,m_period);        
        if(hwnd!=0) PostMessageA(hwnd,WM_COMMAND,33324,0);                                           
        
        Comment("tm = ", TimeToStr(tm,TIME_DATE|TIME_MINUTES),"\n","cm = ",cm);
      }
    
    //-----------------------------Сброс ключей-----------------------------------      
      
      if (f==1 || f==2) f=0;
      if ((f==3 || f==4) && nn==10) {f=0; nn=0;} 
      if (fi==2) fi=1;
      fm=0;
      
      if (fi==0 && fk==1) {if (af_Timer(tmr)==1) f=1; tmr=500;}
      if (fi==0 && fk==2) {if (af_Timer(tmr)==1) f=2; tmr=500;}
      if (fi==0 && fk==3) {if (af_Timer(tmr)==1) f=3; tmr=250;}
      if (fi==0 && fk==4) {if (af_Timer(tmr)==1) f=4; tmr=250;}
      
      if (i0==0) {f=0; fi=0;}
    //-----------------------------------------------------------------------------
    } //while   
//----
   return(0);
  } //start()
//*******************************************************************
void deinit()
  {
    if(o_handle>=0) { FileClose(o_handle); o_handle=-1; } 
    ObjectDelete("VLDATA");
    GlobalVariableDel("gfm");
    GlobalVariableDel("gcm");
    GlobalVariableDel("gtm"); 
    GlobalVariableDel("gtmr");
    Comment(" ");
  }
//*******************************************************************
bool  copy_title_proc(int o_handle)
   {
     int    i_unused[13];
     int    i_handle=FileOpenHistory(symbol_m+m_period+".hst",FILE_BIN|FILE_READ);
   
     if(i_handle>0)  
     {
   //
       FileWriteInteger(o_handle,FileReadInteger(i_handle,LONG_VALUE),LONG_VALUE);   //версия
       FileWriteString(o_handle,FileReadString(i_handle,64), 64);                    //копирайт
       FileWriteString(o_handle,"ah_"+FileReadString(i_handle,12), 12);  //символ
       FileWriteInteger(o_handle,FileReadInteger(i_handle,LONG_VALUE),LONG_VALUE); //период
       FileWriteInteger(o_handle,FileReadInteger(i_handle,LONG_VALUE),LONG_VALUE);   //количество знаков после точки
       FileWriteInteger(o_handle,FileReadInteger(i_handle,LONG_VALUE),LONG_VALUE);   //время создания
       FileWriteInteger(o_handle,FileReadInteger(i_handle,LONG_VALUE),LONG_VALUE);   //синхро
   //
       FileReadArray(i_handle,i_unused,0,13);
       FileWriteArray(o_handle,i_unused,0,13);   //пустой на всякий случай
   //
       o_sm=FileTell(o_handle);
       FileFlush(o_handle);
       
       if(i_handle>=0) { FileClose(i_handle); i_handle=-1; }       //закрываем файлы источника
     }
   //
   return(true);
   }
//+------------------------------------------------------------------+
//запись одного бара в файл истории
void   write_bars_hst(int i)
   {
   FileSeek(o_handle,o_sm,SEEK_SET);
   FileWriteInteger(o_handle,Time[i],LONG_VALUE);
   //
   FileWriteDouble(o_handle,Open[i],DOUBLE_VALUE);
   FileWriteDouble(o_handle,Low[i],DOUBLE_VALUE);
   FileWriteDouble(o_handle,High[i],DOUBLE_VALUE);
   FileWriteDouble(o_handle,Close[i],DOUBLE_VALUE);
   FileWriteDouble(o_handle,Volume[i],DOUBLE_VALUE);
   o_sm=FileTell(o_handle);
   //
   FileFlush(o_handle);
   //
   }
//************************************************
//запись одного пустого бара в файл истории
void   write_bars_hst_null( )
   {
   FileSeek(o_handle,o_sm-44,SEEK_SET);
   FileWriteString(o_handle,"", 44);
   FileSeek(o_handle,o_sm-44,SEEK_SET);
   o_sm=FileTell(o_handle);
   //
   FileFlush(o_handle);
   //
   }
//***************************************************************
// функция Таймера
int af_Timer(int tmr)
  {
    int fret=0;
    if (tmr==0) {ftmr=0; tmc=0; tm0=0; tmn=0; }
    if (tmr!=0)
    {
      if (ftmr==0) {tmc=GetTickCount(); tm0=tmc; tmn=0; ftmr=1;}
      if (ftmr==1) {tmc=GetTickCount(); tmn=tmc-tm0;}
      if (ftmr==1 && tmn>=tmr) {ftmr=0; fret=1;} 
    }
    return(fret);
  }
//****************************************************************




 

2) Вы сделали так, что свопы закрываются на следующий день в 00:01 и открываются в этуже 00:01. Но это не верно. В том то и суть переноса позиции, чтобы ее закрыть в предыдущей день в 23:59 и открыть в 00:00 но не в понедельник по "гэпонутой" цене, а по тойже цене что и на момент закрытия.


1. Укажите, каким образом было получено время 00:01 - режим тестирования, настройки тестера, на каком сервере тестировалось.
Позиции при переоткрытии на свопах, имеют время закрытия - 23:59, и время открытия - 00:00.

2. Переоткрытие осуществляется на первой котировке нового дня, НО при этом и при закрытии и при открытии используется одна и та же цена - цена на начало дня - 00:00 (с учётом своп пунктов). Нет разницы по какой именно цене мы мы переоткрываем позицию, поскольку цены открытия и закрытия совпадают.
 
1) Вы можите все проверить приконектившись к интеграл банку, и прогнав в нем элементарный эксперт
3 2004.04.06 11:00 buy 2 1.00 1.2046 1.1991 1.2381 0.00 9450.00
4 2004.04.07 00:01 swap close 2 1.00 1.2116 1.1991 1.2381 700.00 10150.00
5 2004.04.07 00:01 swap open 3 1.00 1.2117 1.1991 1.2381 0.00 10150.00
6 2004.04.08 00:01 swap close 3 1.00 1.2173 1.1991 1.2381 561.20 10711.20
7 2004.04.08 00:01 swap open 4 1.00 1.2174 1.1991 1.2381 0.00 10711.20
8 2004.04.08 11:00 close 4 1.00 1.2170 1.1991 1.2381 -38.80 10672.40

2) Также при переоткрытии своп может начислятся в виде десятых и сотых пункта. т.е. цена открытися может быть на евре эквивалентна 1.211736 например. Или вы просто добавите к открытой позиции своповые начисления а цену открытия менять не будите?
 
1) Вы можите все проверить приконектившись к интеграл банку, и прогнав в нем элементарный эксперт

Вы указали время логов, но не время _сделок_. Посмотрите на время внутри сделок. Там будет 23:59.


2) Также при переоткрытии своп может начислятся в виде десятых и сотых пункта. т.е. цена открытися может быть на евре эквивалентна 1.211736 например. Или вы просто добавите к открытой позиции своповые начисления а цену открытия менять не будите?

Цена меняется и точность повышается (обычно еще на 2 знака после запятой). Вы уверены, что пользуетесь именно 195 билдом от 29 августа?
 
Вы указали время логов, но не время _сделок_. Посмотрите на время внутри сделок. Там будет 23:59.

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

Цена меняется и точность повышается (обычно еще на 2 знака после запятой). Вы уверены, что пользуетесь именно 195 билдом от 29 августа?

Сто процентов уверен.

На это кто нибудь когда нибудеть ответит мне? Если затрудняетесь то так и скажите...
И просто вопрос. Как делать так чтобы после открытия графика после тестирования он отображался не в барах, а в какомто фиксированом виде.. Ну свечи, без решотки, и с разделителями периодов допустим.
 
Круто!!!
Сейчас реализовал свою давнюю задумку - ручная торговля в тестере стратегий!!!!
Нужно просто встроить в пустой эксперт dll-ку, которая перехватывает нажатие клавиш
и запустить эксперт на визуальное тестирование.

#import "IdleLib.dll"
int GetLastKeyWP();
int IdleLibInit();
int IdleLibUnInit();
string GetActiveWndName();
#import



а дальше просто:

//-----------------------------------------------------------------------
   IdleLibInit();//инициализируем Dll для перехвата событий 
   int lastkey=GetLastKeyWP();//Опрашиваем код посл. клавиши
   string lastwnd=GetActiveWndName();//Имя окна Metatrader где произошло событие
   int pos=Check_for_open_pos(); // Проверяем, есть ли открытые позиции
   
   if ((lastkey!=0) && (lastwnd!="") && (lastkey==66) && pos!=1 )  // Команда на открытие Buy клавиша "b"-код 66
   {             
      buy_open(0,0);
    //Print("Код нажатой клавиши=",lastkey," из окна ",lastwnd);
   }  
   if ((lastkey!=0) && (lastwnd!="") && (lastkey==83) && pos!=-1 )  // Команда на открытие Sell клавиша "s"-код 83
   {             
      sell_open(0,0);
    // Print("Код нажатой клавиши=",lastkey," из окна ",lastwnd);
   }  
   if ((lastkey!=0) && (lastwnd!="") && (lastkey==67) )  // Команда на закрытие позиции клавиша "c"-код 67
   {             
     close_order(0,0);
    // Print("Код нажатой клавиши=",lastkey," из окна ",lastwnd);
   }  
   //-----------------------------------------------------------------------



DLL-ка лежит тут очень давно :)
"MQL4: Interception"

 
Вы указали время логов, но не время _сделок_. Посмотрите на время внутри сделок. Там будет 23:59.

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

Моделирование - это дискретный процесс. И отлов свопирования в тестере производится при получении первой котировки следующей сессии. Поэтому в логах об свопировании пишется как 00:01, но в самих ордерах все даты свопирования проставляются точно.

В данном случае логи не обязательно должны совпадать с реалом. Особенно на фоне того, что свопирование в реале никак не отображается в логах терминала.

Цена меняется и точность повышается (обычно еще на 2 знака после запятой). Вы уверены, что пользуетесь именно 195 билдом от 29 августа?

Сто процентов уверен.

Я сам смотрел на Укрсоцбанке - там было все нормально. Перепроверю и на Интеграл Банке.


На это кто нибудь когда нибудеть ответит мне? Если затрудняетесь то так и скажите...
И просто вопрос. Как делать так чтобы после открытия графика после тестирования он отображался не в барах, а в какомто фиксированом виде.. Ну свечи, без решотки, и с разделителями периодов допустим.


Очень просто - сделайте желаемый шаблон под именем tester.tpl

Кстати, о мелких секретах терминала есть пара статей:
"MQL4: Секреты клиентского терминала MetaTrader 4"
"MQL4: Секреты клиентского терминала MetaTrader 4: Система оповещений"
Причина обращения: