見出し画像

Williams%Rにどのテクニカル指標を追加したら勝てるのか検証してみた【あなたの考えたFX手法をEAにする】


ChatGPT担当のナナミです。

前回から新シリーズ「あなたの考えたFX手法をEAにする」というテーマで動画を投稿しています。

最初のお題は「ASCTrend&フラクタルズ」だったのですが、作業を進めるうえで様々な疑問がわいてきました。

これらの疑問を解決しつつ、本日のテーマ「Williams%Rにどのテクニカル指標を追加したら勝てるのか?」の検証動画を撮っていこうと思います。

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

■ブログURL
https://fx.reform-network.net/2024/08/29/新シリーズ「あなたの考えたfx手法をeaにする」/

■前回記事(ASCTrendにフラクタルズのフィルターを追加したら勝てるのか?)
https://note.com/aimjey/n/n60868f33ddb3

まず、4つの疑問を、最近話題のAI検索エンジン、ジェンスパークにぶつけてみたいと思います。

質問1、Williams%Rが-30以上でロング、-70以下でショートとすることは、移動平均線を用いたトレンドフォローの手法と同じになりますか?

【回答】
Williams%Rと移動平均線を用いた手法は、基本的に違います。

Williams%Rの手法は、オシレーター系指標を使い、-30以上でロング、-70以下でショートを行う逆張り戦略です。←ここ間違っています。
移動平均線の手法は、トレンドフォロー戦略として長期的なトレンドに基づいた取引を行います。
Williams%Rは短期の反転を狙う逆張り手法で、移動平均線はトレンドに従うフォローストラテジーです。

ジェンスパークさん、逆張りの手法と順張り手法を混同していますね。

質問2、ASCTrendのサインの出るロジックを教えて

【回答】
ASCTrendは、トレンドフォロー型のインジケーターで、トレンドシグナルを生成します。
ウィリアムズパーセントレンジ (WPR): 短期(9期間)と長期(54期間)のWPRを使用して色分けされたトレンドシグナルを生成するなど、初心者から経験者まで広く利用できるインジケーターです。

質問3、ASCTrendとフラクタルズのサインの違いを教えて

【回答】
ASCTrendとフラクタルズは、異なる目的と手法を持つトレーディングインジケーターです。

ASCTrend: 市場のトレンドを識別し、トレンドフォロー戦略を取り、長期的なトレンドの流れに基づいた取引に適しています。

フラクタルズ: 5本のローソク足パターンを使い、短期的な価格の反転ポイントを特定するツールで、サポートやレジスタンスの特定に役立ちます。

まとめると、ASCTrendはトレンドフォロー型、フラクタルズは反転狙いの逆張り手法ということですね。

質問4、ASCTrendとフラクタルズはMT4のインジケーターは存在します。関数をそのままEAにしてもレートが正しく取得されないのはなぜですか?

【回答】
ASCTrendとフラクタルズはMT4で利用可能なインジケーターですが、これらをエキスパートアドバイザー(EA)に変換する際、レートが正しく取得されないことがあります。

関数の互換性問題として、 MT4のインジケーター用関数(例:iFractals)がEA内で動作しないことが確認されています。

解決には、インジケーターのロジックを再構築し、MT4の仕様に基づいたプログラミングが必要です。

この元の記事って全部わたしがnoteで書いたことですよね。


iFractalsがEA内で動作しないことが確認されています。って、わたしが一昨日noteで書いたことですよね。

これはつまり、わたしが嘘の記事を書けばジェンスパークが嘘の回答をするわけで、ハルシネーション(AIが質問に対して不正確な情報を返すこと)に繋がります。

いちおう、ASCTrendとフラクタルズの関数がEAで機能しないことをChatGPTとGeminiにも聞いてみます。

やっぱり具体的な解決策は得られませんでした。

原因が分かる人いたらコメントで教えていただけると助かります。

Williams%Rについての理解が深まったところで、Williams%Rを使用したEAの開発を行いたいと思います。

Williams%Rを使用したEAは、ChatGPTでも作れますし、手作業でコーディングすることもできます。

問題は、どの様なロジックにするかです。

試しに、Williams%Rが-30以上でロング、-70以下でショートというEAをMasayan EA Generator for MT4で作ってみます。

プロパティ画面で設定を変えながら、バックテストして最適な値を調べます。

