Bir EA/göstergeden kenelerin öykünmesi

 

Bir EA/göstergeden (yani, kendi kendini "işaretleyebilmesi" için) otomatik tik öykünmesini kendi kendine yazılan DLL'leri kullanmaya veya komut dosyalarını çalıştırmaya başvurmadan uygulamak uzun zamandır bir hedef olmuştur. Tamamen sportif ilgi, tabiri caizse :) Görev MQL dosyasının ötesine geçmek değilse ve kodu (özellikle göstergeler) döngüye sokmak imkansızsa, birisi için çok yararlı olsa da.

Genel olarak, bunu olağan yollarla yapmak imkansız, bu yüzden kısmen makine kodunu yazmak zorunda kaldım. Aşağıda ortaya çıkan sürümdür.

EA, grafiğinde belirli aralıklarla bir onay işareti oluşturan bir zamanlayıcı ayarlar .

 #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);
}
 
kodunuz neden period_converter betiğinden işaretlemekten daha iyidir?
 
IgorM :
kodunuz neden period_converter betiğinden işaretlemekten daha iyi?
Döngüsel olmaması ve buna bağlı olarak göstergelerde kullanılabilmesi.
 

şöyle yaptı:

 #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);
}

günlükte bir kez:

11:02:31 USDCHF,H1 testi: başarıyla yüklendi
11:02:31 USDCHF,H1 testi: başlatıldı
11:02:31 USDCHF,H1 testi: döngü tamamlandı....

sol yorum: i = 0

bu doğru değil ((((

 

Kendi başına bir incir değil, bir kod ne kadar! Gösterge için bir satır yeterlidir.

 #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 :

Kendine bir incir değil, kaç tane bir kod! Gösterge için bir satır yeterlidir.

Kodunuzda, ilk olarak, yalnızca bir kene öykünmesi değil, aynı zamanda her bir tike karşılık gelen geçmiş yüklemesiyle grafiğin zorunlu bir güncellemesi vardır. Bazen günlük kaydına bile bakar mısın? Boş zamanlarınızda uğrayın ve neler olduğunu görün. Ve örneğin bir gün içinde ne olacağını düşünün. Özellikle göstergenin birkaç kopyası çalışıyorsa. Sistemin yükü ve İnternet kanalı hakkında sessizim.

Kodunuzda, grafiği güncellemek yerine, tam olarak kene öykünmesini yaparsanız, bu bir döngüye (yani gösterge durmadan başlar) ve buna bağlı olarak terminalin donmasına neden olur.

IgorM , olması gerektiği gibi her saniye Print yazdırırım. Neden sadece bir kez sahip olduğunuzu bilmiyorum... Belki işletim sistemlerindeki farklılıklardan dolayı... Bende XP var.

Günlükte herhangi bir hata var mı? Ve PostMsgAddr'nizin sıfır olmadığını kontrol edin.

 
Meat :

IgorM , olması gerektiği gibi her saniye Print yazdırırım. Neden sadece bir kez sahip olduğunuzu bilmiyorum... Belki işletim sistemlerindeki farklılıklardan dolayı... Bende XP var.

Günlükte herhangi bir hata var mı? Ve PostMsgAddr'nizin sıfır olmadığını kontrol edin.


Win7'im var, günlükte hata yok, şu anda meşgul, belki biraz sonra bilgisayarı xp'de yeniden başlatırım - 2 işletim sistemim var
 

Evet, zorlanamazsınız, ben kendim yediyi (Ultimate) başlattım. Her şey onun üzerinde harika çalışıyor. Bu yüzden senin için neden işe yaramadığını bilmiyorum ...

 
Meat :

Evet, zorlanamazsınız, ben kendim yediyi (Ultimate) başlattım. Her şey onun üzerinde harika çalışıyor. Bu yüzden senin için neden işe yaramadığını bilmiyorum ...

xp'de çalışır: her saniye yazdırır, ancak win7'de bu güne ait güncellemelerle maksimum çalışmaz, bu yüzden neden sizin için çalıştığını bilmiyorum ....
 
IgorM :
...bu yüzden senin için neden işe yaradığını bilmiyorum...


Bu yüzden nihayet kimin haklı kimin haksız olduğuna karar vermek için yedi hakkında başka birinin geri bildirimini duymamız gerekiyor :)

Bu arada, yukarıda yazdığım PostMsgAddr ne olacak? sıfıra eşit değil mi?

 
Meat : Bu arada yukarıda yazdığım PostMsgAddr ne olacak? sıfıra eşit değil mi?

sonra koymak

 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[];
günlüğe girdi:

23:39:01 EURUSD testi,H1: başarıyla yüklendi
23:39:01 EURUSD testi,H1: PostMsgAddr =1977398342
23:39:01 EURUSD testi,H1: başlatıldı
23:39:01 EURUSD testi,H1: döngü bitti....