English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
フィッシャートランスフォームの適用とMetaTrader5の市場分析に対するフィッシャートランスフォーム

フィッシャートランスフォームの適用とMetaTrader5の市場分析に対するフィッシャートランスフォーム

MetaTrader 5トレーディング | 18 11月 2015, 12:55
2 602 0
investeo
investeo

はじめに

以下の記事は、フィッシャートランスフォームと、金融市場に適用されるフィッシャートランスフォームを紹介します。

フィッシャートランスフォーム理論は、雑誌"Stocks and Commodities"(株と商品)の2010年10月号にて記載されていたSmoothed RSI Inverse Fisher TrasnformインジケーターのMQL5版を稼働させることで、実行されます。そのインジケーターの確率は、Fisherインジケーターに基づくシグナルを使用するエキスパートアドバイザーによってバックテストされています。

この記事は、J.F.Ehlersの著書とネット上に見られる記事に基づいています。すべての参照元は、記事の最後に記載されています。


1. ガウジアンPDF vs 市場サイクル

共通の想定は、価格は標準の確率密度関数を備えているということです。

これは、価格の逸脱は、よく知られるガウジアンベルトとして紹介されることを意味します。

図1. 正規分布

図1. ガウジアンベルト

標準の確率密度関数について紹介しました。完璧に理解するために、いくつかのアイディアと数学の公式を紹介します。多くの読者にとって理解いただけることを願っています。

Merriam-Webster辞書を調べると確率 は以下のように定義されています。

  1. 同等に等しい結果における、特定の結果の数の比率であり、特定のイベントにつながるであろう合計の数に対する
  2. 特定のイベントを生み出す結果です。

ランダム変数は、いくつかのランダムなプロセスにおける基準から生じる結果の変数です。この場合、ランダム変数は資産の価格です。

最後に、PDFは、確率密度関数の頭字語であり、その関数はランダム変数X(この場合、価格)が可能な値の範囲の中での数値を取得します。標準分布か正規分布から生じるランダム変数は、現実世界の一つの値になりがちのランダム変数を示すために使用される確率分布です。

数学的に言うと、[a,b]間にある値をランダム変数が取得する可能性は、必須であると定義されています。

図2. 確率密度積分

これは、aからbまでのカーブf(x)の下にあるエリアを示し、確率は、0から100で数えるか、0から1.00で数えられます。したがって、f(x)カーブの下の合計のエリアは1でなければならないという制限があります(確率の合計):

図3. カーブ下の合計エリア

図1の下部を見てみましょう:

図4. ガウジアン図下部

図2. ガウジアンベル標準逸脱

どのパーセントの値が標準偏差+/-1-3の下にあるか見えます。ガウジアンPDF67.2%の発生は、標準偏差1プラス/マイナスの範囲にあり、94.5%は、標準偏差2プラス/マイナスにあり、99.73%は標準偏差プラス/マイナス3の範囲にあります。

これは実際の市場データにもあてはまると思いますか?実際はそうではありません。市場価格を見ると、むしろチャートは、短形波のようになります。大きい注文はグループ化される抵抗・サポート線を突破した後、価格は次のサポート/抵抗線より上昇するか、減少します。なので、市場は、短形波や正弦波としてモデル化されます。

以下の正弦をみてください。

正弦

図3. 正弦図

実際は、大半のトレードは、単純にサポート、抵抗線の近くに配置され、自然に見えるということに注意しなければなりません。それでは、正弦波の密度図を描きます。図3を90度右に回転させ、図を下に落ちるように回転させたようだと想像できるでしょう。

密度

図4. 正弦曲線密度図

密度は、一番左か右の位置にて最も高くなります。これは、多くのトレードが抵抗・サポート線近くにて作成されるという以前述べた内容に一致しています。発生率がどのようなものとしてヒストグラムによって描かれているのかチェックしてみましょう;

ヒストグラム

図5. 正弦曲線密度ヒストグラム

ガウジアンベルトのように見えるでしょうか?そうでもありません。最初と最後3つのバーは、多くの発生を持っているようdす。

J.F. 著書"Сybernetic analysis for stocks and futures"(株と将来における人工頭脳学の分析)の中でEhlersは、彼が15年間の間アメリカのT-Bondsを分析した実験について紹介しています。T-Bonds over a span of 15 years. 彼は、標準化されたチャネル10のバーを適用し、100ビンの間での価格の位置を計り、価格がそれぞれのビンにあった回数を数えました。この確率分布の毛かは正弦波のものに近くなります。


2. フィッシャートランスフォームとその時系列への適用。

