MQL4 - automated forex trading   /  

Code Base

Code Base  Скрипты  StepByStep Авторизуйтесь или зарегистрируйтесь, чтобы добавить новый код

Этот скрипт для
MetaTrader 4

Мобильный трейдинг!
Купите лицензию и торгуйте мобильно

Имя:
StepByStep [ en | cn ]
Автор: Avals (06.04.2006 10:04)
Рейтинг: 6.8
Скачано: 2852
Скачать:
 IdleLib.dll (60.0 Kb)
 StepByStep.mq4 (10.5 Kb) View
 StepByStep.zip (35.7 Kb)
Не все ТС можно автоматизировать. Часто необходимо ручное тестирование. При этом возникает проблема "заглядывания в будущее", что сильно влияет на качество тестирования. Скрипт позволяет имитировать торги, пошагово выводя исторические котировки разных инструментов и тайм-фреймов. Подача управляется пользователем.
Состав:
IdleLib.dll - библиотека перехвата нажатия клавиш в окнах Metatrader. Скопировать в \experts\libraries
StepByStep.mq4 - сам скрипт
Входные параметры для скрипта:
startdate - дата и время начала тестирования
instruments - инструменты тестирования через пробел, например "EURUSD GBPUSD USDCHF"
minperiod - минимальный период тестирования. М.б. M1, M5, M15, M30, H1, H4, D1, W1.

После запуска скрипта Файл->Открыть автономно. Там выбираем файлы с приставкой "t_" и тайм-фреймом на 1 больше. Например, чтобы открыть EURUSD 30-минутный - нужно открыть файл "t_EURUSDM31.hst". Далее клавишей "6" на расширенной клавиатуре пошагово добавляем котировки. Шаг добавления будет соответствовать тайм-фрейму активного окна. Например, если нажали "6" в окне с часовым тайм фреймом, то шаг будет 1 час и т.д.
35 комментариев: 1 2 3 4   Авторизуйтесь или зарегистрируйтесь, чтобы добавить новый комментарий

Avals писал(а):
Jur писал(а):
Слава, Вы собирались добавить с скрипт возможность торговать - не успели?
Новая версия MT позволяет многое упростить и это уже сделали:
'klot'
А так же:
'Визуализация тестирования. Ручная торговля.'
'Визуализация тестирования. Закладка "История счета".'
'Визуализация тестирования. Закладка "Торговля".'
21.10.2006 09:29 Avals
Jur писал(а):
Слава, Вы собирались добавить с скрипт возможность торговать - не успели?
Новая версия MT позволяет многое упростить и это уже сделали:
'klot'
17.09.2006 15:24 Avals
Merin095 писал(а):
Входные параметры для скрипта:
startdate - дата и время начала тестирования
Ломаю голову как дожны выглядеть вводные данные "дата и время" если любые данные компиляция не пропускает?????
Подскажите кто знает.

я это скрипт впервые вижу, но судя по всему, раз там используется формат datetime, то время в секундах прошедших от 1.1.1970...

например, 25 авг. 2006 17.00 = 1156525200
11.09.2006 12:24 Myxu
Входные параметры для скрипта:
startdate - дата и время начала тестирования
instruments - инструменты тестирования через пробел, например "EURUSD GBPUSD USDCHF"
minperiod - минимальный период тестирования. М.б. M1, M5, M15, M30, H1, H4, D1, W1.

Ломаю голову как дожны выглядеть вводные данные "дата и время" если любые данные компиляция не пропускает?????
Подскажите кто знает.
07.09.2006 09:00 Merin095
Слава, Вы собирались добавить с скрипт возможность торговать - не успели?
21.08.2006 16:59 Jur
Star писал(а):
Avals, добрый вечер!

Соединил оба блока, пока все ОК.

Если я правильно понял, в " extern string period="M5 H1 D1"; "
задаются периоды, на которых собираемся работать, включая и М1,
Правильно?
А в StepbyStep_v1 (вариант, в котором тики генерируются сами)
как я понимаю надо сделать аналогично или нет ?

Сейчас будем пытать.



Star


Все верно.

