2009/05/27

移動平均線ってなに?

先回の掲示に不適切な部分がありましたので、訂正し掲示しておきます。
『今さら何を!』との声が聞こえてきそうですが、『初心者向け』というよりは、私自身が無知だったので私の学習も兼ねて作成しました。

【移動平均線の特徴】
①そのまま記載すれば、適用期間の平均を適用期間の最新の値の位置に記載したもの。
②平均の取り方には、数多くの方法が存在する。(MT4の標準は4種類)
③移動平均線の適用期間が長くなると、データの平滑化が進む。
④データを多周波数の集まりと見ると、移動平均線とは、低周波通過フィルタとして機能している。
⑤移動平均線の最大のデメリットは、遅延である。

【移動平均線の書き方】
時系列データが、左から右に行くに従い新しいデータになる場合、適用期間の一番右(最新のデータ位置)に記載するのが基本です。また、最新のデータ位置よりも右(未来のデータ位置)にシフトして使われる場合もあります。例)Mizutori_EAの旧エンジンに使用していたSMA(単純移動平均線)は、最新のデータ位置に5バー過去のSMAをシフトして使用しています。つまり、最新のデータ位置のSMAデータは、5バー先の未来のデータの判断に使用しています。また、一目均衡表の遅行スパンのように左にシフトする場合もあります。

【移動平均線の種類】
  MT4に標準で装備されているものだけで4種類存在します。
①単純移動平均(SMA)
SMA=(適用期間のデータの合計)/(適用期間)
②線形加重移動平均(LWMA)
LWMA=(D[0]×(W-0) + D[1]×(W-1) + D[2]×(W-2)…….. +D[n-1]×(W-n-1)+D[n]×(W-n))/(加重合計)
※D[n]:データ(D[0]が最新、D[n]が最後)
※(W-n):加重 (W-n)=1 :(W-n-1)=2
例)適用期間:4 データ{9:8:7:6}(右が最新)の場合
LWMA =(6×4+7×3+8×2+9×1)/10= 7
③指数移動平均線(EMA)  A=2/(適用期間+1)※A<1
EMA=A×D[0]+(1-A)×EMA[1]
※D[0]:適用範囲の最新データ
※EMA[1]:1つ前のEMA値
④平滑移動平均線(SMMA)
SMMA=(D[0]+SMMA[1]×(適用期間―1))/適用期間
※D[0]:適用範囲の最新データ
※SMMA[1]:1つ前のSMMA値 ◆そのほかにも無数に存在します。たとえば、LWMAの加重をフィボナッチにするとか!EMAのAを変更するとか!しかし、大きく分類すると2種類になります。①と②のように適用期間内で計算処理が完了するものと、③と④のように前回の結果をもとに処理されるものに分類できます。また、③④は、適用期間以上にデータがないと(十分に過去のデータがないと)、軽微な誤差を伴います。 ちなみに、④のSMMAを③のEMAの公式の形にすると! ≪A=1/適用期間: SMMA=A×D[0]+(1-A)×SMMA[1]≫ となります。つまりAの初期条件を変えたものです。 また、A=3/(適用期間+2)にすると・・・・・・後ほど説明します。

【移動平均線の役割】
【SMA】 図1は、元データに波長(λ)20のSIN曲線を用い、適用期間を5(λ/4),10(2λ/4),15(3λ/4),20(λ)にしたSMA(単純移動平均線)です。振幅が徐々に減り、SMA(20)の時に振幅が0になります。また、期間が長くなればなるほど、振幅の頂点は、右にズレていきます。ただし、波長が変わることはありません。 図2は、元データに波長(λ)20のSIN曲線を用い縦軸に振幅の最大値、横軸にSMAの適用期間を示した図です。まるで高い位置からボールを落とした時の軌跡のようです。これは、SMAの適用期間の違いによりどれだけ元データが減衰されたかを示しています。SMA(20)で一時、振幅が0になり再度、振幅が現れますが、その振幅は、元データの30%程度です。そして、再度0になり再再度、振幅が発生しますが、初回の振幅の減衰に比べて減衰量が減ります。その後、振幅の最大値は、微量に減っていきますが、0になることはありません。また、適用期間20(λ)の整数倍で振幅=0が繰り返されます。この図でわかることは、逆転の発想で、SMAの適用期間の3/4より短い波長は、SMAすることにより、著しく減衰され、適用期間より長い波長は、多少の減衰はあるものの、残る(通過する)ことがわかります。つまり低周波通過フィルタの役割をしています。

【EMA】 図3は、図1のデータをEMAに置き換えたものです。EMAの特徴として、振幅が0になることはありません。 また、適用期間ごとの振幅の頂点のズレ(遅延)がSMAより少ない。しかも適用期間を大きくした場合のズレ(遅延)の間隔が少なくなっていくのがわかります。 図4は、図2のSMAをEMAに置き換えたものです。元データの70%程度減衰する適用期間が20となっています。SMAのように記載すると、EMAの適用期間より短い波長は、EMAすることにより著しく減衰されます。しかし、適用期間より長い波長でも、SMAと比べた場合、減衰量が多いのが特徴です。つまりSMAより精度が劣る低周波通過フィルタの役割をしています。


【その他】
図4は、縦軸をY:横軸をXとした場合のY=X+1の直線を元のデータとした場合のズレ(遅延)を図形化したものです。縦軸がズレ(遅延)量:横軸を適用期間としています。凡例が4種類あるにも関わらず、3本しか線がありません。これは、SMAとEMAが同じ値をとり重なっているのが原因です。言い換えれば、MT4に標準装備されているEMAは、Y=X+1の直線時のズレ(遅延)がSMAと同じ値をとるように調整された、指数移動平均線でることを示しています。また、EMAの変数AをA=3/(適用期間+2)とした場合、LWMA(線形加重移動平均)と同じ値となります。  


