2012/03/29

Sqlite3を使って相互のデータを確認できるか試してみた。

kartzさんにご指摘頂いた内容を訂正しました。2012/3/30
※2012/4/5作成したコードを変更しました。【sqlite3_wrapper_2.0.zip
※2012/4/7に追記しました。
テストの内容は、以下のとおりです。また、作成したコードは、ココにあります。
  1. MT4(A)のデータをコピーし、データベースに保存する。
  2. データベースからMT4(B)へデータを送る。
    ※イメージ的にはこんな感じになります。
334

DLLの追記

前に紹介したSqlite3のwrapperにSqlite3関数を直接操作する関数を追加しました。
※追加作成した関数には、_nを追記しています。なお、以下は抜粋したものです。
////////////////////////////////////////////////////////////////////////////
//int sqlite_query_n (int handle_db, string sql, int& cols[]);
//  handle : sqlite_open_n にて取得
//  sql         : クエリ
//  cols[ ]      : int cols[1];と設定。列数の合計を受け取る。
//  ※戻りデータのあるクリエを発行し、ハンドルを返す。
//  ※反復処理は、(sqlite_next_n,sqlite_get_*_n)を使用。
//  ※(sqlite_free_query_n)を使用しリセットをおこなう。
// ※戻り値は、実行用のハンドルhandel_qr
////////////////////////////////////////////////////////////////////////////
__declspec(dllexport) int __stdcall sqlite_query_n (int handle_db, const char *sql, int* cols){
    sqlite3 *s= (sqlite3 *)handle_db;
    sqlite3_stmt *stmt;
    int res;
    res = sqlite3_prepare (s, sql, strlen (sql), &stmt, NULL);
    if (res != SQLITE_OK) return -1;
     *cols = sqlite3_column_count (stmt);
    return (int)stmt;
}
////////////////////////////////////////////////////////////////////////////
//int sqlite_next_row_n (int handle_qr);
//  ※次の行を取得する 。
//  ※戻り値(1:あり 0:なし)
////////////////////////////////////////////////////////////////////////////
__declspec(dllexport) int __stdcall sqlite_next_row_n (int handle_qr){
    sqlite3_stmt *stmt = (sqlite3_stmt*)handle_qr;
    int ret;
    ret = sqlite3_step (stmt);
    return ret == SQLITE_ROW ? 1 : 0;
 //return ret;
}
///////////////////////////////////////////////////////////////////////////
//string sqlite_bind_*_n (int handle_qr,int index,* data);
// ※データの入力
//  ※int index 列番号 (1,2,3,4.....)
//  ※*  data  入力データ
//  ※戻り値 エラーコード
///////////////////////////////////////////////////////////////////////////
//文字
__declspec(dllexport) int  __stdcall sqlite_bind_text_n (int handle_qr,int index,const char *text){
    sqlite3_stmt *stmt = (sqlite3_stmt*)handle_qr;
    int ret;
    ret = sqlite3_bind_text(stmt,index,text,(int)strlen(text),SQLITE_STATIC);
    return ret;
}


MQL4の作成

【sqlite3.mqh】 Sqlite3wrapper.dllを使用するためのヘッダー
【Import_sqlite.mq4】 データベースにコピーするためのインジケータ
【export_sqlite.mq4】 データベースから値を取得する(今回は、HiとLowのみ)インジケータ
パラメータの説明
  • extern string Symb = "USDJPY";//通貨ペア名
  • extern int Tframe = 5 ;//タイムフレーム(1,5,15,30…)
  • extern string DB = "C:\\HistData.db" //DB名(絶対パス)
    ※ 通貨ペア名+タイムフレームでテーブル名を作成します。


セット

  1. 以下の様にセットしてください。
    【terminal.exe】と同じ位置にSqlite3.dll
    【expertsフォルダ】
      ┣【librariesフォルダ】にSqlite3wrapper.dll 
      ┣【include】にsqlite3.mqh
      ┗【indicators】にImport_sqlite.mq4、export_sqlite.mq4
  2. 2種類のMT4に同じようにセットします。
  3. データを抽出する側のMT4を起動させ、チャートを開き新規のデータを取得させます。
  4. Import_sqlite作動させ、指定した場所にDBが作成されたことを確認します。
  5. データを取得する側のMT4を起動させて、export_sqliteを作動させます。 
     


Build418への対応

現在、最新版のBuild418は、DLLからの戻り値がdoubleの場合にエラーが発生するとの報告が上がっています。そこで、Build418で使用する場合は、double型で取得している部分のコードを文字型で取得する様に変更してやる必要があります。以下がその変更部分です。
export_sqlite.mq4 コメント化されているコードと変更する。
//取得 for(i=0; i<limit; i++){    if(sqlite_next_row_n (handle_qr)==1){
   
// Hi[i] = StrToDouble(sqlite_get_col_n(handle_qr, 0));//Build418用
   
// Lw[i] = StrToDouble(sqlite_get_col_n(handle_qr, 1));//Build418用
    
Hi[i] = sqlite_get_col_double_n(handle_qr, 0);
    
Lw[i] = sqlite_get_col_double_n(handle_qr, 1);
 
}




挙動不安定

データをDBに送るImport_sqliteは、安定しているのですが、DBからデータを取得するexport_sqliteが、Buildのバージョンによって挙動が不安定になるようです。作動確認したBuildは、409、416、418です。(OS:XP)(・・?
  • 409:ヒストリカルデータは取得は出来るが、更新時にDLLエラーが発生しexport_sqliteが停止する。
  • 416:更新時に挙動が不安定になる。(データ抜けが発生する。)
  • 418:文字型で取得すれば416よりも挙動が安定する。 
※再確認します。(2012/3/30追記)
   確認した内容を記載します。
   ※418:ヒストリカルデータは取得できるが、更新時にDLLエラーが発生し停止する。
   ※409:更新時に挙動が不安定となった。不安定の原因は、足の作成タイミングのズレが原因?
   ※416:今回は、テストしていません。。orz

(2012/4/7追記)
現在添付してあるコードでの作動状況を動画で添付しておきます。
左側:データを取得しDBへ保存及びDBから自データを取得しチャートに表示したものです。
右側:左側のデータをDBから取得しチャートに表示したものです。
 動画より以下の点が確認できます。
  • 左側のチャートは、問題なく作動している。
  • 右側のチャートの指標も新規のBarが確立していれば問題なく作動する。
  • 左側のチャートのBarが確立後に右側のBarが確立すれば問題は起こらない。
  • 指標に問題が発生するのは、右側のチャートのBarが左側のBarよりも早く表示された時。
  • 誤作動が起こった箇所のデータは、Bar[2]のデータを表示している。
となっています。新規Barの発生タイミングのズレが何らかのバグを発生させているのは解りましたが、その後の対応策は現在のところ思いついていません。。。orz


まとめ

どんな目的でこれを使用するか?を考えてみると。
  • データの抜け確認用に使用すれば簡単に抜けが確認できそうです。
    rrt 
    上記は、週末・週初の取引時間が違うためにデータ抜けを起こした部分です。

export_sqliteの挙動を安定させようと試行錯誤してみましたが良い成果を上げることができませんでした。。orz