05.06.2006 21:36 Avals
Avals писал(а):
Блин, в одно сообщение не влазит. Вот продолжение:
Avals, добрый вечер!

    Соединил оба блока, пока все ОК.

Если я правильно понял, в " extern string period="M5 H1 D1"; " 
задаются периоды, на которых собираемся работать, включая и М1, 
  Правильно?
  А в StepbyStep_v1 (вариант, в котором тики генерируются сами)
 как я понимаю надо сделать аналогично или нет ?
  
Сейчас будем пытать.
   


Star



05.06.2006 18:18 Star
Блин, в одно сообщение не влазит. Вот продолжение:
eframe,tfFinde); 
     mytimeframe[tfFinde-1]=5;     
     Print("Найден период M5");     
   } 
   if (StringFind(period,"M15",0)!=-1){
     M15=true;
     tfFinde++;
     ArrayResize(mytimeframe,tfFinde); 
     mytimeframe[tfFinde-1]=15;     
     Print("Найден период M15");     
   } 
   if (StringFind(period,"M30",0)!=-1){
     M30=true;
     tfFinde++;
     ArrayResize(mytimeframe,tfFinde); 
     mytimeframe[tfFinde-1]=30;     
     Print("Найден период M30");     
   } 
   if (StringFind(period,"H1",0)!=-1){
     H1=true;
     tfFinde++;
     ArrayResize(mytimeframe,tfFinde); 
     mytimeframe[tfFinde-1]=60;     
     Print("Найден период H1");     
   } 
   if (StringFind(period,"H4",0)!=-1){
     H4=true;
     tfFinde++;
     ArrayResize(mytimeframe,tfFinde); 
     mytimeframe[tfFinde-1]=240;     
     Print("Найден период H4");     
   } 
   if (StringFind(period,"D1",0)!=-1){
     D1=true;
     tfFinde++;
     ArrayResize(mytimeframe,tfFinde); 
     mytimeframe[tfFinde-1]=1440;     
     Print("Найден период D1");     
   } 
   if (StringFind(period,"W1",0)!=-1){
     W1=true;
     tfFinde++;
     ArrayResize(mytimeframe,tfFinde); 
     mytimeframe[tfFinde-1]=10080;     
     Print("Найден период W1");     
   } 
   
   IdleLibInit();//инициализируем Dll
   InitAllHistory();
   minTime=iTime(NameOfHandles[1],HandlesPeriod[1]-1,iBars(NameOfHandles[1],HandlesPeriod[1]-1)-1); 
   maxTime=iTime(NameOfHandles[1],HandlesPeriod[1]-1,0);   
   //Print("minTime=",TimeYear(minTime)," ",TimeMonth(minTime)," ",TimeDay(minTime));
    
   BuildHistoryToDateTime();      
 
         bool NeedLoop=true;int tick=0;int predTime=0;bool Simulat=false;
         while(NeedLoop){            
           predTime++;
           int lastkey=GetLastKeyWP();           
           string lastwnd=GetActiveWndName();
           if (lastkey==KeyCode2) Simulat=false;
           if (Simulat || ((lastkey==KeyCode1) && (lastwnd!=""))) {  
               if (!Simulat) string  histwnd=lastwnd; else lastwnd=histwnd;
               Simulat=true;
               predTime=0;
               if (StringFind(lastwnd,"M10081",0)>0) AddData(10080); else
               if (StringFind(lastwnd,"M1441",0)>0) AddData(1440); else               
               if (StringFind(lastwnd,"M241",0)>0) AddData(240); else 
               if (StringFind(lastwnd,"M61",0)>0) AddData(60); else 
               if (StringFind(lastwnd,"M31",0)>0) AddData(30); else 
               if (StringFind(lastwnd,"M16",0)>0) AddData(15); else 
               if (StringFind(lastwnd,"M6",0)>0) AddData(5); else 
               if (StringFind(lastwnd,"M2",0)>0) AddData(1);
               if (EmulationTime>=maxTime) NeedLoop=false;
           }//if  
 
           Sleep(100);
           tick++;
           if (tick>=20){
             for (int i=1;i<=CountHandle;i++){
               tick=0;
               int hwnd=WindowHandle("t_"+NameOfHandles[i],HandlesPeriod[i]);        
               if(hwnd!=0) PostMessageA(hwnd,WM_COMMAND,33324,0);                                           
             }//for  
            }//if  
         }//while                
              
   IdleLibUnInit();
   return(0);
  }//start
 