【まとめ】
  何気なく使用してきた移動平均線ですが、調べてみると奥が深く完全に理解することができませんでした。 しかし、今後のEA作成には、役立と思っています。また、トレードに理想的な移動平均線とは、遅延が少なく平滑な平均線であると思っています。  

【参考文献】
ロケット工学投資法 ジョン・F・エーラース 著 

2009/04/17

Mizutoriをカスタマイズ!


ご無沙汰しております。
今回の課題は、『なぜこのEAの取引数が、サーバー(取引業者)によって異なるか?』です。
※この内容は、私の憶測です。

大きく分けると4つの要因が考えられます。
①サーバー(取引業者)によって微妙にデータが違い、それが原因となり注文処理が行われずスルーするのではないか?
②サーバー(取引業者)との接続状況もしくはサーバーの処理状況が悪く、本来1Pips毎に送られてくるデータが数Pipsまとめて送られてくる場合に注文処理がスルーするのではないか?
③こちらからは、注文オーダーを出したにも関わらず、サーバー(取引業者)で受け付けてもらえなかったからではないか?(この要因は、今回対象外としておきます。)
※ちなみに『OFF QUOTES エラーについて by FXDD
④PCの処理途中にpipsの更新があり、対応できない場合に注文処理がスルーするのではないか?(この要因は、今回対象外としておきます。)

2つの要因に対する解決策(?)は?
①に対しては、オリジナルのデータを元に、パラメーターの調整をすることで対応する方法がベターかもしれません。
②を今回のテーマと位置づけて考えてみました。
A)まずこのEAの取引条件の要の2つの条件を考えてみます。
1.『上部の乖離線を売値が越えたら売り!』若しくは、『下部の乖離線を買値が下回ったら買い!』としています。
 2.上記かつ、『RSI【(期間14)終値】が(ある数値を越えたら売りorある数値を下回ったら買い)としています。
※つまり、データがまとめて配信され、その中の一部のデータが、取引条件を超えていても
まとめられたデータの最後の値が、取引条件に達していなければ取引は成立しません。
これが、接続状況及びサーバー処理状況による取引回数が減る要因だと考えました。
B)上記の対策として、以下のように取引条件を変更してみました。
1.『上部の乖離線を現在のバーの高値が越えたら売り!』若しくは、『下部の乖離線を現在のバーの安値が下回ったら買い!』
 2.上記かつ、『RSI【(期間14)終値「ただし、現在のバーのみ高値or安値」】が(ある数値を越えたら売りorある数値を下回ったら買い)
C)上記の内容にしたらどうなるか?
利点:『新しいバーが作成されるか、または、注文オーダーが通るまで注文シグナルを送り続けます。』
欠点:『注文は処理されたが、予定値と実際の注文値に開きが生じる可能性がある。』

では、どの様に実装すればよいか?を以下に掲示しておきます。
①まず、『MQL4からRSIの指標を入手し指標のフォルダーに格納』 iRSIの代わりに使用します。
②次に、EAを開き以下のコードを追加する。
【指標の計算の変更(RSI期間14の場合)】
//RSI = iRSI(NULL,0,14,PRICE_CLOSE,0); 『要らないコードの削除もしくはコメント化』
double Hi_RSI;
double Lw_RSI;
double sump=0,sumn=0,rel=0;
double positive=0;
double negative=0;
double B_positive = iCustom(NULL,0,"RSI",1,1);
double B_negative = iCustom(NULL,0,"RSI",2,1);
//Hi_RSI用
rel=High[0]-Close[1];
if(rel>0) sump=rel;
else sumn=-rel;
positive=(B_positive*13+sump)/14;
negative=(B_negative*13+sumn)/14;
if(negative==0.0) Hi_RSI=0.0;
else Hi_RSI=100.0-100.0/(1+positive/negative);
//Lw_RSI用
sump=0;sumn=0;
rel=Low[0]-Close[1];
if(rel>0) sump=rel;
else sumn=-rel;
positive=(B_positive*13+sump)/14;
negative=(B_negative*13+sumn)/14;
if(negative==0.0) Lw_RSI=0.0;
else Lw_RSI=100.0-100.0/(1+positive/negative);
【条件式記入場所】(参考)
(BUY)
if(
(!OderStop)
&&(pos1<Max_Position)
&&(st>=Xox)
&&(Lw_RSI<=RSILowLimt)【RSIをLw_RSIに変更】
&&(MaLow>=Low[0]) 【AskをLow[0]に変更】
&&(ATR<=ATRLimt)
&&((Ask<=(LastPrice-(PipStep*Point)))||pos1==0)【お好みで、ASKをLow[0]に変更】
)Buy_Flag = true;

(SELL)
if(
(!OderStop)
&&(pos2<Max_Position)
&&(st>=Xox)
&&(Hi_RSI>=RSIHiLimt)【RSIをHi_RSIに変更】
&&(ATR<=ATRLimt)
&&(MaHi<=High[0]) 【BidをHigh[0]に変更】
&&((Bid>=(LastPrice+(PipStep*Point)))||pos2==0)【お好みでBidをHigh[0]に変更】
)Sell_Flag = true;

こんな感じになります。

まとめ
本来は、フォームに掲載するような内容ですが、ブログの更新のために使用させて頂きました。
また、お決まりのように、フォワードテスト等をしておりませんので、ご使用される方は、『人柱覚悟!』でお願いします。
では!