2014/09/05

なんとな~くWebRequest()が使ってみたくなって。。。イベントタイマーを作ってみました。

新MT4で新たに追加されたWebRequest()関数を使うことで、外部のサーバーにリクエストを送ることが可能となりました。(DLLを使用したり、ほかの言語を使用すれば、もちろん可能ですが。。^^;)ということで、今回は、DLLや多言語を使用することなく、外部サーバーから指標データを取得し、表示させてみました。

準 備

まず、WebRequest()関数のリファレンスを確認すると、この関数を使用する場合は、【ツール(T)】-【オプション(o)】―【エキスパートアドバイザー】で《Allow WebRequest for listed URL:》にチェックを入れ、外部サーバーのアドレスを追加しておきます。
今回は、DailyfxJapanを使用させて頂くので以下のようにしています。
opustion
その他の注意事項として、WebRequest()関数は、非同期関数で、EAもしくはスクリプトのみ使用可能。インジケーターで使用すると【error 4060 – "Function is not allowed for call".】と怒られます。∑(゚∀゚ノ)ノキャー今回は、EA上で使用することにしました。

 


実行してみると・・・

karenda
今回作成したEAをココに置いておきます。使用する際はEAとして使用してください。※2014/9/8EAを一部変更しました。
また、サーバーから取得したhtmlファイルは、MQL4/Filesに保存されます。


課題やら留意した点やら問題点

1.結局WebRequest()関数のテストをしようと思って作り始めたのですがリファレンスの例をそのまま使用しています。..orz
2.保存したHTMLファイルは、Shift_JISで保存しているのでブラウザで開くと文字化けする。(本来は、UTF-8)
3.StringSetChar(A,B,'文字')関数の文字部分は、”ストレートクォーテーションマーク”を使用するとバグが発生しましたので
  ’アポストロフィー’を使用しました。リファレンスも ’アポストロフィー’を使用しています。
4.終日イベントの時間を00:00としているので、00:00を過ぎると表示されなくなる。。orz
5.LABELオブジェクトを使用したので、表示させる文字数が多すぎるとすべてが表示されない。。orz
6.週末すべてのイベントが終了すると寂しい。土曜日に実行しても同じ。。。


まとめ

ん~なんだか中途半端な気がします。。^^;

2014/08/05

new MT4 de SQLite3

古い仕様のMT4が使えなくなってしまったので、新しい仕様に対応したSLQLite3用のヘッダーファイルを作成しました。
(※warapperDLL未使用)

はじめに

新しいMT4のエンコードを調べてみたら以下の通りとなりまいた。
  • MetaEditorが新規に作成するmq4,mqhは、ANSI(Shift_JIS)
  • UNICODE(UTF-16BOM)で作成したmq4.mqhでもコンパイル出来た。
  • 内部は、UNICODE(UTF-16BOM)
  • logファイルは、ANSI(Shift_JIS)
※毎回ではないが、UNICODE(UTF-16BOM)で作成したファイルをMetaEditorで加工すると文字化けが発生しました。
流れとしては、mq4(ANSI or UNICODE)→MT4(UNICODE)→SQLite3(UTF-8)→MT4(UNICODE)→output(ANSI)となります。
また、MQL5フォームに『SQL and MQL5: Working with SQLite Database』という記事があったのですが、使用することができませんでした。そのため、この記事を参考にコンパクトな物を作ることにしました。

コード

ココからDLすることが出来ます。(sqlite3.mqh test.mq4 sqlite3.dll )

//+------------------------------------------------------------------+
//|                                                      SQLite3.mqh |
//+------------------------------------------------------------------+

#define PTR            int //32bit:int 64bit:long?
#define sqlite3_stmt   PTR
#define sqlite3        PTR
#define PTRPTR         PTR