市場サイクルのPDFは、ガウジアンではなく、むしろ正弦波のPDFになり、多くのインジケーターが市場サイクルPDFはガウジアンであると知っているため、それを正す必要があります。その解決策は、フィッシャートランスフォームを使用することです。フィッシャートランスフォームは、いかなる波形のPDFをガウス性に変換します。

フィッシャートランスフォームにおいての公式は:

図6. フィッシャートランスフォーム等式,

図5. フィッシャートランスフォーム

図6. フィッシャートランスフォーム

フィッシャートランスフォームの結果は、おおよそガウジアンPDFになると述べました。これを説明するために、図6を見ることが有効です。

入力データがその平均値に近い場合、その利益は、単一になります(|X<0.5|のチャートをみてください)一方、標準の入力値が制限に近づいている際は、そのアウトプットは大いに拡大されます( 0.5<|x|<1のチャートをご覧ください). 実際、偏差が多く出現すれば、成長する「ガウジアン」の尻尾であると考えるでしょうーこれは、正しくは変形されたPDFに出現するものです。

フィッシャートランスフォームをどのようにトレーディングに適用するのでしょうか?まず最初は、|x|<1 定数のせいで、価格はこの範囲に標準化されなければなりません。標準化された価格がフィッシャートランスフォームに適用された際、その価格移動は、相対的にまれになります。これは、フィッシャートランスフォームがこれらの価格移動を取得し、それらの極値に沿ってトレードすることを可能にしています。


3. MQL5でのフィッシャートランスフォーム

フィッシャートランスフォームインジケーターのソースコードは、Ehlerの著書 "Cybernetic Analysis for Stocks and Futures"(株と先物における人工頭脳的な分析).

MQL4にてすでに実行されており、それをMQL5に転換しました。そのインジケーターは平均価格 (H+L)/2を使用し、 iMA()関数が履歴から平均価格を抽出するために使用されます。

最初は、価格が10バーの範囲にて正規化され、正規化された価格がフィッシャートランスフォームに適用されます。

//+------------------------------------------------------------------+
//|                                              FisherTransform.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                           http://www.investeo.pl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, Investeo.pl"
#property link      "http://www.investeo.pl"
#property version   "1.00"
#property indicator_separate_window

#property description "MQL5 version of Fisher Transform indicator"

#property indicator_buffers 4
#property indicator_level1 0
#property indicator_levelcolor Silver
#property indicator_plots 2
#property indicator_type1         DRAW_LINE
#property indicator_color1        Red
#property indicator_width1 1
#property indicator_type2         DRAW_LINE
#property indicator_color2        Blue
#property indicator_width2 1

double Value1[];
double Fisher[];
double Trigger[];

input int Len=10;

double medianbuff[];
int hMedian;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Fisher,INDICATOR_DATA);
   SetIndexBuffer(1,Trigger,INDICATOR_DATA);
   SetIndexBuffer(2,Value1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,medianbuff,INDICATOR_CALCULATIONS);
   ArraySetAsSeries(Fisher,true);
   ArraySetAsSeries(Trigger,true);
   ArraySetAsSeries(Value1,true);
   ArraySetAsSeries(medianbuff,true);
   
   hMedian = iMA(_Symbol,PERIOD_CURRENT,1,0,MODE_SMA,PRICE_MEDIAN);
   if(hMedian==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                 _Symbol,
                 EnumToString(PERIOD_CURRENT),
                 GetLastError());
      //--- the indicator is stopped early, if the returned value is negative
      return(-1);
     }
