Diskussion zum Artikel "Statistische Verteilungen in MQL5 - Nur das Beste aus R" - Seite 20

 

Das sind die Ergebnisse.



Auch nicht sehr gut... Im Allgemeinen gehört die Arbeit mit nicht-zentralen Beta-Verteilungen eher zu den nicht-trivialen Aufgaben. Wir haben es geschafft, Boost aus dem offenen Quellcode zu sehen. Und es wird komplizierter sein als das, was wir jetzt in SB haben.

 
Danke, wir werden uns das ansehen.
 
Denis Kirichenko #:

Die gleiche Wikipedia hat es:

Das heißt, es werden zwei Zufallsvariablen genommen, wobei die erste aus einer nicht zentralen Chi-Quadrat-Verteilung und die zweite aus einer zentralen Verteilung stammt. Wahrscheinlich kann der Code dahingehend korrigiert werden:

//--- Zufallszahl mit Noncentral ChiSquare erzeugen
double chi1=MathRandomNoncentralChiSquare(a2,lambda2,error_code);
double chi2=MathRandomChiSquare(b2,error_code);
 result[i]=chi1/(chi1+chi2);

Die geänderten Graphen im Beispiel werden unten stehen.

Vielen Dank, Sie haben Recht, wir müssen durch diese Formel zu berechnen, aber es war ein weiterer Fehler, der Lambda Nicht-Zentralität Parameter sollte ohne Multiplikator 2 sein.

//+------------------------------------------------------------------+
//| Zufallsvariable aus der nicht-zentralen Beta-Verteilung |
//+------------------------------------------------------------------+
//| Berechnen Sie die Zufallsvariable aus dem nichtzentralen Beta |
//| Verteilung mit den Parametern a, b und lambda.
//||
//| Argumente:|
//| a : Erster Formparameter |
//| b : Zweiter Formparameter |
//| lambda : Parameter der Nicht-Zentralität |
//| error_code : Variable für Fehlercode |
//||
//| Rückgabewert:|
//| Der Zufallswert mit nichtzentraler Beta-Verteilung.
//+------------------------------------------------------------------+
double MathRandomNoncentralBeta(const double a,const double b,const double lambda,int &error_code)
  {
//--- wenn lambda==0, Rückgabe der Zufallsvariante beta
   if(lambda==0.0)
      return MathRandomBeta(a,b,error_code);
//--- Parameter prüfen
   if(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
     {
      error_code=ERR_ARGUMENTS_NAN;
      return QNaN;
     }
//--- a,b,lambda muss positiv sein
   if(a<=0.0 || b<=0.0 || lambda<0)
     {
      error_code=ERR_ARGUMENTS_INVALID;
      return QNaN;
     }

   error_code=ERR_OK;
//--- Zufallszahl mit Noncentral ChiSquare erzeugen
   double chi1=MathRandomNoncentralChiSquare(2*a,lambda,error_code);
   double chi2=MathRandomChiSquare(2*b,error_code);
   return chi1/(chi1+chi2);
  }
//+------------------------------------------------------------------+
//| Zufallsvariable aus der nicht-zentralen Beta-Verteilung |
//+------------------------------------------------------------------+
//|| Erzeugt Zufallsvariablen aus der nicht-zentralen Beta-Verteilung |
//| mit den Parametern a,b, lambda.|
//||
//| Argumente:|
//| a : Erster Formparameter |
//| b : Zweiter Formparameter |
//| lambda : Parameter der Nicht-Zentralität |
data_count : Anzahl der benötigten Werte //|
//| Ergebnis: Array mit Zufallswerten ausgeben |
//||
//| Rückgabewert:|
//| true wenn erfolgreich, sonst false. ||
//+------------------------------------------------------------------+
bool MathRandomNoncentralBeta(const double a,const double b,const double lambda,const int data_count,double &result[])
  {
//--- wenn lambda==0, Rückgabe der Zufallsvariante beta
   if(lambda==0.0)
      return MathRandomBeta(a,b,data_count,result);
//--- Parameter prüfen
   if(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
      return false;
//--- a,b,lambda muss positiv sein
   if(a<=0.0 || b<=0.0 || lambda<0)
      return false;

   int error_code=0;
//--- Ausgabe-Array vorbereiten und Zufallswerte berechnen
   ArrayResize(result,data_count);
   double a2=a*2;
   double b2=b*2;
   for(int i=0; i<data_count; i++)
     {
      //--- Zufallszahl mit Noncentral ChiSquare erzeugen
      double chi1=MathRandomNoncentralChiSquare(a2,lambda,error_code);
      double chi2=MathRandomChiSquare(b2,error_code);
      result[i]=chi1/(chi1+chi2);
     }
   return true;
  }

Test-Skript:

//+------------------------------------------------------------------+
//|TestNoncentralBeta.mq5 |
//|Urheberrecht 2024, MetaQuotes Ltd. |
//| 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
//--- Eingabeparameter
input double a_par=2;    // erster Parameter der Beta-Verteilung (shape1)
input double b_par=5;    // zweiter Parameter der Beta-Verteilung (shape2)
input double l_par=1;    // Parameter der Nicht-Zentralität (Lambda)
//+------------------------------------------------------------------+
//| Skript-Programmstartfunktion|
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Anzeige des Preisdiagramms deaktivieren
   ChartSetInteger(0,CHART_SHOW,false);
//--- Initialisierung des Zufallszahlengenerators 
   MathSrand(GetTickCount());
//--- Erzeugen einer Stichprobe der Zufallsvariablen
   long chart=0;
   string name="GraphicNormal";
   int n=1000000;       // Anzahl der Werte in der Stichprobe
   int ncells=52;       // Anzahl der Intervalle im Histogramm
   double x[];          // Histogramm-Intervallzentren
   double y[];          // Anzahl der Werte aus der Stichprobe, die in das Intervall fallen
   double data[];       // Stichprobe von Zufallswerten 
   double max,min;      // Höchst- und Mindestwerte in der Stichprobe
//--- eine Stichprobe aus der nicht zentralen Beta-Verteilung erhalten 
   MathRandomNoncentralBeta(a_par,b_par,l_par,n,data);
//--- Daten für die Erstellung von Histogrammen berechnen
   CalculateHistogramArray(data,x,y,max,min,ncells);
//--- Ermittlung der Sequenzgrenzen und des Schritts für die theoretische Kurvenkonstruktion
   double step;
   GetMaxMinStepValues(max,min,step);
   step=MathMin(step,(max-min)/ncells);
//--- wir erhalten theoretisch berechnete Daten auf dem Intervall [min,max]
   double x2[];
   double y2[];
   MathSequence(min,max,step,x2);
   MathProbabilityDensityNoncentralBeta(x2,a_par,b_par,l_par,false,y2);
//--- Skalierung
   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;
//--- Diagramme anzeigen
   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);
//--- alle Kurven zeichnen
   graphic.CurveAdd(x,y,CURVE_HISTOGRAM,"Sample").HistogramWidth(6);
//--- und nun zeichnen wir die theoretische Verteilungsdichtekurve 
   graphic.CurveAdd(x2,y2,CURVE_LINES,"Theory");
   graphic.CurvePlotAll();
//--- alle Kurven zeichnen
   graphic.Update();
   
   DebugBreak();
  }
