English Русский 中文 Español Deutsch Português Türkçe
取引システムの開発と分析への最適なアプローチ

取引システムの開発と分析への最適なアプローチ

MetaTrader 5トレーディングシステム | 21 1月 2021, 13:30
842 0
Evgeniy Ilin
Evgeniy Ilin

はじめに

現在、外国為替取引の人気はますます高まっており、新しいシグナルと取引システムが絶えず出現しています。早く簡単にお金を稼ぎたいという人はいつもたくさんいるので、これは避けられません。世界中のインターネットインフラストラクチャの拡大に伴い、この市場はますます大きくなっています。このWebサイトはこれの実例です。これには、ユーザーが製品やサービスを購入したり、Webサイトの開発に貢献してお金を稼いだりできるようにする、多数の機能を備えた最も開発されたエコシステムが含まれています。本稿では、製品やシグナルを選択する際に使用するべき基準と、独自の取引システムを開発および適用する際に従うべきルールに焦点を当てます。

私の哲学

私の動機と取引システムを構築するための私のアプローチの原則について少しお話ししましょう。MetaTrader 5に慣れるべき時ですが、私は主にMetaTrader 4で複数の異なるEAを開発しました。その後、一部のシステムはMetaTrader 5に適合されました。

機能面では、MetaTrader 5はもちろんその前身をはるかに超越しています。市場を理解するためには、まず理論と実践を組み合わせる必要があると思います。MetaTrader 4は必要な練習を十分に提供します。

できるだけ簡潔かつ迅速に開発し、その結果を見ていきます。結果がパターンに似ている場合は、フィルタを追加し、シグナル強度を上げて、結果を再確認します。改善されている場合は、プロセスを掘り下げて、改善または劣化の背後にある理由を見つけようとします。

その上、ある種の組立ラインを配置するために、異なると同時に単純なシステムを開発する必要があります。単一のシステムを完璧にするために何ヶ月もいじくり回せば、確実に失敗につながります。また、一部のトレーダーは、入力が多ければ多いほどそしてその他が複雑であればあるほどシステムは勝るものだと考えますが、実際には、その逆が当てはまります。

私が開発したEAの中には、2000〜3000行のコードを含みながら結果が得られないものもありますが、20〜50行で構成されるコードには、複数の通貨にわたる履歴全体で機能するものもあります。ここでの主な成功要因は、市場に関する知識です。才能あるプログラマーとは、想像できる最も複雑なシステムを開発できる人ではなく、その目的を理解し、実際にシステムに何を追加する必要があるかを知っている人です。

このアプローチのもう1つの利点は、出力システムが単純であるほど、修正と変更が容易になることです。もう1つの興味深い機能は、開発したEAが最終的には完全に異なるロジックに従っており、理解するのに何年もかかる可能性があるということです。

次のレベルの知識では、市場を理解し始め、開発するほとんどすべてのロボットは、可能な限り収益性と安定性を保ちながら、可能な限り簡潔になります。私は現在まさにこのレベルで、何が機能し、何が機能しないか、そして対処すべき重要な問題は何かを知っています。このレベルに達すると、ローソク足のパターンや指標など、取引コミュニティで流通している情報の99%が完全にナンセンスであることがわかります。トレンドやフラットなどの他の情報は比較的信頼できるように見えるかもしれませんが、秘訣はさまざまな方法で解釈できるという事実にあります。したがって、負けた場合、取引の「専門家」は常に、何かを見逃したかトレンドラインが正しく設定されていないと言うことができます。

時間を無駄にするかわりに、実際に何が価格を左右するかを考え始めるべきです。もう1つの必要な前提条件は、数学の知識と、結果を分析し、合理的な規則性を検出し、その背後にある物理学を理解するときにそれを適用する能力です。これはすべて、理論と実践を組み合わせることによってのみ達成できます。結局、それはすべて開発してテストした取引システムの数に依存します。他人のコードを使用せずに、最初から独自のコードを作成してください。また、すぐに聖杯を見つけることができるとは思わないでください。数年は見つけられると思いました。考えることは知っていることではありません。


シグナル、EA、インディケーター

これらのツールはすべて、外国為替トレーダーとサブスクライバーを支援するように設計されており、正しく使用すれば、それぞれが有益になる可能性があります。この点で、全体として正しいビジョンを形成するためには、これらのツールのそれぞれを個別に正しく理解することが非常に重要であると私は信じています。最も重要なことは、サービスというのはツールを提供することだけを目的としており、ソリューションを提供することを目的とはしていないということを理解することです。値札の背後に実際に何があるのかを理解することは非常に重要です。個人的に、私はこれらの問題について長い間理解を深めてきており、それが誰かの役に立つかもしれないと信じています。もう1つの理由は、カスタム取引システムの開発についての私の考えを共有したいということです。

シグナル

シグナルは実際の口座とデモ口座で取引されます。シグナルを使用すると、自分の取引口座と他のトレーダーの口座を監視したり、シグナルをサブスクライブしたり、他のトレーダーの取引をコピーしたりできます。 個人的には、平均ポジション保持時間が1分未満のシグナルをサブスクライブすることはお勧めしません。事実、そのような短期間の取引は裁定取引またはスカルパーのいずれかです。どちらの場合も、そのような戦略はpingに非常に敏感であり、ポジションが間違った方法で開くには10ミリ秒でも十分な場合があります。 平均取引期間が長いほど、元の取引との違いは少なくなります。

以下に悪いシグナルと良いシグナルの例を示します。

安全なシグナル:


エクイティラインが可能な限り残高ラインに近いため、安全です。つまり、長期の取引がなく、ポジションが順番に開閉され、マーチンゲールとグリッドがありません。シグナルが安定していることは明らかです。それは直線に非常に似ており、預金への負荷が比較的小さく、収益性の高い取引の割合が高いという特徴があります。

次のシグナル:


このシグナルも非常に良好ですが、大きな緑色の下向きのピークは、システムが積極的にマーチンゲールを適用していることを示しています。テストの始まりには、獲得した利益全体を破壊する可能性のあるいくつかのピークがあります。これがまた起こらないという保証はありません。預金全体が吹き飛ばされることになる場合があります。それにもかかわらず、「マーケット」には非常に多くのシグナルの選択肢があり、非常に優れた標本を見つけることができます。

エキスパートアドバイザー

販売することで開発者が使用する以上のことがもたらされることを考慮せずに、安定した収益性の高いEAがマーケットに公開されることはありません。別の可能なオプションは、開発者がシステムに確信がなく、多額の投資をするリスクを冒したくないということです。代わりに、リスクを削減するらめに少額で取引します。EAを購入した元をとるには、多額の預金が必要になります。たとえば、EAを200ドルの費用でレンタルして最初の100ドルから200ドルを得た場合、EAが稼働し続けても何も得られません。

