プログラム
MetaTrader 4に付属しているサンプル
言語・バージョン
MQL4
トレードの概要
- 買い条件:移動平均線が上向きのときに、MACDがマイナスの低い位置でゴールデンクロスを満たしたら買い注文をだす
- 売り条件:移動平均線が下向きのときに、MACDがプラスの高い位置でデッドクロスを満たしたら売り注文をだす
- 買いポジションの決済:MACDがプラスの高い位置でデッドクロスしたとき、またはトレーリングストップにひっかかったとき
- 売りポジションの決済:MACDがマイナスの低い位置でゴールデンクロスしたとき、またはトレーリングストップにひっかかったとき
ソース全体
//+------------------------------------------------------------------+
//| MACD Sample.mq4 |
//| Copyright 2005-2014, MetaQuotes Software Corp. |
//| http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright "2005-2014, MetaQuotes Software Corp."
#property link "http://www.mql4.com"
input double TakeProfit =50;
input double Lots =0.1;
input double TrailingStop =30;
input double MACDOpenLevel =3;
input double MACDCloseLevel=2;
input int MATrendPeriod =26;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTick(void)
{
double MacdCurrent,MacdPrevious;
double SignalCurrent,SignalPrevious;
double MaCurrent,MaPrevious;
int cnt,ticket,total;
//---
// initial data checks
// it is important to make sure that the expert works with a normal
// chart and the user did not make any mistakes setting external
// variables (Lots, StopLoss, TakeProfit,
// TrailingStop) in our case, we check TakeProfit
// on a chart of less than 100 bars
//---
if(Bars<100)
{
Print("bars less than 100");
return;
}
if(TakeProfit<10)
{
Print("TakeProfit less than 10");
return;
}
//--- to simplify the coding and speed up access data are put into internal variables
MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
total=OrdersTotal();
if(total<1)
{
//--- no opened orders identified
if(AccountFreeMargin()<(1000*Lots))
{
Print("We have no money. Free Margin = ",AccountFreeMargin());
return;
}
//--- check for long position (BUY) possibility
if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened : ",OrderOpenPrice());
}
else
Print("Error opening BUY order : ",GetLastError());
return;
}
//--- check for short position (SELL) possibility
if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
MacdCurrent>(MACDOpenLevel*Point) && MaCurrent<MaPrevious)
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point,"macd sample",16384,0,Red);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("SELL order opened : ",OrderOpenPrice());
}
else
Print("Error opening SELL order : ",GetLastError());
}
//--- exit from the "no opened orders" block
return;
}
//--- it is important to enter the market correctly, but it is more important to exit it correctly...
for(cnt=0;cnt<total;cnt++)
{
if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))
continue;
if(OrderType()<=OP_SELL && // check for opened position
OrderSymbol()==Symbol()) // check for symbol
{
//--- long position is opened
if(OrderType()==OP_BUY)
{
//--- should it be closed?
if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
MacdCurrent>(MACDCloseLevel*Point))
{
//--- close order and exit
if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet))
Print("OrderClose error ",GetLastError());
return;
}
//--- check for trailing stop
if(TrailingStop>0)
{
if(Bid-OrderOpenPrice()>Point*TrailingStop)
{
if(OrderStopLoss()<Bid-Point*TrailingStop)
{
//--- modify order and exit
if(!OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green))
Print("OrderModify error ",GetLastError());
return;
}
}
}
}
else // go to short position
{
//--- should it be closed?
if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&
MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point))
{
//--- close order and exit
if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet))
Print("OrderClose error ",GetLastError());
return;
}
//--- check for trailing stop
if(TrailingStop>0)
{
if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
{
if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
{
//--- modify order and exit
if(!OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red))
Print("OrderModify error ",GetLastError());
return;
}
}
}
}
}
}
//---
}
//+------------------------------------------------------------------+
解説
9行目から14行目 グローバル変数の設定
| 変数名 | 説明 | 設定値(単位) |
|---|---|---|
| TakeProfit | 利食い幅 | 50 (ポイント) |
| Lots | ロット数 | 0.1 |
| TrailingStop | トレーリングストップのトレール幅。 買いポジションの場合、価格が上昇したら そのレートの30ポイント下にロスカットラインを 引き上げて追随。 | 30 (ポイント) |
| MACDOpenLevel | エントリー条件 。 MACDの絶対値がこの数値以上の場合エントリー。 | 3 (ポイント) |
| MACDCloseLevel | クローズ条件。 MACDの絶対値がこの数値以上の場合クローズ。 | 2 (ポイント) |
| MATrendPeriod | EMA(指数平滑移動平均)の期間 | 26 |
24行目から41行目 変数の初期値のチェック
//---
// initial data checks
// it is important to make sure that the expert works with a normal
// chart and the user did not make any mistakes setting external
// variables (Lots, StopLoss, TakeProfit,
// TrailingStop) in our case, we check TakeProfit
// on a chart of less than 100 bars
//---
if(Bars<100)
{
Print("bars less than 100");
return;
}
if(TakeProfit<10)
{
Print("TakeProfit less than 10");
return;
}
ここではコード中のコメントにあるように変数の初期値のチェックをしています。
外部変数(Lots、StopLoss、TakeProfit、TrailingStop)の値に間違えがないことを確認しています。
変数Bars は、現在のチャートの中にあるバーの数です。
バーとは、ロウソク足の一本一本のことです。
バーの数 が少ない場合(100未満の場合)は、処理をせずに終了します。
42行目から48行目 MACDとEMAの取得
//--- to simplify the coding and speed up access data are put into internal variables MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
43行目から46行目でMACDを計算しています。各変数に格納している値の意味は下表のとおりです。 短期EMAは期間12、長期EMAは期間26で計算しています(終値を使用)。シグナルは期間9で計算しています。 それぞれの期間の時間単位は現在のチャートの時間単位になります(日足ならそれぞれ12日・26日・9日、時間足なら12時間・26時間・9時間)。
| 変数 | 説明 |
| MacdCurrent | 現在のMACD |
| MacdPrevious | 1つ前のMACD |
| SignalCurrent | 現在のシグナル |
| SignalPrevious | 1つ前のシグナル |
MACDについては用語解説を参照してください。
47行目から48行目はEMA (指数移動平均)の計算です。
各変数に格納している値の意味は下表のとおりです。
| 変数 | 説明 |
| MaCurrent | 現在の指数移動平均 |
| MaPrevious | 1つ前の 指数移動平均 |
50行目から51行目 ポジションの有無を確認
現在のポジション数を取得して変数totalに格納します。この後の処理では、ポジションの有無によって処理が大きく変わります。
51行目から88行目までがポジションがない場合(変数total が1未満の場合)の処理、90行目以降が ポジションがある場合(変数total が1以上の場合)の処理になります。
total=OrdersTotal();
if(total<1)
{
//--- no opened orders identified
51行目から88行目 ポジションがない場合の処理
total=OrdersTotal();
if(total<1)
{
//--- no opened orders identified
if(AccountFreeMargin()<(1000*Lots))
{
Print("We have no money. Free Margin = ",AccountFreeMargin());
return;
}
//--- check for long position (BUY) possibility
if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened : ",OrderOpenPrice());
}
else
Print("Error opening BUY order : ",GetLastError());
return;
}
//--- check for short position (SELL) possibility
if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
MacdCurrent>(MACDOpenLevel*Point) && MaCurrent<MaPrevious)
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point,"macd sample",16384,0,Red);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("SELL order opened : ",OrderOpenPrice());
}
else
Print("Error opening SELL order : ",GetLastError());
}
//--- exit from the "no opened orders" block
return;
}
//--- it is important to enter the market correctly, but it is more important to exit it correctly...
53行目から58行目 証拠金の残高確認
余剰証拠金の確認をして余力があるかを確認しています。
余剰証拠金 はAccountFreeMargin()で取得します。
total=OrdersTotal();
if(total<1)
{
//--- no opened orders identified
if(AccountFreeMargin()<(1000*Lots))
{
Print("We have no money. Free Margin = ",AccountFreeMargin());
return;
}
//--- check for long position (BUY) possibility
if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened : ",OrderOpenPrice());
}
else
Print("Error opening BUY order : ",GetLastError());
return;
}
59行目から72行目 ロングポジションの確認
total=OrdersTotal();
if(total<1)
{
//--- no opened orders identified
if(AccountFreeMargin()<(1000*Lots))
{
Print("We have no money. Free Margin = ",AccountFreeMargin());
return;
}
//--- check for long position (BUY) possibility
if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened : ",OrderOpenPrice());
}
else
Print("Error opening BUY order : ",GetLastError());
return;
}
以下の条件が同時に成立するときに買い注文を出します。
- 現在のMACD(MacdCurrent)が0より小さい
- 現在のMACD(MacdCurrent)がシグナルより大きい
- 1つ前のMACD(MacdPrevious)が一つ前のシグナルより小さい
- 現在のMACDの絶対値がMACDOpenLevelにPointを掛けた値より大きい
- 現在の指数移動平均(MaCurrent)が1つ前の 指数移動平均(MaPrevious)より大きい