MQL4 Expert Advisor Example

この完全な MQL4 Expert Advisor 記事でフル機能の MA Expert Advisor を作成する方法を学び、トレーディング EA のプログラミングに役立ててください。


エキスパートアドバイザーの構築について説明しているいくつかのマニュアルやガイドでは、例として移動平均クロスオーバー (MACross) が使用される傾向があります。 その理由は、これが最も人気のあるインジケーターベースの戦略であり、ほとんどの人がすでに慣れ親しんでいる取引概念を使用して新しいコーディング概念を教える方がはるかに簡単であるためです。


このおなじみのパスに従って、単純な移動クロス (20 ~ 200) に基づいて基本的なエキスパート アドバイザを送信します。


// セクション 1:

// プリプロセッサ ディレクティブ、外部変数と内部変数

#property copyright “Copyright © 2008-2010, Excel Markets”
#property link “/article/”

extern string EAName = “MACross”;
extern double MagicNumber = 59483;

extern double Lots =0.1;
extern double LotDigits =2;
extern int Slippage = 5;

extern double StopLoss = 80;
extern double TakeProfit =0;

extern bool OppositeClose = true;
extern bool EnterOpenBar = true;

extern int FastMATime = 0;
extern int FastMAPeriod = 2;
extern int FastMAType = 0; //0:SMA 1:EMA 2:SMMA 3:LWMA
extern int FastMAPrice = 0;
extern int FastMAShift = 0;
extern int SlowMATime = 0;
extern int SlowMAPeriod = 30;
extern int SlowMAType = 1; //0:SMA 1:EMA 2:SMMA 3:LWMA
extern int SlowMAPrice = 0;
extern int SlowMAShift = 0;

// Global Variables

int Counter, vSlippage;
double ticket, number, vPoint;

double
FastMACurrent,
FastMAPrevious,
SlowMACurrent,
SlowMAPrevious;

// Section 2: Initialization

int init(){

if(Digits==3 || Digits==5)
{ vPoint=Point*10; vSlippage=Slippage*10; }
else{ vPoint=Point; vSlippage=Slippage; }

return(0); }

//——————————————————-
// Section 3: Start

int start()
{

if(Bars<100) { Print(“Bars less than 100”);
return(0); }

//——————————————————–
// Section 3A: Define ShortCuts to Common Functions

int Total, OType=-1, Ticket;
double Price, SL, TP, Lot;
bool CloseBuy=false, CloseSell=false, OpenBuy=false, OpenSell=false;

for(int Counter=1; Counter<=OrdersTotal(); Counter++)
{
if (OrderSelect(Counter-1,SELECT_BY_POS)==true)
if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)

{
Ticket=OrderTicket();
OType =OrderType();
Price =OrderOpenPrice();
SL =OrderStopLoss();
TP =OrderTakeProfit();
Lot =OrderLots();
}
}
//—————————————————-
// Section 3B: Indicator Calling

int Current = 0;

FastMACurrent = iMA(NULL, FastMATime, FastMAPeriod, FastMAShift, FastMAType, FastMAPrice, Current + 0);

FastMAPrevious = iMA(NULL, FastMATime, FastMAPeriod, FastMAShift, FastMAType, FastMAPrice, Current + 1);

SlowMACurrent = iMA(NULL, SlowMATime, SlowMAPeriod, SlowMAShift, SlowMAType, SlowMAPrice, Current + 0);

SlowMAPrevious = iMA(NULL, SlowMATime, SlowMAPeriod, SlowMAShift, SlowMAType, SlowMAPrice, Current + 1);

//————————————————
// Section 3C: Entry Conditions

bool OpenBar=true;
if(EnterOpenBar) if(iVolume(NULL,0,0)>1) OpenBar=false;

if (FastMACurrent > SlowMACurrent&& FastMAPrevious < SlowMAPrevious
&& OpenBar){
OpenBuy=true;
if (OppositeClose) CloseSell=true;
}

if (FastMACurrent<slowmacurrent&&amp> < SlowMACurrent&& FastMAPrevious > SlowMAPrevious
&& OpenBar){
OpenSell=true;
if (OppositeClose) CloseBuy=true;
}
//————————————————-
// Section 3D: Close Conditions