//---
   return(0);
  }
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   int  nLimit=MathMin(rates_total-Len-1,rates_total-prev_calculated);
   int copied = CopyBuffer(hMedian,0,0,nLimit,medianbuff);
   if (copied!=nLimit) return (-1);
   nLimit--;
   for(int i=nLimit; i>=0; i--) 
     {
      double price=medianbuff[i];
      double MaxH = price;
      double MinL = price;
      for(int j=0; j<Len; j++) 
        {
         double nprice=medianbuff[i+j];
         if (nprice > MaxH) MaxH = nprice;
         if (nprice < MinL) MinL = nprice;
        }
      Value1[i]=0.5*2.0 *((price-MinL)/(MaxH-MinL)-0.5)+0.5*Value1[i+1];
      if(Value1[i]>0.9999) Value1[i]=0.9999;
      if(Value1[i]<-0.9999) Value1[i]=-0.9999;
      Fisher[i]=0.25*MathLog((1+Value1[i])/(1-Value1[i]))+0.5*Fisher[i+1];
      Trigger[i]=Fisher[i+1];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

シャープシグナルが生成されていることに注意してください。

シャープラインは、一つバーによって遅延されたフィッシャートランスフォーム価格です。

フィッシャートランスフォームインジケーター

図7. フィッシャートランスフォームインジケーター


4. 反対のフィッシャートランスフォームと、サイクルインジケーターへの適用

反対のフィッシャートランスフォーム等式は、yの期間でのxにおけるフィッシャートランスフォーム等式を解くことで取得されます。

図8. 反対のフィッシャートランスフォーム等式,

図6. 反対のフィッシャートランスフォーム

図8. 反対のフィッシャートランスフォーム

この関数の遷移レスポンスは、フィッシャートランスフォームのものの反対の形になります。

|x|>2においての入力値は、超過しない単一の値に一致します(負の数においては-1、正の数においては+1)、そして、 |x|<1においては、アウトプットが多かれ少なかれインプットと同じ特徴を入力持つことを意味する直線相関となります。

その結果は、フィッシャートランスフォームの対が適切に準備された入力データに適用された際に、そのアウトプットは、-1か+1になる可能性を持ちます。これにより、フィッシャートランスフォームの対をオシレーターインジケーターに適用する上で完璧となります。フィッシャートランスフォームの対は、鋭い売り・買いシグナルにより改善されます。


5. MQL5でのフィッシャートランスフォームの例

フィッシャートランスフォームを確認するために、 "Stocks and Commodities"(株と商品)という雑誌の2010年10月号にて記載されている、Sylvain's Vervoort Smoothed RSI Inverse Fisher Transformインジケーターを実行し、そのインジケーターに基づくエキスパートアドバイザーとトレーディングシグナルモジュールを作成します。

フィッシャートランスフォームインジケーターは、すでに多くのトレーディングプラットフォームにて実装されており、そのソースコードはtraders.comや、 MQL5.com Code Baseにてみることができます。.

iRSIOnArray関数がMQL5にはないので、そのインジケーターコードに追加しています。元のインジケーターとの唯一の違いは、21にセットされたRSIPeriodと、34にセットされたEMAPeriodです。私の設定の方がよりよく作動するため、変更しました(EURUSD 1H)RSIPeriod 4、EMAPeriod 4に変更することもできます

//+------------------------------------------------------------------+
//|                            SmoothedRSIInverseFisherTransform.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                           http://www.investeo.pl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, Investeo.pl"
#property link      "http://www.investeo.pl"
#property version   "1.00"
#property indicator_separate_window
#include <MovingAverages.mqh>
#property description "MQL5 version of Silvain Vervoort's Inverse RSI"
#property indicator_minimum -10
#property indicator_maximum 110
#property indicator_buffers 16
#property indicator_level1 12
#property indicator_level2 88
#property indicator_levelcolor Silver
#property indicator_plots 1
#property indicator_type1         DRAW_LINE
#property indicator_color1        LightSeaGreen
#property indicator_width1 2

int                  ma_period=10;             // period of ma
int                  ma_shift=0;               // shift
ENUM_MA_METHOD       ma_method=MODE_LWMA;        // type of smoothing
ENUM_APPLIED_PRICE   applied_price=PRICE_CLOSE// type of price

double wma0[];
double wma1[];
double wma2[];
double wma3[];
double wma4[];
double wma5[];
double wma6[];
double wma7[];
double wma8[];
double wma9[];
double ema0[];
double ema1[];
double rainbow[];
double rsi[];
double bufneg[];
double bufpos[];
double srsi[];
double fish[];

int hwma0;

int wma1weightsum;
int wma2weightsum;
int wma3weightsum;
int wma4weightsum;
int wma5weightsum;
int wma6weightsum;
int wma7weightsum;
int wma8weightsum;
int wma9weightsum;

extern int     RSIPeriod=21;
extern int     EMAPeriod=34;

  
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,fish,INDICATOR_DATA);
   SetIndexBuffer(1,wma0,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,wma1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,wma2,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,wma3,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,wma4,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,wma5,INDICATOR_CALCULATIONS);
   SetIndexBuffer(7,wma6,INDICATOR_CALCULATIONS);
   SetIndexBuffer(8,wma7,INDICATOR_CALCULATIONS);
   SetIndexBuffer(9,wma8,INDICATOR_CALCULATIONS);
   SetIndexBuffer(10,wma9,INDICATOR_CALCULATIONS);
   SetIndexBuffer(11,rsi,INDICATOR_CALCULATIONS);
   SetIndexBuffer(12,ema0,INDICATOR_CALCULATIONS);
   SetIndexBuffer(13,srsi,INDICATOR_CALCULATIONS);
   SetIndexBuffer(14,ema1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(15,rainbow,INDICATOR_CALCULATIONS);

   ArraySetAsSeries(fish,true);
   ArraySetAsSeries(wma0,true);
   ArraySetAsSeries(wma1,true);
   ArraySetAsSeries(wma2,true);
   ArraySetAsSeries(wma3,true);
   ArraySetAsSeries(wma4,true);
   ArraySetAsSeries(wma5,true);
   ArraySetAsSeries(wma6,true);
   ArraySetAsSeries(wma7,true);
   ArraySetAsSeries(wma8,true);
   ArraySetAsSeries(wma9,true);
   ArraySetAsSeries(ema0,true);
   ArraySetAsSeries(ema1,true);
   ArraySetAsSeries(rsi,true);
   ArraySetAsSeries(srsi,true);
   ArraySetAsSeries(rainbow,true);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,0);