予測利益は、EAの値段の少なくとも数倍高くなければなりません。さらに、EAのパフォーマンスが必要な期間にわたって収益性を維持することは誰も保証できないことに留意してください。多通貨の性質は、EAの追加の利点として機能します。少なくともいくつかの通貨ペアで機能する場合、それは市場物理学を適用し、利益の可能性を大幅に高めます。例として、最近のシステムのパフォーマンスと結果の1つを実際のテストの形式で表に示します。

まず、主要通貨ペアの過去10年間の履歴に関する一般的なEAテスト表を示します。


これらの結果はすべて、特定の通貨ペアの調整や最適化を行わずに、単一のセットファイルを使用することで達成されました。

以下は、表に示されているオプションの1つです。


このオプションは、これが単なる乱数表ではないことを確認します。さらに、これは自動取引システムを使用して達成できる結果を示しています。そのようなEAを市場で見つけるのは非常に難しいので、私は自分の結果を示すことにしました。このEAは私の製品にはまだ存在しません。1の固定ロットが取引に使用されました。

インディケータ―

インディケータ―に対する私の態度はほとんど否定的です。インディケータ―は手動取引に適していると思います。コードに統合することは可能ですが、非常に低速で動作し、一般に、わずかに変更された価格を表します。インディケーターが相場ウィンドウに描画される場合、これは自然なことです。別ウィンドウのインディケーターについては、ほとんどの場合、関数を計算するか、繰り返し計算を実行します。つまり、次の値は前の値から計算されます。どちらの場合も、これらのツールの効率は大幅に制限されます。

インディケーターの交差の形をとるシグナルを決して当てにしてはいけません。これは単なる心理的な瞬間であり、それ以上のものではありません。最も有用な指標は、市場の形状(パターン)を検出する指標だと思います。 それらは健全なシグナルを持っている必要があります。 とにかく、トレーダーは常にパターンに従うかどうかについて最終決定を下す必要があります。

エントリポイントを正しく検出するインディケーターを開発することができれば、それに基づくEAはずっと前に作成されていたでしょう。 私がテストしたすべてのインディケーター(自分で開発したものを含む)は、エントリポイントを示しません。エントリポイントに基づくEAは役に立たないことが判明しました。 エントリポイントは主に明確化のための補助ツールとして、そして正直言って、トレーダーの心を落ち着かせるために役立ちます。 トレーダーは、エントリとエグジットの両方について確信を持ち続けたいと考えます。

以下は私のインディケータ―の例です。


このインディケータ―は、非標準的なアプローチを示しています。単純な数学関数を定義し、チャート上でそれらを探し、検出された場合に通知します。 繰り返しますが、このインディケーターは時間を節約するために設計されたツールにすぎません。これらの指標は手動取引で役立ちますが、最終的な決定は常にあなた次第です。

投資と取引の追加機能についての短いツアーの後、より深い理解のために数学の観点からテストと開発を見てみましょう。

最適検索の背後にある数学

開発の最終的な目標が要件を満たすn個のシステムを取得することである場合、最初の質問は、作業の効率を最大化するためにシステムをどの程度複雑にする必要があるかということです。 ここで、効率とは、最初のプロトタイプが私が定義したプロトタイプの基準内に入る確率です。言い換えれば、プロトタイプは、特定のペアまたは複数のペアで作業しているときに、初期段階ですでに特定のパラメータを提供する必要があります。 個人的には、私は常に多通貨の性質を必須の基準と考えています。結果として、それはすべてある種の依存関係に要約されます。これは確実に決定することはできませんが、実験を通じて大まかに調べることができます。

  • Ps=Ps(L)

ここで、Lは作業コード文字列の数です。 言い換えると、作成されたシステムの最初のパラメータが許容範囲内にある確率は、作成するコードの量に直接依存します。システムの文字列が多いほど良いと思うかもしれませんが、常にそうであるとは限りません。 以下を念頭に置いてください。

  • T=K*L

文字列が多いほど、開発を完了するのに時間がかかります。しかし、私たちの最優先事項は、コード文字列の数ではなく、それらの効率と、単位時間内に開発できる作業システムの数です。このパラメータは、残りのすべてのパラメータに影響します。

  • E= Ps/T
  • E --> Max

言い換えれば、Eパラメータを可能な限り最大化する必要があります。主な2つの方法は、市場知識の質を向上させ、最適なプロトタイプコードサイズを見つけることです。プロトタイプのサイズを定義するだけでなく、市場の知識とそれを適用する能力は、特定のE0を提供します。それは効率の指標として使用することができます。また、1つのシステムの開発にかかる平均時間を取得します。

開発の後には常にテストと変更が続きます。これらのプロセスにも独自の確率があります。私たちの場合、それは成功した修正+最適化の確率です。一方は他方から切り離せません。テストせずに修正や変更を行うことは不可能です。結果として、それはすべて「テスト-分析-変更」のいくつかの繰り返しサイクルに帰着します。その結果、システムを破棄するか、システムを改善して、適用や販売のために保管します。

また、開発と初期テストへのアプローチを最適化しても、そのようなシステムが1つは見つかるとは限らないことに注意してください。信頼できるのは、目的の結果が得られる最大のチャンスだけです。開発と初期テストにどれだけの時間がかかるかを知る必要があります。ベルヌーイの方程式を使用すると、次のように書くことができます。 

  • Pa=Sum(m0...m...n)[C(n,m)*Pow(Ps ,m)*Pow(1-Ps ,n-m)]
  • m0 - 満足のいくプロトタイプの最小数
  • Pa — 「n」個の開発サイクルから少なくとも「m0」以上を取得する確率
  • n — 動作するプロトタイプを検索するために利用可能な最大サイクル数

満足のいくプロトタイプの数が必要以上に多いことが判明したオプションにも満足しているので、式の合計を使用します。後で提供する方程式は、同じ考え方を適用します。

ここで自分能力を過大評価しないように注意してください。また、多くの優れたプロトタイプを期待しないでください。それらを見つけたとしても、誰もそれらがあなたが望むように働くことを保証することはできません。多くの単純なプロトタイプを頼りにすることも、より複雑なプロトタイプを頼りにすることもできます。選択はあなた次第です。私は単純なものに頼っています。

変更およびテスト中に、最大化できるパラメータと最大化する必要のあるパラメータもあります。まず、テストスキームで受け入れ可能なオプションを見つける確率から始めます。最初に選択されたプロトタイプから許容可能な結果を見つけるプロセス全体は、最終的に単一のテスト-変更-最適化プロセスに統合されます。 これは、ベルヌーイの式を使用して説明できるバッチプロセスです。

  • Pf= Sum(1...m...n)[C(n,m)*Pow(Po,m)*Pow(1-Po,n-m)]
  • Po — 反復中に許容可能な結果が得られる確率
  • n — 利用可能な最大検索サイクル数

許容できる結果を探すには、少なくとも1つの満足のいくイベントが必要だと思います。言い換えれば、テストと改訂には一定の時間があり、最終的には、プロトタイプで最初の結果よりも多くのものを見つけるために利用可能な反復(テストまたは変更)の数に変換され、この結果は私たちに合うはずです 。時間の合理的な使用がより重要であるため、Pfの取得は必須ではありません。

  • Ef= Pf/m
  • Ef--> Max