while(true)
{
if (OType==0 && CloseBuy==true)
{
close (OP_BUY); // Close Buy
return;
}

if (OType==1 && CloseSell==true)
{
close (OP_SELL); // Close Sell
return;
}
break;
}
//————————————————–
// Section 3E: Order Placement

while(true)

{
if (OrdersTotalMagicOpen()==0 && OpenBuy==true)
{

if(StopLoss>0){SL=Bid – StopLoss*vPoint;}else{SL=0;} if(TakeProfit>0){TP=Bid+TakeProfit*vPoint;}else{TP=0;}
ticket=0;number=0;
while(ticket<=0 && number<100){
RefreshRates();
ticket = OrderSend(Symbol(),OP_BUY,NormalizeDouble(Lots,LotDigits), Ask,vSlippage,SL,TP,EAName, MagicNumber, 0, Green);
return (ticket);
}}

if (OrdersTotalMagicOpen()==0 && OpenSell==true)
{
if(StopLoss>0){SL=Ask + StopLoss*vPoint;}else{SL=0;} if(TakeProfit>0){TP=Ask-TakeProfit*vPoint;}else{TP=0;}
ticket=0;number=0;
while(ticket<=0 && number<100){
RefreshRates();
ticket= OrderSend(Symbol(),OP_SELL, NormalizeDouble(Lots,LotDigits), Bid,vSlippage,SL,TP, EAName, MagicNumber, 0, Red);
return (ticket);
}}
break;
}
//———————————————————
return; // End of start()
}

// Section 4A: Close Function

void close(int type){
if(OrdersTotal()>0){
for(Counter=OrdersTotal()-1;Counter>=0;Counter–){
OrderSelect(Counter,SELECT_BY_POS,MODE_TRADES);

if(type==OP_BUY && OrderType()==OP_BUY){
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
RefreshRates();
OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits), vSlippage);
} }

if(type==OP_SELL && OrderType()==OP_SELL){
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
RefreshRates(); OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),vSlippage);
}}
}}}

// Section 4B: OrdersTotalMagicOpen Function

int OrdersTotalMagicOpen() {
int l_count_0 = 0;
for (int l_pos_4 = OrdersTotal() – 1; l_pos_4 >= 0; l_pos_4–) {
OrderSelect(l_pos_4, SELECT_BY_POS, MODE_TRADES);
if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue;
if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
if (OrderType() == OP_SELL || OrderType() == OP_BUY) l_count_0++;
}
return (l_count_0);
}
</slowmacurrent&&amp>

これまでにプログラミングの経験がない場合、上記のコードは少し難解で怖く感じるかもしれません。 威圧的な要素を克服する 1 つの方法は、細かいことは気にせず、全体像に集中することです。


言語の各部分がどのように動作するか、またはプロセッサ レベルで舞台裏で何が起こっているかを理解しようとせず、言語が動作していることだけを受け入れてください。 言語とその形式の詳細にこだわる必要はありません。 EA を理解して構築するために、特定の詳細に焦点を当てる必要はありません。 この時点で必要なのは、パズルのピースがどのように組み合わされるのか、そして最も重要なピースのどれを操作して新しい戦略を立てることができるのかを知ることだけです。


パズルを組み立てて、最も重要なピースの方向を示すのをお手伝いします。 各セクションを説明する際に相互参照しやすいように、EA の各セクションに番号とラベルを付けました。

セクション 1: プリプロセッサ ディレクティブ、外部変数と内部変数

まず、コメントについて説明します。 // の後にいくつかのコメントを追加したことに気づくかもしれません。


// で始まる行はフリー テキストであり、プログラムによって無視されます。


コンピューターが無視する場合でも、プログラミング ステートメントの意味をわかりやすい英語で説明するのに役立つコメントが含まれています。 はい、プログラミング言語は一見すると理解するのが難しい場合がありますが、コードを作成するときにコメントを追加すると便利で、作業が楽になります。