//--- sets drawing line empty value
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- digits
   IndicatorSetInteger(INDICATOR_DIGITS,2);

   hwma0=iMA(_Symbol,PERIOD_CURRENT,2,ma_shift,ma_method,applied_price);
   if(hwma0==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  _Symbol,
                  EnumToString(PERIOD_CURRENT),
                  GetLastError());
      //--- the indicator is stopped early, if the returned value is negative
      return(-1);
     }

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   int nLimit;

   if(rates_total!=prev_calculated)
     {
      CopyBuffer(hwma0,0,0,rates_total-prev_calculated+1,wma0);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma0,wma1,wma1weightsum);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma1,wma2,wma2weightsum);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma2,wma3,wma3weightsum);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma3,wma4,wma4weightsum);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma4,wma5,wma5weightsum);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma5,wma6,wma6weightsum);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma6,wma7,wma7weightsum);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma7,wma8,wma8weightsum);
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,0,2,wma8,wma9,wma9weightsum);

      if(prev_calculated==0) nLimit=rates_total-1;
      else nLimit=rates_total-prev_calculated+1;
      
      for(int i=nLimit; i>=0; i--)
         rainbow[i]=(5*wma0[i]+4*wma1[i]+3*wma2[i]+2*wma3[i]+wma4[i]+wma5[i]+wma6[i]+wma7[i]+wma8[i]+wma9[i])/20.0;

      iRSIOnArray(rates_total,prev_calculated,11,RSIPeriod,rainbow,rsi,bufpos,bufneg);

      ExponentialMAOnBuffer(rates_total,prev_calculated,12,EMAPeriod,rsi,ema0);
      ExponentialMAOnBuffer(rates_total,prev_calculated,13,EMAPeriod,ema0,ema1);

      for(int i=nLimit; i>=0; i--)
         srsi[i]=ema0[i]+(ema0[i]-ema1[i]);

      for(int i=nLimit; i>=0; i--)
         fish[i]=((MathExp(2*srsi[i])-1)/(MathExp(2*srsi[i])+1)+1)*50;         
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
///                        Calculating RSI
//+------------------------------------------------------------------+
int iRSIOnArray(const int rates_total,const int prev_calculated,const int begin,
                const int period,const double &price[],double &buffer[],double &bpos[],double &bneg[])
  {
   int        i;
//--- check for data
   ArrayResize(bneg,rates_total);
   ArrayResize(bpos,rates_total);

   if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
   bool as_series_price=ArrayGetAsSeries(price);
   bool as_series_buffer=ArrayGetAsSeries(buffer);
   if(as_series_price) ArraySetAsSeries(price,false);
   if(as_series_buffer) ArraySetAsSeries(buffer,false);

   double diff=0.0;
//--- check for rates count
   if(rates_total<=period)
      return(0);
//--- preliminary calculations
   int ppos=prev_calculated-1;
   if(ppos<=begin+period)
     {
      //--- first RSIPeriod values of the indicator are not calculated
      for (i=0; i<begin; i++)
      {
      buffer[i]=0.0;
      bpos[i]=0.0;
      bneg[i]=0.0;
      }
      double SumP=0.0;
      double SumN=0.0;
      for(i=begin;i<=begin+period;i++)
        {
         buffer[i]=0.0;
         bpos[i]=0.0;
         bneg[i]=0.0;
         //PrintFormat("%f %f\n", price[i], price[i-1]);
         diff=price[i]-price[i-1];
         SumP+=(diff>0?diff:0);
         SumN+=(diff<0?-diff:0);
        }
      //--- calculate first visible value
      bpos[begin+period]=SumP/period;
      bneg[begin+period]=SumN/period;
      if (bneg[begin+period]>0.0000001)
      buffer[begin+period]=0.1*((100.0-100.0/(1+bpos[begin+period]/bneg[begin+period]))-50);
      //--- prepare the position value for main calculation
      ppos=begin+period+1;
     }
//--- the main loop of calculations

   for(i=ppos;i<rates_total && !IsStopped();i++)
     {
      diff=price[i]-price[i-1];
      bpos[i]=(bpos[i-1]*(period-1)+((diff>0.0)?(diff):0.0))/period;
      bneg[i]=(bneg[i-1]*(period-1)+((diff<0.0)?(-diff):0.0))/period;
      if (bneg[i]>0.0000001)
      buffer[i]=0.1*((100.0-100.0/(1+bpos[i]/bneg[i]))-50);
      //Print(buffer[i]);
     }
//--- restore as_series flags
   if(as_series_price) ArraySetAsSeries(price,true);
   if(as_series_buffer) ArraySetAsSeries(buffer,true);

   return(rates_total);
  }
