
平均足と移動平均を組み合わせると良好なシグナルを提供できるのか
はじめに
戦略を組み合わせることで、より良い機会が得られる可能性があります。指標を組み合わせたり、パターンを組み合わせたり、さらに良いことに指標とパターンを組み合わせたりして、追加の確認要素を得ることができます。この記事では、トレンド確認テクニックとして移動平均線と並行して平均足チャートを使用する方法を説明します。そして最後に、最適化オプションを見てみましょう。
平均足ローソク足法
ローソク足は、OHLCデータを理解し、パターンを検出する簡単な方法です。非常に単純明快で解釈しやすいです。強気のローソク足 (通常は緑色) は、市場が始値を上回って終了したときに発生します。弱気のローソク足 (通常は赤色) は、市場が始値を下回って終了したときに発生します。
ローソク足がどのように表示されるかをよりよく理解するために、ローソク足の完全なチャートを見てみましょう。トレンドは明らかに強気であり、赤いローソク足の周囲でいくつかの修正が見られます。始値が終値とほぼ同じである小さなローソク足に注目してください。これは「同事」と呼ばれ、優柔不断と反転または統合の可能性を示します。
平均足ローソク足は、OHLCデータを平滑化することで全体像を整理し、より明確なトレンドを示すことを目指しています。平均足ローソク足の計算方法は次のとおりです。
(始値+高値+安値+終値) ÷ 4
平均足高値=最大値(高値-0、始値-0、終値-0)
平均足安値=最小値(安値-0、始値-0、終値-0)
平均足は「平均ペース」を意味する日本の取引指標および財務チャートです。 平均足チャートはローソク足チャートに似ていますが、ローソク足のようにすべての価格の動きを追跡するのではなく、さまざまな価格の動きを追跡するため、より滑らかな外観を持っています。平均足は、ローソク足チャートも作成した本間宗久によって1700年代に作成されました。これらのチャートは、トレーダーや投資家が価格変動の決定と予測に使用します。
標準的なローソク足と同様、平均足ローソクには実体と髭がありますが、ローソク足チャートとは目的が違います。 平均足ローソクの最終価格は、現在のバーまたは時間枠の平均価格によって計算されます(たとえば、日次時間枠では、各バーがその特定の日の価格変動を表します)。平均足バーまたはローソク足の最終価格の計算式は、(始値 + 高値 + 安値 + 終値) ÷ 4 です。 平均足の始値は、前のローソク足の中間点から始まります。これは、(前のバーの始値 + 前のバーの終値) ÷ 2 によって計算されます。 最高価格ポイントと最低価格ポイントは、ローソク足と同様に髭で表されます。
上記の公式はローソク足を平滑化し、より明確で明確なトレンドを与えます。
2 つのチャートは、通常のローソク足チャートと平均足チャートの比較です。類似していることがわかりますが、最初の方がスムーズであることもわかります。ただし、平均足法はあくまで平均値であるため、表示されている価格が真の市場価格ではない場合があることに注意してください。
移動平均の概念
移動平均はトレンドを確認し、それに乗るのに役立ちます。これらは、そのシンプルさと、分析に付加価値をもたらす実証済みの実績により、最もよく知られているテクニカル指標です。これらを使用して、支持と抵抗のレベル、ストップとターゲット、および基本的なトレンドを見つけることができます。この多用途性により、これらは取引の武器庫に不可欠なツールとなっています。
統計における移動平均は、完全なデータセットのさまざまな選択の一連の平均を作成することによって、データポイントを分析するための計算です。これは、移動平均(MM)またはローリング平均とも呼ばれ、有限インパルス応答フィルターの一種です。バリエーションには、単純な形式、累積形式、または重み付けされた形式 (後述) が含まれます。
移動平均フィルターは、特にデシメーションが後に続く場合、ボックスカーフィルターと呼ばれることもあります。
一連の数値と固定サブセットサイズが与えられると、移動平均の最初の要素は、数値系列の最初の固定サブセットの平均を取ることによって取得されます。次に、サブセットは「前方シフト」によって変更されます。つまり、系列の最初の数値を除外し、サブセット内の次の値を含めます。
移動平均は、短期的な変動を平滑化し、長期的な傾向やサイクルを強調するために時系列データでよく使用されます。短期と長期の間の閾値はアプリケーションによって異なり、移動平均のパラメータはそれに応じて設定されます。経済学では、国内総生産、雇用、その他のマクロ経済時系列を調べるためにも使用されます。数学的には、移動平均は畳み込みの一種であるため、シグナル処理で使用されるローパスフィルターの一例とみなすことができます。非時系列データで使用される場合、移動平均は時間との特別な関係なしに高周波成分をフィルタリングしますが、通常は何らかの順序付けが暗示されます。単純化して考えると、データを平滑化すると考えることができます。
名前が示すように、これは単純な平均値であり、統計や基本的に私たちの生活の他のあらゆる部分で使用されています。これは、単に観測値の合計値を観測値の数で割ったものです。数学的に言えば、次のように書き表すことができます。
移動平均が、市場が下落した場合に注文できる適切な動的の支持と抵抗のレベルを提供していることがわかります。
プラン
他の適切な調査方法と同様に、目的は戦略をテストし、既存の取引フレームワークへのアドオンとして価値があるかどうかを自分の目で確認できるようにすることです。
最初のステップは取引ルールの作成です。システムはいつ買い、いつ売るのでしょうか。言い換えれば、現在の市場が上昇するか下降するかをシステムに伝えるシグナルはいつ与えられるのでしょうか。
選択できる取引条件は次のとおりです。
- 平均足チャートが強気で、市場が100期間移動平均線を上回ったときに買います。
- 市場が100期間移動平均を下回っている間に平均足チャートが弱気になった場合は、売ります。
取引アルゴリズムを開発するときは、シグナルの頻度を念頭に置く必要があります。シグナル関数は前述の条件に基づいてトリガーを生成するために使用されます。
結果
これらは、2022年1月1日から2023年7月5日までの、30分間のEURUSD銘柄の結果です。最適化やその他の期間を使用すると、より良い結果が得られるはずです。すべての銘柄で使用するには、最適化とテストが必要です。
コード
int OnInit() { //--- handle_iCustomMA=iCustom(_Symbol,my_timeframe,"\\folder/s where you have the indicator\\sma",MAPeriod,MAShift); handle_iCustomHeiken=iCustom(_Symbol,my_timeframe_Heiken,"\\folder/s where you have the indicator\\Heiken_Ashi_copy"); //--- if(handle_iCustomMA==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d", _Symbol, EnumToString(my_timeframe), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } if(handle_iCustomHeiken==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d", _Symbol, EnumToString(my_timeframe_Heiken), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } return(INIT_SUCCEEDED); }
このコードは、MQL5言語で2つのカスタム指標を初期化するために使用されます。最初の指標は、MAPeriodおよびMAShiftパラメーターを備えた単純移動平均(SMA)です。2番目の指標は平均足のコピーです。コードは各指標のハンドルを作成し、エラーをチェックします。エラーが見つかった場合、コードはエラーコードを出力し、INIT_FAILED値を返します。エラーが見つからなかった場合、コードは INIT_SUCCEEDED値を返します。
void OnTick() { double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[]; CopyBuffer(handle_iCustomHeiken,0,0,2,heikenAshiOpen); CopyBuffer(handle_iCustomHeiken,1,0,2,heikenAshiHigh); CopyBuffer(handle_iCustomHeiken,2,0,2,heikenAshiLow); CopyBuffer(handle_iCustomHeiken,3,0,2,heikenAshiClose); Comment("heikenAshiOpen ",DoubleToString(heikenAshiOpen[0],_Digits), "\n heikenAshiHigh ",DoubleToString(heikenAshiHigh[0],_Digits), "\n heikenAshiLow ",DoubleToString(heikenAshiLow[0],_Digits), "\n heikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits)); //--- MqlTick tick; double last_price = tick.ask; SymbolInfoTick(_Symbol,tick); int total = PositionsTotal(); //--- // Retrieve the current value MqlTradeResult result; MqlRates rates[]; //--- double array_ma[]; ArraySetAsSeries(array_ma,true); int start_pos2=0,count2=5; if(!iGetArray2(handle_iCustomMA,0,start_pos2,count2,array_ma)) return; //------------------------------------------------------------------------------ { if(DoubleToString(heikenAshiClose[0],_Digits) < DoubleToString(heikenAshiOpen[0],_Digits) && (DoubleToString(heikenAshiClose[1],_Digits) > DoubleToString(heikenAshiOpen[1],_Digits))) { Print("Open Order Buy"); Alert(" Buying"); Orden="Buy"; sl=NormalizeDouble(tick.ask - ptsl*_Point,_Digits); tp=NormalizeDouble(tick.bid + pttp*_Point,_Digits); trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,get_lot(tick.bid),tick.bid,sl,tp,"Buy"); return; } } { if(DoubleToString(heikenAshiClose[0],_Digits) > DoubleToString(heikenAshiOpen[0],_Digits) && (DoubleToString(heikenAshiClose[1],_Digits) < DoubleToString(heikenAshiOpen[1],_Digits))) { Print("Open Order Sell"); Alert(" Selling"); Orden="Sell"; sl=NormalizeDouble(tick.bid + ptsl*_Point,_Digits); tp=NormalizeDouble(tick.ask - pttp*_Point,_Digits); trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,get_lot(tick.ask),tick.ask,sl,tp,"Sell"); return; } } if(total>0) { if(Orden=="Sell" &&(DoubleToString(heikenAshiClose[0],_Digits) < DoubleToString(heikenAshiOpen[0],_Digits) )) { trade.PositionClose(_Symbol,5); Print("cerró sell"); return; } if(Orden=="Buy" &&(DoubleToString(heikenAshiClose[0],_Digits) > DoubleToString(heikenAshiOpen[0],_Digits) )) { trade.PositionClose(_Symbol,5); Print("cerró buy"); return; } } }
このコード部分は、外国為替市場でポジションをオープンおよびクローズするために使用されるMQL5スクリプトです。まず、4つのdouble型配列(heikenAshiOpen、heikenAshiHigh、heikenAshiLow、heikenAshiClose) を宣言し、カスタム指標「iCustomHeiken」から値をコピーします。次に、銘柄から現在のティックデータを取得し、MqlTradeResult配列とMqlRates配列を宣言します。次に、移動平均の配列(array_ma)を宣言し、その配列を系列として設定します。次に、カスタム指標「iCustomMA」から値を取得し、array_ma配列に保存します。最後に、現在の平均足の終値が始値より低く、前回の平均足の終値が始値より高いかどうかを確認し、高い場合は、指定されたストップロスとテイクプロフィットで買い注文を開きます。また、現在の平均足の終値が始値より高く、前回の平均足の終値が始値より低いかどうかも確認し、そうであれば、指定されたストップロスとテイクプロフィットで売り注文をオープンします。オープンポジションがある場合、平均足の終値が売り注文の始値より低く、買い注文の始値より高いかどうかを確認し、そうであればポジションを決済します。
明確にするために、CopyBufferの2番目のintはカウントを開始する位置の値であり、2番目はカウント数の値です。1-n(この場合は直前の平均足ローソク足)を考慮するために、1つではなく2つを使用しました。これは、注文をオープンするか否かのために、if条件で色の変化を確認するために戦略で使用されています。
注文を開くか閉じるための2つのif条件は、コード内で変更する必要があります。たとえば、注文を開く前に同じ色のローソク足をさらに使用したり、別の色の2番目のローソク足にスキップして注文を閉じることができます。
注文を閉じるもう1つの良い解決策は、異なる期間の別のSMAを使用し、クロスシグナルを使用して注文を閉じることです。次の画像は例です。
//+------------------------------------------------------------------+ double get_lot(double price) { if(inp_lot_type==LOT_TYPE_FIX) return(normalize_lot(inp_lot_fix)); double one_lot_margin; if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,one_lot_margin)) return(inp_lot_fix); return(normalize_lot((AccountInfoDouble(ACCOUNT_BALANCE)*(inp_lot_risk/100))/ one_lot_margin)); } double normalize_lot(double lt) { double lot_step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); lt = MathFloor(lt / lot_step) * lot_step; double lot_minimum = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); lt = MathMax(lt, lot_minimum); return(lt); } bool iGetArray2(const int handle2,const int buffer2,const int start_pos2, const int count2,double &arr_buffer2[]) { bool result2=true; if(!ArrayIsDynamic(arr_buffer2)) { //if(InpPrintLog) PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__); return(false); } ArrayFree(arr_buffer2); //--- reset error code ResetLastError(); //--- fill a part of the iBands array with values from the indicator buffer int copied2=CopyBuffer(handle2,buffer2,start_pos2,count2,arr_buffer2); if(copied2!=count2) { //--- if the copying fails, tell the error code //if(InpPrintLog) PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d", __FILE__,__FUNCTION__,count2,copied2,GetLastError()); //--- quit with zero result - it means that the indicator is considered as not calculated return(false); } return(result2); }
このコードは、取引のロットサイズを計算するMQL5の関数です。この関数は、priceと呼ばれるdouble型変数を受け取り、それを使用してロットサイズを計算します。
この関数はまずロットタイプが固定されているかどうかを確認し、固定されている場合は正規化されたロットサイズを返します。そうでない場合は、1ロットの証拠金を計算し、口座残高とリスクの割合に基づいてロットサイズを計算します。次に、正規化されたロットサイズを返します。
次に、normalize_lot関数を使用して、ロットサイズを最も近いステップサイズに丸め、ロットサイズが最小ロットサイズより小さくならないようにします。
次に、iGetArray2関数を使用して指標バッファから値をコピーし、エラーがないかを確認します。エラーが見つかった場合、関数はfalseを返します。
結論
平均足を別の指標で使用する方法を見てきました。
明らかに、シグナルの頻度を調整して品質を向上させるために、ここで多くの最適化をおこなうことができます。
- 連続したローソク足の後にシグナルをトリガーする平均足チャートに関連する条件を選択します。
- 移動平均の振り返り期間を調整します。他の移動平均を追加し、市場価格と単一の移動平均の単純なクロスではなく、移動平均のクロスに戦略を切り替えることもできます。
- 平均足にローソク足チャートを含めたり、移動平均と組み合わせたりすることができます。
- また、リスクの尺度として、または逆張りのトリガーとして、移動平均に近い平均足の距離を含めることもできます。
- ローソクの実体の幅をトレンドの強さの尺度として使用できます。移動平均の急峻度を式に含めることもできます。
この戦略を実装する方法を学び、カスタム 指標を実装する方法も学びました。固定ロットまたはリスクの割合のあるロットを使用することを学びました。注文のオープンとクローズの方法、および注文の条件の使用方法を学びました。平均足指標とMA指標にはcopybufferを使用しました。有益なテストを実行し、結果を示しました。StopLossとTakeProfitのポイントを追加し、銘柄の桁数で正規化する方法を学びました。ロットを正規化するために銘柄ボリュームステップと銘柄ボリューム最小値を使用しました。
この記事が気に入っていただければ幸いです。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/12845





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