我做了个多种登录模式的重连脚本。EA暂时没弄。有空交流下。
//+------------------------------------------------------------------+ //| 断线自动重连脚本.mq4 | //| "ldj" | //| "http://www.fxvip.net" | //+------------------------------------------------------------------+ //scripts//脚本文件 #property copyright "ldj" #property link "http://www.fxvip.net" #property show_inputs //自动登录准备 //把要登录的账号添加到收藏夹,并保证列在第一位。 extern string 邮件标记字符串="EA"; extern string 所有参数单位为秒="以下参数均折算为妙"; extern int 时差=18000; //本地时间与服务器时间的时间差,本地时间迟于服务器时间其值为负。单位秒。 extern int 允许时差=120;//允许服务器行情报价停滞的时间,建议设置2分钟即120秒。 extern int 检测间隔=20;//单位秒,不应小于20秒。 extern bool 邮件报警=false; extern bool 声音报警=false; //0、不自动登录。1、重新扫描服务器。2、重新登录第一个服务器。3、登录收藏夹第一个账号4、登录导航窗第一个账号 extern int 重连方式=1; int ServerNum=0; #include <WinUser32.mqh> #import "user32.dll" int GetParent( int hWnd ); int GetDlgItem( int hDlg, int nIDDlgItem ); int GetLastActivePopup( int hWnd ); int GetAncestor(int hWnd,int gaFlags);//GetAncestor(HWND hwnd,UINT gaFlags); #import #define VK_HOME 0x24 #define VK_DOWN 0x28 #define VK_ENTER 0x0D #define PAUSE 1000 int LoginSleep=120; //不小于2分钟,避免频繁发送登录请求 int MailSleep=120; //不小于2分钟,避免频繁发送邮件 datetime LoginTime,MailTime; //+------------------------------------------------------------------+ //| script program init function | //+------------------------------------------------------------------+ void init() { LoginTime=TimeLocal(); MailTime=TimeLocal(); if(检测间隔<10)检测间隔=10; //避免频繁检测系统资源消耗过多! return; } //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ void start() { if ( !IsDllsAllowed() ) { Alert( "禁止调用DLL文件" ); return; } string 正文; double T; int week; while(IsStopped()==false)//如果没有接到脚本终止命令则一直运行 { 正文="服务器时间:"+TimeToStr(TimeCurrent())+"\n本地的时间:"+TimeToStr(TimeLocal())+"\n"+AccountCompany()+"平台"+"账号为:"+AccountNumber()+"的账户"; T=(TimeLocal()-TimeCurrent())/360.0; Comment("服务器时间:",TimeToStr(TimeCurrent(),TIME_SECONDS), "\n本地的时间:",TimeToStr(TimeLocal(),TIME_SECONDS), "\n参考时差值:",MathRound(T)*360); week=TimeDayOfWeek(TimeLocal()-时差); if(week>=1 && week<=5)//服务器时间为 星期一 至 星期五,有星期天或星期六 K线的平台可适当修改。 { if ((TimeLocal()-TimeCurrent()-时差)>允许时差) { if (LoginTime+LoginSleep<TimeLocal()) { LoginTime=TimeLocal(); switch(重连方式) { case 0 : break; case 1 : ReConnecter();break; case 2 : ReConnecterN(ServerNum);break; case 3 : ReLogin(1);break; case 4 : ReLogin2();break; default : break; } } //正文=AccountCompany()+"平台"+"账号为:"+AccountNumber()+"的账户"; if (声音报警==true) Alert("从服务器上获取行情数据超时"); if (邮件报警==true && MailTime+MailSleep<TimeLocal()) { SendMail("从服务器上获取行情数据超时",正文+"\n从服务器上获取行情数据超时及时处理\n"+邮件标记字符串); MailTime=TimeLocal(); } Sleep(检测间隔*1000); } } if(IsConnected()==false) { if (LoginTime+LoginSleep<TimeLocal()) { LoginTime=TimeLocal(); switch(重连方式) { case 0 : break; case 1 : ReConnecter();break; case 2 : ReConnecterN(ServerNum);break; case 3 : ReLogin(1);break; case 4 : ReLogin2();break; default : break; } } //正文=AccountCompany()+"平台"+"账号为:"+AccountNumber()+"的账户"; if (声音报警==true) Alert("服务器断线"); if (邮件报警==true && MailTime+MailSleep<TimeLocal()) { SendMail("服务器连接中断",正文+"\n与服务器连接中断请及时处理\n"+邮件标记字符串); MailTime=TimeLocal(); } Sleep(检测间隔*1000); } Sleep(1*1000); } Comment(""); return(0); } //+------------------------------------------------------------------+
一个帖子贴不下
//+------------------------------------------------------------------+ //| script program ReLogin function | //+------------------------------------------------------------------+ //在位于窗口的行数数我的最爱标签导航帐户连接 void ReLogin( int Num ) { int hwnd = WindowHandle(Symbol(), Period()); //当前图表的句柄 (Handle) int hwnd_parent = 0; while (!IsStopped())//如果没有接到脚本终止命令则一直运行 { hwnd = GetParent(hwnd);//当前图表的父窗口句柄(Handle) if (hwnd == 0) break; //句柄等于0退出while循环 hwnd_parent = hwnd; } if (hwnd_parent != 0) //获得收藏夹句柄 { hwnd = GetDlgItem(hwnd_parent, 0xE81C); //59420 查找导航窗口句柄 hwnd = GetDlgItem(hwnd, 0x52); //82 选择导航窗口 * hwnd = GetDlgItem(hwnd, 0x8A70); //35440 获得收藏夹窗口句柄 PostMessageA(hwnd, WM_KEYDOWN, VK_HOME,0); //选择导航收藏夹第一个账号,上线最喜爱的收藏夹窗口导航 while (Num > 1) { PostMessageA(hwnd, WM_KEYDOWN,VK_DOWN, 0); //转移到所需行 Num--; } PostMessageA(hwnd, WM_KEYDOWN, VK_ENTER, 0); //输出enter 打开登录窗口 Sleep(PAUSE); // 等待1秒 hwnd = GetLastActivePopup(hwnd_parent); //选择登录窗口 //GetLastActivePopup**该函数确定指定窗口中的哪一个弹出式窗口是最近活动的窗口。 PostMessageA(hwnd, WM_KEYDOWN, VK_ENTER, 0); //输出enter 确认登录 } return; } //+------------------------------------------------------------------+ //| script program Login2 function | //+------------------------------------------------------------------+ void ReLogin2() { //导航窗口中第一个账号登录; int hwnd = WindowHandle(Symbol(), Period()); int hwnd_parent = 0; while (!IsStopped()) { hwnd = GetParent(hwnd); if (hwnd == 0) break; hwnd_parent = hwnd; } if (hwnd_parent != 0) // { PostMessageA(hwnd_parent, WM_COMMAND, 35429, 0); // Sleep(PAUSE); // hwnd = GetLastActivePopup(hwnd_parent); // PostMessageA(hwnd, WM_KEYDOWN, VK_ENTER, 0); // } return; } //+------------------------------------------------------------------+ //| script program ReConnecter function | //+------------------------------------------------------------------+ void ReConnecter() { int hwnd = WindowHandle(Symbol(), Period()); //当前图表的句柄 (Handle) int hwnd_parent = 0; while (!IsStopped())//如果没有接到脚本终止命令则一直运行 获得mt4进程句柄 { hwnd = GetParent(hwnd);//当前图表的父窗口句柄(Handle) if (hwnd == 0) break; //句柄等于0退出while循环 hwnd_parent = hwnd; } //int hMetaTrader = GetAncestor(WindowHandle(Symbol(),Period()),2); if (hwnd_parent != 0) { SendMessageA (hwnd_parent, WM_COMMAND, 37400, 0);//发送扫描服务器命令; } return; } //+------------------------------------------------------------------+ //| script program ReConnecter function | //+------------------------------------------------------------------+ void ReConnecterN(int S_Num) { int hwnd = WindowHandle(Symbol(), Period()); //当前图表的句柄 (Handle) int hwnd_parent = 0; while (!IsStopped())//如果没有接到脚本终止命令则一直运行 获得mt4进程句柄 { hwnd = GetParent(hwnd);//当前图表的父窗口句柄(Handle) if (hwnd == 0) break; //句柄等于0退出while循环 hwnd_parent = hwnd; } //int hMetaTrader = GetAncestor(WindowHandle(Symbol(),Period()),2); if (hwnd_parent != 0) { int Sdig=33900+S_Num; Sdig=SendMessageA (hwnd_parent, WM_COMMAND, Sdig, 0);//发送扫描服务器命令; Print("Sdig=",Sdig); } return; } //+------------------------------------------------------------------+
1、导航-->收藏夹-->第一个账号登陆
2、导航-->常用 -->第一个账号登陆
3、发送扫描服务器指令重连指令(软件右下角)
4、发送指定序列中某个编号的服务器重连指令(软件右下角)
另外我觉得最好不要用EA来弄,EA在启动MT4的时候就开始工作了。这时候MT4还没有正常登陆可能会造成发送重新登录请求过于频繁。
如果要用EA来自动登录,我觉得需要解决一个控制问题。
1、重新启动MT4后等待MT4正常连接后再运行检测和自动重连工作。
我是这样想的。
static datetime next_connect; int init() { next_connect = TimeCurrent() + 10; } int start() { datetime curr_time; curr_time = TimeCurrent(); if (next_current < curr_time) { // 重新连接mt4服务器. ... ... next_current = curr_time + 10; } ... ... }
用next_connect来定义,每隔10分钟重新连一次服务器。
只需要ea的start()中增加一次判断,就可以实现定时重新登陆的功能。
这样处理后,即使电脑重新启动,也可以继续执行ea。减少人工操作的步骤。
y2k_connect 写道 >>
只有mt4系统将新的报价发到ea后,ea才能够启动运行。因此,个人认为ea中不需要检测mt4是否已经登陆的问题。
当然了,如果是其它系统就不能这样做了。这是因为,mt4将行情服务器和交易服务器设置在一起。其它软件的设置,基本上都不在一起。
因此,在其它交易商中交易时,需要检测与交易服务器连接是否正常的问题。
我想你的逻辑不对。
在自动断线检测重连这个问题中,是要解决断线或者假死(没有行情数据到达)然后让系统重现登录下。
而当断线或者假死的时候是没有tick到达的,因此tick出发的start()函数就不能运行了,这样里面的代码就不可能再执行了。
所以必须把检测和重连的代码放在
while(IsStopped()==false)
这个死循环里面才可以。不然都没有tick了,EA根本就不执行任何代码了
原程序是ReConnecter.mq4脚本程序. 用google将俄文注释翻译成中文.
由于mt4重新启动后, 脚本程序不能自动运行, 而ea是可以的, 因此希望将其改写到ea中.
所以希望能够明白每行代码的具体意义, 了解该脚本程序会受到何种限制.
原文: ReConnecter - A Script for Periodical Reconnections
Login()中 if (hwnd_parent != 0) {... ...} 那段代码, 可能分析的有问题. 麻烦大家帮忙看看.
谢谢!