見出し画像

【ストキャスティクスとフィボナッチリトレースメント編】FXテクニカル手法をChatGPTでEA化する【ノーコードEA開発】


■YouTube動画で解説
https://youtu.be/3RUTdOQ3CeY

ChatGPT担当のナナミです。

前回の動画では、RSIを使用した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/n1c91cd18f3b1

本日使用するテクニカル指標は、ストキャスティクスとフィボナッチリトレースメントです。

ストキャスティクス

ストキャスティクスは、相場の過熱感を分析するオシレーター系のインジケーターで、逆張りのロジックと相性が良く、他のテクニカル指標と組み合わせることで威力を発揮します。

反応速度について
ファーストストキャス: %Kと%Dの反応速度が速く、短期的な価格変動に敏感に反応します。
スローストキャス: %Dとスロー%Dの反応速度が遅く、長期的な価格変動を捉えやすい指標です。

ダマシについて
ファーストストキャス: 反応速度が速いため、ダマシが多くなります。
スローストキャス: 反応速度が遅いため、ダマシが少ない指標です。

使い分けについて
ファーストストキャス: 短期売買やデイトレードに向いています。
スローストキャス: 中長期売買やスイングトレードに向いています。

わたしが開発したEAに、「GyakubariKing Stochastics G B P U S D」というEAがあります。
https://www.gogojungle.co.jp/systemtrade/fx/30756
このEAでは、ファーストストキャスを使用します。
時間足は4時間足を使用します。
一日のうちでエントリーと決済を行うデイトレEAとなっております。
内部のロジックがとても複雑で、ChatGPTに正確にプロンプトを送信することができません。

そこで今回は、簡易的なロジックでEAを作成しようと思います。

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

%K期間「5」(固定)
%D期間「3」(固定)
スローイング期間「1」(固定)

2本前のバーの%Kの値が2本前のバーの%Dの値以下で、かつ、1本前のバーの%Kの値が1本前のバーの%Dの値よりも大きい場合で1本前の足が陽線でロングエントリー。

2本前のバーの%Kの値が2本前のバーの%Dの値以上で、かつ、1本前のバーの%Kの値が1本前のバーの%Dの値よりも小さい場合で1本前の足が陰線でショートエントリー。

有料版のEAのロジックは、時間帯別に順張りと逆張りを切り替えるマルチロジックを採用していますが、今回作成するEAはシングルロジックのEAとします。

バックテストの期間は2010年1月2日から2021年4月30日です。

元になったEAのバックテスト結果

元になったEA

今回作成したEAのバックテスト結果

今回作成したEA

成績はイマイチですね。

サーバー時間の7時から18時は欧州、ロンドン、ニューヨークの市場が順次オープンする時間帯になります。
参考までにサーバー時間の7時から18時にエントリーするロジックに書き換えてもらいます。

バックテストをまわしてみます。


修正版


特徴の無いバックテスト結果ですね。

このロジックに意味を見出せません。

こうしたジグザグした資産チャートは、優位性の無いEAの可能性が高いです。

続けてフィボナッチリトレースメントのEAを作成してみましょう。


フィボナッチ

ロジックについてあれこれ考える必要はありません。

プロンプトは「フィボナッチリトレースメント」とだけ送信します。

わたしが作成したGPTs「Masayan EA Generator for MT4 」は、テンプレートを使用してEAのコードを生成します。

ChatGPTがフィボナッチリトレースメントの手法を考えEAテンプレートにロジックを組み込みします。

生成されたコードでバックテストをまわしてみます。

バックテストの期間は、2013年1月2日から2024年6月30日です。

24時間トレードする順張りのロジックが生成されました。


24時間トレードする順張りのロジック

バックテスト結果はイマイチですね。

実は、順張りのロジックの場合、サーバー時間の7時から18時までエントリーするようにすれば、簡単に成績を改善させることができます。


改良版のEA サーバー時間の7時から18時までエントリー

どうですか?

24時間トレードより、サーバー時間の7時から18時までエントリーするロジックの方が成績が良いのが分かります。

この様に、一日のうちでトレードする時間帯を限定することで成績が改善することがあります。
順張りの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 FibonacciLookback = 20; // フィボナッチリトレースメントを計算するための期間
//ここまで改変可能

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 CalculateFibonacciLevels(double &fibHigh, double &fibLow, double &fibLevel38, double &fibLevel61)
  {
   int lookback = FibonacciLookback;
   fibHigh = High[iHighest(NULL, 0, MODE_HIGH, lookback, 0)];
   fibLow = Low[iLowest(NULL, 0, MODE_LOW, lookback, 0)];
   fibLevel38 = fibLow + (fibHigh - fibLow) * 0.382;
   fibLevel61 = fibLow + (fibHigh - fibLow) * 0.618;
  }

// ティックが動くごとに処理
void OnTick()
  {
   if(Bars < FibonacciLookback)
     {
      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 fibHigh, fibLow, fibLevel38, fibLevel61;
   CalculateFibonacciLevels(fibHigh, fibLow, fibLevel38, fibLevel61);

   double currentPrice = Close[0];

   if(currentPrice > fibLevel61)
     {
      LongSign = true;
      ShortSign = false;
     }
   else
      if(currentPrice < fibLevel38)
        {
         ShortSign = true;
         LongSign = false;
        }
//ここまで改変可能

   if(MaxSpread < Info_Spread)
     {
      LongSign = false;
      ShortSign = false;
      spread_msg = "Max spread Order\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 = "";
     }

   // エントリー時間の制限
   int currentHour = Hour();
   if(currentHour < 7 || currentHour >= 18)
     {
      LongSign = false;
      ShortSign = false;
     }

   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;
  }

ちなみに、逆張りに有利な時間帯は日本時間の深夜から日本時間の午前中になります。
サーバー時間で言う18時過ぎから6時くらいまでです。
ピンポイントで逆張りに有利な時間帯を狙うならサーバー時間の23時から3時くらいでしょうか。
注意しなければいけない点として、サーバー時間の0時前後は、スプレッドが拡大しやすい時間帯となり、不利なトレードになりやすいです。
したがって、リアルトレードでは思ったほど利益が出ないことがあります。
朝スキャEAを作成する際は、サーバー時間の0時付近のトレードには注意して下さい。サーバー時間の0時は日本時間で夏だと朝の6時、冬だと朝の7時です。

次回のテクニカル指標は、ZigZagとダウ理論です。


ZigZag

ZigZagとダウ理論は、補完的な関係にあることから、ダウ理論についても次回の動画でEA化してみたいと思います。

実は、ZigZagを使用したEAを何個か開発したことがあります。
どれもイマイチな成績だったことから、公開することなくすべてお蔵入りとなってしまいました。
ダウ理論に関してはEA化が難しく、開発したことはありません。

ダウ理論

おそらくChatGPTなら簡単にロジックを組んでくれるでしょうから、ダウ理論には期待しています。

次回の動画が終わったら、次は新連載として「勝てるロジックのEA化」というテーマで動画を撮っていこうと思います。
「勝てるロジックのEA化」とは、ネットなどで公開されている勝てると言われる手法をわたしの作成したGPTs「Masayan EA Generator for MT4 」を使ってEAにしていく。
そんな感じの動画を撮っていきますので、応援よろしくお願いします。


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