程序库: 统计功能 - 页 3

 

你好,我 其中一个函数有疑问。


我需要用标准的 Dickey Fuller 检验来确定是否存在静态性。我看到这套程序中有这个测试,但我不知道它使用的是哪种测试,因为 Dickey Fuller 既有标准测试,也有增强测试,而在这两种测试中,我们又有几种测试,包括引入漂移、常数等的测试。

我看到了代码,但公式并不合适,我也用其他程序(如 R)检查了结果,但并没有得到相同的结果,所以我想知道是否有人确切知道使用的是哪种检验,这样我就能知道我是否在所有程序中使用了相同的检验,或者看看差异在哪里等等。

非常感谢

 
//+------------------------------------------------------------------+
//|统计。mqh | |
//|版权所有 2015, Herajika |
//|morinoherajika@gmail.com ||
//+------------------------------------------------------------------+
#property copyright "赫拉吉卡/亚当-斯鲁基"
#property link      "morinoherajika@gmail.com"

//+------------------------------------------------------------------+
#include <Expert/Expert.mqh>
#include <Trade/SymbolInfo.mqh>
#include <Trade/OrderInfo.mqh>
#include <Trade/HistoryOrderInfo.mqh>
#include <Trade/Trade.mqh>
#include <Trade/PositionInfo.mqh>
#include <Trade/DealInfo.mqh>
#include <Trade/TerminalInfo.mqh>  
#include <Trade/AccountInfo.mqh>  
#include <Object.mqh>
#include <MovingAverages.mqh>
#include <Arrays\ArrayObj.mqh>
#include <Math\Stat\Math.mqh>
#include <Math\Alglib\statistics.mqh>
//--------------------------------------------------------------

MqlTradeRequest mrequest;  // Used for sending our trade requests
MqlTradeResult mresult;    // Used to get our trade results
MqlRates mrate[];          // Used to store the prices, volumes and spread of each bar
CTerminalInfo terminalInfo;
                       
datetime startTime = TimeCurrent();
datetime lastCheckedTradeTime = startTime;
                       
bool sqDisplayInfoPanel = MQLInfoInteger(MQL_TESTER) != 0 && MQLInfoInteger(MQL_OPTIMIZATION) != 0;
int sqLabelCorner = 1;
int sqOffsetHorizontal = 5;
int sqOffsetVertical = 20;
color sqLabelColor = clrWhite;

int magicNumber;
int minBars = 30;
int sqMaxSlippage;
int sqVerboseMode;
int sqMaxRetries = 5;

double gPointCoef = 0;                  

int deviationPoints = 10;
int sqTicket = 1;
datetime lastBarTime;
bool mcond[100];

double initialBalance = 0;

string valueIdentificationSymbol = "";

int indicatorHandles[];
//+------------------------------------------------------------------+


bool _sqIsBarOpen;
input int OpenBarDelay = 0; // 酒吧开放时间延迟,以分钟为单位
input int ma_period1  = 55;
input int ma_shift1  = 0 ;
input int ma_period2  = 144;
input int ma_shift2  = 0 ;
input ENUM_MA_METHOD       movavg_method=MODE_EMA;           // 平滑类型 
input ENUM_APPLIED_PRICE   applied_price=PRICE_CLOSE;    // EMA 价格类型

input string statistics = "-----------statistics analysis  -----------";

int hnd1, hnd2;
double arr1[], arr2[];
input int statSampleSize = 100; /将样本量限制在 100 个值以内

double detrendres[] , olsres[];
double aLinCoeff = 0.0, bLinCoeff = 0.0, cointegrationCoeff = 0.0;
double AugDF,egt,AR1forcast;

#define  EMA_1 0                   //iMA(NULL,0,ma_period1,ma_shift1,ma_method,PRICE_CLOSE)
#define  EMA_2 1                   //iMA(NULL,0,ma_period2,ma_shift2,ma_method,PRICE_CLOSE)

