知っておくべきMQL5ウィザードのテクニック(第27回):移動平均と迎角
はじめに
MQL5ウィザードのおかげで、迎角を考慮することで、素早くテストでき、確実な取引セットアップとアイデアを紹介する連載を続けます。大雑把に言えば、「迎角」という言葉は、戦闘機が最大揚力と最小燃料消費を達成するために最適化すべき離陸角度に関連しています。
しかし、トレーダーにとっては、この言葉は通常、トレンドの最中にあるときの証券価格の軌跡を指し、急角度は強いトレンドを意味するというのが広く受け入れられている見解です。そこで、この記事では、既存の見方を超えて、指標や価格角度を測定する新たな手法を採用し、その問題点を批判しながら、より良い代替案を提案します。そして、このアプローチの問題点を指摘することで批判し、より良い代替案を提案し、いつものようにテスト結果とレポートで締めくくります。
いつものように、カスタムシグナルクラスのインスタンスを使用して、迎角の測定方法に関する仮説を検証し、この角を生の価格ではなく、移動平均から測定します。迎角の重要性を測定および追跡するための指標として、減衰移動平均(英語)を使用します。生値段も迎角を監視するために使用できますが、指標バッファよりも不安定な値を持つため、移動平均を採用します。どの移動平均を使用してもよかったのですが、少し斬新で多くのトレーダーには馴染みがないかもしれない減衰移動平均を採用しました。
現在の迎角を利用するアプローチ
迎角を計算するための基本的なアプローチは、角度を測定する価格または指標バッファ内の2つの価格ポイントを特定することから始まります。このバッファには生の証券価格を使用することもできますが、これらは非常に変動しやすいため、移動平均バッファのような平滑化されたバッファを使用するのが一般的です。つまり、日足で分析を行う場合、今日の移動平均とN日前の移動平均が得られます。
その後、期間ごとの移動平均の変化を求めることです。この場合、2つの移動平均値が得られるN期間が対象です。通常、最初に決定されるのは勾配mで、これは以下の式で計算できます。
ここで
- MA (today)は今日の移動平均値
- MA (N days ago)はN日前の移動平均値
- Nは2点間の日数
上記の式から返されるmは傾きを表し、移動平均の迎角に比例します。現在の形式では、スティープネス、つまり価格の勢いを測る指標として使用できます。しかし、多くの人にとって、角度の概念はプライスアクションの目的のために、紙の上で0〜90度の範囲にある何かを指すものです。
したがって、この傾きを角度として表したい場合は、次のようになります。 アークタンジェント関数(逆正接)を使用して傾きを度数に変換します。
返される値θはラジアン単位の角度です。度数に変換するには、これを乗算します。
これを実際に見るために、非常に単純なアプリケーションの例を考えてみましょう。10日間のデータがあったとします。
- 10日前のMAは100
- 今日のMAは110
上記の簡単な式から、勾配mは次のようになります。
ここから、ラジアン単位の角度θは次のようになります。
これを度数に換算すると
そうなれば、多くの人が急騰の一歩手前の価値として考える、45度に相当する角度になります。もし対象の証券が円のFXペアであれば、45度という考えを正当化したり、再考することもできるでしょう。しかし、あるハイテク企業の株価が1日で同じだけ上昇した場合を考えてみましょう。上記と同じ計算をすれば、角度は84度で、90度に近づきますしかし、金融分析では標準的な用語ではないものの、このアプローチによる「迎角」の基本的な解釈は、移動平均の傾きがトレンドの強さと方向性を示すと理解されるでしょう。角度(傾斜)が急であればあるほど、トレンドは強くなります。
現在のアプローチと方法の問題点
前述のように、現在の迎角計測の応用には、主に価格スケールへの過敏性や、異なる時間軸で一貫性のない角度結果など、多くの問題があります。これを説明するために、まず価格感応度の問題から始めましょう。
取引対象がGBPUSDのような円以外のFXペアの場合、10日間の価格変動は約0.10で、m値は0.01となります。これを180倍してPIで割ると、角度は0.57度になります。45度と0.57度が大きさで大きく異なることは、誰もが理解できるはずですが、それでも円ペアとGBPUSDの両方で10,000ポイントの変動がありました。この角度の違いは、円ペアのボラティリティの高さによるものだと主張することもできますが、2つの角度の比率は90倍です。ほとんどのトレーダーが同意するように、円がGBPUSDのような円以外のペアより90倍もボラティリティが高いわけではありません。これは、FXペア価格の変化を適切に評価するために、ポイントの動きにおけるティック値を考慮する必要があることを示しています。また、forex.comによると、2023年に最も変動の大きいペアは AUDUSDとNZDUSDになります。
最もボラティリティの高い円ペアは3位で、これはAUDUSDとNZDUSDがいずれも5桁の小数で取引されているにもかかわらず、上記の0.10ポイントの変動が同じ0.57度の角度をもたらすことを意味します。
forex.comのリストによると、AUDUSDは1日の平均変動率が1.04%で、最もボラティリティが高いペアです。価格が0.68150の場合、1日あたり1.04%の変動で10日間で0.070876動くことになります。これにより、m(傾き)は0.0070876、10日間の角度は0.406度になります。上記のGBPUSDで試算した0.507度よりは少ないですが、より重要なのは、ランキング7位のGBPJPYの平均価格変動率が0.81%であったということです。147.679を基準価格とする10日間の価格変動は、50.1度になります。
迎角はボラティリティを測定する指標ではありませんが、多くの読者やトレーダーは、迎角の大きさが、最終的な証券の値動きの大きさを何らかの形で示すと予想するでしょう。しかし、実際にはそうではないため、この角度を測定するアプローチには危険が伴います。このような価格に対する感度の不一致に加え、チャート/分析時間枠の変化は、迎角の大きさを大きく揺さぶる可能性があります。
例えば、上記のケースで、日足から例えば4時間足に切り替えた場合を考えてみましょう。最初の図では角度が45度でしたが、新しい時間枠では0.95度に変わることがあります。そうなると、価格スケールに何の変更も加えずに、角度を測定している期間を単に「詳細化」するだけで、なぜ突然1度未満の非常に平坦な角度が得られるのかという疑問が生じます。これに対する直接的な答えは、底辺が長くなったため、同じ高さと比較すると角度の上昇が少なくなるが、単位ではなく時間で測定した場合、底辺の長さは実際には同じであるため、この歪みは存在しないはずである、ということです。
代替法の導入
しかし、時間枠の変更による問題を詳しく調べると、解決策が見つかります。三角形の角度を求める場合、直角三角形であれば、高さと底辺の両方がわかれば、底辺を高さで割って正接を求めることで、角度を度単位で計算できます。
つまり、上のイメージから、大きい方の直角三角形の底辺は実際には1であり(cosθより大きい)、そのため反対側の辺の高さはtanθとなります。ここで注意すべき点は、隣接する辺(底辺)の単位は、反対側の辺(高さ)の単位と似ているということです。このような場合、角度θのアーク接線やアークコサインを求めるときに、θに意意味のある角度値が得られます。
上で紹介した図は、「情報が多すぎる」とはいえ、接線の定義が比であることを強調しています。サインからコサインへ。「好き」から「好き」へ。角度θに意味を持たせるには、横軸を縦軸と同じ単位にする必要があります。では、価格と時間という2つの軸を同じ単位に調和させるにはどうすればいいのでしょうか。
この正規化で直面する選択肢は、時間軸と価格軸の両方を時間単位に変換するか、両方を価格単位に変換するかです。このコンバージョンの考え方は、最初は過激に見えるかもしれませんが、結果を見比べるようになれば、すべてが納得できるようになります。価格が重要であり、間違った方向への価格の動きがドローダウンのコストとなるため、プライスアクションの「縦軸」と「横軸」の両方を価格単位でマークします。では、時間軸を価格に置き換えるにはどうすればいいのでしょうか。
そのために取り得るアプローチはいくつもあるが、この記事の目的は、そのすべてを列挙することでも、必ずしも「ベスト」なものを使用することでもありません。しかし、私たちが使用するのは可変スケールです。時間的に距離Dの離れた2つの価格ポイントが提示された場合、距離Dはその前の距離Dを超える価格レンジの価格単位に変換されます。非常にシンプルに見えますが、迎角の大きさについては比較的一貫した結果が得られます。MQL5では、これを次のように実装します。
//+------------------------------------------------------------------+ //| Get Angle function //+------------------------------------------------------------------+ double CSignalAA::Angle(int Index) { double _angle = 0.0; double _price = DM(Index) - DM(Index+m_length_period); double _max = DM(Index+m_length_period+1); double _min = DM(Index+m_length_period+1); for(int i=Index+m_length_period+2;i<Index+(2*m_length_period);i++) { double _dm = DM(i); _max = fmax(_max, _dm); _min = fmin(_min, _dm); } double _time = fmax(m_symbol.Point(), _max - _min); _angle = (180.0 / M_PI) * MathArctan(fabs(_price) / _time); if(_price < 0.0) { _angle *= -1.0; } return(_angle); }
この関数は、単純に2つのインデックスプレースホルダーを受け取り、それを使用して、迎角を測定する開始点を決定します。また、前述のように、時間や横軸の値の指標となる価格範囲を探すために、どの程度歴史を遡るかを決定します。選択した履歴の価格範囲はゼロになる可能性があるため、取引された証券の最小価格ポイント サイズによって決定されるポイントが最小範囲として機能します。読者は、ゼロ除算を避ける限り、この値をその時点のスプレッドに変更することも、任意の値に変更することもできます。以下に、減衰移動平均関数(DM)を紹介します。
減衰移動平均(DMA)
この移動平均は指数関数的に減衰する重みを与え、従来の指数関数的移動平均よりも早く減衰します。これは以下の式で定義されます。
ここで
- nは平均化されたサンプルのサイズ
- iはサンプル内の位置インデックス
- Pはi時点の価格
本連載の最近の記事で紹介したいくつかの斬新な移動平均線と同様に、この移動平均線も関数として実装できます。カスタム指標はバッファリングに優れており、EAにさらなる効率をもたらします。ただし、カスタム指標はコンパイルされたEAに追加の要求をもたらすため、テスト目的では関数のアプローチにこだわります。
直近の価格に重きを置く指数移動平均はたくさんありますが、私は減衰移動平均がそれをさらに強化していると考えています。これはMQL5では次のように実装できます。
//+------------------------------------------------------------------+ //| Decaying Mean | //+------------------------------------------------------------------+ double CSignalAA::DM(int Index, int Mask = 8) { double _dm = 0.0; vector _r; if(_r.CopyRates(m_symbol.Name(), m_period, Mask, Index, m_length_period)) { //vectors are not series double _weight = 0.0; for(int i = 0; i < m_length_period; i++) { _dm += (1.0/pow(2.0, m_length_period-i))*_r[i]; _weight += (1.0/pow(2.0, m_length_period-i)); } if(_weight != 0.0) { _dm /= _weight; } } return(_dm); }
平均化されるサンプル内の各価格に重みを適用しているだけです。ここでの主な注意点は、ベクトルはレートをシリーズとしてコピーしないということです。つまり、最も高いインデックスが最新の価格であること、コピーを開始したインデックスに最も近い価格であることを認識する必要があります。これは、forループでカウントアップしているときに、重み付け(2つの分母に与えられる指数)が逆になることを意味します。
シグナルクラス
このすべてをクラスにまとめるには、シグナルクラスのインスタンスに減衰平均と角度関数を追加し、もちろんロングとショートの条件を以下のように変更します。
//+------------------------------------------------------------------+ //| "Voting" that price will grow. | //+------------------------------------------------------------------+ int CSignalAA::LongCondition(void) { int result = 0; double _angle = Angle(StartIndex()); if(_angle >= m_threshold) { result = int(round(100.0 * ((_angle) / (90.0)))); } return(result); } //+------------------------------------------------------------------+ //| "Voting" that price will fall. | //+------------------------------------------------------------------+ int CSignalAA::ShortCondition(void) { int result = 0; double _angle = Angle(StartIndex()); if(_angle <= -m_threshold) { result = int(round(100.0 * (fabs(_angle) / (90.0)))); } return(result); }
ここでの条件は非常にシンプルで、入力された距離から測定された角度が、入力された閾値を超えるか、または入力された閾値と等しいかどうかを確認するだけです。つまり、ここでの条件は本質的にトレンドに追随するものなのです。Angle関数はプラスまたはマイナスの値を返すので、売買の条件はポジションを建てる前にこの値を確認します。トレンドフォローのアプローチでは、角度が急すぎる状況では反転する可能性があります。この点については、この記事で詳細に検討していないため、読者の皆さんに追究し、そのメリットを見極めることをお勧めします。もうひとつ注目すべき点は、コンディションのresult値をどのようにサイズ調整したかです。角度の関数が、オーソドックスなアプローチとは対照的に、より「一貫性のある」値を返すようになったので、90度を超える、あるいは90度に近い角度を得ることはないと確信できます。
そのため、角度の絶対値を90で割って正規化し、その後0〜100の範囲になるようにスケーリングします。これとは異なる正規化のアプローチも検討できますが、この記事では迎角の値に最も重きを置く傾向があります。
両アプローチの戦略テストとレポート
2023年(2023.01.01から2024.01.01まで)のGBPCHFペアの4時間足でテストすると、以下の結果が得られます。
確かにある程度の可能性はありますが、十分な取引がおこなわれていないという議論も起こり得ます。そしてもちろん、これらの実行はわずか1年に限られている上に、何がうまくいき、何がうまくいかないかを素早くふるいにかけることができるストラテジーテスターのウォークフォワード機能を利用していません。しかし、私たちは価格の傾きの代用として減衰移動平均の傾きを使用しており、この特別な平均は直近の価格に大きく偏っているため、シグナルに多くの乱高下が生じることになります。
臨界迎角
臨界角は航空力学から借用した概念です。これまでの設定では、移動平均の角度の減衰の大きさに基づいて売買条件の状態を探ってきました臨界迎角の考え方では、この角度が単なる閾値として定義されるのではなく、帯域や特定の範囲内にあることが望ましいとされています。これをテストし、利用するために、追加のパラメータを導入し、カスタムシグナルクラスを修正します。
シグナルクラスに追加するパラメータは、m_bandというdouble型の値で、トリガー角度の外側の範囲を設定するのに役立ちます。この変更は、売り条件と買い条件の関数に以下のように反映されます。
//+------------------------------------------------------------------+ //| "Voting" that price will grow. | //+------------------------------------------------------------------+ int CSignalAA::LongCondition(void) { int result = 0; double _angle = Angle(StartIndex()); if(_angle >= m_threshold && _angle <= m_threshold+m_band) { result = int(round(100.0 * ((_angle) / (90.0)))); } return(result); } //+------------------------------------------------------------------+ //| "Voting" that price will fall. | //+------------------------------------------------------------------+ int CSignalAA::ShortCondition(void) { int result = 0; double _angle = Angle(StartIndex()); if(_angle <= -m_threshold && _angle >= -(m_threshold+m_band)) { result = int(round(100.0 * (fabs(_angle) / (90.0)))); } return(result); }
主な変更点は、最初のシグナルの場合と同様に、角度が閾値以上であることを確認し、さらにバンドパラメータで定義される上限値以下であることを確認することです。このシグナルファイルを使用してテストを実行してEAに組み込むと、上記と同様のテスト実行から次の結果が得られます(初心者向けのガイドは、こちらとこちらにあります)。
以前の結果と比較すると、取引頻度がそれほど高くないことは明らかです。これは、角度が単に閾値を超えるだけでなく、特定の範囲内に留まる必要があるためです。プロフィットファクター、リカバリーファクター、ドローダウンのパーセンテージなど、ほとんどの指標で全体的なパフォーマンスが向上しました。したがって、その有効性について結論を出す前に、より長期間のテストやティックデータを使用してさらに検討する必要があります。
結論
以上の内容から、金融時系列の指標として、単に価格と生の時間変化から角度を取るという伝統的なアプローチと、時系列の時間軸を価格単位に変換する斬新なアプローチの両方を検討しました。前者のアプローチについては、この記事ではテストを紹介していません。迎角の測定方法に多くの矛盾が見つかったため、ストラテジーテスターでの実行は無駄であり、コンピュータ資源の浪費であると判断されたからです。
しかし、迎角を計算する前に、水平軸または時間軸を時間単位で区切るという新しいアプローチでテストをおこなったところ、有望な結果が得られました。このアプローチでは、2つのモードでテストを実施しました。まず、角度の閾値を使用してどのポジションを建てるべきかを判断し、次に臨界角の概念を用いてポジションを建てるタイミングを決定しました。迎角は単に閾値を超えるだけでなく、特定のバンド内に収まることでしきい値に十分近いものでなければなりませんでした。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/15241
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索