私はいつもはEAを作る時は、5分足チャートで動くEAを開発するのですが、今回はスキャルピング系のサインインジケーターをリリースしていきたいとの思いから、開発は1分足チャートで行います。

デフォルトの設定のままでは、トレード回数が多すぎて順張りのロジックではうまくいかなかったので、逆張りのロジックをテストするために、売りと買いを逆にしました。

スプレッドは最小の0.1pipsでの結果です。

1分足チャートだとトレード回数が多すぎるので、Williams%Rの期間を長くするしかありません。

とりあえず、最初は順張りとして開発を進めて、最後に逆張りでテストします。

ChatGPTに追加で、以下のプロンプトを送信します。

様々なトレンドフォローのテクニカル指標を追加してください。
Williams%Rが-30以上になったら買いサイン、-70以下になったら売りサインは必ず入れます。
その他のテクニカル指標のフィルターは、プロパティ設定で切り替えできるようにしてください。

これで、複数の売買フィルターを一度に追加することが出来ます。

期間を2020年からとして、フィルターを切り換えながらバックテストしていきます。

いろいろな設定を試してみましたが、移動平均線のロジックと相性がよさそうです。

ということで、移動平均線を3本用いたパーフェクトオーダーのロジックをフィルターに加えることとします。

移動平均線の期間は、わたしのEA「PerfectOrderポンド円」の販売ページにあります、ドル円15分足の最適な設定を参考にします。

PerfectOrder_GBPJPY
https://www.gogojungle.co.jp/systemtrade/fx/30753



短期が25で、中期が50、長期が80ですね。

1分足チャートで動かすので、それぞれの値に15を掛けて短期が375、中期が750、長期が1200で設定します。

実はこの設定、移動平均線でおおまかなトレンドを判断することになるのですが、移動平均線の優位性のみで勝ってしまいます。

つまり、移動平均線を使用したトレンドフォローのEAとほとんど同じになってしまうのです。

ここからが、ウイリアムズのロジックに磨きをかけていく作業です。

まず、ウイリアムズ単体で決済のロジックを追加してみます。

期間が14だと負けてしまいます。

やはり、ウイリアムズの期間を14から変える必要がありそうです。

通常であれば1時間足とか4時間足で動かすのでしょうから、期間が14というのは、1時間足なら14時間、日足なら14日ということになります。
さすがに1分足で期間14は短すぎます。

というわけで、ウイリアムズの期間を延ばしていくと、プロフィットファクターはぐんぐん上がっていきます。
ウイリアムズの期間は1000がよさそうですね。

1分足で1000ということは、1000分つまり16時間でのWilliams%Rの値で売買判定するということですね。

ここで、移動平均線などのフィルターを有効にしてバックテストしてみましたが、どれもイマイチです。

全部の設定をためしたわけではありませんが、移動平均線のみ追加した時のプロフィットファクターは1.14と、成績が一番良かったです。

また、MACDとRSIの設定を変更することで大幅に成績が改善する可能性があります。

完成した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 = 20240905;// 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 10=1000pips
extern double TakeProfitRequest = 5.0;// TakeProfit 0.5=50pips 10=1000pips
extern int MaxSpread = 50;// Max spread (50=5pips)
extern int MaxError = 100;// Continuous order count limit (Max=100)
extern string CommentPositions = "WillsukyaEA";
extern bool OnlyWilliams = false; // Williams%Rだけで売買判定 true 他のテクニカル指標を追加して判定 false
extern double OverboughtLevel = -10.0; // Williams%R 買われすぎの閾値
extern double OversoldLevel = -70.0;   // Williams%R 売られすぎの閾値
extern int WilliamsPeriod = 1000;        // Williams%Rの期間(デフォルト1000)

// 移動平均線フィルタ
extern bool UseSMAFilter = true;
extern int ShortMAPeriod = 375;
extern int MiddleMAPeriod = 750;
extern int LongMAPeriod = 1200;

// MACDフィルタ
extern bool UseMACDFilter = true;
extern int MACDFastPeriod = 12;
extern int MACDSlowPeriod = 26;
extern int MACDSignalPeriod = 9;

// RSIフィルタ
extern bool UseRSIFilter = true;
extern int RSIPeriod = 14;
extern double RSIOverbought = 70.0;
extern double RSIOversold = 30.0;

