MT4でフィボナッチリトレースメントEAを作成|自動エントリーするMQL4サンプルコード付き解説

EAサンプル・ノウハウ
記事内に商品プロモーションを含む場合があります
スポンサーリンク

はじめに

「フィボナッチリトレースメントを使った押し目買いロジックを、EAで自動化したい!」そんな希望を持つ方に向けて、この記事ではMT4(MQL4)で動作するフィボナッチEAの作成方法とサンプルコードを丁寧に解説します。

フィボナッチ比率は、トレードのリトレースメント判断で非常に人気があり、裁量トレードだけでなく自動売買でも有効です。ここでは、実際にチャート上にラインを引き、それを基準に自動エントリーさせるEAを紹介します。


フィボナッチリトレースメントとは?

フィボナッチリトレースメントとは、特定の高値と安値に対して、23.6%、38.2%、50%、61.8%、78.6%などの比率でラインを引く手法です。これらの水準は、トレンドが押し目を付けた後に再上昇(または再下降)する可能性があるとされ、多くのトレーダーがエントリーポイントとして活用しています。


EAの概要とポイント

  • チャートに自動でフィボナッチラインを描画
  • 指定のラインに価格がタッチしたら自動エントリー
  • エントリー場所の変更も可能

本記事では、ロング(買い)エントリーを例に解説しますが、ショートも同様に実装可能です。

エントリーポイントの確認

フィボナッチリトレースメントのエントリー時ポイント図

上記の画像でいうと、下から上にフィボナッチリトレースメントを引いた際の38.2%が赤い破線になっていますが、ここがエントリーポイントで、タッチでロングエントリーとなります。

フィボナッチリトレースメントのエントリー後の図
エントリー時にフィボナッチリトレースメントのラインを消しています

さらに高値を更新していくと、当然高値のポイントは更新されますので、38.2%のラインも上にいきます。そして、38.2%のラインタッチでロングエントリーします。

また、ショートエントリーは今回作っておりませんがサンプルコードの53行目を修正する事によってショート版のフィボナッチラインが引けます。

//ショート版で作りたい場合は53行目を以下に修正
ObjCreate(funcHighLowGet(2,Search_bar,0),funcHighLowGet(1,Search_bar,0));  //ショート版

こうする事によって、ロング版では安値から高値に引いていたフィボナッチラインをショート版では高値から安値に引くイメージです。


注意点

決済ポイントとしてはTP/SLのみにまります。
※独自のタイミングでの決済はありません

利確(TP)ポイントはフィボナッチリトレースメントの0ライン、損切り(SL)ポイントはフィボナッチリトレースメントの100ラインとしています。


ダウンロード

EAファイルをダウンロードできます。

“フィボナッチEA” をダウンロード Fibonacci.ex4 – 335 回のダウンロード – 12.96 KB

フィボナッチEAのサンプルコード解説

以下サンプルソースコードになります。
※丸々コピペでコンパイルできます

//+------------------------------------------------------------------+
//|                                                    Fibonacci.mq4 |
//|                                    Copyright © 2020-2025 ぷろぐらむFX |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020-2025 ぷろぐらむFX"
#property link      "https://fx-prog.com/"
#property version   "1.00"
#property strict

enum EnumTradeType
{
   f23,  //23.6%
   f38,  //38.2% 
   f50,  //50.0%
   f61,  //61.8%
};

input EnumTradeType EType =  f50;   //エントリータイミング
input int Search_bar = 300;   //検索足数
input double LOTS = 0.01;   //取引ロット数

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   ObjDelete();
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   double SignalPrice=0;
   
   
   if(OrdersTotal() == 0){
   
      ObjDelete();
      ObjCreate(funcHighLowGet(1,Search_bar,0),funcHighLowGet(2,Search_bar,0));
 
      if(ObjectFind(0, "LINE_F_0") >= 0){
      
         switch(EType)
         {
            case f23:
               SignalPrice = GetHorizontalLinePrice("LINE_F_23"); 
               ObjectSet("LINE_F_23",OBJPROP_COLOR,clrRed);    
               break;
            case f38:
               SignalPrice = GetHorizontalLinePrice("LINE_F_38");    
               ObjectSet("LINE_F_38",OBJPROP_COLOR,clrRed);            
               break;
            case f50:
               SignalPrice = GetHorizontalLinePrice("LINE_F_50");    
               ObjectSet("LINE_F_50",OBJPROP_COLOR,clrRed);
               break;
            case f61:
               SignalPrice = GetHorizontalLinePrice("LINE_F_61");    
               ObjectSet("LINE_F_61",OBJPROP_COLOR,clrRed);
               break;      
         }
   
   
         Print("Ask:",Ask," SP:",SignalPrice, " rosoku:",iClose(NULL, 0, 2));
         if(Ask <= SignalPrice && SignalPrice !=0){
         Print("a");
         if(SignalPrice < iClose(NULL, 0, 2)){
         Print("b");
         
            double Rikaku = GetHorizontalLinePrice("LINE_F_0");
            double Songiri = GetHorizontalLinePrice("LINE_F_100");
               
            //新規注文
            bool OrderKekka = funcOrder_Send(OP_BUY,Rikaku,Songiri,"TEST",0,LOTS,Ask);
            ObjDelete();
         }
         }
      }
   }
  }
