Emulation des ticks d'un EA/indicateur

 

Depuis longtemps, je cherche à mettre en place une émulation automatique des ticks à partir d'un Expert Advisor/indicateur (c'est-à-dire lui permettre de se "ticker" lui-même) sans utiliser de DLL ou de scripts écrits par lui-même. Un intérêt purement sportif, pour ainsi dire :) Bien que, peut-être, cela sera très utile pour quelqu'un, si son but n'est pas d'aller au-delà du fichier MQL, mais d'éviter les boucles (indicateurs en particulier).

Je dois utiliser du code machine, car je ne peux pas le faire avec les méthodes habituelles. Vous trouverez ci-dessous la variante finale du code.

Le conseiller expert définit une minuterie qui génère un tick dans son propre graphique à des intervalles spécifiés.

#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);
}
 
en quoi votre code est-il meilleur que le "ticker" du script period_converter?
 
IgorM:
En quoi votre code est-il meilleur que le "ticker" du script period_converter ?
Parce qu'il n'est pas bouclé et peut donc être utilisé dans les indicateurs.
 

J'ai fait ça :

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

dans le journal une fois :

11:02:31 test USDCHF,H1 : chargé avec succès
11:02:31 test USDCHF,H1 : initialisé
11:02:31 test USDCHF,H1 : cycle terminé....

commentaire à gauche : i = 0

quelque chose ne va pas ((((

 

C'est beaucoup de code ! Une ligne suffit pour un indicateur.

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

C'est beaucoup de code ! Une ligne suffit pour un indicateur.

Tout d'abord, votre code ne se contente pas d'émuler un tick, il met à jour de force le graphique avec l'historique correspondant à chaque tick. Ne regardez-vous même pas le log au moins une fois de temps en temps ? Jetez-y un coup d'œil à votre guise et voyez ce qui s'y passe. Et estimez ce qui sera là dans un jour ou deux. Sans parler de la charge sur votre système et votre canal Internet.

Si, au lieu de mettre à jour le graphique dans votre code, vous émulez le tick, cela entraînera des boucles (c'est-à-dire que l'indicateur démarrera sans s'arrêter) et, par conséquent, le terminal se bloquera.

IgorM, mon empreinte est émise toutes les secondes, comme il se doit. Je ne sais pas pourquoi vous ne l'avez qu'une fois... Peut-être à cause des différents systèmes d'exploitation... J'ai XP.

Y a-t-il une erreur dans le journal de bord ? Et vérifiez si votre PostMsgAddr est différent de zéro ?

 
Meat:

IgorM, mon empreinte est émise toutes les secondes, comme il se doit. Je ne sais pas pourquoi vous n'avez qu'une seule fois... Peut-être à cause des différents systèmes d'exploitation... J'ai XP.

Y a-t-il une erreur dans le journal de bord ? Et vérifiez si votre PostMsgAddr est différent de zéro ?


J'ai win7, pas d'erreur dans le journal, je suis occupé en ce moment, peut-être que je redémarrerai en xr plus tard - j'ai 2 systèmes d'exploitation.
 

Ne vous inquiétez pas, je viens d'utiliser la version 7 (Ultimate) moi-même. Tout fonctionne bien dessus, donc je ne sais pas pourquoi ça ne marche pas pour vous...

 
Meat:

Ne vous inquiétez pas, je viens d'utiliser la version 7 (Ultimate) moi-même. Tout fonctionne bien dessus, donc je ne sais pas pourquoi ça ne marche pas pour vous...

en hr fonctionne : imprime toutes les secondes, mais en win7 max avec les mises à jour à date ne fonctionne pas, donc je ne sais pas pourquoi ça marche pour vous....
 
IgorM:
...donc je ne sais pas pourquoi cela fonctionne pour vous....


Nous avons donc besoin d'entendre l'avis de quelqu'un d'autre sur les sept pour décider finalement qui a raison et qui a tort :)

Au fait, qu'en est-il du PostMsgAddr dont j'ai parlé plus haut ? N'est-il pas égal à zéro ?

 
Meat: Au fait, qu'en est-il du PostMsgAddr dont j'ai parlé plus haut ? N'est-elle pas égale à zéro ?

le mettre après.

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[];
le journal reçu :

23:39:01 test EURUSD,H1 : chargé avec succès
23:39:01 test EURUSD,H1 : PostMsgAddr =1977398342
23:39:01 test EURUSD,H1 : initialisé
23:39:01 test EURUSD,H1 : cycle terminé....

Raison: