banner
李大仁博客

李大仁博客

天地虽大,但有一念向善,心存良知,虽凡夫俗子,皆可为圣贤。

MT4でMQLを使用してRedisに接続するプラグイン

仕事で MT4 のデータを読み取り、Redis データベースに保存する必要があります。また、MT4 は Redis からデータを読み取り、注文のアカウントを切り替えます。 MT4 は MQL を使用して開発をサポートしており、標準のシステム DLL を呼び出してシステムコールを実現します。したがって、技術的な実装はそれほど難しくなく、MQL のインターフェース要件に従って対応する CPP コードを記述し、DLL にコンパイルするだけで必要な機能を実現できます。

Windows プラットフォームでは、Redis に接続するクライアントとして Hiredis を選択します。

MT4 接続 Redis ヘッダーファイル定義、 MT4RedisPlugin.h

#define MT4_REDIS_ERR -1 /* エラー */
#define MT4_REDIS_OK 0 /* OK */
#define MT4_REDIS_ERR_IO 1 /* 読み書きエラー */
#define MT4_REDIS_ERR_EOF 3 /* EOF */
#define MT4_REDIS_ERR_PROTOCOL 4 /* プロトコルエラー */
#define MT4_REDIS_ERR_OTHER 2 /* その他のエラー */

#define MT4_REDIS_CMD_SUCCESSED 0 /* 成功 */
#define MT4_REDIS_CMD_FAILED -1 /* 失敗 */

//---
#define MT4_EXPFUNC __declspec(dllexport)

//+------------------------------------------------------------------+
//| Redis が動作しているかテストする |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall RedisTest(const char* server, const int port);

//+------------------------------------------------------------------+
//| Redis コマンド "GET key" を実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC wchar_t* __stdcall RedisGet(const wchar_t* key);

//+------------------------------------------------------------------+
//| Redis コマンド "GET key" を実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC wchar_t* __stdcall RedisGetWithTimeout(const wchar_t* key,int timeout);

//+------------------------------------------------------------------+
//| Redis コマンド "SET key value" を実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall RedisSet(const wchar_t* key, const wchar_t* value);

//+------------------------------------------------------------------+
//| Redis コマンド "SET key value" を実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall RedisSetWithTimeout(const wchar_t* key, const wchar_t* value,int timeout);

//+------------------------------------------------------------------+
//| Redis コマンドを実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall RedisCommand(const wchar_t* command);

//+------------------------------------------------------------------+
//| Redis コマンドを実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall RedisCommandWithTimeout(const wchar_t* command,int timeout);

//+------------------------------------------------------------------+
//| char を WCHAR、wchar_t、LPWSTR などに変換する |
//+------------------------------------------------------------------+
static wchar_t * CStr2WStr(const char *cStr);

//+------------------------------------------------------------------+
//| WCHAR、wchar_t、LPWSTR を char に変換する |
//+------------------------------------------------------------------+
static char* WStr2CStr(const wchar_t *wchar);

//+------------------------------------------------------------------+
//| メッセージボックスを表示する |
//+------------------------------------------------------------------+
static void MT4RedisMsgBox(const wchar_t* msg);

Hiredis を使用して Redis データベースを読み取る

//+------------------------------------------------------------------+
//| Redis コマンド "GET key" を実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC wchar_t* __stdcall RedisGetWithTimeout(const wchar_t* key,int timeout)
{
// Windows ソケットオブジェクトを構築する
//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("Redisサーバーへの接続に失敗しました\[%s:%d\]\\n",REDIS\_SERVER,REDIS\_PORT);
        redisFree(context);
        return NULL;
    }

    // Redisコマンドを構築する
    // サイズを取得する
    size\_t len = wcslen(key) + 20;
    // コマンドの長さ
    if (len > COMMAND\_BUFFER) {
        printf("コマンドが長すぎます。コマンド文字列は%d未満でなければなりません",COMMAND\_BUFFER);
        return NULL;
    }
    // コマンドを構築する
    wchar\_t command\[COMMAND\_BUFFER\];
    // Redisコマンドを構築する
    wsprintf(command,L"GET %s",key);

    // 文字列変換
    const char\* command1 = WStr2CStr(command);

    // Redisコマンドを実行する
    printf("コマンドを実行する準備ができました\[%s\]\\n", command1);

    // コマンドを実行する
    redisReply\* reply = (redisReply\*)redisCommand(context, command1);

    // Redisの応答がない
    if( NULL == reply)
    {
        printf("コマンドの実行に失敗しました\[%s\]\\n",command1);
        redisFree(context);
        return NULL;
    }

    // 応答の状態
    if ( reply->type != REDIS\_REPLY\_STRING)
    {
        printf("コマンドの実行に失敗しました\[%s\]\\n",command1);
        freeReplyObject(reply);
        redisFree(context);
        return NULL;
    }
    printf("値 \\"%s\\" は \\"%s\\" です\\n", key, reply->str);

    // 文字列変換
    wchar\_t \* result = CStr2WStr(reply->str);

    // Replyオブジェクトを解放する
    freeReplyObject(reply);
    // Redis接続を解放する
    redisFree(context);
    printf("コマンドの実行に成功しました\[%s\]\\n", command1);
    delete command1;
    command1 = NULL;
    // 結果の文字列を返す
    return result;

}

