
Pythonを使用したEA用ディープラーニングONNXモデルの季節性フィルタと期間
はじめに
「外国為替市場の季節性から利益を得る」稿を読んだとき、これを興味深い記事にしようと考えました。季節性のあるEAと季節性のないEAを比較し、EAが恩恵を受けるかどうかを確認することができます。
市場が季節要因に影響されることはすでに知っていました。マーク・ザッカーバーグが投資家からの資金でFacebookの資金を手に入れたことを知ったとき、このことは明らかでした。 この投資家は以前、カリブ海で予想されるハリケーンによる上昇を予測して、バー・ミツバからの資金を石油株に投資していました。彼はまず気候を調査し、ある期間に悪天候が続くと予測しました。
たとえ市場と季節性が良い関係にあることはわかっていても、結果が良くならなかったとしても、私はこの記事を書くことに非常に誇りを持っており、興味を持っています。これを実現する良い方法は、両方のEAを1つに統合することですが、それについてはすでに記事があるので、ここにリンクを貼っておきます (「MQL5でONNXモデルをアンサンブルする方法の例」)。
まず、EAを使用してフィルタありとなしのモデルを比較し、データのフィルタがどのような影響を与えるかを確認します。その後、グラフを使用して季節性について議論し、最終的に2024年 2月を実際に季節性ありとなしで研究します。記事の最後の部分では(非常に興味深いと思います)、「MQL5でONNXモデルを使用する方法」稿ですでに得たEAに対する他のアプローチについて説明し、EAとONNXモデルを微調整することで利益を得られるかどうかを見てみます(答えは「得られる」です)。
これを実現するために、まずこの「Download all data from a symbol」スクリプトでデータ(すべてのティック)をダウンロードします(このスクリプトを購入してこの記事をサポートしてください)。このスクリプトを調べたい銘柄・チャートに追加するだけで、しばらく(1時間以内)すれば、その銘柄の過去のティックがすべてFilesフォルダにダウンロードされます。
すべてのティックをダウンロードしたら、そのcsvを操作して、必要な、あるいは欲しいデータ(この場合は2015年1月から2月までの期間から2023年までの期間)だけを抽出します。
季節性
取引における季節性とは、年間を通じて予測可能な資産価格の定期的な変動と変動を見極めることです。ある銘柄が他の銘柄よりも特定の時期に良い結果を出す傾向があることを認識するようなものです。この考えを少し紐解いてみましょう。
取引における季節性を理解します。
- 定義:季節性とは、価格が時期によって繰り返し変動する傾向にあることに気づくことです。これは、実際の季節(夏や冬など)、商業シーズン(休日の雑踏など)、あるいは特定の月と関連付けることもできます。
- 例:賢明な投資家が注意するパターンの例をいくつか挙げます。
- 天候に左右される季節性:天候が農繁期に影響を与えるように、天候は商品価格や関連銘柄などにも影響を与えます。例えば、ビーチ用品を販売する会社では、夏場は売上が伸びるが、寒くなると落ち込み、株価に影響を与えるかもしれません。
- 祝日の季節性:小売株は、祝日商戦の熱狂の中でしばしば上昇します。ギフトショップのような祝日商戦に強い企業は、この時期に輝きを増す傾向があります。
- 四半期業績の季節性:上場企業は四半期ごとに決算を発表しており、株価はこの時期に予想通りの反応を示します。
- 税務の季節性:税務関連の出来事は、特に金融に関連するセクターにとっては市場を揺るがす可能性があります。
- 自然のサイクル:観光業やエネルギー産業には、夏のバカンスや冬の暖房需要など、季節ごとの需要パターンがあります。
季節性に基づく取引戦略:
- トレーダーはいくつかの方法で季節性を活用することができます。
- 季節のパターンを見極める:過去のデータを調べ、特定の時期に繰り返される傾向を見つけます。
- 取引タイミング:こうした季節的なトレンドに基づいて、ポジションを建てたり決済したりします。
- リスク管理:不安定な時期にどの程度のリスクを取るかを調整します。
- セクターローテーション:1年のうち、時期によってパフォーマンスが良くなる傾向のあるセクター間で投資を切り替えます。
データのフィルタ
ここではローパスフィルタを使用します。次はウィキペディアからの引用です。
ローパスフィルタは、遮断周波数より低い周波数の成分はほとんど減衰させず、遮断周波数より高い周波数の成分を逓減させるフィルタである。フィルタの正確な周波数特性は、フィルタ設計に依存する。このフィルタは、オーディオ用途ではハイカットフィルタやトレブルカットフィルタと呼ばれることもある。ローパスフィルタはハイパスフィルタと対称の関係にある。
なぜアルゴリズム取引ではハイパスフィルタではなくローパスフィルタを選択するのでしょうか。アルゴリズム取引においてローパスフィルタが好まれるのは、いくつかの重要な利点に由来します。- シグナルの平滑化:ローパスフィルタはノイズの多い値動きを効果的に平滑化し、短期的な変動よりも長期的なトレンドを強調します。
- 高周波ノイズの低減:ローパスフィルタは、取引戦略にとって意味のある情報を提供しない可能性のある高周波ノイズを減衰させるのに役立ちます。
- 取引コストの削減:より長期的なトレンドに注目することで、ローパスフィルタはより少ない戦略的な取引につながり、取引費用を削減できる可能性があります。
- より優れたリスク管理:ローパスフィルタは、短期的な市場変動の影響を軽減し、より安定した予測可能な取引戦略に貢献します。
- 投資ホライズンとの整合性:ローパスフィルタは、長期的な視野に立った投資戦略に適しており、長期間にわたるトレンドを効果的に捉えることができます。
個人的には、高周波をフィルタするためにローパスフィルタを使用しています。ここでハイパスフィルタを使用するのはあまり意味がありません。
これを使用します(注:結局、記事の最後の部分で、パラメータのcutoff_frequencyを0.1、cutoffとorderを1に変更しました。それの方が結果が良かったからです。また、フィルタするための正しい.pyは、記事の最後の部分のものです(そこでは、より良いパラメータを使用しただけでなく、フィットとインバースにminmaxscalerも使用しました))。
# Low-pass filter parameters cutoff_frequency = 0.01 # Cutoff frequency as a proportion of the Nyquist frequency order = 4 # Apply the low-pass filter def butter_lowpass_filter(data, cutoff, fs, order): nyquist = 0.5 * fs normal_cutoff = cutoff / nyquist b, a = butter(order, normal_cutoff, btype='low', analog=False) print("Filter coefficients - b:", b) print("Filter coefficients - a:", a) y = lfilter(b, a, data) return y filtered_data_low = butter_lowpass_filter(df2['close'], cutoff_frequency, fs=1, order=order)
ここでは onnx_LSTM_simple_filtered.pyとonnx_LSTM_simple_not_filtered.pyを使用してONNXモデルを作り、比較します。
注:ローパスフィルタのパラメータが異なるモデルv1とモデルv2を使用しました。
これがその結果です。
EAには同じ入力を使用します。
研究期間は2月1日から3月1日までです。
フィルタなしモデルの場合:
RMSE : 0.0010798043714784716 MSE : 1.165977480664017e-06 R2 score : 0.8799146678247277
フィルタ付きV1
# Parámetros del filtro pasa bajo cutoff_frequency = 0.01 # Frecuencia de corte en proporción a la frecuencia de Nyquist order = 4
RMSE : 0.0010228999869332884 MSE : 1.0463243832681218e-06 R2 score : 0.8922378749062259
フィルタ付きV2
cutoff_frequency = 0.1 # Frecuencia de corte en proporción a la frecuencia de Nyquist order = 2
RMSE : 0.0010899163515744447 MSE : 1.1879176534293484e-06 R2 score : 0.8775550550819025
フィルタの結論
正しいパラメータを使用した場合のみ、より良い結果が得られます。よって、フィルタの使用は便利です。
使用コードとモデル
ONNX.eurusd.H1.120.Prediction_FILTERED.mq5
ONNX.eurusd.H1.120.Prediction_FILTERED_v2.mq5 ONNX.eurusd.H1.120.Prediction_NOT_FILTERED.mq5のダウンロード onnx_LSTM_simple_EURUSD_filtered.pyonnx_LSTM_simple_EURUSD_not_filtered.py
銘柄からすべてのデータをダウンロードする: EURUSD_LSTM_120_1h_not_filtered.onnx EURUSD_LSTM_120_1h_filtered_v1.onnx EURUSD_LSTM_120_1h_filtered_v2.onnx銘柄には季節性があるのか?
この部分では、まずこれをグラフで見ます。2015年から2023年までの2月のデータを取得し、その週前後の動きを見るためにデータを追加します。
これがその期間から見えるものです。
結論
いくつかの傾向があることがわかります。少なくとも黒(合計線)は水平でありません。各行の間にはギャップがありますが、これは銘柄が年間を通じて取引され、価格が変動するためです。このため、この記事の次の部分では、2月のすべての銘柄を年ごとに連結します。また、このため、たとえば、2022年の最後の日付から2023年2月1日までの高頻度を通過させないため、フィルタを使用する必要があります。AIがたとえば金曜日のクローズと月曜日のオープンを学習した場合、これらの変化を学習せず、より平滑化されたデータを求めます。
スクリプトと使用データ
銘柄から全てのデータをダウンロードする Download_seasonalities_1h_v2.py data febs.zip draw_with_sum.pyこの銘柄データは相関関係があるのか?
自己相関は、連続する時間間隔の値間の類似性の程度を示すデータの特性です。
1に近い値は、大きな正の相関があることを示します。
これはautocorrelation.pyで得られた結果です。
[1. 0.99736147 0.99472432 0.99206626 0.98937664 0.98671649 0.98405706 0.98144222 0.9787753 0.97615525 0.97356318 0.97099777 0.96848029 0.96602671 0.96360361 0.96113539 0.95865344 0.95615626 0.95362417 0.95108177 0.94854957 0.94599045 0.94346076 0.94091564 0.93837742 0.93583734 0.9332909 0.93074655 0.92826504 0.92579028 0.92330505 0.92084645 0.91834403 0.91581296 0.91328091 0.91076099 0.90826447]
2月シーズン用のONNXモデルの作成
このタスクでは、すべてのデータを1つのcsvに連結し、それを使用してモデルを作るだけです。
create concatseasonal.pyを使用して1つのCSVを作成し、zip seasonal_feb_contacに追加します。onnx_LSTM_..._seasonals.pyで訓練し、モデルを作成します。
使用したスクリプトとデータ
seasonal_feb_concat.zip create_concat_seasonal_data.py
onnx_LSTM_simple_EURUSD_concat_seasonals.py
季節モデルのテスト結果と120日(1H)フィルタ付きモデルとの比較
季節モデル
RMSE : 0.013137568368684325 MSE : 0.00017259570264185493 R2 score : 0.7166764010650979
これは驚くような結果ではありませんが、全体的には良好な結果です(マイナスのシャープの結果はあまりない)。
フィルタ付きモデルと比較すると、このようになります。
私が不思議に思ったのは、フィルタモデルの最適化ではシャープ値のマイナスの数が表の半分を占めているのに対し、季節性モデルではマイナスの数が表の5分の1程度を占めていることです。これは注目すべきことで、たとえr2が低くても、利益をもたらす頑健なモデルであるように思われるからです。
SLとTPを使わずにEAをテストすることもできましたが、EAでは常にSLとTPを使用する方が良いです。
使用したコードとONNXモデル
ONNX.eurusd.H1.120.Prediction_seasonal.mq5 EURUSD_LSTM_270_1h_filtered_seasonal0.72.onnx onnx_LSTM_simple_EURUSD_concat_seasonals.py
どの時期に使用するのか?
この記事では、EURUSDでより良い結果が得られるようにフィルタを微調整しました。
cutoff_frequency = 0.1 # Frecuencia de corte en proporción a la frecuencia de Nyquist order = 1
フィルタも修正しました。
from sklearn.preprocessing import MinMaxScaler from scipy.signal import butter, lfilter # Parámetros del filtro pasa bajo cutoff_frequency = 0.1 # Frecuencia de corte en proporción a la frecuencia de Nyquist order = 1 # Aplicar filtro pasa bajo def butter_lowpass_filter(data, cutoff, fs, order): nyquist = 0.5 * fs normal_cutoff = cutoff / nyquist b, a = butter(order, normal_cutoff, btype='low', analog=False) print("Coeficientes del filtro - b:", b) print("Coeficientes del filtro - a:", a) y = lfilter(b, a, data) return y scaled = MinMaxScaler(feature_range=(0,1)) valores_df1 = df.filter(['close']).values valores_df1 = pd.DataFrame(valores_df1) x_features1 = valores_df1[[0]] valores_df2 = x_features1.values data_escalada = scaled.fit_transform(valores_df2) print(data_escalada) filtered_data_low = butter_lowpass_filter(data_escalada, cutoff_frequency, fs=1, order=order) print("filtered_data_low",filtered_data_low) filtered_data_low_unscaled = scaled.inverse_transform(filtered_data_low)
注文は整数の価格に四捨五入する必要があります。
この戦略は、1 時間間隔では1ヶ月にわたって、具体的には2024年2月にテストされます。30分間隔では、2月1日から2月15日までテストされます。
15分間隔では、フィルタを使用した場合と使用しなかった場合のテストをおこない、その結果、微調整したフィルタを使用した方が(少なくとも全体的には)良い結果が得られるという結論に達しました。
フィルタ付き15分(シャープ)
フィルタなし15分
フィルタ付き30分(以後は常にフィルタを使用)
LSTM.30m.EURUSD.120.0.94.onnx LTSM_simple_30m_filtrado.py ONNX.eurusd.H1.120.30m_eurusd.mq5
1時間
1 hour files.zip (815.64 KB)
2時間
2日間の期間を使用することができないので、1日間の期間を使用しました(EAのNextDay値)。
32以上のファイルは読み込めないので、次のファイルはすべてフォルダにアップロードされます。
結論
この戦略では、期間が長くなるにつれて、すべてのTPとSLの結果がより強固になるようです。
NextDay変数
「ONNXモデルをmql5で使用する方法」稿の戦略を使用していますが、2時間戦略で良い結果を得ているので、1日足を使用しています。他のNextDay変数値を検討します。
if(TimeCurrent()>=ExtNextDay) { GetMinMax(); //--- set next day time ExtNextDay=TimeCurrent(); ExtNextDay-=ExtNextDay%PeriodSeconds(PERIOD_D1); ExtNextDay+=PeriodSeconds(PERIOD_D1); }
void GetMinMax(void) { vectorf close; close.CopyRates(_Symbol,PERIOD_D1,COPY_RATES_CLOSE,0,SAMPLE_SIZE); ExtMin=close.Min(); ExtMax=close.Max(); }
ここでは、期間30分のEURUSDをフィルタ付きデータで、異なるNextDay期間(1日、12時間、6時間を使用)で研究し、結果を議論します。
30分(NextDayは1日)
30分(NextDayは12時間)
30分(NextDayは6時間)
NextDay変数値を微調整すると、結果は良くなるようです。NextDayが短い期間でどのように変化するか見てみましょう。
30分(NextDayは4時間)
30分(NextDayは2時間)
30分(NextDayは1時間)
少なくとも30分間では、30分間に8バーから12バー程度が良い結果をもたらすようです。
この「ゲーム」はより多くのお金を獲得することであり、そのための1つの方法は、より多くの勝ちトレードと堅実な戦略を持つことです。この戦略を使用して5分間の期間で勝つことができるかどうかを見てみましょう。NextDay変数を1時間と30分にして試してみます。
5分(NextDayは1時間)
5分(NextDayは30分)
使用ファイル: Last files.zip
他の期間はより信頼性が高いようですが、別のEAが必要な場合は、より多くのEAを使用する必要があります。
例えば、時間やバーの制限を設けるなどして、より良い結果やより堅実な結果を得ることができます。例えば、1時間の期間で、NextDayを12時間とすると、一度注文を出したら、12時間以内に決済しなければならないことにできます。
if(ExtPredictedClass>=0) { if(PositionSelect(_Symbol)) CheckForClose(); else { CheckForOpen(); started_time1 = rates[0].time; string started_time1_str = TimeToString(started_time1);
int total = PositionsTotal(); if(total>0) { datetime started_time2 = rates[0].time; string started_time2_str = TimeToString(started_time2); int segundos = started_time2 - started_time1; Print("Tiempo 1: ", started_time1_str); Print("Tiempo 2: ", started_time2_str); Print("Diferencia en segundos: ", segundos); if((segundos >= days*PeriodSeconds(PERIOD_H12)) && segundos != 0) { Print("closing position----------------"); ExtTrade.PositionClose(_Symbol,3); } }
ONNX.eurusd.120.1h_H12_eurusd.v3.mq5 (9.23 KB)
結論
季節性、フィルタ、モデルやEAの比較、EAのパラメータを見てきました。私がこの記事を作るのを楽しんだように、読者がこの記事を読むのを楽しんでくれたら幸いです。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/14424





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