//+------------------------------------------------------------------+
//| 专家勾选功能|
//+------------------------------------------------------------------+
void OnTick() {


 //************************************************************************
   //--- 我们有足够的酒吧来工作吗?
   if(Bars(_Symbol,_Period) < minBars) {   // 如果总条数小于 minBars
      Alert(StringFormat("NOT ENOUGH DATA: Less Bars than %d", minBars));
      return;
   }

   //--- 获取最近 2 个条形图的详细信息
   if(CopyRates(_Symbol, _Period, 0, 2, mrate) < 2) {
      Alert("Error copying rates/history data - error:", GetLastError(), "!!");
      ResetLastError();
      return;
   }
     
   ZeroMemory(mrequest);      // 初始化 mrequest 结构
   
   
   // 用于存储指标值的动态数组是 arr1[]、arr2[] 和 arr3[]。
   // 已经在上面声明
   
   
   // 在数组中设置与时间序列相同的索引,即数组元素为零
   // 索引将存储最后一个条形图的值,第 i 个索引是最后一个条形图的值,以此类推。
   ArraySetAsSeries(arr1, true);
   ArraySetAsSeries(arr2, true);
   
     
   // 使用指标句柄,复制指标值
   // 将缓冲区转换为数组,这是专门为此准备的
   CopyBuffer(hnd1,0,0,statSampleSize,arr1);
   CopyBuffer(hnd2,0,0,statSampleSize,arr2);
   
   checkBarOpen();
   
    if (_sqIsBarOpen == true) //为避免 CPU 和内存占用过高,我们只在酒吧开门时进行计算。
   {
          
      //第 1 步:从样本数据中移除趋势(程序中包含回归) - 返回数组
      detrend(arr1, detrendres);      
      
      //第 2 步 样本静态检验 - 返回值
      AugDF = dickeyFuller(detrendres);
      
      //步骤 3 样本协整检验 - 返回值
      egt =  engleGrangerTest(detrendres, arr1, cointegrationCoeff);
      
      //第 4 步 如果 Lag = 1,预测样本 AR1 的下一个值 - 返回值
      AR1forcast = AR1(detrendres);
      
      Print("adf = ", AugDF, "  egt = ", egt , "  ar1 = ",AR1forcast);
  }
   
   
}

//+------------------------------------------------------------------+
//| 专家初始化函数|
//+------------------------------------------------------------------+
int OnInit()
{
   
   //初始化所有数组指标句柄
   if(!initIndicators()) return(INIT_FAILED);
   
     
   //复制数组 用于数学统计计算 
   hnd1 = indicatorHandles[EMA_1];     //iMA(NULL,0,ma_period1,ma_shift1,ma_method,applied_price)
   hnd2 = indicatorHandles[EMA_2];     //iMA(NULL,0,ma_period2,ma_shift2,ma_method,applied_price)
   
   return(INIT_SUCCEEDED);
   
}

//+------------------------------------------------------------------+
//| 专家去初始化函数|
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
    writeReportFile(); 
  }


bool initIndicators(){
   
   ArrayResize(indicatorHandles, ArraySize(indicatorHandles) + 1, 10);
   indicatorHandles[EMA_1] = iMA(NULL,0,ma_period1,ma_shift1,movavg_method,applied_price) ;
   
   ArrayResize(indicatorHandles, ArraySize(indicatorHandles) + 1, 10);
   indicatorHandles[EMA_2] = iMA(NULL,0,ma_period2,ma_shift2,movavg_method,applied_price) ;
   
         
   for(int a=0; a<ArraySize(indicatorHandles); a++){
      //--- 如果没有创建句柄 
      if(indicatorHandles[a] == INVALID_HANDLE) { 
         //--- 报告故障并输出错误代码 
         Print("Failed to create handle of the indicator, error code %d", GetLastError()); 
         //---指标提前停止 
         return(false); 
      }
   }
   
   return(true);
}             


// NOTE: 
// 如果将数组的大小调整为 i,数组将包含 arr[0] 到 arr[i-1] 的内容
// arr[i] 不存在,因此会出现数组超出范围的错误。

