2017/03/14

(Open-Close)のヒストグラムを再現してみました。

今回は、Jupyter Notebookの勉強も兼ねなが進めていきます。^^;方法として、まずTickVolumeをヒストリカルデータから見積もります。次に、作成したTickVolume数だけランダムウォークさせて実際の値幅との違いを見ます。

まずは、TIckVolumeの作成です。


次に密度分布の作成です。


いろいろなペアと時間で試してみました。




まとめ

 試行回数が異なるランダムウォークの密度分布がほぼ(Open-Close)の密度分布と重なるということは、(Open-Close)のヒストグラムは、分散が異なる正規分布の集合体で表せれる。ということですね。。

2015/08/08

外部エネルギーが加えられることによりエントロピーの増大が妨げられるとさ。。

はじめに

ご無沙汰しております^^;
 さてさて今回は、チャート内の特異値(Bar)を見える化する指標を作成することにしました。


手順


まず初めに、各Barの値として(高値-安値)《以下 高安値》を採用しました。
高安値を採用したことにより対数正規分布を連続確率分布として採用します。
参考記事:ベキ分布?  対数正規分布を調べてみた。  検証してみました。

あとは、分布のパラメータを推定して、各高安値を当てはめて発生確率を求めました。そして出来上がったのがコレです。。。。。なんだか全然見える化できていない。。orz


 そこで、選択情報量の定義を利用して左記のように見やすくしました。自画自賛w
※ちなみに情報量の定義などは、こちら








まとめ

  今回実施した特異値に理由付けを行ってみた結果が以下の画像です。

大きく指標が跳ね上がった部分は、何らかの理由付けができそうです。いや~黒田日銀総裁の円安是正発言は、まいりました。^^;
 さてさて、今回の指標は、高安値が高いから指標が跳ね上がるだけでなく極端に低い場合でも跳ね上がります。右のチャート部分は、時間当たり2ティックしかなく特異値として指標が跳ね上がりました。発生確率が低い値(高安値)を見える化する事が目的なのでこんな感じとなります。データの抜けが原因かな?。。
  ここでお題の話を少し。。情報エントロピーという情報量の定義指標があって(参考)、情報を受け取ると情報エントロピーは、最小となる。つまり、事象の不確かさが、最小となる。つまり、(ここからは、妄想。。)不確実さが低減されるのであれば、秩序だった動きが現れるんじゃないの?だったら∑(゚Д゚;)!! いや~妄想ってホント素敵ですねw 夏があまり好きではないおっさんの戯言でありました。


コード

DLは、ココ

//+------------------------------------------------------------------+
//|                                                       impact.mq4 |
//|                                         Copyright 2015, bighope. |
//|                        http://expertadviser-bighope.blogspot.jp/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015,bighope."
#property link      "http://expertadviser-bighope.blogspot.jp/"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_minimum 5
#property indicator_maximum 20
#property  indicator_buffers 1
#property indicator_color1 Snow
#define pi 3.14159265358979
input int Startbar     =     0;     //データの取得開始Bar数
input int Range        = 2000;     //平均と偏差を導くためのデータ数
input double  wide    = 10.0;       //確率密度×○倍(特に意味がありません)

double Buf[];
string Indicator_Name ;