現段階では、編集とテストの残高を維持し、特定のパラメータが最終結果にどのように影響するか、さらにテストすることに意味があるかどうかを定義することが重要です。テストと改善には常にほぼ同じ時間がかかるため、「m」は直感や経験を使用して独自に定義する必要のあるテストの数です。ここには特定のガイドラインや推奨事項はありません。もちろん、「n」サイクルを実行して結果を確認する標準アルゴリズムに従うことは可能ですが、多くの場合、反復回数を減らして、たとえば初期段階でシステムを破棄したり、または逆に、効率的で柔軟性があると判断したりすることができます。時間を節約できるので、私は常にこの特定のアプローチに固執しようとします。時間は私たちが持っている最も貴重なものです。以前の調査結果に基づいて、平均して完全な「n」テストではなく「m」テストを使用することを考慮して、開発効率のより完全で一般的な測定値を作成できます。

  • ET= ( Ps*Pf)/(TSumm)
  • TSumm = T + m*Tm
  • Tm — 平均サイクル時間(testing-modification-optimization)

Pf確率とPs確率のイベントには一貫性がないため、新しいイベントがプロトタイプを見つけている新しいイベントスペースを比較する権利があります。比較の後には、基本的に許容可能な取引システムが見つかったことを意味する改善が成功します。したがって、確率を乗算して、特定のイベントの確率を取得します。

ただし、検出されたすべてのオプションには、「T」プロトタイプの開発時間と「m*Tm」の改善時間が必要であることもわかっています。1つの完全な開発サイクルに関連する成功の可能性が高いほど、アプローチはより効果的です。多くの点で、最終時間はテスト時間に依存します。当初はティックベースのロボットを作りましたが、バーベースのプロトタイプを開発することをお勧めします。まず、テストを数回高速化します。次に、ティックから離れて、実際のティックを使用したテストで時間を無駄にすることなく、開発を大幅に加速します。次に、最も重要な戦略基準を分析します。

主な戦略パラメータ

特定のパラメータを反映して戦略の品質を評価するための特定の定量値があります。一部の値は他の値よりも重要ですが、一般的に、それらは戦略についてすべてを語ることができます。次の定量的戦略パラメータがあります。

  • ペイオフの期待値
  • 利益率
  • 絶対ドローダウン
  • 相対ドローダウン
  • 最大ドローダウン
  • 回復率
  • 収益性の高い取引の割合

ペイオフの期待値

ペイオフの期待値は、EAまたは手動取引システムの最も重要なパラメータです。まともなペイオフの期待値を持っていないならば、純粋に運が良い場合を除いて成功するチャンスがありません。ペイオフの期待値には、ポイント単位と預金通貨単位の2種類あります。

  • M_Points=( Sum(1,n)(PrPoints[i]) - Sum(1,n)(LsPoints[i]) )/n
  • M=( Sum(1,n)(Pr[i]) - Sum(1,n)(Ls[i]) )/n

ここで

  • PrPoints[i] — i番目の取引が利益を生む場合、これはポイント単位の利益額です
  • LsPoints[i] — i番目の取引が損失を生む場合、これはポイント単位の損失額です
  • Pr[i] — i番目の取引が利益を生む場合、これは預金通貨単位の利益額です
  • Ls[i] — i番目の取引が損失を生む場合、これは預金通貨単位の損失額です
  • n — 取引数

ここで説明するすべての値は、100%の精度で戦略を特徴付けるものではありません。正確に決定するには、nが無限大になる傾向がある必要があるためです。しかし、適度な取引量の場合でも、これらすべての値は、非常に高い信頼性で戦略について多くのことを教えてくれます。

戦略の収益性を確保するには、値がゼロを超える必要があります。同時に、利益の一部はスプレッド、手数料、スワップによって減少することを覚えておく必要があります。

  • PrPoints[i]=PrPoints_0[i] - (SpreadOpen[i]/2 + SpreadClose[i]/2) - (OrderComission[i]/OrderLots[i])/TickValue + (OrderSwap[i]/OrderLots[i])/TickValue
  • Pr[i]=Pr_0[i] - (SpreadOpen[i]/2 + SpreadClose[i]/2)*OrderLots[i])*TickValue - OrderComission[i] + OrderSwap[i]

ここではTickValueへの特別な言及が必要です。これは、1ロットを使用する場合の預金の1ポイントの価格です。この値はすべての通貨ペアで異なり、最小価格変更で整数TickValueが生成されるように設定されています。実際、スプレッドは本質的に証券会社に送られるペイオフの期待値の一部であるため、これは戦略の最も重要なパラメータです。したがって、それに最大限の注意を払う必要があります。ペイオフの期待値がスプレッドをわずかに超えるだけの場合、他のすべての戦略パラメータは重要ではありません。

利益率

利益率は、戦略の2番目に重要なパラメータです。良好なペイオフの期待値が得られた場合、これはシグナルの品質、つまり予測品質を反映するため、次に注目すべきパラメータです。取引からの利益の合計額が大きく、損失の合計が小さいほど、パラメータ値は大きくなります。

  • PrFactor = Sum(1,n)(Pr[i]) / Sum(1,n)(Ls[i])

ご覧のとおり、方程式の分母がゼロになると、利益係数を計算できません。または、正式には、これが引数の正の部分から分母がゼロになる傾向がある場合の限界であると見なすことができます。制限は正の無限大です。これは、このインディケーターは、不採算の取引がない場合無限大に変わり、収益性のある取引がない場合は0に変わることを意味します。したがって、値の範囲は[0、+無限大]です。平均値は1です。それを超えるものはすべて利益を生み、それ以下のものはすべて赤字です。

次の2つのパラメータは同じことを反映していますが、方法が少し異なります。

最大ドローダウン

最大ドローダウンは、高値が最初に来ると仮定した場合、2つの隣接する株式の高値と安値の間の最大差です。ピーク配列価格をPriceExtremum[i]として設定すると、最大ドローダウンは次のようになります。

  • MaximumDrawdown = MaxOf( PriceExtremum[i+1]- PriceExtremum[i] )

最終利益が同じである戦略が2つ以上ある場合は、最大ドローダウンが最も少ない戦略を選択してください。次のパラメータは、この仮定をする必要bなしでこれを反映しています。

回復率

このパラメータは、利益が次の式に含まれることを除いて、前のパラメータとほぼ同じです。

  • RecoveryFactor = TotalProfit/MaximumDrawdown

このパラメータの方が有益だと思います。回復率が高いほど、戦略はより安定します。たとえば、このパラメータが大きいほど、損失のシーケンスが小さくなり、損失の場合に預金を失うことを恐れずにロットを増やし始めることができるため、戦略はマーチンゲールを使用するのにより適するようになります。

収益性の高い取引の割合

このパラメータは、平均的な収益性の高い取引の値が平均的な損失のある取引の値に非常に近いか等しい場合にのみ関連します。私たちは50%のレベルに慣れています。それを超えるすべての値は、戦略が有益であることを示します。そうでない場合、それは赤字です。個人的には60%の使用をお勧めします。このパラメータはどのトレーダーにも大きな影響を与えるため、このレベルは特に手動取引システムにとって非常に重要であると私は信じています。しかし、このパラメータは利益要因を明らかにしません。さらに、このパラメータは常に有益であるとは限りません。

  • WinPercent= (100*NProfit)/(NProfit + NLoss)

絶対ドローダウン

このパラメータは、戦略が預金に重い負荷をかけることを意味する場合、または残高曲線が直線に似ていない場合、または利益にわずかな傾向があるだけの混沌とした混乱にある場合、または将来的に少なくともこれにいくつかの前提条件がある場合に重要です。絶対ドローダウンは破滅から資金を救うことを可能にする最低預金を示すことができるように見えるかもしれませんが、これは妄想であり、その考えに固執しないことをお勧めします。この値は、テスト済みまたは取引済みのセグメント内の開始残高と残高グラフの最下点の差に等しくなります。

  • AbsoluteDrawdown = StartBalance - MinimumBalance
相対ドローダウン

このパラメータは、総利益を考慮しているため、取引システムの収益性や安定性よりも有益だと思います。違いは、最大ドローダウンと回復率の違いとほぼ同じです。

  • 100*AbsoluteDrawdown/EndProfit

値は割合として測定され、絶対ドローダウンが最終利益にどの程度影響するかを示します。この要因の有益な価値も非常に限られています。値が小さいほど、戦略は優れています。

その他の戦略パラメータ

以下は、それほど重要ではない戦略パラメータですが、それらを過小評価してはなりません。

  • 最大利益
  • 最大損失
  • 平均利益
  • 平均損失
  • 最大連勝数
  • 最大連敗数
  • 平均連勝数
  • 平均連敗数

最大利益

最大の利益を伴う取引。このパラメータは、預金通貨単位またはポイント単位のいずれかです。それはすべて、パラメータが必要な理由によって異なります。その重要性はかなり抽象的なものです。次のパラメータについても同じことが言えます。

最大損失

最大の損失を伴う取引。

平均利益

すべての取引の利益の合計を取引数で割ったもの。このパラメータは、ペイオフ期待値と利益率が正の場合にのみ有益です。

  • MiddleProfit= Sum(Pr[i])/n;

平均損失

すべての取引の損失の合計を取引数で割ったもの

  • MiddleLoss= Sum(Ls[i])/n;

最大連勝数

このパラメータは非常に便利です。上記から制限されている場合は、逆マーチンゲールを使用するのに最適です。連勝数が少ないほど、リバースマーチンゲールに適しています。

最大連敗数

前のパラメータとは対照的に、現在のパラメータを制限すると、直接マーチンゲールを使用できます。何らかの方法でシグナルのこの値を制限することができれば、預金を失うことを恐れることなく、マーチンゲールを使用して迅速かつ安全にお金を稼ぐことができます。

平均連勝数

このパラメータは、勝ちトレードの割合とほぼ同じです。実際、それはわずかに異なる方法で取引システムのほぼ同じ指標を反映しています。

  • MiddleWins= Sum(Wins[i])/n

ここで、Wins [i]は特定の半波の長さです。残高グラフ全体を上昇セグメントと下降セグメントに分割して、上昇セグメントを強調表示し、それらの取引数と上昇中途半端な数(n)を計算すると、パラメータ自体を計算できます。 これは、特定の半波の算術平均にすぎません。

平均連敗数

上記と同じパラメータ。唯一の違いは、負の半波を考慮することです。

  • MiddleLosses= Sum(Loss[i])/n

私の追加

より完全な戦略評価を提供するさらに別のパラメータがあると思います。

  • 直線性係数

これは、残高グラフの最初と最後を結ぶ直線からの残高曲線の偏差を反映しています。固定ロットを取引するときに残高グラフが直線のように見えるほど、システムは良くなります。これにより、将来的に高効率になる可能性が高くなります。このパラメータは、固定ロットを取引するときに特に役立ちます。市場のボラティリティは絶えず変化しています。つまり、平均ローソク足サイズ(全体的な市場のダイナミクス)も変化しています。これを理解すれば、いくつかの戦略のペイオフ期待値がテストの終わりまでに減少する理由、または逆に、グラフが非常に湾曲しており、傾斜角、したがってペイオフ期待値が安定したままであるという保証がない理由がわかります。

  • LinearFactor = MaxDeviation/EndBalance
  • MaxDeviaton = Max(MathAbs(Balance[i]-AverageLine))
  • AverageLine=StartBalance+K*i
  • K=(EndBalance-StartBalance)/n
  • n - テストの取引数

このようなパラメータがMetaTrader 4およびMetaTrader 5ストラテジーテスターに存在しない理由は非常に単純です。このようなパラメータを計算では最終的な利益が特徴であるため、常に2回の実行が必要です。パラメータ値が低いほど、戦略は優れています。必要に応じて、%で測定できます。

以下の画像でいくらか説明します。


システムをテストまたはレビューするときに焦点を当てるべきインディケータ―

焦点を当てる価値のある基本的なシステムパラメータはごくわずかだと思います。

  • ポイント単位のペイオフの期待値
  • 利益率またはそれに相当するもの
  • 最大ドローダウン
  • 最大連敗数
  • 直線性係数

他のパラメータは、システムまたは市場に関する追加情報として使用するのが非常に困難です。いずれにせよ、私はまだそれらを適用できるアルゴリズムばかりかそれらを使用するための前提条件さえも見つけていません。見た目よりもはるかに単純なことを複雑にすることに意味はないと私は信じています。これは混乱をもたらし、実際に重要なことから気をそらします。

これらの基準の選択について、できるだけ簡単な方法で説明しようと思います。

戦略が利益を生むためには、ポイントで測定されたスプレッド+手数料+スワップを超えるポイントでペイオフの期待値を提供する必要があります。ペイオフの期待値が平均スプレッド+手数料+スワップの2倍であることが望ましいです。次に、損失を補償し、パラメータ係数以上の利益を取得します。

戦略の収益性を確信した後、予測の質、つまり利益要因に注意を払う必要があります。指標が1を超えるほど、予測の品質は向上します。予測の品質が高いほど、パラメータが残りのすべてのパラメータに与える影響が大きくなります。ペイオフの期待値を無視することができたとしたら、利益率が最も重要なパラメータだったでしょう。利益率は他のすべてのパラメータに直接または間接的に影響します。

適切な収益性が得られたら、最大ドローダウンについて考える時です。このパラメータは、現在の預金段階で最大の収益性を確保するために必要な最小預金を定義します。最大ドローダウンに基づいて、預金を失うことを心配せずに最大の年間利益率を確保するような方法で開始預金を選択できます。最大連続損失または最大ドローダウンが極値であることが確実な場合、ストップアウトを恐れることなくシグナルにマルチンゲールを適用することが可能です。

線形性係数は、これがランダムな結果ではなく、規則性であることを確認します。グラフが直線に似ているほど、これが実際の規則性または市場の特徴である可能性が高くなります。

