トレーダーのリスクを低減するには
Aleksandr Masterskikh | 12 3月, 2018
内容
- プロセス動態の観点からの金融市場とは
- 金融市場で利益を上げる可能性は
- 価格変動の動態に関連する市場リスク
- 市場の動態に関連するリスクの分類
- 市場エントリ時の高ボラティリティに伴うリスク
- 市場エントリ時における抵抗レベルの存在に伴うリスク
- 市場エントリ時に買われ過ぎ/売られ過ぎ領域に入り込むリスク
- 市場エントリ時に明確なトレンドがないことに伴うリスク
- 指標計算期間の誤った選択に伴うリスク
- 市場エントリ時における指値注文の使用に伴うリスク
- 市場エントリ後の価格変動の不確実性に伴うリスク
- 市場エントリ後の価格の暴落に伴うリスク
- 分析中に1つの価格変動スケールのみを使用することに伴うリスク
- テクニカル分析またはファンダメンタル分析のみを使用することに伴うリスク
- 市場の動態に関連しないリスク
- 市場の動態に関連しないリスクの分類
- 取引システムの構造に伴うリスク
- 預金の損失限度超過に伴うリスク(預金による投資家のリスク限度の管理)
- 取引条件のマイナスの変化に伴うリスク
- 証券会社の取引サーバへの接続の品質によるリスク
- 証券会社側とクライアント側の自動取引許可に伴うリスク
- 金融市場法制の変更に伴うリスク
- 言及されたリスクのいくつかを低減するためのモジュールを備えたシンプルなEA
- 終わりに
はじめに
まず、本稿は初心者のトレーダーやアナリストが独自の取引戦略を開発するのに役立つでしょう。しかし、経験豊富な市場参加者でも、リスクの分類、買われ過ぎ/売られ過ぎ領域を定義するローソク足分析の適用、ファンダメンタル分析とテクニカル分析の関係、移動平均計算期間の選択、可能な価格の暴落、また価格暴落の可能性に伴うリスク低減などの有用な何かを見い出すかもしれません。
本稿では、次の問題を扱います。
- 動態の観点からの金融市場および株式市場における取引プロセスの本質
- 取引における利益確率
- 取引システムを開発する際にトレーダーのリスクを低減する方法
金融市場で取引する際の完全に包括的な分析とリスクの完全な分類をお約束することはできません。代わりに、金融商品の価格変動の動態に関連する主要な市場リスクに焦点を当てる予定です。また、市場の動態に直接関係しないが取引効率にとっては依然として重要なリスクについても明らかにしていくつもりです。本稿を書くにあたって、私は自分が取引システムの分析と開発で得た経験を使用しました。
EAのMQL5版はこちらです。
プロセス動態の観点からの金融市場とは
取引戦略(手動取引と自動取引の両方)を開発する際には、どのプロセスを扱っているのかを理解する必要があります。金融市場における価格の動きは、非定常的な過程です。それは複数の要因の影響を受け、決定的要因を特定することは不可能なことがあります。
プロセスの非定常的な特性は、市場参加者の行動において決定されます。彼らの反応は多方向です。その結果、市場における振幅と周波数の変化は、決定論的行動法によって決定することはできません。一般的に、このような過程はランダムと見なすことができます。
ただし、動きを正しく予測できる領域はまだあります。これらの領域を示す要因を列挙しましょう。
- 価格の波のような動き: 波の始まりは、例えば移動平均のグループと交差するローソク足や従来の指標からのシグナルによって、定義することができます。ここではそのような定義の正確さについては話さずに、それが可能であることだけに留意します。
- 保合領域の狭さ(価格は常にそれらを出ます)
- 特定の基本的、ファンダメンタル、テクニカル要素に対応するための規則
金融市場で利益を上げる可能性は
これは主要な質問です。なぜなら、トレーダーは誰でも実際には投資家であるからです。主な移動範囲は正確にトレンド領域に位置しているため、金融市場での取引時に利益を得る確率はトレンド継続予測の正確さに直接関係しています。
トレンドの継続または逆転を計算する方法は多数ありますが、すべての取引システムが市場状態モデルであるため、共通の欠点を持っています。このようなモデルの精度を評価することは常に問題です。第一に、プロセス自体は、非定常(ランダム)な性質のために動態に関してかなり複雑です。第二に、すべての精度評価方法は、ランダムプロセスの「内側」でも複雑であり、その効率はあいまいです。
したがって、利益を上げる可能性を評価するために、別の方法で実際の(計算されていない)データを使用します。これを行うには、投資会社と証券会社によって提供される外国為替および株式市場取引の効率に関する統計を分析します。
「ロシアと米国の民間外国為替取引の効果」稿(ロシア語)に記載されているデータによれば、2015年現在、ロシアの民間勝ちトレーダーは28%で、米国では33%でした。もちろん、調査には限られた数の企業が含まれており期間もわずか6ヶ月であったため、これらのデータは網羅的とはみなされません。しかしながら、これらの数字によっていくらかの洞察が得られます。可能な結論は何でしょうか。
ほとんどの市場参加者が使用している従来の分析方法では、金融市場における価格変動のプロセスを効果的に予測することはできません。資産管理手法を含む追加の措置もまた非効率的です。その理由は、テクニカル分析やファンダメンタル分析を使用して行われた市場トレンドの基本的な予測の初期の非効率性にあります。その結果、金融市場参加者の3分の1以上が利益を得ることはできません。
株式市場については、統計は一様ではありません。私が引用するのは比較的「中程度の」データです。フランス金融機関の金融機関向けの調査によると、10人の個人トレーダーのうち8人が最終的に資金を失います。これは、株式市場での取引の効率が20%であることを意味します。これは、数的にはほぼ同じですが、外国為替市場よりもさらに悪いです。
お分かりのように、投資家にとっては包括的なリスクの会計処理が最も重要です。
リスクの2つの主要なグループを強調しましょう。
- 価格変動の動態に関連するリスク
- 市場の動態に関連しないリスク
これらのリスクとそれらを低減する方法を詳しく見ていきます。
最初のリスクグループから始めます。リストは、金融商品チャートの分析に基づいて決定されます。個々のローソク足とそのグループの特性、移動平均などのチャートの要素とそのパラメータを分析する必要があります。それらの数学的モデルは価格変動の概念に対応していないため、他の従来の指標は使用しません。
価格変動の動態に関連する市場リスク
技術的には、トレーダーの主要リスクはトレンドの逆転です。金融商品の価格は方向を変えて、ポジションとは反対に動き始める可能性があります。ポジションがまだ開かれていない場合、リスクはそのような逆転を予測することにあります。
すべてのトレーダーはトレンドを独自に定義します。奇妙に思えるかもしれませんが、テクニカル分析におけるこの概念に「公式」定義はなく、トレンド逆転確率の評価も主観的です。すべてのトレーダーによって定義される危機的振幅(トレンド逆転中)は、受容可能なリスク(リスク限界)に依存します。この値は、各トレーダーの口座にある資金の量によって定義されます。言い換えれば、すべては可能な最大限のドローダウンに依存します。銀行に良いものは普通のトレーダーにとっては悪いものです。
リスクを見て、それらを低減するためのソリューションを探してみましょう。
市場の動態に関連するリスクの分類
伝統的な分析では、短期、中期、長期の3つのタイプのトレンドが強調されます。
局所的および全域的トレンドもよく言及されています。伝統的に、局所的トレンドは、短期的または中期的に形成されたものです。全域的トレンドは長期的に形成されます。これらの概念の時間および振幅の境界を特定する明確な値はありません。すべてが相対的です。したがって、分析を単純化してみましょう。逆転の振幅は、トレンド逆転に伴うリスクの基準として使用されます。重要な技術水準または投資家の預金の規模に応じて、所定のリスク限度を考慮して評価します。
トレンド逆転の可能性に伴うリスクを分類するためには、市場価格の動態の要因も考慮する必要があります。簡単に調べてみましょう。
- 市場エントリ時の高ボラティリティに伴うリスク
- 市場エントリ時における抵抗レベルの存在に伴うリスク
- 市場エントリ時に買われ過ぎ/売られ過ぎ領域に入り込むリスク
- 市場エントリ時に明確なトレンドがないことに伴うリスク
- 指標計算期間の誤った選択に伴うリスク
- 市場エントリ時における指値注文の使用に伴うリスク
- 市場エントリ後の価格変動の不確実性に伴うリスク
- 市場エントリ後の価格の暴落に伴うリスク
- 単一期間の使用に伴うリスク
- 単一タイプの分析(テクニカルまたはファンダメンタル)の使用に伴うリスク
市場エントリ時の高ボラティリティに伴うリスク
多くのトレーダーは、この種のリスクを全く考慮に入れていません。変動の振幅(主なトレンドに対するものを含む)は高ボラティリティ間では上昇するため、これは大きな誤りです。これがリスク要因です。
伝統的な指標を用いたボラティリティの評価はあまりにも主観的です。第一に、指標の設定自体が主観的であり、第二に、その数学的モデルは常にそのような評価のために設計されているとは限りません。したがって、市場エントリ時に必要なボラティリティの程度を定義するモデルとして保合領域を使用する方が信頼性が高くなります。
このリスクを低減するために、エントリアルゴリズムに最も近い気配値履歴の閾値振幅限界の条件を設定することができます。このような価格帯は以下のように設定することができます。
- 2つの対向するフラクタル間の振幅
- またはローソク足群の振幅
ローソク足の振幅を制限するのが最も簡単な方法です。適切なコードの断片を見てみましょう。
//--- 市場エントリアルゴリズム - 買----------------------------------------------------------------------------------------- if( //---- 市場エントリ時の高ボラティリティに伴うリスクの低減 ---- // 最近の履歴において高ボラティリティがないことをシミュレートする: ( High[1] - Low[1]) <= 200*Point && // 短時間枠(М1)の振幅を制限する ( High[2] - Low[2]) <= 200*Point && ( High[3] - Low[3]) <= 200*Point && (H_prev_m15 - L_prev_m15) <= 300*Point && // 長時間枠(М15)ローソク足の振幅を制限する (H_2p_m15 - L_2p_m15) <= 300*Point && (H_3p_m15 - L_3p_m15) <= 300*Point && (H_prev_m15 - L_3p_m15) <= 300*Point && // 長時間枠(М15)ローソク足のチャネル振幅を制限する (High[1] - Low[1]) >= (1.1*(High[2] - Low[2])) && // 気配値履歴の2番目のバーに対する前のバーのアクティビティを制限する (High[1] - Low[1]) < (3.0*(High[2] - Low[2])) && // 同じ
図1 エントリアルゴリズムのモジュール: 市場エントリ時の高ボラティリティに伴うリスクの低減
図1は、エントリアルゴリズム(買)におけるモジュールを示します。
記法:
- High{1], High[2], High[3] — M1の最後の3つのバーの高値
- H_prev_m15, H_2p_m15, H_3p_m15 — M15の最後の3つのバーの高値
- Low[1], Low[2], Low[3] — M1の最後の3つのバーの安値
- L_prev_m15, L_2p_m15, L_3p_m15 — M15の最後の3つのバーの安値
このモジュールはエントリポイントがかなりのボラティリティ領域にある場合に発生するリスクを低減することができます。これは、チャネルの終わり(中程度のボラティリティ)だけでなく、水平価格チャネルをモデリングすることによって達成されます。
気配値履歴の前の3つのバーのローソク足の振幅を制限することによって、М1およびМ15時間枠の価格チャネルをシミュレートします。振幅制限は、別々のローソク足とローソク足群全体の両方に設定されます。チャネル振幅は、その最初のローソク足と最後のローソク足の極値の差として定義されます。
チャネルの終わりの中程度のボラティリティは、M1時間枠の2つの隣接するローソク足の振幅の比を制限することによってシミュレートされます(この場合、適用される比は1.1から3.0)。もちろん、他の振幅比を使用することもできます。
問題は、何故チャネル全体の振幅を設定する必要があるのかです。各ローソク足の振幅を設定するので十分ではないのでしょうか。いいえ、違います。チャネル全体の振幅を定義しなければ、波のような(水平ではなく)チャネルが形成され、その振幅は単一のローソク足の大きさの2倍になる可能性があります。
これは買いの例です。売りの場合、チャネルと別々のローソク足の振幅は高値と安値の差として定義され、方向は現在のアルゴリズムではなく他のエントリアルゴリズムモジュールで設定されるため、コードは同じままです。
市場エントリ時における抵抗レベルの存在に伴うリスク
市場参加者は、チャート上に存在する抵抗レベルに反応します。一部の人にとっては、これは利益の目標で、他の人にとっては、損失のリミッタ、また他の人にとっては、レベルブレークダウンの最初の目標です。このため、フラクタルレベルは、価格が小振幅で異なる動きをする領域に囲まれていることがあります。このような領域でポジションを開くリスクは増加しますが、様々な取引システムのテスト結果によると、領域内での予測は非効率的です。したがって、市場エントリポイントがトレンドの方向で抵抗レベルの外であるのが合理的に思えます。
この取引リスクはどのように考慮に入れることができるでしょうか。
ポジションが既に抵抗レベルの方向に開かれていて価格がそれに近づいている場合、強いロールバックがその結果を妨害する可能性が高いため、このポジションを前もって決済する方が良いです。
価格が抵抗レベルを超えた後にアルゴリズムに従ってポジションを開く場合は、選択した方向で信頼できるブレークスルーを待ちます。
実際、これは偽と真のブレークダウンの問題です。その可能な解決策の1つは次のとおりです。新しい抵抗レベルがフラクタルレベルの後に形成されるまで待ち、価格がそれを突破するまで待ちます。必ず短めの時間枠を使ってください。しかし、これだけでは十分ではありません。現在の動態は、ブレークスルーの方向および新しいフラクタルレベルを超えた明確な活動兆候を示すはずです。
このアプローチの欠点は、時間枠の不確実性です。レベルブレークスルーの振幅は事前に予測することは不可能であるため、主観的に選択されます。したがって、エントリの時点でレベルが既に渡されるべきであるという条件を指定することにより、問題を単純化します。
取引システムを開発する際、エントリアルゴリズムにいくつかのオプションを使用して、抵抗レベルの存在に伴うリスクを低減することができます。
- 選択肢1: 最も近い抵抗フラクタル(コード内では、ループを使用して実装されています)を検索した後。この方法の利点は、この時間枠で実際の抵抗レベルを見つけることができるということです。しかしながら、2つの欠点があります。まずは、初心者のプログラマにとってループを開発するのは難しいかもしれないということです。次に、フラクタルが昔過ぎる、つまり抵抗レベルとは無関係であるかもしれないということです。
- 選択肢2: 1つ前のローソク足の高値(買い)と安値(売り)を使います。この方法には2つの利点があります。まずは、簡単にプログラムすることができることです。次に、複数の時間枠を同時に設定することができることです。これは、古いフラクタルを検索することと同じです。欠点は、いくつかのフラクタルが検出されないことがあるということです。ローソク足の極限は、いわゆる髭の存在下でのみフラクタルであるためです。
初心者のプログラマーにとっても、手作業の戦略を開発する場合にも、選択肢2を適用することをお勧めします。フラクタルの一部が失われて精度が低下するため、単純で効率的です。コードの断片を見てみましょう。
//---- 市場エントリ時における抵抗レベルの存在に伴うリスクの低減 ----- // 現行価格が局地的抵抗レベルを通過するときの状況をシミュレートする Bid > High[1] && // М1(短時間枠) Bid > H_prev_m15 && // М15(長時間枠)
図2 エントリアルゴリズムのモジュール: 市場にエントリする際の抵抗レベルの存在に伴うリスクの低減
図2は、上向きの動きでの抵抗レベルの存在に伴う買いエントリのリスクを低減するためのエントリアルゴリズムモジュールです。これは、現行価格が以前のローソク足の高値(2つの時間枠で別々に)として抵抗レベルを既に超えているという特定の条件を設定することによって達成されます。
さらに変動のアクティビティを設定すべきです。しかし、変数の重複を避けるために、これは他のモジュール(方向とアクティビティの両方が設定されている)で行われています。
売りを出すには、1つ前のローソク足の低値(M1とM15の時間枠)を下降トレンドを考慮した抵抗レベルとして使用します。
市場エントリ時に買われ過ぎ/売られ過ぎ領域に入り込むリスク
これらのリスクには、エントリの方向の残りの振幅が小さくて逆転の確率が急激に増加するときに、活動的な波のような動きの最後にエントリする確率が含まれます。このような領域は、売られ過ぎ/買われ過ぎ領域以外の何でもありません。定義に伝統的な指標(RSIなど)を使うのは効率が悪いことが多く、シグナルが誤っていることがよくあります。理由は同じです。従来の指標は、これらの領域を決定するための適切な数学的アルゴリズムを備えていません。売られ過ぎ/買われ過ぎ領域をより正確に検索するには、トレンドの減速の兆候を特定する必要があります(他のすべての時間枠での逆転を直ちに示すので、M1を含む)。
フラクタルとローソク足の分析を組み合わせることによって、減速の兆候を次の基準で検出します。
- 隣接するフラクタル抵抗レベル間の距離(振幅サイズ)を小さくします。隣接する2つの領域の振幅を比較するには、3つのフラクタルが必要です。
- ローソク足内の補正を増加させ、ローソク足の「実体」を減少させます(ローソク足内分析)。
- ローソク足のピボットシフトの方向を以前のローソク足のピボットに対して変更します(これには3つのローソク足が必要です)。
この方法を使用する場合は、記載された要素がないことを示す条件をエントリアルゴリズムに追加します。たとえば、これは falseとtrueを使用して行うことができます。trueは 特定の減速要因が市場に存在することを示します。
しかし、より簡単なオプションがあります。これは、買われ過ぎ/売られ過ぎ領域の検索には直接関係しません。ここでは間接的な兆候が使用されています。波のような動きの開始時に市場にエントリすると、買われ過ぎ/売られ過ぎ領域に入る可能性が大幅に減ります。実際、ここでは局地的トレンドの初期段階をシミュレートしています。
- まず、同じローソク足の中の1つ以上の移動平均(MA)の交差点を特定します。これには、波のような動きの始まりである可能性があります。波の始まりを確認するには、追加の条件が必要です(下記参照)。
- その後、波のような動きの初期段階をシミュレートします。それは新しいトレンドの始まりになるでしょう。これを達成するために、交差後のローソク足の方向、その活動、直前のバーで交差に参加した高速МАの方向、 これらのМАに関連する現行価格の位置を指定します。
注意: 局地的トレンドの初期段階をシミュレートするときは、高速MAの方向のみを設定することをお勧めします。低速МАの方向を設定する必要はありません。
そのような移動平均と別のアプローチをとるのは、古いMAは遅延が大きいため、新しいトレンドの方向に逆転する時間がないということです。したがって、その方向を設定すると、シミュレートされた市場へのエントリポイントは、トレンドの始まりから遠くにあり、危険な売られ過ぎ/買われ過ぎ領域内に入る可能性があります。
2番目の選択肢(局地的トレンドの初期段階をシミュレート)はより簡単で、初心者の開発者にはお勧めです。コードの断片を見てみましょう。
//--- 市場エントリ時に買われ過ぎ領域に入り込むリスクの低減 ----- // 買われ過ぎ領域にエントリする確率を減少させるために波の開始点への結合をシミュレートする: ((MA8_prev > Low[1] && MA8_prev < High[1]) || (MA8_2p > Low[2] && MA8_2p < High[2]) || // 波の初め - データ履歴(М1)の3つのバーよりも遠くない (MA8_3p > Low[3] && MA8_3p < High[3])) && // 同じ MA5_prev_m15 > L_prev_m15 && MA5_prev_m15 < H_prev_m15 && // 波の初め - 長時間枠(М1)の1つ前のバー
図3 3 - 市場エントリ時に買われ過ぎ/売られ過ぎ領域に入り込むリスクを低減するためのモジュールは無効にされている
記法:
- МА8_prev、МА8_2p、 МА8_3p — 気配値履歴でそれぞれ1つ前、2つ前、3つ前のバーで計算された期間8のМА(М1)
- МА5_prev_m15、 МА5_2p_m15、МА5_3p_m15 — 気配値履歴でそれぞれ1つ前、2つ前、3つ前のバーで計算された期間5のМА(М15)
- ローソク足の極値が先に指定されます(図2参照)。
買われ過ぎ領域内に入り込むリスクは、推定された波の始まりにエントリポイントを結びつけることによって減少します。波の始まりの兆候は、ローソク足が交差しているMAです。М1では、これは期間8のМА、М15 では期間5のМАです。移動平均の期間の値は、フィボナッチ数列から選択されます。このパラメータについては、「指標計算期間の誤った選択に伴うリスク」セクションで詳しく説明します。
このモジュールは、ローソク足とMAの活動と方向、およびMAに相対する現行価格の位置を特徴付けるパラメータを指定していません。これは、変数を複製しないために行われます。モジュールのこれらのパラメータは、「市場エントリ時に明確なトレンドがないことに伴うリスク」から設定します。
M1時間枠上のローソク足とMAの交差は、履歴内の1つのバーに限定されないことにご注意ください。これは論理ORによって、履歴の1つ前、2つ前、または3つ前のバーに設定されます(M1)。М15では、単一の交差オプションは、気配値履歴の1つ前のバーでです。この潜在的なオプションのセットによっては、そのような交差に関連した局地的トレンドの発展に関連する複数のバリアントを持つ実際の市場状況を考慮に入れることができます。
上記の例は、買いエントリ(買われ過ぎ領域を避ける)のために書かれています。ローソク足を横切るМАのアルゴリズムは移動方向に依存しないため、売りエントリ(売られ過ぎ領域を避ける)では、モジュールは同じです。
よって、買われ過ぎ/売られ過ぎ領域を避けて市場にエントリするため、またこれらの領域を見つけるための2つの方法を検討しました。取引システムを作成するときや取引指標を開発するときに、これらの方法を試してみることができます。
市場エントリ時に明確なトレンドがないことに伴うリスク
はっきりと目立つトレンドがないことは、動態の不確実性とそれに伴うリスクのもう一つの要因です。ここでは、市場が小さな振幅を持つ横向きのトレンドやフラットによって支配される状況について話しています。
狭い範囲で絶えず変化しているため、価格の一般的な方向を決定することは困難です。したがって、市場エントリ方向を予測する際にエラーが発生するリスクが増大します。
従来の分析方法では、フラットの明確な定義(トレンドの場合と同様)が得られないため、問題はさらに複雑になります。 したがって、フラットとトレンドの始まりとの境界の定義はありません。既存の方法は非常に主観的です。たとえば、StdDev指標のような二乗偏差法、さらに高度な適応関数(たとえば、 FRAMA)があります。この問題は、トレンド定義のグラフィカルなメソッドを扱うときにさらに複雑になります。異なる解釈によれば、様々な市場セグメント(かなり大きな振幅を有するセグメントを含む)は、フラットであると考えられます。これは利益の損失につながります。
私の個人的な経験(TSの結果によって確認された)によれば、平坦な境界を定義する最も効率的な方法は、横方向のトレンドの中に絶対振幅値を設定することです。
しかし、振幅が選択した閾値よりも大きくても、新しいトレンドを目撃しているわけではないので、すぐに急いでポジションを開いてはいけません。現在の動態でこれらのデータを確認する必要があります。
絶対的な閾値を適用することは、ランダムな非定常的なプロセスの条件下で定義するのが非常に困難な相対振幅値を推定することよりも有望であるように思われます。もちろん、これは大幅な単純化ですが、実際には良い結果が得られます。フラットとトレンドの境界がファジィ論理の対象であるため、それがなければ深刻な問題と複雑な理論計算に直面します。
買いのエントリコードの断片を見てみましょう。
//--- 市場エントリ時に明確なトレンドがないことに伴うリスクの低減 ------- // 短時間枠でのローソク足の方向をシミュレートする: Close[2] > Open[2] && // 履歴の2番目のバーのローソク足が上向き(М1) Close[1] > Open[1] && // 履歴の1つ前のローソク足が上向き(М1) // 長時間枠での移動平均の方向をシミュレートする: MA5_cur > MA5_2p && MA60_cur > MA60_2p && // 上向きМА: 期間5と60の移動平均を使う(М1) // 短時間枠での移動平均の階層をシミュレートする: MA5_cur > MA8_cur && MA8_cur > MA13_cur && // М1に3つのМАの「階層」(フィボー期: 5、8、13)を形成する(上向きの動きの間接的な兆候) // 短時間枠の移動平均を基準に現在の価格の位置をシミュレートする: Bid > MA5_cur && Bid > MA8_cur && Bid > MA13_cur && Bid > MA60_cur && // 現行価格がМ1のМА(5,8,13,60)を上回っている(上向きの動きの間接的な兆候) // 長時間枠でのローソク足の方向をシミュレートする: C_prev_m15 > O_prev_m15 && // 1つ前のローソク足が上向き(М15) // 長時間枠でのMAの方向をシミュレートする: MA4_cur_m15 > MA4_2p_m15 && // 上向きの期間4のМА (М15) // 長時間枠での移動平均の階層をシミュレートする: MA4_prev_m15 > MA8_prev_m15 && // М15に2つのМАの「階層」(期間: 4、8)を形成する(上向きの動きの間接的な兆候) // 長時間枠の移動平均を基準に現在の価格の位置をシミュレートする: Bid > MA4_cur_m15 && // 現行価格がМA4を上回る(M15)(上向きの動きの間接的な兆候) Bid > MA24_cur_h1 && // 現行価格がМA24を上回る(MH1)(上向きの動きの間接的な兆候) // 短時間枠の現在のローソク足内の微小トレンドとエントリポイントをシミュレートする: Bid > Open[0] && // 現在のローソク足の中に上向きの動きが存在する(М1) // 長時間枠で前のプロセスのアクティビティの十分さをシミュレートする: (C_prev_m15 - O_prev_m15) > (0.5*(H_prev_m15 - L_prev_m15)) && // ローソク足の実体の割合がローソク足(以前のМ15ローソク足)の振幅値の50%を超える (H_prev_m15 - C_prev_m15) < (0.25*(H_prev_m15 - L_prev_m15)) && // 修正深度制限がローソク足(以前のМ15ローソク足)の振幅値の25%未満である H_prev_m15 > H_2p_m15 && // 局地的抵抗レベルへの上向きトレンド(2つのМ15ローソク足) O_prev_m15 < H_prev_m15 && O_prev_m15 > L_prev_m15 && // 現在のローソク足の始値に対する髭(1つ前のМ15ローソク足)の存在 // 短時間枠で前のプロセスのアクティビティの十分さをシミュレートする: (Close[1] - Open[1]) > (0.5*(High[1] - Low[1])) && // ローソク足の実体の割合がローソク足(以前のМ1ローソク足)の振幅値の50%を超える (High[1] - Low[1]) > 70*Point && // 1つ前のローソク足の振幅値が閾値1を超えている(明らかなフラットを除く) (High[2] - Close[2]) < (0.25*(High[2] - Low[2])) && // 修正深度制限がローソク足(М1データ履歴の2番目のローソク足)の振幅値の20%未満である High[1] > High[2] && // 局地的抵抗レベルの上向きトレンド(2つのМ1ローソク足) Open[1] < High[1] && Open[1] > Low[1] ) // 現在のローソク足の始値に対する髭(1つ前のМ15ローソク足)の存在
図4 エントリアルゴリズムのモジュール: 市場エントリ時に明確に定義されたトレンドが存在しないことに伴うリスクの低減
記法:
- Open[1]、Close[1] — 1つ前のバーのそれぞれ始値と終値(М1)
- МА5_cur、MA8_cur、MA13_cur、MA60_cur — 現在のバーの5、8、13、60の値に応じたМА値(М1)
- MA4_cur_m15、MA4_prev_m15、MA4_2p_m15 — 気配値履歴でそれぞれ1つ前と2つ目に計算された期間4のМА(М15)
- MA8_prev_m15 — 気配値履歴での1つ前のバーの期間8のМА(М15)
2つの時間枠(M1とM15)で明確に定義されたトレンドを同時にシミュレートすることで、このリスクを低減します。
- ポジションを開く方向の1つ前のローソク足(М1で2つのローソク足とМ15で1つのローソク足)
- MAの方向(М1で2つのМА、М15で1つのMA
- 移動平均の階層(М1で3つのМА、М15で2つのMA)
- MAに対する現行価格の位置( М1で3つのМА)
この「一連の措置」は、ポジションエントリポイントが明確に定義されたトレンドの中にあり、同時に2つの時間枠に入る可能性を大幅に高めます。 したがって、フラット領域や他の不規則な変動および不明瞭なトレンドの領域に当たる確率が減少します。この不利な要因に関連するリスクも同様に低下します。
この例は買い取引のためのものです。売りには、反対のアルゴリズムが使われます。上向きのものの代わりに、ローソク足とМАの下向きの動きが設定されます。 エントリポイントは、指定されたМАより下です。
指標計算期間の誤った選択に伴うリスク
トレーダーは、個人の経験に基づいて、移動平均などの指標期間を設定します。期間200のMAを好む人も、期間を50に設定する人も、フィボナッチ数列に従う人もいます。具体的な指標設定(そして、まず、最も関心のある期間)は直感的に選択されます。
この強制的な直観の理由は、従来の分析方法では特定の瞬間に周波数変調された振動を識別するためのメカニズムが提供されないからです。これによって、指標期間を設定する際には不確実性が生じます。もちろん、適応関数(Kaufman、 FRAMAなど)を構築する方法もありますが、それらのアルゴリズムでは常に変化する市場変動の頻度を考慮していません。
部分解として、MA期間の定義にある論理を加える従来の分析方法を使用します。時間に関連する一定の要因を適用します。この原理に賛成するのは、長時間枠のローソク足の境界は、これらのローソク足が灯心(髭)を有する場合に限って、ローソク足内の動きのフラクタルレベルであるという事実です。髭がなければ、動きはフラクタルを形成することなく次のローソク足に移動することができます。
フィボナッチ数列の標準的な時間枠と数値(大きさが近い)を比較します。その結果、時間枠とMA計算期間の間のおおよその対応が得られます。
- 1分 - 最も近いFibo値1(分、これはピボットです)
- 5分 - 最も近いFibo値5(分)
- 15分 - 最も近いFibo値13(分)
- 1時間(60分) - 最も近いFibo値55(分)
- 4時間(240分) - 最も近いFibo値3(時間)、5(時間)、233(分)
- 1日(24時間) - 最も近いFibo値21(時間)
- 5日(取引週、外国為替市場の場合は120時間) - Fiboに最も近い値は89(時間)と144(時間)
これに加えて、MA遅延を最小化するオプションを推奨できます。
- 1(ピボット)、3、5、8、13の各時間枠で数列の最初の番号のみを使用します。
- 複雑な方法でそれらを使用します。時間枠の比率に等しい比率を使用して、より若い時間枠に変換します。最小期間でМАを使用すると、これらの機能の遅延を減らすことができます。
結果として、異なる時間枠(4つの時間枠を使用する例)のMAの集合が得られます。
- М1: 5、8、13、55(または60 = 1時間)、233(または240 = 4時間)の期間を持つМА
- М15: 5、8、13、55(または60 = 4時間?)の期間を持つМA
- Н1: 5、8、13、21(または24 = 1日)、89、144(または120 = 5日)の期間を持つМА
- D1: 5、8、13、21 (または24 = 1取引月)の期間を持つМА
もちろん、これはMAのサンプルセットに過ぎません。ご自分の値を自由に追加してください。とにかく、MA期間を選択するこの原則は、取引セッションの開始と終了、統計の周期性、配当の支払いなど、多くの要因が明確に定義された周期性を持っているため、存在する権利があります。したがって、指標期間(この場合はMA)を論理的に選択することで、市場事象の頻度を考慮に入れることができ、したがってリスクをある程度低減することができます。
ここでは、他の記述されたモジュールの開発においてMAを選択する上でこれらの勧告を使用します。
市場エントリ時における指値注文の使用に伴うリスク
ここでは、目標レベルを設定するために(成行注文ではなく)指数注文に依存する戦略を意味します。より多くの場合、指数注文は、保合領域からの価格の終了に関連する戦略で使用されます。
このようなさまざまな戦略を使用して、1つの注文が正しく機能することを期待して、保合領域の両側に指値注文のペアを使用する方法について説明し、最初の注文がトリガされた直後に2番目の注文が削除されるようにします。エントリポイントを決定するために指値注文を使用することは、リスクに関連していることに注意してください。指値注文が設定されているレベルは、希望する価格に達する前に常に定義されます。指値注文レベルは、たとえば、保合領域の振幅の%で定義されています。直観的には、これは実際の価格動向とは関係ありません。
事実、エントリの瞬間にマイナス要因の存在下でポジションを開くことができないことは、成行注文のものと比較した指値注文の主な欠点です。目標価格に達した直後に、動態がこの指値注文にとって不利になる可能性がありますが、市場エントリは依然として起こり、損失の原因となります。
したがって、依然として特定の固定レベルから取引したい場合は、標準の指値注文を適用するのではなく、エントリアルゴリズム内で事実上割り当てることがより合理的です。必要な動態が交差したときに検出された場合にのみ、固定レベルを使用して市場にエントリします。これはもちろん、従来の指値注文よりも複雑です。なぜなら、価格が仮想レベルを横切るときに動態を制御するための追加のアルゴリズムが必要であるからです(このようなアルゴリズムを開発するプログラミングスキルも必要です)。しかし、これにより、暗黙のうちに取引を取り除くことが可能になります。これは、従来の指値注文を適用する際には避けられません。
この方法にも欠点があります。価格が必要なレベルに達すると、成行注文(指値注文でない)を使用してエントリします。これは、すでに出された指値注文よりも遅れて証券会社プラットフォームに反映されます。注文が多い場合、注文の優先順位のために実行遅延の確率が高くなります。エントリ時に急激な価格急騰が発生した場合でも、スリッページは可能です。
したがって、指値注文と市場注文の実行遅延リスクを使用して「暗闇の中」に入るリスクを選択する必要があります。同時に、仮想レベルを使用する利点は、定義されたレベルに達したときに市場にエントリするための追加の好条件がない場合、システムが自動的にエントリを取り消すことができることです。
個人的な意見ですが、指値注文を使用するとリスクが増加するため、そのような注文を放棄してリスクを低減する必要があります。これは、とりわけ、市場だけが価格変動の振幅を決定するという事実によって正当化されます。ここでの唯一の目的は、開発の特定の段階でそのような動きを修正し、分析機能を使用してそれらの動きに付随することです。
市場エントリ後の価格変動の不確実性に伴うリスク
多くのトレーダーの典型的な間違いは、特定の目標レベルの定義に過度に依存していることです。価格変動のランダムで非定常的なプロセスを考えると、最終トレンドの振幅は確率値です。上述の指値注文と同様に、固定目標利益レベルを設定すること(すなわち、市場エグジットポイントを定義すること)は直感的です。したがって、このアプローチはしばしば損失を招きます。
市場エグジットアルゴリズムは、減速の兆候(適応機能)を制御する機能または一定のレベル(エントリレベル、ポジション内の現在の高値と安値)に対する固定振幅値を制御する機能のいずれかを特徴とすべきです。また、ポジションと預金全体の両方について、リスク制限コントロールを第2のオプションに追加するでしょう。最後の簡単なバージョンを使用します。コードの断片を見てみましょう。
// 市場エントリ時の価格変動の振幅の不確実性に伴うリスクの低減 // 固定利益値を追跡する(1ポジションあたり) (Bid > OrderOpenPrice() && (Bid - OrderOpenPrice()) >= 100*Point) // 利益領域のエグジット条件(影テイクプロフィット) || // 市場に入った後の現在の最大値から // 利用可能な最大価格偏差を管理する (shift_buy >= 1 && // エントリポイントから1バー以上シフトする Time_cur > OrderOpenTime() && Max_pos > 0 && OrderOpenTime() > 0 && OrderOpenPrice() > 0 && // エントリの後に現在の最大値がある Max_pos > OrderOpenPrice() && // 現在の最大値が利益領域にある Bid < Max_pos && // 価格逆転の動きがある (Max_pos - Bid) >= 200*Point) // 市場エグジットのための現在の最大値からの逆の偏差 || // 事前定義されたリスク限度を追跡する(1ポジションあたり) (Bid < OrderOpenPrice() && (OrderOpenPrice() - Bid) >= 200*Point) // 損失領域でのエントリの条件(影ストップロス) || // 事前定義されたリスク限度を追跡する(1ポジションあたり) (AccountBalance() <= NormalizeDouble( (Depo_first*((100 - Percent_risk_depo)/100)), 0)) ) // 現在の取引中に預金全体のリスク限度額を超えた場合
図5 エグジットアルゴリズムのモジュール: 市場エントリ後の価格変動の振幅の不確実性に伴うリスクの低減
記法:
- OrderOpenPrice() — 市場エントリ価格
- Shift_buy — エントリポイントに対しての(М1のバーで)シフト(ポジションの中で最大値を定義するために必要)
- Max_pos — ポジションの中での最大値
- AccountBalance() — 現在残高(貨幣単位)
- Depo_first — 初期入金(貨幣単位)
- Percent_risk_depo — 入金全体の最大許容損失%
この種のリスクは、以下の機能を使用することで低減されます。
- ポジションあたりの固定利益の管理(実際には「影」テイクプロフィット)
- 市場エントリ後の現在の最大値(買いの場合)または最小値(売りの場合)からの最大許容価格偏差の管理
- ポジションごとの事前に定義されたリスク制限の管理(実際には「影」ストップロス)
- 預金全体に対する事前定義されたリスク制限を管理
これらのすべての場合において、エントリレベル、ポジション内の最大値および初期入金を含む、値を変更することができるレベルに対して、ある振幅値を制御します。したがって、厳密に設定された目標レベルとは異なり、この場合、これらのレベルは固定されていません。
買いポジション決済アルゴリズムでサンプルモジュールを検討しました。売りモジュールの場合、変更は取引方向でのみ発生します。ポジション内の現在の最大値(Max_pos)の代わりに最小値(Min_pos)が使用されます。
次のセクションでは、市場価格が暴落する際に特に重要な価格スピードも考慮に入れたリスクを考慮します。
市場エントリ後の価格の暴落に伴うリスク
局所的トレンド逆転の危険な形態の1つは、短時間に大きな振幅を有する衝突およびスパイクです。対での1つの通貨のジャンプは、常にあと1つの通貨の暴落を意味します。 ポジションがあり、暴落の方向がそれに不利な場合、これは特に危険で、預金が少ない場合、完全に失われる場合があります。
問題の本質
- 価格の暴落では、市場参加者には適切に対応する時間がありません。
- 現代の分析法は、急激な価格の暴落に内在する動的構造を特定するメカニズムを提供できません。
- ポジションがある場合、市場参加者は価格の暴落時に完全に無防備です。主な動きのピークが去った後であったり一連の証券会社や銀行でパニックが起こって市場がブロックされていたりするため、早期に暴落を検出し、それに対応することは非常に困難です。
その結果、市場参加者は大きな損失を被ります。例えば、2010年5月6日、ダウ・ジョーンズ指数は6分で1000ポイント低下しましたが、専門家の見積もりによれば、市場は約1兆ドルの損失となりました。
より最近の例(図6)はBrexitであり、2016年6月24日にGBPUSDの暴落を一度に560ポイントで引き起こしました。1分で473ポイントが失われました。
図6 2014年6月24日のGBPUSD暴落
価格の暴落には3つのグローバルな理由があります。
- 市場そのものの性質: 暴落は何か異質のものではなく、市場の動態の自然な現れです。とりわけ、(例えば、自動売買ロボットを含む市場参加者の数が増加したことによって)市場では価格変動率の急激な変化が引き起こされる可能性があります。 例えば、メディアの報道によると、米国証券市場には、何千もの1秒未満の超高速変動が登録されています。
- 分析法の開発レベル: このような市場の兆候を特定する方法は不完全です。適切な対応を取るには、状況を分単位で分析する能力が必要ですが、2番目の時間枠は市場プラットフォームではまれなものです。
- 金融市場における規制活動の失敗:例えば、マーケットメーカーが実施する人為的価格操作に対処するための法的メカニズムがありません。
MACDに基づくEAがUSDCHF価格の急落にどのように反応するかの例を以下に示します。
図7 MACDに基づいたEAは、2015年10月2日のUSDCHF価格の暴落に対応する時間がない
図7は、EAが価格の暴落前(矢印1)と後(矢印2)に2つのポジションを開くことを示しています。暴落には単に気付かなかったので、反応しませんでした。
したがって、ポジションが開かれている場合、価格の暴落やラリー期間中に預金のかなりの部分を失うリスクがあります。 これは、ポジション決済アルゴリズムに特別な保護モジュールが必要であるということです。
コードの断片を見てみましょう。
if( //-市場エントリ時における価格の暴落に伴うリスクの低減 ----- (Bid < Open[0] && (Open[0] - Bid) >= 100*Point && (Time_cur - Time[0]) <= 20) // 価格暴落中のエグジットの条件(参照点 - 現在のローソク足の始値) || (Bid < O_cur_m15 && (O_cur_m15 - Bid) >= 200*Point && (Time_cur - Time_cur_m15) <= 120) // 価格暴落中のエグジットの条件(参照点 - 現在のM15ローソク足の始値) || ((Time_cur - OrderOpenTime()) > 60 && Close[1] < Open[1] && (Open[1] - Close[1]) >= 200*Point) // 価格暴落中のエグジットの条件(参照点 - 現在のM1ローソク足の振幅) ||
図8 エグジットアルゴリズムのモジュール: 市場エントリ後の価格の暴落に伴うリスクの低減
ポジションを開いた後の価格の暴落に伴うリスクは、以下のように減少します。
- 価格の逆転偏差(暴落)の限界は、現在のローソク足のオープンレベルとは別の時間枠で個別に設定されています(この例ではМ1とМ15)。このような暴落の最大許容期間も同様に定義されています。
- 完成した1つ前のローソク足としての形で最大許容暴落の振幅が設定されます(これは分足であるため、暴落の時間も間接的に指定されます)。
したがって、暴落は、現在のローソク足の始まり(1つ前のローソク足での暴落を使用して)とその発達過程の両方で追跡されます。指定された条件のいずれかが(ORロジックによって)表示されると、そのポジションは決済され、リスクは最小化されます。
この例では買いポジション決済モジュールが示されています。売りポジションの決済には、価格の動きを鏡映的に検討してください。
単一期間の使用に伴うリスク
価格の変更は、異なる時間枠のチャートでは異なって反映されます。より短い時間枠でトレンドに見えるのは、より長い時間帯ではほんのわずかな修正であるかもしれません。
したがって、価格動向は複数の時間枠で分析する必要があります。1つでは十分ではありません。
分析に時間枠をいくつ使用するかは、あなた次第です。個人的には、下記の4つの時間枠を同時に使用します(4つの画面で)。
- М1: この時間枠は、トレンド逆転(グローバルなものを含む)と市場の高速暴落を示すのに優れています。
- М15: チャートのこの時間枠のローソク足は、しばしば、より短い時間枠(М1およびМ5)で形成される、市場の高速暴落の完成した動的構造を反映します。
- Н1: この時間枠のローソク足は、自然な時間制限(取引セッションスケジュール、マクロ経済指数の発表、ニュースなどを含む)です。
- D1: この時間枠のローソク足は自然なリミッターです(1週間以内の取引日を含みます)。
私は、これらの時間枠は市場の動態を正確に分析するための効率的なセットを形成すると信じています。もちろん、価格変動の「容積的」な認識の経験が必要ですが、これは金融市場で働く際に不可欠です。
取引のリスクは単一の時間枠を使用することによって必然的に増大するため、エントリアルゴリズムのコードはローソク足、MAおよび他の指標をいくつかの時間枠に関連して分析するべきです。
単一タイプの分析(テクニカルまたはファンダメンタル)の使用に伴うリスク
価格の変動は多くの要因の影響を受けます。市場は、参加者の経済的利益に基づく行動システムです。テクニカル分析(取引ロボットのベースとなる)は、特定の金融商品の価格という1種類のデータのみを使用します。そして、ファンダメンタル分析では、1種類のデータ(特定のマクロ経済要因など)のみを考慮します。明らかに、そのような分析は不完全で片面であり、従って不正確です。価格変動の要因を考察せずに価格だけを分析したり、価格の実際の動力学を考察せずにファンダメンタルの指標にのみ焦点を当てるのは間違いでしょう。
両方のタイプの分析は論理的にお互いを補完するので、それらを組み合わせる方が合理的です。一般的に、ファンダメンタル要素(ただし絶対的なものではない)は、価格変動方向を決定し、テクニカル要素はそれを確認します。しかし、テクニカル要素に比してファンダメンタル要素の優位性は絶対的なものではありません。
時には、市場は、例えば歴史的な高値に達するなど、ファンダメンタル要素よりもテクニカル要素に多く反応します。これについての顕著な例は、歴史的な高さに達した直後のビットコインの周期的な暴落(ときどき1日あたり20%)です。しかし、仮想通貨のファンダメンタル分析は市場特質によって問題があるため、ビットコインを用いた例は完全には良い例ではありません。
しかし、外国為替市場、特に株式市場の場合、ファンダメンタル分析の影響は明らかです。例えば、2015年10月の USDCHFの暴落は、スイス銀行がユーロからのCHF金利を「引き上げる」ことによって誘発されました。
したがって、私は、分析タイプの1つの優先順位を定義し、それを代わりに使用することには意味がないと考えています。しかしながら、取引システムのアルゴリズムがテクニカルな市場パラメータのみを適用することを考慮すると、ファンダメンタル分析を自動取引にどのように使用することができるのかという疑問があります。
ファンダメンタル分析をTSに埋め込むための2つの選択肢を提案します。
- 選択肢1: TSアルゴリズムでファンダメンタル分析パラメータをテクニカル分析のものに変換します(たとえば、アクションロジックを定義した後に経済カレンダーのデータを入力します)。
- 選択肢2: エキスパートアドバイザーの市場エントリ方向を手動で制限する(ファンダメンタルパラメータに対応する方向のみ)。
ご覧の通り、アルゴリズムのファンダメンタル分析は不便ですが、正しい方法です。両方の方法を手動取引で組み合わせて適用する方が簡単です。初心者のアナリストやトレーダーはこのために努力すべきです。
市場の動態に関連しないリスク
運用、財務、法などの外部要因も取引プロセスの一部で、リスクの発生に同様に重要な役割を果たします。したがって、取引システムを開発する際には、可能な限りそれらを考慮する必要があります。
リストを定義しましょう。
市場の動態に関連しないリスクの分類
下記は価格動向に関連しない可能なリスクのうち最も一般的なものです。
- 取引システムの構造に伴うリスク
- 預金の損失限度超過に伴うリスク(預金による投資家のリスク限度の管理)
- 取引条件のマイナスの変化に伴うリスク
- 証券会社の取引サーバーへの接続の品質によるリスク
- 証券会社側とクライアント側の自動取引許可に伴うリスク
- 金融市場法制の変更に伴うリスク
これらのリスクとその低減方法を詳しく見てみましょう。
取引システムの構造に伴うリスク
主なルールは、取引システムの構造はリスクの構造を考慮する必要があるということです。上記で考慮される可能性のある最大限のリスクに対する防御を含めるべきです。これにより、取引効率が向上します。
しかし、リスクを避ける方法は実際にはフィルタであるため、リスクを最小限に抑えるためにブロック数を増やすと必然的にフィルタの数が増えます。その結果、自動売買ロボットの入力アルゴリズムの「オーバーフィルタリング」に直面します。同時に、ほとんどのトレーダーは、ロボットが積極的に取引を行い、少なくとも毎日ポジションを開いていくと考えています。この意味で、トレーダーはロボットの顧客として行動し、そのような要件は彼らの側からはかなり論理的に見えます。しかし、私は、これはプロセスの性質上正しくないと信じています。
EAアルゴリズムはどれでも、非常に複雑な動的プロセスをシミュレートし、必然的にそれらを単純化します。エラーは、特定のEAのモデルが市場の動態に完全に一致しないことに関連しています。
開発者は、取引システムのエントリ数とエントリアルゴリズムにおけるフィルタリングの量との間に関係があることを知っています。フィルタリングの量が多いほど、エントリの数は少なくなり、その逆もあります。一般に、フィルタリングが増加すると、取引結果が向上します。しかしもちろん、それはすべてフィルタの内容に依存します。エントリ数と取引結果の間、またはより正確には各取引システムの最大リスク(預金引出し)を妥協する必要があります。これを従来の最適化と呼びます。
しかし、フィルタリングとは何でしょうか。
スペクトル全体から有用な信号を割り当てることを意味するのなら、その有用性の明確な基準が必要です。従来の分析ではこれを提供することはできません。従来の指標の活性化は、価格変動などの複雑なプロセスの「正確な」フィルタリングとは言いがたいものです。たとえば、エリオット波構造やテクニカル分析分析パターンを適用して有用なシグナルを見つけた場合、各トレーダが同じチャート上で異なって決定するため、解析に適していないことがわかります。
したがって、取引システム構造は、これらのリスクが決定するパラメータの重要な値を整理することによって、リスクを低減すべきです。しかし、リスクは多数あり、フィルタリングの程度はその量とともに増加します。したがって、個々のEAの効率を評価する場合、主なものはエントリ数ではなく、許容可能なリスク(ドローダウン)を伴う安定した(低いながらも)利益です。この場合、エントリ数(単一の金融商品でテストする場合)はあまりないかもしれません。利益は、複数の通貨ペアで同時に取引することで増やすことができます。
したがってこれが結論です。
開かれるポジションの数は、EAの品質を評価する際の第2の要因です。主なものは、利益を上げるときの相対的な安定性です。
取引システムの効率性は、いくつかの金融商品で評価されるべきです。これにより、シミュレーションの品質と最終的な結果が向上します。
- TSは市場動態の様々な現れでテストされます。
- いくつかの商品について肯定的な結果が得られた場合、預金の総利益は伸び、投資家の利益への要求を満たします。
したがって、TSの最適化は、いくつかの金融商品でテストされたときに利益を示すような設定の選択に減らされるべきです。
預金の損失限度超過に伴うリスク
取引前であっても、預金のリスクには限度を設定する必要があります。限度は、固定(絶対的)または相対的(初期預金合計の%)金額で指定できます。達成後、取引は停止します。
より経験豊富なトレーダーに口座の管理を依頼する場合は、契約でリスク限度を設定してください。
自分で取引する場合は、エントリアルゴリズム(リスク限度を超えた場合はエントリを無効にする)とエグジットアルゴリズムにコードを追加する必要があります(これについては、「市場えんとり後の価格変動の不確実性に伴うリスク」のセクションで前述しました)。デポジットの二重管理は、開かれたポジションがあるときに最初にデポジットのリスク限度額が達成されるためです(これは市場エグジットアルゴリズムで修正されています)。その後、デポジットのリスク限度額はすでに達成されているため、後続のエントリを無効にする必要があります(これは、市場エントリアルゴリズムの前のモジュールで修正されています)。
コードの断片を見てみましょう。
// 顧客の預金に対する総リスクを制限する金融パラメータを管理する if(kol < 1) // 注文なし { if(AccountBalance() <= NormalizeDouble( (Depo_first*((100 - Percent_risk_depo)/100)), 0))// 以前に預金全体のリスク限度額を超えた場合 { Print("Entry disabled-risk limit reached earlier=",Percent_risk_depo, " % for the entire deposit=", Depo_first); Alert("Entry disabled-risk limit reached earlier=",Percent_risk_depo, " % for the entire deposit=", Depo_first); return; } if(AccountFreeMargin() < (1000*Lots)) // 現在の預金口座で注文を出すための証拠金額が不十分な場合 { Print("Insufficient margin funds. Free account margin = ",AccountFreeMargin()); Alert("Insufficient margin funds. Free account margin = ",AccountFreeMargin()); return; //...終了する } } //--------------
図9 エントリアルゴリズムの前のモジュール: 預金の損失限度額超過に伴うリスクの低減
最初のブロックは、クライアントの入金ステータスを管理します(AccountBalance())。カスタマイズ可能な変数:
- Depo_first — 初期入金(貨幣単位)
- Percent_risk_depo — デポジットによる損失限度額(初期値の%)
デポジットの損失がPercent_risk_depo変数に設定された値に達すると、アルゴリズムがトリガされます。同時に、市場エントリは無効になり、プログラムが終了します。
2番目のブロックは、市場エントリが許可されている口座の証拠金を管理します。このアルゴリズムは、余裕量が特定のロット数を下回ったときにトリガされます。市場エントリは無効になり、プログラムが終了します。
不利な取引条件に伴うリスク
ポジションを開閉するときのスプレッドの拡張、注文実行時の価格スリッページ、注文実行遅延は証券会社によって提供される気配値の品質です。
このすべてが取引の結果(預金の総損失まで)に強く影響するため、関連するパラメータを監視する必要があります。特に、価格、スプレッド、エントリ、およびエグジットアルゴリズムのトリガ時間の値を自動的に追跡し、それらを実際のポジション開閉時の値と比較しなければなりません。
そのようなモジュールは自分の取引システムで開発することができます。
証券会社の取引サーバへの接続の品質によるリスク
取引サーバへの接続の質は、2つの要因によって決まります。
- 証券会社側の取引サーバの状態
- クライアント側のインターネット接続
第2の要因は、クライアント端末を外部サーバに置くことによって排除することができます。最初の要素は、TSアルゴリズムにコードを追加することによってプログラムで検証されます。
コードの断片を見てみましょう。
if(IsConnected() == false) // クライアント端末と証券会社サーバとのメイン接続を確認する { Print("Entry disabled-broker's server offline"); Alert("Entry disabled-broker's server offline"); return; }
図10 証券会社の取引サーバとの接続品質によるリスクを低減するモジュール
図10は、証券会社のサーバへの接続を監視することを可能にするコード断片を示します。これは、エントリアルゴリズムの前にEAに組み込まれる必要があります。これらの条件が発生すると、ポジションを開くことができなくなります。
証券会社側とクライアント側の自動取引許可に伴うリスク
場合によっては、TSはクライアント端末に注文を送信するが、注文は実行されません。しかし、TS自身が取引を制限することはできません。下記は考えられる理由です。
- クライアント側のクライアント端末の設定で自動取引が無効になっている
- 現在の口座での取引が証券会社によって無効にされている
これらのリスクを排除するためには、取引システムプログラムで自動取引を許可するかどうかを制御する必要があります。
コードの断片を見てみましょう。
if(IsTradeAllowed() == false) EA(証券会社の流れ、取引許可)を使って取引する能力を確認する { Print("Entry disabled-broker's trading flow busy and/or the robot has no permission to trade :", IsTradeAllowed()); Alert("Entry disabled-broker's trading flow busy and/or the robot has no permission to trade :", IsTradeAllowed()); return; } if( !AccountInfoInteger(ACCOUNT_TRADE_EXPERT) ) // 取引口座プロパティを確認する { Print("Automated trading disabled for the account :", AccountInfoInteger(ACCOUNT_LOGIN), "on trade server side"); Alert("Automated trading disabled for the account :", AccountInfoInteger(ACCOUNT_LOGIN), "on trade server side"); return; } if(IsExpertEnabled() == false) // クライアント端末でEAの起動が許可されているかどうかを確認する { Print("Entry disabled- robot's trading permission disabled in the terminal :", IsExpertEnabled()); Alert("Entry disabled- robot's trading permission disabled in the terminal :", IsExpertEnabled()); return; } if(IsStopped() == true) // mql4プログラムの実行を完了するコマンドの到着を確認する { Print("Entry disabled-command to complete mql4 program execution triggered"); Alert("Entry disabled-command to complete mql4 program execution triggered"); return; }
図11 証券会社側とクライアント側の自動取引の許可に伴うリスクを低減するためのモジュール
上記のコードの断片は、証券会社とクライアントの両方で自動取引の権限の状態を制御します。これらの条件が満たされると、市場エントリは無効になります。
金融市場法制の変更に伴うリスク
これらは、顧客のリスクに直接的または間接的に影響を及ぼす金融市場業界の関係についてのルールです。様々な国が株式市場や金融市場における関係を規制する立法を展開しています。将来的には、さまざまな違反に関連した多くのリスクが減少するはずです。
前述のリスクのいくつかを考慮したサンプルEA
私たちは市場動向に関連しているリスクとしていないリスクを特定し、調査しました。また、それらを減らすための具体的な解決方法を定義しました。
リスクはEAに特定のモジュールを挿入することによって低減されます(エントリアルゴリズムの前、また、エントリアルゴリズムとエグジットアルゴリズムの前に)。各モジュールは特定の種類のリスクを管理します。
主要な分析要素は、異なる時間枠のローソク足です。ローソク足の内部(単一構造分析)およびそれらの間(構造群分析)の両方で動態を分析します。
以下は、上記のリスクを低減するためのソリューションを備えたシンプルなEAのコードです。上記の制限を考慮して、従来のすべての指標から移動平均のみを適用していることに注意してください。
下記は5桁の気配値(またはUSDJPYの3桁)のEAコードです。
//+------------------------------------------------------------------+ //| Reduce_risks.mq4 | //| Copyright 2017, Alexander Masterskikh | //| | //+------------------------------------------------------------------+ #property copyright "2017, Alexander Masterskikh" #property link "https://www.mql5.com/ja/users/a.masterskikh" input double TakeProfit = 600; // 指値 input double StopLoss = 300; // 逆指値 input double Lots = 1; // ロット数 input int Depo_first = 10000; // 顧客の初期入金(貨幣単位) input int Percent_risk_depo = 5; // 入金当りの最大許容リスク(顧客の初期入金に対する%単位) input bool test = false; // テストでtrueに設定(デフォルトはfalse) //------------------------------------------------------------------------------------------------- void OnTick(void) { //---変数を定義する--- int f,numb,kol; double sl_buy, tp_buy, sl_sell, tp_sell; double L_prev_m15, L_2p_m15, L_3p_m15; double H_prev_m15, H_2p_m15, H_3p_m15; double O_cur_m15, O_prev_m15, O_2p_m15, C_prev_m15, C_2p_m15; double MA4_cur_m15, MA4_prev_m15, MA4_2p_m15, MA5_prev_m15, MA8_cur_m15, MA8_prev_m15, MA8_2p_m15; double MA8_cur, MA8_prev, MA8_2p, MA8_3p, MA5_cur, MA5_prev, MA5_2p, MA13_cur, MA13_prev, MA13_2p, MA60_cur, MA60_prev, MA60_2p, MA24_cur_h1; double C_prev_h1, O_prev_h1, H_prev_h1, L_prev_h1, H_2p_h1, L_2p_h1; datetime Time_cur, Time_cur_m15; double shift_buy, shift_sell; double Max_pos, Min_pos; //-------- // 技術的パラメータの管理(状態と許可) - 証券会社端末側とクライアント端末側------------------------------- if(test==false) // テストか取引かを確認する(テスト - true、取引 - false) {// 履歴データをテストするときに確認されないパラメータ --- if(IsConnected() == false) // クライアント端末と証券会社サーバとのメイン接続の状態を確認する { Print("Entry disabled-broker server offline"); Alert("Entry disabled-broker server offline"); return; } if(IsTradeAllowed() == false) // EAを使って取引する能力を確認する(証券会社フロー、取引許可) { Print("Entry disabled-broker trade flow busy and/or EA trading permission disabled :", IsTradeAllowed()); Alert("Entry disabled-broker trade flow busy and/or EA trading permission disabled :", IsTradeAllowed()); return; } if( !AccountInfoInteger(ACCOUNT_TRADE_EXPERT) ) // 取引口座プロパティを確認する { Print("Auto trading disabled for account :", AccountInfoInteger(ACCOUNT_LOGIN), "on trade server side"); Alert("Auto trading disabled for account :", AccountInfoInteger(ACCOUNT_LOGIN), "on trade server side"); return; } if(IsExpertEnabled() == false) // クライアント端末でEAの起動が許可されているかどうかを確認する { Print("Entry disabled- robot's trading permission disabled in the terminal :", IsExpertEnabled()); Alert("Entry disabled- robot's trading permission disabled in the terminal :", IsExpertEnabled()); return; } if(IsStopped() == true) // mql4プログラムの実行を完了するコマンドの到着を確認する { Print("Entry disabled-command to complete mql4 program execution triggered"); Alert("Entry disabled-command to complete mql4 program execution triggered"); return; } } // 履歴データをテストするときに確認されないパラメータはここで終わる // 使用されている銘柄によって、端末に十分な数の気配値が存在するかどうかを管理する --- if(Bars<100) { Print("insufficient number of bars on the current chart"); return; } // EAの必要な時間枠への配置を管理する ---- if(Period() != PERIOD_M1) { Print("EA placed incorrectly, place EA on tf :", PERIOD_M1); Alert("EA placed incorrectly, place EA on tf :", PERIOD_M1); return; } // EAの必要な金融商品への配置を管理する ---- if(Symbol() != "EURUSD" && Symbol() != "USDCHF" && Symbol() != "USDJPY") { Print("EA placed incorrectly-invalid financial instrument"); Alert("EA placed incorrectly-invalid financial instrument"); return; } //---------- // 顧客の預金に対する総リスクを制限する金融パラメータを管理する if(kol < 1) // 注文なし { if(AccountBalance() <= NormalizeDouble( (Depo_first*((100 - Percent_risk_depo)/100)), 0))// 以前に預金全体のリスク限度額を超えた場合 { Print("Entry disabled-risk limit reached earlier=",Percent_risk_depo, " % for the entire deposit=", Depo_first); Alert("Entry disabled-risk limit reached earlier=",Percent_risk_depo, " % for the entire deposit=", Depo_first); return; } if(AccountFreeMargin() < (1000*Lots)) // 現在の預金口座で注文を出すための証拠金額が不十分な場合 { Print("Insufficient margin funds. Free account margin = ",AccountFreeMargin()); Alert("Insufficient margin funds. Free account margin = ",AccountFreeMargin()); return; //...終了する } } //-------------- // 変数値: L_prev_m15 = iLow(NULL,PERIOD_M15,1); L_2p_m15 = iLow(NULL,PERIOD_M15,2); L_3p_m15 = iLow(NULL,PERIOD_M15,3); H_prev_m15 = iHigh(NULL,PERIOD_M15,1); H_2p_m15 = iHigh(NULL,PERIOD_M15,2); H_3p_m15 = iHigh(NULL,PERIOD_M15,3); O_cur_m15 = iOpen(NULL,PERIOD_M15,0); O_prev_m15 = iOpen(NULL,PERIOD_M15,1); O_2p_m15 = iOpen(NULL,PERIOD_M15,2); C_prev_m15 = iClose(NULL,PERIOD_M15,1); C_2p_m15 = iClose(NULL,PERIOD_M15,2); Time_cur_m15 = iTime(NULL,PERIOD_M15,0); C_prev_h1 = iClose(NULL,PERIOD_H1,1); O_prev_h1 = iOpen(NULL,PERIOD_H1,1); H_prev_h1 = iHigh(NULL,PERIOD_H1,1); L_prev_h1 = iLow(NULL,PERIOD_H1,1); H_2p_h1 = iHigh(NULL,PERIOD_H1,2); L_2p_h1 = iLow(NULL,PERIOD_H1,2); MA4_cur_m15 = iMA(NULL,PERIOD_M15,4,0,MODE_SMA,PRICE_TYPICAL,0); MA4_prev_m15 = iMA(NULL,PERIOD_M15,4,0,MODE_SMA,PRICE_TYPICAL,1); MA4_2p_m15 = iMA(NULL,PERIOD_M15,4,0,MODE_SMA,PRICE_TYPICAL,2); MA5_prev_m15 = iMA(NULL,PERIOD_M15,5,0,MODE_SMA,PRICE_TYPICAL,1); MA8_cur_m15 = iMA(NULL,PERIOD_M15,8,0,MODE_SMA,PRICE_TYPICAL,0); MA8_prev_m15 = iMA(NULL,PERIOD_M15,8,0,MODE_SMA,PRICE_TYPICAL,1); MA8_2p_m15 = iMA(NULL,PERIOD_M15,8,0,MODE_SMA,PRICE_TYPICAL,2); MA8_cur = iMA(NULL,PERIOD_M1,8,0,MODE_SMA,PRICE_TYPICAL,0); MA8_prev = iMA(NULL,PERIOD_M1,8,0,MODE_SMA,PRICE_TYPICAL,1); MA8_2p = iMA(NULL,PERIOD_M1,8,0,MODE_SMA,PRICE_TYPICAL,2); MA8_3p = iMA(NULL,PERIOD_M1,8,0,MODE_SMA,PRICE_TYPICAL,3); MA5_cur = iMA(NULL,PERIOD_M1,5,0,MODE_SMA,PRICE_TYPICAL,0); MA5_prev = iMA(NULL,PERIOD_M1,5,0,MODE_SMA,PRICE_TYPICAL,1); MA5_2p = iMA(NULL,PERIOD_M1,5,0,MODE_SMA,PRICE_TYPICAL,2); MA13_cur = iMA(NULL,PERIOD_M1,13,0,MODE_SMA,PRICE_TYPICAL,0); MA13_prev = iMA(NULL,PERIOD_M1,13,0,MODE_SMA,PRICE_TYPICAL,1); MA13_2p = iMA(NULL,PERIOD_M1,13,0,MODE_SMA,PRICE_TYPICAL,2); MA60_cur = iMA(NULL,PERIOD_M1,60,0,MODE_SMA,PRICE_TYPICAL,0); MA60_prev = iMA(NULL,PERIOD_M1,60,0,MODE_SMA,PRICE_TYPICAL,1); MA60_2p = iMA(NULL,PERIOD_M1,60,0,MODE_SMA,PRICE_TYPICAL,2); MA24_cur_h1 = iMA(NULL,PERIOD_H1,24,0,MODE_SMA,PRICE_TYPICAL,0); kol = OrdersTotal(); Time_cur = TimeCurrent(); if(kol < 1) // 注文がない場合は続ける { //--- 市場エントリアルゴリズム - 買 ------------------------------------------------------------------------------------------- if( //----市場エントリ時の高ボラティリティに伴うリスクの低減 ---- // 最近の履歴において高ボラティリティがないことをシミュレートする: ( High[1] - Low[1]) <= 200*Point && // 短時間枠(М1)の振幅を制限する ( High[2] - Low[2]) <= 200*Point && ( High[3] - Low[3]) <= 200*Point && (H_prev_m15 - L_prev_m15) <= 300*Point && // 長時間枠(М15)の振幅を制限する (H_2p_m15 - L_2p_m15) <= 300*Point && (H_3p_m15 - L_3p_m15) <= 300*Point && (H_prev_m15 - L_3p_m15) <= 300*Point && // 長時間枠(М15)ローソク足で作られたチャネルの振幅を制限する (High[1] - Low[1]) >= (1.1*(High[2] - Low[2])) && // 気配値履歴の2番目のバーに対する前のバーのアクティビティを制限する (High[1] - Low[1]) < (3.0*(High[2] - Low[2])) && // 同じ //---- 市場エントリ時における抵抗レベルの存在に伴うリスクの低減 ----- // 現在の価格で局地的抵抗レベルが壊れている場合をシミュレートする: Bid > High[1] && // М1 Bid > H_prev_m15 && // М15 //--- 市場エントリ時に買われ過ぎ領域に入り込むリスクの低減 ----- // 買われ過ぎ領域にエントリする確率を減少させるために波の開始点への結合をシミュレートする: ((MA8_prev > Low[1] && MA8_prev < High[1]) || (MA8_2p > Low[2] && MA8_2p < High[2]) || // 波の初め - データ履歴(М1)の3つのバーよりも遠くない (MA8_3p > Low[3] && MA8_3p < High[3])) && // 同じ MA5_prev_m15 > L_prev_m15 && MA5_prev_m15 < H_prev_m15 && // 波の初め - 長時間枠(М15)の1つ前のバー //--- 市場エントリ時に明確なトレンドがないことに伴うリスクの低減 ------- // 短時間枠でのローソク足の方向をシミュレートする: Close[2] > Open[2] && // 履歴の2番目のバーのローソク足が上向き(М1) Close[1] > Open[1] && // 履歴の1つ前のローソク足が上向き(М1) // 長時間枠での移動平均の方向をシミュレートする: MA5_cur > MA5_2p && MA60_cur > MA60_2p && // 上向きМА: 期間5と60の移動平均を使う(М1) // 短時間枠での移動平均の階層をシミュレートする: MA5_cur > MA8_cur && MA8_cur > MA13_cur && // М1に3つのМАの「階層」(フィボー期: 5、8、13)を形成する(上向きの動きの間接的な兆候) // 短時間枠の移動平均を基準に現在の価格の位置をシミュレートする: Bid > MA5_cur && Bid > MA8_cur && Bid > MA13_cur && Bid > MA60_cur && // 現行価格がМ1のМА(5,8,13,60)を上回っている(上向きの動きの間接的な兆候) // 長時間枠でのローソク足の方向をシミュレートする: C_prev_m15 > O_prev_m15 && // 1つ前のローソク足が上向き(М15) // 長時間枠でのMAの方向をシミュレートする: MA4_cur_m15 > MA4_2p_m15 && // 上向きの期間4のМА (М15) // 長時間枠での移動平均の階層をシミュレートする: MA4_prev_m15 > MA8_prev_m15 && // М15に2つのМАの「階層」(期間: 4、8)を形成する(上向きの動きの間接的な兆候) // 長時間枠の移動平均を基準に現在の価格の位置をシミュレートする: Bid > MA4_cur_m15 && // 現行価格がМA4を上回る(M15)(上向きの動きの間接的な兆候) Bid > MA24_cur_h1 && // 現行価格がМA24を上回る(MH1)(上向きの動きの間接的な兆候) // 短時間枠の現在のローソク足内の微小トレンドとエントリポイントをシミュレートする: Bid > Open[0] && // 現在のローソク足の中に上向きの動きが存在する(М1) // 長時間枠で前のプロセスのアクティビティの十分さをシミュレートする: (C_prev_m15 - O_prev_m15) > (0.5*(H_prev_m15 - L_prev_m15)) && // ローソク足の実体の割合がローソク足(以前のМ15ローソク足)の振幅値の50%を超える (H_prev_m15 - C_prev_m15) < (0.25*(H_prev_m15 - L_prev_m15)) && // 修正深度制限がローソク足(以前のМ15ローソク足)の振幅値の25%未満である H_prev_m15 > H_2p_m15 && // 局地的抵抗レベルへの上向きトレンド(2つのМ15ローソク足) O_prev_m15 < H_prev_m15 && O_prev_m15 > L_prev_m15 && // 現在のローソク足の始値に対する髭(1つ前のМ15ローソク足)の存在 // 短時間枠で前のプロセスのアクティビティの十分さをシミュレートする: (Close[1] - Open[1]) > (0.5*(High[1] - Low[1])) && // ローソク足の実体の割合がローソク足(以前のМ1ローソク足)の振幅値の50%を超える (High[1] - Low[1]) > 70*Point && // 1つ前のローソク足の振幅値が閾値1を超えている(明らかなフラットを除く) (High[2] - Close[2]) < (0.25*(High[2] - Low[2])) && // 修正深度制限がローソク足(М1データ履歴の2番目のローソク足)の振幅値の20%未満である High[1] > High[2] && // 局地的抵抗レベルの上向きトレンド(2つのМ1ローソク足) Open[1] < High[1] && Open[1] > Low[1] ) // 現在のローソク足の始値に対する髭(1つ前のМ15ローソク足)の存在 { // 上記で指定した買いエントリアルゴリズム条件が満たされている場合は、買いエントリ注文を生成する sl_buy = NormalizeDouble((Bid-StopLoss*Point),Digits); tp_buy = NormalizeDouble((Ask+TakeProfit*Point),Digits); numb = OrderSend(Symbol(),OP_BUY,Lots,Ask,3,sl_buy,tp_buy,"Reduce_risks",16384,0,Green); if(numb > 0) { if(OrderSelect(numb,SELECT_BY_TICKET,MODE_TRADES)) { Print("Buy entry : ",OrderOpenPrice()); } } else Print("Error when opening Buy order : ",GetLastError()); return; } //--- 市場エントリアルゴリズム - 売 -------------------------------------------------------------------------------------------------- if( //----市場エントリ時の高ボラティリティに伴うリスクの低減 ---- // 最近の履歴において高ボラティリティがないことをシミュレートする: ( High[1] - Low[1]) <= 200*Point && // 短時間枠(М1)の振幅を制限する ( High[2] - Low[2]) <= 200*Point && ( High[3] - Low[3]) <= 200*Point && (H_prev_m15 - L_prev_m15) <= 300*Point && // 長時間枠(М15)の振幅を制限する (H_2p_m15 - L_2p_m15) <= 300*Point && (H_3p_m15 - L_3p_m15) <= 300*Point && (H_prev_m15 - L_3p_m15) <= 300*Point && // 長時間枠(М15)ローソク足で作られたチャネルの振幅を制限する (High[1] - Low[1]) >= (1.1*(High[2] - Low[2])) && // 気配値履歴の2番目のバーに対する前のバーのアクティビティを制限する (High[1] - Low[1]) < (3.0*(High[2] - Low[2])) && // 同じ //---- 市場エントリ時における抵抗レベルの存在に伴うリスクの低減 ----- // 現在の価格で局地的抵抗レベルが壊れている場合をシミュレートする: Bid < Low[1] && // М1 Bid < L_prev_m15 && // М15 //--- 市場エントリ時に売られ過ぎ領域に入り込むリスクの低減 ----- // 売られ過ぎ領域にエントリする確率を減少させるために波の開始点への結合をシミュレートする: ((MA8_prev > Low[1] && MA8_prev < High[1]) || (MA8_2p > Low[2] && MA8_2p < High[2]) || // 波の初め - データ履歴(М1)の3つのバーよりも遠くない (MA8_3p > Low[3] && MA8_3p < High[3])) && // 同じ MA5_prev_m15 > L_prev_m15 && MA5_prev_m15 < H_prev_m15 && // 波の初め - 長時間枠(М15)の1つ前のバー //--- 市場エントリ時に明確なトレンドがないことに伴うリスクの低減 ------- // 短時間枠でのローソク足の方向をシミュレートする: Close[2] < Open[2] && // 履歴の2番目のバーのローソク足が下向き(М1) Close[1] < Open[1] && // 履歴の1つ前のローソク足が下向き(М1) // 短時間枠での移動平均の方向をシミュレートする: MA5_cur < MA5_2p && MA60_cur < MA60_2p && // 下向きМА: 期間5と60の移動平均を使う(М1) // 短時間枠での移動平均の階層をシミュレートする: MA5_cur < MA8_cur && MA8_cur < MA13_cur && // М1(フィボー期: 5、8、13)に3つのМАの「階層」を形成する(下降の間接的な兆候) // 短時間枠の移動平均を基準に現在の価格の位置をシミュレートする: Bid < MA5_cur && Bid < MA8_cur && Bid < MA13_cur && Bid < MA60_cur && // 現行価格がМ1のМА(5,8,13,60)を上回っている(下降の間接的な兆候) // 長時間枠でのローソク足の方向をシミュレートする: C_prev_m15 < O_prev_m15 && //1つ前のローソク足が下向き (М15) // 長時間枠でのローソク足の方向をシミュレートする: MA4_cur_m15 < MA4_2p_m15 && // 1つ前のローソク足が下向き (М15) // 長時間枠でのMAの方向をシミュレートする: MA4_prev_m15 < MA8_prev_m15 && // М1に2つのМАの「階層」(期間: 4、8)を形成する(下降の間接的な兆候) // 長時間枠の移動平均を基準に現在の価格の位置をシミュレートする: Bid < MA4_cur_m15 && // 現行価格がМA4を下回る(M15)(下降の間接的な兆候) Bid < MA24_cur_h1 && // 現行価格がМA24を下回る(MH1)(下降の間接的な兆候) // 短時間枠の現在のローソク足内の微小トレンドとエントリポイントをシミュレートする: Bid < Open[0] && // 現在のローソク足の中に下向きの動きが存在する (М1) // 長時間枠で前のプロセスのアクティビティの十分さをシミュレートする: (O_prev_m15 - C_prev_m15) > (0.5*(H_prev_m15 - L_prev_m15)) && // ローソク足の実体の割合がローソク足(以前のМ15ローソク足)の振幅値の50%を超える (C_prev_m15 - L_prev_m15) < (0.25*(H_prev_m15 - L_prev_m15)) && // 修正深度制限がローソク足(以前のМ15ローソク足)の振幅値の25%未満である L_prev_m15 < L_2p_m15 && // 局地的抵抗レベルへの上向きトレンド(2つのМ15ローソク足) O_prev_m15 < H_prev_m15 && O_prev_m15 > L_prev_m15 && // 現在のローソク足の始値に対する髭(1つ前のМ15ローソク足)の存在 // 短時間枠で前のプロセスのアクティビティの十分さをシミュレートする: (Open[1] - Close[1]) > (0.5*(High[1] - Low[1])) && // ローソク足の実体の割合がローソク足(以前のМ1ローソク足)の振幅値の50%を超える (High[1] - Low[1]) > 70*Point && // 1つ前のローソク足の振幅値が閾値1を超えている(明らかなフラットを除く) (Close[2] - Low[2]) < (0.25*(High[2] - Low[2])) && //修正深度制限がローソク足(М1データ履歴の2番目のローソク足)の振幅値の20%未満である Low[1] < Low[2] && // 局地的抵抗レベルの下向きトレンド(2つのМ1ローソク足) Open[1] < High[1] && Open[1] > Low[1] ) // 現在のローソク足の始値に対する髭(1つ前のМ1ローソク足)の存在 { // 上記で指定した売り エントリアルゴリズム条件が満たされている場合は、売りエントリ注文を生成する sl_sell = NormalizeDouble((Ask+StopLoss*Point),Digits); tp_sell = NormalizeDouble((Bid-TakeProfit*Point),Digits); numb = OrderSend(Symbol(),OP_SELL,Lots,Bid,3,sl_sell,tp_sell,"Reduce_risks",16384,0,Red); if(numb > 0) { if(OrderSelect(numb,SELECT_BY_TICKET,MODE_TRADES)) { Print("Sell entry : ",OrderOpenPrice()); } } else Print("Error when opening Sell order : ",GetLastError()); } //--- 市場エントリアルゴリズム( 売買)はここで終わる return; } / ---ポジション決済を準備するために未決注文と金融商品銘柄を確認する for(f=0; f < kol; f++) { if(!OrderSelect(f,SELECT_BY_POS,MODE_TRADES)) continue; if(OrderType()<=OP_SELL && // 注文の種類を確認する OrderSymbol()==Symbol()) // 銘柄を確認する { if(OrderType()==OP_BUY) // 買い注文の場合、買いポジションを決済する { //------買いポジション決済アルゴリズム------------------------------------------------------------------------------------------------- // ポジション内で価格の最大値を検索するモジュール-------------- // 最初に、ポジションの中の現在のポイントから市場へのエントリポイントまでの距離を定義する shift_buy = 0; if(Time_cur > OrderOpenTime() && OrderOpenTime() > 0) // 現在の時刻がエントリポイントより遠い場合 { shift_buy = NormalizeDouble( ((Time_cur - OrderOpenTime() ) /60), 0 ); } // M1バーでエントリポイントまでの距離を定義する // 市場エントリ後の価格の最大値を定義する Max_pos = 0; if(Time_cur > OrderOpenTime() && shift_buy > 0) { Max_pos = NormalizeDouble((High[iHighest(NULL,PERIOD_M1, MODE_HIGH ,(shift_buy + 1), 0)]), Digits);} // ポジション内で価格の最大値を検索するモジュールはここで終わる // 買いポジションの決済に渡す(ORロジックオプション) if( // 市場エントリ時における価格の暴落に伴うリスクの低減---------------------- (Bid < Open[0] && (Open[0] - Bid) >= 100*Point && (Time_cur - Time[0]) <= 20) // 価格暴落の場合のエントリの条件(参照点 - 現在のM1ローソク足の始値) || (Bid < O_cur_m15 && (O_cur_m15 - Bid) >= 200*Point && (Time_cur - Time_cur_m15) <= 120) // 価格暴落の場合のエグジットの条件(参照点 - 現在のM15ローソク足の始値) || ((Time_cur - OrderOpenTime()) > 60 && Close[1] < Open[1] && (Open[1] - Close[1]) >= 200*Point) // 価格暴落の場合のエグジットの条件(参照点 - 1つ前のM1ローソク足の振幅) || // 市場エントリ時の価格変動の振幅の不確実性に伴うリスクの低減 // 固定利益値を追跡する(1ポジションあたり) (Bid > OrderOpenPrice() && (Bid - OrderOpenPrice()) >= 100*Point) // 利益領域のエグジット条件(影テイクプロフィット) || // 市場エントリ後の現在の高値からの // 許容可能な最大価格偏差を管理する (shift_buy >= 1 && // エントリポイントから1バー以上シフトする Time_cur > OrderOpenTime() && Max_pos > 0 && OrderOpenTime() > 0 && OrderOpenPrice() > 0 && // エントリの後に現在の最大値がある Max_pos > OrderOpenPrice() && // 現在の最大値が利益領域にある Bid < Max_pos && // 価格逆転の動きがある (Max_pos - Bid) >= 200*Point) // 市場エントリのための現在の最大値からの逆の偏差 || // 事前定義されたリスク限度を管理する(1ポジションあたり) (Bid < OrderOpenPrice() && (OrderOpenPrice() - Bid) >= 200*Point) // 損失領域でのエグジットの条件(影ストップロス) || // 事前定義されたリスク限度を管理する(デポジット全体) (AccountBalance() <= NormalizeDouble( (Depo_first*((100 - Percent_risk_depo)/100)), 0)) ) // 現在の取引中にデポジット全体のリスク限度額を超えた場合 { if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet)) // エグジットアルゴリズムが処理された場合は、買いポジションを決済するための注文を作成する Print("Error closing Buy position ",GetLastError()); // さもなければ、買いポジション決済エラーを印字する return; } } else // さもなければ、売りポジションの決済に移る { //------ 売りポジション決済アルゴリズム ------------------------------------------------------------------------------------ // ポジション内で価格の最大値を検索するモジュール-------------- // 最初に、ポジションの中の現在のポイントから市場へのエントリポイントまでの距離を定義する shift_sell = 0; if(Time_cur > OrderOpenTime() && OrderOpenTime() > 0) // 現在の時刻がエントリポイントより遠い場合 { shift_sell = NormalizeDouble( ((Time_cur - OrderOpenTime() ) /60), 0 ); } // M1バーでエントリポイントまでの距離を定義する // 市場エントリ後の価格の最小値を定義する Min_pos = 0; if(Time_cur > OrderOpenTime() && shift_sell > 0) { Min_pos = NormalizeDouble( (Low[iLowest(NULL,PERIOD_M1, MODE_LOW ,(shift_sell + 1), 0)]), Digits); } // ポジション内で価格の最大値を検索するモジュールはここで終わる // 売りポジションの決済に渡す(ORロジックオプション) if( // 市場エントリ時における価格の暴落に伴うリスクの低減---------------------- (Bid > Open[0] && (Bid - Open[0]) >= 100*Point && (Time_cur - Time[0]) <= 20) // 任意の領域での価格暴落中のエグジットの条件(参照点 - 現在のM1ローソク足の始値) || (Bid > O_cur_m15 && (Bid - O_cur_m15) >= 200*Point && (Time_cur - Time_cur_m15) <= 120) // 任意の領域での価格暴落中のエグジットの条件(参照点 - 現在のM15ローソク足の始値) || ((Time_cur - OrderOpenTime()) > 60 && Close[1] > Open[1] && (Close[1] - Open[1]) >= 200*Point) //exit conditions in any zone during a price collapse (reference parameter - previous M1 candle amplitude) || // 市場エントリ時の価格変動の振幅の不確実性に伴うリスクの低減 // 固定利益値を追跡する(1ポジションあたり) (Bid < OrderOpenPrice() && (OrderOpenPrice()- Bid) >= 100*Point) // 利益領域のエグジット条件(影テイクプロフィット) || // 市場エントリ後の現在の高値からの // 許容可能な最小価格偏差を管理する (shift_sell >= 1 && // エントリポイントから多くて1バーシフトする Time_cur > OrderOpenTime() && Min_pos > 0 && OrderOpenTime() > 0 && OrderOpenPrice() > 0 && // エントリの後に現在の最小値がある Min_pos < OrderOpenPrice() && // 現在の最小値が利益領域にある Bid > Min_pos && // 価格逆転の動きがある (Bid - Min_pos) >= 200*Point) //r 市場エグジットのための現在の最小値からの逆の偏差 || // 事前定義されたリスク限度を管理する(1ポジションあたり) (Bid > OrderOpenPrice() && (Bid - OrderOpenPrice()) >= 200*Point) // 損失領域でのエグジットの条件(影ストップロス) || // 事前定義されたリスク限度を管理する(デポジット全体) (AccountBalance() <= NormalizeDouble( (Depo_first*((100 - Percent_risk_depo)/100)), 0)) ) // t現在の取引中にデポジット全体のリスク限度額を超えた場合 { if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet)) // エグジットアルゴリズムが処理された場合は、売りポジションを決済するための注文を作成する Print("Error closing Sell position ",GetLastError()); // さもなければ、売りポジション決済エラーを印字する return; } } } } //--- } //-----------------------------------------------------------------------------------------------------------
図12 前述のリスクのいくつかを考慮したサンプルEA
EAのコード構造は、上記のリスクのいくつかを考慮しています。また、それらを減らすための適切なモジュールも含まれています。
EAはМ1で起動され、EURUSD、USDCHF、USDJPYの履歴データでテストされています。
EURUSDテスト結果:
図13 EURUSDテスト結果
1年半のテストで肯定的な結果が得られました。
USDCHFテスト結果:
図14 USDCHFテスト結果
1年半のテストで肯定的な結果が得られました。しかし、市場エントリの数は十分ではありません。
USDJPYテスト結果:
図15 USDJPYテスト結果
1年半のテストで肯定的な結果が得られました。
ここで各リスクの重大性を評価します。これには以下の手順を使います。
- EAが獲得した純利益は主要なパラメータとみなされる
- EAアルゴリズムで適切なモジュールを(個別に)無効にすることによって特定のリスクタイプの重要性を定義する
- 取引結果が悪ければ、このタイプのリスクがより重要になる
EURUSDテスト結果をレベルとして使い、各モジュールの影響はこれに相対して定義されます。次のチャートをご覧ください。
図16 前述のEAを例としたリスクタイプの意義
下記は図16の表記です。
- 純利益(net profit)はEAの純利益が表示される軸です
- А - 「組み立てた形での」純利益(すべてのリスク低減モジュールを含む)
- 1 - 市場エントリ時の高ボラティリティの存在に伴うリスクを低減するためのモジュールは無効にされています
- 2 - 市場エントリ時の抵抗レベルの存在に伴うリスクを低減するためのモジュールは無効にされています
- 3 - 市場エントリ時に買われ過ぎ/売られ過ぎ領域に入り込む低減するためのモジュールは無効にされています
- 4 - 市場エントリ時に明確に定義されたトレンドが存在しないことに伴うリスクを低減するためのモジュールは無効にされています(前のプロセスの十分な活動をシミュレートするブロック)
- 5 - 市場エントリ時に明確に定義されたトレンドが存在しないことに関連するリスクを低減するためのモジュールは無効にされています(ローソク足の方向と移動平均をシミュレートするブロック)
図は、最大損失が点4に対応していることを示しています。ここでの結果は、グラフ上の他の点よりも数倍悪くなります。したがって、最も重要なTSコンポーネントはプロセスアクティビティが指定されているモジュールです。
これは、(少なくとも与えられたEAの)最も重要なリスクは、明確に定義された傾向がないこと(プロセス活動が不十分であること)に関連するリスクであることを意味します。
終わりに
本稿では、主なリスクの種類(市場のトレンドに伴うものおよびそれ以外のもの)を分類しました。また、それらを低減する方法を説明し、それらの一部を実装するアルゴリズムを示しました。次に、これらのアルゴリズムの一部を含む単純なEAのコードを調べました。また、EURUSD、 USDCHF、USDJPYの3つの金融商品でEAをテストしました。結果はEAを最適化せずに得られたことに注意してください。モジュールに適用される閾値のレベルは私の個人的な経験に基づいて設定しました。
さらに、移動平均セットとそれをカレンダーサイクルに基づいてセットに組み込む方法が提供されています。リスク低減モジュールとEA全体を開発する際にこの方法を適用しました。買われ過ぎ/売られ過ぎ領域に入り込む可能性を幾分低下させる方法(波状運動をシミュレートすることに基づく)も提供されています。
3つの金融商品については肯定的な結果が得られ、これは、これらのリスクを考慮した取引システムの構造の決定だけでなく、リスクの分類とリスク低減の方法の両方において、記述されたアプローチの正しさを一般的に確認するものです。
実施された分析は、プロセス活動シミュレーションを特徴としないトレンドフォロー取引システムが最も高いリスクを受けるものであることを示しました。残りの要因よりも取引成績に高く反映されるのはこの要因です。
上記のEA(およびTS構築に対する記述されたアプローチ)の利点は、入力および出力アルゴリズムに従来の指標が存在しないことです。ローソク足分析と移動平均(制限付)のみが適用されます。これにより、最適化の量が大幅に減少します。ここでは、適切なモジュールがトリガされる閾値レベルの選択、および利用可能な計算期間のリストからのMA期間の選択に低減されます(「指標計算期間の誤った選択に伴うリスク」セクション)。
記載されたアプローチの欠点は、あまりにも多くのリスク(および適切な入力フィルタ)が存在する可能性があることによる、エントリアルゴリズムの「オーバーフィルタリング」です。この結果、市場エントリが限られてしまいます。しかし、これは、いくつかの金融商品(予備的なテストの後)で同時に取引する能力によって部分的に緩和されます。
この作業の目的は、初心者トレーダーが簡単に把握できるアルゴリズムを備えながら主なリスクを低減するための簡単なEAを作成することでした。もちろん、フラクタルレベルを解析するアルゴリズムを含めることによって、EAの効率を大幅に改善することができます。しかし、これにはフラクタルの検索が伴います(ループが含まれているため、コードが大幅に複雑になる)。初心者のアナリストやトレーダーにとって最も重要なことは、プログラミングスキルをさらに向上させる前に、取引システムの構造(市場動態パラメータの観点から)を把握することだと私は信じています。
このEAを例にすると、論理的な決定に応じて、特定のモジュールを無効にしたり、設定を変更したりして、実験を実行できます。
注意事項このEAは、実際の取引を目的としていないシンプルなデモ版です。
市場リスクを低減するために記載されたアプローチは、独自の取引システムを開発する際に役立つかもしれません。
本稿のEAのMQL5版はReduce_risksにあります。