移動ミニマックス法:テクニカル分析用新インディケータと MQL5への実装実装
はじめに
「定量的ファイナンス」と名のついた科学があります。それは理論物理学および数理物理学の手法を用い金融派生商品価格設定の研究を可能にします。
最近、量子物理学から発生した考えを採り入れたテクニカル分析のための新しいインディケータについて述べた論文を見つけました。それに興味を引かれ、MQL5で科学的論文に基づくインディケータを導入する方法を教えようと決意しました。
元となる移動ミニマックス論文 [2] はブドカー原子核物理研究所および国立ノボシビルスク大学の量子物理学者Z.K.Silagadze氏によるものです。本稿末尾に論文および MQL5 ソースコードの添付があります。
インディケータ
この文章を書くとは夢にも思いませんでしたが、これから量子トンネルについて説明をしていきます。読者はほとんどが金融アナリストではないと思いますので、簡単な言葉でお話していきますが、不快に感じないで下さい。まず、ファイナンシャル時系列のテクニカル分析の背後にある考えを一文で定義します。われわれは次のことを見つけようとしていると思います。
- サポートとレジスタンスの価格レベル
- 短期長期のトレンド方向
- トレンドの頂点と底
移動ミニマックス インディケータの発想は、核を解放する量子α粒子の類似体を使ってチャート上で頂点と底を見つけることです。設問は George Gamov [1] 氏のα 崩壊理論から借用しています。
多くの言葉よりも図の方が有効だと思われるので、以下に小さなグラフを貼りつけます。
図1 外為価格グラフ上の架空量子ボール
丘のてっぺんからボールが投げられるのを想像します。われわれの場合は、時系列グラフの直近の頂上からです。従来の力学では、障害物に跳ね返り、最大の障害物で止まる可能性はありません。なぜなら途中どこかで立ち往生するかもしれないからです。
ところが、量子力学およびα崩壊理論によると、そのボールは障害をくぐり抜けポテンシャル井戸の底を見つけそこで前後に動き続けるという、ひじょうに小さいがゼロではない可能性があるのです。
これが価格チャートでローカル最小値を見つけることに類似した現象です。Z.K.Silagadze [2] 氏の論文では実際の量子力学問題を解くのではなく、複雑な計算を避けるためには量子力学的ふるまいのまねごとで十分であるとの理論展開があります。ここでは、原論文で述べられている数学的背景を紹介し、その後 MQL5でそれを実装していきます。
価格系列を時間ウィンドウとします。移動ミニマックスは価格系列の非線形変換です。
ここで and for は以下のように定義されます。
ご覧のように、これは再帰関係で i 番目の要素は i-1 要素に依存しています。この移動ミニマックス系列は正規化条件を満たし、それは1に等しい全エレメントの合計です。
量子ボールのトンネル確率は変換確率と呼ばれます。なぜならそれらは価格系列の小さな障害物、すなわち架空の下り坂にある小さな障害、を横切る確率のモデル化だからです。
次とともに
パラメータ m は量子ボールの(反比例する)質量と小さな障害を渡す機能を模倣した平滑化ウィンドウの幅です。極大を強調する移動ミニマックス d(si) は exp() 関数に渡されるパラメータ内にマイナス記号を入れることで構築されます。
実装
インディケータの背後の数学について知識を得たので、それを MQL5に実装することができます。そのためには、上記の最後の方程式から見ていくのが一番よいでしょう。変数 m および n に注意を払うと、このインディケータにはミニマックス ウィンドウ一つに価格の n+2m エレメント配列が必要で、それは m バーのラグサイズであることがわかるでしょう。
これは Q 変数計算のインデックスS i+k および S i-k のためです。変数 i は 1 ~ n までインクリメントされ、変数k は 1 ~ m の間でインクリメントされます。よって開始する n+2m バッファが必要です。これは以下を呼ぶことで行われます。
double S[]; ArrayResize(S,n+2*m); CopyClose(Symbol(),0,0,n+2*m,S);
これはダブルの配列を宣言し、そのサイズを n+2m に変更し、直近のバーから開始する現シンボルのチャートから最後の n+2m バーに近い値をコピーします。
次のステップは Q 値の計算です。定義を注意して読むと、分析した価格系列の i 番目のエレメントに対して、価格値変数を用いて exp() 関数のm 結果を合計する必要があるのがわかります。よってすべての値Q を数えるループを1~ n まで作成する必要があります。
void calcQii() { int i,k; for(i=0; i<n; i++) { double sqiip1=0; double sqiim1=0; double dqiip1=0; double dqiim1=0; for(k=0; k<m; k++) { sqiip1 += MathExp(2*(S[m-1+i+k]-S[i])/(S[m-1+i+k]+S[i])); sqiim1 += MathExp(2*(S[m-1+i-k]-S[i])/(S[m-1+i-k]+S[i])); dqiip1 += MathExp(-2*(S[m-1+i+k]-S[i])/(S[m-1+i+k]+S[i])); dqiim1 += MathExp(-2*(S[m-1+i-k]-S[i])/(S[m-1+i-k]+S[i])); } sQiip1[i] = sqiip1; sQiim1[i] = sqiim1; dQiip1[i] = dqiip1; dQiim1[i] = dqiim1; } }
ご覧のように、観測される価格ウィンドウサイズ n について calcQii 関数がQ と Q` の i 番目の値を計算しています。S 配列は価格値を持ち、sQiip1, sQiim1, dQiip1, dQiim1 は Q and Q'の中間計算変数として使われます。
確率は変数 Q と Q` に基づき計算されるので、配列 sQii および dQii を用いて1 ~ nまで循環する別の関数を作成することが可能です。
void calcPii() { int i; for(i=0; i<n; i++) { sPiip1[i] = sQiip1[i] / (sQiip1[i] + sQiim1[i]); sPiim1[i] = sQiim1[i] / (sQiip1[i] + sQiim1[i]); dPiip1[i] = dQiip1[i] / (dQiip1[i] + dQiim1[i]); dPiim1[i] = dQiim1[i] / (dQiip1[i] + dQiim1[i]); } }
あとはエレメント uSi とのちに dSi の計算とその結果を配列 uSi および dSi に入れることです。
void calcui() { int i; sui[0] = 1; dui[0] = 1; for(i=1; i<n; i++) { sui[i] = (sPiim1[i]/sPiip1[i])*sui[i-1]; dui[i] = (dPiim1[i]/dPiip1[i])*dui[i-1]; } double uSum = 0; double dSum = 0; ArrayInitialize(uSi, 0.0); ArrayInitialize(dSi, 0.0); for(i=0; i<n; i++) { uSum+=sui[i]; dSum+=dui[i]; } for(i=0; i<n; i++) { uSi[n-1-i] = sui[i] / uSum; dSi[n-1-i] = dui[i] / dSum; } }
正規化条件が有効か確認するために以下の行を追加します。
double result=0; for(i=0; i<n; i++) { /* Print("i = "+i+" uSi = "+uSi[i]); */ result+=uSi[i]; } Print("Result = "+ DoubleToString(result));
計算がすべて終わったら、それをインディケータウィンドウ内に表示する必要があります。そのために、最低2個のインディケータバッファを宣言します。ひとつは uSi 配列 向け、もうひとつは dSi 配列向けです。そしてインディケータタイプを DRAW_LINE と宣言します。
#property indicator_separate_window #property indicator_buffers 2 #property indicator_plots 2 #property indicator_type1 DRAW_LINE #property indicator_type2 DRAW_LINE #property indicator_color1 SeaGreen #property indicator_color2 BlueViolet
それからSetIndexBuffer() 関数を呼び、INDICATOR_DATAとして表示するために配列 uSi および dSi を割り当てます。
SetIndexBuffer(0,uSi,INDICATOR_DATA); SetIndexBuffer(1,dSi,INDICATOR_DATA); PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0); PlotIndexSetInteger(0,PLOT_SHIFT,-(m-1)); PlotIndexSetInteger(1,PLOT_SHIFT,-(m-1));
図2 実装済み移動ミニマックスインディケータ
本稿に述べるインディケータの可能なアプリケーションはサポートおよびレジスタンスラインとインディケータの固有平滑化によるチャートバターンを特定しています。サポートとレジスタンスラインに関しては、価格系列の移動ミニマックスおよび移動平均の移動ミニマックスをクロスすることで形成されます。
価格が極大を過ぎ移動平均をクロスすると、レジスタンスとなります。実装後、メソッドが数個の誤ったシグナルに悩まされているのを見ましたが、ChartObjectsLines.mqh ライブラリを使用しMQL5に行を入れる方法についての参照ソースコードをペーストしました。
void SR() { // if price goes through local maximum and crosses a moving average draw resistance int i, cnt=0; int rCnt=CopyClose(Symbol(),0,0,n+2*m,S); for (i=n-2; i>=0; i--) if (uSi[i]<uSi_MA[i] && uSi[i+1]>=uSi_MA[i+1]) { Print("Resistance at " + i); CChartObjectHLine *line=new CChartObjectHLine(); line.Create(0, "MiniMaxResistanceLine:"+IntegerToString(cnt), 0, S[i]); line.Color(LightSkyBlue); line.Width(1); line.Background(true); line.Selectable(false); cnt++; } // if price goes through local minimum and crosses a moving average draw support for (i=n-2; i>=0; i--) if (dSi[i]<dSi_MA[i] && dSi[i+1]>=dSi_MA[i+1]) { Print("Support at " + i); CChartObjectHLine *line=new CChartObjectHLine(); line.Create(0, "MiniMaxSupportLine:"+IntegerToString(cnt), 0, S[i]); line.Color(Tomato); line.Width(1); line.Background(true); line.Selectable(false); cnt++; } }
ですが、インディケータの興味深い事実は、既定の時間ウィンドウについて短かいトレンドの極小および極大をじつによく認識していることでした。よって移動ミニマックスの最大値と最小値間のスプレッドを検索条件に追加し、短期のブルまたはベアトレンドの始まりとしてマークすれば十分です。
その他のインディケータや資金管理に応じて、収益性ある Expert Advisor を作成するためにこの変動を利用することが可能です。
現在時間ウィンドウ上で最高値をマークするには、スプレッドが最大のときにいつも上下矢印を表示する別のインディケータバッファを使用します。また、インディケータをより好ましいものにするには MQL5の新機能であるカラーヒストグラムを使用することにしました。上昇トレンドおよび下降トレンドは異なる色にし、トレンド変化は黄色のバーで示します。
2つのバッファ間でカラーヒストグラムを使用するには、データバッファを2個とカラーインデックス用にバッファを1個使用する必要があります。プロットの定義方法を見てください。合計インディケータバッファは5個です。カラーヒストグラムに3色が決定されています。
//+------------------------------------------------------------------+ //| MovingMiniMax.mq5 | //| Copyright 2011, Investeo.pl | //| http://Investeo.pl | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, Investeo.pl" #property link "http://Investeo.pl" #property description "Moving Mini-Max indicator" #property description "proposed by Z.K. Silagadze" #property description "from Budker Institute of Nuclear Physics" #property description "and Novosibirsk State University" #property description "Original paper can be downloaded from:" #property description "http://arxiv.org/abs/0802.0984" #property version "0.6" #property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 3 #property indicator_type1 DRAW_COLOR_HISTOGRAM2 #property indicator_type2 DRAW_ARROW #property indicator_type3 DRAW_ARROW #property indicator_color1 Chartreuse, OrangeRed, Yellow #property indicator_color2 RoyalBlue #property indicator_color3 RoyalBlue #property indicator_width1 5 #property indicator_width2 4 #property indicator_width3 4
ヒストグラムは INDICATOR_DATA タイプのバッファを2個と INDICATOR_COLOR_INDEX タイプを1個取ることに留意します。バッファは次の順序で正確に設定する必要があります。最初にデータバッファがきて、それからカラーインデックスバッファが定義されます。
SetIndexBuffer(0,uSi,INDICATOR_DATA); SetIndexBuffer(1,dSi,INDICATOR_DATA); SetIndexBuffer(2,trend,INDICATOR_COLOR_INDEX); SetIndexBuffer(3,upArrows,INDICATOR_DATA); SetIndexBuffer(4,dnArrows,INDICATOR_DATA); PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0); PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0); PlotIndexSetInteger(1,PLOT_ARROW,234); PlotIndexSetInteger(2,PLOT_ARROW,233);
バッファ 0、1、2 はカラーヒストグラム用、バッファ 3、4 は矢印表示用です。
色をつけるアルゴリズムは以下です。
if (upind<dnind) { for (i=0; i<upind; i++) trend[i]=0; for (i=upind; i<dnind; i++) trend[i]=1; for (i=dnind; i<n; i++) trend[i]=0 ; } else { for (i=0; i<dnind; i++) trend[i]=1; for (i=dnind; i<upind; i++) trend[i]=0; for (i=upind; i<n; i++) trend[i]=1; } trend[upind] = 2; trend[dnind] = 2;
最終結果のスクリーンショットを貼りつけます。
図3 移動ミニマックスインディケータの最終バージョン
上昇トレンド、下降トレンドの値は新規バーが作成されるたびに所定の時間ウィンドウに対して計算されます。これが移動ミニマックスを呼ぶ理由です。
それは m バーでラグしますが、現在の時間ウィンドウにおけるトレンドの概況を驚くほどよく示し、またマーケットがどのように「呼吸」しているか読み解いてくれます。
私はこのインディケータは有益であると確信しています。
おわりに
テクニカル分析用新インディケータの背後にある数学と MQL5への実装についてお話しました。
Z.K.Silagadze 氏による原論文はhttp://arxiv.org/abs/0802.0984で入手可能です。添付のソースコードはダウンロードすることができます。
今後、もっとおもしろいテクニカルインディケータとそのMQL5への実装についてご紹介できればと思っています。
参照文献:
1. G.Gamov, Theory of alpha decay.
2. Z.K. Silagadze, Moving Mini-Max - a new indicator for technical analysis.
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/238
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索