//+------------------------------------------------------------------+

フィッシャーインジケーター

図9. 対のフィッシャーインジケーター

変形等式のみを紹介したため、フィッシャートランスフォームやその対のものに困惑するかもしれません。

この記事を書くための資料を集めている際に、どのようにFisherが両方の変形を取得したのか気になりましたが、インターネットでは見つかりませんでした。

しかし、両方のフィッシャートランスフォーム、対のフィッシャートランスフォームを見て、それらが三角法や総局関数を思い出させました。(類似点がわかりますか?)これらの関数は、Eulerの公式に由来し、「e」というEulerの用語で表現されているため、本に戻り、チェックしました。

図9. 正弦方程式,

図11. コッシュ法的式,

tanh(x)は、以下によって取得されます:

図12. 双曲線正接方程式,

そして...

図12. Atanh 方程式

ええ、これは、上記で紹介した方程式と同じものです、フィッシャートランスフォームが解明されました!フィッシャートランスフォームは、単にarchtanh(x)であり、対のフィッシャートランスフォームはその逆、tanh(x)だったのです!


6. トレーディングシグナルモジュール

対のフィッシャートランスフォームを確認するために、そのインジケーターに基づくトレーディングシグナルモジュールを作成します。

カスタムインジケーターに基づくトレーディングモジュールを見ることは役に立つかもしれません。 CExpertSignal クラスの4つの再定義済みの仮装メソッドとフィッシャーインジケーターを維持するためにCiCustomクラスを使用しました: CheckOpenLong()CheckOpenShort()は、オープンポジションがなければ、シグナルを生成する役割を担います。そして、CheckReverseLong()CheckReverseShort()はオープンポジションをリバースするための役割を担います。

//+------------------------------------------------------------------+
//|                               InverseFisherRSISmoothedSignal.mqh |
//|                                    Copyright © 2011, Investeo.pl |
//|                                               http://Investeo.pl |
//|                                                      Version v01 |
//+------------------------------------------------------------------+
#property tester_indicator "SmoothedRSIInverseFisherTransform.ex5"
//+------------------------------------------------------------------+
//| include files                                                    |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>
//+------------------------------------------------------------------+
//| Class CSignalInverseFisherRSISmoothed.                           |
//| Description: Class generating InverseFisherRSISmoothed signals   |
//|              Derived from CExpertSignal.                         |
//+------------------------------------------------------------------+

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signal on the Inverse Fisher RSI Smoothed Indicator        |
//| Type=SignalAdvanced                                              |
//| Name=InverseFisherRSISmoothed                                    |
//| Class=CSignalInverseFisherRSISmoothed                            |
//| Page=                                                            |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| CSignalInverseFisherRSISmoothed class                            |
//| Purpose: A class of a module of trade signals,                   |
//| on InverseFisherRSISmoothed                                      |
//+------------------------------------------------------------------+
class CSignalInverseFisherRSISmoothed : public CExpertSignal
  {
protected:
   CiCustom          m_invfish;
   double            m_stop_loss;
   
public:
                     CSignalInverseFisherRSISmoothed();
   //--- methods initialize protected data
   virtual bool      InitIndicators(CIndicators *indicators);
   virtual bool      ValidationSettings();
   //---
   virtual bool      CheckOpenLong(double &price,double &sl,double &tp,datetime &expiration);
   virtual bool      CheckReverseLong(double &price,double &sl,double &tp,datetime &expiration);
   virtual bool      CheckOpenShort(double &price,double &sl,double &tp,datetime &expiration);
   virtual bool      CheckReverseShort(double &price,double &sl,double &tp,datetime &expiration);
   
protected:
   bool              InitInvFisher(CIndicators *indicators);
   double            InvFish(int ind) { return(m_invfish.GetData(0,ind)); }
  };
//+------------------------------------------------------------------+
//| Constructor CSignalInverseFisherRSISmoothed.                                    |
//| INPUT:  no.                                                      |
//| OUTPUT: no.                                                      |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
void CSignalInverseFisherRSISmoothed::CSignalInverseFisherRSISmoothed()
  {
//--- initialize protected data
  }
