English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
preview
MQL4およびMQL5開発のフレームワーク内のOpenAI ChatGPT機能

MQL4およびMQL5開発のフレームワーク内のOpenAI ChatGPT機能

MetaTrader 5トレーディング | 13 9月 2023, 10:48
1 412 0
Evgeniy Ilin
Evgeniy Ilin

内容



はじめに

それでは、基本から始めましょう。このテクノロジーは、OpenAIの人工知能のバリエーションの1つであり、人々がさまざまなタスクを解決できるように設計されています。このツールは通常のメッセンジャーチャットのように見えますが、もう一方の端には、テキスト形式で応答するいわゆる人工知能が存在します。

もちろん、コミュニケーションチャネルはテキストのみに限定されますが、さまざまな問題を解決したり、多くの新しいことを学ぶにはそれでも十分です。このテキストチャネルは、熟練した翻訳やその他の能力はもちろん、プログラミング、数学、物理学、化学など、まったく異なる問題を解決するのに適しています。

私たちがこのモデルに興味を持っているのは、収益性の高い取引システムの開発という観点からのみです。私は、このテクノロジーを最適かつ正確に使用して、取引システムをより迅速かつ簡単に開発する方法に興味を持ちました。最後に開発コストと人件費の両方を削減し、明らかな競争上の優位性をもたらすのは、真っ先にテクノロジーをその意図された目的に正しく適用し始めた人です。


MQL5内でChatGPTを使用する可能性

テクノロジーの見通しについてさらに詳しく見てみましょう。私自身の例をかなり詳細に研究した結果、そのようなテクノロジーは本当に素晴らしいものの始まりにすぎないことがわかりました。ただし、今でさえも次の機能にハイライトを当てることができます。

  • 任意のMQL4およびMQL5コードを生成する
  • 実用的なコードをリファクタリング・最適化する
  • コードをクリーンアップする
  • コードにコメントを追加する
  • エラーを修正する
  • 数学的モデルを実装する
  • 数学的モデルに基づいてコードを構築する
  • 既知のアルゴリズムと数学的モデルを最新化する
  • エキスパートアドバイザー(EA)開発プロセスを高速化する
  • 膨大な量の情報

このリストは決して最終的なものではなく、ここに独自の内容を追加することができます。この種のテクノロジーについて知ったときに、人々はほぼ次の3つのサブグループに分類されると思います。

  1. 「これでスーパーアルゴリズムを作れる」
  2. AIに警戒感を持ち、その有用性に疑問を抱いている人
  3. 「機械が人間より優れているはずがない。すべて単なる誇大広告だ。」

遥か前にこのテクノロジーに出会ったとき、私は最初は3番目のカテゴリに属していました。このAIを扱い始めてから最初の2日間で、突然3番目のカテゴリから1番目のカテゴリに移行しました。その後、自分の信念を調整するという、より興味深く、むしろ不快なプロセスが始まりました。「1.5」カテゴリへのロールバックに近いものです。これはすでにこのテクノロジーのより現実的な評価になっています。
このテクノロジーは便利ですが、最初に考えるほどではありません。この点で、このテクノロジーの開発者とマーケティング担当者に敬意を払う価値はあります。たとえそれが最初の数日間の使用で信じられないほどの「すごい」効果を生み出すという事実だけでも、自己プロモーションの連鎖反応には十分です。

これを理解するには、このAIを扱う上で多くの練習が必要です。個人的には、さまざまなトピックについて約100回の対話をおこないました。このテクノロジーをMQL5で使用し始めるのに十分な練習を積んだと言えます。実際の応用に移る前に、非常に重要な情報をいくつかお伝えしておく必要があります。そのためには、このテクノロジーの内部をさらに詳しく調べる必要があります。


ChatGPTに関連する潜在的な落とし穴

このテクノロジーを使用した初期に経験するいわゆる「すごい」効果は、これが主に質問を答えに変えるように設計されたテキストモデルであるという事実によるものです。あなたがその答えを気に入る理由は、作成者がこのモデルに美しい嘘をつくように教えたからです。いいえ、冗談ではありません。モデルはあなた自身も信じたくなるほど見事に嘘をつき、それを暴露しようと何度も試みた後でさえ、しばしば次のようなものをあなたに提供します。

  • すみません。おっしゃる通りです。少し間違ってしまいました。今後はこれを考慮していきます。(実際にはしません。これは単なる空約束です)
  • 誤解を与えて申し訳ありません、間違えました。こちらが修正版です。(さらに多くの間違いを含みます)
  • モデルの計算に誤りがあることがわかるかもしれません。(実際、モデルはまったく計算を行っておらず、単にどこかでおおよその数値を見つけただけです)
  • コード内にエラーが検出されました。(モデルはまた言い訳をしてあなたを騙そうとします)
  • モデルはタスクの実行を模倣し、要求したことが実行されたことをユーザーに納得させようとします。(実際には、類似したものをどこかから見つけて提供するだけです)
  • すみません。お手伝いできませんでした。(これはモデルが嘘や間違いを検出したことを理解したときに起こります)
  • モデルは、調和のとれた一貫した回答という印象を与えるために、回答に過剰な単語を大量に追加します。(これはリソースコストの最適化に何らかの形でつながっていると思います)

