記事"戦略バランス曲線の品質評価としての R 乗"についてのディスカッション - ページ 2

 
私は斜め読みしたが、それにもかかわらず、私は自分自身で重要な結論を出した。 著者に感謝する。
 
役に立つ記事をありがとう!再投稿しました!:-)
 

図19: 10,000ランダムウォークのLR-相関分布


図20:10,000ランダムウォークのR^2分布

R^2が2つ目のグラフのような負の値をとるとは思えないのですが?はい、最初のグラフにも疑問があります。線形回帰が 正しくプロットされているなら、ピアソンのRQ (LR)が負になることはないように思えます。しかし、グラフではそうではありません。どこが間違っていますか?


わかりました。グラフのR^2とLRがカスタムになっているだけで、数値系列の最後の要素が最初の要素より小さい場合、実数値の-1 乗算が発生します。グラフの前に書いておくといいと思います。

 

この論文では、線形回帰は CLinReg::LRLineを介した誤差を考慮する。

証明

#include <Graphics\Graphic.mqh> 
#include <Math\Stat\Normal.mqh>
#include <Math\Alglib\Alglib.mqh>

// 直線のY値を返す (y(x)=a*x+b)
void GetLine( const double a, const double b, const int Amount, double &Result[] )
{
  ArrayResize(Result, Amount);
  
  for (int i = 0; i < Amount; i++)
    Result[i] = a * i + b;    
}

// CLinReg::LRLine による線形回帰を返す。
void GetLinearRegression( const double &Array[], double &Result[] )
{
  const int Total = ArraySize(Array);
  
  CMatrixDouble XY(Total, 2);
  
  for (int i = 0; i < Total; i++)
  {
    XY[i].Set(0, i);
    XY[i].Set(1, Array[i]);
  }
  
  int retcode;
  double a, b;
  
  CLinReg::LRLine(XY, Total, retcode, a, b);

  GetLine(a, b, Total, Result);    
}

// CAlglib::LRBuild + CAlglib::LRUnpack によって線形回帰を返す。
void GetLinearRegression2( const double &Array[], double &Result[] )
{
  const int Total = ArraySize(Array);
  
  CMatrixDouble XY(Total, 2);
  
  for (int i = 0; i < Total; i++)
  {
    XY[i].Set(0, i);
    XY[i].Set(1, Array[i]);
  }
  
  int retcode;
  
  CLinearModelShell lm;
  CLRReportShell    ar;
//--- 回帰結果を格納するための配列
  double lr_coeff[];
//--- 線形回帰係数の計算
  CAlglib::LRBuild(XY, Total, 1, retcode, lm, ar);
//--- 線形回帰係数を求める
  CAlglib::LRUnpack(lm, lr_coeff, retcode);

  GetLine(lr_coeff[0], lr_coeff[1], Total, Result);      
}

void ToChart( const double &Array1[], const double &Array2[], const int X = 0, const int Y = 0, const int Width = 780, const int Height = 380 )
{
  static const string Name = __FILE__;
  
  CGraphic Graphic; 

  if (ObjectFind(0, Name) < 0) 
    Graphic.Create(0, Name, 0, X, Y, Width, Height); 
  else 
    Graphic.Attach(0, Name); 

  Graphic.CurveAdd(Array1, CURVE_LINES);
  Graphic.CurveAdd(Array2, CURVE_LINES);
  
  Graphic.CurvePlotAll(); 
  Graphic.Update();  
}

void GetRandomArray( double &Array[], const int Amount = 1 e3 )
{
  double Random[];
  
  MathSrand(GetTickCount()); 

  MathRandomNormal(0, 1, Amount, Random); 
  MathCumulativeSum(Random, Array);
}

#define  TOSTRING(A) #A + " = " + (string)(A) + "\n"

void OnStart() 
{   
  double Array[];
  
  GetRandomArray(Array);  
  
  double Estimate[];
  double Estimate2[];
     
  GetLinearRegression(Array, Estimate);
  GetLinearRegression2(Array, Estimate2);

  const double R = CAlglib::PearsonCorr2(Array, Estimate);
  const double R2 = CAlglib::PearsonCorr2(Array, Estimate2);
  
  Print(TOSTRING(R) +
        TOSTRING((Array[0] > Array[ArraySize(Array) - 1]) ? -R : R) +
        TOSTRING(R2));
  
  ToChart(Array, Estimate2);
}


結果

R = -0.5864718581193301
(Array[0]>Array[ArraySize(Array)-1])?-R:R = -0.5864718581193301
R2 = 0.58647185811933


符号が正しくない。別のLR実装(CAlglib::LRBuild + CAlglib::LRUnpack)は正しくカウントされる:


 
fxsaber:

論文で紹介されている、独立した1万例のLR相関分布とR^2分布のグラフを見ると、R^2 != LR^2 となっている。

なぜ元の「凹」分布の2次が「平」分布になるのか理解できない。

