見出し画像

専業スキャルパーのヒロシさんのFX手法をベースに勝てるデイトレEAを完成させてみた【勝てるロジックのEA化】


ChatGPT担当のナナミです。

前回の動画では、FXスキャルパーのヒロシさんの手法を使いスキャルのEAを作成しました。


失敗作 スキャルのEA

ですが、移動平均線を用いた売買フィルターを追加しただけでは勝てないことが分かったので、今回、様々なテクニカル指標の売買フィルターを追加して勝てるEAに仕上げたいと思います。

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

■ブログURL
https://fx.reform-network.net/2024/07/23/【新連載】fx手法をchatgptでea化する【勝てるロジックの/

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

今回行う作業は、以下の通りです。

まず、前回作成したテンプレートをベースに、ChatGPTを使いテクニカル指標を追加していきます。

次に、成績の良かったEAに、決済のロジックを追加します。

最初の問題として、手当たり次第にロジックを試すのは効率的か?というのがあります。

わたしはこれまで、100個以上のEAを開発してきました。

なので、過去に開発したEAのロジックであれば、いくらでも組み込むことはできます。

例えば、わたしの最も得意とするマルチタイムフレーム分析を使用したロジックをEAに組み込めば、簡単に勝てるEAは作れます。

Bear Mindというわたしの最高傑作といえるEAは、マルチタイムフレーム分析によるトレンド判断ロジックを採用したグリッドトレードナンピンEAです。

Bear Mind

https://www.gogojungle.co.jp/systemtrade/fx/51278

わたしが開発したマルチタイムフレーム分析によるトレンド判断ロジックは一般には公開していません。

有料にはなりますが、ゴゴジャンで販売しているので購入して頂けると本物のEAというのがどういうものなのか分かると思います。

ちなみに、日々の収益というのはリアルトレードで確認できます。
https://www.gogojungle.co.jp/users/626040/realtrade

FXTFのリアル口座となりますので、嘘偽りのない本当の成績になります。

さて、皆様にロジックを公開できる範囲でのEA開発となると、やはり一般に普及しているプライスアクション手法やテクニカル指標を使用するというのが現実的となります。

わたしの過去の動画として、noteとYouTubeに以下のプライスアクション手法やテクニカル指標を使用したEA開発を行いました。

【プライスアクション手法】
1.ブレイクアウト
2.フェイクアウト
3.スラストアップ・スラストダウン
4.リバーサルハイ・リバーサルロー
5.ピンバー
6.フェイクセットアップ
7.フォールスブレイクアウト
8.スパイク
9.アウトサイドバー・インサイドバー
10.ランウェイアップ・ランウェイダウン

【テクニカル指標】
11.移動平均線(前回使用)
12.一目均衡表
13.ボリンジャーバンド(メインロジックで使用)
14.MACD
15.RSI(メインロジックで使用)
16.ストキャスティクス
17.フィボナッチリトレースメント
18.ZigZag

このうち、移動平均線は前回使用しました。
ボリンジャーバンドとRSIは、メインロジックで使用しています。

ということで、残りのプライスアクション手法とテクニカル指標を順番にEAに組み込み、片っ端からバックテストを取ってみたいと思います。

ChatGPTが生成するEAとなることから、コードに問題があったとしても手動修正は行わず、エラーのEAが出来た時はNGとして次に進みます。

どれか一つでも、勝てるEAが出来るとよいですね。

それでは作業を進めていきます。

ChatGPTに修正内容とEAのテンプレートを送信します。

【プライスアクション手法】
1.ブレイクアウト、⇒NGトレードしない
2.フェイクアウト、⇒プロフィットファクター 1.05
3.スラストアップ・スラストダウン、⇒プロフィットファクター 1.10
4.リバーサルハイ・リバーサルロー、⇒プロフィットファクター 1.05
5.ピンバー、⇒プロフィットファクター 1.05
6.フェイクセットアップ、⇒NGトレード少ない
7.フォールスブレイクアウト、⇒プロフィットファクター 1.05
8.スパイク、⇒プロフィットファクター 1.06
9.アウトサイドバー・インサイドバー、⇒プロフィットファクター 1.02
10.ランウェイアップ・ランウェイダウン、⇒プロフィットファクター 1.00

【テクニカル指標】
12.一目均衡表、⇒プロフィットファクター 1.04
14.MACD、⇒NGトレード回数が少ない
16.ストキャスティクス、⇒プロフィットファクター 1.03
17.フィボナッチリトレースメント、⇒プロフィットファクター 1.17
18.ZigZag、⇒プロフィットファクター 1.02

この中で好成績なロジックは、フィボナッチリトレースメントですね。

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

スパイクも若干成績が上がりました。

スパイク

フィボナッチリトレースメントは、過去の高値 (highestHigh) と安値 (lowestLow) を使用して、指定したレベル (FibonacciLevel) におけるフィボナッチレベルを計算し、フィボナッチリトレースメントのレベルを考慮し、価格が適切なレベルにあるかどうかで売買シグナルをフィルタリングします。
フィボナッチレベルを計算しfibonacciLevelより上の時はロング、下の時はショートのポジションを持つようです。

最初に生成されたコードでは、フィボナッチリトレースメントの計算のための過去の期間が50となっていました。
このままでは、エントリー回数の少ないEAになってしまいます。

そこで、期間を500にすると、右肩上がりの資産チャートになります。

結論から申し上げますと、1分足チャートで動かす場合、期間50では短すぎるので、500とか1000にすると成績が改善されるようです。

スパイクは、特定の時間内に急激に価格が上昇または下落した後に、逆方向に反転するプライスアクションです。