テスト時間も過小評価されているパラメータの1つです。テストされたセグメントが長く、収益性の結果が類似しているほど、システムがランダムな結果ではなく、グローバルパターンを反映する可能性が高くなります。

残高とエクイティ

このトピックは、これらの値の違いがわからない初心者にとって非常に重要です。エクイティは現在の変動利益であり、残高は現在の固定利益です。トレーダーはよく、エクイティではなく残高ラインを見ます。優れた取引システムでは、エクイティは可能な限り残高ラインの近くに配置されます。これは、戦略がグリッド、マルチンゲール、ピラミッドを適用しないことを示唆しています。これらの方法が機能しないことを意味するわけではありませんが、適切なシグナルが必要です。これについては、以前の記事で詳しく説明しています。MetaTrader 5ストラテジーテスターとMQL5Webサイトでは、残高ラインは濃い青で表示され、エクイティラインは緑で表示されます。エクイティラインが残高ラインに近いほど、両方のラインが上昇するという条件で、戦略はより安全になります。 

実際の取引システムのパラメータと実行可能性

この問題を私の実践と私が開発した実際の取引システムに基づいて検討します。素敵な写真を表示するだけで他に何もしないシグナルやEAへの投資からあなたを保護したいと思っています。私の謙虚な経験では、10年未満の履歴でテストされたシステムは、最終的に損失を被るリスクが高くなります。テストされたセグメントが2年以下の場合、リスクはさらに高くなります。

私の経験によれば、その歴史を通して利益と取引できるシステムでは、ペイオフの期待値は約5〜50ポイントですが、利益率は1.05〜3.0の範囲にあります。私が作成したすべての機能しているシステムはこの時間枠で動作し、必要に応じてM1で実行することもできるので、私はM5の時間枠が本当に好きです。これも非常に優れたチャートです。おそらく、単位時間あたりのデータ量が最も多い最小のバー(High[i]、Low[i]、Close[i]、Open[i])が含まれているためです。これらのバーポイントは実際に保存された実際のティックです。チャート期間が短いほど、より多くの実際のティックがローソク足内に保存されます。多くのシステムでは、テストで実際のティックを使用しない限り、これはテスターでシステムをチェックするときに非常に重要です。

個人的には、私は実際のティックを使いません。私のEAはすべてバーの閉鎖に基づいており、バーの閉鎖は常に実際のティックであるため、人工的なティックの生成について心配する必要はありません。私のシステムの平均利益率は約1.2ですが、かなり短い時間枠を使用しているため、ペイオフの期待値は約15ポイントです。長居時間枠で機能するものを見つけることははるかに困難です。ペイオフの期待値を上げることはできますが、利益率を上げることはできません。

多くの販売者は、EAの最適化が最も重要であり、再最適化の前に特定の予測時間を示していると主張しています。EAの将来の作業時間を予測することはまったく不可能なので、そのようなステートメントにだまされないでください。また、このツールの使用方法を学ぶまで、「最適化」という言葉を忘れることをお勧めします。目的の結果を得るために何でも最適化できますが、ほとんどの場合、それはランダム性の結果です。最適化には徹底的なアプローチが必要です。私はこのツールをほとんど使用せず、代わりにすべてを手動でチェックします。人間の脳は、パラメータの鈍い列挙よりもはるかに効率的なシステムです。

システムを適切にテストする方法

私は次のアプローチを使用して、自分のシステムと他の人のシステムの両方をテストします(ただし、99%の場合、自分のシステムをテストします)。

最初のテストでは、常に現在の日付から昨年かそれ以上を選択します。テスト結果が気に入ったら、さらにいくつかのセグメントを使います。包括的な分析には少なくとも10年のセグメントが必要であることに注意してください。20年のセグメントはさらにいいです。

最初と最後の年が良ければ、中央に近いいくつかのセグメントを取ります。そこにある結果も許容できる場合は、10年間すべてをテストし、残高曲線とエクイティを評価します。それらが直線に似ている場合、システムは注目に値します。このアプローチには、時間を節約し、結果として得られるシステムの品質を最大化するという1つの目標があります。

分析を行ったら、さらなるアクションを決定する時です。システムへの信頼をさらに強化するには、他のいくつかの通貨ペアでテストする必要があります。少なくともそこで効率の一部を保持している場合は、市場の物理学に基づいており、改善することができます。メインシステムパラメータを1つずつ確認し、それらが結果にどのように影響するかを定義します。ほとんどの場合、特定のパラメータの影響は別のパラメータからほぼ完全に独立していることがわかります。

最高のパフォーマンスを達成したら、デモ口座でシステムをテストします。システムがデモ口座で許容できる結果を示している場合は、実際の口座で試します。バーを使用するもう1つの利点は、証券会社が有能であれば、デモ口座の結果が実際の結果と変わらないことです。私は個人的にAlp***をお勧めします。***はおわかりだと思います。この証券会社の履歴データは歪められていません。ティックロボットのテストは保証されていないため、お勧めしません。バーの開閉に基づくEAのみを使用してください。

バーパラメータ

相場を正しく理解するには、バーまたはローソク足、それに含まれるデータ、およびバーまたはローソク足の外観に基づいて取得できるデータを定義する必要があります。バー(ローソク足)は固定長のティック履歴セグメントであり、すべてのティックを保存するのではなく、始値、終値、高値、安値のティックと、バーが開いた時間を日時に変更して保存します。これは、1970年1月1日から経過した秒数です。バー内には6つの値があります。

  • Close[]
  • Open[]
  • Low[]
  • High[]
  • Time[]
  • Volume[]

最初の4つの値は、バーに保存された4ティックで、その後にバーの開いた時間とボリュームが続きます。ボリュームは、バーに収まるティックの数です。価格データが最も重要ですが、時間とボリュームについても忘れないでください。このデータを正しく処理できれば、良いシグナルを見つけることができます。バーとローソク足は同じ意味です。唯一の違いは、同じ値のグラフィック表現です。


バーやローソク足を分析するにはさまざまな方法があります。これはグラフィックデータにすぎないため、厳密に適用することはお勧めしません。これは、指標やその他の分析方法と組み合わせた場合にのみ役立つ場合があります。

単純なボリュームベースのEAの作成とテスト

追加の市場データと取引制限として、ボリュームと時間の回廊を使用してEAを開発することを検討しましょう。ボリュームの急上昇により、市場参加者による重要な決定を検出できます。EAサーバの稼働時間を制限する機能により、ボリュームが非常に重要な領域を検出できます。EAを作成し、いくつかのテストと完全な分析を実行して、システムに関する結論を導き出しましょう。システム自体は、市場パラメータを掘り下げ、それらの関係を研究するためにのみ必要です。このシステムは、主に、各バーパラメータに独自の重みがあり、システムの全体的な品質に寄与することを示すために必要です。EA自体が記事に添付されているため、必要に応じて誰でも使用および変更できます。

ポジションを操作するための有名なライブラリから始めましょう。