//--- 时间序列分解(去除趋势)
void detrend(double &arr[],double &res[])
  {
   double regRes[];
   double iterator[];
   int length=ArraySize(arr);
   ArrayResize(regRes,length);
   ArrayResize(iterator,length);
//---
   for(int i=0; i<length; i++)
     {
      iterator[i]=i+1;
     }
//---
   regression(iterator,arr,regRes);
//---

   for(int i=0; i<length;i++)
     {
      Print("   arr = ", arr[i], "   regRes  = ", regRes[i], "    SumXY =", arr[i] - regRes[i] );
      res[i] = arr[i] - regRes[i]; // 注意:此处出现 "数组超出范围"。

     }
  }
  
 
 //===================================================== 
//--- 返回包含回归线值的数组
void regression(double &tsarr1[],double &tsarr2[],double &res[])
  {
//---
   double a = 0;
   double b = 0;
//---
   int length=ArraySize(tsarr1);
//---
   ArrayResize(res,length);
//---
   double meanX = MathMean(tsarr1);
   double meanY = MathMean(tsarr2);
//---
   double sumXY=0;
   double sqSumX=0;
//---
   for(int i=0; i<length; i++)
     {
      Print("   tsarr1 = ", tsarr1[i], "   tsarr2  = ", tsarr2[i], "    SumXY =", tsarr1[i]*tsarr2[i] );
      sumXY+=tsarr1[i]*tsarr2[i];
      sqSumX+=MathPow(tsarr1[i],2);
     }
//---
   a = (sumXY - length*meanX*meanY)/(sqSumX - length*MathPow(meanX,2));
   b = meanY - a*meanX;
//---
   for(int i=0; i<length; i++)
     {
      res[i]=a*tsarr1[i]+b;
     }
  }
  
 //===================================================== 
//--- 返回包含回归线值和回归线系数(来自 y = ax+b 的 a 和 b)的数组
void regression(double &tsarr1[],double &tsarr2[],double &res[],double &aCoeff,double &bCoeff)
  {
//---
   double a = 0;
   double b = 0;
//---
   int length=ArraySize(arr1);
//---
   ArrayResize(res,length);
//---
   double meanX = MathMean(tsarr1);
   double meanY = MathMean(tsarr2);
//---
   double sumXY=0;
   double sqSumX=0;
//---
   for(int i=0; i<length; i++)
     {
      sumXY+=tsarr1[i]*tsarr2[i];
      sqSumX+=MathPow(tsarr1[i],2);
     }
//---
   a = (sumXY - length*meanX*meanY)/(sqSumX - length*MathPow(meanX,2));
   b = meanY - a*meanX;
//---
   for(int i=0; i<length; i++)
     {
      res[i]=a*tsarr1[i]+b;
     }
   aCoeff = a;
   bCoeff = b;
  }
  
//======================Test for STATIONARITY=============================== 
//---增量迪基-富勒静态检验
//bool dickeyFuller(double &arr[])
double dickeyFuller(double &arr[])
  {
// n=25 50 100 250 500 >500
// {-2.62, -2.60, -2.58, -2.57, -2.57, -2.57};
   double cVal;
   bool result;
   int n=ArraySize(arr);
   double tValue;
   double corrCoeff;
   double copyArr[];
   double difference[];
   ArrayResize(difference,n-1);
//---
   for(int i=0; i<n-1; i++)
     {
      difference[i]=arr[i+1]-arr[i];
     }
//---
   ArrayCopy(copyArr,arr,0,0,n-1);
   //corrCoeff=myStats.PearsonCorr2(copyArr,difference,statSampleSize);
   corrCoeff=myStats.SpearmanCorr2(copyArr,difference,statSampleSize);
   tValue=corrCoeff*MathSqrt((n-2)/(1-MathPow(corrCoeff,2)));
//---
   if(n<25)
     {
      cVal=-2.62;
        }else{
      if(n>=25 && n<50)
        {
         cVal=-2.60;
           }else{
         if(n>=50 && n<100)
           {
            cVal=-2.58;
              }else{
            cVal=-2.57;
           }
        }
     }
//Print(tValue);
   result=tValue>cVal;
   return(result);
   return (tValue);
  }
 
 