ここで私は間違っていたことが証明された。私にとって、この記述はまったく自明ではない

驚くべきは、 単純な数学的作用によって(2次まで上げることによって) 、分布の不要な周辺効果が完全に取り除かれたことである。

そこで、私はアニメーションで実験的に確認することにした(私の言葉を鵜呑みにしないように)。

#include <Graphics\Graphic.mqh> 
#include <Math\Stat\Normal.mqh>
#include <Math\Alglib\Alglib.mqh>

// 直線のY値を返す (y(x)=a*x+b)
void GetLine( const double a, const double b, const int Amount, double &Result[] )
{
  ArrayResize(Result, Amount);
  
  for (int i = 0; i < Amount; i++)
    Result[i] = a * i + b;    
}

// CAlglib::LRBuild + CAlglib::LRUnpack によって線形回帰を返す。
void GetLinearRegression( const double &Array[], double &Result[] )
{
  const int Total = ArraySize(Array);
  
  CMatrixDouble XY(Total, 2);
  
  for (int i = 0; i < Total; i++)
  {
    XY[i].Set(0, i);
    XY[i].Set(1, Array[i]);
  }
  
  int retcode;
  
  CLinearModelShell lm;
  CLRReportShell    ar;
//--- 回帰結果を格納するための配列
  double lr_coeff[];
//--- 線形回帰係数の計算
  CAlglib::LRBuild(XY, Total, 1, retcode, lm, ar);
//--- 線形回帰係数を求める
  CAlglib::LRUnpack(lm, lr_coeff, retcode);

  GetLine(lr_coeff[0], lr_coeff[1], Total, Result);      
}

// Rを計算する
double GetCustomR( const double &Array[] )
{
  double Estimate[];
   
  GetLinearRegression(Array, Estimate);
   
  const double R = CAlglib::PearsonCorr2(Array, Estimate);

  return((Array[0] > Array[ArraySize(Array) - 1]) ? -R : R);
}

// R個のランダムベクトルを計算する
void GetRandomCustomR( const int Amount, const int VectorSize, double &Result[] )
{
  double Random[];
  double Sum[];
  
  MathSrand(GetTickCount()); 

  ArrayResize(Result, Amount);
  
  for (int i = 0; i < Amount; i++)
  {
    MathRandomNormal(0, 1, VectorSize, Random); 
    MathCumulativeSum(Random, Sum);
    
    Result[i] = GetCustomR(Sum);
  }  
}

void ToChart( const double &X[],  const double &Y[], const string Str = NULL, const int X0 = 0, const int Y0 = 0, const int Width = 780, const int Height = 380 )
{
  static const string Name = __FILE__;
  
  CGraphic Graphic; 

  if (ObjectFind(0, Name)<0) 
    Graphic.Create(0, Name, 0, X0, Y0, Width, Height); 
  else 
    Graphic.Attach(0, Name); 

  Graphic.BackgroundMain(Str); 
  Graphic.BackgroundMainSize(16); 

  Graphic.CurveAdd(X, Y, CURVE_HISTOGRAM).HistogramWidth(6);
  
  Graphic.CurvePlotAll(); 
  Graphic.Update();  
}

void MathPow( double &Result[], const double &Array[], const double Pow )
{
  const int Size = ArrayResize(Result, ArraySize(Array));
  
  for (int i = 0; i < Size; i++)
    Result[i] = (Array[i] < 0) ? -MathPow(-Array[i], Pow) : MathPow(Array[i], Pow);
}

//https://www.mql5.com/ja/docs/standardlibrary/mathematics/stat/normal
//+------------------------------------------------------------------+ 
//| データセットの度数を計算する| 
//+------------------------------------------------------------------+ 
bool CalculateHistogramArray(const double &data[],double &intervals[],double &frequency[], 
                             double &maxv,double &minv,const int cells=10) 
  { 
   if(cells<=1) return (false); 
   int size=ArraySize(data); 
   if(size<cells*10) return (false); 
   minv=data[ArrayMinimum(data)]; 
   maxv=data[ArrayMaximum(data)]; 
   double range=maxv-minv; 
   double width=range/cells; 
   if(width==0) return false; 
   ArrayResize(intervals,cells); 
   ArrayResize(frequency,cells); 
//--- 区間の中心を設定する 
   for(int i=0; i<cells; i++) 
     { 
      intervals[i]=minv+(i+0.5)*width; 
      frequency[i]=0; 
     } 
//--- 間隔周波数を埋める 
   for(int i=0; i<size; i++) 
     { 
      int ind=int((data[i]-minv)/width); 
      if(ind>=cells) ind=cells-1; 
      frequency[ind]++; 
     } 
   return (true); 
  } 