#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
CPositionInfo  m_position=CPositionInfo();// trade position object
CTrade         m_trade=CTrade();          // trading object

これらは主にコードを単純化するために必要です。動作原理を説明する必要はないと思います。Webサイトには、このトピックに関するデータがたくさんあります。

次に、操作モードを切り替えることができるように番号付きリストを定義します。

enum MODE_CALCULATE
   {
   MODE_1=0,
   MODE_2=1,
   MODE_3=2,
   MODE_4=3
   };

これは、最も効果的な市場方程式を決定するためにいくつかのモードがあることを期待して行われます。最初は、どの物理学を利用したいかについていくつかの一般的なアイデアがあるはずですが、どの方程式が私たちのケースに最も効果的であるかはわかりません。現在のEAでは、4つの方程式の変形を実装しました。どのオプションが市場を可能な限り最良の方法で説明しているかがわかります。作成するモードが多すぎても意味がありません。私たちの仮定が正しければ、確実にそれがわかります。私は通常4つ以下のモードを作成します。

次に、入力とその目的を定義します。

input MODE_CALCULATE MODEE=MODE_1;//Mode
input int TradeHour=0;//Start Trading Hour
input int TradeMinute=1;//Start Trading Minute
input int TradeHourEnd=23;//End Trading Hour
input int TradeMinuteEnd=59;//End Trading Minute

input bool bWriteValuesE=false;//Log
input int CandlesE=50;//Bars To Analyse
input int Signal=200;//Signal Power
input int PercentE=52;//Percent Signals To One Side

input bool bInvert=false;//Trade Invert

input int SLE=3000;//Stop Loss Points
input int TPE=3000;//Take Profit Points
input double Lot=0.01;//Lot

input int MagicF=15670867;//Magic

動作モードの後には、サーバ時間コリドーを記述する4つのパラメータを持つブロックが続き、その中でポジション(または取引セッション)を開きます。奇妙に思われるかもしれませんが、この値は多くを定義します。次は、最も重要なシステム変数を説明する操作パラメータのブロックです。必要に応じて、追跡された値の現在の状態に関するデータをログに書き込んで、モードを切り替えるときに入力を調整できるようにします。

次は、分析するバーの市場セグメントです。履歴の多いすべてのローソク足は、計算では考慮されません。次に、モードごとに異なるスケールを持つシグナル強度があります。これが、ログが必要な理由です。最後のコンポーネントは、追加のシグナル制御要素です。シグナルが大きい場合もありますが、すべてのシグナルに対するシグナルの大部分の割合を理解せずに強さを設定しても意味がありません。最後の変数を使用すると、取引を反転し、ストップロスを設定して利益を得ることができ、すべての注文の取引量とマジックナンバーを定義できます。

次の関数を追加して、事前定義されたすべての配列の値をすばやく便利に計算します。

MqlTick LastTick;//the last tick

double High[];
double Low[];
double Close[];
double Open[];
datetime Time[];
long Volume[];

void DimensionAllMQL5Values()//prepare the arrays
   {
   ArrayResize(Time,CandlesE,0);
   ArrayResize(High,CandlesE,0);
   ArrayResize(Close,CandlesE,0);
   ArrayResize(Open,CandlesE,0);   
   ArrayResize(Low,CandlesE,0);
   ArrayResize(Volume,CandlesE,0);
   }

void CalcAllMQL5Values()//recalculate the arrays
   {
   ArraySetAsSeries(High,false);                        
   ArraySetAsSeries(Low,false);                              
   ArraySetAsSeries(Close,false);                        
   ArraySetAsSeries(Open,false);                                 
   ArraySetAsSeries(Time,false); 
   ArraySetAsSeries(Volume,false);                                   
   CopyHigh(_Symbol,_Period,0,CandlesE,High);
   CopyLow(_Symbol,_Period,0,CandlesE,Low);
   CopyClose(_Symbol,_Period,0,CandlesE,Close);
   CopyOpen(_Symbol,_Period,0,CandlesE,Open);
   CopyTime(_Symbol,_Period,0,CandlesE,Time);
   CopyTickVolume(_Symbol,_Period,0,CandlesE,Volume);
   ArraySetAsSeries(High,true);                        
   ArraySetAsSeries(Low,true);
   ArraySetAsSeries(Close,true);                        
   ArraySetAsSeries(Open,true);                                 
   ArraySetAsSeries(Time,true);
   ArraySetAsSeries(Volume,true);
   }

これらの関数については、要約ではありますが、以前の記事ですでに説明しました。さらに、ここにはLastTick変数もあります。これは、サーバから到着した最後のティックのすべてのパラメータの値を格納するためのものです。MQL4と同じように、配列にアクセスするために必要です。

主な変数とロジックは「静的クラス」に配置されます。

class TickBox
   {
   public:
   static int BarsUp;
   static int BarsDown;
   static double PowerUp;
   static double PowerDown;
   static double PercentUp;
   static double PercentDown;
   static double PercentPowerUp;
   static double PercentPowerDown;

   static void CalculateAll(MODE_CALCULATE MODE0)//calculate all the necessary parameters
      {
      BarsUp=0;
      BarsDown=0;
      PercentUp=0.0;
      PercentDown=0.0;
      PowerUp=0.0;
      PowerDown=0.0;
      if ( MODE0 == MODE_1 )
         {
         for ( int i=0; i<CandlesE; i++ )
            {
            if ( Open[i] < Close[i] )
               {
               BarsUp++;
               PowerUp+=(MathAbs(Open[i] - Close[i])/(High[i] - Low[i]))*Volume[i];
               } 
            if ( Open[i] > Close[i] )
               {
               BarsDown++;
               PowerDown+=(MathAbs(Open[i] - Close[i])/(High[i] - Low[i]))*Volume[i];
               } 
            }
         }
         
      if ( MODE0 == MODE_2 )
         {
         for ( int i=0; i<CandlesE; i++ )
            {
            if ( Open[i] < Close[i] )
               {
               BarsUp++;
               PowerUp+=(MathAbs(Open[i] - Close[i])/_Point)*Volume[i];
               } 
            if ( Open[i] > Close[i] )
               {
               BarsDown++;
               PowerDown+=(MathAbs(Open[i] - Close[i])/-_Point)*Volume[i];
               } 
            }
         }
         
      if ( MODE0 == MODE_3 )
         {
         for ( int i=0; i<CandlesE; i++ )
            {
            if ( Open[i] < Close[i] )
               {
               BarsUp++;
               PowerUp+=(double(CandlesE-i)/double(CandlesE))*(MathAbs(Open[i] - Close[i])/_Point)*Volume[i];
               } 
            if ( Open[i] > Close[i] )
               {
               BarsDown++;
               PowerDown+=(double(CandlesE-i)/double(CandlesE))*(MathAbs(Open[i] - Close[i])/_Point)*Volume[i];
               } 
            }
         }
         
      if ( MODE0 == MODE_4 )
         {
         for ( int i=0; i<CandlesE; i++ )
            {
            if ( Open[i] < Close[i] )
               {
               BarsUp++;
               PowerUp+=(double(CandlesE-i)/double(CandlesE))*(MathAbs(Open[i] - Close[i])/(High[i] - Low[i]))*Volume[i];
               } 
            if ( Open[i] > Close[i] )
               {
               BarsDown++;
               PowerDown+=(double(CandlesE-i)/double(CandlesE))*(MathAbs(Open[i] - Close[i])/(High[i] - Low[i]))*Volume[i];
               } 
            }
         }
         
      if ( BarsUp > 0 && BarsDown > 0 )
         {
         PercentUp=(double(BarsUp)/double(BarsUp+BarsDown))*100.0;
         PercentDown=(double(BarsDown)/double(BarsUp+BarsDown))*100.0;
         PercentPowerUp=(double(PowerUp)/double(PowerUp+PowerDown))*100.0;
         PercentPowerDown=(double(PowerDown)/double(PowerUp+PowerDown))*100.0;
         }         
      }
   };
   int TickBox::BarsUp=0;
   int TickBox::BarsDown=0;
   double TickBox::PowerUp=0;
   double TickBox::PowerDown=0;   
   double TickBox::PercentUp=0;
   double TickBox::PercentDown=0;
   double TickBox::PercentPowerUp=0;
   double TickBox::PercentPowerDown=0;