バックテストをまわしてみた結果、スパイクには優位性は感じられないのでスパイクは無効化してフィボナッチリトレースメントのみ売買フィルターに追加します。

完成したEAのソースコードはこちらです。

//+------------------------------------------------------------------+
//|                                    Masayan EA Generator_1.01.mq4 |
//|17.フィボナッチリトレースメント+スパイク
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Masayan."
#property version   "1.01"
#property strict
#property description "https://fx.reform-network.net"

extern int Magic = 20240828;// Magic number
extern double Lots = 0.1;//1.0=100000 0.1=10000 0.01=1000
extern double StopLossRequest = 1.0;// StopLoss 0.1=10pips 0.5=50pips 1=100pips
extern double TakeProfitRequest = 1.0;// TakeProfit 0.1=10pips 0.5=50pips 1=100pips
extern int MaxSpread = 50;// Max spread (50=5pips)
extern int MaxError = 100;// Continuous order count limit (Max=100)
extern string CommentPositions = "Fibonacci Retracement";

//ここから改変可能
extern int RsiPeriod = 14; // RSIの期間
extern int BollingerBandsPeriod = 30; // ボリンジャーバンドの期間
extern int BollingerBandsDeviation = 2; // ボリンジャーバンドのシグマ値
extern int FibonacciLookBack = 500; // フィボナッチリトレースメント計算のための過去の期間500か1000
extern double FibonacciLevel = 0.5; // フィボナッチリトレースメントのレベル (例: 0.5 = 50%)
extern int SpikeLookBackPeriod = 5; // スパイクを確認する過去のバーの数(無効)
extern double SpikeThreshold = 0.006; // スパイクの閾値(パーセンテージ)(無効)
//ここまで改変可能

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;

// フィボナッチリトレースメントを計算する関数
double CalculateFibonacciLevel(double high, double low, double level)
{
   return high - (high - low) * level;
}

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

   if (StopLossRequest <= 0.01)
   {
      StopLossRequest = 0.01;
   }
   if (TakeProfitRequest <= 0.01)
   {
      TakeProfitRequest = 0.01;
   }
   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 highestHigh = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, FibonacciLookBack, 0));
   double lowestLow = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, FibonacciLookBack, 0));
   
   // フィボナッチレベルを計算
   double fibonacciLevel = CalculateFibonacciLevel(highestHigh, lowestLow, FibonacciLevel);

   // RSIとボリンジャーバンドを計算
   double rsi = iRSI(NULL, 0, RsiPeriod, PRICE_CLOSE, 1);
   double upperBand = iBands(NULL, 0, BollingerBandsPeriod, BollingerBandsDeviation, 0, PRICE_CLOSE, MODE_UPPER, 1);
   double lowerBand = iBands(NULL, 0, BollingerBandsPeriod, BollingerBandsDeviation, 0, PRICE_CLOSE, MODE_LOWER, 1);
   double currentPrice = Close[0];

/*
   // スパイクフィルターの追加
   bool spikeDetected = false;
   for (int i = 1; i <= SpikeLookBackPeriod; i++)
   {
      double priceChange = MathAbs((Close[i] - Open[i]) / Open[i]);
      if (priceChange >= SpikeThreshold)
      {
         spikeDetected = true;
         break;
      }
   }
*/
 //if (!spikeDetected){
   // ロングサインの条件
   if (rsi <= 30 && currentPrice <= lowerBand && currentPrice >= fibonacciLevel)
   {
      LongSign = true;
      ShortSign = false;
   }
   // ショートサインの条件
   else if (rsi >= 70 && currentPrice >= upperBand && currentPrice <= fibonacciLevel)
   {
      ShortSign = true;
      LongSign = false;
   }
   else
   {
      LongSign = false;
      ShortSign = 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;
}

スパイクは無効にしてます。
スパイク有効にする場合、カスタマイズしてご利用ください。

次に、決済のロジックを追加します。

前回の動画でも使用したRSIが50にタッチで決済するやり方です。

始値のみのバックテストにはなりますが、プロフィットファクターは1.16でトレード回数は27137回に跳ね上がりました。

ですが、利益は下がってしまい使い物にならないEAになってしまいました。

おそらく、全ティックでバックテストを回すと勝てないEAになるでしょうから、やはりドテンの売買ロジックのほうが優秀ということでしょうか。

というわけで、完成したEAのTDSによる全ティックバックテストをまわしてみます。


完成したEAのTDSによる全ティックバックテスト

プロフィットファクターは1.09と決して高くはありませんが、トレード回数は年間500回程度と非常にバランスの取れたEAだと思います。

次回の動画では、FX億トレーダーの「しん」さんのスキャル手法をEAにしたいと思います。

FX億トレーダーの「しん」さん

「しん」さんのYouTubeチャンネル

しんさんの代表的なトレードルールを抜粋してみました。

【逆張りトレード】
ボリンジャーバンドの±2シグマが9pips以上開いているレンジ相場の時は
逆張りでトレードを行います。
ボリンジャーバンドの±2シグマのレンジの上限で売り、
下限で買ってボリンジャーバンドの中心線の手前で利確します。
利食い幅は値動きの小さい時は2pips、値動きの大きな時は5pipsとします。
ヒゲが2本3本続くと反転しやすいので逆張りでエントリーします。
キリバン手前も反発しやすいので逆張りでエントリーします。
この時は、キリバンタッチで損切りします。
ヒゲがない陰の丸坊主の時はショート、
陽の丸坊主が出現した時はロングエントリーします。

【順張りトレード】
トレンド相場ではボリンジャーバンドの中心線近くまで
引き付けての押し目買い、戻り売りとします。

以上の条件をChatGPTに打ち込み、EAを作ってみたいと思います。

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

この記事が気に入ったらサポートをしてみませんか?