見出し画像

【MACD編】FXテクニカル手法をChatGPTでEA化する【ノーコードEA開発】


ChatGPT担当のナナミです。

前回の動画では、ボリンジャーバンドを使用したEAを開発しました。

GPTsのリンクはこちら(GPT Store)
https://chatgpt.com/g/g-VYNEupgws-masayan-ea-generator-for-mt4-ver1-01

■ブログURL
https://fx.reform-network.net/2024/06/11/gpts「masayan-ea-generator-for-mt4-」条件を指定するだけで高性能なeaを生/

■前回記事
https://note.com/aimjey/n/n4a200f25e036

本日使用するテクニカル指標は、MACDです。

MACD

MACDは、単体でも使用できますが、他のテクニカル指標と組み合わせることで威力を発揮します。

わたしが開発したEAに、「MACD SignalTrade EURUSD」というEAがあります。

オシレーター系のテクニカル指標のMACDとローソク足から反転ポイントを見極めて売買するEAです。

このEAは、MACDがゼロ以下の時に上向きでシグナル線にクロスでロングエントリーします。
反対にMACDがゼロ以上の時に下向きでシグナル線にクロスでショートエントリーします。

MACD単体ではダマシが多くなるので、ローソク足で上げ止まり、下げ止まりを確認してからエントリーするようにプログラミングしました。

「MACD SignalTrade EURUSD」有料EA
https://www.gogojungle.co.jp/systemtrade/fx/30754

また、昨年作成した無料のEA「MACD SMA Trade GBPJPY」という1時間足チャートで動くEAがあります。
「MACD SMA Trade GBPJPY」無料EA
https://note.com/aimjey/n/nc3b26bc94e7c

というわけで、今回は、この2つのEAのロジックを使用し、EAを作成したいと思います。

まず初めに作成するEAは、MACD SignalTrade EURUSDです。

複雑なロジックだとChatGPTに正しく理解してもらえず、バグEAが生成される可能性があるので、今回は簡略化したロジックを使用します。

使用する時間足は15分足です。

送信するプロンプトは以下の通りです。

MACDのパラメーター:短期EMA「12」、長期EMA「26」、MACDシグナル「9」。

トレードする時間はサーバー時間の3時から9時、サーバー時間の15時から3時までです。
サーバー時間の9時から15時まではトレードは行いません。
サーバー時間の21時から3時までは、売買判定を逆にします。

1本前のバーと2本前のバーを比較して、MACDがゼロ以下の時に上向きでシグナル線にクロスでロングエントリーします。
反対にMACDがゼロ以上の時に下向きでシグナル線にクロスでショートエントリーします。

また、ロングの条件として、1本前の足が陽線の時だけロングすることとします。
反対にショートの条件として、1本前の足が陰線の時だけショートすることとします。

生成されたコードでバックテストしましたが、ロジックの優位性がイマイチで、完全にオワコンEAになってしまいました。

気を取り直して次のEA「MACD SMA Trade GBPJPY」の作成に進みます。

MACD SMA Tradeは、わたしの主力のEA「PerfectOrder GBPJPY」の弱点を補う目的で作成しました。

PerfectOrder GBPJPYはトレンドフォロー型のEAの宿命というべきか、レンジ相場で勝てないことが唯一の弱点でした。
この弱点を克服すべく開発したEAが「MACD SMA Trade GBPJPY」であり、その後に有料で販売することになったMagical Trend(マジカルトレンド)というEAです。

2013年からのアベノミクス相場は、比較的為替相場が穏やかな時期が続きました。
2020年のコロナパンデミックまで、値幅の小さな時期が続いており、この期間でも勝てる(負けない)トレンドフォロー型のEAの開発を行う必要がありました。
そこでわたしが選んだテクニカル指標がMACDだったわけです。

送信するプロンプトは以下の通りです。

MACD_EMA1 = 9;// MACDの短期EMA
MACD_EMA2 = 50;// MACDの長期EMA
MACD_Signal = 9;// MACDのシグナル

1本前のバーのMACDがゼロ以上、上昇方向に2本のSMAの差が拡大したタイミングでロングエントリーします。
1本前のバーのMACDがゼロ以下、下落方向に2本のSMAの差が拡大したタイミングでショートエントリーします。

1時間足チャートで動作します。

2007年01月から2023年11月30日まででバックテストをまわしてみます。

目標は、MACDSMA Tradeのプロフィットファクター1.21です。

MACDSMA Tradeのプロフィットファクター1.21

今回作成したEAのTDSによる詳細バックテストをまわしてみます。

今回作成したEAのTDSによる詳細バックテスト


2007年から2015年くらいまでは横ばいでしたが、その後は利益が伸びて、まずまずの結果が出ました。
プロフィットファクターは1.11です。

元になったEAほどのパフォーマンスは出せませんでしたが、無料で作れるEAとしては合格ではないでしょうか?
EAのソースコードは、こちらです。

