移動平均の交互売買の方法

移動平均の交互売買の方法


今回は、xyz__さんからの質問がございましたので、
臨時記事といたしまして、

1.移動平均を上(下)に超えた直後に買い(売り)ポジションを取る。
2.買い(売り)ポジションがある場合は
ポジションを取らない。要はポジションは常に1個
3.移動平均より上(下)でポジションをとった場合は連続でポジションを同じ方向にはとらない。要は買い→売り→買い→売り・・・の法則でのみ
4.買いのポジションで決済されずに売りのポジションを持つ場合は買いを決済して売り
のポジションをもつ

というものを作りましょうか。


まずはパラメータです。

//利食い損切りピプス
extern int TakeProfit = 10;
extern int StopLoss =10;
//ロット数
extern double lots=0.1;
//移動平均の計算期間
extern int maPeriod = 21;

後から設定できる変数ですね。


次に記憶用の変数を宣言します。

int bar,LastType;

いつものように、一つのバーで1回までというようにしたいので
バーの番号を記憶する整数変数 bar と、
買い→売り→買い→売りを交互に注文することを可能にするため
最後におこなった注文を記憶する LastType という変数です。

でわ、
int start()
{
の中身を見ていきましょう!

最初に移動平均線の値を計算します。


//現在の移動平均線の値
double ma0 = iMA(NULL,0,maPeriod,0,MODE_SMA,PRICE_CLOSE,0);
//1つ前の移動平均線の値
double ma1 = iMA(NULL,0,maPeriod,0,MODE_SMA,PRICE_CLOSE,1);


ma0 , ma1 という小数変数を宣言しながら、移動平均線の値を代入しています。
このように変数が初めて出てくるところで宣言してあげても大丈夫なんですね。

今回は、【直後】というキーワードで確定前の一瞬でも超えた時点で
シグナルを出すようにしたため、現在動いている移動平均を使っています。
クロスが確定したときにシグナルを出したいときは、
iMA のカッコ内の最後の数字を1と2にして、
1つ前のバーの移動平均の値と2つ前のバーの移動平均の値を使えばいいですよね。


でわ、つぎにシグナルを出したいと思います。

//シグナル
if(Close[1]<ma1 && Close[0]>ma0) int sign=1;
if(Close[1]>ma1 && Close[0]<ma0) sign=-1;

もし、1つ前のバーの終値が移動平均値がより小さくて、かつ、
今の値が移動平均値より大きい場合は、整数変数 sign に1を代入。
もし、1つ前のバーの終値が移動平均値がより大きくて、かつ、
今の値が移動平均値より小さい場合は、整数変数 sign に-1を代入。

これで、クロスの条件が表現できますね。

1とか-1は勝手に取り決めたものですので、自由です^^;
MT4の取り決めと合わせる場合は買いが0売りが1となると思いますが、個人的に分かり易いものでいいと思います。

if文などの条件内の実行が1行の場合は{}は必要ないですね。


でわ、次です。


// オーダーチェック(ポジションなどのデータ)
int CurrentPosition=-1;
for(int cnt=0;cnt<OrdersTotal();cnt++)
{
OrderSelect(cnt,SELECT_BY_POS);
if(OrderMagicNumber() == 123 && OrderSymbol() == Symbol()) CurrentPosition=cnt;
}

この辺は、【完全自動売買への道のり】で詳しく説明してあると思うのでさらっと行きます。

整数変数 CurrentPosition の宣言で初期値は-1です。
cntが0からポジション総数の数値より小さいうちは{}内を実行しcntに1を足すというのを繰り返す。

インデックスcntのポジションを選択
もし、マジックナンバーが123でかつ、通貨ペアがチャートの通貨ペアと同じなら CurrentPosition にcntの数値を代入する。

と言った感じです。
ここで、マジックナンバーと通貨ペアを照合することによって
他のEAでおこなっている取引をカウントしない。
同じEAでおこなっている他通貨での取引をカウントしない。
という効果があります。

そして、照合した結果、マッチするもののインデックスを CurrentPosition に
代入するといった感じになります。


でわ、次行きましょう。

// ポジションチェック ポジション無し
if(CurrentPosition == -1)
{

です。
前の照合結果、CurrentPosition には何も代入されずに初期値のままのときという感じですね。
なので、【このEAでのこの通貨ペアはもっていない場合】ということになります。


//買い条件
if(bar!=Bars && LastType!=1 && sign==1)
{
//買いポジションを取る
int Ticket = OrderSend(Symbol(), OP_BUY,lots, Ask, 3, Ask-(StopLoss*Point), Ask+(TakeProfit*Point), "test", 123, 0, Blue);
if(Ticket>0)
{
bar=Bars;
LastType=1;
}
}

もし、記憶用の変数 bar の値が今のバーの番号と違って、
記憶用の変数 LastType が1じゃなくて、
sign が1の場合は
()内の条件で買い注文を出しつつ、整数変数 Ticket に注文番号を代入する。
そして、注文番号が0より大きい(注文が成立した)とき
barに現在のバーの番号を代入。
LastTypeに1を代入。

こうしてあげれば、同じバーで複数回注文することがなく前回買い注文を出した場合、
今回は買い注文をださないといった感じになります。


//売り条件
if(bar!=Bars && LastType!=-1 && sign==-1)
{
//売りポジションを取る
Ticket = OrderSend(Symbol(), OP_SELL, lots, Bid, 3, Bid+(StopLoss*Point), Bid-(TakeProfit*Point), "test", 123, 0, Red);
if(Ticket>0)
{
bar=Bars;
LastType=-1;
}
}

売り注文の場合も同じ様にしてあげましょう。


でわ、次に

}
// ポジション有り
else
{

です。

if(CurrentPosition == -1)のカッコを閉じてelseということは CurrentPosition が -1以外の場合、
すなわち【このEAでのこの通貨ペアはもっている場合】ということになります。


さてここからポジション有りの場合の実行コードになります。


//ポジションの選択
OrderSelect(CurrentPosition,SELECT_BY_POS);

持っているポジションの情報を知りたいときにはまずポジションの選択をしてあげなければいけません。
ここで生きてくるのが先ほどのfor文で代入されたインデックスです。
今、CurrentPositionにはfor文で照合にヒットしたインデックスが代入されているので、
そのインデックスのポジションを選択してあげるわけです。


次に、
//もし買いポジションで売りシグナルがでたら
if(OrderType()==OP_BUY && sign==-1)
{
//手仕舞い
OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,Green);
//ドテン売り
Ticket = OrderSend(Symbol(), OP_SELL, lots, Bid, 3, Bid+(StopLoss*Point), Bid-(TakeProfit*Point), "test", 123, 0, Red);
if(Ticket>0)
{
bar=Bars;
LastType=-1;
}
}

内容は、
もし選択されたポジションが買いで、signが-1の場合
選択されたポジションを手仕舞い。
そして、売り注文を出す。
注文成立したときbarに今のバーの番号、LastTypeに-1を代入。

といった感じです。

この取引のシグナルは一つ前のバーでsignが1になるか-1になるか
決定しているので、
同じバーで反対のシグナルが出ることがありません。
もし、同じバーで反対のシグナルが出るようなシステムでも同じバーでは複数回取引をしないという条件にする場合は、ここの条件でもbar!=Barsというものを付け加えなければなりません。


//もし売りポジションで買いシグナルがでたら
if(OrderType()==OP_SELL && sign==1)
{
//手仕舞い
OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,Green);
//ドテン買い
Ticket = OrderSend(Symbol(), OP_BUY,lots, Ask, 3, Ask-(StopLoss*Point), Ask+(TakeProfit*Point), "test", 123, 0, Blue);
if(Ticket>0)
{
bar=Bars;
LastType=1;
}
}