//+------------------------------------------------------------------+
//| Validation settings protected data.                              |
//| INPUT:  no.                                                      |
//| OUTPUT: true-if settings are correct, false otherwise.           |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSignalInverseFisherRSISmoothed::ValidationSettings()
  {
//--- initial data checks
 if(!CExpertSignal::ValidationSettings()) return(false);
//--- ok
   return(true);
  }
  
//+------------------------------------------------------------------+
//| Create Inverse Fisher custom indicator.                          |
//| INPUT:  indicators -pointer of indicator collection.             |
//| OUTPUT: true-if successful, false otherwise.                     |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
  bool CSignalInverseFisherRSISmoothed::InitInvFisher(CIndicators *indicators)
  {
//--- check pointer
   printf(__FUNCTION__+": initializing Inverse Fisher Indicator");
   if(indicators==NULL) return(false);
//--- add object to collection
   if(!indicators.Add(GetPointer(m_invfish)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
     MqlParam invfish_params[];
   ArrayResize(invfish_params,2);
   invfish_params[0].type=TYPE_STRING;
   invfish_params[0].string_value="SmoothedRSIInverseFisherTransform";
   //--- applied price
   invfish_params[1].type=TYPE_INT;
   invfish_params[1].integer_value=PRICE_CLOSE;
//--- initialize object
   if(!m_invfish.Create(m_symbol.Name(),m_period,IND_CUSTOM,2,invfish_params))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
   m_invfish.NumBuffers(18);
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Create indicators.                                               |
//| INPUT:  indicators -pointer of indicator collection.             |
//| OUTPUT: true-if successful, false otherwise.                     |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSignalInverseFisherRSISmoothed::InitIndicators(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL) return(false);
//--- initialization of indicators and timeseries of additional filters
   if(!CExpertSignal::InitIndicators(indicators)) return(false);
//--- create and initialize SAR indicator
   if(!InitInvFisher(indicators)) return(false);
   m_stop_loss = 0.0010;
//--- ok
   printf(__FUNCTION__+": all inidicators properly initialized.");
   return(true);
  }
//+------------------------------------------------------------------+
//| Check conditions for long position open.                         |
//| INPUT:  price      - reference for price,                        |
//|         sl         - reference for stop loss,                    |
//|         tp         - reference for take profit,                  |
//|         expiration - reference for expiration.                   |
//| OUTPUT: true-if condition performed, false otherwise.            |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSignalInverseFisherRSISmoothed::CheckOpenLong(double &price,double &sl,double &tp,datetime &expiration)
  {
   printf(__FUNCTION__+" checking signal");
   
   int idx=StartIndex();
   
//---
   price=0.0;
   tp   =0.0;
//---
   if(InvFish(idx+2)<12.0 && InvFish(idx+1)>12.0)
   { 
      printf(__FUNCTION__ + " BUY SIGNAL");
      return true;
   } else printf(__FUNCTION__ + " NO SIGNAL");
//---
   return false;
  }
//+------------------------------------------------------------------+
//| Check conditions for long position close.                        |
//| INPUT:  price - refernce for price.                              |
//| OUTPUT: true-if condition performed, false otherwise.            |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSignalInverseFisherRSISmoothed::CheckReverseLong(double &price,double &sl,double &tp,datetime &expiration)
  {
   long tickCnt[1];
   int ticks=CopyTickVolume(Symbol(), 0, 0, 1, tickCnt);
   if (ticks!=1 || tickCnt[0]!=1) return false;
   
   int idx=StartIndex();
   
   price=0.0;
// sl   =m_symbol.NormalizePrice(m_symbol.Bid()+20*m_stop_level);
//---
   
   if((InvFish(idx+1)>88.0 && InvFish(idx)<88.0)  || 
     (InvFish(idx+2)>88.0 && InvFish(idx+1)<88.0) ||
     (InvFish(idx+2)>12.0 && InvFish(idx+1)<12.0))
  {
   printf(__FUNCTION__ + " REVERSE LONG SIGNAL");
   return true;
   } else printf(__FUNCTION__ + " NO SIGNAL");
   return false;
  }
//+------------------------------------------------------------------+
//| Check conditions for short position open.                        |
//| INPUT:  price      - refernce for price,                         |
//|         sl         - refernce for stop loss,                     |
//|         tp         - refernce for take profit,                   |
//|         expiration - refernce for expiration.                    |
//| OUTPUT: true-if condition performed, false otherwise.            |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSignalInverseFisherRSISmoothed::CheckOpenShort(double &price,double &sl,double &tp,datetime &expiration)
  {
   printf(__FUNCTION__+" checking signal");
   int idx=StartIndex();
//---
   price=0.0;
   sl   = 0.0;
//---
   if(InvFish(idx+2)>88.0 && InvFish(idx+1)<88.0)
   {printf(__FUNCTION__ + " SELL SIGNAL");
      return true;} else printf(__FUNCTION__ + " NO SIGNAL");
      
//---
   return false;
  }
//+------------------------------------------------------------------+
//| Check conditions for short position close.                       |
//| INPUT:  price - refernce for price.                              |
//| OUTPUT: true-if condition performed, false otherwise.            |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
bool CSignalInverseFisherRSISmoothed::CheckReverseShort(double &price,double &sl,double &tp,datetime &expiration)
  {
   long tickCnt[1];
   int ticks=CopyTickVolume(Symbol(), 0, 0, 1, tickCnt);
   if (ticks!=1 || tickCnt[0]!=1) return false;
   
   int idx=StartIndex();
  
   price=0.0;
//---
   
   if((InvFish(idx+1)<12.0 && InvFish(idx)>12.0) ||
    (InvFish(idx+2)<12.0 && InvFish(idx+1)>12.0) ||
    (InvFish(idx+2)<88.0 && InvFish(idx+1)>88.0)) 
  {
   printf(__FUNCTION__ + " REVERSE SHORT SIGNAL");
   return true;
   } else printf(__FUNCTION__ + " NO SIGNAL");
   return false;
  }


7. エキスパートアドバイザー

フィッシャートランスフォームを確認するため、以前紹介されたトレーディングモジュールを使用する標準EAを作成しました。

"MQL5 Wizard: How to Create a Module of Trailing of Open Positions"(MQL5ウィザード:オープンポジションのトレーリングモジュールの作成方法の記事から取得したストップロスモジュールを追加しました。

//+------------------------------------------------------------------+
//|                                                 InvRSIFishEA.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include                                                          |
//+------------------------------------------------------------------+
#include <Expert\Expert.mqh>
//--- available signals
#include <Expert\Signal\MySignal\InverseFisherRSISmoothedSignal.mqh>
//--- available trailing
#include <Expert\Trailing\SampleTrailing.mqh>
//--- available money management
#include <Expert\Money\MoneyFixedLot.mqh>
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string Expert_Title         ="InvRSIFishEA";   // Document name
ulong        Expert_MagicNumber   =7016; // 
bool         Expert_EveryTick     =true; // 
//--- inputs for main signal
input int    Signal_ThresholdOpen =10;    // Signal threshold value to open [0...100]
input int    Signal_ThresholdClose=10;    // Signal threshold value to close [0...100]
input double Signal_PriceLevel    =0.0;   // Price level to execute a deal
input double Signal_StopLevel     =0.0;   // Stop Loss level (in points)
input double Signal_TakeLevel     =0.0;   // Take Profit level (in points)
input int    Signal_Expiration    =0;    // Expiration of pending orders (in bars)
input double Signal__Weight       =1.0;   // InverseFisherRSISmoothed Weight [0...1.0]
//--- inputs for money
input double Money_FixLot_Percent =10.0;  // Percent
input double Money_FixLot_Lots    =0.2;   // Fixed volume
//+------------------------------------------------------------------+
//| Global expert object                                             |
//+------------------------------------------------------------------+
CExpert ExtExpert;
//+------------------------------------------------------------------+
//| Initialization function of the expert                            |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Initializing expert
   if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
     {
      //--- failed
      printf(__FUNCTION__+": error initializing expert");
      ExtExpert.Deinit();
      return(-1);
     }
//--- Creating signal
   CSignalInverseFisherRSISmoothed *signal=new CSignalInverseFisherRSISmoothed;
   if(signal==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating signal");
      ExtExpert.Deinit();
      return(-2);
     }
//---
   ExtExpert.InitSignal(signal);
   signal.ThresholdOpen(Signal_ThresholdOpen);
   signal.ThresholdClose(Signal_ThresholdClose);
   signal.PriceLevel(Signal_PriceLevel);
   signal.StopLevel(Signal_StopLevel);
   signal.TakeLevel(Signal_TakeLevel);
   signal.Expiration(Signal_Expiration);

//--- Creation of trailing object
   CSampleTrailing *trailing=new CSampleTrailing;
   trailing.StopLevel(0);
   trailing.Profit(20);
   
   if(trailing==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating trailing");
      ExtExpert.Deinit();
      return(-4);
     }
//--- Add trailing to expert (will be deleted automatically))
   if(!ExtExpert.InitTrailing(trailing))
     {
      //--- failed
      printf(__FUNCTION__+": error initializing trailing");
      ExtExpert.Deinit();
      return(-5);
     }
//--- Set trailing parameters
//--- Creation of money object
   CMoneyFixedLot *money=new CMoneyFixedLot;
   if(money==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating money");
      ExtExpert.Deinit();
      return(-6);
     }
//--- Add money to expert (will be deleted automatically))
   if(!ExtExpert.InitMoney(money))
     {
      //--- failed
      printf(__FUNCTION__+": error initializing money");
      ExtExpert.Deinit();
      return(-7);
     }
//--- Set money parameters
   money.Percent(Money_FixLot_Percent);
   money.Lots(Money_FixLot_Lots);
//--- Check all trading objects parameters
   if(!ExtExpert.ValidationSettings())
     {
      //--- failed
      ExtExpert.Deinit();
      return(-8);
     }
//--- Tuning of all necessary indicators
   if(!ExtExpert.InitIndicators())
     {
      //--- failed
      printf(__FUNCTION__+": error initializing indicators");
      ExtExpert.Deinit();
      return(-9);
     }
//--- ok
   return(0);
  }
//+------------------------------------------------------------------+
//| Deinitialization function of the expert                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ExtExpert.Deinit();
  }
//+------------------------------------------------------------------+
//| "Tick" event handler function                                    |
//+------------------------------------------------------------------+
void OnTick()
  {
   ExtExpert.OnTick();
  }
//+------------------------------------------------------------------+
//| "Trade" event handler function                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
   ExtExpert.OnTrade();
  }