//+------------------------------------------------------------------+

//フィボナッチライン生成関数
void ObjCreate(double high, double low)
{
   double f0, f23, f38, f50, f61, f100;
   color E_color =clrNONE;
   
   f0 = high - (high - low) * 0;   
   f23 = high - (high - low) * 0.236;
   f38 = high - (high - low) * 0.382;
   f50 = high - (high - low) * 0.5;
   f61 = high - (high - low) * 0.618;
   f100 = high - (high - low) * 1;

   E_color =clrYellow;


   //【0ラインの設定】
   ObjectCreate(0, "LINE_F_0",OBJ_HLINE,0,0,f0); 
   ObjectSet("LINE_F_0",OBJPROP_COLOR,E_color);
   ObjectSet("LINE_F_0",OBJPROP_STYLE,STYLE_DOT); 
   ObjectSet("LINE_F_0",OBJPROP_BACK,false);           // オブジェクトの背景表示設定
   
   //【23ラインの設定】  
   ObjectCreate(0, "LINE_F_23",OBJ_HLINE,0,0,f23); 
   ObjectSet("LINE_F_23",OBJPROP_COLOR,E_color);
   ObjectSet("LINE_F_23",OBJPROP_STYLE,STYLE_DOT); 
   ObjectSet("LINE_F_23",OBJPROP_BACK,true);           // オブジェクトの背景表示設定
      
   //【38ラインの設定】  
   ObjectCreate(0, "LINE_F_38",OBJ_HLINE,0,0,f38); 
   ObjectSet("LINE_F_38",OBJPROP_COLOR,E_color);
   ObjectSet("LINE_F_38",OBJPROP_STYLE,STYLE_DOT); 
   ObjectSet("LINE_F_38",OBJPROP_BACK,true);           // オブジェクトの背景表示設定   

   //【50設定】         
   ObjectCreate(0, "LINE_F_50",OBJ_HLINE,0,0,f50); 
   ObjectSet("LINE_F_50",OBJPROP_COLOR,E_color);
   ObjectSet("LINE_F_50",OBJPROP_STYLE,STYLE_DOT); 
   ObjectSet("LINE_F_50",OBJPROP_BACK,true);           // オブジェクトの背景表示設定

   //【61ラインの設定】     
   ObjectCreate(0, "LINE_F_61",OBJ_HLINE,0,0,f61); 
   ObjectSet("LINE_F_61",OBJPROP_COLOR,E_color);
   ObjectSet("LINE_F_61",OBJPROP_STYLE,STYLE_DOT); 
   ObjectSet("LINE_F_61",OBJPROP_BACK,true);           // オブジェクトの背景表示設定     
   
   //【100ラインの設定】         
   ObjectCreate(0, "LINE_F_100",OBJ_HLINE,0,0,f100); 
   ObjectSet("LINE_F_100",OBJPROP_COLOR,E_color);
   ObjectSet("LINE_F_100",OBJPROP_STYLE,STYLE_DOT); 
   ObjectSet("LINE_F_100",OBJPROP_BACK,false);           // オブジェクトの背景表示設定

}

//フィボナッチライン削除関数
void ObjDelete()
{

   ObjectDelete(0,"LINE_F_0");
   ObjectDelete(0,"LINE_F_23");
   ObjectDelete(0,"LINE_F_38");   
   ObjectDelete(0,"LINE_F_50");   
   ObjectDelete(0,"LINE_F_61");
   ObjectDelete(0,"LINE_F_100");

}

//水平ライン価格取得関数
double GetHorizontalLinePrice(string lineName)
{
    if (ObjectFind(0, lineName) >= 0){
        return ObjectGetDouble(0, lineName, OBJPROP_PRICE1);
    }else{
        return 0;
    }
}

//+------------------------------------------------------------------+
//|【関数】直近の高値安値を取得する                                       |
//|                                                                  |
//|【引数】 Type=(1:高値 2:安値)  Kikan=確認する期間                     |
//|                                                                  |
//|【戻値】最高値又は最安値                                              |
//|                                                                  |
double funcHighLowGet(int Type,int Kikan,int Start)
{
   double Kakaku=0;

   if(Type==1){
      Kakaku = iHigh(NULL, 0, iHighest(NULL,0,MODE_HIGH,Kikan,Start));
   }
   else if(Type==2){
      Kakaku = iLow(NULL, 0, iLowest(NULL,0,MODE_LOW,Kikan,Start));
   }
   return Kakaku;   
}