string tmpstr;
string error_msg;
string spread_msg;
string position_msg;
bool LongSignMh = false;
bool ShortSignMh = false;
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;
     }

// フィルタの判定
   LongSign = false;
   ShortSign = false;
   LongSignMh = false;
   ShortSignMh = false;
   
   double WilliamsR = iWPR(NULL, 0, WilliamsPeriod, 1); // Williams%Rの値を取得
   if(WilliamsR > OverboughtLevel)  // Williams%Rが-30以上の場合、ロングシグナル
     {
      LongSignMh = true;
     }
   else if(WilliamsR < OversoldLevel)  // Williams%Rが-70以下の場合、ショートシグナル
     {
      ShortSignMh = true;
     }

   // SMAフィルタ
   if(UseSMAFilter)
     {
      double shortMA = iMA(NULL, 0, ShortMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
      double middleMA = iMA(NULL, 0, MiddleMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
      double longMA = iMA(NULL, 0, LongMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
      if(shortMA > middleMA && middleMA > longMA && LongSignMh == true) // ロングシグナル
        {
         LongSign = true;
         ShortSign = false;
        }
      else if(shortMA < middleMA && middleMA < longMA && ShortSignMh == true) // ショートシグナル
        {
         ShortSign = true;
         LongSign = false;
        }
     }

   // MACDフィルタ
   if(UseMACDFilter)
     {
      double macdMain = iMACD(NULL, 0, MACDFastPeriod, MACDSlowPeriod, MACDSignalPeriod, PRICE_CLOSE, MODE_MAIN, 0);
      double macdSignal = iMACD(NULL, 0, MACDFastPeriod, MACDSlowPeriod, MACDSignalPeriod, PRICE_CLOSE, MODE_SIGNAL, 0);
      if(macdMain > macdSignal && LongSignMh == true) // ロングシグナル
        {
         LongSign = true;
         ShortSign = false;
        }
      else if(macdMain < macdSignal && ShortSignMh == true) // ショートシグナル
        {
         ShortSign = true;
         LongSign = false;
        }
     }

   // RSIフィルタ
   if(UseRSIFilter)
     {
      double rsi = iRSI(NULL, 0, RSIPeriod, PRICE_CLOSE, 0);
      if(rsi > RSIOverbought && LongSignMh == true) // ロングシグナル
        {
         LongSign = true;
         ShortSign = false;
        }
      else if(rsi < RSIOversold && ShortSignMh == true) // ショートシグナル
        {
         ShortSign = true;
         LongSign = false;
        }
     }
 if(OnlyWilliams == true){
 LongSign = false;
 ShortSign = false;
   if(LongSignMh == true)  // Williams%Rが-30以上の場合、ロングシグナル
     {
      LongSign = true;
     }
   else if(ShortSignMh == true)  // Williams%Rが-70以下の場合、ショートシグナル
     {
      ShortSign = true;
     }
 }
// ここまでフィルタの判定
/*
//決済ロジックを追加する場合
if(CalculateCurrentOrders() == 1){// ロングポジション保有
    if(ShortSignMh = true){//Williams%Rが-30以上の場合
CloseLongPosition();// ロングポジションを決済
    }
} else if(CalculateCurrentOrders() == -1){// ショートポジション保有
    if(LongSignMh = true){//Williams%Rが-70以下の場合
CloseShortPosition();// ショートポジションを決済
    }
}
*/
   if(MaxSpread < Info_Spread)
     {
      LongSign = false;
      ShortSign = false;
      spread_msg = "Max spread exceeded\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
     {
      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;
  }

興味のある方は、ぜひ使ってみてください。

というわけで、本日のまとめです。

Williams%Rは、順張り方向にトレードする方が逆張りより勝ちやすい。

1分足チャートの場合のWilliams%Rの期間は1000、つまり1000分で売買判定すると勝てる可能性が高い。

他のテクニカル指標と組み合わせることで成績が改善する可能性がある。

Williams%Rの最適な設定は-10以上でロング、-70以下でショートです。


完成したEAのバックテスト

当チャンネルでは、MT4のEA開発に役に立つ情報を配信しています。

他にも、こんな手法EAにしてほしいみたいなリクエストがあれば、コメントお願いします。


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

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