Também não são muito bons... Em geral, trabalhar com uma distribuição beta não centralizada pertence à classe de tarefas não triviais. Conseguimos ver o Boost no código-fonte aberto. E ele será mais complicado do que o que temos agora no SB.
Ou seja, duas variáveis aleatórias são tomadas, onde a primeira é de uma distribuição qui-quadrado não central e a segunda é de uma distribuição central. Provavelmente o código pode ser corrigido para isso:
//--- gerar número aleatório usando Noncentral ChiSquaredouble chi1=MathRandomNoncentralChiSquare(a2,lambda2,error_code);double chi2=MathRandomChiSquare(b2,error_code);
result[i]=chi1/(chi1+chi2);
Os gráficos modificados no exemplo estarão abaixo.
Obrigado, você está certo, precisamos calcular por meio dessa fórmula, mas houve outro erro, o parâmetro de não centralidade lambda deveria estar sem o multiplicador 2.
//+------------------------------------------------------------------+//| Variável aleatória da distribuição Beta não centralizada//+------------------------------------------------------------------+//| Calcular a variável aleatória a partir do Beta não central//| distribuição com parâmetros a,b e lambda. ||//||//| Argumentos:|//| a : Primeiro parâmetro de forma |//| b : Segundo parâmetro de forma |//| lambda : Parâmetro de não centralidade |//| error_code : Variável para o código de erro//||//| Valor de retorno:|//| O valor aleatório com distribuição Beta não central.//+------------------------------------------------------------------+double MathRandomNoncentralBeta(constdouble a,constdouble b,constdouble lambda,int &error_code)
{
//--- se lambda==0, retorna a variante aleatória betaif(lambda==0.0)
return MathRandomBeta(a,b,error_code);
//--- verificar parâmetrosif(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
{
error_code=ERR_ARGUMENTS_NAN;
return QNaN;
}
//--- a,b,lambda devem ser positivosif(a<=0.0 || b<=0.0 || lambda<0)
{
error_code=ERR_ARGUMENTS_INVALID;
return QNaN;
}
error_code=ERR_OK;
//--- gerar número aleatório usando Noncentral ChiSquaredouble chi1=MathRandomNoncentralChiSquare(2*a,lambda,error_code);
double chi2=MathRandomChiSquare(2*b,error_code);return chi1/(chi1+chi2);
}
//+------------------------------------------------------------------+//| Variável aleatória da distribuição Beta não centralizada//+------------------------------------------------------------------+//|| Gera variáveis aleatórias a partir da distribuição Beta não centralizada//| com parâmetros a,b, lambda.|//||//| Argumentos:|//| a : Primeiro parâmetro de forma |//| b : Segundo parâmetro de forma |//| lambda : Parâmetro de não centralidade |//| Data_count : Número de valores necessários//| Resultado: matriz de saída com valores aleatórios//||//| Valor de retorno:|//| verdadeiro se for bem-sucedido, caso contrário, falso.//+------------------------------------------------------------------+bool MathRandomNoncentralBeta(constdouble a,constdouble b,constdouble lambda,constint data_count,double &result[])
{
//--- se lambda==0, retorna a variante aleatória betaif(lambda==0.0)
return MathRandomBeta(a,b,data_count,result);
//--- verificar parâmetrosif(!MathIsValidNumber(a) || !MathIsValidNumber(b) || !MathIsValidNumber(lambda))
returnfalse;
//--- a,b,lambda devem ser positivosif(a<=0.0 || b<=0.0 || lambda<0)
returnfalse;
int error_code=0;
//--- preparar a matriz de saída e calcular os valores aleatóriosArrayResize(result,data_count);
double a2=a*2;
double b2=b*2;
for(int i=0; i<data_count; i++)
{
//--- gerar número aleatório usando Noncentral ChiSquaredouble chi1=MathRandomNoncentralChiSquare(a2,lambda,error_code);
double chi2=MathRandomChiSquare(b2,error_code);
result[i]=chi1/(chi1+chi2);
}
returntrue;
}
Script de teste:
//+------------------------------------------------------------------+//|TestNoncentralBeta.mq5//|Copyright 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//--- parâmetros de entradainputdouble a_par=2; // primeiro parâmetro da distribuição beta (shape1)inputdouble b_par=5; // segundo parâmetro de distribuição beta (shape2)inputdouble l_par=1; // parâmetro de não-centralidade (lambda)//+------------------------------------------------------------------+//| Função de início do programa de script|//+------------------------------------------------------------------+voidOnStart()
{
//--- desativar a exibição do gráfico de preçosChartSetInteger(0,CHART_SHOW,false);
//--- inicializar o gerador de números aleatórios MathSrand(GetTickCount());
//--- gerar uma amostra da variável aleatórialong chart=0;
string name="GraphicNormal";
int n=1000000; // número de valores na amostraint ncells=52; // número de intervalos no histogramadouble x[]; // centros de intervalo do histogramadouble y[]; // número de valores da amostra que se enquadram no intervalodouble data[]; // amostragem de valores aleatórios double max,min; // valores máximos e mínimos na amostra//--- obter uma amostra da distribuição beta não central
MathRandomNoncentralBeta(a_par,b_par,l_par,n,data);
//--- calcular dados para a construção do histograma
CalculateHistogramArray(data,x,y,max,min,ncells);
//--- obter os limites da sequência e a etapa para a construção da curva teóricadouble step;
GetMaxMinStepValues(max,min,step);
step=MathMin(step,(max-min)/ncells);
//--- obtemos dados calculados teoricamente no intervalo [min,max]double x2[];
double y2[];
MathSequence(min,max,step,x2);
MathProbabilityDensityNoncentralBeta(x2,a_par,b_par,l_par,false,y2);
//--- escalonamentodouble 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;
//--- exibir gráficos
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);
//--- traçar todas as curvas
graphic.CurveAdd(x,y,CURVE_HISTOGRAM,"Sample").HistogramWidth(6);
//--- e agora vamos traçar a curva de densidade de distribuição teórica
graphic.CurveAdd(x2,y2,CURVE_LINES,"Theory");
graphic.CurvePlotAll();
//--- traçar todas as curvas
graphic.Update();
DebugBreak();
}
//+------------------------------------------------------------------+//| Calcular frequências para o conjunto de dados|//+------------------------------------------------------------------+bool CalculateHistogramArray(constdouble &data[],double &intervals[],double &frequency[],
double &maxv,double &minv,constint 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) returnfalse;
ArrayResize(intervals,cells);
ArrayResize(frequency,cells);
//--- definir os centros dos intervalosfor(int i=0; i<cells; i++)
{
intervals[i]=minv+(i+0.5)*width;
frequency[i]=0;
}
//--- preencher as frequências de intervalofor(int i=0; i<size; i++)
{
int ind=int((data[i]-minv)/width);
if(ind>=cells) ind=cells-1;
frequency[ind]++;
}
return (true);
}
//+------------------------------------------------------------------+//| Calcula valores para a geração de sequências//+------------------------------------------------------------------+void GetMaxMinStepValues(double &maxv,double &minv,double &stepv)
{
//--- calcular a magnitude absoluta da sequência para obter a precisão da normalizaçãodouble range=MathAbs(maxv-minv);
int degree=(int)MathRound(MathLog10(range));
//--- normalizar os valores máximos e mínimos com a precisão especificada
maxv=NormalizeDouble(maxv,degree);
minv=NormalizeDouble(minv,degree);
//--- a etapa de geração da sequência também é definida a partir da precisão fornecida
stepv=NormalizeDouble(MathPow(10,-degree),degree);
if((maxv-minv)/stepv<10)
stepv/=10.;
}
23 July 202405: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
55540.8640.45630210.45630224833903671.483 e-07551400.90.10413370.10413347908759822.209 e-07551700.9560.60223530.60224181585488076.516 e-061010540.86860.9187770.91877592543309741.075 e-0610101400.90.60081060.60080678940968323.811 e-0610102500.90.0902850.09028989932605594.899 e-062020540.87870.99986550.99986140486117034.095 e-0620201400.90.99259970.99259547773473624.222 e-0620202500.9220.96411119999999990.96411795457015096.755 e-0610201500.8680.93766265730.93766265552197311.778 e-0910101200.90.73068178580.7306817844791931.321 e-09155800.880.16042569180.16042569169197811.08 e-1020101100.850.18674853130.1867485309480683.519 e-102030650.660.65593868740000010.65593868739922887.713 e-1320501300.720.97968814860.97968814742020761.18 e-093020800.720.11623864230.11623864215237971.476 e-1030401300.80.99304300540.99304300423072621.169 e-09105200.6440.05068992730.050689879813552734.749 e-081010540.70.10309597060.10309597061126841.127 e-111030800.780.99784178320000010.99784178304248381.575 e-1015201200.760.25555523690.25555523558549331.315 e-09105550.7950.06683070640.06683070640851368.514 e-121217640.560.01136010670.011360106665912963.409 e-1130301400.80.78133666150.78133665911859012.381 e-093530200.670.88671264770.88671255693544489.076 e-08
ASA310_PRB:
Normal end of execution.
Por exemplo, alguns dos resultados no Wolfram Mathematica:
Estes são os resultados.
Também não são muito bons... Em geral, trabalhar com uma distribuição beta não centralizada pertence à classe de tarefas não triviais. Conseguimos ver o Boost no código-fonte aberto. E ele será mais complicado do que o que temos agora no SB.
Na mesma Wikipédia, há essa informação:
Ou seja, duas variáveis aleatórias são tomadas, onde a primeira é de uma distribuição qui-quadrado não central e a segunda é de uma distribuição central. Provavelmente o código pode ser corrigido para isso:
Os gráficos modificados no exemplo estarão abaixo.
Obrigado, você está certo, precisamos calcular por meio dessa fórmula, mas houve outro erro, o parâmetro de não centralidade lambda deveria estar sem o multiplicador 2.
Script de teste:
Resultado:
Também verifiquei a função CFD para a distribuição beta não central.
Alguns resultados questionáveis:
Fontes alternativas usam o algoritmo ASA310:
Por exemplo, alguns dos resultados no Wolfram Mathematica:
O que é mais ou menos parecido com a verdade...