(MQL4)インジケーターをEA化するやり方[EA自作]
目次/もくじ
iCustomでZigZagをEA化する(初歩編)
インジケーターとiCustom
今回はインジケーターのシグナルを使って、EAを作ります。iCustomという関数を使うとインジケーターをEAのロジックに組み込むことができるようになります。
ただし、すべてのインジケーターがiCustomでデータを取得できるわけではありません。
シグナルをバッファとして出力するインジケーターでないとiCustomが使えません。
具体的には、チャート上にセットしたインジケーターのラインや矢印にマウスカーソルをのせて、Value1やValue2などという表示がでれば、iCustomでEA化できます。
iCustomは
1 2 |
iCustom(通貨ペア, 時間枠, "インジケーター名", インジケーターのパラメータ,インジケーターのパラメータ..... , バッファ,シフト); |
という記述で扱うことができます。
インジケーター名の後にはそのインジケーターのパラメータを複数渡すことができます。
バッファというのはそのインジケーターが返す値の種類のことです。
MT4のインジケーターには8つまでのバッファを組み込むことができ、それぞれのバッファにシグナルのデータが格納されています。たとえば、バッファ1には上向きの矢印の数値が入っていたり、バッファ2には下向きの矢印のデータが入っていたり、といった具合です。
それぞれのバッファにはシグナルのデータが入っているので、iCustomの引数のバッファの数値を変えると、そのインジケーターの上矢印の値や下矢印の値などをそれぞれ取得できます。
シフトは欲しい値のロウソク足の場所です。0なら現在のロウソク足、1なら一本前のロウソク足になります。
とりあえずZigZagインジケーターを例に
ここではMT4に標準搭載されているZIGZAG(ジグザグ)というインジケーターでEA化します。
デフォルトでインジケーターフォルダにセットされているのでZigZagインジケーターをダウンロードする必要はありません。
ZigZagは以下のようなジグザグ線を描くインジケーターです。
ZigZagはそのロウソク足が頂点になったときにバッファ0と1と2が値を返します。
今回は3つ前のロウソク足が頂点になった際にエントリーするロジックを考えます。
ZigZagの下向き頂点で買いエントリー、上向き頂点で売りエントリー
3つ前のロウソク足でのZigZagは
1 |
iCustom(Symbol(),Period(),"ZigZag",0,3); |
として記述できます。
ZigZagインジケーターは頂点でないときには上の値(バッファ)が0になり、頂点になった場合にはそのときの高値or安値のレートが返ります。
そのため、3本前のロウソク足が上向きの頂点になったときは、
1 2 |
if( iCustom(Symbol(),Period(),"ZigZag",0,3) == iHigh(Symbol(),Period(),3),Digits) |
とすれば良さそうですが、
イコール として条件を組んでしまうと、小数点以下で一致しないバグが起こります。
具体的には、
if( 110.001 == 110.001 )
に外見上は見えていても、
if( 110.001 == 110.00100001 )
になっていることがあるという訳です。
そのため、少数を3桁に四捨五入する関数を使います。
1 |
NormalizeDouble(四捨五入する数, 少数第何位か) |
で数の小数点をそろえることができます。
その通貨ペアの最小桁数を表すDigitsを使います。
上記の条件式の少数点以下をそろえると、
1 2 |
NormalizeDouble(iCustom(Symbol(),Period(),"ZigZag",0,3),Digits) == NormalizeDouble(iHigh(Symbol(),Period(),3),Digits) |
となります。
逆の場合は、HighをLosに変えて
1 2 |
NormalizeDouble(iCustom(Symbol(),Period(),"ZigZag",0,3),Digits) == NormalizeDouble(iLow(Symbol(),Period(),3),Digits) |
となります。
テスト結果は以下のようになります。
リペイントインジケーターに注意
ZigZagはリペイント(再描写)を行うので、EAでエントリーしたときの様子と後から見た様子がかなり変わります。
このような後出しインジケーターは多く、インジケーターをEA化する際にはこのような点にも注意しなければなりません。
- 特に注意しなければならない特徴は、
- 最新のロウソク足ではなく、数本前のロウソク足にシグナルを表示させるインジケーター
- 一度描写したシグナルを消すインジケーター
- 一度描写したシグナルを変更するインジケーター
- セットしたタイミングによって描写が変わるインジケーター
などがあります。
(MQL4)市販のインジケーターをEA化するやり方 実践編(EA自作)
市販のインジケーターのEA化
上ではMT4に標準搭載されているZIGZAGを対象のインジケーターとして使いましたが、今回は市販のインジケーターでよくあるパターンでやってみます。
具体的には、
- インジケーターのexファイルはあるが、mqファイルはない
- チャート上にセットすると買いと売りのサインがでる
という設定です。
まず、このインジケーターがどのような挙動をするかを把握する必要があります。
・矢印はバッファに値が入っているのか否か(カーソルを合わせたときに数字が出るか否か)
・リペイントはするのかどうか
・現在足でサインがでることはあるか(その場合消えるかどうか)
インジケーターの挙動を調べるコード
まずは、てきとうにEAファイルを作ってインジケーターの挙動をざっくり調べます。
1 2 3 4 5 6 7 8 9 10 11 |
void OnTick() { //--- Comment("0,1:"+iCustom(Symbol(),Period(),"インジケーターの名前",0,1)+"n"+ "1,1:"+iCustom(Symbol(),Period(),"インジケーターの名前",1,1)+"n"+ "2,1:"+iCustom(Symbol(),Period(),"インジケーターの名前",2,1)+"n"+ "3,1:"+iCustom(Symbol(),Period(),"インジケーターの名前",3,1)+"n"+ "4,1:"+iCustom(Symbol(),Period(),"インジケーターの名前",4,1)+"n"+ "5,1:"+iCustom(Symbol(),Period(),"インジケーターの名前",5,1)+"n"+ "6,1:"+iCustom(Symbol(),Period(),"インジケーターの名前",6,1)+"n"); } |
このコードはインジケーターの挙動を調べるための”ざっくりとした”コードです。
調べる対象のインジケーター名を”インジケーターの名前”と入れ替えてください。拡張子(ex.4)はあってもなくても大丈夫です。
括弧の前の数字は最新のロウソク足の右からの順番(現在足は0)その左の数字はバッファを表します。
おさらいですが、バッファというのはインジケーターを開発する際に線とかヒストグラムを描画する際に使うもので、バッファに数字を入れてバッファの描画タイプを指定することでチャートに表示させています。
後はこれをコンパイルして、
- ストラテジーテスターで
- ビジュアルモードで
- 対象のインジケーターをチャートにセットした状態で
テストを行います。
コンパイルが何かわからない方はこちら
ソースコード(.mq)からEA(.ex4)を生成するやり方[EA自作]
すると、ちょっと見にくいですが、一つ前の足に矢印があるとき、{2 1} に値が入っていることが分かります。矢印がないときには0として表示されるので、「上向きの矢印があるときにはそのレートがバッファに反映される」ということがわかります。
同じように上向きの矢印は{3 1}に値が入ることがわかります。
つまり
- 上向きの矢印がでる = バッファ2が0でない(そのときのレートが入る)
- 下向きの矢印がでる = バッファ3が0でない(そのときのレートが入る)
ということが分かります。
ちなみに、チャート上の上向きの矢印にカーソルを合わせたときに「Value3:111.429」とでますが、実際のバッファ指定の際には0スタートのため、1ずれて2番になります。
具体的に言うと、
- iCustom(Symbol(),Period(),”ArrowIndicator”,2,1) <- こっちが上向き矢印
- iCustom(Symbol(),Period(),”ArrowIndicator”,3,1) <- こっちが下向き矢印
(バッファは0スタートなので1ずれる)
あとは、これを条件に式を作ればいいだけなので、
1 2 3 4 5 6 7 8 9 10 |
if( iCustom(Symbol(),Period(),"ArrowIndicator",2,1) > 0 ) { //買いオーダー //もしくは売りポジション決済 } else if( iCustom(Symbol(),Period(),"ArrowIndicator",3,1) > 0 ) { //売りオーダー //もしくは買いポジション決済 } |
※オーダー処理については「EA開発講座」を参照してください。
新規オーダーを送信するOrderSendの書き方[EA自作]
EA化する際の注意
実際には特定の条件下で変な挙動をするインジケーターなどもあるので、もう少し慎重に調べ上げてから実装するのが賢明です。
また、このインジケーターは現在足ではリペイントを行うので、確定足でコーディングした方が良いパターンでした。
この他にも
”バッファを一切使わずにオブジェクトで矢印を表示するインジケーターや
”過去10本以上さかのぼってリンペイントするインジケーター”
などいろいろありますので、その都度試してみてください。
iCustomでインジケーターのEA化 実践サンプル
もう一つインジケーターをEA化してみます。
こちらは読者の方からいただいた「EMA signal」という矢印系のインジケーターです。
矢印にマウスカーソルを当てると、
- 緑色の上向き矢印=Value1=buffer0
- 赤色の下向き矢印=Value2=buffer1
と出ることから、それぞれのバッファ値の対応が分かります。
次に、このインジケーターの挙動を一応調べます。
私が使っているパソコンは普通のパソコンの4倍以上の解像度があるので、左上のCommentの出力がつぶれてしまっていますが、「矢印が出るときはそのその矢印が出ているときのレートを表示し、それ以外ではint型のmax値2147483647が常に入っている」仕様だとわかります。
つまり、iCustomの出力値がある程度膨大な数よりも小さければ、矢印が出現しているということになります。
1 2 3 4 5 6 7 8 9 10 |
if( iCustom(Symbol(),Period(),"EMA Signal",0,1) < 10000000 ) { //買いオーダー //もしくは売りポジション決済 } else if( iCustom(Symbol(),Period(),"EMA Signal",1,1) < 10000000 ) { //売りオーダー //もしくは買いポジション決済 } |
今回はてきとうに10,000,000にしました。この値ならint型の最大値2147483647よりも十分に小さく、また、ビットコインを円表示した際の1,000,000よりも十分に大きいので、どの相場にも適応できます。
次に、フィルターを考えてみます。
これはHBBというインジケーターで、上昇トレンドのときは青いラインがレートに下にサポートラインのように表示され、下降トレンドの時には赤いラインがレジスタンスラインのように表示されます。
これを先ほどのEMA signalのフィルター(エントリーする前の前提条件)にしましょう。
まずはこのインジケーターの挙動を調べます。(さすがに文字がつぶれて分析不能なので、オブジェクト関数で出力しました。)
よく観察すると、青いサポートラインが表示されている間はバッファ0とバッファ4の値に青い点のレートが格納されることが分かります。
そして、赤いラインがでているときは、
バッファ1とバッファ5に赤いラインのレートが格納されていることが分かります。
つまり、
- 青いラインが出ている=バッファ0バッファ4にレートが入っている
- 赤いラインが出ている=バッファ1バッファ5にレートが入っている
また、
- 青いラインがでていない=バッファ0が-1で、バッファ4がintの最大値
- 赤いラインがでていない=バッファ1が-1で、バッファ5がintの最大値
と言うことが分かります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void OnTick() { //青いラインがでている=バッファ0が-1でない if( iCustom(Symbol(),Period(),"HBB",0,1) != -1 ) { if( iCustom(Symbol(),Period(),"EMA Signal",0,1) < 10000000 ) { //買いオーダー //もしくは売りポジション決済 } } //赤いラインがでている=バッファ1が-1でない else if( iCustom(Symbol(),Period(),"HBB",1,1) != -1 ) { if( iCustom(Symbol(),Period(),"EMA Signal",1,1) < 10000000 ) { //売りオーダー //もしくは買いポジション決済 } } } |
これで、
- HBBの青いラインが出ていて、上向きの緑色の矢印がでたときに買い
- HBBの赤いラインが出ていて、下向きの赤色の矢印がでたときに売り
という順張りロジックが出来上がります。(逆張りにしたい場合や押し目狙いにしたい場合は適宜if文を入れ替えればOKです。)
少し整えてバックテストできるようにしましょう。
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 |
#property strict input double Lot = 0.01; input double SLpips = 15; input double TPpips = 5; input int Magic = 114514; void OnTick() { if( OrdersTotal() > 0 ) return; //青いラインがでている=バッファ0が-1でない if( iCustom(Symbol(),Period(),"HBB",0,1) != -1 ) { if( iCustom(Symbol(),Period(),"EMA Signal",0,1) < 10000000 ) { //買いオーダー int Ticket = OrderSend(Symbol(),OP_BUY,Lot,Ask,30,0,0,NULL,Magic,0,clrRed); if( Ticket > 0 ) { OrderSelect(Ticket,SELECT_BY_TICKET); double SL = NormalizeDouble(OrderOpenPrice() - SLpips*10*Point,Digits); double TP = NormalizeDouble(OrderOpenPrice() + SLpips*10*_Point,Digits); OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP,0,clrNONE); } } } //赤いラインがでている=バッファ1が-1でない else if( iCustom(Symbol(),Period(),"HBB",1,1) != -1 ) { if( iCustom(Symbol(),Period(),"EMA Signal",1,1) < 10000000 ) { //売りオーダー int Ticket = OrderSend(Symbol(),OP_SELL,Lot,Bid,30,0,0,NULL,Magic,0,clrBlue); if( Ticket > 0 ) { OrderSelect(Ticket,SELECT_BY_TICKET); double SL = NormalizeDouble(OrderOpenPrice() + SLpips*10*Point,Digits); double TP = NormalizeDouble(OrderOpenPrice() - SLpips*10*_Point,Digits); OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP,0,clrNONE); } } } } |
超絶グチャグチャですが、狙った通りの売買ができています。
せっかくなので、SLとTPを過剰最適化させます。(笑)
USDJPY 2019.11.1~2020.7.1 M5 x軸:SL, y軸:TP
過剰最適化っていうか、もはや異常値の作為的抽出ですね。
iCustomではEA化できないインジケーターをEA化するやり方
世の中にはいろいろなMT4用インジケーターがあるわけですが、その中にもEA化できるインジケーターとEA化できないインジケーターがあります。ここではぱっと見ではEA化できないインジケーターをEA化する方法についてご紹介します。
EA化できるインジケーターとできないインジケーターの違いとは
そもそも、EAできるできないの境目はどうなっているかというと、基本的にはインジケーターのプログラミングの書き方に依存しています。
具体的にはバッファに値を格納しているかどうか、ということになります。
バッファというのは、MT4なら8つまで登録可能なインジケーターが出力するシグナルデータのことです。(MT5なら500以上登録可能です。)
サブウィンドウに表示されるオシレーター系のインジケーターの場合は、オシレーターのラインそのものがバッファで構成されています。
メインチャートに表示されるインジケーターの場合は、マウスを近づけたときに、値が表示されるものがバッファです。
EA化できない原因は
インジケーターをEA化するには通常MQLのiCustomという関数を使います。トレーダーの方ならiCustomは名前だけは聞いたことがあると思います。
オシレーター系のインジケーターの場合は、ラインを描画するためにバッファが不可欠なので問題はないのですが、メインチャートに表示される矢印系のインジケーターの場合には、そもそもバッファで処理していないことがあります。
「バッファでシグナルを処理するようにプログラミングしていないこと」、これがiCustomでインジケーターをEA化できない原因です。
バッファレスインジケーターはiCustomではEA化できません。
iCustomが通用しないインジケーターをEA化するには
一般的には、バッファに値を入れないタイプのインジケーターの場合、「残念ですが、EA化は諦めてください」ということになるのですが、実はEA化することは可能です。
MQLプログラマの方で、オブジェクト関数をよく触る人なら気づいていると思いますが、チャート上に表示されているオブジェクトはそれぞれスクリプト側から制御することができます。
要するに、オブジェクトでシグナルを出力しているなら、オブジェクト関数で処理すればいいじゃない、って話です。
ここでいうオブジェクトとは、オブジェクト指向のオブジェクトではなく、チャート上に表示される矢印とか星とか花マークとかトレンドラインのことです。
オブジェクト関数の操作権限は、プログラムをセットしているチャートやオブジェクトを生成したプログラムには依存しないので、他のプログラムが生成したオブジェクトを取得することが可能です。
分かりやすく言うと、
・インジケーターが矢印とか花マーク(オブジェクト)とか表示
・EAがチャート上に表示されたマーク(オブジェクト)の情報を取得
・取得したオブジェクトの情報を元に自動売買
という構図です。
一般的なインジケーターからEA化する場合は、
・EAがインジケーターのバッファをiCustomという関数で取得
・iCustomのデータを基に自動売買
なので、
一般的なやり方と比べるとプロセスが増えます。
iCustomでインジケーターをEA化する場合のデメリット
チャート上に出力されたオブジェクトを元にEAに自動売買をさせる場合、EAのセットとは別にインジケーターも毎度セットする必要があります。(たいした手間ではないですが…)
一見これはデメリットに見えますが、実はメリットでもあります。
というのも、世の中には
・セットしたタイミングやその他条件によって描写が変わるインジケーター
があることです。
EAの内部でiCustomでインジケーターを処理した場合、トレーダーがデバッグのためにチャートにインジケーターをセットすると、その描写と異なる演算結果を出力することがあります。
これは、EAがインジケーターを処理し始めたタイミングが、EAがチャートにセットされたタイミングで行われるのに対して、チャート上で表示されるインジケーターの演算の開始がチャートにセットされたタイミングで起こることに起因します。
それがiCustomのデメリットであり、クレームの原因になる訳ですね。
オブジェクト関数でインジケーターをEA化するやり方
今回はMAのクロスを矢印でシグナルとして出力するインジケーターをEA化してみます。
インジケーターのオブジェクトを分析する
(例によってMyPCは解像度がアホみたいに高いので矢印が小さいですが、普通のパソコンなら矢印がもっと大きく表示されると思います。)
インジケーターのソースコード(mq4)
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
#property indicator_chart_window #property indicator_buffers 2 #property indicator_color1 LawnGreen #property indicator_color2 Red //---- //---- extern int FastMA_Mode=1; //0=sma, 1=ema, 2=smma, 3=lwma, 4=lsma extern int FastMA_Period= 5; extern int FastPriceMode=0;//0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2, 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4 extern int SlowMA_Mode=1; //0=sma, 1=ema, 2=smma, 3=lwma, 4=lsma extern int SlowMA_Period= 6; extern int SlowPriceMode=0;//0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2, 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4 double CrossUp[]; double CrossDown[]; int flagval1=0; int flagval2=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- indicators SetIndexBuffer(0,CrossUp); SetIndexBuffer(1,CrossDown); GlobalVariableSet("AlertTime"+Symbol()+Period(),CurTime()); GlobalVariableSet("SignalType"+Symbol()+Period(),OP_SELLSTOP); // GlobalVariableSet("LastAlert"+Symbol()+Period(),0); //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- GlobalVariableDel("AlertTime"+Symbol()+Period()); GlobalVariableDel("SignalType"+Symbol()+Period()); // GlobalVariableDel("LastAlert"+Symbol()+Period()); //---- return(0); } //+------------------------------------------------------------------+ //| LSMA with PriceMode | //| PrMode 0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2, | //| 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4 | //+------------------------------------------------------------------+ double LSMA(int Rperiod,int prMode,int shift) { int i; double sum,pr; int length; double lengthvar; double tmp; double wt; //---- length=Rperiod; //---- sum=0; for(i=length; i>=1;i--) { lengthvar=length+1; lengthvar/=3; tmp=0; switch(prMode) { case 0: pr=Close[length-i+shift];break; case 1: pr=Open[length-i+shift];break; case 2: pr=High[length-i+shift];break; case 3: pr=Low[length-i+shift];break; case 4: pr=(High[length-i+shift] + Low[length-i+shift])/2;break; case 5: pr=(High[length-i+shift] + Low[length-i+shift] + Close[length-i+shift])/3;break; case 6: pr=(High[length-i+shift] + Low[length-i+shift] + Close[length-i+shift] + Close[length-i+shift])/4;break; } tmp =(i - lengthvar)*pr; sum+=tmp; } wt=sum*6/(length*(length+1)); //---- return(wt); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { int i,counter; double tmp=0; double fastMAnow,slowMAnow,fastMAprevious,slowMAprevious; double Range,AvgRange; int counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; int limit=Bars-counted_bars; if(counted_bars==0) limit-=1+9; //---- for(i=0; i<=limit; i++) { counter=i; Range=0; AvgRange=0; for(counter=i;counter<=i+9;counter++) { AvgRange=AvgRange+MathAbs(High[counter]-Low[counter]); } Range=AvgRange/10; //---- if(FastMA_Mode==4) { fastMAnow=LSMA(FastMA_Period,FastPriceMode,i); fastMAprevious=LSMA(FastMA_Period,FastPriceMode,i+1); } else { fastMAnow=iMA(NULL,0,FastMA_Period,0,FastMA_Mode,FastPriceMode,i); fastMAprevious=iMA(NULL,0,FastMA_Period,0,FastMA_Mode,FastPriceMode,i+1); } if(SlowMA_Mode==4) { slowMAnow=LSMA(SlowMA_Period,SlowPriceMode,i); slowMAprevious=LSMA(SlowMA_Period,SlowPriceMode,i+1); } else { slowMAnow=iMA(NULL,0,SlowMA_Period,0,SlowMA_Mode,SlowPriceMode,i); slowMAprevious=iMA(NULL,0,SlowMA_Period,0,SlowMA_Mode,SlowPriceMode,i+1); } if((fastMAnow>slowMAnow) && (fastMAprevious<slowMAprevious)) { if(i==1 && flagval1==0){ flagval1=1; flagval2=0; } CrossUp[i]=Low[i]-Range*0.75; ObjectCreate(ChartID(),"BuyArrow"+iTime(Symbol(),Period(),i),OBJ_ARROW,0,iTime(Symbol(),Period(),i),iLow(Symbol(),Period(),i)); ObjectSetInteger(0,"BuyArrow"+iTime(Symbol(),Period(),i),OBJPROP_ARROWCODE,SYMBOL_ARROWUP); } else if((fastMAnow<slowMAnow) && (fastMAprevious>slowMAprevious)) { if(i==1 && flagval2==0) { flagval2=1; flagval1=0; } CrossDown[i]=High[i]+Range*0.75; ObjectCreate(ChartID(),"SellArrow"+iTime(Symbol(),Period(),i),OBJ_ARROW,0,iTime(Symbol(),Period(),i),iHigh(Symbol(),Period(),i)); ObjectSetInteger(0,"SellArrow"+iTime(Symbol(),Period(),i),OBJPROP_ARROWCODE,SYMBOL_ARROWDOWN); } } return(0); } //+------------------------------------------------------------------+ |
ちなみに、チャート上に表示されているオブジェクトは
・チャート上で右クリック
・オブジェクトリストをクリック
で参照できます。
このインジケーターはご親切にも矢印をバッファでも出力してくれているので、正直言うとiCustomでもEA化可能です。
あまり見慣れないかもしれませんが、「チャート」の「オブジェクト」の「オブジェクトリスト」を選択すると、現在表示しているチャート上に描画されているオブジェクトの一覧を見ることができます。
そもそもの話ですが、チャート上に表示されているオブジェクト名は必ず重複しない名前になっているので、オブジェクト名とシグナルの対応が取れれば自動売買ソフト化ができます。
今回の場合は買い矢印の場合「BuyArrow+その足のオープンの時間」、売り矢印の場合は「SellArrow+その足のオープンの時間」となっているので、逆にこれで取得すればいいという話になります。
(チャート上にたくさんの矢印や花などのマークを描画させる場合、それぞれをわかりやすく区別する必要があるため、大抵は記号名+時間に関連する数字がオブジェクト名になっています。今回はUnixタイムですが、その他は大抵Barsとかです。)
EA側でオブジェクト関数を使ってオブジェクトの情報を取る
もう、ここまでくればあとはただのオブジェクト関数の時間です。
ObjectFind(“オブジェクト名”)で、falseならオブジェクトなし、trueならオブジェクトがあるので、
1 2 3 4 5 6 7 8 9 10 11 12 |
if( ObjectFind("BuyArrow"+iTime(Symbol(),Period(),1) ) { //ひとつ前の確定したロウソク足に買いシグナルがある //買いエントリー条件 OrderSend(...); } else if( ObjectFind("SellArrow"+iTime(Symbol(),Period(),1) ) { //ひとつ前の確定したロウソク足に売りシグナルがある //売りエントリー条件 OrderSend(...); } |
これで、EA化できました。
オブジェクト関数によるインジケーターのEA化の肝は
間違いなく、チャート上に表示されているオブジェクトにつけられた名前の分析能力だと思います。
ただし、何度かインジケーターを開発した経験があれば、何となくわかると思います。(共通項を発見する能力はIQに依存するところもありますけどね。)
そもそもバッファを使わずにインジケーターがコーディングされている時点で、そのインジケーターのプログラマの技量はそこまで高くないと推察されるので、リバースエンジニアリングするのも容易い(だろう)ということだと思います。
関連記事
-
短いコードでも右肩上がりのグラフにできることの証明(MT4EA)非実用
バックテスト結果 ソースコードはこちら 33行あるやんけ...
-
EAが動かない原因と対処法 一覧[MT4/MT5]
「EAが動かな~い」というときには様々な原因と可能性がありますが、そんな時は一個一個原因を解消してい
-
プログラマ向け自動売買開発アイディア
「MQL4/MQL5は扱えるようになったけど、プログラミングのアイディアがない」というプログラマは比
-
株価指数両建て裁定取引のやり方と検証
日経225やダウ、SP500のチャートには強い相関関係があります。かつては「日経はニューヨークの後追
-
[MT4]EAに口座縛り/期間限定縛りをかける種類と方法(MT5)
良いEAができた場合、身内で配布したい場合があります。しかし、知らない間に自分のEAが出回っていた場