MQL4 中的皮尔逊相关系数是如何计算的?

How is the Pearson's Correlation calculated in MQL4?

为了轻松交易相关对 (hedge),我需要编写一个相关矩阵,例如 myfxbook 或 Oanda 上的那些。

要点是我希望能够遍历矩阵中的每个值并检查它是否大于 85.0 左右。

Q:如何在 MQL4 中计算 Pearson 相关系数?

方法A:
使用MQL4直接计算PearsonCorr_r

如果使用 double 的精度就足够了,MQL4 代码可以实现合理大小的值向量的过程 ( X[], Y[] )

#define RET_OK    0
#define RET_ERROR EMPTY
#define VAL_ERROR EMPTY_VALUE

int   PearsonCorr_r( double const &vectorX[], //   |-> INPUT X[]      = { 1, 3,  5,  5,  6 }
                     double const &vectorY[], //   |-> INPUT Y[]      = { 5, 6, 10, 12, 13 }
                     double       &pearson_r  // <=|   returns RESULT = 0.968
                     ){
      double  sumX = 0,
             meanX = 0,
             meanY = 0,
              sumY = 0,
             sumXY = 0,
             sumX2 = 0,
             sumY2 = 0;
          // deviation_score_x[],               // may be re-used for _x^2
          // deviation_score_y[],               // may be re-used for _y^2
          // deviation_score_xy[];
/* =====================================================================
                  DEVIATION SCORES                                       >>> http://onlinestatbook.com/2/describing_bivariate_data/calculation.html
        X[]  Y[]  x      y      xy    x^2    y^2
        1    4   -3     -5      15    9     25
        3    6   -1     -3       3    1      9
        5   10    1      1       1    1      1
        5   12    1      3       3    1      9
        6   13    2      4       8    4     16
       _______________________________________

SUM    20   45    0      0      30   16     60
MEAN    4    9    0      0       6   

       r = SUM(xy) / SQRT(  SUM( x^2 ) * SUM( y^2 ) )
       r =      30 / SQRT( 960 )
       r = 0.968
   =====================================================================
                                                                        */
      int    vector_maxLEN = MathMin( ArrayRange( vectorX, 0 ),
                                      ArrayRange( vectorY, 0 )
                                      );

      if (   vector_maxLEN == 0 ){
             pearson_r = VAL_ERROR;          // STOR VAL ERROR IN RESULT
             return(     RET_ERROR );        // FLAG RET_ERROR in JIT/RET
      }
      for ( int jj = 0; jj < vector_maxLEN; jj++ ){
            sumX += vectorX[jj];
            sumY += vectorY[jj];
      }
      meanX = sumX / vector_maxLEN;          // DIV!0 FUSED
      meanY = sumY / vector_maxLEN;          // DIV!0 FUSED

      for ( int jj = 0; jj < vector_maxLEN; jj++ ){
         // deviation_score_x[ jj] =   meanX - vectorX[jj];  // 
         // deviation_score_y[ jj] =   meanY - vectorY[jj];
         // deviation_score_xy[jj] = deviation_score_x[jj]
         //                        * deviation_score_y[jj];
         //              sumXY    += deviation_score_x[jj]
         //                        * deviation_score_y[jj];
                         sumXY    += ( meanX - vectorX[jj] ) // PSPACE MOTIVATED MINIMALISTIC WITH CACHE-BENEFITS IN PROCESSING
                                   * ( meanY - vectorY[jj] );
         // deviation_score_x[jj] *= deviation_score_x[jj];  // PSPACE MOTIVATED RE-USE, ROW-WISE DESTRUCTIVE, BUT VALUE WAS NEVER USED AGAIN
         //              sumX2    += deviation_score_x[jj]
         //                        * deviation_score_x[jj];
                         sumX2    += ( meanX - vectorX[jj] ) // PSPACE MOTIVATED MINIMALISTIC WITH CACHE-BENEFITS IN PROCESSING
                                   * ( meanX - vectorX[jj] );
         // deviation_score_y[jj] *= deviation_score_y[jj];  // PSPACE MOTIVATED RE-USE, ROW-WISE DESTRUCTIVE, BUT VALUE WAS NEVER USED AGAIN
         //              sumY2    += deviation_score_y[jj]
         //                        * deviation_score_y[jj];
                         sumY2    += ( meanY - vectorY[jj] ) // PSPACE MOTIVATED MINIMALISTIC WITH CACHE-BENEFITS IN PROCESSING
                                   * ( meanY - vectorY[jj] );
      }
      pearson_r = sumXY
                / MathSqrt( sumX2
                          * sumY2
                            );            // STOR RET VALUE IN RESULT
      return( RET_OK );                   // FLAG RET_OK in JIT/RET

方法 B:
在 R、MATLAB 等中重新使用具有 Pearson 相关性的外部库:

可以使用分布式处理,例如使用 ZeroMQ 消息传递基础设施来请求在 MQL4 之外/独立于本地主机处理执行微积分。

如果有兴趣,请阅读我的other posts on distributed processes in MQL4 ( a code-example -- just to have some feeling of how the MQL4 side gets setup -- could be found here) 和 MATLAB( ZeroMQ 基础设施设置的代码示例可以是 found here

从而允许使用 MATLAB 内置的 Pearson 相关性实现(请记住将数据正确地预先格式化为列,最好还添加一个 DIV!0-融合 ), 计算:

[ RHO, PVAL ] = corr( vectorX, vectorY, 'type', 'Pearson' );
                                               % note: double-r in corr() 
                                               %            # 'Pearson' is default method

类似地,R-语言有一个内置工具:

corr_r <- cor( vecORmatX, vecORmatY, use = "everything", method = "pearson" )
                                                            # "Pearson" is default method

最后但并非最不重要的是 python scipy.stats.stats pearsonr-作为工具的实施,同时具有 float32float64 精度:

>>> from scipy.stats.stats import pearsonr as pearson_r
>>>
>>> X = np.zeros( (5,), dtype = np.float32 )
>>> Y = np.zeros( (5,), dtype = np.float32 )
>>>
>>> X[0] =  1; X[1] = 3; X[2] =  5; X[3] =  5; X[4] =  6
>>> Y[0] =  5; Y[1] = 6; Y[2] = 10; Y[3] = 12; Y[4] = 13
>>>
>>> pearson_r( X, Y)
(0.94704783, 0.01451040731338055)
>>>
>>> X = np.zeros( (5,), dtype = np.float64 )
>>> Y = np.zeros( (5,), dtype = np.float64 )
>>>
>>> X[0] =  1; X[1] = 3; X[2] =  5; X[3] = 5; X[4] = 6
>>> Y[0] = 5; Y[1] = 6; Y[2] = 10; Y[3] = 12; Y[4] = 13
>>>
>>> pearson_r( X, Y)
(0.94704783738690446, 0.014510403904375592)
>>>

结语:
方法 A 产生结果 == python.scipy.stats.stats.pearsonr(X,Y)
(即引用的 onlinestatbook.com 结果不准确 )

2016.10.13 11:31:55.421 ___Whosebug_Pearson_r_DEMO XAUUSD,H1:
                           PearsonCorr_r( testX, testY, Pearson_r ):= 0.968
                           The actual call returned    aReturnCODE == 0,
                                  whereas the          Pearson_r   == 0.9470