工作中需要将MT4的数据读取并且存储到Redis数据库中去,同时MT4读取Redis当中的数据用于下单的切换账户。
MT4支持使用MQL进行开发,通过调用标准的系统DLL实现系统调用,因此技术实现并不是太难,只需要按MQL的接口要求编写相应的CPP代码
编译成DLL即可实现所需要的功能。
在Windows平台上,连接Redis的客户端选用Hiredis作为连接客户端lib。
MT4 连接Redis 头文件定义,
MT4RedisPlugin.h
#define MT4_REDIS_ERR -1 /* Error */#define MT4_REDIS_OK 0 /* OK */#define MT4_REDIS_ERR_IO 1 /* error in read or write */#define MT4_REDIS_ERR_EOF 3 /* eof */#define MT4_REDIS_ERR_PROTOCOL 4 /* protocol error */#define MT4_REDIS_ERR_OTHER 2 /* something else */#define MT4_REDIS_CMD_SUCCESSED 0 /* Successed */#define MT4_REDIS_CMD_FAILED -1 /* Failed *///---#define MT4_EXPFUNC __declspec(dllexport)//+------------------------------------------------------------------+//| Test Redis if is working |//+------------------------------------------------------------------+MT4_EXPFUNC int __stdcall RedisTest(const char* server, const int port);//+------------------------------------------------------------------+//| Excute Redis Command "GET key" |//+------------------------------------------------------------------+MT4_EXPFUNC wchar_t* __stdcall RedisGet(const wchar_t* key);//+------------------------------------------------------------------+//| Excute Redis Command "GET key" |//+------------------------------------------------------------------+MT4_EXPFUNC wchar_t* __stdcall RedisGetWithTimeout(const wchar_t* key,int timeout);//+------------------------------------------------------------------+//| Excute Redis Command "SET key value" |//+------------------------------------------------------------------+MT4_EXPFUNC int __stdcall RedisSet(const wchar_t* key, const wchar_t* value);//+------------------------------------------------------------------+//| Excute Redis Command "SET key value" |//+------------------------------------------------------------------+MT4_EXPFUNC int __stdcall RedisSetWithTimeout(const wchar_t* key, const wchar_t* value,int timeout);//+------------------------------------------------------------------+//| Excute Redis Command |//+------------------------------------------------------------------+MT4_EXPFUNC int __stdcall RedisCommand(const wchar_t* command);//+------------------------------------------------------------------+//| Excute Redis Command |//+------------------------------------------------------------------+MT4_EXPFUNC int __stdcall RedisCommandWithTimeout(const wchar_t* command,int timeout);//+------------------------------------------------------------------+//| char to WCHAR 、wchar_t、LPWSTR etc |//+------------------------------------------------------------------+static wchar_t * CStr2WStr(const char *cStr);//+------------------------------------------------------------------+//| WCHAR 、wchar_t、LPWSTR to char |//+------------------------------------------------------------------+static char* WStr2CStr(const wchar_t *wchar);//+------------------------------------------------------------------+//| Show Messagebox |//+------------------------------------------------------------------+static void MT4RedisMsgBox(const wchar_t* msg);
使用Hiredis读取Redis数据库
//+------------------------------------------------------------------+//| Excute Redis Command "GET key" |//+------------------------------------------------------------------+MT4_EXPFUNC wchar_t* __stdcall RedisGetWithTimeout(const wchar_t* key,int timeout) { // 构造windows socket对象 //WSADATA wsaData; //WSAStartup(MAKEWORD(2,1), &wsaData); // 设置超时 struct timeval tv; tv.tv_sec = timeout/1000; tv.tv_usec = timeout *1000; redisContext* context = redisConnectWithTimeout(REDIS_SERVER,REDIS_PORT,tv); //判断连接是否有错误 if (context->err) { printf("Failed to connect redis server[%s:%d]\n",REDIS_SERVER,REDIS_PORT); redisFree(context); return NULL; } //构造Redis命令 //获取size size_t len = wcslen(key) + 20; //命令长度 if (len > COMMAND_BUFFER) { printf("Command is too long, Command string must short than %d",COMMAND_BUFFER); return NULL; } // 构建Comand wchar_t command[COMMAND_BUFFER]; //构造Redis命令 wsprintf(command,L"GET %s",key); //字符串转换 const char* command1 = WStr2CStr(command); //执行Redis命令 printf("Ready to execute command[%s]\n", command1); // 执行命令 redisReply* reply = (redisReply*)redisCommand(context, command1); //没有Redis响应 if( NULL == reply) { printf("Failed to execute command[%s]\n",command1); redisFree(context); return NULL; } //响应状态 if ( reply->type != REDIS_REPLY_STRING) { printf("Failed to execute command[%s]\n",command1); freeReplyObject(reply); redisFree(context); return NULL; } printf("The value of \"%s\" is \"%s\"\n", key, reply->str); //字符串转换 wchar_t * result = CStr2WStr(reply->str); //释放Reply对象 freeReplyObject(reply); //释放Redis连接 redisFree(context); printf("Succeed to execute command[%s]\n", command1); delete command1; command1 = NULL; //返回结果字符串 return result; }
使用Hiredis写入Redis数据库
//+------------------------------------------------------------------+//| Excute Redis Command "SET key value" |//+------------------------------------------------------------------+MT4_EXPFUNC int __stdcall RedisSetWithTimeout(const wchar_t* key, const wchar_t* value, int timeout) { //构造Redis命令 //获取size size_t len = wcslen(key)+wcslen(value) + 20; //命令长度 if (len > COMMAND_BUFFER) { printf("Command is too long, Command string must short than %d",COMMAND_BUFFER); return MT4_REDIS_CMD_FAILED; } // 构建Comand wchar_t command[COMMAND_BUFFER]; //构造Redis命令 wsprintf(command,L"SET %s %s",key,value); return RedisCommandWithTimeout(command,timeout); }
使用Hiredis执行Redis命令
//+------------------------------------------------------------------+//| Excute Redis Command |//+------------------------------------------------------------------+MT4_EXPFUNC int __stdcall RedisCommandWithTimeout(const wchar_t* command,int timeout) { // 构造windows socket对象 //WSADATA wsaData; //WSAStartup(MAKEWORD(2,1), &wsaData); // 设置超时 struct timeval tv; tv.tv_sec = timeout/1000; tv.tv_usec = timeout *1000; redisContext* context = redisConnectWithTimeout(REDIS_SERVER,REDIS_PORT,tv); //判断连接是否有错误 if (context->err) { printf("Failed to connect redis server[%s:%d]\n",REDIS_SERVER,REDIS_PORT); redisFree(context); return MT4_REDIS_CMD_FAILED; } // 命令长度 size_t len = wcslen(command) + 1; if (len > COMMAND_BUFFER) { printf("Command is too long, Command string must short than %d",COMMAND_BUFFER); redisFree(context); return MT4_REDIS_CMD_FAILED; } //字符串装换 const char* command1 = WStr2CStr(command); //执行Redis命令 printf("Ready to execute command[%s]\n", command1); // 执行命令 redisReply* reply = (redisReply*)redisCommand(context, command1); //没有Redis响应 if( NULL == reply) { printf("Failed to execute command[%s]\n",command1); redisFree(context); return MT4_REDIS_CMD_FAILED; } //响应状态 if( !(reply->type == REDIS_REPLY_STATUS && _stricmp(reply->str,"OK")==0)) { printf("Failed to execute command[%s]\n",command1); freeReplyObject(reply); redisFree(context); return MT4_REDIS_CMD_FAILED; } //释放Reply对象 freeReplyObject(reply); //释放Redis连接 redisFree(context); printf("Succeed to execute command[%s]\n", command1); delete command1; command1 = NULL; //返回成功状态 return MT4_REDIS_CMD_SUCCESSED; }
测试MQL代码
//+------------------------------------------------------------------+//| DLLSampleTester.mq4 |//| Copyright ? 2005-2014, MetaQuotes Software Corp. |//| http://www.metaquotes.net/ |//+------------------------------------------------------------------+#property copyright "Copyright ? 2005-2014, MetaQuotes Software Corp."#property link "http://www.metaquotes.net/"#import "MT4RedisPlugin.dll"string HelloWorld(string);string RedisGet(string);string RedisGetWithTimeout(string,int);int RedisSet(string,string);int RedisSetWithTimeout(string, string, int);int RedisCommand(string);int RedisCommandWithTimeout(string,int);int RedisTest(string,int);#import#define TIME_INDEX 0#define OPEN_INDEX 1#define LOW_INDEX 2#define HIGH_INDEX 3#define CLOSE_INDEX 4#define VOLUME_INDEX 5//+------------------------------------------------------------------+//| expert initialization function |//+------------------------------------------------------------------+int init() { Print("GO GO GO"); string hello; hello = HelloWorld("1234abc"); Print("result is", hello); string test; test = RedisTest("127.0.0.1",6379); Print("test result is", test); int cmd1; cmd1 = RedisCommand("set KEYabc VALUE123"); Print("RedisCommand test = ", cmd1); int cmd2; cmd2 = RedisCommandWithTimeout("set KEYabc VALUE123",10000); Print("RedisCommandWithTimeout test = ", cmd2); string key1 = "key1"; string value1 = "value1"; int set1 = RedisSet(key1,value1); Print("RedisSet test = ", set1); string key2 = "key2"; string value2 = "value2"; int timeout = 10000; int set2 = RedisSetWithTimeout(key2,value2,timeout); Print("RedisSetWithTimeout test = ", set2); string get1 = RedisGet(key1); Print("RedisGet test = ", get1); string get2 = RedisGetWithTimeout(key2,timeout); Print("RedisGetWithTimeout test = ", get2); string key3 = "key3"; string get3 = RedisGet(key3); Print("RedisGet test = ", get3); string key4 = "key4"; string get4 = RedisGet(key4); Print("RedisGet test = ", get4);//--- return(0); }//+------------------------------------------------------------------+//| array functions call |//+------------------------------------------------------------------+int start() { return(0); }//+------------------------------------------------------------------+
完整的代码地址
https://github.com/limccn/mt4-redis
--------------------------------------------------------------------------------------
- 版权声明:
- 如在本页面内无特别说明,本文内容均为[李大仁博客]原创,本文版权归[李大仁博客]所有。
- 欢迎转载,转载请务必在文章页面明显位置提供原文链接并注明出处。欢迎您在转载本文时保留本段声明。
- 文章标题:
MT4使用MQL连接Redis的插件
- 独立博客:
李大仁博客
- 永久链接:
http://www.lidaren.com/archives/1678
--------------------------------------------------------------------------------------
以上内容由博客自动发布工具自动发布,最终显示内容和效果会与原文内容有所偏差,敬请谅解。
转载请注明原文地址: https://ju.6miu.com/read-1307920.html