#define SQLITE_OK           0   /* Successful result */
#define SQLITE_ERROR        1   /* SQL error or missing database */
#define SQLITE_INTERNAL     2   /* An internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */
#define SQLITE_BUSY         5   /* The database file is locked */
#define SQLITE_LOCKED       6   /* A table in the database is locked */
#define SQLITE_NOMEM        7   /* A malloc() failed */
#define SQLITE_READONLY     8   /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT     11   /* The database disk image is malformed */
#define SQLITE_NOTFOUND    12   /* (Internal Only) Table or record not found */
#define SQLITE_FULL        13   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN    14   /* Unable to open the database file */
#define SQLITE_PROTOCOL    15   /* Database lock protocol error */
#define SQLITE_EMPTY       16   /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT  19   /* Abort due to contraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_ROW         100  /* sqlite_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite_step() has finished executing */

#import "sqlite3.dll"
//int sqlite3_open(const uchar &filename[],sqlite3 &paDb);
int sqlite3_open16(string filename,sqlite3 &paDb);
int sqlite3_close(sqlite3 aDb);
//int sqlite3_prepare(sqlite3 aDb,const char &sql[],int nByte,sqlite3_stmt &pStmt,PTRPTR pzTail);
//int sqlite3_prepare16(sqlite3 aDb,string sql,int nByte,sqlite3_stmt &pStmt,PTRPTR pzTail);
int sqlite3_prepare16_v2(sqlite3 aDb,string sql,int nByte,sqlite3_stmt &pStmt,PTRPTR pzTail);
int sqlite3_exec(sqlite3 aDb,const char &sql[],PTR acallback,PTR apvoid,PTRPTR errmsg);
int sqlite3_step(sqlite3_stmt apstmt);
int sqlite3_finalize(sqlite3_stmt apstmt);
int sqlite3_reset(sqlite3_stmt apstmt);
int sqlite3_errcode(sqlite3 db);
int sqlite3_extended_errcode(sqlite3 db);
//const PTR sqlite3_errmsg(sqlite3 db);
const string sqlite3_errmsg16(sqlite3 db);
int sqlite3_bind_null(sqlite3_stmt apstmt,int icol);
int sqlite3_bind_int(sqlite3_stmt apstmt,int icol,int a);
int sqlite3_bind_int64(sqlite3_stmt apstmt,int icol,long a);
int sqlite3_bind_double(sqlite3_stmt apstmt,int icol,double a);
//int sqlite3_bind_text(sqlite3_stmt apstmt,int icol,char &a[],int len,PTRPTR destr);
int sqlite3_bind_text16(sqlite3_stmt apstmt,int icol,string a,int len,PTRPTR destr);
//int sqlite3_bind_blob(sqlite3_stmt apstmt,int icol,uchar &a[],int len,PTRPTR destr);
const PTR sqlite3_column_name(sqlite3_stmt apstmt,int icol);
int sqlite3_column_count(sqlite3_stmt apstmt);
int sqlite3_column_type(sqlite3_stmt apstmt,int acol);
int sqlite3_column_bytes(sqlite3_stmt apstmt,int acol);
int sqlite3_column_int(sqlite3_stmt apstmt,int acol);
long sqlite3_column_int64(sqlite3_stmt apstmt,int acol);
double sqlite3_column_double(sqlite3_stmt apstmt,int acol);
//const PTR sqlite3_column_text(sqlite3_stmt apstmt,int acol);
string sqlite3_column_text16(sqlite3_stmt apstmt, int acol);
const PTR sqlite3_column_blob(sqlite3_stmt apstmt,int acol);
#import

class CSQLite3{
   public:
     sqlite3       sdb;
     sqlite3_stmt  stmt;
     
                   CSQLite3(){};
                   CSQLite3(string file_name);
                  ~CSQLite3(){if(stmt){finalize(); sqlite3_close (sdb);}};
      
     void          db_set(string file_name);            //ファイル名のセット
     int           reset();                             //ステートメントの初期化
     int           finalize();                          //ステートメントの解放
     void          db_close(){sqlite3_close (sdb);}
     int           execute(string sql);                 //入出力のないクエリーの実行
     int          prepare(string sql);                 //入出力のあるクエリーの実行
     int           col_count();                         //列数の取得
     bool          next_row();                          //次の行を取得(true:あり false:なし)
     int           bind_text(int col,string txt);       //文字データの入力
     int           bind_int(int col,int integer);       //整数値の入力
     int           bind_double(int col, double dbl);    //Doubule値の入力
     int           get_int(int col);                    //整数値の出力
     double        get_double(int col);                 //Doubule値の出力
     string        get_text(int col);                   //文字データの出力
     void          errmsg();                            //エラーメッセージをプリント
};

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CSQLite3::CSQLite3(string file_name){
   if(file_name != "")db_set(file_name);
}