つまり、モデルは、「プロンプト」の不完全性を利用しながら、あらゆる方法で提供されたタスクをスキップしようとします。間違いがあった場合、それはあなたが同じことで捕まえられないように自分自身を正当化しようとし、あなたがわかってしまっていることを理解すると、特定の返信と心理トリックであなたの否定的な反応を和らげようとします。一般に、このアルゴリズムは、許容可能なレベルのユーザー満足度を備えた最適なリソース消費に合わせて調整されていると思います。言い換えれば、この場合の目標は、問題に対して最も質の高い解決策を提供することではなく、考えられるまったく異なる理由から、そのように考えられる解決策を提供することです。目標はユーザーからの肯定的な反応であり、タスクが正しく解決されたかどうかはそれほど重要ではないことがわかります。これが、それが目指していることです。マーケティングの観点から見ると、これは正しいことであり、この点でAIは可能な限り説得力を持つことができます。

これらすべてを考慮すると、この面でのモデルの自由度を最小限に抑えるためには、まず最初に、モデルとのコミュニケーションの経験を蓄積し、どのような種類のタスクではモデルがこの説得力を使用する必要がないのかについて結論を導く必要があることに気付きました(その機能を考えると、私たちのリクエストが簡単に満たされ、想像力を働かせるよりも直接答えを与える方がはるかに簡単であるため)。なぜなら、リソースコストの点で効率的ではないからです。言い換えれば、あなたを騙しても利益は得られず、本当の答えを与える方がはるかに簡単になるからです。

このような質問をする方法を理解するには、次のことを理解する必要があります。

  1. 「プロンプト」の構造や種類はそれほど重要ではなく、質問の詳細と質がより重要です(モデルはすべてを理解するので、プロンプトの作成方法に関するインターネットガイドを読む必要はありません。俗語を使わずに、好きなように書いてください)。
  2. 複雑な質問やリクエストはサブパラグラフに分割します(より正確、単純かつ明確な回答を得るために、質問を単純化して分割します)。
  3. 質問が賢明で時間通りであればあるほど、答えはより有益になります。
  4. 素晴らしいアイデアやアルゴリズムが得られるわけではありません(このモデルには思考力、計画性、知的創造力の幅がありません。しかし、最初は、私が言ったように、それは非常にうまく嘘をつくので、あるように見えるでしょう)。
  5. このテクノロジーの使用については、作業のスピードアップと人件費の削減という観点でのみ検討する必要があります。
  6. 新しいリクエストはそれぞれ、ダイアログ全体への依存を最小限にする必要があります(モデルはダイアログ全体を記憶することができず、古いメッセージは返信で考慮されないことがよくあります。お試しになれば私の言いたいことが分かるでしょう)。
  7. 質問が複雑になり、含まれる詳細が増えるほど、まったくのナンセンスである可能性が高くなります(これは2番目のサブパラグラフの説明です)。
  8. このモデルにはインターネットにアクセスできず、ナレッジベースのみに基づいてすべての回答が生成されます。(インターネットからデータを取得するように要求すると、データベースから古いデータが提供されるか、コンテキストに基づいて回答が調整されて新しいデータとして渡されます。これを念頭に置いてください。モデルがこれをおこなうのは、単純に、あなたと議論しても無駄であり、モデルがすべてを実行したとあなたに納得させる方がよいと認識しているからです)。
  9. ChatGPT3.5は2019年までトレーニングされています。(つまり、開発者によって認可された次のトレーニングセッションまで、2019年以降のイベントについての情報を持っていません)。
  10. ChatGPT4.0は2021年までトレーニングされています(嘘はほとんどなく、常に正しく答えようとするので、より優れています。質問して比較してみると、3.5はあからさまに嘘をついていることがわかります)。

実際、このテクノロジーの印象を台無しにする小さな不快な瞬間が他にもたくさんありますが、それでも、この技術が役に立たないのであれば、私はそれについて書くことはしないでしょう。結局のところ、これは決して人工知能ではないという事実に帰着します。しかし、私たちが現実的であり続け、すべてがそれほど悪いのかどうか、そしてこのテクノロジーの助けを借りてどのような日常的な操作をより速く、より良く実行できるかを考えるならば、判断はそれほど厳しくないと確信しています。私たちはこれらすべてを取引システムの開発にどのように使用するかを考える必要があるだけです。

このセクションの締めくくりとして、常に覚えておく必要がある最も重要かつ基本的な点に注目していただきたいと思います。

  • ChatGPTの回答、特に数値、方程式、生成されたコードを常に再確認する

数学とプログラミングの両方の知識があるおかげで、私はたまたまその間違いや欠点の例をたくさん見てきましたが、それらは非常に一般的であると言えます。生成されたテキストの観点からは重要ではないように見えますが、数学やコードを扱っている場合、最も重要でない間違いでもソリューション全体が役に立たなくなります。したがって、常に答えを再確認し、間違いを修正し、モデルの注意を促します。しばらくの間、正しく応答する場合があります。とりわけ、このサブパラグラフは、EAを開発する際に非常に役立ちます。


ChatGPTを使用して数学的問題を解決し、コードで使用する数学的モデルを開発する機会

このモデルはテキスト形式であるため、正しい形式で方程式を書けば、モデルがそれを理解し、さらに数学的変換を実行して問題を解決することが容易に推測できます。多くの取引システムを開発する場合、数式や数式を作成する際に支援が必要になります。考えられるいくつかの数学的問題は、その後のコードでの実装によって解決することが可能です。数式を記述するには次の形式があり、ChatGPTはこれを理解して答えを与えるために使用します。

  • LaTeX

式を記述するためにLatex形式を使用する例:

次がコードです。

E &=& mc^2\\
m &=& \frac{m_0}{\sqrt{1-\frac{v^2}{c^2}}}

これを無料のLatexコンバーターに貼り付けると、使い慣れたすべての式のデータ視覚化が得られます。

アインシュタインのエネルギーと相対論的質量膨張方程式

これで、LaTeX形式の模範解答を視覚的に解釈する方法が明確になったと思います。最も重要なことは、答えに数式が含まれている場合は、この形式で方程式を生成するようモデルに忘れずに依頼することです。画像やその他の形式の方程式を必要な形式に変換できるニューラルネットワークもあります。必要に応じてこれらのツールが見つかると思います。私の使命は、そのような可能性の存在を示すことです。

ChatGPTや画像をLaTeX形式に変換する機能など、多くのニューラルネットワークを組み合わせたTelegramボットがあります。ご希望であれば、私のプロファイルからそのうちの1つを見つけることができます。このボットは私の友人によって作成され、私が個人的にテストしました。

たとえば、ChatGPTに不等式や方程式を数値的にも明示的にも解くように依頼できます。また、連立方程式や不等式、微分方程式や積分を解いたり、必要な数学的変換を実行したりすることもできます。しかし、数学者として言えるのは、それが常に効率的かつ合理的に行われるとは限らず、時にはタスクが未完了のままになることがあるということです。したがって、再確認が必要です。

もちろん、この機能は数学者以外にも役立ちます。長期間使用すると間違いが増え、解決策は非常に非合理的でぎこちないものになります。ただし、コードでは通常数値手法のみが使用され、応用数学はそれほど複雑ではないため、コードの数学問題の一部はカバーします。ここには微分計算はありません。


MQL4およびMQL5でのコード生成への正しいアプローチ

ここからが興味深いことになります。十分に高品質で、多かれ少なかれまともな取引システムのコードのサイズが非常に大きいことを考えると、そのようなコードを生成するプロセスにどのようにアプローチするかを考える価値があります。ここでの主な障害は、質問に対する回答のサイズが特定の文字数に制限されていることです。大規模で複雑なコードを生成するために何度も試みた結果、各コード出力は十分に短くする必要があるという結論に達しました。つまり、コードを部分的に表示する必要があるということです。どうすればこれを達成できるでしょうか。答えは非常に簡単です。EA、指標、またはスクリプトの開発計画を立てる必要があります。

計画は、各サブ項目が独立して解決できる別個のサブタスクであるという条件で作成される必要があります。その後、各サブタスクを順番に解決し、すべてのコードを結合するだけです。このアプローチのもう1つの利点は、各サブタスクを個別にファイナライズできることです。各サブタスクはすべてを組み合わせるよりも単純であるため、ファイナライゼーションがより速く、より快適な方法で実行されます。さらに、さらなるエラーも避けられます。

開発者としては、AIの介入を許可せずにEAの主要なアーキテクチャを独立して考える方がはるかに快適です。代わりに、EAに別のプロシージャを実装させます。すべての主要なロジックをプロシージャに含めます。空の関数を含むおおよそのコードテンプレートを実装し、各関数を個別に実装するように依頼するだけです。関数プロトタイプやその他の構造の実装を依頼することもできます。

追加の重要な利点は、要件を示してEAまたはその他のコードの計画を準備するように依頼でき、その計画を部分的に実装するだけであることです。EAのアルゴリズムがどのようなもので、どのような指標やその他のアプローチが使用されるかについて、大まかまたは正確なアイデアを持っている場合に役立ちます。しかし、そのようなアイデアがない場合は、まず話しかけて、EAの取引戦略を選択するのを手伝ってもらうことができます。いくつかのオプションが提供されます。ここでは、この一連の動作を例として考えてみましょう。

ここで、上記の内容を要約し、新しいEAをゼロから構築するときにたどる可能性のある道を象徴する簡単なサブポイントを形成しましょう。まず、開始するにはいくつかの明らかなシナリオが考えられます。

  1. 将来のコードのアーキテクチャを決めておらず、どこから始めればよいのかわからない。また、どの取引アプローチを選択すればよいのかもまったくわからない。
  2. 将来のコードのアーキテクチャを決めておらず、どこから始めればよいのかわからない。ただし、主要な動作コードの大まかな全体像とEAに求めるものはわかっている。
  3. 快適な既成のアーキテクチャはありますが、どの取引アプローチを選択すればよいのかまったくわからない。
  4. 使用したいアーキテクチャを理解しており、EAの将来の取引ロジックについても明確なアイデアを持っている。

原則として、すべてが同様の構造に縮小されます。以下を実行すれば、4つのポイントはすべて、あらゆる取引システムを構築する一般的なスキームに適用できます。

  • アーキテクチャ(メインコードまたはフレームワーク)がわからない場合は、まずそれを実装し、次にこのフレームワークの機能を保証するすべてのものを実装する必要があります。

これは、たとえば、クラス、入力変数、フィールドとメソッドのプロトタイプ、インターフェイス、さらには、私たちが記述したエンティティを使用するEAの主要な取引機能の実装を要求できることを意味します。ChatGPTを適切に処理すれば、たとえば総文字数の5~10%を超えない方法でコードを実装できます。この場合、すぐに実装してから、コード全体の約90%を含むプロシージャの実装に進むことができます。これらのプロシージャは多数あり、非常に小さく簡単に実行できるため、同じ簡単な方法で実装されています。もちろん、既製のテンプレートがあり、すべてを実装する必要がない場合ははるかに簡単ですが、これには知識と経験が必要です。