//====================Test for COINTEGRATION================================= 
//--- 返回 beta 参数 
bool engleGrangerTest(double &tsarr1[],double &tsarr2[],double &cointCoeff)
  {
   bool result;
   int length=ArraySize(tsarr1);
   double regressionRes[];
   double residuals[];
   double copyArr1[],copyArr2[];
   double a;
   double b;
//---
   ArrayResize(regressionRes,length);
   ArrayResize(residuals,length);
   ArrayResize(copyArr1,length);
   ArrayResize(copyArr2,length);
//---
   ArrayCopy(copyArr1,tsarr1,0,0);
   ArrayCopy(copyArr2,tsarr2,0,0);
//---
   for(int i=0; i<length;i++)
     {
      copyArr1[i] = MathLog(copyArr1[i]);
      copyArr2[i] = MathLog(copyArr2[i]);
     }
//---
   regression(copyArr1,copyArr2,regressionRes,a,b);
   cointCoeff=a;
//---
   for(int i=0; i<length; i++)
     {
      residuals[i]=copyArr2[i]-regressionRes[i];
     }
//---
   result=dickeyFuller(residuals);
//---
   return(result);
  }
  
  
//===================================================== 
//--- 滞后 1 的自回归模型;预测下一期的回报率
double AR1(double &arr[])
  {
   double arrY[],arrX[],regRes[];
   double a,b,fcst;
   int n=ArraySize(arr);
   ArrayResize(arrY,n-1);
   ArrayResize(arrX,n-1);
//---
   ArrayCopy(arrY,arr,0,1,n-1);
   ArrayCopy(arrX,arr,0,0,n-1);
//---
   regression(arrX,arrY,regRes,a,b);
   fcst=arr[n-1]*a+b;
//---
   return(fcst);
  }
  
//===================================================== 
  
//--- [a -> down, b -> up, n -> polynominal degree] (a -> down, b -> up, n -> polynominal degree
double signedIntegral(double a,double b,int n)
  {
//---
   int mult;
   double h=(b-a)/n;
   double integral=foo(a);
//---
   for(int i=1; i<n; i++)
     {
      if(i%2==0) mult=4; else mult=2;
      integral+=mult*(foo(a+i*h));
     }
//---
   integral += foo(a+n*h);
   integral *= h/3;
//---
   return integral;
  }
  
//===================================================== 
  
//--- 编辑后与积分一起使用
double foo(double x)
  {
   return x;
  }
  
//===================================================== 

//--- 鸣谢 Sitt Chee Keen
double erf(double x)
  {
//--- A&S 公式 7.1.26
   double a1 = 0.254829592;
   double a2 = -0.284496736;
   double a3 = 1.421413741;
   double a4 = -1.453152027;
   double a5 = 1.061405429;
   double p=0.3275911;
   x=MathAbs(x);
   double t=1/(1+p*x);
//---
   return 1 - ((((((a5 * t + a4) * t) + a3) * t + a2) * t) + a1) * t * MathExp(-1 * x * x);
  }
  
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
double normDistZ(double z)
  {
   double sign=1;
   if(z<0) sign=-1;
   return 0.5 * (1.0 + sign * erf(MathAbs(z)/MathSqrt(2)));
  }
//+------------------------------------------------------------------+

void checkBarOpen(){
   datetime currentBarTime = mrate[0].time;   
   _sqIsBarOpen = false;
   
   if(lastBarTime == 0){
      _sqIsBarOpen = true;          
      lastBarTime = currentBarTime;
   }
   else if(currentBarTime != lastBarTime){
      bool processBarOpen = true;

      if(OpenBarDelay > 0) {
         // 设置条形图在实际打开 X 分钟后打开
         processBarOpen = false;

         int diffInSeconds = (int) (TimeCurrent() - currentBarTime);
         if(diffInSeconds >= OpenBarDelay * 60) {
            processBarOpen = true;
         }
      }

      if(processBarOpen) {
         _sqIsBarOpen = true;
         lastBarTime = currentBarTime;      
      } 
   }
}





帮助:在尝试更新以前的脚本以符合更新的 MQL5 statistics.mqh 之后,我似乎在去趋势方法中遇到了 "数组超出范围 错误"。我错过了什么?