次に、プリプロセッサ ディレクティブについて説明します。 各ディレクティブはポンド記号 (#) で始まります。 #import や #include など、高レベルの形式のディレクティブが多数ありますが、コードを自分のものとして識別する最も単純な #property 著作権プリプロセッサ ディレクティブのみを使用します。 それ以外はそれほど重要ではありませんし、特別なことでもありません。


次は外部変数です。これは非常に重要です。 前回の記事で、変数が後で使用するために内容を保存できる小さな箱のようなものであることを説明しました。 外部変数 (extern という単語が前に付く) は、その引数がプログラムの外側のエキスパート ダイアログに表示され、ユーザーが簡単に操作できるようにするため、重要です。


上記の基本的な EA で見られる外部変数の多くは、一目瞭然です。 EAName、MagicNumber、Lotsize、TakeProfit、Stoploss については、後で OrderSend 関数の構文を学習するときに説明します。セクション 3E「OrderPlacement」を参照してください。 これらの変数は主にその関数を参照します。


このセクションの興味深い外部変数は次のとおりです: 移動平均パラメータ変数 (特に MAPeriod)、OppositeClose、EnterOpenBar。

移動平均パラメータ変数。

すべての移動平均パラメータ値を外部変数として配置したことに注意してください。 これをする必要はありません。 セクション 3B「インジケーター呼び出し」でこれらを呼び出したとき、最も重要な変数 MAPeriod のみを外部変数にして、残りのパラメーターをインジケーター内のデフォルト値のままにすることもできました。 後でパラメータを最適化したい場合に備えて、ほぼすべてのパラメータを外部変数として宣言しました。 現時点ではおそらく MAPeriod のみを最適化しますが、将来的には他のいくつかを最適化すると役立つ可能性があります。 これらのパラメータについては、セクション 3B「インジケーターコール」を扱うときに詳しく説明します。

私の True/False Bool 変数: OppositeClose と EnterOpenBar

変数に bool がある場合、それは真理値に使用される型です。 bool 型は、論理微積分の発明者の姓である boolean に由来しています。 bool OppositeClose を確認してみましょう。


外部ブール値 OpositeClose=true


この変数の外部ブール値を使用すると、次のことが可能になります。 open と close の反対側の close 条件。 コード内でoppositecloseが参照されると、デフォルトでtrueになります。これは、オープンすることを意味します。 false に設定するとオフになります。 あるいは、true または false を使用する代わりに、false の場合は 0、true の場合は 1 を使用することもできます。


OppositeClose ブール値は、反対のシグナルで注文をクローズできるというアイデアを指します。 どういう意味ですか? true に設定すると、現在ロング ポジションにあり、ショート エントリー注文がトリガーされると、ショート トレードを行う前にショート エントリー注文によって現在のロング ポジションがクローズされます。 ショートエントリーシグナルは、現在のロングポジションを決済するための反対のシグナルです(逆も同様です)。 絶対にアクティブ化したいので、oppositeclose をデフォルトで true に設定しています。 false を選択した場合、つまり反対のクローズを無効にした場合、ショートエントリーシグナルは以前のロングトレードをクローズせず、ストップロスまたはテイクプロフィットを押してクローズするまでロングトレードはオープンしたままになります。 一般に、oppositeclose を true に設定してアクティブ化することをお勧めします。 セクション 3D「クローズ条件」で、oppositeclose のエンコードについて説明し、セクション 4A「クローズ関数」で関連する関数について説明します。


EnterOpenBar bool は、バーの間や終値ではなく、新しいバーの開始時にのみエントリーするというアイデアを指します。 インジケーターに基づいて新しい戦略を作成するときは、戦略がどのようにバックテストされるかを簡単に確認できるように、EnterOpenBar をデフォルトで true に設定することを好みます。 Strategytester のドロップダウン メニューには、すべてのティック ポイント、コントロール ポイント、始値のみの 3 種類のバックテスト モードがあります。 各スケールはより正確ですが、他のスケールよりも遅くなります。 始値の精度はそれほど高くありませんが、他のものよりも高速です。 Control Point は、精度と速度の点で 2 つの中間に位置します。 ただし、EnterOpenBar が true に設定されている場合は、オープン専用モードで安全にバックテストを行うことができ、バックテストが大幅に高速化され、同時に、everytick モードとほぼ同様の精度と結果が得られます。 バックテストの速度に加えて、enteronopenbar を true に設定すると、特に一般的なメトリクスに基づいている場合、システムの全体的なパフォーマンスと信頼性が向上することにも気付きました。 enteronopenbar を true と false に設定して、結果の違いを確認することをお勧めします。 EnterOpenBar の背後にあるコーディングについては、セクション 3C「エントリ ロジック」を参照してください。


最後に、このセクションでは、次のようないくつかの内部変数 (グローバル変数と呼ばれることもあります) を宣言します。


Double ticket、number、vPoint;


各識別子の特定の値を宣言していないことに注意してください。 値が宣言されていない場合、各識別子のデフォルトは 0 ですが、後で決定されます。 OKが完了すると0に戻ります。 また、ステートメントがセミコロンで終わるまで、double の後に識別子をコンマで区切って順番にリストしていることにも注意してください。 これが可能なのは、どれもグローバルに異なる値を持たないためです。 これらをここではなく start() 関数で宣言することもできましたが、このセクションに置くことで、コード内の任意の関数からグローバルに参照できるようになります。 これは非常に便利で、不必要な繰り返しを避けることができます。

ヒント!

特定の識別子に遭遇し、それがコードのどの部分を参照しているのかがわかりにくい場合は、すぐに確認できる方法があることを覚えておいてください。一致するものを見つける方法。 識別子 (例: ExpertName) をコピーしてルックアップ フィールド (Cnt+F) に貼り付けるだけで、コード内の別の場所にある一致する識別子にすぐにジャンプできます。 リテラルを使って ISPY をいじるのが好きでない限り、コードのさまざまな部分を一致させるためにこれを頻繁に行うことになるかもしれません。

パート 2: 初期化

ご覧のとおり、このセクションには多くの内容はありません。


このセクションに含まれているコードは、ブローカーの通貨番号に相対的なピップ値を設定するためのものです (ブローカーは 4 桁または 5 桁の相場システムで設定されています)。

if(桁==3 || 桁==5)
{ vPoint=ポイント*10; vSlippage=Slippage*10; }
else{ vPoint= ポイント; vSlippage=スリッページ; }

簡単な英語訳: 通貨ペアが 3 または 5 の数字でクオートされている場合、pip 値はポイントと等しくなります*10、そうでない場合(例: 2 または 4)、ポイント値は乗数なしのポイント値のままになります。


小数点以下 3 桁または 5 桁のブローカーを自動的に検出して調整するコードを挿入することは、独自の記事「スリッページの自動検出と」で説明した便利なアイテムです。ポイント価値の詳細」。


構文、言語、構造を学びます。 if 条件がどのように括弧 () で囲まれているか、およびステートメントがどのように中括弧 {} で囲まれているかに注意してください。 これは、if 条件の後にそのステートメントが続く一般的な構造です。 この場合、if 条件は if(Digits==3 || Digits==5) です。二重等号 (==) は等しいを意味し、二重縦棒 (||) は「または」を意味することに注意してください。自分の言葉がどのように機械語に翻訳されるかを知る必要があります。単に「および」または「または」と言えば便利ですが、これらの言葉を使用するとプログラムは理解できません。 「または」には二重縦棒 (||) を使用し、「および」には二重記号 (&&) を使用します。

二重の「and」記号 (&&) を入力するのは簡単ですが、「または」二重縦棒 (||) を入力するのは難しいため、簡単なショートカットはコピーして貼り付けることです。

最後に、括弧 { vPoint=Point*10; vSlippage=Slippage*10; } で囲まれた最初のステートメントには、実際にはセミコロンで区切られた 2 つのステートメントがあります。1 つは vPoint の意味を定義するステートメントで、もう 1 つは vSlippage の意味を定義するステートメントです。条件が満たされない場合は、括弧 { vPoint=Point; vSlippage=Slippage; } 内の代替複合ステートメントを指す、連動する else 関数があります。
最後に、括弧内の最初のステートメント { vPoint=Point*10; vSlippage= Slippage*10; } には、実際にはセミコロンで区切られた 2 つのステートメントがあります。1 つのステートメントは vPoint の意味を定義し、もう 1 つのステートメントは vPoint の意味を定義します。 vSlippage。条件が満たされない場合、括弧内の代替複合ステートメントを指す連動 else 関数 { vPoint=Point; vSlippage= Slippage; }。

セクション 3: Start() 関数

このセクションは最も重要かつ最長です。このセクションを 3A、3B などの別々のチャンクに分割するのが最善です。


この start() 関数の先頭に、次の行を含めました。


< p>if(Bars<100) { Print("100 未満のバー");

return(0); }


意味: バーが 100 未満の場合は取引を行わず、バーが 100 未満であることを画面に表示します。 チャートに読み込まれたバーが不十分な場合に取引が行われないようにするには、このコードを含めると便利です。


構文、言語、構造を学びます。 これは、「if」の後の括弧内に設定された別の if 条件 (バー < 100) です。 if 条件に続く式に 2 つ以上の複合ステートメントが含まれる場合は、中かっこ {} で囲む必要があり、中かっこ内の各ステートメントはセミコロンで区切る必要があることに注意してください。 この例では、if 条件の後に 2 つのステートメントがあります。 最初のステートメントでは、Print は常駐関数であり、引用符で囲み括弧で囲んで記述する必要があります。 条件が満たされると、その説明が画面に表示されます。 セミコロンで式を完成させます。 2 番目のステートメントの return (0) は、バーが 100 未満の場合は取引が行われないことを意味します。

各左中括弧には、一致する右中括弧を使用しないとコンパイルされないため、2 つのステートメントを右中括弧で閉じます。

セクション 3A: 一般的なトランザクション機能の短いタグの定義

ここでは、一般的なトランザクション機能を表すいくつかの短いタグを定義し、MagicNumbers で使用できるようにします。


トランザクションを MagicNumbers で動作させる必要があるのはなぜですか?


MagicNumber は EA の指紋であり、プログラムがこの EA を同じ通貨と時間枠で動作する他の EA (または取引) と区別できるようにします。 たとえば、プラットフォーム自体のオープン購入ポジションではなく、この EA のオープン購入ポジションのみをプログラムで追跡したい場合です。 そのため、トランザクション情報関数を参照するときは、それらを MagicNumber に関連付けたいと考えています。

これらの取引情報関数の完全なリストと定義については、ここをクリックしてください: http://docs.mql4.com/trading


トランザクション関数を OrderSelect() 関数の下に置くことで、マジックナンバーを使用できるようにしました。

for(int Counter=1; Counter<=OrdersTotal(); Counter++)
{ if (OrderSelect (Counter-1,SELECT_BY_POS, MODE_TRADES)==true)
if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
タグ名 =一般的な取引機能;
}
}}

