
MQL5を使用したカスタムTrue Strength Index指標の作成方法
はじめに
テクニカル指標は、適切に使用すれば、プライスアクションを見るだけでは発見しにくい新たな洞察を与えてくれる可能性があるため、非常に有用です。テクニカル指標には、すぐに使えるものがたくさんありますが、時には、それらをカスタマイズして、特定の洞察を示したり、あるいは勝つためのアイデアに基づいて新しいものを作成する必要があることに気づくかもしれません。このようなカスタマイズされた指標をMQL5で作成し、MetaTrader 5の取引プラットフォームで使用する方法があります。今回は、TSI指標をゼロから作成する方法を紹介します。この指標の仕様を学び、コードで計算する方法を確認します。それだけでなく、このカスタマイズされた指標を、EAを作成することによって、取引戦略に基づいた取引システムで使用する方法を学びます。以下のトピックを通じて、そのすべてをカバーします。
前述のトピックを理解した後、TSI指標の使用方法と解釈をよく理解し、それを計算し、MetaTrader 5で使用するMQL5言語のカスタム指標としてコード化することができるようになるはずです。また、他の取引やEAに指標を実装することもできるようになります。コーディングスキルを伸ばしたいのであれば、この練習はあらゆる学習プロセスやロードマップにおいて非常に重要なステップであるため、ここにあるコンテンツを自分でコーディングしてみることをアドバイスします。MetaTrader 5を使用して、MQL5のコードをMetaTrade r5取引ターミナルに組み込まれているIDEで記述します。プラットフォームをお持ちでない方、ダウンロードや使い方がわからない方は、以前の記事の「MetaEditorでMQL5コードを書く」トピックをお読みください。
TSI (True Strength Index)の定義
この部分では、TSI (True Strength Index)テクニカル指標を正しく理解するために、TSIについて学びます。TSIは、ウィリアム・ブラウが開発したテクニカル指標で、値動きの勢いを測る、つまり強いのか弱いのかを測る指標です。ゼロライン付近で振動するので、モメンタムオシレーターです。シグナルラインを併用することで、これらのライン間のクロスオーバーに基づき、追加の売買シグナルを得ることができます。ただし、TSIラインのみでも、ゼロレベルとのクロスオーバーを基準にシグナルを得ることができます。ゼロラインより上にあれば強気の勢い、下にあれば弱気の勢いを意味します。買われすぎや売られすぎの領域を検出したり、強気や弱気の乖離を検出するために使用することができます。証拠の重みを増加させるために、そのシグナルを確認する必要があることは分かっているので、より良い洞察を得るためにプライスアクションの同じコンテキストで使用する必要があり、他の技術的なツールを伴ってそれを使用することをお勧めします。
では、この指標の計算方法を説明します。計算は、いくつかのステップでおこなわれます。
二重平滑化した運動量を計算する
- 現在の価格から前の価格を引いて運動量(価格変化)を計算する
- 算出された運動量の25周期EMAを取得して1回目の平滑化を算出する
- 1回目の平滑化の13周期EMA(算出されたモメンタムの25周期EMA)を取得して2回目の平滑化を算出する
二重平滑化した絶対運動量を計算する
- 絶対的な現在の価格から絶対的な前の価格を引くことで絶対的な勢いを計算する
- 算出した絶対運動量の25周期EMAを取得して1回目の平滑化を計算する
- 1回目の平滑化の13周期EMA(算出した絶対運動量の25周期EMA)を取得して2回目の平滑化を算出する
TSI = 100 * (二重平滑化運動量/二重平滑化絶対運動量)で算出
この計算は、ゼロを中心とした振動線となり、値動きの勢いを測定し、これまで述べてきたような買われすぎや売られすぎの領域を検出することができます。
カスタムSimple TSI指標
プログラミング言語MQL5には、あらかじめ定義されたテクニカル指標がたくさんあり、定義された関数を使うことで、それらをシステムで使うことができます。この連載の過去の記事では、すでに多くのそのような指標について話し、これらの人気のあるテクニカル指標に基づいて取引システムを設計する方法について議論しています。過去の記事を確認すれば、何か役に立つことがあるかもしれません。問題は、標準のプラットフォーム配信パッケージに指標が存在しない場合、どのように指標を作成するか、あるいは存在する場合でも、目的のシグナルやトリガーを得るためにカスタマイズした指標を作成するかということです。簡単に言うと、主なプログラミング言語を使用してカスタム指標を作成することであり、この部分ではこれをおこなうことになります。
MQL5を使用して、カスタムTrue Strength Index指標を作成する方法を学びます。そして、その機能を他のシステムやEAで使っていきます。以下の手順は、このカスタム指標を作成するためのものです。
パラメータを追加で作成するには、#propertyを使用し、その横に識別子の値を指定することになります。
- indicator_separate_window:指標を別のウィンドウに表示
- indicator_buffers:指標のバッファ数(8を使用)
- indicator_plots:指標のグラフィックシリーズの数(1を使用)
- indicator_label1:グラフィックシリーズの番号のラベル(TSIを使用)
- indicator_type1:グラフィカルなプロットの種類(ENUM_DRAW_TYPEの値からDRAW_LINEを使用)
- indicator_color1:表示される指標のラインの色(clrBlueを使用)
- indicator_style1:指標のラインのスタイル(STYLE_SOLIDを使用)
- indicator_width1:指標の線の太さ(3を使用)
#property indicator_separate_window #property indicator_buffers 8 #property indicator_plots 1 #property indicator_label1 "TSI" #property indicator_type1 DRAW_LINE #property indicator_color1 clrBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 3
MovingAverage.mqhのコンポーネントを計算に使用するために、MovingAverage.mqhファイルをインクルードする必要があります。#includeコマンドを使用してIncludeファイル内に存在させます。必ず次のようにファイル名を書いてください。
#include <MovingAverages.mqh>
プログラムで指定されたデフォルト値を更新する必要がある場合、ユーザーがこれらの値を入力するための入力クラスを使用して、指標の計算で使用する平滑化期間の2つの入力を設定する必要があります。その後、宣言する変数(InpSmPeriod1、InpSmPeriod2)のデータ型を、符号なし整数であるuintとして指定します。そして、InpSmPeriod1には25、InpSmPeriod2には13をデフォルト値として割り当てます。
input uint InpSmPeriod1 = 25; // Smoothing period 1 input uint InpSmPeriod2 = 13; // Smoothing period 2
平滑化期間(smperiod1、smperiod2)用の整数変数を2つ作成します。
int smperiod1; int smperiod2;
指標バッファ用の7つの配列を作成します。
double indBuff[]; double momBuff[]; double momSmBuff1[]; double momSmBuff2[]; double absMomBuff[]; double absMomSmBuff1[]; double absMomSmBuff2[];
OnInit()関数の中で、次のような手順をとります。
InpSmPeriod1、InpSmPeriod2のユーザー入力が2未満の場合は2の値を、それ以外の場合はInpSmPeriod1、InpSmPeriod2の値を返すことで、smperiod1、smperiod2の変数を宣言します。
smperiod1=int(InpSmPeriod1<2 ? 2 : InpSmPeriod1); smperiod2=int(InpSmPeriod2<2 ? 2 : InpSmPeriod2);
SetIndexBuffer関数を使って、指標バッファを配列と結合します。パラメータは次の通りです。
index:指標バッファの番号(0から7までの数字を設定)
buffer[]:カスタム指標で宣言された配列
data_type:指標配列に格納されるデータの種類
SetIndexBuffer(0,indBuff,INDICATOR_DATA); SetIndexBuffer(2,momBuff,INDICATOR_CALCULATIONS); SetIndexBuffer(3,momSmBuff1,INDICATOR_CALCULATIONS); SetIndexBuffer(4,momSmBuff2,INDICATOR_CALCULATIONS); SetIndexBuffer(5,absMomBuff,INDICATOR_CALCULATIONS); SetIndexBuffer(6,absMomSmBuff1,INDICATOR_CALCULATIONS); SetIndexBuffer(7,absMomSmBuff2,INDICATOR_CALCULATIONS);
対応する指標プロパティの値を設定します。この指標プロパティ(prop値)は、プロパティ識別子のみを指定して呼び出すバリアントでIndicatorSetString関数を使用することにより、文字列型である必要があります。この手順では、指標の短い名前を設定し、指標ウィンドウの左上部分に表示させる期間を決定します。そのパラメータは次の通りです。
- prop_id:ENUM_CUSTOMIND_PROPERTY_STRING列挙の1つである指標プロパティの識別子(INDICATOR_SHORTNAMEを使用)
- prop_value:プロパティの値(文字列データ型で、"True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")")
IndicatorSetString(INDICATOR_SHORTNAME,"True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")");
indicatorSetIntegerを使用し、プロパティ識別子のみを指定して呼び出すバリアントで、指標プロパティの別の値を整数データ型で設定し、指標の値を桁ごとに正規化します。そのパラメータは次の通りです。
- prop_id:指標となるプロパティの識別子(ENUM_CUSTOMIND_PROPERTY_INTEGER列挙のいずれかで、INDICATOR_DIGITSを使用)
- prop_value:プロパティの値(整数データ型、Digits()を使用)
IndicatorSetInteger(INDICATOR_DIGITS,Digits());
ArraySetAsSeriesを用いて配列にAS_SERIESフラグを設定します。
ArraySetAsSeries(indBuff,true); ArraySetAsSeries(momBuff,true); ArraySetAsSeries(momSmBuff1,true); ArraySetAsSeries(momSmBuff2,true); ArraySetAsSeries(absMomBuff,true); ArraySetAsSeries(absMomSmBuff1,true); ArraySetAsSeries(absMomSmBuff2,true);
OnCalculate関数の後は次をおこないます。
- OnCalculate部分でclose配列にAS_SERIESフラグを設定し、rates_totalが2未満であれば0を返す
- rates_total-prev_calculatedと等しくなるように整数型の変数limitを作成する
- limit変数が1より大きいかどうかを確認し、大きい場合、以下の手順を実行。
- rates_total-2の結果でリミット変数を更新
- ArrayInitialize関数を用いて、double型の数値配列をあらかじめ設定した値で初期化(パラメータは、初期化する数値配列を指定するarray[]と、設定する新しい値を指定するvalue)
ArraySetAsSeries(close,true); if(rates_total<2) return 0; int limit=rates_total-prev_calculated; if(limit>1) { limit=rates_total-2; ArrayInitialize(indBuff,EMPTY_VALUE); ArrayInitialize(momBuff,0); ArrayInitialize(momSmBuff1,0); ArrayInitialize(momSmBuff2,0); ArrayInitialize(absMomBuff,0); ArrayInitialize(absMomSmBuff1,0); ArrayInitialize(absMomSmBuff2,0); }
momBuff[i]、absMomBuff[i]を更新するためのループを作成します。この手順で使用した新しい関数は、以下の通りです。
- 3つの式と実行可能な演算子を持つ、forループの操作
- IsStopped()で、mql5プログラムの強制シャットダウンがあるかどうかを確認
- MathAbsは絶対値(モジュラス)を返す関数で、febs()関数と同じ結果
for(int i=limit; i>=0 && !IsStopped(); i--) { momBuff[i]=close[i]-close[i+1]; absMomBuff[i]=MathAbs(momBuff[i]); }
MovingAverageインクルードファイルのExponentialMAOnBuffer関数を使って、以下のことを確認します。
if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,momBuff,momSmBuff1)==0) return 0; if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,absMomBuff,absMomSmBuff1)==0) return 0; if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,momSmBuff1,momSmBuff2)==0) return 0; if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,absMomSmBuff1,absMomSmBuff2)==0) return 0;
for関数でindBuff[i]変数を更新するループをもう1つ作ります。
for(int i=limit; i>=0 && !IsStopped(); i--) indBuff[i]=(absMomSmBuff2[i]!=0 ? 100.0*momSmBuff2[i]/absMomSmBuff2[i] : 0);
プログラムの最後に、return(rates_total)関数があります。
return(rates_total);
これでTSIカスタム指標を作成するコードは終了です。また、コードに環境設定を編集して、さらにカスタマイズすることもできます。以下は、この作成した指標の1ブロックの全コードです。
//+------------------------------------------------------------------+ //| simple TSI.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property indicator_separate_window #property indicator_buffers 8 #property indicator_plots 1 #property indicator_label1 "TSI" #property indicator_type1 DRAW_LINE #property indicator_color1 clrBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 3 #include <MovingAverages.mqh> input uint InpSmPeriod1 = 25; // Smoothing period 1 input uint InpSmPeriod2 = 13; // Smoothing period 2 int smperiod1; int smperiod2; double indBuff[]; double momBuff[]; double momSmBuff1[]; double momSmBuff2[]; double absMomBuff[]; double absMomSmBuff1[]; double absMomSmBuff2[]; int OnInit() { smperiod1=int(InpSmPeriod1<2 ? 2 : InpSmPeriod1); smperiod2=int(InpSmPeriod2<2 ? 2 : InpSmPeriod2); SetIndexBuffer(0,indBuff,INDICATOR_DATA); SetIndexBuffer(2,momBuff,INDICATOR_CALCULATIONS); SetIndexBuffer(3,momSmBuff1,INDICATOR_CALCULATIONS); SetIndexBuffer(4,momSmBuff2,INDICATOR_CALCULATIONS); SetIndexBuffer(5,absMomBuff,INDICATOR_CALCULATIONS); SetIndexBuffer(6,absMomSmBuff1,INDICATOR_CALCULATIONS); SetIndexBuffer(7,absMomSmBuff2,INDICATOR_CALCULATIONS); IndicatorSetString(INDICATOR_SHORTNAME,"True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")"); IndicatorSetInteger(INDICATOR_DIGITS,Digits()); ArraySetAsSeries(indBuff,true); ArraySetAsSeries(momBuff,true); ArraySetAsSeries(momSmBuff1,true); ArraySetAsSeries(momSmBuff2,true); ArraySetAsSeries(absMomBuff,true); ArraySetAsSeries(absMomSmBuff1,true); ArraySetAsSeries(absMomSmBuff2,true); return(INIT_SUCCEEDED); } int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { ArraySetAsSeries(close,true); if(rates_total<2) return 0; int limit=rates_total-prev_calculated; if(limit>1) { limit=rates_total-2; ArrayInitialize(indBuff,EMPTY_VALUE); ArrayInitialize(momBuff,0); ArrayInitialize(momSmBuff1,0); ArrayInitialize(momSmBuff2,0); ArrayInitialize(absMomBuff,0); ArrayInitialize(absMomSmBuff1,0); ArrayInitialize(absMomSmBuff2,0); } for(int i=limit; i>=0 && !IsStopped(); i--) { momBuff[i]=close[i]-close[i+1]; absMomBuff[i]=MathAbs(momBuff[i]); } if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,momBuff,momSmBuff1)==0) return 0; if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,absMomBuff,absMomSmBuff1)==0) return 0; if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,momSmBuff1,momSmBuff2)==0) return 0; if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,absMomSmBuff1,absMomSmBuff2)==0) return 0; for(int i=limit; i>=0 && !IsStopped(); i--) indBuff[i]=(absMomSmBuff2[i]!=0 ? 100.0*momSmBuff2[i]/absMomSmBuff2[i] : 0); return(rates_total); }
このコードをエラーなくコンパイルした後、ナビゲータのIndicatorsフォルダにある利用可能な指標を見つけ、目的のチャートにドラッグ&ドロップすると、指標のウィンドウと入力が以下のようになります。
ユーザーは2つの入力を指定できます。初期値として、smoothing period 1は25、smoothing period 2は13となっていますが、今述べたように、ユーザーは自分の好みに合わせて編集することができます。
前の写真の[カラー]タブで、ユーザーがTSIラインの色、幅、スタイルを選択できることを確認できます。指標の入力とスタイルを決めたら、次のようにチャート上で指標を見つけることができます。
前のチャートでわかるように、価格の下に別ウィンドウでTSI指標の線が表示されており、この線はゼロ付近で振動しています。そして、指標のラベル、その平滑化期間、指標の値もあります。
カスタムTSI EA
この部分では、カスタム指標を自動化システムで使用し、特定の条件がトリガーされたときに特定のシグナルやアクションを生成する方法を、非常にシンプルな方法で学びます。まずは、TSIの現在値をチャート上にコメントとして生成するEAを作成することで、非常にシンプルなシステムを作り、その後、より複雑な命令を実行するEAを開発します。
それでは、EAを作成するために必要な手順を以下に示します。
- TSI整数変数を作成する。
- iCustom関数を使ってTSIを定義すると、指標のハンドルが返され、そのパラメータは次のようになります。
- symbol_name:銘柄(現在の銘柄に適用される_Symbolを使用)
- period:現在の期間または時間枠に適用(_periodを使用)
- name:カスタム指標のパス
- EAが削除されたらOnDeinit(const int reason)部分で「TSI System Removed」のテキストを印刷する
- tsiVal[]の配列を作成する
- TSI指標のバッファのデータを、最初の位置と必要な要素数で呼び出す変形のCopyBuffer関数を使用して取得します。パラメータは次の通りです。
- indicator_handle:指標が返す指標ハンドル(TSIを使用)
- buffer_num:指標バッファ番号(0を使用)
- start_pos:コピーの開始位置(0を使用)
- count:コピーするデータ数(1を使用)
- buffer[]:コピーする配列(tsiValを使用)
- Comment関数を使って、現在のTSI値を文字列に変換して表示する(DoubleToString関数のパラメータは、現在のTSI値を指定するvalueと桁数を指定するdigitsなので、現在のものは_Digitsとする)
完全なコードは以下のようになります。
//+------------------------------------------------------------------+ //| customSimpleTSI-EA.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" int TSI; int OnInit() { TSI=iCustom(_Symbol,_Period,"My Files\\TSI\\simpleTSI"); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { Print("TSI System Removed"); } void OnTick() { double tsiVal[]; CopyBuffer(TSI,0,0,1,tsiVal); Comment("TSI Value ",DoubleToString(tsiVal[0],_Digits)); }
このコードをエラーなしでコンパイルして実行すると、チャートに接続されます。以下は、テストによるそのシグナルの例です。
左上のグラフに、現在のTSIの値がコメントとして表示されているのがわかります。もしシグナルが指標に基づくものと同じであることを確認したい場合は、EAを接続し、同時に指標を挿入して、値を確認することができます。以下ではそのために、私たちの仕事を確認します。
右上に書いてあるように、EAが接続されており、そのシグナルは左上隅に現在のTSI値とともに表示されます。同時に、TSI指標が価格の下に別ウィンドウとしてチャートに挿入されており、その値は左隅の線の上にEAのシグナルと同じに表示されています。
TSI System EA
この部分では、作成したカスタムTSI指標をベースに、特定の戦略に基づいたシグナルを取得するEAを開発します。なお、これから説明する戦略は、あくまでも教育目的であることをご了承ください。いずれにせよ、他の戦略と同じように最適化が必要です。ですから、実際の口座で使用する前にはテストして、ご自分にとって有用かどうかを確認してください。
カスタムTSI指標と2本の移動平均線を組み合わせて、特定の戦略に基づいた売買シグナルを得るために使用するのですが、それは以下のようなものです。
2つの単純な移動平均を使用します。1つは10周期の高速移動平均、もう1つは20周期の低速移動平均で、さらにカスタムTSI指標を使用します。もし、前回の高速MAの値が前回の低速MAより小さく、同時に現在の高速MAが現在の低速MAより大きければ、これは強気のMAクロスオーバーがあることを意味し、現在のTSI値がゼロより大きければ、チャート上のコメントとして買いシグナルを得る必要があるので、確認します。前回の高速MAの値が前回の低速MAより大きく、同時に現在の高速MAが現在の低速MAより小さい場合、これは弱気のMAクロスオーバーがあることを意味します。この場合、現在のTSI値が0より小さい場合はチャート上のコメントとして売りシグナルを得る必要があるので、確認します。
単純に言うと次のようになります。
fastMA[1]>slowMA[1] && fastMA[0]<slowMA[0] && tsiVal[0]<0 ==> 売りシグナル
以下は、このようなシステムを作るための全コードです。
//+------------------------------------------------------------------+ //| TSI System EA.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" input ENUM_MA_METHOD inpMAType = MODE_SMA; //Moving Average Type input ENUM_APPLIED_PRICE inpPriceType = PRICE_CLOSE; //Price type input int inpFastMAPeriod = 10; // Fast moving average period input int inpSlowMAPeriod = 20; //Slow moving average period int tsi; double fastMAarray[], slowMAarray[]; int OnInit() { tsi=iCustom(_Symbol,_Period,"My Files\\TSI\\simpleTSI"); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { Print("TSI System Removed"); } void OnTick() { double tsiVal[]; CopyBuffer(tsi,0,0,1,tsiVal); int fastMA =iMA(_Symbol,_Period,inpFastMAPeriod,0,inpMAType,inpPriceType); int slowMA =iMA(_Symbol,_Period,inpSlowMAPeriod,0,inpMAType,inpPriceType); ArraySetAsSeries(fastMAarray,true); ArraySetAsSeries(slowMAarray,true); CopyBuffer(fastMA,0,0,3,fastMAarray); CopyBuffer(slowMA,0,0,3,slowMAarray); if(fastMAarray[1]<slowMAarray[1]&&fastMAarray[0]>slowMAarray[0]) { if(tsiVal[0]>0) { Comment("Buy Signal", "\nTSI Value ",DoubleToString(tsiVal[0],_Digits), "\nfastMA ",DoubleToString(fastMAarray[0],_Digits), "\nslowMA ",DoubleToString(slowMAarray[0],_Digits)); } } if(fastMAarray[1]>slowMAarray[1]&&fastMAarray[0]<slowMAarray[0]&&tsiVal[0]<0) { if(tsiVal[0]<0) { Comment("Sell Signal", "\nTSI Value ",DoubleToString(tsiVal[0],_Digits), "\nfastMA ",DoubleToString(fastMAarray[0],_Digits), "\nslowMA ",DoubleToString(slowMAarray[0],_Digits)); } } }
このコードの違いは、次の通りとなります。
移動平均の種類、適用価格の種類、高速MA期間、低速MA期間の4つのユーザーによる入力を作成し、それらにデフォルト値を割り当てます。
input ENUM_MA_METHOD inpMAType = MODE_SMA; //Moving Average Type input ENUM_APPLIED_PRICE inpPriceType = PRICE_CLOSE; //Price type input int inpFastMAPeriod = 10; // Fast moving average period input int inpSlowMAPeriod = 20; //Slow moving average period
高速MA配列と低速MA配列の2つの配列を作成します。
double fastMAarray[], slowMAarray[];
移動平均のハンドルを返すために定義済みのiMA関数を使用して2つの移動平均を定義します。そのパラメータは次のとおりです。
- symbol:現在の銘柄に適用(_Symbolを使用)
- period:現在の期間に適用(_periodを使用)
- ma_period:ユーザーが入力したものを高速MAと低速MAに使用
- ma_shift:シフトする必要がないため、0を使用
- ma_method:MAの種類(ユーザーによる入力を使用)
- applied_price:価格の種類(ユーザーによる入力を使用)
int fastMA =iMA(_Symbol,_Period,inpFastMAPeriod,0,inpMAType,inpPriceType); int slowMA =iMA(_Symbol,_Period,inpSlowMAPeriod,0,inpMAType,inpPriceType);
低速MAと高速MAのArraySetAsSeries関数によってAS_SERIESフラグを設定します。
ArraySetAsSeries(fastMAarray,true); ArraySetAsSeries(slowMAarray,true);
CopyBuffer関数を使って、2つの移動平均のバッファからデータを取得します。
CopyBuffer(fastMA,0,0,3,fastMAarray); CopyBuffer(slowMA,0,0,3,slowMAarray);
戦略条件を定義します。
買いシグナルの場合
前回のfastMAが前回のslowMAより小さく、今回のfastMAが今回のslowMAより大きく、同時に今回のtsiValが0より大きい場合、以下の注文と同じように、EAから買いシグナルをチャート上のコメントとして返す必要があります。
- 買いシグナル
- TSI値
- fastMAの値
- slowMAの値
if(fastMAarray[1]<slowMAarray[1]&&fastMAarray[0]>slowMAarray[0]) { if(tsiVal[0]>0) { Comment("Buy Signal", "\nTSI Value ",DoubleToString(tsiVal[0],_Digits), "\nfastMA ",DoubleToString(fastMAarray[0],_Digits), "\nslowMA ",DoubleToString(slowMAarray[0],_Digits)); } }
売りシグナルの場合
前回のfastMAが前回のslowMAより大きく、今回のfastMAが今回のslowMAより小さく、同時に今回のtsiValが0より小さい場合、EAは以下の順序でチャートにコメントとして売りシグナルを返します。
- 売りシグナル
- TSI値
- fastMAの値
- slowMAの値
if(fastMAarray[1]>slowMAarray[1]&&fastMAarray[0]<slowMAarray[0]&&tsiVal[0]<0) { if(tsiVal[0]<0) { Comment("Sell Signal", "\nTSI Value ",DoubleToString(tsiVal[0],_Digits), "\nfastMA ",DoubleToString(fastMAarray[0],_Digits), "\nslowMA ",DoubleToString(slowMAarray[0],_Digits)); } }
このコードをエラーなくコンパイルし、ドラッグ&ドロップで実行してシグナルを取得すると、[入力]タブのウィンドウは次のようになります。
MAタイプ、価格タイプ、高速MA期間、低速MA期間の4つの入力があることからわかるように、MAタイプ、価格タイプ、高速MA期間、低速MA期間の4つの入力があります。環境設定をおこない、[OK]を押すと、EAがチャートに接続され、そのシグナルは以下のようになることがわかります。
買いシグナルの場合
前のチャートでわかるように、私たちの戦略条件と同じように、左上にコメントとして買いシグナルが表示されています:
- 買いシグナル
- TSI値
- fastMAの値
- slowMAの値
売りシグナルの場合
先ほどのチャートでは、ストラテジーの条件通り、左上にコメントとして売りシグナルが表示されていますが、以下と同じです:
- 売りシグナル
- TSI値
- fastMAの値
- slowMAの値
結論
今回は、自分専用の設定や好みを実装した独自のTSI(True Strength Index)テクニカル指標を作成する方法について学びました。これまで、この指標が提供する情報や洞察が、取引に非常に役立つことを見てきました。また、このカスタマイズされた指標を簡単な取引システムで使用し、TSI指標の現在値をチャート上のコメントとして生成する方法も学びました。TSIのデータを他のテクニカルツール(この場合は移動平均線)と組み合わせて利用するEAを作成し、自動売買システムでこの指標を利用する方法も確認しました。このカスタムTSIと2本の移動平均線の組み合わせは、TSIシステムEAのトピックで詳しく検討した、特定の戦略に基づく売買シグナルを生成します。
この記事が、皆様のトレードやプログラミング学習にお役に立てれば幸いです。指標に関する他の記事を読みたい、最も人気のあるテクニカル指標に基づいて取引システムを作成する方法を学びたいという方は、移動平均、ボリンジャーバンド、RSI、MACD、ストキャスティクス、パラボリックSAR、ATRなどの人気の指標を取り上げた私の過去の記事をご覧ください。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/12570





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