移動平均線のゴールデンクロスでエントリーするという、古典的なトレード手法をEAにしてみました。
ソースコードも公開しているので、ご参考くださいませ。
MT4のインストールは必須
MT4のインストールは必須です。私はXMTrading のMT4を使用していますが、基本的な操作は、どのサードパーティのMT4でも同じです。
なお、XMTradingのインストール方法はこちらの記事にまとめました。

デモ口座が使えるので、無料で最初から始められます。

単純移動平均線のゴールデンクロスとは?
今回、EAにしたのは、「単純移動平均線のゴールデンクロスでエントリー」です。
ゴールデンクロスは、短期移動平均線が下から、長期移動平均線に重なったときのタイミングを指します。逆はデッドクロス。

黒:短期、水色;長期
MQL4でコーディング
メタエディタを使ってコーディングします。基本的なコーディング方法と、使い方は、こちらの記事にまとめました。初心者の方はご参考ください。

ソースコード
今回の移動平均線のゴールデンクロスで買うというソースコードはこちら。

注意:実トレードで使わないでください。めっちゃ損します。
//+------------------------------------------------------------------+
//| GoldenCross_buy.mq4 |
//| Copyright 2020, Yanoteck |
//| https://investment-vmoney.com/ |
//+------------------------------------------------------------------+
#property strict
#define MAGIC 20200412007
//SMA short
extern int sma_short = 20;
//SMA long
extern int sma_long = 100;
//パラメータ
extern double Lots = 0.1; //ロット
extern int Slippage = 30; //スリッページ
extern double Profitrate = 0.002; //利確(0.002=0.2%)
extern double SLrate = 0.01; //損切り(0.01=1%)
int flg_buy = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
flg_buy = 0;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
//変数
double now_ask = Ask; //現在のAsk
double now_bid = Bid; //現在のBid
//SMA取得
double sma_short_now = iMA(NULL,PERIOD_CURRENT,sma_short,0,MODE_SMA,PRICE_CLOSE,0);
double sma_long_now = iMA(NULL,PERIOD_CURRENT,sma_long,0,MODE_SMA,PRICE_CLOSE,0);
double sma_short_before = iMA(NULL,PERIOD_CURRENT,sma_short,0,MODE_SMA,PRICE_CLOSE,1);
double sma_long_before = iMA(NULL,PERIOD_CURRENT,sma_long,0,MODE_SMA,PRICE_CLOSE,1);
//ゴールデンクロスでBUYエントリー
if((sma_short_before < sma_long_before) && //1バー前の短期移動平均線が長期移動平均線より小さい
(sma_short_now >= sma_long_now) && //今の短期移動平均線が長期以上?
flg_buy == 0){
// レートのリフレッシュ
RefreshRates();
//成り行き買いオーダー
OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,Ask*(1-SLrate),Ask*(1+Profitrate),"Buy order",MAGIC,0,Blue);
//フラグON
flg_buy = 1;
//デッドクロスでBUYクローズ
}else if((sma_short_before >= sma_long_before) && //1バー前の短期移動平均線が長期移動平均線以上
(sma_short_now < sma_long_now) && //今の短期移動平均線が長期より小?
flg_buy == 1){
ClosePositions_BUY();
//フラグOFF
flg_buy = 0;
}
}
//+------------------------------------------------------------------+
//| ポジション決済 |
//+------------------------------------------------------------------+
void ClosePositions_BUY(){
int i;
for(i=0;i<OrdersTotal();i++){
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) == false){
break;
}
if(OrderMagicNumber() != MAGIC || OrderSymbol() != Symbol()){
continue;
}
//買いポジションのチェック
if(OrderType() == OP_BUY){
OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White);
break;
}
// ループを抜ける
break;
}
}
void ClosePositions_SELL(){
int i;
for(i=0;i<OrdersTotal();i++){
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) == false){
break;
}
if(OrderMagicNumber() != MAGIC || OrderSymbol() != Symbol()){
continue;
}
//売りポジションのチェック
if(OrderType() == OP_SELL){
OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,White);
break;
}
// ループを抜ける
break;
}
}
//+------------------------------------------------------------------+
ティック毎にチェックしているので、フラグを入れてます。
フラグがないと、しこたまBuyオーダーが入ります。
バックテストの結果