翻訳: オープンまたは保留中の取引にマジックナンバーがある場合、次のタグ名が一般的に使用される取引を表します。関数


無駄のない構文、言語、構造。 さまざまな EA で OrderSelect 関数のバリアントがよく見られますが、通常はカスタム関数の最初の行にあります (私はこれを自分の関数 4A と 4B の 2 つで使用しました)。 OrderSelect 関数は、さらに処理する注文を選択し、関数が成功した場合は true を返し、失敗した場合は false を返します。


OrderSelect() 関数は非常に重要であるため、独自の記事を作成しました。「OrderSelect を使用した注文情報の取得」という記事を参照してください。


私の目的では、OrderSelect 関数を使用して、取引、MODE_TRADES (オープン注文と保留中の注文を示す)、および MagicNumber によって選択します。 言い換えれば、この関数の下に含める取引関数で、マジックナンバーに属するオープン注文と未決注文を処理できるようにしたいのです。 3行目、特にOrderMagicNumber() == MagicNumberという部分は、MagicNumberにトランザクション関数を含める条件を表しています。 この関数にグループ化したすべてのトランザクション関数のうち、コードの後半で使用する関数は OType=OrderType() です。これはセクション 3D「Close 関数」で使用しました。


このコード ブロックの最初の行の関連性についても触れておく必要があります。