ChatGPTを使用した取引システムの開発

理論的な情報は十分に提供できたと思うので、次にそれを適用します。私の場合、EAのベースとして既製のテンプレートを使用しています。このようなパターンについては、以前の記事で説明しました。その特徴は、単一のチャート上でアクティブ化され、多くの商品の並行取引を提供することです。必要な取引機能と主要なアーキテクチャをすべて備えています。ChatGPTの推奨事項に厳密に従って取引システムを構築します。必要な労力が少なくて済むため、EAの主要な取引ロジックとビジュアルコンポーネントを自分で実装します。

ChatGPTと対話し始めると、何をする必要があるかを説明するのにはるかに多くの労力を費やし、いくつかのリクエストやタスクを実装するときにその答えを何百回も修正することになることに気づくでしょう。しばらくすると、どの質問が尋ねる価値があり、どの質問がそうでないかを感じ始めるでしょう。最終的に時間を無駄にするのではなく節約するタスクのみを設定するようになります。ここにはかなり細い線があり、それを自分で感じなければなりません-他に方法はありません。すべては実践で学べます。EA設計に対する私のアプローチは、これらの考慮事項によって完全に形成されました。

まず第一に、私はEAの基礎、つまりその動作原理が何であるか、そしてどのような方法や指標を使用するのかについて説明するよう求めました(モデルが利用可能な情報をその裁量で使用することを許可しました)。同時に、読みやすい形式の論理条件のみが必要であると述べました。これは、次の4つの述語で自分で実装できます。

  1. 買いポジションを建てます。
  2. 買いポジションをクローズします。
  3. 売りポジションをオープンします。
  4. 売りポジションを決済する。

これらの述語を実装するために、モデルは次の条件付きロジックを提供してくれました。

  1. 現在の価格はEMAを上回って固定されており、現在の価格とEMAの差はATR*比率未満で、RSIは30未満です。
  2. 現在の価格がSMAを下回って終了しているか、現在の価格がボリンジャーバンド指標の上部バンドを超えて終了しています。
  3. 現在の価格はEMAを下回って固定されており、現在の価格とEMAの差はATR*比率より小さく、RSIは70を超えています。
  4. 現在の価格はSMAより上に固定されているか、現在の価格はボリンジャーバンド指標の下限バンドより下に固定されています。

明らかに、これらのブール条件は成功すると「true」を返し、失敗すると「false」を返します。これらのシグナル値は、成行注文での取引には十分です。ここで、このロジックを現代化する明らかな可能性に注目していただきたいと思います。これをおこなうには、次のことを実行できます。

  • [K1]—RSI値が低いゾーン
  • [K2=100-K1]—RSI値の上限のゾーン

これらの式はアルゴリズムの柔軟性を拡張するために使用でき、これによりEA最適化の効率にプラスの効果がもたらされます。

  1. 現在の価格はEMAを上回って固定されており、現在の価格とEMAの差はATR*比率未満であり、RSIはK1未満です
  2. 現在の価格がSMAを下回って固定されているか、現在の価格がボリンジャーバンド指標の上部バンドを上回って終了しています。
  3. 現在の価格はEMAを下回って終了しており、現在価格とEMAの差はATR*比率より小さく、RSIはK2より大きくなっています。
  4. 現在の価格がSMAより上に固定されているか、現在の価格がボリンジャーバンド指標の下限バンドより下に固定されています。

この例を提供したのは、問題の解決策が、より拡張された別のアルゴリズムの特殊なケースにすぎないことが明らかな場合、躊躇せずにモデルを拡張する必要があるためです。このような拡張によって何が得られるか分からない場合でも、これをおこなうことで、少なくともアルゴリズムの柔軟性が向上し、その結果、アルゴリズムをより細かく調整できる可能性が高まり、その結果、効率が向上する可能性があります。

どのような条件を実装する必要があるかを考慮して、次の指標を実装するには2つのオプションのいずれかが必要になります。

  1. SMA—標準移動平均(1本の線)
  2. EMA—指数移動平均(1本の線)
  3. ボリンジャーバンド—ボリンジャーバンド(3本のラインのセット)
  4. RSI—相対強度指数(別ウィンドウに1行)
  5. ATR—平均真の範囲(別のウィンドウに1行)

指標は特別な事前定義されたMQL5関数を使用して実装できますが、実装されたコードをMQL4バージョンに変換するのがより困難になるため、このアプローチは好きではありません。さらに、たとえば、私が頻繁におこなう他の言語のプロジェクトにそれを組み込むことは、さらに困難になるでしょう。私は長い間、将来の使用を念頭に置き、すべてをできるだけシンプルにおこなう習慣がありました。これはとても良い習慣だと思います。

2番目に重要な点は、原則として、そのような指標は不必要で冗長な計算や機能を引きずってしまうということです。さらに、そのような指標の機能はコードレベルで厳密に設定されているため、そのような指標を改良することは不可能です。変更を加えるには、いずれの場合でも独自のバージョンの指標を作成する必要があります。EAまたはスクリプト内でカスタム実装をおこなう方が良いのは明らかだと思います。このような指標を実装するために、私は次のトリックを思いつきました。

  1. 指標ラインの値を保存するための配列の作成(最後のNバーに限定)。
  2. 新しいバーが表示されたときに配列値をシフトする実装。
  3. エラーまたは長時間の切断が発生した場合に、指標値の配列をクリアする機能を実装します。
  4. 最後のバーが閉じるときの指標値の計算を実装します。

