目次
はじめに
ChatGPTでEAが作成できるという噂を聞いたので、今回はナンピンEAを作成してみました。
そこで作成にあたり今回は縛りを一つ入れておりまして、それは「自然言語」でのみ指示をし、手動でのプログラム修正を禁止して、作成してみました。
返答時間も含めて30分程で一応動くものはできましたので、宜しければコードをご確認下さい。
ご自身のMetaEditorに張り付けてコンパイルすれば動くと思います。
ナンピン戦略の基礎
X界隈で大人気のナンピン戦略。
個人的には使った事はありませんが、人気という事で作成してみました。
ナンピンとは、逆指値を指定せず、価格が一定逆行するごとにポジションを追加するという手法です。
特徴として、勝率が劇高なこと。
負け=破綻を意味する事です。
証拠金維持率が関わってくるため、どちらかと言えば海外口座が適した手法だとも言えます。
ChatGPTとの初期段階
まずChatGPTへの最初の指示はこうでした。
「MQL4にてEAのコードを示して
・ナンピンを使用」
以上です。
で、出てきたコードはこちら
コメントも自動で入力してくれているのが嬉しい点。
//+------------------------------------------------------------------+
//| Expert advisor sample |
//+------------------------------------------------------------------+
input double LotSize = 0.01; // ロットサイズ
input double TakeProfit = 50; // 利益確定点(ポイント)
input double StopLoss = 50; // 損切り点(ポイント)
input double Distance = 50; // ナンピンする距離(ポイント)
input int MaxOrders = 5; // 最大オーダー数
int OnInit()
{
// EA初期化コード
return(INIT_SUCCEEDED);
}
void OnTick()
{
// 現在のオープンオーダー数を確認
int orders = OrdersTotal();
// 最大オーダー数に達していない場合、新規オーダーを作成
if(orders < MaxOrders)
{
double price = Ask;
// 最後のオーダーから一定距離離れているか確認
if(orders > 0)
{
OrderSelect(orders - 1, SELECT_BY_POS);
price = OrderOpenPrice();
}
if(Ask - price > Distance * Point)
{
// ナンピンオーダーを作成
OpenBuyOrder();
}
}
}
// バイオーダーを開く関数
void OpenBuyOrder()
{
double sl = Ask - StopLoss * Point;
double tp = Ask + TakeProfit * Point;
// オーダーを開く
OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp, "", 0, clrNONE);
}
コードの修正と改善
形上は動きそうなものがでてきましたが、この状態では当然使えません。
少しづつ指示を与えて修正していきます。
上のコードをコンパイルしたところ、OrderSelect、OrderSendの戻り値チェックに関するエラーが出たので「OrderSelectの戻り値があるかチェックを入れて下さい。」と指示したところ、無事修正がされました。
最終的なEAコード
ここから、さらにおかしい点に修正指示を出していきました。
修正指示の概要
- ストップロスとテイクプロフィット: 当初のコードでは、ストップロス(SL)とテイクプロフィット(TP)の設定が不適切であることが判明。市場の最小ストップレベルを考慮し、TPを適切に設定する必要がありました。
- 平均価格の計算: ナンピン戦略では、全ポジションの平均取得価格を考慮することが重要です。この価格の正確な計算と更新が必要でした。
- リスク管理: ナンピン戦略は高リスクであるため、適切なリスク管理のための仮定と制限を設けることが必要でした。
実装された主要な修正
各修正指示に基づいて、以下のような変更がコードに実装されました。
- TPの動的調整: ブローカーの最小ストップレベルと市場価格からの1 pipsの距離を考慮してTPを設定。
- 平均価格の正確な更新: 新しいポジションが開かれるたびに平均価格を更新し、これを新しいTPの計算に利用。
- リスク管理の強化: 合計ポジションサイズや最大ドローダウンなど、リスクを管理するためのパラメータを導入。
そして出来たコードがこちら
フリーです。お好きなようにお使いください。
//+------------------------------------------------------------------+
//| Expert advisor sample |
//+------------------------------------------------------------------+
input double LotSize = 0.01; // 初期ロットサイズ
input double TakeProfit = 50; // 利益確定点(ポイント)
input double Distance = 50; // ナンピンする距離(ポイント)
input int MaxOrders = 5; // 最大オーダー数
input int ShortMAPeriod = 10; // 短期移動平均線の期間
input int LongMAPeriod = 20; // 長期移動平均線の期間
double AveragePrice = 0; // 平均取得価格
double TotalLots = 0; // 合計ロット数
int OnInit()
{
// EA初期化コード
return(INIT_SUCCEEDED);
}
void OnTick()
{
// 移動平均線の計算
double shortMA = iMA(Symbol(), 0, ShortMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
double longMA = iMA(Symbol(), 0, LongMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
// エントリー条件(短期MAが長期MAを上回る)
if(shortMA > longMA)
{
// 現在のオープンオーダー数を確認
int orders = OrdersTotal();
// 最後にオープンしたポジションの価格を取得
double lastOrderPrice = 0;
if(orders > 0 && OrderSelect(orders - 1, SELECT_BY_POS))
{
lastOrderPrice = OrderOpenPrice();
}
// 最大オーダー数に達していない場合、新規オーダーを作成
if(orders < MaxOrders)
{
// 最後のオーダーから一定距離離れているか確認
if(orders == 0 || (Ask - lastOrderPrice > Distance * Point))
{
double newLotSize = LotSize * MathPow(2, orders);
// 最初のエントリー時にAveragePriceをAskに設定
if(orders == 0) AveragePrice = Ask;
// ナンピンオーダーを作成
if(OpenBuyOrder(newLotSize))
{
// 平均価格と合計ロット数を更新
UpdateAveragePrice(newLotSize, Ask);
}
else
{
// OrderSendに失敗した場合の処理
Print("OrderSend failed with error: ", GetLastError());
}
}
}
}
}
// バイオーダーを開く関数
bool OpenBuyOrder(double lotSize)
{
double minStopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
double onePip;
// 通貨ペアの桁数に基づく1 pipsの計算
if (Digits == 5)
onePip = 0.00001; // 5桁の通貨ペアの場合
else if (Digits == 3)
onePip = 0.001; // 3桁の通貨ペアの場合
else
onePip = 0.01; // その他の桁数の場合
double tpPrice = AveragePrice + TakeProfit * Point; // 新しいテイクプロフィット価格
// テイクプロフィット価格が最小ストップレベルを満たしているか確認し、1 pips加算
if (MathAbs(tpPrice - Ask) < minStopLevel + onePip)
tpPrice = Ask + minStopLevel + onePip;
tpPrice = NormalizeDouble(tpPrice, Digits);
Print(Ask," ",tpPrice);
// オーダーを開く(ストップロスなし)
int ticket = OrderSend(Symbol(), OP_BUY, lotSize, Ask, 3, 0, tpPrice, "", 0, clrNONE);
return ticket > 0; // オーダー送信が成功したかどうかを返す
}
// 新しい平均価格と合計ロット数を更新する関数
void UpdateAveragePrice(double newLotSize, double newOrderPrice)
{
if(TotalLots == 0) // 初めてのオーダー
{
TotalLots = newLotSize;
}
else
{
TotalLots += newLotSize;
AveragePrice = ((AveragePrice * (TotalLots - newLotSize)) + (newOrderPrice * newLotSize)) / TotalLots;
}
}
コードのテスト結果
とりあえず、ドル円で2023年をテストしてみました。
うん。ナンピンっぽい。

ChatGPTとの開発の振り返り
正直プログラムの開発に難航した部分もありました。
それは意外にも以下の部分でした。
// 最初のエントリー時にAveragePriceをAskに設定
if(orders == 0) AveragePrice = Ask;
初期はこの行がなかったため常にAveragePrice が0.0となり、正常なエントリーがされませんでした。
なので「AveragePrice が0.0でエントリーされないから直して」って指示を数回したのですが、結局直らず、最終的に「最初のエントリー時はAveragePriceにAsk入れとけ!ボケナス!!!」と具体的な指示をしてやっと直りました。
それでもパーツなしで0の状態から作成するよりは断然早く、おおよそ20分ほどで、動作するまでにはできました。※手動で手直ししてよいならもっと早かった。
結論
今回は自然言語の指示に縛ってプログラムをしたため、これでプログラミングスキル0でもEA作れるぜ!!!って言いたいところですが、実際問題それはかなり厳しいと感じました。
その理由は、修正の指示をするのにも多少のプログラミングスキルが必要だからです。
恐らく、プログラミングスキルが0では、どこがおかしいのか分からないため、修正指示もできないと思います。
なのであくまでEAに関して言えば、chatGPTは単なる時短ツールかな~というのが正直な感想でした。


コメント