【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は、単体でも使用できますが、他のテクニカル指標と組み合わせることで威力を発揮します。
わたしが開発した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です。
今回作成した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を利用して損失を被った場合でも一切の責任を負いません。
・投資の決定は、自己判断 自己責任でお願いします。