そのすべての関数と変数は静的です。インスタンスは必要ないため、インスタンスの作成は提供されていません。計算全体は、クラス内の1つの関数で実行されます。強気と弱気のバーの数、およびシグナル強度の同様のコンポーネントを定義し、共通の変数に合計します。各モードの4つの方程式はすべて、この関数に実装されています。

最初の2つの方程式の変形は、分析領域の遠端まで減衰せずに実装され、次の2つは正確なコピーですが、減衰を実装しています。この場合、減衰は線形です。他の減衰はいつでも行うことができますが、簡単にするために、最初は計算量が最も少ないものを試してみることをお勧めします。

全体の合計に寄与する基本項は、ローソク足ごとに計算されます。最初の方程式の変形は、ローソク足に存在するボリューム全体が一方向または別の方向のシグナルであると見なします。その上、最終的な動きが唯一のものにどれだけ近いかが考慮されます。最終的な動きに比べてローソク足の下部と上部の芯が大きいほど、ボリュームの重みは小さくなります。必要に応じて、他の比率を作成できます。

2番目の方程式の変形は、ローソク足の動きの合計をポイントで計算します。符号はローソク足の移動方向によって異なります。また、値に体積を掛けたものであるため、ボリュームはバーの動きの信頼性を示す重量比であると考えられます。残りの変数は、上昇または下降したバーの割合と、シグナル自体の割合を計算します。

次に、ポジションを開閉するメインの関数について説明します。