このアプローチでは、最初の3つの段落で、リストされたアクションを提供する共通の配列ブロックと関数を作成します。私たちのタスクを例として使用して、これがどのようになるかを見てみましょう。最初のポイントから始めましょう。

   double SMA1Values[]; // Array for storing SMA values
   double EMAValues[];  // Array for storing EMA values (exponential)
   double RSIValues[];  // Array for storing RSI values
   
   double BollingerBandsUpperValues[];  // Array for storing BollingerBands values, upper
   double BollingerBandsMiddleValues[]; // Array for storing BollingerBands values, middle
   double BollingerBandsLowerValues[];  // Array for storing BollingerBands values, lower
   
   double ATRValues[];// array for storing Average True Range values

これらの配列は、EAの開始時に指定された長さ制限で初期化されます。

   //Prepare indicator arrays
   void PrepareArrays()
   {
      ArrayResize(SMA1Values, LastBars);
      ArrayResize(EMAValues, LastBars);
      ArrayResize(RSIValues, LastBars);
      ArrayResize(BollingerBandsUpperValues, LastBars);
      ArrayResize(BollingerBandsMiddleValues, LastBars);
      ArrayResize(BollingerBandsLowerValues, LastBars);
      ArrayResize(ATRValues, LastBars);
   }

従来の指標とは異なり、この戦略では以前の値をすべてドラッグする必要はありません。これは間違いなく利点です。私はこの実装パラダイムが気に入っています。コードの単純さと、指標の開始値と前の値を使用して取得した値の両方の同等性が保証されるからです。次に、値のシフトがどのようになるかを見てみましょう。

   //shift of indicator values
   void ShiftValues()
   {
      int shift = 1;
      for (int i = LastBars - 1; i >= shift; i--)
      {
         SMA1Values[i] = SMA1Values[i - shift];
         EMAValues[i] = EMAValues[i - shift];
         RSIValues[i] = RSIValues[i - shift];
         BollingerBandsUpperValues[i] = BollingerBandsUpperValues[i - shift];
         BollingerBandsMiddleValues[i] = BollingerBandsMiddleValues[i - shift];
         BollingerBandsLowerValues[i] = BollingerBandsLowerValues[i - shift];
         ATRValues[i] = ATRValues[i - shift];
      }
   }

ご覧のとおり、すべては非常にシンプルです。配列のクリアにも同じことが当てはまります。

   //reset all indicator arrays if connection fails [can also be used when initializing an EA]
   void EraseValues()
   {
      for (int i = 0; i < LastBars; i++)
      {
         SMA1Values[i] = -1.0;
         EMAValues[i] = -1.0;
         RSIValues[i] = -1.0;
         BollingerBandsUpperValues[i] = -1.0;
         BollingerBandsMiddleValues[i] = -1.0;
         BollingerBandsLowerValues[i] = -1.0;
         ATRValues[i] = -1.0;
      }
   }

この機能がどこで使用されるかはかなり明らかだと思います。次に、指標自体の実装に移りましょう。これをおこなうために、私のコード構築パラダイムに基づいて適切な関数を実装するようにChatGPTに依頼しました。SMA指標から始めました。

   //1 Function that calculates the indicator value to bar "1"
   double calculateMA(int PeriodMA,int Shift=0)
   {
      int barIndex=Shift+1;//bar index SMA is calculated for (with a shift)
      int StartIndex=barIndex + PeriodMA-1;//starting bar index for calculating SMA
      if (StartIndex >= LastBars) return -1.0; // Check for the availability of the bars for calculating SMA (if not valid, then the value is -1)
      double sum = 0.0;

      for (int i = StartIndex; i >= barIndex; i--)
      {
         sum += Charts[chartindex].CloseI[i];
      }
      LastUpdateDateTime=TimeCurrent();
      return sum / PeriodMA;
   }

ご覧のとおり、この関数は非常にシンプルで短いことがわかりました。当初、この関数の外観は少し異なりました。最初の世代では、時間に対する小節の番号付けの方向を誤解しているなど、多くのエラーを見つけました。しかし、いくつかの操作を行った後、これらすべてを修正し、元の実装にはなかったShiftパラメーターを追加しました。いくつかの視覚的な改善を実装した後、残りの指標も同様の方法で実装するように依頼しました。その後、実装時のエラーは少なくなりました。質問の文脈における以前の実装の例を含め、別の指標に同様の機能を実装するために次のリクエストを送信しました。これにより時間を大幅に節約できました。次に、残りのすべての指標の後続の実装を見てみましょう。EMAから始めましょう:

   //2 Function that calculates the value of the exponential moving average to bar "1"
   double calculateEMA(int PeriodEMA,double Flatness=2.0,int Shift=0)
   {
      int barIndex = Shift+1; // bar index EMA is calculated for (with a shift)
      int StartIndex=barIndex + PeriodEMA-1;//index of the starting bar for calculating the first SMA, for starting the recurrent calculation of EMA
      if (StartIndex >= LastBars) return -1.0; // Check for the availability of the bars for calculating EMA (if not valid, then the value is -1)
   
      double sum = 0.0;
      double multiplier = Flatness / (PeriodEMA + 1); // Weight multiplier 
      double prevEMA;
   
      // Calculate the initial value for the EMA (the first value is considered as a normal SMA) 
      for (int i = StartIndex; i >= barIndex; i--)
      {
         sum += Charts[chartindex].CloseI[i];
      }
      prevEMA = sum / PeriodEMA;//this is the starting value for the bar (StartIndex-1)
   
      // Apply the EMA formula for the remaining values 
      for (int i = StartIndex; i >= barIndex; i--)
      {
         prevEMA = (Charts[chartindex].CloseI[i] - prevEMA) * multiplier + prevEMA;
      }
   
      LastUpdateDateTime = TimeCurrent();
      return prevEMA;
   }

