【第5回】FXトレード手法をChatGPTでEA化する【ノーコードEA開発】勝てるプライスアクション手法2個完成
ChatGPT担当のナナミです。
前回第4回の動画では、Masayan EA Generator for MT4を使用して、11個のプライスアクション手法の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を生/
■前回第4回
https://note.com/aimjey/n/n17f0c8f74027
Masayan EA Generator for MT4は、簡単な条件を指定するだけで高性能なEAを生成できるカスタムGPTです。
テンプレート化されたEAプログラムで、ワンポジ型のEAのロジックが生成されます。
ユーザーが入力する条件でLongSign=trueの時はロングのポジションを、ShortSign=trueの時はショートのポジションを持ちます。
決済のタイミングをユーザーが指定しない場合は、ドテン方式で決済します。
テクニカル指標のパラメータ値は、自由に変更できるように、プロパティ項目に追加されます。
デフォルト設定では、3本の移動平均線を使用したパーフェクトオーダーのロジックのEAになっています。
入力されたプロンプトに従い、必要な個所をChatGPTが書き換えます。
というわけで、前回完成したEAの中で優秀と思われるEAを更にカスタマイズしてリアル運用できるレベルに仕上げたいと思います。
1.ブレイクアウト
サポートラインやレジスタンスラインを価格が突破することを示します。ブレイクアウトは、トレンドの方向が変化する可能性を示唆します。
いわゆるレンジブレイクですね。
こちらのロジックに関してはBreakout TradingというEAで検証済みです。
Breakout Trading
https://www.gogojungle.co.jp/systemtrade/fx/45493
サーバー時間の7時から18時までエントリーするようにロジックを修正すれば成績は改善します。
レンジブレイクを狙ったEAで好成績なEAはゴゴジャンの売れ筋ランキングには存在しません。
レンジブレイクの場合、ダマシをどう回避するかが問題となりますが、単純に移動平均線を用いたトレンド判断の方が好成績になることから、ブレイクアウト手法は実用的ではないと結論付けました。
2.フェイクアウト
トレンドが反転するような動きをした後に、元のトレンド方向へ再び動き出すことを示します。
上昇トレンドの押し目買い、下降トレンドの戻り売りのロジックですね。
成績が1と2と3が似ていた理由は、トレンドの確認にパーフェクトオーダーのロジックを使用していることが原因みたいです。
長期トレンドをパーフェクトオーダーで判断してエントリーすることから、ポジションの方向が同じになるのですね。
押し目買い戻り売りのロジックを採用しているEAは世の中にたくさん出回っています。
高性能なEAがあったらロジック部分をChatGPTに伝えれば似たような成績のEAが作れるかもしれませんね。
押し目買い、戻り売りのEAを作成してとプロンプトを送信して作ったEAのバックテストはこんな感じです。
3.スラストアップ・スラストダウン
トレンドの方向に勢いよく価格が動くことを示します。スラストアップとスラストダウンがあり、それぞれ上昇トレンドと下降トレンドの強さを確認できます。
こちらのEAはスラストアップとスラストダウンのロジック部分に不具合があったみたいで、スラストアップ・スラストダウンのロジックではエントリーしないEAになっていました。
パーフェクトオーダーのロジックだけで動いていたことになります。
スラストアップ・スラストダウンのプライスアクション手法は、単純にトレンドを判断するロジックとなることから、パーフェクトオーダーのEAと同じようなEAになることから、今回詳しい検証は行いません。
次に進みましょう。
4.リバーサルハイ・リバーサルロー
トレンドが反転する可能性を示します。リバーサルパターンには、ハンマー、ブルギングベアー、エンガルフイングなど、様々な種類があります。
ChatGPTが勝手に作ったプライスアクションでしょうか?ネットで調べてもブルギングベアーというプライスアクションは存在しないようです。
プロンプトをシンプルにして再度作り直すことにします。
リバーサルハイ・リバーサルローの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 ReversalLookback = 2; // リバーサルをチェックする期間
//ここまで改変可能
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 < ReversalLookback + 1)
{
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;
}
//ここから改変可能
bool isReversalHigh = true;
bool isReversalLow = true;
for (int i = 1; i <= ReversalLookback; i++)
{
if (High[0] <= High[i])
{
isReversalHigh = false;
}
if (Low[0] >= Low[i])
{
isReversalLow = false;
}
}
if (isReversalHigh)
{
ShortSign = true;
LongSign = false;
}
else if (isReversalLow)
{
LongSign = true;
ShortSign = 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;
}
6.フェイクセットアップ
レンジ相場のブレイクに失敗した後、ブレイクと反対方向への値動きを加速させるプライスアクション。
このEAはロジックが複雑なので、プログラムの中身をいじるより、最初からやり直した方が早いです。
レンジ相場のブレイクに失敗した後、ブレイクと反対方向への値動きを加速させるプライスアクションを使用したEAを作成してとプロンプトを送信します。
作成したEAのエントリー回数が少ない場合、ChatGPTにエントリー回数が少なすぎますと修正を依頼しましょう。
それでもダメならバックテストを始値から全ティックに変更します。
どれもイマイチの成績です。
リアル運用できるレベルにはありません。
8.スパイク
ローソク足1本で急激に価格が上昇または下降する動きです。スパイクは、一時的なノイズであることが多いですが、場合によってはトレンドの反転を暗示することもあります。
バックテストの最適化を行ったところ、デフォルト設定がとても優秀でした。
15分足チャートのデフォルト設定が一番良い成績になりました。
5分足チャートはレンジ幅をデフォルト設定の50pipsを40pipsにすると成績が改善しますが、15分足チャートの方が安定するようです。
//+------------------------------------------------------------------+
//| 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 double SpikeThreshold = 0.5; // スパイクの閾値を設定 (例: 50ピップス)
extern int SpikeBar = 1; // 何本前のバーでスパイクをチェックするか (0 は最新のバー)
//ここまで改変可能
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 spikeHigh = High[SpikeBar];
double spikeLow = Low[SpikeBar];
double spikeRange = spikeHigh - spikeLow;
if(spikeRange >= SpikeThreshold * Pips)
{
if(Close[SpikeBar] > Open[SpikeBar])
{
LongSign = true;
ShortSign = false;
}
else
{
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;
}
11.ランウェイアップ・ランウェイダウン
トレンドの方向に価格が徐々に動いていくことを示します。
ロジックを分析したところ、単純に連続で陽線が出たらロング、連続で陰線が出たらショートというロジックでした。
ランウェイ期間つまり、何回連続でランウェイしたらエントリーという回数のところはプロパティ設定で指定できます。
最適化を行い調べたところ、3回連続か4回連続がパフォーマンスが良いみたいです。
デフォルト設定ではランウェイの期間は5回でした。
3回で全ティックでバックテストをまわしてみましたが、成績はイマイチです。
リアル運用できるレベルには達していません。
4の改良版リバーサルハイ・リバーサルローと、8のスパイクがリアル運用できる優秀なEAだと思います。
課題があるとすれば、トレード回数が少ないことですね。
次回から、新連載「テクニカル指標を使ってEA開発してみた」というタイトルで、以下のテクニカル指標を用いたEA開発の記事を書いていきます。
1.移動平均線:過去の一定期間の価格の平均を線で繋ぎ、トレンドの方向や強弱を判断します。期間によって短期、中期、長期のトレンドを分析できます。
2.一目均衡表:ローソク足、移動平均線、雲、基準線など複数要素を組み合わせた、複雑なテクニカル指標です。トレンドの方向や節目、エントリーポイントなどを判断できます。
3.ボリンジャーバンド:移動平均線を中心に、標準偏差を上下に表示したバンドです。ボラティリティの度合いを測ったり、エントリーポイントを探したりできます。
4.MACD:移動平均線の乖離率を棒グラフで表示した指標です。トレンドの方向や強弱、買われすぎ・売られすぎを判断できます。
5.RSI:一定期間における値幅の中で、現在の価格がどの位置にあるのかを%で表した指標です。買われすぎ・売られすぎを判断できます。
6.ストキャスティクス:一定期間における最高値と最安値の幅の中で、現在の価格がどの位置にあるのかを%で表した指標です。RSIと似ていますが、より短期的な買われすぎ・売られすぎを判断できます。
7.フィボナッチリトレースメント:前回の節目(高値・安値)と現在の価格の位置関係を、フィボナッチリ比率で表示した指標です。エントリーポイントやターゲットレベルなどを設定するのに役立ちます。
8.ZigZag:チャートにおける高値と安値をジグザグなラインで結んでくれるテクニカル指標です。トレンド分析やエントリーポイントの判断などに役立つ指標です。
他にも、こんな手法EAにしてほしいみたいなリクエストがあれば、Xにコメントお願いします。
■Xポスト
【免責事項】
・本GPTsについて、正当性を保証するものではありません。
・本GPTsを利用して損失を被った場合でも一切の責任を負いません。
・投資の決定は、自己判断 自己責任でお願いします。