< p >for(int Counter=1; Counter<=OrdersTotal(); Counter++)


これは for 演算子と呼ばれ、所定の数をループするために使用されます何度もコードブロック。 最初の式 int = Counter =1 は、Counter 変数を値 1 で初期化します。 2 番目の式 Counter <=OrdersTotal() は条件で、true の場合、中括弧内のコードが実行されます (オープン注文が 3 つある場合は、ループが 3 回実行されます)。 3 番目の式 Counter++ は、「Counter の値を 1 つ増やす」ことを意味します。 この場合のカウンターは、最終的にすべてのオープン注文がカウントされるまで、ループが完了するたびに 1 ずつ増加します。


パート 3B: インジケーター コール

ここでは 4 つの異なる移動平均を宣言します。


FastMACurrent = iMA(NULL, FastMATime, FastMAPeriod, FastMAShift, FastMAType, FastMAPrice, Current + 0);

FastMAPrevious = iMA(NULL, FastMATime, FastMAPeriod, FastMAShift, FastMAType , FastMAPrice, Current + 1);

SlowMACurrent = iMA(NULL, SlowMATime, SlowMAPeriod, SlowMAShift, SlowMAType, SlowMAPrice, Current + 0);

SlowMAPrevious = iMA(NULL, SlowMATime , SlowMAPeriod, SlowMAShift, SlowMAType、SlowMAPrice、Current + 1);