- USDJPY1時間足でテスト
- 1000$スタートで、−787$の赤字
- 勝率65.79%
- 25勝13敗

大負け。ですが、びっくりしたのが勝率。古典的な手法ですが、意外と勝率は良いですね。
意外と結構勝ってます。でも、負けるときに、めっちゃ大負けします。

チャートを分析
チャートをみてみると、勝ってるときはこんな感じ。ちゃんと、ゴールデンクロスでエントリー出来てます。青い線なので分かりづらいですが・・・

デッドクロスで決済する処理入れてますが、OrderSend時に利益率(0.2%)を設定しているので、それで決済してます。
ところが、こんなにキレイなゴールデンクロスだけじゃないんですね。
いわゆる「騙し」があります。短期と長期が、ぐちゃぐちゃってなるケース。

目視だと絶対にこういうケースで売買はしないけど、プログラムだと条件に合致しちゃうので、ここでエントリーしてしまいます。

大負けするときは、ほとんどこのパターン。
移動平均線のクロスは「騙し」の対処を入れる必要あり
騙しをいかにして対処するかがポイントになりそうです。
一応、思いついた対処法書いてみましたが、他のテクニカル併せているので、スマートではありません。どうも対処が思いつきませんでした。
修正部分のソース
騙しが発生するときは、ボリンジャーバンドの2σ〜-2σの間隔が、めちゃくちゃ狭くなるので、一定以上の幅の時しかトレードしないという処理を入れました。これはこれでアリだと思います。
//修正部分のみ(★の箇所を追加)
//★追加:ボリンジャーバンドの値を取得
double bb_2 = iBands(NULL,PERIOD_CURRENT,20,2,0,PRICE_CLOSE,1,0);
double bb_M2 = iBands(NULL,PERIOD_CURRENT,20,2,0,PRICE_CLOSE,2,0);
//★追加:ボリンジャーバンドの幅
double damashi_chk = bb_2 - bb_M2;
//ゴールデンクロスでBUYエントリー
if((sma_short_before < sma_long_before) && //1バー前の短期移動平均線が長期移動平均線より小さい
(sma_short_now >= sma_long_now) && //今の短期移動平均線が長期以上?
(damashi_chk >= 0.7) && //★追加:騙しチェック
flg_buy == 0){
// レートのリフレッシュ
RefreshRates();
//成り行き買いオーダー
OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,Ask*(1-SLrate),Ask*(1+Profitrate),"Buy order",MAGIC,0,clrYellow);
//フラグON
flg_buy = 1;
//デッドクロスでBUYクローズ
}else if((sma_short_before >= sma_long_before) && //1バー前の短期移動平均線が長期移動平均線以上
(sma_short_now < sma_long_now) && //今の短期移動平均線が長期より小?
flg_buy == 1){
ClosePositions_BUY();
//フラグOFF
flg_buy = 0;
}
修正後のバックテストの結果
前と同じ条件でテストした結果です。
2019年のデータでは、何とかプラス。

- USDJPY1時間足でテスト
- 1000$スタートで、+15$の黒字
- 勝率84.62%
- 11勝2敗

騙しは、ある程度は回避成功。ちょっとはマシになりました。
ただし、2回の敗けでマイナス。
敗けた箇所のチャート分析
超暴騰、直後のゴールデンクロスで天井を掴んでしまってます。騙しは無し。これは別の対処が必要ですね。

こちらも、直前の騙しは回避できたけど、暴騰直後のゴールデンクロスで引っかかりました。


うーん。他にも色々ありそう。
まとめ
単純移動平均線のクロスの売買は、そのままでは使えないなというのはよく分かりました。
ある程度の勝率はあるけど、騙しがあったり、その対処だけではカバー出来ない問題も多々ありますね。

線のクロス処理は、他でも多様するので、EAづくりの練習としては、良い素材でした。









ご質問はコメント欄からお願いします