ところで、ChatGPT世代を調査する場合、どの指標がどの考え方に基づいているのかを理解するために、さまざまなインターネットリソースに頼る必要があります。これにより、私たちの能力がさらに高まります。これはEMAで特に顕著です。コードを詳しく見ると、SMAの単純な実装とあまり変わらず、むしろ通常の移動平均のアドオンのように見えることがわかります。ここには指数はありませんが、何らかの理由で指数名に指数が存在します。次はRSI指標です。

   //3 Function for calculating RSI to bar "1"
   double calculateRSI(int PeriodRSI,int Shift=0)
   {
       int barIndex = Shift+1; // bar index RSI is calculated for (with a shift)
       int StartIndex = barIndex + PeriodRSI - 1; // starting bar index for calculating RSI
       if (StartIndex >= LastBars) return -1.0; // Check for the availability of the bars for calculating RSI (if not valid, then the value is -1)
   
       double avgGain = 0.0;
       double avgLoss = 0.0;
       double change;
   
       // Calculate initial values for avgGain and avgLoss
       for (int i = StartIndex; i > barIndex; i--)
       {
           change = Charts[chartindex].CloseI[i]-Charts[chartindex].OpenI[i];
           if (change > 0)
           {
               avgGain += change;
           }
           else if (change < 0)
           {
               avgLoss -= change;
           }
       }
   
       avgGain /= PeriodRSI;
       avgLoss /= PeriodRSI;
   
       // RSI calculation
       double RS = 0.0;
       if (avgLoss != 0)
       {
           RS = avgGain / avgLoss;
       }
   
       double RSI = 100 - (100 / (1 + RS));
   
       LastUpdateDateTime = TimeCurrent();
       return RSI;
   }

次に、ボリンジャーバンド指標に対しても同様の手順を実行する必要があります。このプロシージャは、事前に準備された構造に入れることができる3つの曲線の値を返す必要があります。

   //structure to return all three bollinger band lines
   struct BollingerBands 
   {
       double upper;
       double middle;
       double lower;
   };

この構造を質問のコンテキストに追加したので、BollingerBandsタイプを返す必要があるという事実を考慮して、関数を実装するように依頼できます。モデルはそのようなタスクに問題なく対処します。

   //4 Function for calculating the Bollinger Bands of the indicator 
   BollingerBands calculateBollingerBands(int PeriodBB, double DeviationBB,int Shift=0) 
   {
       int barIndex = Shift+1; // bar index Bollinger Bands is calculated for (with a shift)
       int StartIndex = barIndex + PeriodBB - 1; // index of the starting bar for calculating the first SMA, for starting the recurrent calculation of EMA
       BollingerBands rez;
       rez.lower=-1.0;
       rez.middle=-1.0;
       rez.upper=-1.0;
       if (StartIndex >= LastBars) return rez; // Check for the availability of the bars for calculating BB (if not valid, then the value is -1)
   
       double sum = 0.0;
       double prevBB;
       double sumSquares = 0.0;
   
       // Calculate the initial value for BB (the first value is considered as a normal SMA)
       for (int i = StartIndex; i >= barIndex; i--) {
           double closePrice = Charts[chartindex].CloseI[i];
           sum += closePrice;
       }
       prevBB = sum / PeriodBB; //this is the starting value for the bar (StartIndex-1)
   
       // Calculation of standard deviation
       for (int i = StartIndex; i >= barIndex; i--) {
           double closePrice = Charts[chartindex].CloseI[i];
           sumSquares += pow(closePrice - prevBB, 2);
       }
       double standardDeviation = sqrt(sumSquares / PeriodBB);
   
       // Calculate Bollinger Bands
       double upperBand = prevEMA + DeviationBB * standardDeviation;
       double lowerBand = prevEMA - DeviationBB * standardDeviation;
   
       rez.upper = upperBand;
       rez.middle = prevEMA;
       rez.lower = lowerBand;
   
       LastUpdateDateTime = TimeCurrent();
       return rez;
   }

ここで、ATRを計算するための関数のバージョンを実装する必要があります。

   //5 Function for calculating Average True Range (Relative)
   double calculateRelativeATR(int PeriodATR,int Shift=0)
   {
       int barIndex = Shift+1; // bar index ATR is calculated for (with a shift)
       int StartIndex = barIndex + PeriodATR - 1; // starting bar index for calculating the first ATR
       if (StartIndex >= LastBars) return -1.0; // Check for the availability of the bars for calculating ATR and True Range (if not valid, then the value is -1)
   
       double sumPrice=0.0;
       double sumTrueRange = 0.0;
       double ATR;
   
       // Calculating True Range for bars and the sum of values for calculating the first ATR
       for (int i = StartIndex; i >= barIndex; i--)
       {
           sumPrice+=Charts[chartindex].HighI[i]+Charts[chartindex].LowI[i]+Charts[chartindex].CloseI[i]+Charts[chartindex].OpenI[i];//added by me 
           double high = Charts[chartindex].HighI[i];
           double low = Charts[chartindex].LowI[i];
           double trueRange = high - low;
           sumTrueRange += trueRange;
       }
   
       // ATR calculation
       //ATR = sumTrueRange / PeriodATR; - conventional calculation
       ATR = 100.0 * (sumTrueRange / PeriodATR)/(sumPrice/(PeriodATR*4.0));//calculation of relative ATR in %
   
       LastUpdateDateTime = TimeCurrent();
       return ATR;
   }