それぞれは MT4 ネイティブ移動平均インジケーターを参照しており、独自の特定の構文があります。

< p>

double iMA(string Symbo)、int Timeframe、int MAPeriod、int MAShift、int MAMethod、int MAPrice、int Shift)


< /p>

私は、iMA 識別子の後の括弧内の構造を、複数の座席が割り当てられたバスとして考えるのが好きです。 バスの各座席はカンマで区切られており、パラメータと呼ばれます。 iMA インジケーターには 7 つのパラメーターがあります。 各パラメータには、カスタマイズ (またはバス メタファーを維持するためにカスタマイズ) できるデフォルト値があります。 各パラメーターの機能、それぞれのデフォルト値、カスタマイズ方法、実際にバスを駆動するパラメーターを知ることは役に立ちます。


下表は移動平均の各パラメータを説明しています:

MA
Parameters
Description
SymbolEURUSD などの取引シンボル。 Symbol() は通貨チャートのペアを表します
TimeFrame移動平均のチャート期間を適用します。通常は 0 に設定され、次のことを示します。 EA はチャートシンボルに付加されます。
MAPeriod移動平均の遡及期間。 これは最も重要な変数です。
MAShift移動平均の前方シフト (バー単位)。通常は 0 に設定されます。
MAMethod移動平均の計算方法は、単純、指数、平滑、または線形加重を選択できます。 第最も重要な 2 つの変数。
MAPrice移動平均を計算するときに使用される価格の配列。終値、始値、最高値、最低価格、またはある種の平均が可能です。 通常は、デフォルト値の 0 またはオフを使用します。
Shift計算されたバーのバックシフトを返します。 値 0 は現在のバーのインジケーター値を返し、値 3 は 3 バー前のインジケーター値を返します。 これから説明するように、これは 3 番目に重要な変数です。

は可能ですここにあります MA パラメーター (および 20 個すべてのネイティブ インジケーターのパラメーター) への便利なクイック リファレンスは、ここにあります: http://docs.mql4.com/indicators/iMA <スパン jsaction="agoMJf:PFBcW;MZfLnc:P7O7bd;nt4Alf:pvnm0e,pfE8Hb,PFBcW;B01qod:dJXsye;H1e5u:iXtTIf;lYIUJf:hij5Wb;bmeZHc:iURhpf;Oxj3Xe:qAKMYb,yaf1 2 d" jsname="txFAF " class= "jCAhz ChMk0b" jscontroller="Gn4SMb"> direct 目的では、デフォルトのパラメータ値を使用します。この目的で最も重要なパラメータは移動平均の長さである MAPeriod です。FastMAPeriod I のデフォルトは 2、SlowMAPeriod I のデフォルトは 30 です。 速い移動平均と遅い移動平均を区別するため、バスを駆動するのは MAPeriod です。 MAMethod も重要で、特に Simple (Integer=0) と Exponential (Integer=1) が重要です。 速い移動平均の場合はデフォルトで 0 または Simple、遅い移動平均の場合は 1 または Exponential に設定します。 したがって、30 期間 EMA が 2 期間 SMA を超えて買いシグナルをトリガーしたいと考えています。 MAShift と MAPrice は通常 0 のままであり、これらのパラメータを変更してもほとんど効果がありません。 最後のパラメーター Shift は 4 番目のパラメーター MAShift と関係がないため、この 2 つを混同しないでください。 実際には、最後のパラメータは時間内の移動平均を見つけるための重要なパラメータです。 前のバーと現在のバーを区別することが特に重要であり、これはエントリーとエグジットのロジックに不可欠な部分です。 これらのパラメーターはすべて、後の段階で簡単に変更または最適化できるように、外部変数として配置されていることに注意してください。 簡単な質問: ダブル MA クロスオーバーに高速移動平均と低速移動平均のみを使用する場合、なぜ 4 つの移動平均を宣言する必要があるのですか? ダブルMAクロスをしたい場合、クロスの前後で何が起こっているかを指摘する必要があります。 これから見ていきますが、買いクロスの例は、現在の高速 MA が現在の低速 MA を上回っており、以前の高速 MA が以前の低速 MA を下回っている場合です。 このため、4 つの移動平均 (FastMACurrent、FastMAPrevious、SlowMACurrent、SlowMAPrevious) を定義する必要があります。 現在の移動平均と前の移動平均の差は何ですか? 現在の移動平均と以前の移動平均の唯一の違いは、最後のパラメーター、つまりシフト パラメーターです。現在のシフトは 0 で、前のシフトは 1 です。