//+------------------------------------------------------------------+
//| "Timer" event handler function                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   ExtExpert.OnTimer();
  }
//+------------------------------------------------------------------+

EAは、すべての資産やすべてのタイムフレームにおいて有益ではないことを認めなければなりませんが、EURUSD 1Hタイムフレームにては良い結果を出すよう微調整しました。

読者の皆様には、シグナルモジュールやインジケータの設定を調整し、この記事のEAよりも有益なものにしていただきたいです。

EAグラフ

図10. フィッシャートランスフォームEA

EA結果

図11. フィッシャートランスフォームEAバランスグラフ


結論

この記事がフィッシャートランスフォームやその対へのよりイントロダクションを提供し、カスタムインジケーターに基づくシグナルトレーディングモジュールの作成方法を紹介できたことを期待しています。

Sylvain's Vervoort Smoothed RSI Inverse Fisher Transformインジケーターを使用しましたが、実際は対のフィッシャートランスフォームを簡単にすべてのオシレーターに適用し、EAを作成することができます。

読者の皆様には、紹介したものに基づいて有益なEAを作成できるよう設定を調整していただきたいと思います。以下にさらなる参照のために外部のリンクを記載しています。


参照

  1. フィッシャートランスフォーム
  2. フィッシャートランスフォームを使用する
  3. フィッシャートランスフォームの対
  4. 平滑化RSIフィッシャートランスフォーム

MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/303

添付されたファイル |
トレーダーの作業における統計的分布の役割 トレーダーの作業における統計的分布の役割
本稿は、理論的統計的分布に連携するクラスについて述べた拙著『MQL5 における投擲的可能性』の続編です。われわれには理論的基盤があるので、現実のデータ設定に進み、こ基盤を情報的に利用していきたいと思います。
UML ツールを用いたExpert Advisorの開発方法 UML ツールを用いたExpert Advisorの開発方法
本稿では UML グラフィカル言語を用いたExpert Advisorの開発方法についてお話します。そのツールはオブジェクト指向のソフトウェアシステムのビジュアルモデル化に使用されるものです。この方法のおもなメリットはモデル化プロセスの可視化です。本稿には Software Ideas Modelerを使用したExpert Advisorの ストラクチャとプロパティのモデル化を示す例が含まれています。
もっとも活発な MQL5.コミュニティメンバーは  iPhonesを勝ち取りました! もっとも活発な MQL5.コミュニティメンバーは iPhonesを勝ち取りました!
もっともすぐれた MQL5.com 参加者に報酬を与えることを決めてからコミュニティの発展に貢献する参加者各位を決定する主要な基準を選んできました。その結果、ウェブサイトに多くの記事を掲載された以下のチャンピオンを得ました。 - investeo (11 件) 、victorg (10 件)、そして『コードベース』にプログラムを投稿され – GODZILLA (340 件)、Integer (61 件) 、 abolk (21 件)です。
MQL5.community 人名鑑 MQL5.community 人名鑑
MQL5.com ウェブサイトはみなさんのことをとてもよく覚えています!何本のスレッドがすばらしい出来か、記事がどれほど人気か、「コードベース」のプログラムがどのくらいの頻度でダウンロードされるか。これは MQL5.comで記憶されていることのほんの小さな一部にしかすぎません。みなさんの実績はプロフィールで確認可能ですが、全体像はどうでしょうか?本稿では全 MQL5.community メンバーの実績概要を示します。