void deinit()
  { 
    for (int i=1;i<=CountHandle;i++){ 
      if(Handles[i]>=0) FileClose(Handles[i]);
    }  
  }//deinit()

05.06.2006 08:49 Avals

На скорость кроме ресурсов и быстродействия компа влияет кол-во валют и мин. TF, а так же кол-во прикрепленных индикаторов и их оптимальность. Некоторые индикаторы каждый раз пересчитывают себя заново, что конечно тормозит работу. Чем меньше мин. TF, тем больше файлов нужно писать при каждом тике, например при M1 - 8 файлов для каждой валюты. Поэтому можно упростить и писать только в TF которые используешь. В приложении - вариант в котором вместо мин.  TF задается перечень исп-ых TF в порядке возрастания - это должно ускорить работу.

//+------------------------------------------------------------------+
//|                                                   StepByStep.mq4 |
//|                                              Viatcheslav Suvorov |
//+------------------------------------------------------------------+
#property copyright "Viatcheslav Suvorov"
#property show_inputs
#include <WinUser32.mqh>
 
#import "IdleLib.dll"
int GetLastKeyWP();
int IdleLibInit();
int IdleLibUnInit();
string GetActiveWndName();
#import
 
extern datetime startdate=0;//дата и время начала эмуляции
extern string instruments="EURUSD GBPUSD";//инструменты эмуляции, например "EURUSD GBPUSD USDJPY"
extern string period="M5 H1 D1";
extern int    KeyCode1=102;
extern int    KeyCode2=101;
 
datetime  minTime;
datetime  maxTime;
int     LastShift[100];
int     Handles[100];
int     HandlesPeriod[100];
string  NameOfHandles[100];
int     CountHandle;
datetime EmulationTime=0;
int mytimeframe[];
 