void Trade()
   {
   SymbolInfoTick(Symbol(),LastTick);
   MqlDateTime tm;
   TimeToStruct(LastTick.time,tm);
   int MinuteEquivalent=tm.hour*60+tm.min;
   int BorderMinuteStartTrade=HourCorrect(TradeHour)*60+MinuteCorrect(TradeMinute);
   int BorderMinuteEndTrade=HourCorrect(TradeHourEnd)*60+MinuteCorrect(TradeMinuteEnd);
   if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= 1.0 && TickBox::PercentPowerUp >= 50.0 )
      {
      if ( !bInvert ) ClosePosition(POSITION_TYPE_BUY);
      else ClosePosition(POSITION_TYPE_SELL);
      }
      
   if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= 1.0 && TickBox::PercentPowerDown >= 50.0 )
      {
      if ( !bInvert ) ClosePosition(POSITION_TYPE_SELL);
      else ClosePosition(POSITION_TYPE_BUY);
      }
      
     if ( BorderMinuteStartTrade > BorderMinuteEndTrade )
        {
        if ( PositionsTotal() == 0 && !(MinuteEquivalent>=BorderMinuteEndTrade && MinuteEquivalent<= BorderMinuteStartTrade) )
           {
           if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= Signal && TickBox::PercentPowerUp >= PercentE )
              {
              if ( !bInvert ) m_trade.Sell(Lot,_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
              else m_trade.Buy(Lot,_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
              }
      
           if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= Signal && TickBox::PercentPowerDown >= PercentE )
              {
              if ( !bInvert ) m_trade.Buy(Lot,_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
              else m_trade.Sell(Lot,_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
              }
           }        
        }
     if ( PositionsTotal() == 0 && BorderMinuteStartTrade <= BorderMinuteEndTrade )
        {
        if ( MinuteEquivalent>=BorderMinuteStartTrade && MinuteEquivalent<= BorderMinuteEndTrade )
           {
           if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= Signal && TickBox::PercentPowerUp >= PercentE )
              {
              if ( !bInvert ) m_trade.Sell(Lot,_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
              else m_trade.Buy(Lot,_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
              }
      
           if ( MathAbs(TickBox::BarsUp-TickBox::BarsDown) >= Signal && TickBox::PercentPowerDown >= PercentE )
              {
              if ( !bInvert ) m_trade.Buy(Lot,_Symbol,LastTick.ask,LastTick.bid-double(SLE)*_Point,LastTick.ask+double(TPE)*_Point);
              else m_trade.Sell(Lot,_Symbol,LastTick.ask,LastTick.ask+double(SLE)*_Point,LastTick.bid-double(TPE)*_Point);
              }
           }        
        }
   }

ポジションは、シグナルの強さとパーセンテージで測定されたその品質に基づいて開かれ、シグナルの変化に少なくともわずかなヒントがある場合は閉じられます。

次の関数は、特定の方向に開いているポジションのみを決済するために使用されます。簡単なことです。

void ClosePosition(ENUM_POSITION_TYPE Direction)//close a position by a symbol
   {
   bool ord;
   ord=PositionSelect(Symbol());
   if ( ord && int(PositionGetInteger(POSITION_MAGIC)) == MagicF  && Direction == ENUM_POSITION_TYPE(PositionGetInteger(POSITION_TYPE)) )
      {
      if(m_position.SelectByIndex(0)) m_trade.PositionClose(m_position.Ticket());          
      }
   }

次に、主なイベントとバーを操作するための関数について説明します。

int OnInit()
  {
  m_trade.SetExpertMagicNumber(MagicF);//set the magic number for positions
  DimensionAllMQL5Values();//prepare the predefined arrays
  return(INIT_SUCCEEDED);
  }

datetime Time0;
datetime TimeX[1];
bool bNewBar()
   {
   CopyTime(_Symbol,_Period,0,1,TimeX);
   if ( Time0 < TimeX[0] )
      {
      if (Time0 != 0)
         {
         Time0=TimeX[0];
         return true;
         }
      else
         {
         Time0=TimeX[0];
         return false;
         }
      }
   else return false;
   }

void OnTick()
  {
  if ( bNewBar())//work by bars
     {
     CalcAllMQL5Values();
     TickBox::CalculateAll(MODEE);
     if (bWriteValuesE)
        {
        Print("% Sit in buy = ",TickBox::PercentUp);
        Print("% Sit in sell = ",TickBox::PercentDown);
        Print("Signal = ",MathAbs(TickBox::BarsDown-TickBox::BarsUp));
        Print("% Resistance = ",TickBox::PercentPowerUp);
        Print("% Support = ",TickBox::PercentPowerDown);        
        Print("***************************************************************************");
        }
     Trade();
     } 
  }

EAを起動するときは、配列を準備してサイズを設定し、ポジションのマジックナンバーを設定する必要があります。その後、バーの変化とその作業に必要な変数を検出するための述語関数について説明します。その後、メインティックイベントを記述し、事前定義された配列の値を再計算してからシステムパラメータを計算します。また、関数が有効になっている場合は、メインシステムパラメータをログに書き込むブロックを追加します。もちろん、必要に応じて別の方法で行うこともできます。重要なことは、すべてが簡潔で明確であるということです。

EAの背後にある考え方は、各バーが現在の図に寄与するということです。次に何が起こるかを2〜3バーで大まかに判断することさえ不可能であることを覚えておいてください。各バーは最終的なシグナルに寄与しますが、市場の物理的性質により、それらの重みは異なります。これについては、次の記事で詳しく説明します。

EAのテスト

EAをテストして、有望な機能を検出してみましょう。昨年から始めて、EURUSDM5を使用します。10年以内の履歴で操作モードを経てさまざまな時間枠を使用したところ、次のような許容できる結果が得られました。EAのテストに使用したセットを以下に添付します。システムを分析するための独自のルールに従って、動作モードとサーバの時間間隔の両方を交互に変更しました。その結果、約30〜60分で以下のパラメータを検出しました。

以下は昨年のテストです。


次に、最初の年を10年のセグメントでテストしました。


グラフはニアセグメントほど良くはありませんが、最終的な動きは保持されます。ここでもすべてが機能しているようです。

その後、セグメントの中央を取り、システムがそこでどのように動作するかを確認しました。


ご覧のとおり、ここにもグローバルパターンの兆候があり、間隔全体をテストして、グローバルスケールでどのように見えるかを確認する必要があります。


グラフは完璧にはほど遠いですが、作業セグメントを確認できます。また、フィルタを導入したり、詳細な最適化を実行したりもできます。特定のツールの選択は常にオプションです。他のペアでテストを実行すると、結果はおそらく異なるでしょうが、一定の時間を費やした後、同時に複数のペアに最適なパラメータを見つける可能性があります。物理学を把握して強化することができれば、結果はさらに大きくなります。

現在の形でさえ、ロボットは許容できる結果をもたらしました。取引はほとんどありませんでしたが、EAは多通貨で機能しました。非常に単純なコードでさえも、アイデアを開発するための強力な基盤として役立ちます。一部のシステムは、変更せずに使用することもできます。

もちろん、多通貨機能を備えるのは良いことですが、これはより多くの作業と積極的な変更によって達成されます。本稿ではそれを行わず、このタスクを読者に任せます。システムからすべてを絞り出そうとして、あまり時間をかけないでください。機能する場合、ほとんどすぐにわかります。結果が表示されない場合は、結論を導き出し、考え方を変えることをお勧めします。場合によっては何かを修正することが可能ですが、常にそうとは限りません。

それでもテストすることはできますが、絶対にすべてのバーパラメータがさまざまな方法で結果に影響を与えることは明らかであり、さまざまなペアでさまざまな組み合わせのパラメータの極値があります。すべてのペアで同時に機能する極値もありますが、それらを見つけるには時間と練習が必要です。 記事にはMQL4バージョンも添付されています。

終わりに

自分でコードを記述してテストすることを恐れないでください。また、自分のシステムが単純すぎるように見えるという事実に落胆しないでください(通常、実際に機能するのは単純なシステムのようです)。複雑になるほどシステムの自由度が増し、入力や予測できないオプションが増えます。コードの複雑さをできるだけ避け、できるだけ簡潔に保ってください。

さらに、システムが複雑になるほど、テストに時間がかかります。何にも基づいていないシステムを開発しないでください。「30件の取引を行ったので、すべてがうまくいくはずです」などと言う人を信じないでください。これは専門家のアプローチではありません。特に、いくつかのインディケータ―に基づいてシステムを作成しないでください。これは、開発者としてできる最も愚かなことです。

一般的に、開発に費やせる時間を必ず理解してください。目標と許容可能な時間枠が必要です。最終的に、目標をより現実的にするために絞り込むことができますが、とにかく目標を設定する必要があります。

私は、何かを見ようとしてチャートに何千ものインディケータ―を設定している長年のコミュニティメンバーをたくさん見ました。これは行き止まりです。まず、特定の結果を得たいのか、それとも取引が趣味なのかを判断する必要があります。私は、何年間も退屈なチャートを見ているよりもはるかに興味深い趣味が他にあると信じています。外国為替はブラックホールです。はまってしまえば、二度と戻ることはないでしょう。

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

添付されたファイル |
VAI_EURUSD_M5.set (1.28 KB)
アルゴリズム取引から100万ドルを稼ぐ方MQL5.comサービスを使用してください アルゴリズム取引から100万ドルを稼ぐ方MQL5.comサービスを使用してください
トレーダーは皆、最初の百万ドルを稼ぐことを目標に市場を訪れます。過度のリスクと初期予算なしでこれを行う方法は何でしょうか。MQL5サービスは、世界中の開発者やトレーダーにそのような機会を提供します。
ニューラルネットワークが簡単に(第6回): ニューラルネットワークの学習率を実験する ニューラルネットワークが簡単に(第6回): ニューラルネットワークの学習率を実験する
これまで、様々な種類のニューラルネットワークをその実装とともに考察してきました。 すべての場合において、ニューラルネットワークは、学習率を選択する必要があるグラディエントディーセント法を用いてトレーニングされました。 今回は、正しく選択されたレートの重要性とニューラルネットワーク学習への影響を例を用いて示したいと思います。
ニューラルネットワークが簡単に(第7回): 適応的最適化法 ニューラルネットワークが簡単に(第7回): 適応的最適化法
以前の記事では、ネットワーク内のすべてのニューロンに対して同じ学習率を用いてニューラルネットワークをトレーニングするためにストキャスティクススロープ降下法を使用しました。 本論文では、各ニューロンの学習速度を変化させることができる適応学習法に着目します。 その是非についても検討していきたいと思います。
ニューラルネットワークが簡単に(第5回): OPENCLでのマルチスレッド計算 ニューラルネットワークが簡単に(第5回): OPENCLでのマルチスレッド計算
ニューラルネットワークの実装のいくつかのタイプについては、これまで説明してきました。 これまで考慮されたネットワークでは、各ニューロンに対して同じ操作が繰り返されます。 さらに論理的な進展としては、ニューラルネットワークの学習プロセスを高速化するために、現代の技術が提供するマルチスレッドコンピューティング機能を利用することです。 可能な実装の1つは、この記事で説明しています。