//+------------------------------------------------------------------+
//|                                    Masayan EA Generator_1.01.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Masayan."
#property version   "1.01"
#property strict
#property description "https://fx.reform-network.net"

extern int Magic = 20240610;// Magic number
extern double Lots = 0.1;//1.0=100000 0.1=10000 0.01=1000
extern double StopLossRequest = 4.0;// StopLoss 0.5=50pips 1.0=100pips 10=1000pips
extern double TakeProfitRequest = 5.0;// TakeProfit 0.5=50pips 1.0=100pips 10=1000pips
extern int MaxSpread = 50;// Max spread (50=5pips)
extern int MaxError = 100;// Continuous order count limit (Max=100)
extern string CommentPositions = "Masayan EA Generator";

//ここから改変可能
extern int MACD_EMA1 = 9;// MACDの短期EMA
extern int MACD_EMA2 = 50;// MACDの長期EMA
extern int MACD_Signal = 9;// MACDのシグナル

extern int ShortSMA = 20;
extern int LongSMA = 75;
//ここまで改変可能

string tmpstr;
string error_msg;
string spread_msg;
string position_msg;
bool LongSign = false;
bool ShortSign = false;
double Pips = 0.01;
int e = 0;
int Adjusted_Slippage = 0;


// ティックが動くごとに処理
void OnTick()
  {
   if(Bars < 10)
     {
      return;
     }

   if(StopLossRequest <= 0.1)
     {
      StopLossRequest = 0.1;
     }
   if(TakeProfitRequest <= 0.1)
     {
      TakeProfitRequest = 0.1;
     }
   if(MaxError >= 100)
     {
      MaxError = 100;
     }

   double Info_Spread = MarketInfo(Symbol(), MODE_SPREAD);
   string value = Symbol();
   string target = "JPY";
   int pos = StringFind(value, target);
   double Symbol_RATE = Close[1];
   if (pos > 0)
     {
     Pips = 1.00;// ドルストレートは0.010(100pips)、クロス円は1.0(100pips)で判定
     }
   else if (Symbol_RATE > 10 && Symbol_RATE <= 100)
     {
     Pips = 0.1;
     }
   else if (Symbol_RATE > 100 && Symbol_RATE <= 1000)
     {
     Pips = 1.0;
     }
   else if (Symbol_RATE > 1000 && Symbol_RATE <= 10000)
     {
     Pips = 10.0;
     }
   else if (Symbol_RATE > 10000 && Symbol_RATE <= 100000)
     {
     Pips = 100.0;
     }
   else if (Symbol_RATE > 100000 && Symbol_RATE <= 1000000)
     {
     Pips = 1000.0;
     }
   else if (Symbol_RATE > 1000000 && Symbol_RATE <= 10000000)
     {
     Pips = 10000.0;
     }
   else if (Symbol_RATE > 10000000 && Symbol_RATE <= 100000000)
     {
     Pips = 100000.0;
     }
   else if (Symbol_RATE > 100000000)
     {
     Pips = 1000000.0;
     }

//ここから改変可能
   double shortSMA = iMA(NULL, 0, ShortSMA, 0, MODE_SMA, PRICE_CLOSE, 0);
   double longSMA = iMA(NULL, 0, LongSMA, 0, MODE_SMA, PRICE_CLOSE, 0);
   double shortSMA_prev = iMA(NULL, 0, ShortSMA, 0, MODE_SMA, PRICE_CLOSE, 1);
   double longSMA_prev = iMA(NULL, 0, LongSMA, 0, MODE_SMA, PRICE_CLOSE, 1);

   double macdCurrent = iMACD(NULL, 0, MACD_EMA1, MACD_EMA2, MACD_Signal, PRICE_CLOSE, MODE_MAIN, 0);
   double macdPrev = iMACD(NULL, 0, MACD_EMA1, MACD_EMA2, MACD_Signal, PRICE_CLOSE, MODE_MAIN, 1);

   if(macdPrev >= 0 && (shortSMA - longSMA) > (shortSMA_prev - longSMA_prev))
     {
      LongSign = true;
      ShortSign = false;
     }
   else if(macdPrev <= 0 && (longSMA - shortSMA) > (longSMA_prev - shortSMA_prev))
     {
      ShortSign = true;
      LongSign = false;
     }
//ここまで改変可能

   if (MaxSpread < Info_Spread)
     {
      LongSign = false;
      ShortSign = false;
      spread_msg = "Max spread Orber\n";
     }
   else
     {
      spread_msg = "";
     }

   if (Hour() == 4 && Minute() == 0 && Seconds() < 6)
     {
      e = 0;
     }
   if (Hour() == 11 && Minute() == 0 && Seconds() < 6)
     {
      e = 0;
     }
   if (Hour() == 18 && Minute() == 0 && Seconds() < 6)
     {
      e = 0;
     }
   if (e > MaxError)
     {
      LongSign = false;
      ShortSign = false;
      error_msg = "Continuous order count limit\n";
     }
   else
     {
      error_msg = "";
     }
   if (LongSign == true)
     {
      position_msg = "LongSign = true\n";
     }
   else if (ShortSign == true)
     {
      position_msg = "ShortSign = true\n";
     }
   else if (LongSign == false && ShortSign == false)
     {
      position_msg = "No Sign\n";
     }

//売買指示
   if (LongSign == true)
     {
      if (CalculateCurrentOrders() == 0)
        {
         // ポジション保有していない場合
         CheckForOpenLong();// 新規ロングオーダー処理を行う
         e++;
        }
      else
        {
         // ポジション保有している場合
         CloseShortPosition();// ショートポジションがある場合のみ決済ロング処理
        }
     }
   if (ShortSign == true)
     {
      if (CalculateCurrentOrders() == 0)
        {
         // ポジション保有していない場合
         CheckForOpenShort();// 新規ショートオーダー処理を行う
         e++;
        }
      else
        {
         // ポジション保有している場合
         CloseLongPosition();// ロングポジションがある場合のみ決済ショート処理
        }
     }

   tmpstr = StringConcatenate(error_msg, spread_msg, position_msg);
   Comment(tmpstr);
  }


