EA/지표의 틱 에뮬레이션

 

자체 작성 DLL을 사용하거나 스크립트를 실행하지 않고 EA/지시자에서 자동 틱 에뮬레이션을 구현하는 것이 오랫동안 목표였습니다. 말하자면 순전히 스포츠에 대한 관심 :) 작업이 MQL 파일을 넘어서는 것이 아니고 코드(특히 표시기)를 반복하는 것이 불가능한 경우 누군가에게 매우 유용할 수 있습니다.

일반적으로 일반적인 방법으로는 불가능하기 때문에 부분적으로 기계어로 작성해야 했습니다. 아래는 결과 버전입니다.

EA는 지정된 간격으로 차트에 눈금을 생성 하는 타이머를 설정합니다 .

 #import "user32.dll"
   int    RegisterWindowMessageA( string lpString);
   int    SetTimer( int hWnd, int nIDEvent, int uElapse, int & lpTimerFunc[]);
   bool   KillTimer( int hWnd, int uIDEvent);
#import "kernel32.dll"
   int    GetModuleHandleA( string lpModuleName);
   int    GetProcAddress( int hModule, string lpProcName);
  

int TimerId= 666 ;

//----------------------------------------------------------------------

int init()
{
  SetMyTimer( 1000 );   // интервал в миллисекундах
}
//----------------------------------------------------------------------

int deinit()
{
  KillMyTimer();
}  

//+------------------------------------------------------------------+
//| program start function                                           |
//+------------------------------------------------------------------+
int start()
{
   PlaySound ( "tick.wav" ); 
}
//-------------------------------------------------------------------

int SetMyTimer( int interval)
{    
   int MT4InternalMsg= RegisterWindowMessageA( "MetaTrader4_Internal_Message" );
   int hWnd= WindowHandle ( Symbol (), Period ());
   int PostMsgAddr= GetProcAddress(GetModuleHandleA( "user32.dll" ), "PostMessageA" );
   int code[];
  AddBytes(code, 0x55 );   // push ebp
  AddBytes(code, 0x8B );   // move ebp,esp
  AddBytes(code, 0xEC );  
  AddBytes(code, 0x6A );   // push 01
  AddBytes(code, 0x01 );
  AddBytes(code, 0x6A );   // push 02
  AddBytes(code, 0x02 );
  AddBytes(code, 0x68 );   // push MT4InternalMsg
  AddBytes(code,MT4InternalMsg, 4 );
  AddBytes(code, 0x68 );   // push hWnd
  AddBytes(code,hWnd, 4 );
  AddBytes(code, 0xB8 );   // mov eax, PostMsgAddr
  AddBytes(code,PostMsgAddr, 4 );
  AddBytes(code, 0xFF );   // call eax
  AddBytes(code, 0xD0 );  
  AddBytes(code, 0x33 );   // xor eax, eax
  AddBytes(code, 0xC0 );
  AddBytes(code, 0x5D );   // pop ebp
  AddBytes(code, 0xC3 );   // ret
  
   return (SetTimer(hWnd, TimerId, interval, code) );
}
//---------------------------------------------------

bool KillMyTimer()
{
   return ( KillTimer( WindowHandle ( Symbol (), Period ()), TimerId) );
}
//+------------------------------------------------------------------+

int AddBytes( int & code[], int value, int bytescount= 1 )
{
   static int pos= 0 ;   // текущая позиция (в байтах)
   if ( ArraySize (code)== 0 ) pos= 0 ;
   for ( int i= 0 ; i<bytescount; i++, pos++)
  {
     int cell=pos/ 4 ;
     if (cell>= ArraySize (code)) ArrayResize (code,cell+ 1 );
     int byte=pos% 4 ;
    code[cell] &= ~( 0xFF <<(byte* 8 ));    // обнуляем место под байт
    code[cell] |= value& 0xFF <<(byte* 8 ); // записываем байт
    value>>= 8 ;
  }  
   return (pos);
}
 
당신의 코드가 period_converter 스크립트에서 체크하는 것보다 나은 이유는 무엇입니까?
 
