今回の内容は、私が違和感(自分で作っておきながら・・・)を感じていたMizutori_EAの指標について検証してみました。
対象になった指標は、以下のコードの指標です。
+―――――――――――――――――――――――――――――――+
stb = iMA(NULL,0,MaLimtPeriod,MaLimtShift,MODE_SMMA,PRICE_OPEN,0);
HiLimt = High[iHighest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
LowLimt = Low[iLowest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
st = (HiLimt-LowLimt)/(stb/100);
+――――――――――――――――――――――――――――――――+
※この指標を説明すると
ある一定期間(デフォルトなら、80バー期間(約6時間40分))の値幅(終値の高値―安値)を基準値(デフォルトなら、SMMA500)で割り、100倍したものです。
※では、なぜこの指標が必要だったか?(作成した当時の考え方です。)
①ある一定期間の値幅には、ある程度限界があるのではないか?(限界付近での逆張りは、リスク回避につながるのではないか?)
②値幅の限界は、価格に比例するのではないか?(100USDJPY より120USDJPYの方が値幅の限界が大きいはずだ!)
③導き出した値が小さすぎたので100倍して指標とした。
※限界とは,最大の意味ではなく、偏差的発想?ととらえてください。
【作成した当時妙にしっくりくる指標となりまともな検証もしないまま、使用してきました。】
しかし、違和感があったのも事実です。今回は、上記内容を検証してみます。
【検証内容】
手っ取り早く検証するために、今回は、ある一定期間を4時間(つまり4時間足)と設定し、その高値と安値の差を値幅(=高値―安値)として検証してみました。
また、0.01USDJPYピッチで出現頻度(ヒストグラム)を作成しその累計を百分率で表示させました。
下記の図は、2001年~現在までを年ごとにまとめたグラフです。
上記の図を説明すると、縦軸が出現頻度の累計百分率で、横軸が刻み(ピッチ)を表しています。
例えば、2001年では、【0~0.76】の範囲に約90%のデータがあることを意味しています。
また、標準偏差の2倍(95.45%)を値幅の上限(上記で言う限界)と見ると以下の値が導きだされます。
【2001】0.93 【2002】0.88 【2003】0.75 【2004】0.82 【2005】0.70 【2006】0.82 【2007】0.82 【2008】1.35 【2009】1.06(※データ数がほかのに比べて半分程度)
このことが、上記①の内容を意味しています。
しかし、漠然とですが、上記②の内容が否定されていることがわかるでしょうか?
わかりやすくするために、今度は、2001年~現在までのデータを安値を基軸に並べ替えてまとめた物を使用し、上記と同じようなグラフを作りました。
まとめた範囲は、【安値が90USDJPY以下】【90~100】【100~110】【110~112.5】【112.5~115】【115~117.5】【117.5~120】【120~122.5】【122.5~125】【125~】です。 
上記図を見て頂くと一目瞭然です。上記指標の考えだと、価格が大きくなれば値幅も大きく(右にラインが移動する)なるはずでした。
しかし、実情は、価格の大きさと値幅は無関係にあることがわかります。
残念ですが、この指標は、不完全な物であるというほかありません。
そのまま使用される場合は、上記②の考えを排除した以下のコードに変更する方がベターだと思います。
+――――――――――――――――――――――――――――――――――――――+
//stb = iMA(NULL,0,MaLimtPeriod,MaLimtShift,MODE_SMMA,PRICE_OPEN,0);削除
HiLimt = High[iHighest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
LowLimt = Low[iLowest(NULL,0,MODE_CLOSE,LimtPeriod,0)];
st = (HiLimt-LowLimt);
+――――――――――――――――――――――――――――――――――――――+
【まとめ】
偶然とは怖いものです。結果ばかり追いかける怖さを再確認しました。
また、上記の図を見て2008年の数値が突出していることが分かると思います。
これが崩壊の原因になったEAも少なくないはずです。
『100年に1度の・・・』との話をよく耳にしましたが、このデータを見ても納得できるところです。
さて、近況報告です。
ここ数カ月Mizutori から距離を置き、資料集めにぼっとしています。特に、データの【変換】方法の勉強です。
今注目している物が、ウェーブレット変換です。もちろん!EAの開発用ですよ!
では!
新たに指標を自作した際に付きまとう厄介なバグの修正作業!に注目してみました。
コンパイルは、出来たものの表示されない!MT4が、動かなくなったなど数多く経験されていると思います。
今回は、コンパイル完了後のバグについて記載しておきます。
まず、MT4がフリーズしてしまった時の作業です。
『MT4フリーズ時の脱出方法』
①Windowsタスクマネージャーの呼び出し【XPの場合(CTRL)+(ALT)+(DELETE)】
②(プロセス)→terminal.exeの選択→(プロセスの終了)
③原因の指標の変更
④MT4の起動(再度フリーズの場合は、①に戻る)
A)MT4がフリーズしてしまう場合
①無限ループに陥っている。
※ループ条件の脱出条件が未定の場合に発生します。
よくある?(私がよくする間違い)
例1:
while(i >= 0)
{
************************************
i--;※この条件を忘れてしまう!もしくは、符号を間違える。
}
例2:
For(i=0,k=0;i<100;k++){********************}
※iを終了条件にしているにも関わらず、k++となっており、i++がない場合
※こんなことするわけがないとお思いでしょうが、ループが2重、3重になると意外に多いものです。(私の場合・・・)
②除算の分母に0(ゼロ)を代入した場合
※多くは、一端フリーズ状態を経て指標を表示せずMT4が起動して、バーの更新があると最新の指標を表示するなどの症状になります。
※除算の分母に変数を用いる場合は、初期条件に、ゼロを否定する条件を入れたほうが問題の発生を低減させることができます。
例)
Double A =0;
Double B =0;
A = Volume[0];
If(A!=0) B = 10/A;※このようにしておけばゼロエラーが回避できます。
B)指標が表示されない場合(すべては掲示出ませんが・・・)
①基本事項の確認をしてみる
・大域での宣言に間違いがないか?(#property indicator_buffers 1 #property indicator_color1 Red など・・・・)
※indicator_buffers Xは、表示する指標の個数になっていますか?など
・初期関数部(int init())の設定に間違いはないか?(SetIndexStyle(0,DRAW_LINE); SetIndexShift(0,MA_Shift); など・・・・・)
※非表示の時系列配列(計算用の時系列配列)も初期関数部でのセットが必要です。
②存在しないものを元に計算処理させた場合
・移動平均を再度平均化処理する場合などに、発生する可能性があります。
C)実際に例を元に、バグ取りを行ってみます。
例)終値を単純移動平均(SMA10)し、再度、単純平均する(SMA10)するコードを以下に示します。
このコードは、コンパイルエラーは起こらず、エラーを含んだコードです。(何個エラーがあるでしょうか?)
//+------------------------------------------------------------------+
1:#property indicator_chart_window
2:#property indicator_buffers 1
3:#property indicator_color1 Gold
4:extern int SMAPeriod = 10;
//---- buffers
5:double SMA[];
6:double SMASMA[];
//| Custom indicator initialization function |
7:int init()
8: {
9: IndicatorBuffers(2);
10: SetIndexStyle(1,DRAW_LINE);
11: SetIndexBuffer(1,SMASMA);
12: SetIndexStyle(2,DRAW_NONE);
13: SetIndexBuffer(2,SMA);
14: return(0);
15: }
//| Custom indicator deinitialization function |
16:int deinit()
17: {
18: return(0);
19 }
//| Custom indicator iteration function |
20:int start()
21: {
22: int CountedBars = IndicatorCounted();
23: int i = Bars-SMAPeriod-1;
24: if(CountedBars>0)i=Bars-CountedBars;
25: while(i >= 0)
26: {
27: SMA[i] = iMA(NULL,0,SMAPeriod,0,MODE_SMA,MODE_CLOSE,i);
28: SMASMA[i] = iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,i);
29: i++;
30: }
31: return(0);
32: }
//+------------------------------------------------------------------+
※上記コードを用いて、バグ取り手順(素人の自己流なので、ベストな方法か疑問が残りますが・・・・)の説明
①何はともあれ、一度稼働させてみる。
※上記コード自体を稼働させないでください。(PCがフリーズします。)
②上記コードを稼働させたところ、PCがフリーズしたため、上記『MT4がフリーズした場合の脱出方法』を元に、脱出し、ループ関数を確認してみる。
A:29:行目【 i++;】が無限ループの原因と発覚!【i--;】 に変更、再度稼働。
B:再稼働後、MT4はフリーズから脱出したが、指標が表示されず。
③1:行目のコードをコメント化【//#property indicator_chart_window】2:行目の上に【#property indicator_separate_window】を記入。
※指標をサブウインドウで表示させることで、今後の確認作業を簡素化するためです。(この例ではほとんど関係ありませんが・・・)
④指標表示用配列(上記コードの場合SMASMA[ ]:) にiを代入【28:行目SMASMA[i] = i: //iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,i);】し再稼働してみる。
A:この状態で再稼働させても、指標が表示されないため、初期設定を疑う。
B:初期設定確認時に、10:行目から13:行目にエラーコード発見、下記のように変更。
9: IndicatorBuffers(2);
10: SetIndexStyle(0,DRAW_LINE);
11: SetIndexBuffer(0,SMASMA);
12: SetIndexStyle(1,DRAW_NONE);
13: SetIndexBuffer(1,SMA);
※ちなみに、【SetIndexBuffer(A,B)】とは、配列(名前B[ ])をバーが更新するたびに、更新してくれる機能(バッファ)を持たせるというものです。
例)【B[0] =5 B[1]=4 B[2]=3】の場合、新規バーが発生すると、【B[0] =新規 B[1] =5 B[2] =4 B[3] =3】になります。
また、SetIndexBuffer(バッファ)の設定は、8つまで持つことができます。Aは、その番号です。(ただし、A=0~7です。)
番号の割り当ては、0から始めなければならないお約束があります。
つまり、元のコード(エラーコード)を訳すと!
9行目 2つのバッファを設定します。
10行目 バッファ1は、線表記を設定 (本来は、バッファ0にセットしなければなりません。)
11行目 バッファ1に配列名SMASMAをセット(本来は、バッファ0にセットしなければなりません。)
12行目 バッファ2は、表記しません。(本来は、バッファ1にセットしなければなりません。)
13行目 バッファ2に配列名SMAをセット(本来は、バッファ1にセットしなければなりません。)
こんな感じです。
つまり、ここでエラーが発生していたことになります。
C:再稼働後、右肩下がりの指標が現れる。④で変更したコードを元に戻す。【28:行目SMASMA[i] =iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,i);】コンパイル後再稼働
D:再度指標が表示されなくなる。
⑤前処理用の配列(バッファ)【SMA[ ]】が機能しているか確認してみる。コード変更【28:行目SMASMA[i] = SMA[i] ; //iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,i);】
A:コンパイル後、再稼働!指標が表示されていることを確認
B:上記記載『B)② 存在しない配列を元に計算処理させた場合』が考えられるので、ループを別にしてみる。
int start()
{
int k;(新規ループ用に追加)
int CountedBars = IndicatorCounted();
int i = Bars-SMAPeriod-1;
k = i-SMAPeriod; (新規ループ用に追加)
if(CountedBars>0){i=Bars-CountedBars-SMAPeriod;k=i;} (新規ループ用に追加)
while(i >= 0)
{
SMA[i]=iMA(NULL,0,SMAPeriod,0,MODE_SMA,MODE_CLOSE,i);
i--;
}
while(k >= 0)
{
SMASMA[k] =iMAOnArray(SMA,0,SMAPeriod,0,MODE_SMA,k);
k--;
}
return(0);
}
⑥コンパイル後再稼働で指標が表示された。③で変更した部分を元に戻し終了です。(バグ取り完了)お疲れさまでした!
D)作成した指標が予定通り稼働しているか確認する。
※これが一番厄介なことです。なぜなら、実際のデータで指標を動かしても、自分の考え通りなのか不明確であることが多いためです。
そのため、サンプルデータを用いて確認する方法があります。
添付ファイルは、適当に作ったサンプルデータ(日足用)です。不要なシンボルに組み込んでみてください。
以下のようなチャートが現れるはずです。(わかっているとは思いますが、指標は別です。)
ご参考までに!
追記
『今年中にMT5が発表予定!』とか、『金融庁によるレバ規制!』とか、今後目まぐるしく変化することと思います。
やなぎのごとく柔軟に対応できるチカラ!を持ちたいものです!では・・・