void AddData(int minutes)
{
  int oldTime=EmulationTime;
  EmulationTime=EmulationTime+minutes*60; 
  bool holy=false;
  if (TimeDayOfWeek(EmulationTime)==0 || TimeDayOfWeek(EmulationTime)==6){
    while ((EmulationTime<maxTime) && (TimeDayOfWeek(EmulationTime)==0 || TimeDayOfWeek(EmulationTime)==6)) EmulationTime++;
    EmulationTime=EmulationTime+3600;    
    holy=true;
  }//   
  for (int i=1;i<=CountHandle;i++){    
    int shift=iBarShift(NameOfHandles[i],HandlesPeriod[i]-1,EmulationTime);     
    if (LastShift[i]>0) int shift1=LastShift[i]; else
      shift1=iBarShift(NameOfHandles[i],HandlesPeriod[i]-1,oldTime);              
    if ((shift!=-1) && (shift1!=-1)){       
      for (int j=shift1-1;j>shift;j--){                
         LastShift[i]=j;
         FileWriteInteger(Handles[i], iTime(NameOfHandles[i],HandlesPeriod[i]-1,j), LONG_VALUE);
         FileWriteDouble(Handles[i], iOpen(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);
         FileWriteDouble(Handles[i], iLow(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);
         FileWriteDouble(Handles[i], iHigh(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);
         FileWriteDouble(Handles[i], iClose(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);
         FileWriteDouble(Handles[i], iVolume(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);        
      }//for
   // if (minutes<HandlesPeriod[i]-1){
    if (HandlesPeriod[i]-1>mytimeframe[0]){
      datetime timeLastBar=iTime(NameOfHandles[i],HandlesPeriod[i]-1,LastShift[i]-1); 
      int sh1=iBarShift(NameOfHandles[i],mytimeframe[0],timeLastBar);
            
      int sh2=iBarShift(NameOfHandles[i],mytimeframe[0],EmulationTime)+1;
      if (sh1-sh2==0) int delt=1; else  delt=sh1-sh2+1;
      
 
      if ((sh1<0) || (sh2<0)){
        double h1=iHigh(NameOfHandles[i],HandlesPeriod[i]-1,LastShift[i]-1);
        double l1=iLow(NameOfHandles[i],HandlesPeriod[i]-1,LastShift[i]-1);            
      } else {              
        h1=iHigh(NameOfHandles[i],mytimeframe[0],Highest(NameOfHandles[i],mytimeframe[0],MODE_HIGH,delt,sh2));
        l1=iLow(NameOfHandles[i],mytimeframe[0],Lowest(NameOfHandles[i],mytimeframe[0],MODE_LOW,delt,sh2));            
      }
      double o1=iOpen(NameOfHandles[i],HandlesPeriod[i]-1,LastShift[i]-1);
      double c1=iClose(NameOfHandles[i],mytimeframe[0],sh2);
      if ((o1>h1) || (o1<l1) || (c1>h1) || (c1<l1)) {
        h1=MathMax(h1,MathMax(o1,c1));
        l1=MathMin(l1,MathMin(o1,c1));
      }  
      
      if (EmulationTime>=timeLastBar+HandlesPeriod[i]-1){                        
         int LastFPos=FileTell(Handles[i]);
         FileWriteInteger(Handles[i], iTime(NameOfHandles[i],HandlesPeriod[i]-1,LastShift[i]-1), LONG_VALUE);
         FileWriteDouble(Handles[i], o1, DOUBLE_VALUE);
         FileWriteDouble(Handles[i], l1, DOUBLE_VALUE);
         FileWriteDouble(Handles[i], h1, DOUBLE_VALUE);
         FileWriteDouble(Handles[i], c1, DOUBLE_VALUE);         
         FileWriteDouble(Handles[i],iVolume(NameOfHandles[i],HandlesPeriod[i]-1,LastShift[i]-1), DOUBLE_VALUE);                         
         FileSeek(Handles[i],LastFPos,SEEK_SET);         
      }     
    }//if  
      FileFlush(Handles[i]);
      int hwnd=WindowHandle("t_"+NameOfHandles[i],HandlesPeriod[i]);        
      if(hwnd!=0) PostMessageA(hwnd,WM_COMMAND,33324,0);                              
    }//if
  }//for  
}
void BuildHistoryToDateTime()
{
  if (EmulationTime==0) EmulationTime=startdate;
  if (EmulationTime<minTime) EmulationTime=minTime;
  if (EmulationTime>maxTime) EmulationTime=minTime;
  for (int i=1;i<=CountHandle;i++){
    int shift=iBarShift(NameOfHandles[i],HandlesPeriod[i]-1,EmulationTime);          
    if (shift!=-1) {      
      for (int j=iBars(NameOfHandles[i],HandlesPeriod[i]-1);j>shift;j--){
         LastShift[i]=j;
         FileWriteInteger(Handles[i], iTime(NameOfHandles[i],HandlesPeriod[i]-1,j), LONG_VALUE);
         FileWriteDouble(Handles[i], iOpen(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);
         FileWriteDouble(Handles[i], iLow(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);
         FileWriteDouble(Handles[i], iHigh(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);
         FileWriteDouble(Handles[i], iClose(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);
         FileWriteDouble(Handles[i], iVolume(NameOfHandles[i],HandlesPeriod[i]-1,j), DOUBLE_VALUE);        
      }//for
      FileFlush(Handles[i]);
      int hwnd=WindowHandle("t_"+NameOfHandles[i],HandlesPeriod[i]);        
      if(hwnd!=0) PostMessageA(hwnd,WM_COMMAND,33324,0);                              
    }//if
  }//for
}
void InitAllHistory()
{  
  int pos=0;
  string curstr="";
  bool sign=true;
  CountHandle=0;
  int    i_unused[13];
  ArrayInitialize(Handles,0);
  ArrayInitialize(HandlesPeriod,0);     
  ArrayInitialize(LastShift,0);  
     
  while (sign) {
    if (pos>StringLen(instruments))  sign=false; else {
      int curchar=StringGetChar(instruments,pos);
      if ((curchar==' ') || (pos==StringLen(instruments))) { 
        Print("Распознал имя ",curstr);
        for (int i=0;i<ArraySize(mytimeframe);i++){     
          int modifyTF=mytimeframe[i]+1;
          int ExtHandle=FileOpenHistory("t_"+curstr+modifyTF+".hst", FILE_BIN|FILE_WRITE);   
          if (ExtHandle>0) {          
            CountHandle++;
            Handles[CountHandle]=ExtHandle;
            HandlesPeriod[CountHandle]=modifyTF;
            NameOfHandles[CountHandle]=curstr;          
               FileSeek(Handles[CountHandle],0,SEEK_SET);           
               FileWriteInteger(Handles[CountHandle], 400, LONG_VALUE);
               FileWriteString(Handles[CountHandle],"(C)opyright 2003, MetaQuotes Software Corp.", 64);
               FileWriteString(Handles[CountHandle], "t_"+curstr, 12);
               FileWriteInteger(Handles[CountHandle], modifyTF, LONG_VALUE);
               FileWriteInteger(Handles[CountHandle], MarketInfo(curstr,MODE_DIGITS), LONG_VALUE);
               FileWriteInteger(Handles[CountHandle], 0, LONG_VALUE);      
               FileWriteInteger(Handles[CountHandle], 0, LONG_VALUE);       
               FileWriteArray(Handles[CountHandle], i_unused, 0, 13);               
          }//if            
        }//for
        curstr="";
      } else curstr=curstr+CharToStr(curchar);
    }//else  
    pos++;
  }//while 
}//InitAllHistory
 
int start()
  {
   bool M1=false,M5=false,M15=false,M30=false,H1=false,H4=false,D1=false,W1=false;
   int tfFinde=0;
   if (StringFind(period,"M1",0)!=-1){
     M1=true;
     tfFinde++;
     ArrayResize(mytimeframe,tfFinde); 
     mytimeframe[tfFinde-1]=1;
     Print("Найден период M1");
   } 
   if (StringFind(period,"M5",0)!=-1){
     M5=true;
     tfFinde++;
     ArrayResize(mytim
05.06.2006 08:33 Avals
Avals писал(а):
Star писал(а):
Avals

Ваша прог. StepbyStep обладает свойствами тикового эмулятора!
Это означает, что если "extern string minperiod="M1"; ", то при каждом очередном шаге на периоде М5 на нем формируется сразу свечка, на старших периодах, М15, Н1 и т.д., свеча формируется по тикам периода М5.
Для старших периодов это почти тиковая эмуляция.
Есть два но.
1. Если младшим периодом выбрать М1(для увеличения количества тиков на старших периодах) то прога не работает.
Посоветуйте, что нужно сделать, чтобы Ваша прекрасная прога заработала
с периода М1.
2. Ваша прога не запускает эксперт, если он присоединен к графику.
Я понимаю, для Вашей проги эксперт не может выполнить торговые команды, но в режиме индикатора то он может выдавать сигналы.
Посоветуйте, что нужно сделать, чтобы по сигналам Вашей проги мог работать и эксперт.
P.S.
Все индикаторы, находящиеся в окне, работают исправно по сигналам Вашей проги.
В общем если удастся решить эти два пунктика, то получается полноценный эмулятор для МТ4, позволяющий трассировать и пошагово проверять выполнение экспертом программы как в ручном так и в автоматическом режиме с использованием всех програмных наработок,
имеющихся для МТ4.

Star
1. Должно работать и для минуток (у меня работает).
2. 'Можно ли заставить эксперта работать на оффлайновом графике?'

В общем то работает и на М1, но при tick=2 , но StepbyStep1 медленно и с задержками.
Поясните в чем причина ограничения скорости работы, что нужно сделать чтобы ее можно
было увеличить и регулировать. Может это связано с записью данных цен к файл. В таком случае
переписывать их во временные множества в памяти и от туда брать их для работы программы
Надо этот вопрос доработать и приспособить ее для работы с экспертом. StepbyStep1 ведь
отличая программа для анализа и тренировки. Надо ее довести до ума. А мы поможем в меру своих
сил и опыта.
Star
05.06.2006 06:08 Star