//+------------------------------------------------------------------+
//|GetData
//|out[Ns]     データの取得配列
//|Ns            データの取得数
//|St            開始インデックス
//+------------------------------------------------------------------+  
int  GetData(int St,int Ns,const double &hi[],const double &lw[],double &out[]){
   int i;
   double pt = MathPow(10,Digits);
   for(i=0;i<Ns;i++) out[i]=(hi[St+i] - lw[St+i])*pt;
   return(i);
}
//+------------------------------------------------------------------+
//| Logsd_likelihood 対数正規分布 最尤法によるパラメータ推定
//|data[Ns]     対象データ
//|Ns           データの取得数
//|mu           対数正規分布パラメータ
//|sigma2       対数正規分布パラメータ (sigma^2) 
//+------------------------------------------------------------------+  
void Logsd_likelihood(int Ns,double &data[],double &mu,double &sigma2){
   int i;
   mu =0.0;
   sigma2 = 0.0;
   for(i=0;i<Ns;i++)mu += MathLog(data[i]);
   mu /= Ns;
   for(i=0;i<Ns;i++) sigma2 += MathPow((MathLog(data[i])-mu),2);
   sigma2 /= Ns;
}
//+------------------------------------------------------------------+
//|Logsd_dist  対数正規分布の確率密度
//|dt              データ
//|w               対象データの幅
//|mu              対数正規分布パラメータ
//|sigma2          対数正規分布パラメータ  (sigma^2) 
//+------------------------------------------------------------------+ 
double Logsd_dist(double dt,double w,double mu,double sigma2){
    double A,B;
        A = 1/MathSqrt(2*pi*sigma2);
        B = MathPow((MathLog(dt)-mu),2)/(2 * sigma2);
    return(w*A*MathExp(-B)/dt); 
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
    IndicatorBuffers(1);
    SetIndexStyle(0,DRAW_LINE);
    SetIndexBuffer(0,Buf);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
    int i,limit;
    double d;
    ArraySetAsSeries(high,true);
    ArraySetAsSeries(low,true);
    //対数正規分布 最尤法によるパラメータ
    static double Mu     = 0.0;
    static double Sigma2 = 0.0;
    //初期設定 
    if(prev_calculated ==0){
        double date[];
        ArrayResize(date,Range);
        //データの取得
        if(GetData( Startbar,Range,high,low,date)<(Range-2)){
            Print("データが設定分取得できませんでした。");
            return(0);
        }
        
         //パラメータ推定
        Logsd_likelihood(Range,date,Mu,Sigma2);
        if(Mu >0 && Sigma2 >0){
          Print("mu=",Mu,"  Sigma^2=",Sigma2);  
        }else{
               Print("パラメータの推定に失敗しました。");
               return(0);
        }
    }
    
    limit = rates_total-prev_calculated-1;
    if(prev_calculated>0)limit++;
    for(i=0;i<limit;i++){
      d = (high[i+1]-low[i+1])* MathPow(10,Digits);
      if(d>0) Buf[i] = -MathLog(Logsd_dist(d,wide,Mu,Sigma2));
    }
    return(rates_total);
  }
//+------------------------------------------------------------------+

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

2013/11/17

f(x)=a+bX1+cX2+dX3+eX4+fX5+gX6 で重回帰分析

今回は、多項式回帰のコードを流用して複数(6つ以下)の異なる時系列データを用て、元となる時系列データを重回帰分析してみました。

jp225

【仕様説明】

f(x)=a+bX1+cX2+dX3+eX4+fX5+gX6 (a~g:定数 X1~X6:説明変数)
の場合の定数(a~g)を重回帰分析で求め近似モデルf(x)を表示させる。また、上記式に代入した式と近似モデルからの残差二乗和を精度としコメント表示させる。
重回帰分析の範囲は、各説明変数の最古の時系列データの中で最新データのものを基準としパラメータで指定した範囲で分析する。また、欠損データがある場合は、欠損データからもっとも近い過去のデータを使用し補完を行う。

例)
USDJPY(M5)を説明変数(EURUSDとEURJPY)で分析した場合は、以下のようになる。
[USDJPY]f(x)=[97.80020313]+[72.30209778]*EURUSD+[0.73920198]EURJPY 精度=0.00525783
USDJPYTT ※本来USDJPYをEURUSD及びEURJPYで説明する場合は、f(x)=EURJPY/EURUSDですよね^^;
ちなみに、一番初めの画像は、
[NIKKEI225]f(x)=[4382]+[372]*USDJPY+[0.3139]*DJ30+[0.2165]*GOLD+[-501]*JAPAN_BOND+[-223]*5Y_T-NOTES+[225]*10Y_T-NOTES   精度=6954558 (※細部省略) です。