void CSQLite3::db_set(string file_name){
   int res =  sqlite3_open16 (file_name, sdb);
   if (res != SQLITE_OK) errmsg();
}

//+-----------------------------------------------------------------+
// int CSQLite3::reset();
// ※ステートメントのリセット
//+-----------------------------------------------------------------+
int CSQLite3::reset(){
   int ret = 0;
   if(stmt)ret = sqlite3_reset(stmt);
   return(ret);
}
//+-----------------------------------------------------------------+
// int CSQLite3::finalize();
// ※ステートメントの解放
//+-----------------------------------------------------------------+
int CSQLite3::finalize(){
   int ret = 0;
   if(stmt){
      ret = sqlite3_finalize (stmt);
      stmt = 0;
   }
   return(ret);
}

//+------------------------------------------------------------------+
// int CSQLite3::execute(string sql)                                                                                  
//  ※入出力のないクリエ―の実行
//  sql : クエリー                       
//+------------------------------------------------------------------+
int CSQLite3::execute(string sql){
   int sq,res;
   uchar qr[];
   sq = StringToCharArray(sql,qr);
   ArrayResize(qr,sq);
   if(stmt)reset();
   res = sqlite3_exec (sdb, qr, NULL, NULL, NULL);
   return(res);
}

//+-----------------------------------------------------------------+
//  int  CSQLite3::prepare(string sql);
//  ※入出力のあるクリエーの実行。
//  ※反復処理は、(next_row,get_col)を使用。
//  ※finalize()を使用し解放をおこなう。
//  sql : クエリー                       
//+------------------------------------------------------------------+
int CSQLite3::prepare(string sql){
   int res;
   if(stmt)finalize();
   res = sqlite3_prepare16_v2(sdb, sql,StringLen(sql)*2 , stmt, NULL);
   return(res);
}
//+------------------------------------------------------------------+
// int CSQLite3::colum_count ();
// ※列数を返す。
//+------------------------------------------------------------------+
int CSQLite3::col_count(){
   return(sqlite3_column_count (stmt));
}  
//+------------------------------------------------------------------+
// bool CSQLite3::next_row ();
// ※次の行を取得する 。(true:あり false:なし)
//+------------------------------------------------------------------+
bool CSQLite3::next_row (){
   if(!stmt)return(false);
   int ret = 0;
   ret = sqlite3_step (stmt);
   return (ret == SQLITE_ROW ? true : false);
}
//+------------------------------------------------------------------+
// bind_?? ();
// ※値を入力
//+-------------------------------------------------------------------+
//文字データ
int CSQLite3::bind_text(int col,string txt){
   int ret = 0;
   ret = sqlite3_bind_text16(stmt,col,txt,StringLen(txt)*2,0);
   return (ret);
}
//整数値
int CSQLite3::bind_int(int col,int integer){
   int ret = 0;
   ret = sqlite3_bind_int(stmt,col,integer);
   return (ret);
}
//double値
int CSQLite3::bind_double(int col, double dbl){
   int ret = 0 ;
   ret = sqlite3_bind_double(stmt,col,dbl);
   return (ret);
}