セクション 3C: エントリ ロジック:

エントリ ロジックの最初の部分では、前述の EnterOpenBar ロジックを作成します。 興味深いことに、これは短いですが重要なコードであり、多くの専門アドバイザーによって見落とされがちです。 コードは次のようになります:


Boolean OpenBar = true;

if(EnterOpenBar) if(iVolume(NULL,0,0) >1) openbar=false;


プログラムはどのようにして新しいバーの始値を見つけますか? 新しいバーに表示される最初のティックを見つける必要があります。 したがって、上記のコードでは、出来高をチェックし、見つかった新しいバーの最初の気配を検出するまで取引のエントリーを遅らせています。 2 つの if 条件文が連続していることがわかります。


最初の「if (enteronopenbar)」は、先ほどデフォルトで true に設定した bool 変数を参照します。 true の場合、次の if 条件文「if (iVolume(NULL,0,0)>1)」に進みます。 2 番目の if 条件は、ボリュームが 1 であるかどうかをチェックします。この場合、新しいバーの最初のティックが見つかったため、openbar は true (1 より大きいものはすべて false) になります。 オープンバーのこのチェックは、新しいシステムにとって非常に単純ですが重要なコンポーネントであるため、独自の記事「オープン バーで入力」で詳しく説明します。


次に、EA の頭脳であるエントリーとエグジットの戦略的条件について引き続き説明します。


コード化する予定の売買条件は次のとおりです。


購入条件1:

3 期間移動平均が 30 期間移動平均を超えた場合に市場で購入します (オープンな売りポジションもクローズします)。


売り条件 1:

3 期間移動平均が 30 期間移動平均を下回っている場合は、市場で売ります (オープンな買いポジションもクローズします)。


これら 2 つの条件はどのように MQL4 コードに変換されるのでしょうか?


クロス条件を記述する方法はたくさんありますが、教育目的のため、最も簡単な方法を採用します。 MT4 にはクロスオーバー機能が組み込まれていないため、一般的な 2 ステップのソリューションを構築します。 前の足の高速移動平均が以前の低速移動平均を下回っており、現在の足の移動平均が低速移動平均を上回っているかどうかを観察することにより、買いクロス条件を示します。 したがって、一線を越えてしまったのです。 おそらく、次のコードをよりよく理解できるようになりました。


If (

FastMACurrent > SlowMACurrent &&

FastMAPrevious < SlowMAPrevious

&& オープンバー)


{

open buy=true;

if (OppositeClose) CloseSell =true;

}

If(

FastMACurrent FastMAPrevious > SlowMAPrevious && openbar)

{

Open sale=true;

if (OppositeClose) CloseBuy=true;

}


構文に関して言えば、if 条件を宣言するときは、特に 2 つ以上のステートメントが関係する場合は、ロジックを中括弧 {} で囲む必要があります。 FastMACurrent が SlowMACurrent より大きくなければならないことを示唆するために、演算子と呼ばれる > 記号を使用します。 基本的に、前の足の 20 期間移動平均が 200 期間移動平均を下回り、現在の足の 20 期間移動平均が現在の足の 200 期間移動平均を上回っている場合、市場では買う。 演算子は取引条件にとって非常に重要であるため、演算子について短い記事を書きました。そして理解できる。 2 番目のステートメントはもう少し微妙です。 前の移動平均条件が満たされる場合、CloseSell を true に設定し、extern bool OppositeClose を true に設定します。 CloseSell または CloseBuy bool をアクティブにする前に、独自の内部 if 条件 (この場合は OppositeClose bool = true または false) を要求する方法に注目してください。 私は、これらの内部の if bool 条件をキーとロックのメカニズムとして考えるのが好きで、エンド ユーザーがエキスパートのプロパティ タブからメカニズム (この場合は OppositeClose) を簡単に開閉できるようにします。