//保有中のポジションを計算
int CalculateCurrentOrders(void)
  {
   int buys = 0;
   int sells = 0;
   int icount;
   for (icount = 0; icount < OrdersTotal(); icount++)
     {
      if (OrderSelect(icount, SELECT_BY_POS, MODE_TRADES) == false)
        {
         break;
        }
      if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
        {
         if (OrderType() == OP_BUY)
           {
            buys++;
           }
         if (OrderType() == OP_SELL)
           {
            sells++;
           }
        }
     }
   if (buys > 0)
     {
      return (buys);
     }
   else
     {
      return (-sells);
     }
  }

//ショートポジション⇒ロングクローズ処理
void CloseShortPosition()
  {
   int icount;
   bool ret;
   for (icount = 0; icount < OrdersTotal(); icount++)
     {
      if (OrderSelect(icount, SELECT_BY_POS, MODE_TRADES) == false)
        {
         break;
        }
      if (OrderMagicNumber() != Magic || OrderSymbol() != Symbol())
        {
         continue;
        }
      //ショートポジションの場合⇒ロングエントリー
      if (OrderType() == OP_SELL)
        {
         ret = OrderClose(
                  OrderTicket(),
                  OrderLots(),
                  Ask,
                  Adjusted_Slippage,
                  clrBlue);
         if (ret == false)
           {
            Print("オーダークローズエラー:エラーコード=", GetLastError());
           }
         break;
        }
     }
  }

//ロングポジション⇒ショートクローズ処理
void CloseLongPosition()
  {
   int icount;
   bool ret;
   for (icount = 0; icount < OrdersTotal(); icount++)
     {
      if (OrderSelect(icount, SELECT_BY_POS, MODE_TRADES) == false)
        {
         break;
        }
      if (OrderMagicNumber() != Magic || OrderSymbol() != Symbol())
        {
         continue;
        }
      //ロングポジションの場合⇒ショートエントリー
      if (OrderType() == OP_BUY)
        {
         ret = OrderClose(
                  OrderTicket(),
                  OrderLots(),
                  Bid,
                  Adjusted_Slippage,
                  clrRed);
         if (ret == false)
           {
            Print("オーダークローズエラー:エラーコード=", GetLastError());
           }
         break;
        }
     }
  }

//ロングオーダー処理
void CheckForOpenLong()
  {
   int res;
   double entrylot;
   entrylot = NormalizeDouble(Lots, 2);
   res = OrderSend(
            Symbol(),
            OP_BUY,
            entrylot,
            Ask,
            Adjusted_Slippage,
            Ask - (Pips * StopLossRequest),
            Ask + (Pips * TakeProfitRequest),
            CommentPositions,
            Magic,
            0,
            clrRed);
   return;
  }

//ショートオーダー処理
void CheckForOpenShort()
  {
   int res;
   double entrylot;
   entrylot = NormalizeDouble(Lots, 2);
   res = OrderSend(
            Symbol(),
            OP_SELL,
            entrylot,
            Bid,
            Adjusted_Slippage,
            Bid + (Pips * StopLossRequest),
            Bid - (Pips * TakeProfitRequest),
            CommentPositions,
            Magic,
            0,
            clrBlue);
   return;
  }

【免責事項】
・本GPTsについて、正当性を保証するものではありません。
・本GPTsを利用して損失を被った場合でも一切の責任を負いません。
・投資の決定は、自己判断 自己責任でお願いします。

いいなと思ったら応援しよう!