ChatGPTによる成行買い指値/逆指値付き注文関数の作成
ChatGPT(GPTs)を活用して、水平線を設定した位置に指値/逆指値を設定し、成行買い注文を行う便利な関数を作成しました。
使用GPTs:EA Creator
目的とプロセス
目的は端的に言うと、“現在値の上下に設定した水平線に基づいて、指値と逆指値を自動で設定し成行買い注文を実行する“関数を作成することでした。
最適な依頼方法を模索しつつ、何度かのやり取りを経て、望んだ結果を得ることができました。
最終的な依頼内容と実行結果
以下が最終的な依頼内容であり、この通りに期待された関数を作成しました。
詳細なプロセスに興味のある方は、「期待結果にたどり着くまでのChatGPTとのやり取り」をご参照ください。
依頼内容
以下の仕様で買い注文を行うMQL4用の関数を作成してください。
・現在値で成り行き注文を行い、同時に指値、逆指値も設定する。
・ObjectName()とObjectType()を使って、チャート上に設定されている水平線を確認する。
外部パラメータで設定された文字列”Horizontal Line”で始まるものを有効な水平線とする。
・指値は、現在値より上にある有効な水平線の内、もっとも現在値に近い水平線の値とする。
上に水平線が見つからなかった場合は、指値は外部パラメータ(指値オフセット値)で設定した値とする。
・逆指値は、現在値より下にある有効な水平線の内、もっとも現在値に近い水平線の値とする。
下に水平線が見つからなかった場合は、逆指値は外部パラメータ(逆指値オフセット値)で設定した値とする。
・指値および逆指値として使用した水平線は削除する
・ロットサイズは外部パラメータ”lotSize”で設定したものを使用する
・ロットサイズの初期値は0.1とする
・スリッページの値は外部パラメータ(Slippage)で設定する
・注文時のマジックナンバーは外部パラメータ(MagicNumber)で設定する
ChatGPT出力結果
以下は、指定された仕様に基づいてMQL4用の買い注文関数です。この関数は、指定された条件に合致する水平線を探索し、それを基にして指値と逆指値を設定します。さらに、ロットサイズ、スリッページ、マジックナンバーは外部パラメータから取得します。
// 外部パラメータ extern double lotSize = 0.1; // ロットサイズの初期値 extern string linePrefix = "Horizontal Line"; // 水平線の名前の接頭辞 extern double takeProfitOffset = 50.0; // 指値オフセット値(pips) extern double stopLossOffset = 50.0; // 逆指値オフセット値(pips) extern int slippage = 3; // スリッページ extern int MagicNumber = 123456; // マジックナンバー // 買い注文関数 void PlaceBuyOrder() { double askPrice = MarketInfo(Symbol(), MODE_ASK); double bidPrice = MarketInfo(Symbol(), MODE_BID); double upperLimitPrice = 0.0; double lowerStopPrice = 0.0; string upperLineName = ""; string lowerLineName = ""; // チャート上の水平線をチェック for(int i = 0; i < ObjectsTotal(); i++) { string name = ObjectName(i); if(ObjectType(name) == OBJ_HLINE && StringFind(name, linePrefix) == 0) { double linePrice = ObjectGet(name, OBJPROP_PRICE1); // 現在値より上にある有効な水平線を探す if(linePrice > askPrice && (upperLimitPrice == 0.0 || linePrice < upperLimitPrice)) { upperLimitPrice = linePrice; upperLineName = name; } // 現在値より下にある有効な水平線を探す else if(linePrice < bidPrice && (lowerStopPrice == 0.0 || linePrice > lowerStopPrice)) { lowerStopPrice = linePrice; lowerLineName = name; } } } // 指値および逆指値の設定 if(upperLimitPrice == 0.0) upperLimitPrice = askPrice + (takeProfitOffset * Point * 10); if(lowerStopPrice == 0.0) lowerStopPrice = bidPrice - (stopLossOffset * Point * 10); // 成行買い注文を出す int ticket = OrderSend(Symbol(), OP_BUY, lotSize, askPrice, slippage, lowerStopPrice, upperLimitPrice, "Buy Order", MagicNumber, 0, clrBlue); if(ticket <= 0) { Print("OrderSend failed with error #", GetLastError()); } else { Print("Buy order placed successfully with ticket #", ticket); // 使用した水平線を削除 if(upperLineName != "") ObjectDelete(upperLineName); if(lowerLineName != "") ObjectDelete(lowerLineName); } }
この関数は、現在価格で成行買い注文を出し、
"Horizontal Line"
で始まる名前を持つ水平線を検索します。最も現在値に近い上方と下方の水平線が指値と逆指値の基準になります。水平線が見つからなかった場合、外部パラメータで設定されたオフセット値を使用して指値と逆指値を設定します。注文後、指値および逆指値として使用した水平線は削除されます。
期待結果にたどり着くまでのChatGPTとのやり取り
最初のやり取り
最初の依頼とその結果は不十分で、依頼内容をより明確にし、目的に合った関数を作成するための改善が必要でした。
んん、、指値、逆指値を設定する処理がないし、水平線を1つしか探していない、、依頼が曖昧過ぎたか。。
依頼内容
以下の仕様で買い注文を行うMQL4用の関数を作成したください。
・現在値で成り行き注文を行う。
・ObjectName()とObjectType()を使って、チャート上に設定されている水平線を確認する。
外部パラメータで設定された文字列”Horizontal Line”で始まるもののみを対象とする。
・現在値より上にある対象の水平線が見つかったら、それを指値に設定する。
・現在値より下にある対象の水平線が見つかった場合は、それを逆指値とする。
・水平線が見つからなかった場合は、指値または逆指値は設定なしとする。
・条件に合致するものが複数見つかった場合は、現在値より最も近い線を有効とする。
・有効とした水平線は削除する
・ロットサイズを外部パラメータで設定したものを使用する
・ロットサイズの初期値は0.1とする
ChatGPT出力結果
了解しました。以下は、指定された要件に基づいたMQL4用の関数です。この関数は、現在価格での成行買い注文を行い、特定の条件に基づいて指値または逆指値を設定します。また、指定された名前で始まる水平線をチャート上で探し、最も近い水平線を利用して注文を設定します。
// 外部パラメータ extern double lotSize = 0.1; // ロットサイズの初期値 extern string linePrefix = "Horizontal Line"; // 水平線の名前の接頭辞 // 買い注文関数 void PlaceBuyOrder() { double currentPrice = MarketInfo(Symbol(), MODE_ASK); // 現在の買い値を取得 double pendingPrice = 0.0; // 指値または逆指値 double nearestDistance = DBL_MAX; // 最も近い距離を記録する変数 string nearestLineName = ""; // 最も近い水平線の名前 // チャート上の全オブジェクトを走査 for(int i = 0; i < ObjectsTotal(); i++) { string name = ObjectName(i); // 水平線で、名前が指定された接頭辞で始まるか確認 if(ObjectType(name) == OBJ_HLINE && StringFind(name, linePrefix) == 0) { double linePrice = ObjectGet(name, OBJPROP_PRICE1); double distance = MathAbs(currentPrice - linePrice); // 現在値に最も近い水平線を見つける if(distance < nearestDistance) { nearestDistance = distance; nearestLineName = name; pendingPrice = linePrice; } } } // 最も近い水平線が見つかった場合 if(nearestLineName != "") { // 指値または逆指値を設定 if(pendingPrice > currentPrice) { // 指値注文 } else { // 逆指値注文 } // 使用した水平線を削除 ObjectDelete(nearestLineName); } // 成行買い注文を出す int ticket = OrderSend(Symbol(), OP_BUY, lotSize, currentPrice, 3, 0, 0, "", 0, 0, Blue); }
この関数は、現在価格での成行買い注文を行い、指定された名前の接頭辞で始まる水平線を探します。最も近い水平線が見つかれば、その価格を指値または逆指値として使用し、使用した水平線は削除されます。ロットサイズは外部パラメータとして設定されており、初期値は0.1です。
2回目のやり取り
ということで、依頼内容を見直しました。
んん、、、指値と逆指値を設定してないし、まだまだか、、、
依頼内容
以下の仕様で買い注文を行うMQL4用の関数を作成したください。
・現在値で成り行き注文を行う。
・ObjectName()とObjectType()を使って、チャート上に設定されている水平線を確認する。
外部パラメータで設定された文字列”Horizontal Line”で始まるものを有効な水平線とする。
・指値は、現在値より上にある有効な水平線の内、もっとも現在値に近い水平線の値とする。
上に水平線が見つからなかった場合は、指値設定はなしとする。
・逆指値は、現在値より下にある有効な水平線の内、もっとも現在値に近い水平線の値とする。
下に水平線が見つからなかった場合は、逆指値設定はなしとする。
・有効とした(使用した)水平線は削除する
・ロットサイズを外部パラメータで設定したものを使用する
・ロットサイズの初期値は0.1とする
ChatGPT出力結果
了解しました。以下は、指定された要件に基づいてMQL4用の買い注文関数です。この関数は、チャート上にある特定の名前で始まる水平線をチェックし、条件に合うものがあればそれを使用して指値または逆指値を設定します。また、関数は現在の価格で成行買い注文を行います。
// 外部パラメータ extern double lotSize = 0.1; // ロットサイズの初期値 extern string linePrefix = "Horizontal Line"; // 水平線の名前の接頭辞 // 買い注文関数 void PlaceBuyOrder() { double currentPrice = MarketInfo(Symbol(), MODE_ASK); // 現在の買い値を取得 double upperLimitPrice = 0.0; // 指値 double lowerStopPrice = 0.0; // 逆指値 double nearestUpperDistance = DBL_MAX; // 上の水平線までの最も近い距離 double nearestLowerDistance = DBL_MAX; // 下の水平線までの最も近い距離 string upperLineName = ""; // 上の水平線の名前 string lowerLineName = ""; // 下の水平線の名前 // チャート上の全オブジェクトを走査 for(int i = 0; i < ObjectsTotal(); i++) { string name = ObjectName(i); // 水平線で、名前が指定された接頭辞で始まるか確認 if(ObjectType(name) == OBJ_HLINE && StringFind(name, linePrefix) == 0) { double linePrice = ObjectGet(name, OBJPROP_PRICE1); if(linePrice > currentPrice) { // 現在値より上の水平線 double distance = linePrice - currentPrice; if(distance < nearestUpperDistance) { nearestUpperDistance = distance; upperLimitPrice = linePrice; upperLineName = name; } } else if(linePrice < currentPrice) { // 現在値より下の水平線 double distance = currentPrice - linePrice; if(distance < nearestLowerDistance) { nearestLowerDistance = distance; lowerStopPrice = linePrice; lowerLineName = name; } } } } // 使用した水平線を削除 if(upperLineName != "") ObjectDelete(upperLineName); if(lowerLineName != "") ObjectDelete(lowerLineName); // 成行買い注文を出す int ticket = OrderSend(Symbol(), OP_BUY, lotSize, currentPrice, 3, 0, 0, "", 0, 0, Blue); // 指値と逆指値を設定する場合は、追加の注文処理を行う // (ここで適切なOrderSend関数を使用して設定する) }
この関数は、外部パラメータとしてロットサイズを設定し、初期値は0.1です。水平線は、指定された接頭辞で始まるもののみが考慮されます。現在価格より上にある最も近い水平線は指値として、下にある最も近い水平線は逆指値として使用されます。使用した水平線は削除されます。最後に、成行買い注文が出されます。指値や逆指値を設定する場合、追加の注文処理が必要になります。
3回目以降のやり取り
ということで、さらに、以下など問題があった部分の修正依頼を行ったら、おおよそ期待した結果を出してもらえました。
そこで、水平線が無かった場合の仕様など、少し見直して依頼し直した結果が、最初に「最終的な実行結果」で記載した結果になります。
依頼内容
成行買い注文を出すときに、指値と逆指値を設定してください
OrderSend で指値と逆指値を設定できるはずです。見直しお願いします
水平線の削除は、すべての水平線をチェックし終わった後にしてもらえますか。 オブジェクトの総数が変化することと、使用してない水平線を削除してしまうのではないかと思われるため。
ChatGPT出力結果
extern double takeProfitOffset = 50.0; // 指値オフセット値(pips)
extern double stopLossOffset = 50.0; // 逆指値オフセット値(pips)void PlaceBuyOrder() {
double askPrice = MarketInfo(Symbol(), MODE_ASK);
double upperLimitPrice = 0.0; // 指値
double lowerStopPrice = 0.0; // 逆指値
string upperLineName = “”;
string lowerLineName = “”;// チャート上の水平線をチェック for(int i = 0; i < ObjectsTotal(); i++) { string name = ObjectName(i); if(ObjectType(name) == OBJ_HLINE && StringFind(name, linePrefix) == 0) { double linePrice = ObjectGet(name, OBJPROP_PRICE1); if(linePrice > askPrice && (upperLimitPrice == 0.0 || linePrice < upperLimitPrice)) { upperLimitPrice = linePrice; upperLineName = name; } else if(linePrice < askPrice && (lowerStopPrice == 0.0 || linePrice > lowerStopPrice)) { lowerStopPrice = linePrice; lowerLineName = name; } } } // 指値と逆指値のオフセットを適用 if(upperLimitPrice == 0.0) upperLimitPrice = askPrice + takeProfitOffset * Point * 10; if(lowerStopPrice == 0.0) lowerStopPrice = askPrice - stopLossOffset * Point * 10; // 使用した水平線を削除 if(upperLineName != "") ObjectDelete(upperLineName); if(lowerLineName != "") ObjectDelete(lowerLineName); // 成行買い注文を出す int ticket = OrderSend(Symbol(), OP_BUY, lotSize, askPrice, 3, lowerStopPrice, upperLimitPrice, "", 0, 0, Blue);
}
コメント