セクション 3D: 終了条件

このセクションは while 演算子から始めます。 これは、MQL4 でループする簡単な方法で、上で説明した for ループに似ていますが、反復回数がわからない場合に適しています。 while ループは基本的に次のようになります:

while (true) {
/ / ループ コード
}

次に、買い注文と売り注文を閉じるための条件を設定します。

if (OType==0 && CloseBuy= =true)
{
close (OP_BUY); // 購入を閉じる
return;
}

OType は変数であり、トランザクション情報関数 OderType を表します()、毎 各取引注文タイプには対応する整数があります。 OrderType == 0 は OP_BUY、つまり買いポジションを指し、OrderType = 1 は OP_SELL、つまり売りポジションを指します。


以下は、さまざまな注文タイプとそれに対応する整数値です。

< td class="rowhead">OP_SELL< td >3 < td class="rowhead">OP_SELLSTOP
OrderTypeInteger 説明
OP_BUY0買いポジション
1売りポジション
OP_BUYLIMIT買い指値保留中
OP_BUYSTOP4買いストップ保留中
OP_SELLLIMIT5販売制限保留中
6保留中の売りストップ

現在、 buy ポジション (OType==1) を入力し、bool CloseBuy が (==) true の場合、カスタム決済関数 close (OP_BUY) を実行できます。 カスタム クローズ機能について読むには、ここをクリックしてください。


このセクションはブレーク演算子で終了します。 演算子 'break' は、タイプ 'while'、'for'、または 'switch' の最も近い外部演算子の実行を停止します。 演算子 'break' の実行は、タイプ 'while'、'for'、または 'switch' の複合演算子の外側にある最も近い後続の演算子に制御を渡すことで構成されます。


セクション 3E: 注文

< p>前のセクションの Break 演算子の後に、このセクションを別の while 演算子で開始します。 前のセクションの中断により、制御またはフローが 2 番目の while ループに渡されました。


このセクションでは、プログラムは買い注文と売り注文を出します。


次の条件で始まります:


If (OrdersTotalMagicOpen()== 0 && OpenBuy==true)


OrdersTotalMagicOpen() はカスタム プログラムであり、すぐに参照します。オープン注文の数を計算します。番号で。 注文の合計数が 0 (==0) の場合は、続行できます。 そして (&&) bool OpenBuy が true の場合、続行できます。


次に、ストップロスと利益の目標値を決定するコードです。


if (StopLoss>0){SL=Bid – StopLoss*vPoint;}else{SL=0;} if(TakeProfit>0){TP=Bid+TakeProfit*vPoint;}else{TP=0;}

< p>

ここでは、2 つの if-else 連続ステートメントを連続して使用します。 少し後戻りしましょう。 先行する if ステートメントが false の場合、else 条件は代替条件を評価することに注意してください。 else と if を組み合わせて、true の場合にのみ実行される代替条件を作成しています。 この場合、StopLoss > 0 の場合、StopLoss の値 (Bid-StopLoss *vPoint) を決定できると言います。 それが 0 ではなくストップロスの場合、ストップロスの値がわからないため、代わりにストップロスを 0 に維持することになります。 同じロジックが利食いにも繰り返されます。 これらの if-else 条件に従って決定された値は、OrderSend() 関数の StopLoss パラメーターと TakeProfit パラメーターに表示されます。


次に、レートを更新し続け、約定されるまで注文をプッシュします。


ticket=0;number=0;

while(ticket<=0 &&number<100){

リフレッシュ レート();< /p>< p>

チケットが 0 (注文が約定されていない) で、約定の試行回数が 100 未満の場合は、引き続きチケットを更新します。評価して埋めてみてください。 これは、動きの速い市場で再クォートがあり、とにかくクローズしたい場合に便利なコードです。 もう一度、while 演算子が実行されているのがわかります。今回はチケットと注文の試行回数をループします。


次は OrderSend() 関数です。 これはそれ自体多面的な機能です。これについてはここに短い記事を書きました。 OrderSend を使用した成行注文