//+------------------------------------------------------------------+
// column_?? ();
// ※値を取得
//+-------------------------------------------------------------------+
//整数値
int CSQLite3::get_int(int col){
   int date = 0 ;
   date = sqlite3_column_int (stmt, col);
   return (date);
}
//double値
double CSQLite3::get_double(int col){
   double date = 0.0;
   date = sqlite3_column_double (stmt, col);
   return(date);
}
//文字データ
string CSQLite3::get_text(int col){
   string date = "";
   date = sqlite3_column_text16(stmt, col);
   return(date);
}
//+------------------------------------------------------------------+
// Errmsg();
// ※エラーメッセージをプリント
//+-------------------------------------------------------------------+
void CSQLite3::errmsg(){
   Print(sqlite3_errmsg16(sdb));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    使用例(サンプル)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//+------------------------------------------------------------------+
//|                                                  SQLite3test.mq4 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
#property show_inputs
#include <sqlite3.mqh>
input string dbns="C:\Testdb.db";//データベース名(フルパス)

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start(){
    string sql = "";
   int i;
   //インスタンス
     CSQLite3 sqlite(dbns);
   
   //テーブルの作成
     sql = "CREATE TABLE IF NOT EXISTS `Test` (`id` INTEGER, `time` TEXT, `open_price` DOUBLE)";
     if(sqlite.execute(sql)!= SQLITE_OK)sqlite.errmsg();
   
   //入力
     sql = "INSERT INTO 'Test' VALUES (?,?,?)";
     //トランザクション 
     if(sqlite.execute("BEGIN")!=SQLITE_OK)sqlite.errmsg();
   
     for(i=0;i<Bars;i++){
       if(sqlite.prepare(sql)!=SQLITE_OK)sqlite.errmsg();
       if(sqlite.bind_int(1,Bars-i)!=SQLITE_OK)sqlite.errmsg();
       if(sqlite.bind_text(2,TimeToStr(Time[i]))!=SQLITE_OK)sqlite.errmsg();
       if(sqlite.bind_double(3,Open[i])!=SQLITE_OK)sqlite.errmsg();
       sqlite.next_row();
     }
     //トランザクション終了
     if(sqlite.execute("COMMIT")!=SQLITE_OK)sqlite.errmsg();
   
     //ステートメントの解法
     sqlite.finalize();
     
   //出力
     sql = "SELECT COUNT(*) FROM  'Test'";
     if(sqlite.prepare(sql)!=SQLITE_OK)sqlite.errmsg();
     sqlite.next_row();
     Print("Bars=",IntegerToString(Bars)," データベース内のデータ数=",sqlite.get_text(0));
     
     //ステートメントの解法
     sqlite.finalize();
     
   //抽出
     sql = "SELECT * FROM 'Test'" ;
     if(sqlite.prepare(sql)!=SQLITE_OK)sqlite.errmsg();
     while(sqlite.next_row()){
       Print(IntegerToString(
                               sqlite.get_int(0))," : ",
                               sqlite.get_text(1)," : ",
                               DoubleToStr(sqlite.get_double(2),Digits));
     }
   
     //ステートメントの解法
     sqlite.finalize();
   //データベースを閉じる。  
   sqlite.db_close();

  return (0);
  }
 

まとめ

mq4(ANSI or UNICODE)→MT4(UNICODE)→SQLite3(UTF-8)→MT4(UNICODE)→output(ANSI)
エンコードの統一ってできないものでしょうか(ー_ー)!!。。

2014/06/03

ボラティリティを手の中に・・

今回の内容は、偏見に満ちた自主検証の内容となっていますのでご了承ください。^^;

 

はじめに

さて、しばらくの間、下記のヒストグラム(CLOSE-OPEN)が、どのような分布で近似できるか検討してきましたが、なかなか良い分布が見つかりませんでした。
clop

そこで、tick-volumeのヒストグラムに視点を変更してみました。すると、そのヒストグラムは、対数正規分布がマッチすることが分かりました。
volumer

また、時間単位で作成されている足(データ)をtick数単位にまとめ直した足(データ)ではどうなるか?
確認しました。すると、正規分布がマッチすることが分かりました。
※1分足をtick数でまとめて加工したデータ
tick

そこで、,まとめるtick数を変化させた場合の偏差を求めてみると、下図のドットが現れました。
次に、そのドットに近似させる式を探したところ、ランダムウォークの拡散現象(分散)を表す式(上)のt(時間)をtick_volumeに置き換えた式であることがわかりました。また、拡散係数を便宜上ルートの外に出すと、下記の通りの式となりマッチさせることが出来ました(緑色のライン)。ちなみにα=2.24
ttcct

※t:時間 / tc:tick_volume
ttty
tttcc

ここまでをまとめてみると・・・
  • ドル円の単位時間当たり(今回は、H1)のボラティリティ(CL-OP)のヒストグラムに単独でマッチするような分布は見つけられなかった。しかし、tick_volumeをまとめて作成したヒストグラムが正規分布となり、かつ、tick_volumeのヒストグラムが対数正規分布となっていることが解った。そのことから、偏差が異なる正規分布の集合(合成)が、あのような分布を形作るという結論となった。
  • ランダムウォークの拡散現象(分散)を表す式をtick_volumeに置き換えた式を用い、偏差とtick_volumeの関係を数式化することができることがわかった。
というものになりました。<-我ながらかなり強引ですww

 

tick_volumeの予測

さて、ここから本題です。偏差とtick_volumeの関係がわかれば、ticl_volumeを予測することにより偏差を予測することが可能ではないか?と考え、tick_volumeを予測してみることにしました。
まずは、チャートのtick_volumeを観察してみます。(今回は、USDJPY & EURUSDのH1を使用しています。)
vol ※縦のラインは、1日を表しています。

ジ~と見ます。wすると、1日単位で周期的に変化している様に見えます。そこで、次の様に仮定してみます。
【各時間毎のtick_volumeは、各時間の固有パラメータと直前のtick_volumeの出来高に影響を受ける。】
これを式にすると。。
tc
※a[0]~a[23]:各時間に割り当てられるパラメータ

ここまで仮定すれば、後は重回帰を用いて最適解を求めれば出来上がりです。まずは、結果からご覧ください。赤の折れ線が予測値で水色が、tick_volumeです。表示期間は、2014/05/29~06/04で、最適化の期間は、2014/05/01から1000barsです。
EURUSDH1
うまくマッチしているように見えるのですが如何なものでしょうか(・・?

今回テストしたモノは、MT4がMT5の仕様に対応したこともありMT5用のヘッダーをお借りして作成してみました。
ココよりDLが可能です。
DL出来るファイルは、以下の通りです。(今回は、DLL未使用にしてみました。)
┣Matrix.mqh 【Matrix operations library - library for MetaTrader 5】から取得し一部加工しました。(行列用)
┣Multiple_Regression_Analysis.mqh (重回帰用)
┗TKVP_H1.mq4 (テスト用のインジケータ)

 

ボラティリティの予測

次に、予測したtick_volumeを用いて1σを表示させてみました。(白線:1時間後 青線:2時間後)
band
tick_volumeの予測値が結果より若干高くなっているためか、1σの範囲が若干広い気もしますが。。

 

課題

パラメータの不足
TKVP_H1.mq4 を作動させてもらうとわかると思いますが、予測値が結果と大きく乖離する場合があります。それは、イベント(指標の発表、要人の発言、市場の休場など)が原因です。イベントを取り入れるパラメータが必要だと思われます。
拡散係数の計算
tickデータから直接計算できれいいのですが、M1を使用しているのでまとめる時に誤差が生じてしまいます。
良い方法があればいいのですが、今回は、単純にvolumeの加算による方法をとりました。

 

まとめ

課題が解決できれば、ボラティリティを予測する手段として良い方法だと思うのですが。。。^^;

2014/03/26

Notepad++ de MQL4 Stage 2

懲りもせずに新MT4用のNotepad++用の補完とハイライト用のデータを作成したので公開しておきます。

mqq

ファイルは、ここからDLしてください。ファイルの説明は、以下の通りです。
  • MQL4.xml              補完用データ         | 保存先は、---\Notepad++\plugins\APIs
  • MQL4_color.xml       ハイライト用のデータ  | 【言語(L)】-【言語の定義】-【インポート】から
  • Reserved_word.mq4  確認用及び他エディタ用予約語一覧テキスト


補足 ハイライトの分類は、以下の配色の通りです。
  • 黄色枠:旧MQL4の範囲
  • 赤色枠:新規追加範囲(MetaEditorのハイライトを参考に分類)
  • 緑色枠:旧+新 ピンク色(デフォルト)
  • 色は、適当に指定していますので調整してください。
 raberu


【蛇足】

mql.exe(旧.metalang.exe)が更新時に添付されなくなるという情報を聞き、新しいmql.exeをDLしてみました。・・・が、倍以上になってる@@;。。。なぜでしょう?
sin