売りポジションを持っているときも同じ様にしてあげます。


そして、最後に

}

return(0);
}

elseのカッコを閉じてあげて、start関数を終了させます。


応援お願いします!
→FXシステムトレード派
→rank応援クリック
→人気ブログランキング


test10.zip(mq4ファイル)のダウンロード


でわ、今回はこの辺で。

2008年1月20日|コメント (3)

カテゴリー:EAの作成方法

コメント (3)

こんばんは。

昨日初めてのEAが完成したので時間足や通貨ペアを色々変えてバックテストしまくってたらメタトレーダーがやたらと重くなったんでファイルを見たら6G以上になってました。

それで色々なファイルを削除したら新規チャートで選択できるチャートの種類が増えました。なぜかそれまではなかったgoldやoilやZARまで選べるようになっちゃいました。

サーバは変わってないみたいなんですけどね。まぁ、それはいい事なんでいいんですけど…

削除してもいいファイルといけないファイルってあるんでしょうか?

特にOptimizationをすると2G以上のファイルができたりしますもんね。

それとMismatched charts errorsとModelling qualityのn/aって何でしょうか?
Modelling qualityはEvery tickでやると90%になると何かで読んだんですが数値はでません。ご存じでしたら教えてください。

長々と質問ばかりですみません。

投稿者:red sauce |2008年1月21日 00:14

記事にまでしていただき感激です!!
じっくりと勉強させていただきます。
本当にありがとうございます。

投稿者:xyz__ |2008年1月21日 08:13

>red sauceさん
こんにちわ。

>新規チャートで選択できるチャートの種類が増えました
なぜでしょうね?私の場合、ODLはもともと選べてましたが^^;

>削除してもいいファイルといけないファイルってあるんでしょうか?

テスターで生成されたファイルは消しても大丈夫そうですが、他は、履歴や設定が保存されたりしているので、そのままにしています。

>Mismatched charts errorsとModelling qualityのn/aって何でしょうか?

Mismatched charts errorsは、別々の時間足で異なるデータがあるときにカウントされます。
n/aはnot allでしょうか^^;完全ではないということだと思います。

>Every tickでやると90%になる
1分足のデータがある期間でやると90%になりますよ。


>xyz__さん
こんにちわ。

がんばりましょうね!

投稿者:慶次 |2008年1月21日 10:38

コメントを投稿する

(初めてのコメントの時は、コメントが表示されるためにこのブログのオーナーの承認が必要になることがあります。承認されるまでコメントは表示されませんのでしばらくお待ちください)






画像の中に見える文字を入力してください。

Captchaの認証で入力ミスがありますと、コメントが消えてしまいますのでご注意ください。
コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。