IgorM :
당신의 코드가 period_converter 스크립트에서 체크하는 것보다 나은 이유는 무엇입니까?
루프가 아니므로 표시기에 사용할 수 있다는 사실입니다.
 

다음과 같이 했습니다.

 #property indicator_chart_window

#import "user32.dll"
   int    RegisterWindowMessageA( string lpString);
   int    SetTimer( int hWnd, int nIDEvent, int uElapse, int & lpTimerFunc[]);
   bool   KillTimer( int hWnd, int uIDEvent);
#import "kernel32.dll"
   int    GetModuleHandleA( string lpModuleName);
   int    GetProcAddress( int hModule, string lpProcName);
int TimerId= 666 ;

//+------------------------------------------------------------------+
int init(){
   SetMyTimer( 1000 );   // интервал в миллисекундах
return ( 0 );
}
//+------------------------------------------------------------------+
int deinit(){
   KillMyTimer();
   Comment ( "" );
return ( 0 );
}
//+------------------------------------------------------------------+
int start(){
   int i,limit;
   limit = 1000 ;
   for (i=limit; i>= 0 ; i--){
       Comment ( "i = " ,i);
   }
   Print ( "цикл завершен...." );
return ( 0 );
}

int SetMyTimer( int interval)
{    
   int MT4InternalMsg= RegisterWindowMessageA( "MetaTrader4_Internal_Message" );
   int hWnd= WindowHandle ( Symbol (), Period ());
   int PostMsgAddr= GetProcAddress(GetModuleHandleA( "user32.dll" ), "PostMessageA" );
   int code[];
  AddBytes(code, 0x55 );   // push ebp
  AddBytes(code, 0x8B );   // move ebp,esp
  AddBytes(code, 0xEC );  
  AddBytes(code, 0x6A );   // push 01
  AddBytes(code, 0x01 );
  AddBytes(code, 0x6A );   // push 02
  AddBytes(code, 0x02 );
  AddBytes(code, 0x68 );   // push MT4InternalMsg
  AddBytes(code,MT4InternalMsg, 4 );
  AddBytes(code, 0x68 );   // push hWnd
  AddBytes(code,hWnd, 4 );
  AddBytes(code, 0xB8 );   // mov eax, PostMsgAddr
  AddBytes(code,PostMsgAddr, 4 );
  AddBytes(code, 0xFF );   // call eax
  AddBytes(code, 0xD0 );  
  AddBytes(code, 0x33 );   // xor eax, eax
  AddBytes(code, 0xC0 );
  AddBytes(code, 0x5D );   // pop ebp
  AddBytes(code, 0xC3 );   // ret
  
   return (SetTimer(hWnd, TimerId, interval, code) );
}
//---------------------------------------------------

bool KillMyTimer()
{
   return ( KillTimer( WindowHandle ( Symbol (), Period ()), TimerId) );
}
//+------------------------------------------------------------------+

int AddBytes( int & code[], int value, int bytescount= 1 )
{
   static int pos= 0 ;   // текущая позиция (в байтах)
   if ( ArraySize (code)== 0 ) pos= 0 ;
   for ( int i= 0 ; i<bytescount; i++, pos++)
  {
     int cell=pos/ 4 ;
     if (cell>= ArraySize (code)) ArrayResize (code,cell+ 1 );
     int byte=pos% 4 ;
    code[cell] &= ~( 0xFF <<(byte* 8 ));     // обнуляем место под байт
    code[cell] |= value& 0xFF <<(byte* 8 ); // записываем байт
    value>>= 8 ;
  }  
   return (pos);
}

로그에서 한 번:

11:02:31 테스트 USDCHF,H1: 성공적으로 로드됨
11:02:31 테스트 USDCHF,H1: 초기화됨
11:02:31 테스트 USDCHF,H1: 주기 완료....

댓글 왼쪽: i = 0

