模仿EA/指示器的刻度线

 

长久以来,我的目标是实现自动模拟专家顾问/指标的刻度(即让它自己 "打勾"),而不使用自己编写的DLL或脚本。 纯粹是体育兴趣,可以这么说 :) 不过,如果某人的目标不是超越MQL-文件,而是避免循环(特别是指标),也许它将非常有用。

我必须使用一些机器代码,因为我不能用通常的方法来做。下面是代码的最终变体。

专家顾问设置了一个计时器,以指定的时间间隔在自己的图表中生成一个刻度。

#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 脚本的 "ticker "好在哪里?
 
IgorM:
你的代码比period_converter脚本中的 "ticker "好在哪里?
因为它不是循环的,因此可以在指标中使用。
 

我这样做了。

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

那是一个很大的代码!对于一个指标来说,一条线就足够了。

首先,你的代码不仅仅是模拟一个tick,它在每一个tick都强行更新图表中的相应历史记录。 你是否至少偶尔会看一下日志? 闲暇时看一下,看看那里发生了什么。并估计一天左右后会有什么。更不用说对你的系统和互联网通道的负荷了。

如果你不在代码中更新图表,而是模拟tick,就会导致循环(即指标会不停地启动),相应地,终端会挂起。

IgorM,我的Print每秒钟都在输出,应该是这样的。我不知道为什么你只有一次...可能是因为不同的操作系统...我有XP。

日志中是否有任何错误?并检查你的PostMsgAddr是否为零?

 
Meat:

IgorM,我的Print每秒钟都在输出,应该是这样的。我不知道为什么你只有一次...也许是因为操作系统的差异...我有XP。

日志中是否有任何错误?并检查你的PostMsgAddr是否为零?


我有win7系统,日志中没有错误,现在很忙,也许以后会重启到xr系统 - 我有两个操作系统
 

不用麻烦了,我自己刚刚运行了7(终极版)。它的一切工作都很正常,所以我不知道为什么它对你不起作用......

 
Meat:

不用麻烦了,我自己刚刚运行了7(终极版)。它的一切工作都很正常,所以我不知道为什么它对你不起作用......

在hr中工作:每秒打印,但在win7中最大的更新日期不工作,所以不知道为什么它对你有用....。
 
IgorM:
...所以不知道为什么它对你有用....


所以我们需要听听别人对七夕的反馈,以最终决定谁对谁错 :)

顺便问一下,我上面写的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:周期完成....