2012/10/30

続・相関係数

2012/10/30追記
前回の内容にて、相関係数は、計算コストが高すぎてリアルタイムで随時処理していくには不向きなものと記述しましたが、kartzさんからコメントを頂き、それが誤りであったことがわかりましたので記述します。
内容は、私が説明するよりkartzさんのコメントを見て頂いた方が良いと思いますのでそちらをご覧ください。
※正直完全に理解できたか疑問が残るというのが本音だったりしますが。。(汗

コード化

kartzさんのコメントをコード化すると以下の様になりました。
//+------------------------------------------------------------------+
//|                                                   相関係数_i.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_separate_window
#property indicator_buffers 1
#property indicator_color1 Yellow

extern int pd = 100;//期間

double Sx[]; //S(x,a,b) := Σ[i=a~b; x[i]]: xの総和
double Sy[]; //S(y,a,b) := Σ[i=a~b; y[i]]: yの総和
             //M(v,a,b) := S(v,a,b) / (b-a+1): 相加平均
double Fxy[];//F(x,y,a,b) := Σ[i=a~b; (x[i] - M(x,a,b)) * (y[i] - M(y,a,b))]
double Fxx[];//F(x,x,a,b) := Σ[i=a~b; (x[i] - M(x,a,b)) * (x[i] - M(y,a,b))]
double Fyy[];//F(y,y,a,b) := Σ[i=a~b; (y[i] - M(x,a,b)) * (y[i] - M(y,a,b))]
double p[];//相加係数
//+------------------------------------------------------------------+
// | Custom indicator initialization function                        |
//+------------------------------------------------------------------+
int init() {
//---- indicators
   IndicatorBuffers(6);
//---- drawing settings
   SetIndexStyle(0,DRAW_LINE);
   SetIndexStyle(1,DRAW_NONE);
   SetIndexStyle(2,DRAW_NONE);
   SetIndexStyle(3,DRAW_NONE);
   SetIndexStyle(4,DRAW_NONE);
   SetIndexStyle(5,DRAW_NONE);
   SetIndexBuffer(0,p);
   SetIndexBuffer(1,Sx);
   SetIndexBuffer(2,Sy);
   SetIndexBuffer(3,Fxy);
   SetIndexBuffer(4,Fxx);
   SetIndexBuffer(5,Fyy);
//----
   return(0);
  }

//+------------------------------------------------------------------+
//|初期値計算                                                        |
//+------------------------------------------------------------------+
 void Base(int index            //開始位置 
             ,int range           //適用範囲
             ,double &S_x[]     //Sx[];
             ,double &S_y[]     //Sy[];
             ,double &F_xy[]   //Fxy[];
             ,double &F_xx[]   //Fx[];
             ,double &F_yy[]   //Fy[];
                                   ){
   
   int i;
   double x,y,avx,avy,sigxy,sigx,sigy;
   
   //x.yの相加平均
   for(i=range;i>0;i--){
      //xの加算
      avx += High[index+i-1] - Low[index+i-1];
      //yの加算
      avy += Volume[index+i-1];
   }
   avx /=range;
   avy /=range;
            
   for(i=range;i>0;i--){
      x = High[index+i-1] - Low[index+i-1];
      y = Volume[index+i-1];
      sigxy += (x-avx)*(y-avy);
      sigx   += (x-avx)*(x-avx);
      sigy   += (y-avy)*(y-avy);
   }
   S_x[index]  = avx*range;
   S_y[index]  = avy*range;
   F_xy[index] = sigxy;
   F_xx[index] = sigx;
   F_yy[index] = sigy;
}
 
//+------------------------------------------------------------------+
//|相関係数                                                          |
//+------------------------------------------------------------------+
int start(){
   double x,y,xn,yn;
   int    counted_bars=IndicatorCounted();
   int limit=Bars-counted_bars -1;//2012/10/30変更
   //初期設定
   if(counted_bars<=0){
   limit -=pd;//2012/10/30追記
   Base(limit+1,pd,Sx,Sy,Fxy,Fxx,Fyy);
      p[limit+1] = Fxy[limit+1]/MathSqrt(Fxx[limit+1]*Fyy[limit+1]);
   }
   for(int i=limit; i>=0; i--){
      //追加項
      x      = High[i] - Low[i];
      y      = Volume[i];
   //削除項(2012/10/30変更) 
      xn    = High[i+pd] - Low[i+pd];//変更前 xn= High[i+pd+1] - Low[i+pd+1];
      yn    = Volume[i+pd];          //変更前  yn= Volume[i+pd+1];
      //総和の更新
      Sx[i]     = Sx[i+1] + x -xn;
      Sy[i]     = Sy[i+1] + y - yn;
      //F項の更新
       Fxy[i]   = Fxy[i+1] + (Sx[i+1]*Sy[i+1] - Sx[i]*Sy[i])/pd - xn*yn +x*y;
      Fxx[i]   = Fxx[i+1] + (Sx[i+1]*Sx[i+1] - Sx[i]*Sx[i])/pd - xn*xn +x*x;
      Fyy[i]   = Fyy[i+1] + (Sy[i+1]*Sy[i+1] - Sy[i]*Sy[i])/pd - yn*yn + y*y;
      //相関係数
       p[i] = Fxy[i]/MathSqrt(Fxx[i]*Fyy[i]);
   }
return(0);
}
  

表示・確認

従来の計算方法で求めた結果を赤線で表示させ、今回の計算結果を黄線で重ね合わせてみました。
(変更前)
photo


(変更後)※わかりやすくするために従来の計算方法を途中で終了させています。

 

まとめ

この方法なら、随時処理しても十分に使用できます。また、一つ勉強になりました。kartzさんありがとうございました。
//2012/10/30追記
kartzさんから指摘して頂いた、【削除項】の変更の結果、ほぼ一致したラインを作ることが出来ました。

2012/10/27

忘却型相関係数

2012/10/29修正しました。

相関係数は、非常に計算コストの高い関数で、私の様な非力なPCを使っている者にとっては、リアルタイムで随時処理していくには不向きなものだと思っています。ということで、近似関数を用いて相関係数の計算コスト削減を行ってみました。

変換

まずは、相関係数の公式の確認です。対象となるデータをxとyとし期間をnとすると以下のようになります。
soukans
この公式の分母と分子にそれぞれ1/nを乗算すると、以下のようになります。
soukann
ここで、各項を見ると相加平均であるのがわかります。そこで、見慣れた記号SMAに置き換えて見ると
soukanm
となります。そこで、SMAをEMAで置き換えると(近似させると)、
soukane
となり、EMAの公式を当てはめると以下のようになります。
susiki
これで忘却型相関係数の完成です。

確認作業

本来の相関係数と忘却型相関係数をコードにすると以下のようになります。
(※以下のコードは、値幅とティックボリュームの相関関係を求める場合です。)
//+------------------------------------------------------------------+
//|相関係数                                                               |
//+------------------------------------------------------------------+
int start(){
   double x,y,avx,avy,sigxy,sigx,sigy;
   int i,q;
   for(i=limit; i>=0; i--){
      // x:(High[i] - Low[i]) y:Volume[i];
      for(q=pd;q>0;q--){
      //xの加算
         avx += High[i+q-1] - Low[i+q-1];
      //yの加算
         avy += Volume[i+q-1];
      }
      //x.yの相加平均
      avx /=pd;
     avy /=pd;
      
      //変数の初期化
      sigxy =0;
     sigx   =0;
     sigy   =0;
      
      for(q=pd;q>0;q--){
         x = High[i+q-1] - Low[i+q-1];
         y = Volume[i+q-1];
         sigxy += (x-avx)*(y-avy);
         sigx   += (x-avx)*(x-avx);
         sigy   += (y-avy)*(y-avy);
      }
      cn[i] = sigxy/(MathSqrt(sigx)*MathSqrt(sigy));
      
   }
return(0);
}

//+------------------------------------------------------------------+
//|忘却型相関係数                                                          |
//+------------------------------------------------------------------+
int start(){
   double x,y;
   int    counted_bars=IndicatorCounted();
   if(counted_bars>0) counted_bars--;
   int limit=Bars-counted_bars-1;
   
   for(int i=limit; i>=0; i--){
      x      = High[i] - Low[i];
      y      = Volume[i];
      avx[i]   = (1-alfa)*avx[i+1] + alfa*x;
      avy[i]   = (1-alfa)*avy[i+1] + alfa*y;
      sigxy[i] = (1-alfa)*sigxy[i+1] + alfa*(x-avx[i])*(y-avy[i]);  
      sigx[i]  = (1-alfa)*sigx[i+1] + alfa*(x-avx[i])*(x-avx[i]);
      sigy[i]  = (1-alfa)*sigy[i+1] + alfa*(y-avy[i])*(y-avy[i]);
      //忘却型相関係数
      cn[i] = sigxy[i]/(MathSqrt(sigx[i])*MathSqrt(sigy[i]));
   }
return(0);
}
  
チャート上で確認すると,このようになります。
soukan
※チャート上のMAは、それそれの適用期間に合わせたSMAとEMAです。
※上記のサンプルをココに置いておきますので確認してみてください。

まとめ

本来、EMAは、忘却性能と逐次性能が有り、逐次型とか指数平均型とかのネーミングが良いのでしょうが、忘却という響きが好きで、忘却型としました。また、今回は、わかりやすいようにバッファを多用しましたが、1つ前の値しか使用しないので変数(static)で十分対応できます。
ChangeFinder、SDARモデルなどで検索すると、この手法の発展系を見ることが出来ます。

2012/10/13

Notepad++ de MQL5

Notepad++ v6.2が登場したことでハイライト機能が充実しました。と言うことで今回は、MQL5の実装をしてみました。
main


初めに

自動補完用の設定ファイル(MQL5.xml)とハイライト用の設定ファイル(MQL5hl.xml)をココからDLしてくだしい。


自動補完の設定

MQL5.xmlを前回と同様の場所[Notepad++]‐[plugins]‐[\APIs]にコピペします。
※今回の自動補完用ファイルには、関数の引数表示は、設定していません。


ハイライトの設定

Notepad++のバージョンアップに伴い[ユーザー定義ダイアログ]がなくなりました。
設定場所は、【言語】‐【Define-your language…】です。
後は、前回同様です。


ヘルプ(chm)の設定

プラグイン【LanguageHelp】をココからDLします。※plugin manager からは、DLできませんでした。
解凍後、[Notepad++]‐[plugins]にLanguageHelpA.dllとLanguageHelpU.dllをコピペします。
Notepad++を再起動すると、注意表示されますが無視ししてください。
【プラグイン】‐【Language Help】‐【option】と進み【Add】をクリックします。設定は、以下のとおりです。
help
検索したい文字を指定しCTRL+F1で実行できます。


コンパイラーの設定

MetaTrader5は、MQL5.DLLでコンパイルを行いますが、コマンドプロンプトでコンパイル作業が行えるようにMQL5.EXEが用意されています。引数などは、MetaEditor Help → Creating Programs → Compilingに記載されていますので確認してください。あとは、MQL4の時と同じです。
comp


その他

MQL5のエディタで作成されるファイルのフォーマットは、UNICODEです。MQL5を新規に作成する場合は、UT-8のフォーマットにした方が良いとは思いますが、SJISのフォーマットでもコンパイルできました。(※作動確認はしていません)
また、MQL5のMetaEditorで行えるデバッグ機能をNotepad++で行う方法がわかりませんでした。もし可能ならコメント頂けると幸いです。

2012/10/04

Notepad++ de MQL4

秀丸エディタをMQL4エディタ(MetaEditor)にする方法』と言う記事を読んで、面白そうだったのでNotepad++でやってみました。実施範囲は、自動補完・ハイライト・コンパイル作業です。
open


初めに

Notepad++とは
notepad++の導入方法などは、コチラの記事を参考してください。
※日本語入力及び表記に多少問題があるようです。気になるかたは、Notepad++ EUC-JP 対応版の方がよいかもしれません。ただし、今回、確認したのは、Notepad++v6.18(UNICODE)版です。
インストールと初期設定が修了したらココからMQL4_bag.zipをDLし解凍してください。


自動補完の設定

DLしたファイル(mql4.xml)を[Notepad++]‐[plugins]‐[\APIs]にコピペします。
標準インストールした場合はココです。[C:\Program Files\Notepad++\plugins\APIs]
Notepad++を機動させ[設定(T)]‐[環境設定]‐[自動保存/入力補完]と進み以下のように設定します。
para
[入力補完フォーム]
┣入力の毎に補完を行うにチェック
┣関数名補完にチェック
┗入力の直後関数パラメーターヒントを表示にチェック
※お好みによって◎文字目から補完するか設定。
以上で完成です。


テスト:拡張子が.mq4のファイルを作成し、[言語(L)]からMQL4を指定すれば確認できます。
また、引数を伴う関数を指定し(かっこ)をつけるとパラメーターのヒントが表示されます。
sort※関数の引数で()で囲まれた部分がデフォルトです。


ハイライトの設定

Notepad++を機動させ[表示(V)]‐[ユーザー定義ダイアログ]‐[Import...]と進みDLしたファイル(mql4hr.mxl)を指定します。
yuza
yuzaoo
お好きな色を設定して、Notepad++を再起動してください。
※演算子に*と/を追加するとコメントが色抜けします。(原因不明です。)
再起動後MQL4ファイルを開いてもハイライト機能が現れなかったら、[言語(L)]のmql4をクリックしてください。


コンパイラーの設定

Notepad++を機動させ[プラグイン]-[Plugin Manager]-[Show Plugin Manager]と進み[NppExec]をインストールします。
NPPE
再起動後[プラグイン]‐[NppExec]-[Execute(F6)]を表示させ画面の様に入力します。
NPPE3

// save current file
NPP_SAVE 
//compile
C:/Program Files\MetaTrader 4/metalang.exe  "$(FULL_CURRENT_PATH)" 

※C:/Program Files\MetaTrader 4/metalang.exe は、コンパイル先のmetalang.exe のpathです。
入力後[OK]で作動確認をし、問題がなければ名前を付けて[save]します。

次にショートカットの割り当てをします。
[プラグイン]‐[NppExec]‐[Advanced Option]-[Addociated script]にて先ほど保存したファイルを指定し[Add/Modify]をクリックし[OK]で終了します。
NPPE5

[設定(T)]‐[ショートカット管理]‐[Plugin Commands]からファイル名を探しショートカットの設定をします。
NPPE6
NPPE7

これで設定完了です。


まとめ

私自身ほとんどnotepad++を使用していないので何らかのトラブルが生じる可能性がありますのでご了承ください。notepad++のおすすめ機能は、折り畳みと[ctrl]+スクロールでの文字拡大縮小機能です。目が疲れてきたときに助かります。やはり、日本語表記及び記入に問題があるようで、日本語記入後のEnterで補完ログが発生したりします。
また、本来ならHelpの表示もしたかったのですが解りませんでした。