//+------------------------------------------------------------------+
//|【関数】新規注文関数
//|
//|【引数】 ea_order_entry_Type:売買(0:買 1:売)
//|【引数】 order_stop_price:損切値  order_good_price:利確値
//|【引数】 orderComment:オーダーコメント    ea_order_MagicNo:マジックNo
//|
//|【戻値】True:成功 False:失敗
//|
//|
bool funcOrder_Send(int ea_order_entry_Type,double orderRikaku,double orderSongiri,string orderComment,int ea_order_MagicNo,double ea_lots,double ea_order_entry_price)
{

   int order_resend_num,ea_ticket_res;        // エントリー試行回数,チケットNo

   double ea_order_good_price=0,ea_order_stop_price=0;
   color order_Color = clrGray;
   bool kekka;
   int ea_ticket[100]; //ポジションのチケット番号保有用(2だと3ポジまで) 5ポジ持たせたい場合は4にすること
   
   kekka=false;

   for( order_resend_num = 0; order_resend_num < 10; order_resend_num++ ) {    // エントリー試行回数上限:10回

         ea_order_stop_price = orderSongiri;
         ea_order_good_price = orderRikaku;   
         
         if(ea_order_entry_Type == OP_BUY || ea_order_entry_Type == OP_BUYLIMIT){   
            order_Color = clrBlue;
         }else if(ea_order_entry_Type == OP_SELL || ea_order_entry_Type == OP_SELLLIMIT){            
            order_Color = clrRed;
         }
         
         ea_order_entry_price = NormalizeDouble(ea_order_entry_price,Digits());
         ea_order_stop_price = NormalizeDouble(ea_order_stop_price,Digits());
         ea_order_good_price = NormalizeDouble(ea_order_good_price,Digits());


         if(orderSongiri ==0){
            ea_order_stop_price = 0;
         }
         if(orderRikaku ==0){
            ea_order_good_price = 0;
         }
         // FXCMでは新規エントリー時にストップ/リミットを設定出来ない。
         ea_ticket_res = OrderSend(   // 新規エントリー注文
            NULL,                     // 通貨ペア
            ea_order_entry_Type,      // オーダータイプ[OP_BUY / OP_SELL]
            ea_lots,                  // ロット[0.01単位](FXTFは1=10Lot)
            ea_order_entry_price,     // オーダープライスレート
            20,                       // スリップ上限    (int)[分解能 0.1pips]
            ea_order_stop_price,      // ストップレート
            ea_order_good_price,      // リミットレート
            orderComment,             // オーダーコメント
            ea_order_MagicNo,         // マジックナンバー(識別用)
            0,                        // オーダーリミット時間
            order_Color               // オーダーアイコンカラー
            );
         
         if ( ea_ticket_res == -1) { 
            Print("新規注文失敗 エラーNo:",GetLastError()," リトライ回数:",order_resend_num+1," lot数:",ea_lots, " Price:",ea_order_entry_price," TP:",ea_order_good_price," SL:",ea_order_stop_price);
            
            Sleep(5000);                                           // msec待ち
            RefreshRates();                                        // レート更新
   
         } else {    // 注文約定
            Print("新規注文完了 レート:",DoubleToStr(ea_order_entry_price,Digits())," ロット数:",ea_lots," オーダーコメント:",orderComment);
            
            Sleep(500);                                           // 500msec待ち
            kekka=true;
            break;
         }

   }
   return kekka;   
}

98行目~149行目がフィボナッチリトレースメントの線を引く関数です。

フィボナッチは線を引いていないと実際そうなってるのか分かりずらいので、EA側でも線を引くようにしています。

スポンサーリンク

パラメータとカスタマイズ

今回のパラメータ設定は3つです。

  • フィボナッチのエントリータイミング(23.6%, 38.2%, 61.8%)
  • フィボナッチの高値安値の取得範囲(ローソク足本数)
  • 取引ロット数
フィボナッチリトレースメントのパラメータ設定図

【エントリータイミング】は何パーセントになったらエントリーするか、検索足数はフィボナッチリトレースメントの0ラインと100ラインを確認するローソク足数です。あとは取引ロット数ですね。

あと、エントリータイミングの設定は選択式にしています。

フィボナッチリトレースメントのパラメータ設定詳細図

ここで選択したパーセンテージが、チャート上で赤色になりタッチでエントリーという感じです。

スポンサーリンク

EAレポート結果

今回はゴールド(XSU/USD)で確認しています。

フィボナッチリトレースメントのレポート結果図
※サンプルEAの作り上、始値のみの確認となっています

1年間の結果ですが中々良かったです。


まとめ

フィボナッチリトレースメントを活用したEAは、視覚的に分かりやすく、ロジックも単純明快です。実装もシンプルなので、初心者のEA開発入門にも最適です。

まずはサンプルコードをコピペして試してみて、自分なりの改良を加えてみましょう。

私がよく利用しているZigZagとも相性が良いので是非使ってみて下さい。


✅ 他にも多数のEAサンプルを公開中!

今回紹介した内容以外にも、当サイトではさまざまなFX自動売買EAのサンプルコードを提供しています。

自分に合った戦略のEAを見つけたい方は、ぜひチェックしてみてください。


EA開発初心者向けに、今後も実践的なMQL4関数を紹介していきます。
気になる機能やロジックがあれば、ぜひ他の記事もあわせてご覧ください!

コメント