Hiredis を使用して Redis データベースに書き込む

//+------------------------------------------------------------------+
//| Redis コマンド "SET key value" を実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall RedisSetWithTimeout(const wchar_t* key, const wchar_t* value, int timeout)
{
// Redis コマンドを構築する
// サイズを取得する
size_t len = wcslen(key)+wcslen(value) + 20;
// コマンドの長さ
if (len > COMMAND_BUFFER) {
printf ("コマンドが長すぎます。コマンド文字列は % d 未満でなければなりません",COMMAND_BUFFER);
return MT4_REDIS_CMD_FAILED;
}
// コマンドを構築する
wchar_t command[COMMAND_BUFFER];
// Redis コマンドを構築する
wsprintf(command,L"SET %s %s",key,value);
return RedisCommandWithTimeout(command,timeout);
}

Hiredis を使用して Redis コマンドを実行する

//+------------------------------------------------------------------+
//| Redis コマンドを実行する |
//+------------------------------------------------------------------+
MT4_EXPFUNC int __stdcall RedisCommandWithTimeout(const wchar_t* command,int timeout)
{
// Windows ソケットオブジェクトを構築する
//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("Redisサーバーへの接続に失敗しました\[%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("コマンドが長すぎます。コマンド文字列は%d未満でなければなりません",COMMAND\_BUFFER);
        redisFree(context);
        return MT4\_REDIS\_CMD\_FAILED;
    }

    // 文字列変換
    const char\* command1 = WStr2CStr(command);

    // Redisコマンドを実行する
    printf("コマンドを実行する準備ができました\[%s\]\\n", command1);

    // コマンドを実行する
    redisReply\* reply = (redisReply\*)redisCommand(context, command1);

    // Redisの応答がない
    if( NULL == reply)
    {
        printf("コマンドの実行に失敗しました\[%s\]\\n",command1);
        redisFree(context);
        return MT4\_REDIS\_CMD\_FAILED;
    }

    // 応答の状態
    if( !(reply->type == REDIS\_REPLY\_STATUS && \_stricmp(reply->str,"OK")==0))
    {
        printf("コマンドの実行に失敗しました\[%s\]\\n",command1);
        freeReplyObject(reply);
        redisFree(context);
        return MT4\_REDIS\_CMD\_FAILED;
    }

    // Replyオブジェクトを解放する
    freeReplyObject(reply);
    // Redis接続を解放する
    redisFree(context);
    printf("コマンドの実行に成功しました\[%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
//+------------------------------------------------------------------+
//| エキスパート初期化関数 |
//+------------------------------------------------------------------+
int init()
{
Print("GO GO GO");

string hello;
hello = HelloWorld("1234abc");
Print ("結果は", hello);

string test;
test = RedisTest("127.0.0.1",6379);
Print ("テスト結果は", test);

int cmd1;
cmd1 = RedisCommand("set KEYabc VALUE123");
Print ("RedisCommand テスト =", cmd1);

int cmd2;
cmd2 = RedisCommandWithTimeout("set KEYabc VALUE123",10000);
Print ("RedisCommandWithTimeout テスト =", cmd2);

string key1 = "key1";
string value1 = "value1";
int set1 = RedisSet(key1,value1);
Print ("RedisSet テスト =", set1);

string key2 = "key2";
string value2 = "value2";
int timeout = 10000;
int set2 = RedisSetWithTimeout(key2,value2,timeout);
Print ("RedisSetWithTimeout テスト =", set2);

string get1 = RedisGet(key1);
Print ("RedisGet テスト =", get1);

string get2 = RedisGetWithTimeout(key2,timeout);
Print ("RedisGetWithTimeout テスト =", get2);

string key3 = "key3";
string get3 = RedisGet(key3);
Print ("RedisGet テスト =", get3);

string key4 = "key4";
string get4 = RedisGet(key4);
Print ("RedisGet テスト =", get4);
//---
return(0);
}
//+------------------------------------------------------------------+
//| 配列関数の呼び出し |
//+------------------------------------------------------------------+
int start()
{
return(0);
}
//+------------------------------------------------------------------+

完全なコードのアドレス https://github.com/limccn/mt4-redis

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。