EAロジック
ボリンジャーバンドを利用してエントリーと手仕舞いをするロジックを複数選択出来るEAです( ・Д・)
パラメーター
【マジックナンバー】
任意の番号を入力して下さい。
【スリッページ】
スリッページの許容限界値を入力して下さい。
【ロット数】
1発注当たりのロット数です。
【利確幅】
利益確定幅(pips)を入力して下さい。
【損切幅】
損失確定幅(pips)を入力して下さい。
【トレーリング】
トレーリングストップを発動させるか否かの選択です。
true=ON,false=OFFです。
【トレーリングストップ幅】
トレーリングで追いかける幅(pips)を入力して下さい。
【コメント】
エントリーしたポジションに表示するコメントを入力して下さい。
【手法選択】
順張り:上バンドを移動平均線が上抜け買いエントリー。下抜け手仕舞いとなります。(売りはその逆)
逆張り:上バンドを移動平均線が上抜け売りエントリー。中央線を下抜けたら手仕舞い。(買いはその逆)
ドテン:上バンドを移動平均線が上抜け売りエントリー&買いポジション手仕舞い。(下バンド時はその逆)
---ボリンジャーバンド---
【期間】
期間を入力して下さい。
【偏差】
標準偏差値を入力して下さい。
【価格】
以下7つから選んで下さい。
Close price:終値
Open price:始値
High price:高値
Low price:安値
Median price:(高値+安値)/2
Typical price:(高値+安値+終値)/3
Weighted price:(高値+安値+終値+終値)/4
---移動平均線---
【期間】
期間を入力して下さい。
【方法】
以下4つから選んで下さい。
Simple:単純移動平均(SMA)
Exponential:指数移動平均(EMA)
Smoothed:平滑移動平均(SMMA)
Linear weighted:線形加重移動平均(LWMA)
【価格】
以下7つから選んで下さい。
Close price:終値
Open price:始値
High price:高値
Low price:安値
Median price:(高値+安値)/2
Typical price:(高値+安値+終値)/3
Weighted price:(高値+安値+終値+終値)/4
ロジックイメージ
※良い所を抽出して表示していますので騙されないで下さいw( ・Д・)
【順張り設定】
ソースコード説明
今回のソースコードはこちら「BB_Cross_Zn」←クリックするとPDFファイルが開きます。
こちらの記事では細かい説明などは一部省きますので、よく分からない方は一度「潤奈流EA講座」から目を通してみて下さい( ・Д・)
パラメーター設定
1 2 3 4 5 6 7 8 9 |
//---パラメーター設定 sinput int MagicNumber=2021; //マジックナンバー input int Slippage=10; //スリッページ input double Lots=0.01; //ロット数 input int TakeProfit=100; //利確幅(pips) input int StopLoss=50; //損切幅(pips) input bool TrailingSwitching=true; //トレーリング(On=true;OFF=false) input int TrailingPips=20; //トレーリングストップ幅(pips) input string comment="BB_Cross_Zn"; //コメント |
1文づつの構成は、「修飾子 型 固有名=値; //コメント」となります。
それぞれの固有名に代入する値の種類によって、型が違っています。
手法選択
1 2 3 4 5 6 7 |
//---手法選択 enum MethodChange{ MarketFollower, //順張り Contrarian, //逆張り Doten //ドテン }; input MethodChange MethodInput=MarketFollower; //手法選択 |
列挙型(enum)は任意のリストを定義する事が出来ます。以下簡単に説明します。
構成は、「型 列挙名{定数リスト1,定数リスト2,定義リスト3};」となります。
定義リストは数を増やす事が出来ます。
次に「装飾子 列挙名(型) 変数=定数リスト;」で定義リストから選択出来るようになります。
これで選択した定数リストを変数に代入して以降のプログラムで使用します。
コードと説明だけでも分かりづらいと思いますので、視覚的に表すと以下のようになります。
まずリストを定義して、そのリストから選択をするという事です。コードと見比べて分解してみて下さい。
インジケーター設定
1 2 3 4 5 6 7 8 9 |
//---インジケーター設定 input string BB=""; //ボリンジャーバンド input int BBPeriod=20; //期間 input int BBDeviation=2; //偏差 input ENUM_APPLIED_PRICE BBPrice=PRICE_CLOSE; //価格 input string MA=""; //移動平均線 input int MAPeriod=5; //期間 input ENUM_MA_METHOD MAMethod=MODE_SMA; //方法 input ENUM_APPLIED_PRICE MAPrice=PRICE_CLOSE; //価格 |
2行目と6行目はBBとMAという空の箱を用意し、右のコメントをパラメーター設定画面に表示する事で見やすくする為に追加している物ですので、内部プログラム自体には関係ない物になります。
↓パラメーター設定画面
「BBPeriod,MAPeriod(期間)」と「BBDeviation(偏差)」は先ほどのパラメーター設定での構成と同じ様になっていますが、「MAMethod(方法)」と「BBPrice,MAPrice(価格)」については少し見慣れない物が型の部分にありますね。
これはあらかじめMT4にいくつかの標準的なテクニカル指標は入力パラメーターとしてリスト化されており、使用する事で大変便利になります。
まずMAMethod(方法)について、計算で使用される平滑化の計算方法を指定するために ENUM_MA_METHOD列挙にリストされている識別子が選択出来るようになります。
[table id=1 /]
次にBBPrice,MAPrice(価格)について、計算に使用する価格ベースを指定するための ENUM_APPLIED_PRICE列挙に7つの事前定義された識別子が選択出来るようになります。
[table id=2 /]
ロジック構成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
void OnTick(){ //ティック受信する度に動くプログラム //トレーリングストップ if(TrailingSwitching){ int sec=TimeSeconds(TimeGMT()); if(sec==0 || sec==30){ TrailingStop(); } } //ポジション数を確認 int BuyPosition=Position(1); int SellPosition=Position(-1); //エントリー判定 int Entry=0; int Closed=0; if(MethodInput==MarketFollower){ //順張りロジック if(BuyPosition==0){ if(BBCross1()==1)OpenOrder(1); }else{ if(BBCross2()==1)CloseOrder(1); } if(SellPosition==0){ if(BBCross1()==-1)OpenOrder(-1); }else{ if(BBCross2()==-1)CloseOrder(-1); } }else if(MethodInput==Contrarian){ //逆張りロジック if(BuyPosition==0){ if(BBCross1()==-1)OpenOrder(1); }else{ if(BBCross3()==1)CloseOrder(1); } if(SellPosition==0){ if(BBCross1()==1)OpenOrder(-1); }else{ if(BBCross3()==-1)CloseOrder(-1); } }else if(MethodInput==Doten){ //ドテンロジック if(BuyPosition==0){ if(BBCross1()==-1)OpenOrder(1); }else{ if(BBCross1()==1){ CloseOrder(1); OpenOrder(-1); } } if(SellPosition==0){ if(BBCross1()==1)OpenOrder(-1); }else{ if(BBCross1()==-1){ CloseOrder(-1); OpenOrder(1); } } } }//OnTick |
OnTick関数では価格を受信する度に動く関数になりますのでこの中にロジックを記入して行きます。
トレーリングストップ
if関数でTrailingSwitchingがture(真)かfalse(偽)を確認し、ture(真)であれば{ }内に進みます。
1 2 3 4 5 |
if(TrailingSwitching){ //トレーリングストップの内容 } |
次にsec変数をint型で宣言し、その中に秒を代入します。
1 |
int sec=TimeSeconds(TimeGMT()); |
秒の取得方法は、TimeSeconds関数とTimeGMT関数を使用します。
TimeSeconds( )は指定した日付データの秒を返します。
TimeGMT( )はPCのローカル時間から計算されたGMT時間を返します。
この2つを組み合わせて、TimeGMT()で取得した時間をTimeSeconds()を使って秒だけ抜き出します。
よって、sec=TimeSeconds(TimeGMT());で現在の秒を取得します。
次の条件はif関数でsecが0秒か30秒かを確認します。
条件に合致すればTrailingStop()関数に移動します。
1 2 3 |
if(sec==0 || sec==30){ TrailingStop(); } |
このような条件を付ける理由は、トレーリングストップは損切値の注文変更を行います。その注文変更をティック更新毎に行ってしまうと証券会社に嫌われるからです。あとは、システム負担の低減ですね。
ポジション数を確認
BuyPosition変数にPosition関数で取得した買いポジション数を代入します。
SellPosition変数には売りポジション数を代入します。
1 2 |
int BuyPosition=Position(1); int SellPosition=Position(-1); |
エントリー判定
int型で宣言したEntry変数とClosed変数に0を代入して0リセットします。
1 2 |
int Entry=0; int Closed=0; |
この中に買いエントリー&手仕舞いタイミングと売りエントリー&手仕舞いタイミングで1か-1を代入するように準備します。
さて、ここからが少しややこしいですので頑張って下さい( ・Д・)
まずそれぞれのオリジナル関数についてまず簡単に説明しておきます。
これらの関数を組み合わせてロジックを組んでいきます。
分割して説明しますね~( ・Д・)まず3つのロジックをif~else if文で分けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if(Methodinput==MarketFollower){ //順張りロジック //ここに順張りのロジックを記述します。 }else if(MethodInput==Contrarian){ //逆張りロジック //ここに逆張りのロジックを記述します。 }else if(MethodInput==Doten){ //ドテンロジック //ここにドテンのロジックを記述します。 } |
else ifとは前の条件に当てはまらず、次の条件に当てはまる場合という意味です。
このプログラムの途中を改行していたのは、if文の条件式を同列にした方が見やすいかな~と( ・Д・)
では順張りロジックから、
1 2 3 4 5 6 7 8 9 10 11 12 |
if(MethodInput==MarketFollower){ //順張りを選択している場合 if(BuyPosition==0){ //買いポジションが0の場合 if(BBCross1()==1)OpenOrder(1); //上バンドを移動平均線が上抜けた時、買い注文 }else{ //買いポジションが0じゃない場合 if(BBCross2()==1)CloseOrder(1); //上バンドを移動平均線が下抜けた時、買いポジション手仕舞い } if(SellPosition==0){ //売りポジションが0の場合 if(BBCross1()==-1)OpenOrder(-1); //下バンドを移動平均線が下抜けた時、売り注文 }else{ //売りポジションが0じゃない場合 if(BBCross2()==-1)CloseOrder(-1); //下バンドを移動平均線が上抜けた時、売りポジション手仕舞い } } |
BuyPositionとSellPositionはelse ifではなくelseだけとなっていますが、これは前の条件に当てはまらない場合はこちらを処理するという意味になります。
つまりポジション数が0でないならポジション持ってますよね!で手仕舞いの処理に進むようにしています。
次に逆張りロジック
1 2 3 4 5 6 7 8 9 10 11 12 |
if(MethodInput==Contrarian){ //逆張りを選択している場合 if(BuyPosition==0){ //買いポジションが0の場合 if(BBCross1()==-1)OpenOrder(1); //下バンドを移動平均線が下抜けた時、買い注文 }else{ //買いポジションが0じゃない場合 if(BBCross3()==1)CloseOrder(1); //中央線を移動平均線が上抜けた時、買いポジション手仕舞い } if(SellPosition==0){ //売りポジションが0の場合 if(BBCross1()==1)OpenOrder(-1); //上バンドを移動平均線が上抜けた時、売り注文 }else{ //売りポジションが0じゃない場合 if(BBCross3()==-1)CloseOrder(-1); //中央線を移動平均線が下抜けた時、売りポジション手仕舞い } } |
最後にドテンロジック
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
if(MethodInput==Doten){ //ドテンを選択している場合 if(BuyPosition==0){ //買いポジションが0の場合 if(BBCross1()==-1)OpenOrder(1); //下バンドを移動平均線が下抜けた時、買い注文 }else{ //買いポジションが0じゃない場合 if(BBCross1()==1){ //上バンドを移動平均線が上抜けた時 CloseOrder(1); //買いポジション手仕舞い OpenOrder(-1); //売り注文 } } if(SellPosition==0){ //売りポジションが0の場合 if(BBCross1()==1)OpenOrder(-1); //上バンドを移動平均線が上抜けた時、売り注文 }else{ //売りポジションが0じゃない場合 if(BBCross1()==-1){ //下バンドを移動平均線が下抜けた時 CloseOrder(-1); //売りポジション手仕舞い OpenOrder(1); //買い注文 } } } |
以上が全体の動きのロジックになります( ・Д・)
オリジナル関数
AdjustPoint関数
AdjustSlippage関数
以上2つについては潤奈流EA講座④で説明していますのでご覧下さい。
Position関数
OpenOrder関数
CloseOrder関数
以上3つについては潤奈流EA講座⑤で説明していますのでご覧下さい。
TrailingStop関数
こちらは潤奈流EA講座⑥で説明していますのでご覧下さい。
今回のエントリー&決済シグナルとなるロジック関数は以下記事で説明していますのでご覧下さい。
BBCross1関数(ボリンジャーバンドクロス:順)
https://zyunafx.com/original_function-4/
BBCross2関数(ボリンジャーバンドクロス:逆)
https://zyunafx.com/original_function-5/
BBCross3関数(ボリンジャーバンドクロス:中)
https://zyunafx.com/original_function-6/
まとめ
今回はボリンジャーバンドを使った3つの組み合わせロジックのEAの解説でしたが如何でしたでしょうか。
ロジックを選択出来るように列挙型なるものを使用したりして、少し複雑になっていますが一つずつ動作を確認して行けば理解出来ますので頑張ってください。
シンプルに、カスタマイズしやすいように書いたつもりですので是非参考にして下さい( ・Д・)
分からない事などがありましたらコメント下さいね!ググりますので( ・Д・)w
コメント
潤奈さんはじめまして!
EAのコードを勉強し始めて、こちらのブログにたどり着いたものです!
こちらのEAのコードに、別ページの指定した曜日のエントリー禁止関数と、指定した時間帯のエントリー禁止関数を組み込みたいと考えています。
その場合にどこに組み込むのが、1番美しく見えますかね?
まだまだ素人なものなのでチンプンカンプンです
カプさん様
コメントありがとうございます。返信が遅くなりすみません。
そうですね。。。どちらの記事も出来る事を欲張って書いているので、全部盛り込もうとすると難しいかもしれません。
まずはシンプルにボリンジャーバンドのロジックも順張りロジックだけなど1つに絞って、それにエントリー禁止制御を加えてみるなどの段階を踏んだ方が良いと思います。
例えば、
if(エントリー禁止曜日チェック){
if(エントリー禁止時間チェック){
if(BuyPosition==0){ //ポジション確認
if(BBCross1()==1)OpenOrder(1); //エントリーロジック
}
}
}
そもそもポジション持っていた場合にエントリーは不要であれば、
if(BuyPosition==0){ //ポジション確認
if(エントリー禁止曜日チェック && エントリー禁止時間チェック){
if(BBCross1()==1)OpenOrder(1); //エントリーロジック
}
}
の様に先にポジションを確認するようにすれば、曜日と時間制御の関数処理を省く事も出来ます。
if文の階層が多くなるようであれば、&& で条件を繋げるものありです。
注意として、決済ロジックをこの曜日と時間制御の中に入れてしまった場合、時間内に決済されない場合次の曜日と時間までエントリーしたままになる。などありますので、ロジックにもよりますが自分の考えている動作が出来ているか確認しながら頑張ってみて下さい( ゚Д゚)