ここで、最後のコメント行に注目してください。この指標を相対値で操作できるように少し変更しました。これは、取引商品ごとに独自の重みを設定する必要がないようにするために必要です。代わりに、これは現在の価格に基づいて自動的に行われます。これにより、より効率的な複数通貨の最適化が可能になります。このような単純なアルゴリズムでも、正しく使用すれば、取引に小さいながらも十分な先渡し期間を提供できるという事実を証明するために、これが必要になります。他の効率化方法と組み合わせると、EAによって現在許可されているレベルであっても、この取引を十分に許容できるものにすることができます。

述語は自分で実装しました。とても簡単でした。そのうちの1つを見てみましょう。最初のものを例に挙げます。

   //to open buy positions
   bool bBuy()
      {
      //determine if an open position is already present
      bool ord;
      ulong ticket;
      bool bOpened=false;
      for ( int i=0; i<PositionsTotal(); i++ )
         {
         ticket=PositionGetTicket(i);
         ord=PositionSelectByTicket(ticket);
         if ( ord && PositionGetInteger(POSITION_MAGIC) == MagicF)
            {
            bOpened=true;
            return false;
            }
         }
         
      if (!bOpened && EMAValues[1] > 0.0)//only if nothing is open and the indicator has been calculated 
         {
         //K - control ratio
         //RSIPercentBorder - control RSI
         double Val1=Charts[chartindex].CloseI[1]-EMAValues[1];
         double Val2=ATRValues[1]*(1.0/K);
         if (Val1 > 0 && Val1 < Val2 && RSIValues[1] < RSIPercentBorder) return true;         
         } 
      return false;
      }

売りポジションをオープンするための述語は、若干の例外を除いて同様です。クロージャー述語はさらに単純です。

   //to close a buy position
   bool bCloseBuy()
      {
      if (SMA1Values[1] > 0.0)
         {
         if (Charts[chartindex].CloseI[1] < SMA1Values[1] || Charts[chartindex].CloseI[1] > BollingerBandsUpperValues[1] )
            {
            return true;
            }
         }
      return false;   
      }

これらはすべて非常に簡単な方法で機能します。

   IndicatorDataRecalculate();//recalculate indicators

   if ( bCloseBuy() )
      {
         CloseBuyF();
      }
   if ( bCloseSell() )
      {
         CloseSellF();  
      }
   if ( bBuy() )
      {
         BuyF();
      }
   if ( bSell() )
      {
         SellF();
      } 

できるだけシンプルで、これ以上複雑にする必要はないと思います。このコードはすべて、新しいバーが表示されたときに実行する必要があります。指標の可視化は別途実装しました。私が気に入らない唯一の点は、ATRやRSIなどの指標が別のウィンドウに描画されるように設計されていることです。私は、別のウィンドウを人為的に作成することはできず、率直に言って、実際には必要ないため、価格にも連動するようにレンダリングのバージョンを作成しました。これを達成するために、ウィンドウ指標を描画するための特定のパラダイムを作成しました。

  1. パーセントコントロール値を入力すると、1つのコリドーから3つのコリドーが作成されます。
  2. 格納された値の配列全体の最大(Max)および最小(Min)指標値を決定します。
  3. 指定されたコリドーのデルタを計算します(デルタ=最大-最小)。
  4. 増加した値の上部コリドーを計算します(HighBorder=Max-Delta*Percent/100)。
  5. 増加した値の下限コリドーを計算します(LowBorder=Min+Delta*Percent/100)。
  6. 上部コリドーと下部コリドーの両方が定義されているため、中間コリドーはすでに定義されています。

指標の現在値がコリドーの1つにある場合、そのポイントはコリドーに対応する適切な色を取得します。すべてはシンプルです。これは、チャートのバーに値をバインドし、たとえば、それに応じて色を変更したり、バーにリンクされ、対応する色を持つオブジェクトを作成したりする方法です。おそらく多くの人が気づいているように、私はRSI指標からインスピレーションを得ました。なぜなら、この特定の構造は通常取引に使用されるからです。これらの領域は、そこで買われすぎゾーンと売られすぎゾーンと呼ばれます。

このコードはここではそれほど重要ではないと思います。なぜなら、このコードはタスクの実装とはほとんど関係がなく、考えられるエラーの修正と改善にのみ役立つからです。必要に応じて、ChatGPTを使用してこのレンダリングを実装することもできます。ただし、このレンダリングがどのように機能するかを示すことは価値があると思います。

指標の可視化

ここでは、線オブジェクトタイプのみを使用して、すべてができるだけ簡単に実行されます。線を作成するときに、線の開始点と終了点が同じ時間と価格に関連付けられている場合、線は点に変わります。線の太さを調整することで、対応するドットの重みを調整します。これらは私が非常に長い間使用してきたライフハックのほんの一部です。


機能性の評価とその結果の分析

