//+------------------------------------------------------------------+ //| Poisson.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "Math.mqh" #include "Gamma.mqh" //+------------------------------------------------------------------+ //| Poisson probability mass function (PDF) | //+------------------------------------------------------------------+ //| The function returns the probability mass function | //| of the Poisson distribution with parameter lambda. | //| | //| Arguments: | //| x : Random variable | //| lambda : Mean | //| log_mode : Logarithm mode flag, if true it returns Log values | //| error_code : Variable for error code | //| | //| Return value: | //| The probability mass evaluated at x. | //+------------------------------------------------------------------+ double MathProbabilityDensityPoisson(const double x,const double lambda,const bool log_mode,int &error_code) { //--- check NaN if(!MathIsValidNumber(x) || !MathIsValidNumber(lambda)) { error_code=ERR_ARGUMENTS_NAN; return QNaN; } //--- lambda must be positive, x must be integer if(lambda<=0.0 || x!=MathRound(x)) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } error_code=ERR_OK; //--- check x if(x<0.0) return TailLog0(true,log_mode); //--- calculate log pdf using LogGamma double log_pdf=-lambda+x*MathLog(lambda)-MathGammaLog(x+1.0); if(log_mode) return log_pdf; //--- return density return MathExp(log_pdf); } //+------------------------------------------------------------------+ //| Poisson probability mass function (PDF) | //+------------------------------------------------------------------+ //| The function returns the probability mass function | //| of the Poisson distribution with parameter lambda. | //| | //| Arguments: | //| x : Random variable | //| lambda : Mean | //| error_code : Variable for error code | //| | //| Return value: | //| The probability mass evaluated at x. | //+------------------------------------------------------------------+ double MathProbabilityDensityPoisson(const double x,const double lambda,int &error_code) { return MathProbabilityDensityPoisson(x,lambda,false,error_code); } //+------------------------------------------------------------------+ //| Poisson probability mass function (PDF) | //+------------------------------------------------------------------+ //| The function calculates the probability density function of | //| the Poisson distribution with parameter lambda for values in x[].| //| | //| Arguments: | //| x : Array with random variables | //| lambda : Mean | //| log_mode : Logarithm mode flag, if true it returns Log values | //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathProbabilityDensityPoisson(const double &x[],const double lambda,const bool log_mode,double &result[]) { //--- check NaN if(!MathIsValidNumber(lambda)) return false; //--- lambda must be positive if(lambda<=0.0) return false; int data_count=ArraySize(x); if(data_count==0) return false; ArrayResize(result,data_count); for(int i=0; i1.0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } //--- check if(prob==1.0) { error_code=ERR_RESULT_INFINITE; return QPOSINF; } error_code=ERR_OK; if(prob==0.0) return 0.0; prob*=1-1000*DBL_EPSILON; int err_code=0; int j=0; const int max_terms=500; double coef_lambda=MathExp(-lambda); double pwr_lambda=1.0; double inverse_fact=1.0; double sum=0; //--- direct calculation of the quantile while(sum0) { pwr_lambda*=lambda; inverse_fact/=j; } sum+=coef_lambda*pwr_lambda*inverse_fact; j++; } //--- check convergence if(j1.0) return false; else if(prob==1.0) result[i]=QPOSINF; if(prob==0.0) result[i]=0; else { prob*=1-1000*DBL_EPSILON; int err_code=0; int j=0; double sum=0.0; const int max_terms=500; double pwr_lambda=1.0; double inverse_fact=1.0; //--- direct calculation while(sum0) { pwr_lambda*=lambda; inverse_fact/=j; } sum+=coef_lambda*pwr_lambda*inverse_fact; j++; } //--- check convergence if(j=1.0 || r2==0.0); //--- Box-Muller transform f=MathSqrt(-2.0*MathLog(r2)/r2); double snorm=f*x2; //--- normal sample g=lambda+s*snorm; if(0.0<=g) { value=(int)(g); //--- immediate acceptance if large enough if(l<=value) return value; //--- squeeze acceptance fk=(double)(value); difmuk=lambda-fk; u=MathRandomNonZero(); //--- if(difmuk*difmuk*difmuk<=d*u) return value; } //--- preparation for steps P and Q double omega=0.3989423/s; double b1 = 0.04166667/lambda; double b2 = 0.3*b1*b1; double c3 = 0.1428571*b1*b2; double c2 = b2 - 15.0*c3; double c1 = b1 - 6.0*b2 + 45.0*c3; double c0 = 1.0 - b1 + 3.0*b2 - 15.0*c3; double c=0.1069/lambda; double del=0; if(0.0<=g) { kflag=0; if(value<10) { px = -lambda; py = MathPow(lambda,value)/MathFactorial(value); } else { del = 0.8333333E-01/fk; del = del - 4.8*del*del*del; v=difmuk/fk; if(0.25