
知っておくべきMQL5ウィザードのテクニック(第06回):フーリエ変換
はじめに
フーリエ変換は、データ点の波を可能な構成部分に分解する方法で、ジョセフ・フーリエによって導入されました。 フーリエ変換で可能なすべての周波数を積分すると、成分のスペクトルが得られます。なぜなら、元の関数を構成要素に分解し、それぞれが異なる周波数成分に対応するからです。
フーリエ変換は定義上、マイナス無限大からプラス無限大の範囲にあります。
ここで、F(w)は関数f(t)のフーリエ変換、iは虚数単位、wは角周波数、eは指数関数です。
しかし実際には、変換を使用する場合、周転円の数は管理しやすい小さな数にあらかじめ決められています。より多くの周転円(構成周波数)を使えば使うほど、元のカーブをより正確に描写することができますが、ある時点で、より多くの周転円を使っても、部分的に描写される曲線に意味のある違いは生まれないため、非効率的になります。
つまり、この変換のユーザーは、離散的な有限個の周転円の数nに 落ち着くことになります。そして、上の式を少し修正すると次のようになります。
すべての可能な周波数を加算するとき、元の関数に対するそれぞれの寄与を合計することになります。各周波数成分は、大きさと位相情報の両方を含む複素数で表されます。大きさは波の振幅を表し、位相は波の時間のずれを表します。つまり、上記の修正方程式はn個の成分にわたって合計され、それらのn個の部分のそれぞれは、時刻tにおいてさまざまな値を持つ波を持っています。
重要なのは、実数部と虚数部の両方を構成する各成分のf(t)を求めることです。フーリエ系は、区間0から2π の任意の関数f(t)を複素数でこの「無限和」として書き直します。 「無限」というのは、足してゼロになるからです。
上の式で、例えば係数を解きます。 C 2 ,
方程式の両辺にe-2itを掛けます。
積分すると、方程式は次のように単純化されます。
つまり、上のf(t)方程式の2(2πの2ではない)をnに置き換えて、他の係数を求めることができます。これらの計算はすべて、MathAlglibのfasttransforms.mqhファイルに記載されているCFastFourierTransformクラスによって処理されるので、このライブラリを使うだけでいいのです。
応用例
非常に具体的な例を挙げて説明する前に、まず、トレーダーがデータポイントの波を構成要素に分解する能力からどのような利益を得ることができるのかについて、より広い視野で考えることが有益でしょう。非常に多くの応用例があります。以下がその候補です。
- 株価の動きを分析する:株価データを集めて時系列に並べれば、その系列データにフーリエ変換を適用して周波数成分を得ることができます。 これらの周波数成分を分析し、データのパターンや傾向を特定することで、より良い情報に基づいた取引判断を下すことができます。例えば、トレーダーはある銘柄の周波数スペクトルがある周波数で繰り返しピークを持つことに気づくかもしれません。この観察は、株価がこの観察されたパターンに従うという予想に基づいて、株価が安値のときに買い、高値のときに売るために使うことができます。しかし、時間が経つにつれて、これは頻繁に監視され、パターンが適用可能であることを確認する必要があります。
- 長期サイクルの分析:景気循環か市場循環のどちらかを選ぶ必要があります。ビジネスサイクルを選択した場合、考えられるデータソースは以下の通りです。
- 国内総生産(GDP):経済成長を示す最も重要な指標のひとつで、通常1年間という一定期間にその国で生産された財やサービスの総額を測定します。
- 雇用統計:失業率や雇用創出数などは、労働市場の健全性について洞察することができます。失業率の上昇や雇用の伸び悩みは、経済の弱体化を示唆します。
- 鉱工業生産データ:製造、鉱業、公益セクターの生産量を測定する鉱工業指数が含まれる可能性があります。製造業、鉱業、公益事業部門の生産高を測定し、経済全体の健全性、購買担当者指数、titlehttps://en.wikipedia.org/wiki/Capacity_utilizationtitle生産能力稼働率 (英語)、耐久財受注、製造業雇用などを示すことができます。
- 消費者信頼感データ:これには、消費者信頼感指数、ミシガン大学消費者態度指数、コンファレンスボード消費者信頼感指数、小売売上高、消費者信用などが含まれます。
- 金利データ:金利は企業投資や個人消費に影響を与える可能性があり、いずれも経済パフォーマンスに影響を与える可能性があります。金利上昇は投資や支出を抑制する傾向がある一方、金利低下は投資や支出を促す要因となり、最終的に上場企業の株価に影響を与える傾向があります。
- インフレデータ:財やサービスの価格上昇率を測定するもので、経済の状態をある程度明確にすることができます。高インフレは経済の過熱を示し、低インフレは経済の低迷を示します。これもまた、トレーダーが様々な銘柄を購入する際の意思決定に影響を与えうるデータセットであり、したがって重要なデータ源です。
- 住宅データ:住宅販売や建設着工をカバーし、経済の重要な構成要素である住宅市場の健全性を明らかにすることができ、トレーダーがポートフォリオに組み込んでいる特定の銘柄に関連する可能性があります。
逆に、市場サイクルのデータソースとしては、以下のようなものがあります。
- 株価収益率(PER):この一般的な指標は、企業の株価と1株当たり利益(EPS)を比較するもので、市場が株価を過大評価しているか(高い数値の場合)、または市場が株価を過小評価しているか(市場の地理に応じて15または10)を測るために使用することができます。
- 配当利回り:株価1株当たりの配当額を測定するものです。低い配当利回りは割高株を示唆し、高い配当利回りは割安株を示唆する可能性があります。
- テクニカル指標:移動平均、モメンタム指標、相対力指標を含むリストは、株式の現在のプライスアクションを要約するのに役立ちます。例えば、株価が200日移動平均線より上で取引されている場合、強気トレンドを示す可能性があり、200日移動平均線より下で取引されている場合、弱気トレンドを示す可能性があります。この場合、データは価格と200日移動平均の間のスプレッドである可能性があります。
- Market Breadth:ここでは、ある市場において上昇している銘柄と下落している銘柄の数を測定します。多くの銘柄が上昇している場合は、市場が健全であることを示唆し、逆に幅が縮小している場合は、市場が弱含みであることを示唆します。このようなデータは、通常、他のデータストリームとバンドルして1回限りの料金か、場合によってはサブスクリプションを支払うサードパーティから調達することができます。
- ボラティリティ:VIXのような指標で測定され、市場リスクと投資家心理の評価に役立ちます。市場リスクやネガティブなセンチメントと正の相関があることが多いです。
上記の可能性のある情報源から関連する金融データを集めたら、それを時系列に並べ、フーリエ変換を適用して周波数成分に分解します。データから繰り返されるサイクルを探すと言う方法で、これらの構成部分を分析することで、取引判断を改善できるかもしれません。例えば、トレーダーはこれを利用して、数年間続く傾向のある金利データの繰り返しサイクルを発見し、取引している株式やETFと遅行性の正の相関関係を持つことができます。この知識を武器に、市場が低水準にあるときに長期ポジションに投資し、ドローダウンのポジションを長期にわたって保有し、金利データの相関がマイナスに転じるか、あるいは下降を予感させるときにのみ、ポジションを手仕舞うことができます。
- シグナル処理:シグナルを見る際には、上昇であれ下降であれ、大きなブレイクアウトの前にある価格波動パターンを考慮することができます。例えば、より具体的なデータソースとして、特定の銘柄の価格履歴のうち、ガートレーパターンのみを調べ、他のデータを省くことができます。この波の価格データは、時系列として記録されます(パターンはまれなので、かなりのギャップが存在するでしょうが)。フーリエ変換は、このシリーズの各波に適用されます。そして、(最終的なブレイクアウトとの相関関係を持つ観測結果に基づいて)成分フーリエ波の周波数閾値を設定し、閾値を満たさないものを省くことができます。そして、このフィルターを通したいくつかの波を使って、今後の予測を立てます。この価格バッファは、株式、FXペア、あるいはコモディティです。原理は同じでしょう。
- リスクマネジメント:市場リスクのような他の種類のリスクは、上記ですでに取り上げたものと重複する可能性があるため、信用リスクに特化するのであれば、これらをデータソースとすることができます。
- デフォルト率:特定の銀行市場、例えば米国の四半期または年間のデフォルト率は、米国の信用リスク、したがってS&P500のパフォーマンスを分析するために使用することができます。
- 信用スプレッド:社債と国庫債券の間の信用スプレッドに関する日次または週次データは、信用力に対する市場の認識の変化に伴う信用リスクの評価に役立ちます。
- ローンの延滞:デフォルト率と違います。デフォルト率は、特定の銀行または貸し手について毎月または四半期ごとに取得でき、トレーダーが特定の銀行株の購入を検討している場合に、この銀行のローンポートフォリオに関連する信用リスクを調査するために使用されます。
- 信用格付け:このデータは、一般的なデータのようにシリアル化されてはいませんが、それでも特定の企業について四半期ごと、あるいは毎年、妥当な歴史的期間にわたって収集することができ、企業のコマーシャルペーパーや長期債の価値を評価するために使用することができます。
- クレジットデフォルトスワップ(CDS):通常、貸し手のローンに対する保険は、毎日または毎週、その契約価格をソースとし、信用力に対する市場の認識の変化に関連する信用リスクを分析するために使用することができます。
これらのソースのいずれかからのデータは時系列に構成され、その時系列データにフーリエ変換が適用されて周波数成分が取得されます。どの要素が最終的な金融ショックやより具体的な株価変動と最も相関性が高いかを分析することは、効果的なリスク管理戦略の策定に役立つでしょう。
- オプション価格:オプションの原資産価格、権利行使価格、満期までの期間、ボラティリティ、金利、配当などの過去のデータは、ブルームバーグターミナルなど、多くの情報源から入手できます。これらのデータセットがそれぞれ、オプション価格の「周波数成分」であることに注目してください。このように複数のデータセットがあれば、分析の方法はいくらでもあります。ある時点におけるオプションの価格について、コンセンサスが得られているわけではありません。私たちが持っているのは、ブラックショールズのような「ベストプラクティス」価格設定モデルです。しかし、これらは必ずしも信頼できるものではありません。有効期限前の一定期間において原資産価格を単純に分解し、どの周波数成分が有効期限における原資産価格と権利行使価格の差と最も相関があるかを見るというアプローチが考えられます。この分析は欧州のオプションには有効ですが、米国のオプションは満期前に行使できるため、より複雑な課題があります。
- センチメント分析:Webのデータをスクレイピングすることに関しては長い道のりを歩んできており、今日、ソーシャルメディア管理ソフトウェアは大きな意味を持っています。Zoho Social、Hootsuite、Khoros Marketingのような名前を挙げればきりがありませんが、これらは急速に有力企業としての足場を固めつつあります。今日、テキスト分析(そしてAIとの組み合わせ)により、企業は顧客とのエンゲージメントや製品・サービスに対する満足度をより定量化できるようになっています。多くのデータを集めることができます。ライバル2社に関心を持つトレーダーは、商品レビューへの関与の長さと、3ヶ月後あるいは6ヶ月後の最終的な商品の売れ行きとの間に相関関係があるかどうかを知りたいと思うかもしれません。エンゲージメントデータを時系列に変換し、構成要素に分解することで、どの構成要素がターゲット(この場合は将来の売上)に最も相関しているかを特定することができます。
- 機械学習:この応用例のためのフーリエ変換は、入力データを構成する周波数に分割することで、入力データをベクトル化するのに役立ちます。入力データとして異なる終値の波があれば、これらの波はそれぞれn個の波に分解することができ、それぞれの新しい波は分割されていない古い波のベクトルの一部となります。これにより、評価する必要のある新しいデータポイントの識別情報が増え、未知の波を評価する際に、元の単一の波だけよりも、すでに訓練されたデータとより正確に比較することができます。そのため、このベクトル化されたデータを訓練し、ユークリッド距離などを使ってテストデータと比較することで、モデルの予測をより鮮明にすることができるでしょう。
実装
MQL5でのフーリエ変換の実装を説明するために、レンジ価格(高値から安値を引いた値)の時系列を分解して見ます。次に、これらの構成頻度を調べ、インデックスによって特定される特定の1つが、価格帯の次の変化と有用な相関関係を持つかどうかを確認します。この情報は、「CExpertTrailing」クラスのカスタム実装で、ポジションのストップロスを調整するために使用されます。シグナルは「SignalRSI.mqh」に記載されているシンプルな内蔵シグナルを使用し、資金管理は固定証拠金を使用します。
カスタムトレイリングクラスを以下のようにリストアップしてみましょう。関数f(t)の実数係数と虚数係数を取り出すには、関数「FFTR1D」で処理した後、構造体「a1_complex」のインスタンスを使用してこの情報を格納します。これらの係数を使用するためには、「積分」する必要があり、そのために行列「_output」を即興で作りました。この行列は、各データポイントにおける各周転円の係数を持っています。6つのデータポイントと5つの周転円を使用しています。 また、フーリエサイクルは繰り返しで、次の足がサイクルの中で最も古い足となるため、予測データポイントのインデックス「m_points-1」が使用されます。
//+------------------------------------------------------------------+ //| TrailingCT.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include <Math\Alglib\fasttransforms.mqh> #include <Expert\ExpertTrailing.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Trailing Stop based on 'Fourier Transform' v3 | //| Type=Trailing | //| Name=CategoryTheory | //| ShortName=CT | //| Class=CTrailingFT | //| Page=trailing_ct | //| Parameter=Step,double,0.5,Trailing Step | //| Parameter=Index,int,0,FT-Index | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CTrailingFT. | //| Appointment: Class traling stops with 'Fourier Transform' v3 | //| relative-sets concepts. | //| Derives from class CExpertTrailing. | //+------------------------------------------------------------------+ #define __PI 245850922/78256779 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CTrailingFT : public CExpertTrailing { protected: CFastFourierTransform FFT; //--- adjusted parameters double m_step; // trailing step int m_index; // the epicycle index public: //--- methods of setting adjustable parameters //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp); virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp); //--- CTrailingFT(void); ~CTrailingFT(void); //--- methods of setting adjustable parameters void Step(double value) { m_step=value; } void Index(int value) { m_index=value; } protected: double ProcessFT(int Index); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CTrailingFT::CTrailingFT(void) { //--- initialization of protected data m_used_series=USE_SERIES_TIME+USE_SERIES_SPREAD+USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CTrailingFT::~CTrailingFT(void) { } //+------------------------------------------------------------------+ //| Validation settings protected data. | //+------------------------------------------------------------------+ bool CTrailingFT::ValidationSettings(void) { //--- validation settings of additional filters if(!CExpertTrailing::ValidationSettings()) return(false); //--- initial data checks if(m_index<0 || m_index>=5) { printf(__FUNCTION__+": index must be greater than 0 and less than epicycles"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CTrailingFT::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- initialization of indicators and timeseries of additional filters if(!CExpertTrailing::InitIndicators(indicators)) return(false); //--- //--- ok return(true); } //+------------------------------------------------------------------+ //| Checking trailing stop and/or profit for long position. | //+------------------------------------------------------------------+ bool CTrailingFT::CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp) { //--- check if(position==NULL) return(false); m_high.Refresh(-1); m_low.Refresh(-1); int _x=StartIndex(); double _ft=ProcessFT(_x); double _type=_ft/100.0; double _atr=fmax(2.0*m_spread.GetData(_x)*m_symbol.Point(),m_high.GetData(_x)-m_low.GetData(_x))*(_type); double _sl=m_low.GetData(_x)-(m_step*_atr); double level =NormalizeDouble(m_symbol.Bid()-m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits()); double new_sl=NormalizeDouble(_sl,m_symbol.Digits()); double pos_sl=position.StopLoss(); double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl; sl=EMPTY_VALUE; tp=EMPTY_VALUE; if(new_sl>base && new_sl<level) sl=new_sl; //--- return(sl!=EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Checking trailing stop and/or profit for short position. | //+------------------------------------------------------------------+ bool CTrailingFT::CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp) { //--- check if(position==NULL) return(false); m_high.Refresh(-1); m_low.Refresh(-1); int _x=StartIndex(); double _ft=ProcessFT(_x); double _type=_ft/100.0; double _atr=fmax(2.0*m_spread.GetData(_x)*m_symbol.Point(),m_high.GetData(_x)-m_low.GetData(_x))*(_type); double _sl=m_high.GetData(_x)+(m_step*_atr); double level =NormalizeDouble(m_symbol.Ask()+m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits()); double new_sl=NormalizeDouble(_sl,m_symbol.Digits()); double pos_sl=position.StopLoss(); double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl; sl=EMPTY_VALUE; tp=EMPTY_VALUE; if(new_sl<base && new_sl>level) sl=new_sl; //--- return(sl!=EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Fourier Transform | //| INPUT PARAMETERS | //| Index - int, read index within price buffer. | //| OUTPUT | //| double - forecast change in price | //+------------------------------------------------------------------+ double CTrailingFT::ProcessFT(int Index) { double _ft=0.0; int _index=Index;//+StartIndex(); m_close.Refresh(-1); double _a[]; matrix _output; al_complex _f[]; //6 data points, 5 epicycles ArrayResize(_a,6);ArrayInitialize(_a,0.0); _output.Init(6,5);_output.Fill(0.0); for(int p=0;p<6;p++) { _a[p]=m_close.GetData(_index+p)-m_close.GetData(_index+p+1); } FFT.FFTR1D(_a,5,_f); for(int p=0;p<6;p++) { for(int s=0;s<5;s++) { double _divisor=(1.0/5),_angle=(p);_angle/=6; _output[p][s]=(_divisor*_a[p]*MathExp(-2.0*__PI*(_f[s].im/_f[s].re)*_angle)); } } double _close=m_close.GetData(_index)>m_close.GetData(_index+1); _ft=(_output[5][m_index]/fmax(m_symbol.Point(),fabs(_output[5][m_index])+fabs(_close)))*100.0; return(_ft); } //+------------------------------------------------------------------+
内蔵のRSIシグナルクラスと内蔵の固定証拠金マネーマネジメントを組み合わせると、EURJPY:2022.01.01から2023.01.01まで:4時間で次のような結果が得られます。このテストでは、利益目標を設定せず、デフォルトの損切り設定も使用しないので、これらの入力は両方ともゼロです。シグナルが反転するか、トレイリングストップによって設定されたストップロスがトリガーされるかによって、エグジットが完全に決定されるようにします。
第2/比較実施については、上記のように、最も振幅の大きい構成周波数と価格帯の変化との相関を検討します。
この実装を以下に示します。
//+------------------------------------------------------------------+ //| TrailingCT.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include <Math\Alglib\fasttransforms.mqh> #include <Expert\ExpertTrailing.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Trailing Stop based on 'Fourier Transform' v3 | //| Type=Trailing | //| Name=CategoryTheory | //| ShortName=CT | //| Class=CTrailingFT | //| Page=trailing_ct | //| Parameter=Points,int,6,FT-Points | //| Parameter=Epicycles,int,5,FT-Epicycles | //| Parameter=Step,double,0.5,Trailing Step | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CTrailingFT. | //| Appointment: Class traling stops with 'Fourier Transform' v3 | //| relative-sets concepts. | //| Derives from class CExpertTrailing. | //+------------------------------------------------------------------+ #define __PI 245850922/78256779 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CTrailingFT : public CExpertTrailing { protected: CFastFourierTransform FFT; //--- adjusted parameters double m_step; // trailing step public: //--- methods of setting adjustable parameters //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual bool CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp); virtual bool CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp); //--- CTrailingFT(void); ~CTrailingFT(void); //--- methods of setting adjustable parameters void Step(double value) { m_step=value; } protected: double ProcessFT(int Index); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CTrailingFT::CTrailingFT(void) { //--- initialization of protected data m_used_series=USE_SERIES_TIME+USE_SERIES_SPREAD+USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CTrailingFT::~CTrailingFT(void) { } //+------------------------------------------------------------------+ //| Validation settings protected data. | //+------------------------------------------------------------------+ bool CTrailingFT::ValidationSettings(void) { //--- validation settings of additional filters if(!CExpertTrailing::ValidationSettings()) return(false); //--- initial data checks //--- ok return(true); } //+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CTrailingFT::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- initialization of indicators and timeseries of additional filters if(!CExpertTrailing::InitIndicators(indicators)) return(false); //--- //--- ok return(true); } //+------------------------------------------------------------------+ //| Checking trailing stop and/or profit for long position. | //+------------------------------------------------------------------+ bool CTrailingFT::CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp) { //--- check if(position==NULL) return(false); m_high.Refresh(-1); m_low.Refresh(-1); int _x=StartIndex(); double _ft=ProcessFT(_x); double _type=_ft/100.0; double _atr=fmax(2.0*m_spread.GetData(_x)*m_symbol.Point(),m_high.GetData(_x)-m_low.GetData(_x))*(_type); double _sl=m_low.GetData(_x)-(m_step*_atr); double level =NormalizeDouble(m_symbol.Bid()-m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits()); double new_sl=NormalizeDouble(_sl,m_symbol.Digits()); double pos_sl=position.StopLoss(); double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl; sl=EMPTY_VALUE; tp=EMPTY_VALUE; if(new_sl>base && new_sl<level) sl=new_sl; //--- return(sl!=EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Checking trailing stop and/or profit for short position. | //+------------------------------------------------------------------+ bool CTrailingFT::CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp) { //--- check if(position==NULL) return(false); m_high.Refresh(-1); m_low.Refresh(-1); int _x=StartIndex(); double _ft=ProcessFT(_x); double _type=_ft/100.0; double _atr=fmax(2.0*m_spread.GetData(_x)*m_symbol.Point(),m_high.GetData(_x)-m_low.GetData(_x))*(_type); double _sl=m_high.GetData(_x)+(m_step*_atr); double level =NormalizeDouble(m_symbol.Ask()+m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits()); double new_sl=NormalizeDouble(_sl,m_symbol.Digits()); double pos_sl=position.StopLoss(); double base =(pos_sl==0.0) ? position.PriceOpen() : pos_sl; sl=EMPTY_VALUE; tp=EMPTY_VALUE; if(new_sl<base && new_sl>level) sl=new_sl; //--- return(sl!=EMPTY_VALUE); } //+------------------------------------------------------------------+ //| Fourier Transform | //| INPUT PARAMETERS | //| Index - int, read index within price buffer. | //| OUTPUT | //| double - forecast change in price | //+------------------------------------------------------------------+ double CTrailingFT::ProcessFT(int Index) { double _ft=0.0; int _index=Index;//+StartIndex(); m_close.Refresh(-1); double _a[]; matrix _output; al_complex _f[]; //6 data points, 5 epicycles ArrayResize(_a,6);ArrayInitialize(_a,0.0); _output.Init(6,5);_output.Fill(0.0); for(int p=0;p<6;p++) { _a[p]=m_close.GetData(_index+p)-m_close.GetData(_index+p+1); } FFT.FFTR1D(_a,5,_f); for(int p=0;p<6;p++) { for(int s=0;s<5;s++) { double _divisor=(1.0/5),_angle=(p);_angle/=6; _output[p][s]=(_divisor*_a[p]*MathExp(-2.0*__PI*(_f[s].im/_f[s].re)*_angle)); } } double _close=m_close.GetData(_index)>m_close.GetData(_index+1); int _max_index=0; double _max=fabs(_output[5][_max_index]); for(int s=0;s<5;s++) { if(_max<fabs(_output[5][s])) { _max_index=s; _max=fabs(_output[5][s]); } } _ft=(_output[5][_max_index]/fmax(m_symbol.Point(),fabs(_output[5][_max_index])+fabs(_close)))*100.0; return(_ft); } //+------------------------------------------------------------------+
同じシグナルと資金管理ファイルを用いてコンパイルすると、以下のようなレポートが得られます。
最大振幅成分ではなく、最小振幅成分を使用する最終的な実装(そのコードもこの記事に添付されている)により、以下のようなレポートが得られます。
3つのサンプルレポートから、同じエントリーシグナルでトレイリングストップシステムをわずかに変更したことが、レポートの結果に大きく影響したことは明らかです。
結論
素人トレーダーの視点からフーリエ変換とは何かを見てきました。トレーダーへのこの変換の膨大な可能性の応用例のいくつかを強調しました。続いて、MQL5でこの変換をいくつか簡単に実装し、ボラティリティ予測を使用して未決済ポジションのストップロスエグジットを管理することに焦点を当てながら、デモンストレーションをおこないました。この変換には、ここに挙げた以外にも多くの応用例があります。また、ここで共有されているコードは、聖杯でもなければ、エキスパートアドバイザー(EA)のための「ライブ口座準備完了」コードでもありません。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/12599





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索