文章 "MQL5 中的统计分布 - 取最佳的 R" - 页 20

 

这就是结果。



也不是很好...一般来说,处理非中心贝塔分布属于非难事。我们设法从开放源代码中看到了Boost。它将比现在的 SB 更加复杂。

 
谢谢,我们会去看看的。
 
Denis Kirichenko #:

维基百科上也有:

也就是说,取两个随机变量,第一个变量来自非中心奇平方分布,第二个变量来自中心 分布。也许代码可以这样修改:

//--- 使用非中心 ChiSquare 生成随机数
double chi1=MathRandomNoncentralChiSquare(a2,lambda2,error_code);
double chi2=MathRandomChiSquare(b2,error_code);
 result[i]=chi1/(chi1+chi2);

示例中修改后的图形如下。

谢谢您,您说得没错,我们需要通过这个公式进行计算,但还有一个错误,lambda 非中心性参数应该不带乘数 2。

//+------------------------------------------------------------------+
//| 来自非中心贝塔分布的随机变量
//+------------------------------------------------------------------+
//| 根据非中心贝塔计算随机变量
//| 参数为 a、b 和 lambda 的分布。
//||
//| 参数:|
//| a :第一个形状参数
//| b :第二个形状参数
//| lambda :非中心参数
//| error_code :错误代码变量
//||
//| 返回值:|
//| 采用非中心贝塔分布的随机值。
//+------------------------------------------------------------------+
double MathRandomNoncentralBeta(const double a,const double b,const double lambda,int &error_code)
  {
//--- 如果 lambda==0, 返回 beta 随机变量
   if(lambda==0.0)
      return MathRandomBeta(a,b,error_code);
//--- 检查参数
   if(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
     {
      error_code=ERR_ARGUMENTS_NAN;
      return QNaN;
     }
//--- a、b、lambda 必须为正数
   if(a<=0.0 || b<=0.0 || lambda<0)
     {
      error_code=ERR_ARGUMENTS_INVALID;
      return QNaN;
     }

   error_code=ERR_OK;
//--- 使用非中心 ChiSquare 生成随机数
   double chi1=MathRandomNoncentralChiSquare(2*a,lambda,error_code);
   double chi2=MathRandomChiSquare(2*b,error_code);
   return chi1/(chi1+chi2);
  }
//+------------------------------------------------------------------+
//| 来自非中心贝塔分布的随机变量
//+------------------------------------------------------------------+
//|| 根据非中心贝塔分布生成随机变量
//| 带参数 a、b、lambda。|
//||
//| 参数:|
//| a :第一个形状参数
//| b :第二个形状参数
//| lambda :非中心参数
//| data_count : 所需值的数量
//} result : 包含随机值的输出数组
//||
//| 返回值:|
//| 如果成功则为 true,否则为 false。
//+------------------------------------------------------------------+
bool MathRandomNoncentralBeta(const double a,const double b,const double lambda,const int data_count,double &result[])
  {
//--- 如果 lambda==0, 返回 beta 随机变量
   if(lambda==0.0)
      return MathRandomBeta(a,b,data_count,result);
//--- 检查参数
   if(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
      return false;
//--- a、b、lambda 必须为正数
   if(a<=0.0 || b<=0.0 || lambda<0)
      return false;

   int error_code=0;
//--- 准备输出数组并计算随机值
   ArrayResize(result,data_count);
   double a2=a*2;
   double b2=b*2;
   for(int i=0; i<data_count; i++)
     {
      //--- 使用非中心 ChiSquare 生成随机数
      double chi1=MathRandomNoncentralChiSquare(a2,lambda,error_code);
      double chi2=MathRandomChiSquare(b2,error_code);
      result[i]=chi1/(chi1+chi2);
     }
   return true;
  }

测试脚本:

//+------------------------------------------------------------------+
//|TestNoncentralBeta.mq5
//|版权所有 2024 年,MetaQuotes 有限公司。|
//|https://www.mql5.com ||
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <Graphics\Graphic.mqh>
#include <Math\Stat\NoncentralBeta.mqh>
#include <Math\Stat\Math.mqh>
#property script_show_inputs
//--- 输入参数
input double a_par=2;    // 贝塔分布的第一个参数(shape1)
input double b_par=5;    // 第二个贝塔分布参数(shape2)
input double l_par=1;    // 非中心参数 (lambda)
//+------------------------------------------------------------------+
//| 脚本程序启动功能|
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 禁用价格图表显示
   ChartSetInteger(0,CHART_SHOW,false);
//--- 初始化随机数生成器 
   MathSrand(GetTickCount());
//--- 生成随机变量的样本
   long chart=0;
   string name="GraphicNormal";
   int n=1000000;       // 样本中的数值个数
   int ncells=52;       // 直方图中的区间数
   double x[];          // 直方图区间中心
   double y[];          // 样本中属于区间的数值个数
   double data[];       // 随机值取样 
   double max,min;      // 样本中的最大值和最小值
//--- 从非中心贝塔分布中获取样本 
   MathRandomNoncentralBeta(a_par,b_par,l_par,n,data);
//--- 计算数据以构建直方图
   CalculateHistogramArray(data,x,y,max,min,ncells);
//--- 获得序列边界和理论曲线构造的步骤
   double step;
   GetMaxMinStepValues(max,min,step);
   step=MathMin(step,(max-min)/ncells);
//--- 我们获得了区间 [最小,最大] 的理论计算数据
   double x2[];
   double y2[];
   MathSequence(min,max,step,x2);
   MathProbabilityDensityNoncentralBeta(x2,a_par,b_par,l_par,false,y2);
//--- 缩放
   double theor_max=y2[ArrayMaximum(y2)];
   double sample_max=y[ArrayMaximum(y)];
   double k=sample_max/theor_max;
   for(int i=0; i<ncells; i++)
      y[i]/=k;
//--- 显示图表
   CGraphic graphic;
   if(ObjectFind(chart,name)<0)
      graphic.Create(chart,name,0,0,0,780,380);
   else
      graphic.Attach(chart,name);
   graphic.BackgroundMain(StringFormat("Noncentral Beta distribution alpha=%G beta=%G lambda=%G",
                          a_par,b_par,l_par));
   graphic.BackgroundMainSize(16);
//--- 绘制所有曲线
   graphic.CurveAdd(x,y,CURVE_HISTOGRAM,"Sample").HistogramWidth(6);
//--- 现在我们来绘制理论分布密度曲线 
   graphic.CurveAdd(x2,y2,CURVE_LINES,"Theory");
   graphic.CurvePlotAll();
//--- 绘制所有曲线
   graphic.Update();
   
   DebugBreak();
  }
//+------------------------------------------------------------------+
//| 计算数据集的频率|
//+------------------------------------------------------------------+
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 GetMaxMinStepValues(double &maxv,double &minv,double &stepv)
  {
//--- 计算序列的绝对幅度,以获得归一化精度
   double range=MathAbs(maxv-minv);
   int degree=(int)MathRound(MathLog10(range));
//--- 将最大值和最小值归一化,达到指定精度
   maxv=NormalizeDouble(maxv,degree);
   minv=NormalizeDouble(minv,degree);
//--- 序列生成的步骤也是根据给定的精确度设定的
   stepv=NormalizeDouble(MathPow(10,-degree),degree);
   if((maxv-minv)/stepv<10)
      stepv/=10.;
  }

结果:

非中心贝塔(2,5,1)

非中心贝塔(2,5,10)

非中心贝塔值(2,15,100)

非中心贝塔(2,15,20)

附加的文件:
 

我还检查了非中心贝塔分布的 CFD 功能。

#include <Math\Stat\NoncentralBeta.mqh>
//+------------------------------------------------------------------+
//| 脚本程序启动功能|
//+------------------------------------------------------------------+
void OnStart()
  {
   matrix nc_beta_params_mx =
     {
      // a b lambda x
        {5, 5, 54, 0.864},
        {5, 5, 140, 0.9},
        {5, 5, 170, 0.956},
        {10, 10, 54, 0.8686},
        {10, 10, 140, 0.9},
        {10, 10, 250, 0.9},
        {20, 20, 54, 0.8787},
        {20, 20, 140, 0.9},
        {20, 20, 250, 0.922},
        {10, 20, 150, 0.868},
        {10, 10, 120, 0.9},
        {15, 5, 80, 0.88},
        {20, 10, 110, 0.85},
        {20, 30, 65, 0.66},
        {20, 50, 130, 0.72},
        {30, 20, 80, 0.72},
        {30, 40, 130, 0.8},
        {10, 5, 20, 0.644},
        {10, 10, 54, 0.7},
        {10, 30, 80, 0.78},
        {15, 20, 120, 0.76},
        {10, 5, 55, 0.795},
        {12, 17, 64, 0.56},
        {30, 30, 140, 0.8},
        {35, 30, 20, 0.67}
     };
// 打印
   PrintFormat("A - B - LAMBDA - X - CDF");
   for(ulong row = 0; row < nc_beta_params_mx.Rows(); row++)
     {
      double a_par, b_par, l_par, x_val;
      a_par = nc_beta_params_mx[row][0];
      b_par = nc_beta_params_mx[row][1];
      l_par = nc_beta_params_mx[row][2];
      x_val = nc_beta_params_mx[row][3];
      int error_code;
      double res_val = MathCumulativeDistributionNoncentralBeta(x_val, a_par,
                       b_par, l_par, error_code);
      ::PrintFormat("%0.0f, %0.0f, %0.0f, %0.2f -->  %0.5f",
                    a_par, b_par, l_par, x_val, res_val);
     }
  }


有些结果值得商榷:

A - B - LAMBDA - X - CDF
5, 5, 54, 0.86 -->  0.74058
5, 5, 140, 0.90 -->  0.40096
5, 5, 170, 0.96 -->  1.00000
10, 10, 54, 0.87 -->  1.00000
10, 10, 140, 0.90 -->  0.99296
10, 10, 250, 0.90 -->  1.00000
20, 20, 54, 0.88 -->  1.00000
20, 20, 140, 0.90 -->  1.00000
20, 20, 250, 0.92 -->  1.00000
10, 20, 150, 0.87 -->  1.00000
10, 10, 120, 0.90 -->  1.00000
15, 5, 80, 0.88 -->  1.00000
20, 10, 110, 0.85 -->  1.00000
20, 30, 65, 0.66 -->  1.00000
20, 50, 130, 0.72 -->  1.00000
30, 20, 80, 0.72 -->  1.00000
30, 40, 130, 0.80 -->  1.00000
10, 5, 20, 0.64 -->  0.05069
10, 10, 54, 0.70 -->  0.18781
10, 30, 80, 0.78 -->  1.00000
15, 20, 120, 0.76 -->  1.00000
10, 5, 55, 0.80 -->  0.13001
12, 17, 64, 0.56 -->  0.00231
30, 30, 140, 0.80 -->  1.00000
35, 30, 20, 0.67 -->  0.88671


其他来源使用的是 ASA310 算法:

23 July 2024 05:23:28 PM

ASA310_PRB:
  C++ version
  Test the ASA310 library.

TEST01:
  NCBETA computes the noncentral incomplete Beta function.
  Compare to tabulated values.

      A        B     LAMBDA        X          FX                        FX2
                                              (Tabulated)               (NCBETA)            DIFF

        5        5       54       0.864                 0.4563021        0.4563022483390367   1.483 e-07
        5        5      140         0.9                 0.1041337        0.1041334790875982   2.209 e-07
        5        5      170       0.956                 0.6022353        0.6022418158548807   6.516 e-06
       10       10       54      0.8686                  0.918777        0.9187759254330974   1.075 e-06
       10       10      140         0.9                 0.6008106        0.6008067894096832   3.811 e-06
       10       10      250         0.9                  0.090285        0.0902898993260559   4.899 e-06
       20       20       54      0.8787                 0.9998655        0.9998614048611703   4.095 e-06
       20       20      140         0.9                 0.9925997        0.9925954777347362   4.222 e-06
       20       20      250       0.922        0.9641111999999999        0.9641179545701509   6.755 e-06
       10       20      150       0.868              0.9376626573        0.9376626555219731   1.778 e-09
       10       10      120         0.9              0.7306817858         0.730681784479193   1.321 e-09
       15        5       80        0.88              0.1604256918        0.1604256916919781    1.08 e-10
       20       10      110        0.85              0.1867485313         0.186748530948068   3.519 e-10
       20       30       65        0.66        0.6559386874000001        0.6559386873992288   7.713 e-13
       20       50      130        0.72              0.9796881486        0.9796881474202076    1.18 e-09
       30       20       80        0.72              0.1162386423        0.1162386421523797   1.476 e-10
       30       40      130         0.8              0.9930430054        0.9930430042307262   1.169 e-09
       10        5       20       0.644              0.0506899273       0.05068987981355273   4.749 e-08
       10       10       54         0.7              0.1030959706        0.1030959706112684   1.127 e-11
       10       30       80        0.78        0.9978417832000001        0.9978417830424838   1.575 e-10
       15       20      120        0.76              0.2555552369        0.2555552355854933   1.315 e-09
       10        5       55       0.795              0.0668307064        0.0668307064085136   8.514 e-12
       12       17       64        0.56              0.0113601067       0.01136010666591296   3.409 e-11
       30       30      140         0.8              0.7813366615        0.7813366591185901   2.381 e-09
       35       30       20        0.67              0.8867126477        0.8867125569354448   9.076 e-08

ASA310_PRB:
  Normal end of execution.


例如 Wolfram Mathematica 中的一些结果:

Table[CDF[NoncentralBetaDistribution[5,5,140],0.9]]
= 0.1041335
Table[CDF[NoncentralBetaDistribution[15,5,80],0.88]]
= 0.1604257
Table[CDF[NoncentralBetaDistribution[35, 30, 20], 0.67]]
= 0.8867126

这或多或少与真相相似...