
MQL5のパラボリックSARトレンド戦略による取引戦略の自動化:効果的なEAの作成
はじめに
アルゴリズム取引戦略は、トレーダーが情報に基づいた迅速な意思決定をおこなえるようにし、金融取引に革命をもたらしました。自動化されたシステムは急速に変化する市場環境において、事前に設定されたパラメータに従って動作するため、人為的な誤差や感情的なバイアスを排除します。その結果、自動取引では、システムが常に同じロジックを使用して取引を実行するため、一貫性が保たれます。
MetaTrader 5は、自動化技術を構築および実装する一般的なプラットフォームです。本記事では、パラボリックSAR指標を用いて取引を自動的に実行するEAの作成プロセスを詳しく説明します。
パラボリックSAR戦略の概要
パラボリックSAR指標:この指標は、1978年にWelles Wilderによって開発されました。この指標は、価格の上下の動きを追跡するチャート上にドットを表示し、市場トレンドの潜在的な反転ポイントを強調します。具体的には、ドットが価格の下に位置する場合、市場は上昇トレンドにあり、ドットが価格の上にある場合、市場は下降トレンドにあることを示します。この特徴により、トレンドが終了する可能性のある反転ポイントを特定するのに非常に役立ちます。
SARステップ:SARの「ステップ」は、SARドットが価格をどれだけ正確に追跡しているかを判断するための要素です。具体的には、SARのステップが低い場合、ドットは価格から遅れを取り、感度が低下します。逆に、ステップが高くなるとドットが価格に近づき、感度が高まります。これにより、トレンドの変化に対する反応が向上します。
SARドット:上限として機能する加速係数です。トレンド市場では、パラボリックSARは価格に追いつくためにステップを増やします。この特性により、トレーダーは潜在的なトレンド反転のエントリポイントとエグジットポイントを特定できます。
この戦略は、他の指標と組み合わせてより包括的なアプローチにすることも、外国為替や商品などのトレンド市場でスタンドアロン戦略として利用することもできます。
MQL5での実装
ヘッダーには、著作権やバージョン番号などの基本的なメタデータが含まれます。Trade.mqhライブラリは、ポジションのオープンとクローズといった取引操作を処理するために含まれています。
#property copyright "Copyright 2024, MetaQuotes Ltd." "Duke" #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh>
ここで、EAをカスタマイズできるようにする入力パラメータを定義しましょう。
LotSize: EAが取引の規模を決定するのに役立ちます。つまり、LotSizeが小さいと、取引サイズが小さくなるため、リスクと利益が減ります。また、LotSizeが大きいと、リスクと利益が増加することを意味します。
SAR_StepとSAR_Maximum:価格変動の検出とパラボリックSAR指標の計算におけるパラボリックSARの感度を制御します。
Slippage: EAが注文を出すときに最大許容スリッページを設定するのに役立ちます。
//--- Input parameters input double LotSize = 0.2 ; // Lot size for trading input double SAR_Step = 0.02; // Parabolic SAR step input double SAR_Maximum = 0.2; // Parabolic SAR maximum input int Slippage = 3; // Slippage for orders
取引操作を管理するために、CTradeクラスのインスタンスを作成できます。
//--- Trade object
CTrade trade;
次のステップは、EAが読み込まれたときに実行されるOnInit関数です。このシンプルなEAでは、EAログの初期化が成功したことを示す確認メッセージを出力するだけなので、EAが問題なく読み込まれて初期化されていることを確認します。この関数は、EAがデータ処理を開始する準備ができているかどうかを確認するデバッグにも役立ちます。何らかの理由で初期化が失敗し、EAの動作が停止した場合、この関数はINIT_FAILEDを返すこともできます。
int OnInit() { //--- Initialization code here Print("Parabolic SAR EA Initialized"); return(INIT_SUCCEEDED); }
OnDeint関数に移動します。EAは再コンパイルされると、チャートから削除されます。このアクションは、OnDeint関数をアクティブにしてクリーンアップ タスクを実行し、リソースが適切に解放されるようにします。このログを確認することで、EAが明示的に削除されたか、再コンパイルされたか、または端末のシャットダウンの結果であるかを判断でき、開発およびテスト段階で有益な情報を提供できます。この関数は、必要なクリーンアップ手順に拡張できます。例えば、開いているリソースを閉じたり、ファイルハンドルを解放したり、現在の状態を保存する必要があるかもしれません。
これにより、初期実行時のパフォーマンスの問題がEAの再読み込みや再起動の機能を妨げないようにし、信頼性と安定性が向上します。
void OnDeinit(const int reason) { //--- Cleanup code here Print("Parabolic SAR EA Deinitialized"); }
OnDeintの次はOnTick関数を見てみましょう。この関数はEAの中核であり、各ティックで実行されます。パラボリックSAR値を計算し、それを最終終値と比較します。この比較に基づいて、EAは買い注文を開くか売り注文を開くかを決定します。
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Get the Parabolic SAR value double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle //--- Check if there is an existing position if(!IsPositionOpen(_Symbol)) { //--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } }
理解を深めるために、OnTick関数を分解してみましょう。
- パラボリックSARの計算:コードの最初の行は、パラボリックSAR値を計算します。
double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value
iSAR():指定された期間の特定の資産のパラボリックSAR指標値を計算するためのMetaTraderプラットフォームの組み込み関数です。
_Symbol:EUR/USD、金、または現在分析しているその他の取引項目などの金融商品または取引資産を指します。
_Period: チャートの時間枠(1分、1時間、1日など)を示します。 SARの計算に使用するローソク足を決定する関数に役立ちます。
SAR_StepおよびSAR_Maximum:パラボリックSAR指標の感度を制御する固有のパラメータです。SAR_Stepは、トレンドの進行に合わせて指標を加速する増分ステップ値であり、SAR_Maximumは加速を制限して、指標が価格の変化に急速に反応するのを防ぎます。
- 前回のローソク足の終値を取得します。次の行は、最後に完了したローソク足の終値を取得します。
double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle
iClose():この関数は、チャート内の特定のローソク足の終値を返します。
_Symbolと_Period:iSAR()関数と同様に、分析対象の特定の金融商品と時間枠を参照します。
-1:このパラメータは、必要なローソク足の終値を指定します。この場合、現在のローソク足はまだ形成中であるため、1は最後に完了したローソク足(前のローソク足)を示します。
LastPriceに保存されるこの値は、最後のローソク足が閉じたときに資産が取引された最終価格レベルを表します。
パラボリックSARコードを使用して、ストップロスの設定や取引終了または反転の決定を自動化します。例えば、ロングポジションで終値がSAR値を下回った場合、トレンドの反転を示している可能性があり、トレーダーはポジションをクローズするか、ショートポジションを検討するよう促されます。EAはこの比較を使用して、市場がトレンドを継続しているか反転しているかを判断します。これにより、感情を排除し、取引に明確なシグナルを頼ることができます。
取引アルゴリズムを構築する場合、特定の資産(銘柄)のポジションがすでに開いているかどうかを確認するチェックを実装するのが一般的です。
//--- Check if there is an existing position if(!IsPositionOpen(_Symbol))
IsPositinOpen(_symbol):この関数は、銘柄「 _symbol」に現在ポジションがあるかどうかを確認します。銘柄は通常、ティッカーまたは資産コードを表します。
!IsPositionOpen(_symbol):指定された銘柄にポジションがない場合にのみ条件がtrueになることを意味します。
if文:指定された銘柄にポジションがない場合、ifブロック内のコードが実行されます。これには、新しいポジションを開くこと、取引を実行すること、または他の取引ロジックをトリガーすることが含まれる可能性があります。
したがって、この関数により、同じ銘柄に対して複数のポジションを開くことによる過剰取引が起こらないことが保証されます。これにより、システムは取引活動をより適切に管理できるようになります。
パラボリックSARはトレンドを追跡し、価格変動に合わせて調整されるトレーリングストップロスでエントリポイントとエグジットポイントを示します。クロスオーバーは潜在的なトレンド反転を示します。
//--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } }
LastPrice:取引されている資産の現在の市場価格を表します。
sar:現時点でのパラボリックSARの値です。
アルゴリズムは、この2つを比較することで、トレンドが上昇トレンドか下降トレンドかを判断し、それに応じて動作します。
売買ロジック
買い注文 :最終価格がSAR値を超えて上昇傾向を示すと、買い注文が出されます。次に、アルゴリズムは、市場がSARを上回る価格で上昇し続けるという仮定に基づいて、OpenBuyOrder()関数をトリガーして取引を実行します。
売り注文:逆に、lastPriceがSARよりも低い場合、これは市場が下降傾向にあるというシグナルとして解釈されます。アルゴリズムはOpenSellOrder()関数を呼び出して応答し、売り取引を出します。ここで、この戦略では、価格がSARを下回ったため、市場は引き続き下落する可能性があると想定しています。
コードは、まず購入注文の評価を優先します。買い注文の条件(lastprice > sar)が満たされた場合、システムは直ちに買い取引を実行します。その条件が満たされない場合、コードは売り条件(lastPrice<sar)を確認します。条件がtrueの場合、売り取引が実行されます。
次のステップ:ユーティリティ関数
ここでは、OpenPositions関数の確認から始めます。IsPositionOpen関数は、現在の取引銘柄に対して既にポジションがあるかどうかを確認します。これにより、EAが同じ方向に複数のポジションを同時に開くことが防止されます。
//+------------------------------------------------------------------+ //|Check if there is an open position for the given symbol | //+------------------------------------------------------------------+ bool IsPositionOpen(string symbol) { uint total=PositionsTotal(); //Get the total number of open positions for(uint i=0; i<total; i++) { string POSITION_SYMBOL=PositionGetSymbol(i); //Get the symbol of the position if(POSITION_SYMBOL == _Symbol) //Check if the symbol matches the current symbol { return true; } } return false; }
関数コードを次のように分解して詳細に見ていきます。
- 入力パラメータ:通貨ペアや株価表示などの目的の銘柄を表す文字列銘柄引数を取ります。
- 合計ポジションの取得:PositionsTotal()を使用して現在開いているポジションの合計数を取得します。実行時に端末で開いているポジションの数を返します。
- ポジションの反復処理:forループを使用してすべてのポジションを反復処理します。変数totalにはポジションの数が格納され、ループは0からtotal - 1まで実行されます。
- 銘柄の比較:取得した銘柄POSITION_SYMBOLは、条件「if(POSITION_SYMBOL==_SYMBOL)」を使用して現在の銘柄と比較されます。変数_Symbolは、関数が呼び出されるチャートの銘柄を表す定義済み識別子です。銘柄が一致する場合、指定された銘柄に対してすでにポジションがあることを示します。
- 戻り値:一致を見つけた場合(つまり、指定された銘柄のポジションがすでに開いている場合)、trueを返します。ループがすべてのポジションを確認した後、一致するポジションが見つからない場合、falseを返し、指定された銘柄にポジションがないことを示します。
この関数は、すでにアクティブなポジションがある場合に、アルゴリズムが同じポジションで新しいポジションを開かないようにするのに特に役立ちます。例えば、EURUSDを取引していて、関数がtrueを返した場合、この戦略では新しいポジションを開くことを回避し、代わりに既存のポジションの管理に重点を置くことができます。
次のユーティリティ関数はOpenBuyOrder()です。この関数は買い取引の実行を担当します。指定されたロット サイズで買い注文を出そうとするととも、プロセスが正しく完了したことを確認したり、何か問題が発生した場合にトレーダーに通知したりするための誤差処理も含まれています。
//+------------------------------------------------------------------+ //| Open a Buy order | //+------------------------------------------------------------------+ void OpenBuyOrder() { if(trade.Buy(LotSize, NULL, 0, 0, 0, "Buy Order")) { Print("Buy order placed successfully"); } else { Print("Error placing buy order: ", GetLastError()); } }
この関数は「void OpenBuyOrder()」として宣言されています。つまり、値は返さずに特定のタスク(この場合は買い注文の配置)を実行します。
この関数はtrade.Buy()メソッドを使用して買い注文を出します。このメソッドには次のパラメータが必要です。
- LotSize:注文のサイズを指定します。この場合は0.2です。
- Null:関数が呼び出されるチャートの現在の銘柄を参照します。この場合、NULLは現在のチャートの銘柄にデフォルト設定されます。
- 0:注文を出す価格を設定します。ゼロを使用すると、注文は現在の市場価格で実行されることを示します。
- 0:このパラメータはストップロスレベルを表します。0は、注文が開かれるときにストップロスが指定されていないことを意味します。
- 0:このパラメータはテイクプロフィットレベルです。ゼロに設定すると、最初はテイクプロフィットが設定されません。
- Buy Order: これは注文に関連付けられたコメントであり、識別のために使用されます。
注文が正常におこなわれた場合(if(trade.Buy(....)がtrueと評価された場合)、関数はPrint()関数を呼び出してメッセージ「Buy order placed successfully」をログに記録します。これにより、注文が正常に実行されたというフィードバックがトレーダーに提供されます。
注文が失敗した場合(else)、関数はエラーメッセージ「Error placing buy order」をログに記録し、その後にGetLastError()によって返される特定のエラーコードが続きます。GetLastError()関数は、システムで発生した最エラーを取得し、トレーダー開発者に問題のトラブルシューティングに役立つ貴重な情報を提供します。
最後のユーティリティ関数は、売り注文を開くためのものです。この関数は、アルゴリズム取引システムで売り注文を開くプロセスを自動化するように設計されています。OpenBuyOrder()関数のロジックを反映していますが、市場でのショート取引、つまり売り注文に合わせて調整されています。
//+------------------------------------------------------------------+ //| Open a Sell order | //+------------------------------------------------------------------+ void OpenSellOrder() { if(trade.Sell(LotSize, NULL, 0, 0, 0, "Sell Order")) { Print("Sell order placed successfully"); } else { Print("Error placing sell order: ", GetLastError()); } }
void OpenSellOrder()関数は値を返しませんが、売り注文の配置という特定のタスクの実行に重点を置いています。
trade.Sell()メソッドは売り注文を開始するために使用されます。このメソッドに渡されるパラメータは次のとおりです。
- Lotsize :売り注文のロット数を定義し、この場合は0.2です。
- NULL:関数が呼び出されている現在のチャートの銘柄を表します。nullを渡すと、関数はデフォルトで現在のチャート上の銘柄を取引するようになります。
- 0: 注文の価格を設定します。0を使用すると、注文は現在の市場価格で実行されます。
- 0: ストップロスレベルを表します。値が0の場合、注文が開かれるときにストップロスレベルが指定されていないことを意味します。
- 0:テイクプロフィットレベルを指定します。ゼロに設定すると、最初はテイクプロフィットが設定されません。
- Sell order: これは注文に添付されるコメントであり、注文の識別と追跡に役立ちます。
売り注文が正常におこなわれた場合、Print()関数を使用して成功メッセージをログに記録します。取引が実行されたことを確認するために、端末のログに「Sell order placed successfully」というメッセージが表示されます。
売り注文が何らかの理由で失敗した場合、関数はエラーメッセージ「Error placing sell order::」をログに記録し、続いて、GetLastError()によって返される特定のエラーコードが表示されます。これは、売り注文が出されなかった理由を診断するのに役立ちます。
以下は、この記事の完全なコードです。
//+------------------------------------------------------------------+ //| ParabolicSAR_EA.mq5 | //| Copyright 2024, MetaQuotes Ltd."Duke" | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." "Duke" #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> //--- Input parameters input double LotSize = 0.2 ; // Lot size for trading input double SAR_Step = 0.02; // Parabolic SAR step input double SAR_Maximum = 0.2; // Parabolic SAR maximum input int Slippage = 3; // Slippage for orders //--- Trade object CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Initialization code here Print("Parabolic SAR EA Initialized"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Cleanup code here Print("Parabolic SAR EA Deinitialized"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Get the Parabolic SAR value double sar = iSAR(_Symbol, _Period, SAR_Step, SAR_Maximum); // Calculate the Parabolic SAR value double lastPrice = iClose(_Symbol, _Period, 1); // Get the close price of the previous candle //--- Check if there is an existing position if(!IsPositionOpen(_Symbol)) { //--- Determine trade direction based on SAR if(lastPrice > sar) { OpenBuyOrder(); // If the last price is above the SAR, open a buy order } else if(lastPrice < sar) { OpenSellOrder(); // If the last price is below the SAR, open a sell order } } } //+------------------------------------------------------------------+ //|Check if there is an open position for the given symbol | //+------------------------------------------------------------------+ bool IsPositionOpen(string symbol) { uint total=PositionsTotal(); //Get the total number of open positions for(uint i=0; i<total; i++) { string POSITION_SYMBOL=PositionGetSymbol(i); //Get the symbol of the position if(POSITION_SYMBOL == _Symbol) //Check if the symbol matches the current symbol { return true; } } return false; } //+------------------------------------------------------------------+ //| Open a Buy order | //+------------------------------------------------------------------+ void OpenBuyOrder() { if(trade.Buy(LotSize, NULL, 0, 0, 0, "Buy Order")) { Print("Buy order placed successfully"); } else { Print("Error placing buy order: ", GetLastError()); } } //+------------------------------------------------------------------+ //| Open a Sell order | //+------------------------------------------------------------------+ void OpenSellOrder() { if(trade.Sell(LotSize, NULL, 0, 0, 0, "Sell Order")) { Print("Sell order placed successfully"); } else { Print("Error placing sell order: ", GetLastError()); } }
ここまでで、EAを実装しました。
以下はバックテストの結果です。
テストはM1チャートのUSDJPYでおこなわれました。テスト期間は2024.01.01から2024.08.05まででした。モデリングのタイプは「すべてのティック」です。
以下はテストプロセスで使用される入力パラメータです。
M1チャートでいくつかのテストをおこなった結果、次のことがわかりました。
- この戦略はUSDJPYとEURUSDに適している
- この戦略はGBPUSDではうまく機能しない
結論
結果から、このシンプルなEAは、さらなる改良と適応を通じて、トレーダーに良好な結果をもたらす可能性があることが示唆されます。具体的には、EAの管理を強化し、資産の高リスクへの露出を減少させることが重要です。これには、市場が有利に動いた際に利益を確保するためのトレーリングストップの追加や、その他のリスク管理機能の実装が含まれます。さらに、パラメータの最適化や複数のテスト、SARステップや最大値などの設定の微調整によって、さまざまな市場状況で最適なパフォーマンスを実現することが可能です。
免責事項:このコードは、トレーダーがパラボリックSAR戦略の実装の基本を理解するための参考を目的としていますが、バックテストから得られるデモ結果がEAの将来の取引パフォーマンスを保証するものではありません。
実稼働前には、徹底したバックテストとフォワードテストを実施することが重要です。これにより、予期しない損失を防ぎ、迅速な調整を行うためには継続的な監視が不可欠です。この戦略で取引を自動化することで、人的誤差や疲労を最小限に抑え、カスタマイズ、最適化、テストを通じて収益性の高い取引システムを構築できます。したがって、このタイプの自動化を導入することで、取引の機会をより効率的に活用し、パフォーマンスを向上させることができます。この記事では、パラボリックSAR戦略の実装に必要な知識とスキルを提供してきましたが、さらなるリソースについてはMQL5プラットフォームからアクセス可能です。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/15589
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索
ディープラーニングモデルとPSARは素晴らしい結果をもたらします。
dlとPSARの使い分けについて教えてください。
https://www.mql5.com/ja/articles/15589
グッドジョーク
それはいいことだ。
悪くないね。
それがなければ、私はそれに気づかなかっただろう:
ウェブサイトの記事の日付は2025年3月10日で、最初のコメントは2024年8月26日。)
"空に浮かぶ暗い水"
ウェブサイトでは、記事の日付は2025年3月10日、最初のコメントは2024年8月26日となっている。)
これは翻訳された日付だ。元の記事は 2024年8月23日に掲載された。