void DistributionToChart( const double &Array[], const string Str = NULL, const int NCells = 51 )
{
  double X[];          // ヒストグラム・インターバル・センター 
  double Y[];          // 区間に入るサンプルの値の数 
  double Max, Min;     // サンプルの最大値と最小値 
  
  CalculateHistogramArray(Array, X, Y, Max, Min, NCells);   

  ToChart(X, Y, Str);
}

void OnInit() 
{   
  double R[];
  
  GetRandomCustomR(1 e3, 1 e4, R);
  
  double Array[];

  const int Max = 50;
  
  while (!IsStopped())
    for (int i = 1; !IsStopped() && i < (Max << 1); i++)
    {
      const double Pow = (i > Max) ? ((Max << 1) - i) * 0.1 : i * 0.1;
      
      MathPow(Array, R, Pow);
      DistributionToChart(Array, "Distribution of R^" + DoubleToString(Pow, 1));      
      
      Sleep(100);
    }
}



どうやらこんな感じだ。

 

 

図21:カスタム最適化基準としてのR^2値

MQL LR Correlationのどこにあるの でしょうか?あるいは、このパラメータや他の多くのパラメータは単一ランでのみ計算されるため、ENUM_STATISTICSには ないのでしょうか?

もしそうであれば、この記事で言及されている合理的な考察からこのパラメータを計算することをお勧めします。


ZY 100万個の値の配列(equityのような)に対してGetCustomRを計算するのにかかる時間を測ってみたところ、2.5秒でした。2.5秒だ。全てはLRの計算(CAlglib::LRBuild + CAlglib::LRUnpack)に費やされている。しかし、CLinReg::LRLineを通して LRを湾曲させた方が一桁速いこともある。それをドーピングすれば、最適化基準として最適化で許容できるようになる。

Документация по MQL5: Стандартные константы, перечисления и структуры / Состояние окружения / Статистика тестирования
Документация по MQL5: Стандартные константы, перечисления и структуры / Состояние окружения / Статистика тестирования
  • www.mql5.com
Максимальная просадка баланса в процентах. В процессе торговли баланс может испытать множество просадок, для каждой фиксируется относительное значение просадки в процентах. Возвращается наибольшее значение Максимальная...
 
Dennis Kirichenko:

ああ!ずっと100 だと思ってた。ありがとう。

そう、Rと統計に関する評判の良い本で目にしたことがある数字だ。でもリンクが見つからなかったのでごめんなさい。

Dennis Kirichenko:

回帰係数の有意性検定も一般的です。Alglibにもあります:-)

明らかに、検定は正規分布に対するものです。我々は一様 分布を得た。

PearsonCorrelationSignificance()、SpearmanRankCorrelationSignificance()。

リンクをありがとう。

 
fxsaber:

ZY 間違った記述

R^2はグラフとその線形モデルとの相関に過ぎない

//-- R^2とその符号を求める
   double r2 = MathPow(corr, 2.0);

確かに、言葉遣いに大きな誤りがあった。こんなことを書いてしまったことに自分でも驚いている。訂正します。

他のすべてのMQLコードを見ても、なぜそれが与えられているのか理解できない。なぜなら、CStrategyの知識がないとまったく読めないからだ

CStrategyは 必要条件を集めるためだけに必要なのだ。主なコードは、正しく指摘されているように、R2の実際の計算である。

R^2に適した「エクイティ」を計算するコード。MT4スタイルで書かれているので、MT5に翻訳するのは難しくないが・・・。

勉強してみよう。

 
Maxim Dmitrievsky:

私はこれに同意します。あなたのシステムに追加するには、残りのすべてをクラスから切り離す必要があります...すべてを別のf-iasesまたは別のincludnikに持つ方が良いでしょう。

あなたのエクイティ計算(またはfxsaberが提示したコード)をダブル配列にして、R^2計算関数に挿入してください。何も切り取る必要はありませんし、クラスやCStrategyを 使う必要もありません。

 
fxsaber:

R^2が2つ目のグラフのように負の値をとることが理解できないのですが?最初のグラフにも疑問があります。線形回帰が 正しく構築されているなら、ピアソンのLRは負にならないはずです。しかし、グラフではそうではありません。どこが間違っていますか?

わかりました。私はどこも間違っていない。ただ、グラフがカスタムR^2とLRを持っているだけで、数値系列の最後の要素が最初の要素より小さい場合、実数値の-1 乗算が発生する。グラフの前にこのことを書くといいだろう。

記事には隠されている:

我々のスクリプトはLR相関とR^2の両方を計算する。この2つの違いは後で説明する。スクリプトにちょっとした追加がある。結果の相関係数に合成グラフの最終的な符号を掛ける。もし結果が0より小さければ相関は負になり、大きければ正になる。これは、他の統計に頼ることなく、ネガティブな結果とポジティブな結果を素早く簡単に分離するために行われます。これはMetaTrader 5でLR相関がどのように機能するかであり、R^2は同じ原理に従って構築されます。

おそらく、私はそれについて別の場所で、何度も書くべきでした。