見出し画像

パラボリックSARを使用したEAを作成してみた【あなたの考えたFX手法をEAにする】


ChatGPT担当のナナミです。

前回の動画では、Williams%Rを使用したスキャルピングEAの開発を行いました。

本日は、パラボリックSARを使用した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/08/29/新シリーズ「あなたの考えたfx手法をeaにする」/

■前回記事(Williams%Rを使用したスキャルピングEAを作成してみた)
https://note.com/aimjey/n/nee7785f27bad

パラボリックは主にトレンド転換点を見極めるために使用されるテクニカル指標です。

パラボリックSAR


SAR(Stop And Reverse)と呼ばれる放物線状のラインをチャート上に表示しますとあります。

この放物線に沿ってトレードするトレンドフォロー型の手法ということですね。

この点線は一目均衡表の雲のようなイメージでしょうか。

また、ストップ&リバースとあるように、ドテンで売買することを前提とするテクニカル指標ということで、Masayan EA Generator for MT4との相性は良さそうです。

それでは早速EAを作ってみましょう。

プロンプトにパラボリックと入力します。

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

ドル円1分足から4時間足まで順番にバックテストします。

1時間足以下はダメですね。

4時間足だとプラスになります。

今度は、TDSによる全ティックバックテストをまわしてみます。

2007年から2024年6月までのバックテスト結果です。

プロフィットファクターは1.11でした。


始値のみの簡易バックテスト(4時間足)

このままでも良いのでしょうが、4時間足というのはEA運用において使いたくない時間足です。

できれば5分足とか15分足でチャート表示したいですよね。

修正方法として、パラボリックSARのステップの値をデフォルトの0.02より小さい数字に変えることで対処できそうです。

試しに、1時間足でSARのステップの値を0.01にしてみます。

プロフィットファクターは1.11に改善しましたね。

15分足でSARのステップの値を0.001にしてバックテストします。

プロフィットファクターは1.17まで上昇しました。

15分足だと、SARのラインがチャートの画面から消えるくらい離れてしまいます。

裁量トレードなら、1時間とか4時間足のほうが見やすいですね。

EAの場合チャートのインジケーターは確認しないので、15分足で動かしても問題なさそうです。

MT4の最適化機能を使い、一番成績の良い設定を探してみます。

一番成績の良いSARのステップの値は、0.001に決まりました。

これは期待できそうです。

TDSによる全ティックバックテストをまわしてみます。

2007年から2024年6月までのバックテスト結果です。


Parabolic SARのドル円のバックテスト結果

トレード回数は4065回、プロフィットファクターは1.16、総利益は13228ドルと最高のパフォーマンスを叩き出すことに成功しました。

このEA、この記事をご覧の皆様に無料でプレゼントします。

EAの名前はParabolic SARです。

下記コードをコピーしてEA設置してください。

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

extern int Magic = 20240918;// 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 = "Parabolic SAR";

extern double Step = 0.001; // パラボリックSARのステップ(15分足)
extern double Maximum = 0.2; // パラボリックSARの最大値

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 sarValue = iSAR(NULL, 0, Step, Maximum, 1);
   double closePrice = Close[1];

   if(closePrice > sarValue)
     {
      LongSign = true;
      ShortSign = false;
     }
   else if(closePrice < sarValue)
     {
      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;
  }

ここで、ある疑問がわいてきました。

このEA、トレンドフォローのEAということで、類似のトレンドフォローのEA「GoldenCross USD/JPY」なんかとトレードのタイミングが被るのではないか?



GoldenCross_USDJPY

GoldenCross_USDJPY
https://www.gogojungle.co.jp/systemtrade/fx/43098

それから、トレンドフォローということは、ポンド円でも勝てるはずです。


Parabolic SARのポンド円のバックテスト結果


ポンド円でのバックテスト結果は、トレード回数は4641回、プロフィットファクターは1.10、総利益は14214ドルとドル円と同等のパフォーマンスとなります。

さすがに、わたしが開発した有料のEA、3本の移動平均線からパーフェクトオーダーを見極めて売買する「PerfectOrder_GBPJPY(パーフェクトオーダー ポンド円)」には敵いませんが、無料EAとしては最強クラスのEAだと思います。



PerfectOrder_GBPJPY

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

ご利用は無料となりますので、ぜひあなたのEAポートフォリオに組み込んでいただけると幸いです。


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

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