//+------------------------------------------------------------------+
//| Häufigkeiten für den Datensatz berechnen|
//+------------------------------------------------------------------+
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);
//--- die Zentren der Intervalle festlegen
   for(int i=0; i<cells; i++)
     {
      intervals[i]=minv+(i+0.5)*width;
      frequency[i]=0;
     }
//--- Ausfüllen der Intervallfrequenzen
   for(int i=0; i<size; i++)
     {
      int ind=int((data[i]-minv)/width);
      if(ind>=cells) ind=cells-1;
      frequency[ind]++;
     }
   return (true);
  }
//+------------------------------------------------------------------+
//| Berechnet Werte für die Sequenzerstellung |
//+------------------------------------------------------------------+
void GetMaxMinStepValues(double &maxv,double &minv,double &stepv)
  {
//--- Berechnung des absoluten Betrags der Sequenz, um die Normalisierungsgenauigkeit zu erhalten
   double range=MathAbs(maxv-minv);
   int degree=(int)MathRound(MathLog10(range));
//--- Maximal- und Minimalwerte mit der angegebenen Genauigkeit normalisieren
   maxv=NormalizeDouble(maxv,degree);
   minv=NormalizeDouble(minv,degree);
//--- Schritt der Sequenzerstellung ebenfalls von der angegebenen Genauigkeit ausgehend festgelegt
   stepv=NormalizeDouble(MathPow(10,-degree),degree);
   if((maxv-minv)/stepv<10)
      stepv/=10.;
  }

Ergebnis:

Nicht-zentralBeta(2,5,1)

Nicht-zentralBeta(2,5,10)

Nicht-zentralBeta(2,15,100)

Nicht-zentralBeta(2,15,20)

Dateien:
 

Ich habe auch die CFD-Funktion für die nichtzentrale Beta-Verteilung überprüft.

#include <Math\Stat\NoncentralBeta.mqh>
//+------------------------------------------------------------------+
//| Skript-Programmstartfunktion|
//+------------------------------------------------------------------+
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}
     };
// drucken
   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);
     }
  }


Einige fragwürdige Ergebnisse:

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


Alternative Quellen verwenden den ASA310-Algorithmus:

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.


Zum Beispiel einige der Ergebnisse in 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

Was der Wahrheit mehr oder weniger ähnlich ist...