【使い方】

1.ココから重回帰.zipをDLし解凍する。
2.gsl.dllとgslcblas.dllをMT4のterminal.exeと同じ位置に置き、!重回帰v2.mq4をindicatorsフォルダに置く。
3.説明変数となる通貨ペアを表示させ、なるべく多くのデータを取得しておく。
4.!重回帰v2.mq4をチャートにセットし、DLLの使用を許可する。
dll
5.パラメータの説明
N:            重回帰分析の範囲 デフォルトは、1000個のデータを使用
type_price: 0:終値 1:初値 2:高値 3:底値 4:(高値+低値)/2 5:(高値+低値+終値)/3
                 6:(高値+低値+2*終値)/4
zeroset:     一日ごとに重回帰分析を更新する場合は、true そうでない場合は、false
                ※ 更新時刻は、サーバー時間の00:00です。
symb1~6:  説明変数の通貨ペアを記入します。ただし、symb1から記入し使用しない箇所は、空欄(何も記入しない)にしてください。
pea

【まとめ】

MT4の仕様(バグ?)により以下のコードが通りませんでした。(昔からだけど。。。)
//////////////////////////////////////////////////////////////////////////////////
string symb[6] = {USDJPY,EURUSD,EURJPY,AUDJPY,CHFJPY,GBPJPY};
double date[6];
for(int i=0;i<6;i++) date[i] = iMA(symb[i], 0,1,0,MODE_SMA,0,0);
////////////////////////////////////////////////////////////////////////////////////
一度、string型の変数に代入し直してやるかiMA(symb[0],…の様にしてやると通りました。
また、ラッパーを使用せず作成したため行列の範囲を指定して剥きとるgsl関数が使用できませんでした。


【PR】

MT4使いの方でMT5なんて別にいらないんじゃないの?という方へ
MT4の最適化作業にイライラしていませんか?
せっかく高スペックのCPUを積んでいるのにMT4が作動しているのはシングルスレッドのみで、ほかのスレッドが空いていませんか?Core i7 が泣いていますよ!
MT5ならマルチスレッドに対応しているので、最適化作業の時間短縮が測れます。また、複数のPCを繋いだり専用クラウドサービスを使用して最適化作業をすることも可能です。
数日前に『メタトレーダー4&5』という書籍が発売になりました。著者は、豊嶋先生です。これを機にMT5の世界に足を組み入れてみませんか?
いつやるの?。。。いまでしょう! <フルw



【code】


//+------------------------------------------------------------------+
//|                                                    !重回帰v2.mq4 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
#property indicator_chart_window
#property show_inputs
#property indicator_buffers 1
#property indicator_color1 Snow

//DLL
#import "gsl.dll"
 //ベクトル 
   //長さ n のベクトルを生成し、生成したベクトル構造体へのハンドルを返す。
   int gsl_vector_alloc (int n);
   //v:成形されているベクトル構造体へのハンドル。すでに確保されているベクトル v を解放する。
   void gsl_vector_free (int v);
   //ベクトル v の i 番目の要素を返す。
   double gsl_vector_get (int v, int i);
   //ベクトル v の i 番目の要素に x の値を代入する。
   void gsl_vector_set (int v, int i, double x);
   
 //行列
   //大きさか. n1 行× n2 列の行列を生成し、新しい初期化された行列構造体へのポインタを返す。
   int gsl_matrix_alloc (int n1, int n2);
   //すでに確保されている行列 m を解放する。
   void gsl_matrix_free (int m);
   //行列 m の (i, j) 成分に x の値を代入する。
   void gsl_matrix_set (int m, int i, int j, double x);
   //行列 m の (i, j) 成分を返す。
   double gsl_matrix_get (int m, int i,int j); 
 
 //重回帰
    //この関数は n 変数て. p 個のパラメータを持つモデルで近似するための作業領域を確保する。
    int gsl_multifit_linear_alloc (int n, int p);
    //この関数は作業領域 w に割り当てられたメモリを解放する。
    void gsl_multifit_linear_free (int work); 
    //この関数は観測データ y と予測子変数の行列 X に対する、モデル y = Xc の最良近似パラ
    //メータ c を計算する。モデルパラメータの分散共分散行列 cov は、近似に対するデータの
    //ばらつきから計算される。近似モデルからの残差二乗和 χ2 は chisq に返される。
    int gsl_multifit_linear (int X, int y, int c,int cov, double & chisq[], int work);
#import

//+--------------------------------------------------------------------------------------+
extern int    N          = 1000;          //回帰範囲
extern int    type_price = PRICE_CLOSE;   //取得値
extern bool   zeroset    = false;         //true: 00:00に再計算 false: 再計算しない
extern string symb1      = "EURUSD";      //説明変数1
extern string symb2      = "EURJPY";      //説明変数2
extern string symb3      = "AUDUSD";      //説明変数3
extern string symb4      = "AUDJPY";      //説明変数4
extern string symb5      = "GBPUSD";      //説明変数5
extern string symb6      = "GBPJPY";      //説明変数6
//+--------------------------------------------------------------------------------------+

string symb[6];
int vcont;
double line1[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init(){
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,line1);
   symb[0]=symb1;
   symb[1]=symb2;
   symb[2]=symb3;
   symb[3]=symb4;
   symb[4]=symb5;
   symb[5]=symb6;
   for(int i=0;i<6;i++)if(symb[i]!="")vcont++; else break;
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit(){
   Comment("");
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start(){
   string text;
   static double ix[8];
   static int barsht;
   int matricx_xn;
   double line;
   string name,sym;
   int i,q,z,j,s;
   int counted_bars=IndicatorCounted();
   if(counted_bars<1){
     //各データ数で最も少ないbar数の取得
      datetime oldbars;
      for(z=0;z<vcont;z++)oldbars = MathMax(oldbars,iTime(symb[z],0,iBars(symb[z],0)-1));
      int lastbar = iBarShift(NULL,0,oldbars)-1;
      barsht = Bars-lastbar;
     //領域の確保 
      int matricx_xt =  gsl_matrix_alloc(lastbar, vcont+1);
      int matricx_xa=  gsl_matrix_alloc(N, vcont+1);
      double date;
     //全データの取得
      SelectPrices(symb,type_price,0,lastbar,matricx_xt);
     /*確認用
      for(i=0;i<lastbar;i++)
         Print(
            gsl_matrix_get(matricx_xt,i,0),":"
            ,gsl_matrix_get(matricx_xt,i,1),":"
            ,gsl_matrix_get(matricx_xt,i,2),":"
            ,gsl_matrix_get(matricx_xt,i,3),":"
            ,gsl_matrix_get(matricx_xt,i,4),":"
            ,gsl_matrix_get(matricx_xt,i,5),":"
            ,gsl_matrix_get(matricx_xt,i,6)
         );
       */
     //重回帰分析用のデータの取得
      for(i=(lastbar-N);i>0;i--){
         if(i== lastbar-N ||(Time[i]%86400 ==0 && zeroset)){
            for(j=0;j<N;j++){
               for(q=0;q<vcont+1;q++){
                  date = gsl_matrix_get(matricx_xt,i+j,q);
                  gsl_matrix_set (matricx_xa,j,q,date);
               }
            }
            //重回帰分析 
            Multiple_regression(i,N,type_price,matricx_xa,ix);
         }
         line=0.0;
         for(q=0;q<=vcont;q++)line += ix[q]*gsl_matrix_get(matricx_xt,i,q);
         line1[i] = line;
      }
      gsl_matrix_free(matricx_xt);
      gsl_matrix_free(matricx_xa);
   }else{
      i=Bars-counted_bars;
      while(i>=0){
         if((ix[0]==0)||(Time[i]%86400 ==0 && zeroset)){
            matricx_xn = gsl_matrix_alloc(N, vcont+1);
            SelectPrices(symb,type_price,i,N,matricx_xn);
            Multiple_regression(i,N,type_price,matricx_xn,ix);
            gsl_matrix_free(matricx_xn);
         }     
         
         line1[i] = ix[0];
         for(s=0;s<vcont;s++){
            sym = symb[s];
            line1[i] += ix[s+1]*iMA(sym,0,1,0,MODE_SMA,type_price,i);
         }
         i--;
      }
   }
   
   text = "["+Symbol()+"]f(x) =["+ix[0] +"]";
   for(s=0;s<vcont;s++) text = text + " + ["+ix[s+1]+"]*"+symb[s];
   text= text +"      精度="+ix[7];
    Comment(text);
   return(0);
  }
//+------------------------------------------------------------------+
//|データの取得
//+------------------------------------------------------------------+
void SelectPrices(string& sym[],int pricetype,int index,int range,int matricx_handle){
   datetime sytime;
   int s,i,q,t;
   double price;
   //f(x) = a + b*x1+c*x2+.....g*x6
   //a
   for(int z=0;z<range;z++)gsl_matrix_set (matricx_handle, z, 0,1.0);
   //x1...x6
   for(s=0;s<vcont;s++){
      if(sym[s]=="")break;
      SelectPrice_symb(sym[s],s,pricetype,index,range,matricx_handle);
   }
}
//+------------------------------------------------------------------+
//|データの取得(通貨ペア)
//+------------------------------------------------------------------+
void SelectPrice_symb(string symbl,int symb_i,int pricetype,int index,int range,int matricx_h){
   datetime sytime;
   int q =0,t=0;
   for(int i=0;i<range;i++){
         sytime = iTime(symbl,0,q+i+index);
         for(t=0;t<100;t++)   {
            if(Time[i+index]>=sytime)break; else q++;
            sytime = iTime(symbl,0,q+i+index);
         }
         gsl_matrix_set (matricx_h, i, symb_i+1,iMA(symbl,0,1,0,MODE_SMA,pricetype,q+i+index));
         if(Time[i+index] > sytime)q--;
   }
}
//+------------------------------------------------------------------+
//|重回帰分析
//+------------------------------------------------------------------+
void  Multiple_regression(int index,int range,int type,int matricx_xd,double & ans[]){
   int matrix_cov,vector_y,vector_c,multifit_work;
   int i;
   double chisq[1];
   //f(x) = a + b*x1+c*x2+.....g*x6
   //作業領域の確保
    matrix_cov     =  gsl_matrix_alloc(vcont+1,vcont+1);
    vector_y       =  gsl_vector_alloc(range);
    vector_c       =  gsl_vector_alloc(vcont+1);
    multifit_work  =  gsl_multifit_linear_alloc (range,vcont+1);

  //y
   for(i=0;i<range;i++)gsl_vector_set (vector_y , i,iMA(NULL,0,1,0,MODE_SMA,type,i+index));
   
  //処理
   multifit_work = gsl_multifit_linear_alloc (range,vcont+1);
   gsl_multifit_linear(matricx_xd,vector_y,vector_c,matrix_cov,chisq,multifit_work);
   gsl_multifit_linear_free (multifit_work);
   
  //結果の取得 
  //ans[8] = {a,b,c,d....chisq}
   for(i=0;i<vcont+1;i++) ans[i] = gsl_vector_get(vector_c,i);
   ans[7] = chisq[0];
   
  //メモリ解放
   gsl_matrix_free(matrix_cov);
   gsl_vector_free(vector_y);
   gsl_vector_free(vector_c);
}