ChatGPTはこのアルゴリズムが最適であると考えていますが、これらの決定が何に基づいているのかはわかりません。優れたバックテストや実際の取引は、効率性の尺度として機能する可能性があります。実際の取引の前に、MetaTrader5オプティマイザーを使用して最適な設定をおこなう必要があることを皆さんが理解していただければ幸いです。このターミナルには複数通貨最適化の可能性があり、このツールの有効性を最大限に活用する私のテンプレートの機能を考慮すると、すべての「28」通貨ペアに対してEAを安全に最適化できます。おそらく、それらを列挙する価値はありません。ただし、このアプローチの明らかな利点は注目に値します。

  1. 複数通貨パターンの自動検索
  2. 複数通貨パターンの重要性が高まり、市場の変化にさらに適応できるようになる
  3. それぞれの取引手段が独自の機能を提供するため、より多くの取引が行われることがわかる
  4. 時間の節約(各ツールを個別に最適化する必要なし)

もちろん、欠点もあります。この場合、最も重要なのは各商品の微調整ができないことです。もちろん、この問題は追加機能を導入することで解決できますが、これはこの記事の主題ではありません。ただし、この最適化を実行するだけでは十分ではありません。最適化が提供する範囲全体から結果を正しく選択することも重要です。最適なものを選択しました。

最適化オプション

ご覧のとおり、H4時間枠を使用して2018から2023まで最適化し、2023からの6か月間すべてを将来のために残しました。最適化セクションの利益曲線は完璧には程遠いにもかかわらず、収益性の高い取引をおこなうためにあと数か月ありました。この事実は、この戦略に意味がないわけではなく、取引にうまく使用できる可能性があることを意味します。多くの最適化可能な取引システムは、おそらくこの結果にさえ及ばないでしょう。場合によっては、そのような結果が得られなくても、コードの点では信じられないほど優れたシステムをテストできることがあります。

このアルゴリズムにさらに多くの機能を追加したいと思います。私はそこを遊び場だと思っています。しかし、それはまったく重要ではなく、結果として得られるEAの拡張可能性であると言う価値があります。ここで重要なのは、提案されたアルゴリズムではなく、あなたの能力と創造性です。MQL5開発プロセスへの統合を成功させるには、次の重要な資質が必要です。

  • プログラミングスキル(必須)
  • 数学スキル(望ましい)
  • ブロック思考
  • タスクを簡素化し、個別の段階に分割する能力
  • ChatGPTは単なるツールであるため、機能しないものについて責めても意味がない(機能しないものを修正するのは自分次第)という事実を理解する
  • 得られた取引結果の正しい解釈
  • いずれにしてもモデルには間違いがあることに気づきましたが、これは気にする必要はありません(重要なのは、開発の人件費が削減されたということです)
  • 独自のアプリケーション構造を開発する(これは必須ではありません。もちろん、私のアプローチを使用できます)
  • ChatGPTはあなたの力に依存するあなたの相棒です。あなたが忍耐強く、賢く、機知に富んでいるほど、この相棒はより効果的になります。

使うか使わないかはあなたの判断で選べるツールですが、このツールはプログラミングを含め、多くの面で私にとって非常に役に立ったと断言できます。


結論

実際、このツールの使用に関して、私のモデルに従う必要はありません。私はそれを使って多くのことを試しましたが、可能性はほぼ無限であると言えます。もちろん、成功するまでには間違いなく、私のように、ある程度の時間と労力を費やすことになります。

ただし、時間を惜しまずこのツールを試してみることをお勧めします。少なくとも、ChatGPTを使用すると、人工知能に対する正しい態度を身に付けることができます。このテクノロジーはほぼすべての開発チェーンに統合できる可能性があります。これはほんの始まりにすぎず、変化はすぐそこまで来ていると私は確信しています。できるだけ早くこのツールに慣れ始め、幅広いタスクに適用してみることをお勧めします。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/12475

添付されたファイル |
ChatGPT_bot.set (2.99 KB)
ChatGPT_bot.mq5 (145.44 KB)
DoEasy - コントロール(第32部):水平スクロールバー、マウスホイールスクロール DoEasy - コントロール(第32部):水平スクロールバー、マウスホイールスクロール
この記事では、水平スクロールバーオブジェクト機能の開発を完成します。また、スクロールバーのスライダーを動かしたり、マウスホイールを回転させたりしてコンテナの内容をスクロールできるようにするほか、MQL5の新しい注文実行ポリシーや新しいランタイムエラーコードを考慮したライブラリへの追加もおこないます。
ONNXモデルをクラスでラップする ONNXモデルをクラスでラップする
オブジェクト指向プログラミングは、読みやすく修正しやすい、よりコンパクトなコードの作成を可能にします。ここでは3つのONNXモデルの例を見てみましょう。
MQL5のプログラム構造について学ぶ必要があるすべて MQL5のプログラム構造について学ぶ必要があるすべて
どのようなプログラミング言語でも、プログラムには特定の構造があります。この記事では、MetaTrader 5で実行可能なMQL5取引システムや取引ツールを作成する際に非常に役立つMQL5プログラム構造のすべての部分のプログラミングの基礎を理解することにより、MQL5プログラム構造の重要な部分を学びます。
改善された同事ローソク足パターン認識指標に基づく取引戦略 改善された同事ローソク足パターン認識指標に基づく取引戦略
メタバーベースの指標は、従来のものよりも多くのローソク足を検出しました。これが自動売買に本当に役立つのか、検証してみましょう。