그것은 옳지 않아 ((((

 

얼마나 코드 자체에 무화과가 아닙니다! 표시기는 한 줄이면 충분합니다.

 #property indicator_chart_window
#include <WinUser32.mqh>
int nCounter = 0 ;
void start()
 {
   int hwndChart = WindowHandle ( Symbol (), 0 );
  SendMessageA(hwndChart, WM_COMMAND, 0x822C , NULL ); // <-- Этой строки.
  nCounter++;
   Comment (nCounter);
 }
 
Zhunko :

얼마나 많은 코드 자체에 무화과가 아닙니다! 표시기는 한 줄이면 충분합니다.

코드에는 먼저 틱 에뮬레이션이 있을 뿐만 아니라 각 틱에서 기록을 로드하여 차트를 강제로 업데이트합니다. 가끔 로그도 보나요? 여가 시간에 들러 무슨 일이 일어나고 있는지 확인하십시오. 예를 들어 하루에 일어날 일에 대해 생각해 보십시오. 특히 표시기의 여러 복사본이 실행 중인 경우. 나는 시스템과 인터넷 채널의 부하에 대해 침묵합니다.

코드에서 차트를 업데이트하는 대신 정확히 틱 에뮬레이션을 수행하면 루프가 발생하고(즉, 표시기가 멈추지 않고 시작됨) 이에 따라 터미널이 정지됩니다.

IgorM , 나는 매초마다 Print를 인쇄해야 합니다. 왜 한 번만 가지고 있는지 모르겠습니다. 아마도 운영 체제의 차이 때문일 것입니다. 나는 XP를 가지고 있습니다.

로그에 오류가 있습니까? PostMsgAddr이 0이 아닌지 확인하십시오.

 
Meat :

IgorM , 나는 매초마다 Print를 인쇄해야 합니다. 왜 한 번만 가지고 있는지 모르겠습니다. 아마도 운영 체제의 차이 때문일 것입니다. 나는 XP를 가지고 있습니다.

로그에 오류가 있습니까? PostMsgAddr이 0이 아닌지 확인하십시오.


win7이 있고 로그에 오류가 없습니다. 지금은 바쁩니다. 나중에 xp에서 컴퓨터를 재부팅할 수 있습니다. 운영 체제가 2개 있습니다.
 

예, 긴장을 풀 수 없습니다. 나는 방금 7 (Ultimate)을 시작했습니다. 모든 것이 그녀에게 효과적입니다. 그래서 당신에게 효과가없는 이유를 모르겠습니다 ...

 
Meat :

예, 긴장을 풀 수 없습니다. 나는 방금 7 (Ultimate)을 시작했습니다. 모든 것이 그녀에게 효과적입니다. 그래서 당신에게 효과가없는 이유를 모르겠습니다 ...

xp에서는 작동합니다. 매초 인쇄하지만 win7에서는 현재까지 업데이트된 최대값이 작동하지 않으므로 왜 작동하는지 모르겠습니다....
 
IgorM :
...왜 그것이 당신에게 효과가 있는지 모르겠습니다....


따라서 최종적으로 누가 옳고 누가 그른지를 결정하기 위해 7에 대한 다른 사람의 피드백을 들어야 합니다. :)

그건 그렇고, 위에서 내가 쓴 PostMsgAddr은 어떻습니까? 제로와 같지 않습니까?

 
Meat : 그런데 위에서 내가 쓴 PostMsgAddr은 어떻습니까? 제로와 같지 않습니까?

뒤에 두다

 int SetMyTimer( int interval)
{    
   int MT4InternalMsg= RegisterWindowMessageA( "MetaTrader4_Internal_Message" );
   int hWnd= WindowHandle ( Symbol (), Period ());
   int PostMsgAddr= GetProcAddress(GetModuleHandleA( "user32.dll" ), "PostMessageA" );
   Print ( "PostMsgAddr =" ,PostMsgAddr);
   int code[];
로그에있어 :

23:39:01 테스트 EURUSD,H1: 성공적으로 로드됨
23:39:01 테스트 EURUSD,H1: PostMsgAddr =1977398342
23:39:01 테스트 EURUSD,H1: 초기화됨
23:39:01 테스트 EURUSD,H1: 사이클이 끝났습니다....