//+------------------------------------------------------------------+ //| Binomial.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "Math.mqh" #include "Beta.mqh" //+------------------------------------------------------------------+ //| Binomial probability mass function (PDF) | //+------------------------------------------------------------------+ //| The function returns the Binomial probability mass function | //| with parameters n and p at x. | //| | //| f(x,n,p)= C(n,x)*(p^x)*(1-p)^(n-x) | //| | //| where binomial coefficient C(n,k)=n!/(k!*(n-k)!) | //| | //| Arguments: | //| x : Integer random variable | //| n : Number of trials | //| p : Probability of success for each trial | //| log_mode : Logarithm mode flag, if true it returns Log values | //| error_code : Variable for error code | //| | //| Return value: | //| The probability mass function evaluated at x. | //+------------------------------------------------------------------+ double MathProbabilityDensityBinomial(const double x,const double n,const double p,const bool log_mode,int &error_code) { //--- check NaN if(!MathIsValidNumber(x) || !MathIsValidNumber(n) || !MathIsValidNumber(p)) { error_code=ERR_ARGUMENTS_NAN; return QNaN; } //--- check n if(n<0 || n!=MathRound(n)) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } //--- check p range if(p<0.0 || p>1.0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } error_code=ERR_OK; //--- case p=0 if(p==0.0 || p==1.0) return TailLog0(true,log_mode); //--- check x range if(x<0 || x>n) return TailLog0(true,log_mode); double log_result=MathGammaLog(n+1.0)-MathGammaLog(x+1.0)-MathGammaLog(n-x+1.0)+x*MathLog(p)+(n-x)*MathLog(1.0-p); if(log_mode==true) return log_result; //--- return probability mass return MathExp(log_result); } //+------------------------------------------------------------------+ //| Binomial probability mass function (PDF) | //+------------------------------------------------------------------+ //| The function returns the Binomial probability mass function | //| with parameters n and p at x. | //| | //| f(x,n,p)= C(n,x)*(p^x)*(1-p)^(n-x) | //| | //| where binomial coefficient C(n,k)=n!/(k!*(n-k)!) | //| | //| Arguments: | //| x : Integer random variable | //| n : Number of trials | //| p : Probability of success for each trial | //| error_code : Variable for error code | //| | //| Return value: | //| The probability mass function evaluated at x. | //+------------------------------------------------------------------+ double MathProbabilityDensityBinomial(const double x,const double n,const double p,int &error_code) { return MathProbabilityDensityBinomial(x,n,p,false,error_code); } //+------------------------------------------------------------------+ //| Binomial probability mass function (PDF) | //+------------------------------------------------------------------+ //| The function calculates the Binomial probability mass function | //| with parameters n and p for values in x[] array. | //| | //| Arguments: | //| x : Array with integer random variables | //| n : Number of trials | //| p : Probability of success for each trial | //| log_mode : Logarithm mode flag,if true it calculates Log values| //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathProbabilityDensityBinomial(const double &x[],const double n,const double p,const bool log_mode,double &result[]) { //--- check NaN if(!MathIsValidNumber(n) || !MathIsValidNumber(p)) return false; //--- check n if(n<0 || n!=MathRound(n)) return false; //--- check p range if(p<0.0 || p>1.0) return false; int data_count=ArraySize(x); if(data_count==0) return false; int error_code=0; ArrayResize(result,data_count); //--- case p=0 or p=1 if(p==0.0 || p==1.0) { for(int i=0; in) result[i]=TailLog0(true,log_mode); else { double log_result=MathGammaLog(n+1.0)-MathGammaLog(x_arg+1.0)-MathGammaLog(n-x_arg+1.0)+x_arg*MathLog(p)+(n-x_arg)*MathLog(1.0-p); if(log_mode==true) result[i]=log_result; else result[i]=MathExp(log_result); } } else return false; } return true; } //+------------------------------------------------------------------+ //| Binomial probability mass function (PDF) | //+------------------------------------------------------------------+ //| The function calculates the Binomial probability mass function | //| with parameters n and p for values in x[] array. | //| | //| Arguments: | //| x : Array with integer random variables | //| n : Number of trials | //| p : Probability of success for each trial | //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathProbabilityDensityBinomial(const double &x[],const double n,const double p,double &result[]) { return MathProbabilityDensityBinomial(x,n,p,false,result); } //+------------------------------------------------------------------+ //| Binomial cumulative distribution function (CDF) | //+------------------------------------------------------------------+ //| The function returns the value of the Binomial cumulative | //| distribution function with given n and p at the desired x. | //| | //| Arguments: | //| x : Integer random variable | //| n : Number of trials | //| p : Probability of success for each trial | //| tail : Flag to calculate lower tail | //| log_mode : Logarithm mode flag,if true it calculates Log values| //| error_code : Variable for error code | //| | //| Return value: | //| The cumulative distribution function evaluated at x. | //+------------------------------------------------------------------+ double MathCumulativeDistributionBinomial(const double x,const double n,double p,const bool tail,const bool log_mode,int &error_code) { //--- check NaN if(!MathIsValidNumber(x) || !MathIsValidNumber(n) || !MathIsValidNumber(p)) { error_code=ERR_ARGUMENTS_NAN; return QNaN; } //--- check n if(n<0 || n!=MathRound(n)) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } //--- check probability if(p<0.0 || p>1.0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } error_code=ERR_OK; //--- case p==0 if(p==0.0) { if(x>=0) return TailLog1(tail,log_mode); else return TailLog0(tail,log_mode); } //--- case p==1 if(p==1.0) { if(x>n) return TailLog1(tail,log_mode); else return TailLog0(tail,log_mode); } //--- x must be>=0 if(x<0) return TailLog0(tail,log_mode); //--- check x if(x>n) return TailLog1(tail,log_mode); int err_code=0; //--- calculate using Beta distribution and correct round-off errors double result=MathMin(1.0-MathCumulativeDistributionBeta(p,x+1.0,n-x,err_code),1.0); //--- return result depending on arguments return TailLogValue(result,tail,log_mode); } //+------------------------------------------------------------------+ //| Binomial cumulative distribution function (CDF) | //+------------------------------------------------------------------+ //| The function returns the value of the Binomial cumulative | //| distribution function with given n and p at the desired x. | //| | //| Arguments: | //| x : Integer random variable | //| n : Number of trials | //| p : Probability of success for each trial | //| error_code : Variable for error code | //| | //| Return value: | //| The cumulative distribution function evaluated at x. | //+------------------------------------------------------------------+ double MathCumulativeDistributionBinomial(const double x,const double n,double p,int &error_code) { return MathCumulativeDistributionBinomial(x,n,p,true,false,error_code); } //+------------------------------------------------------------------+ //| Binomial cumulative distribution function (CDF) | //+------------------------------------------------------------------+ //| The function returns the value of the Binomial cumulative | //| distribution function with given n and p at the desired x. | //| | //| Arguments: | //| x : Array with integer random variables | //| n : Number of trials | //| p : Probability of success for each trial | //| tail : Flag to calculate lower tail | //| log_mode : Logarithm mode flag,if true it calculates Log values| //| error_code : Variable for error code | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathCumulativeDistributionBinomial(const double &x[],const double n,double p,const bool tail,const bool log_mode,double &result[]) { //--- check NaN if(!MathIsValidNumber(n) || !MathIsValidNumber(p)) return false; //--- check n if(n<0 || n!=MathRound(n)) return false; //--- check probability if(p<0.0 || p>1.0) return false; int data_count=ArraySize(x); if(data_count==0) return false; int error_code=0; ArrayResize(result,data_count); //--- case p=0 and p==1 if(p==0.0 || p==1.0) { if(p==0.0) { for(int i=0; i=0) result[i]=TailLog1(tail,log_mode); else result[i]=TailLog0(tail,log_mode); } } else //--- p==1.0 { for(int i=0; in) result[i]=TailLog1(tail,log_mode); else result[i]=TailLog0(tail,log_mode); } } return true; } int err_code=0; for(int i=0; in) result[i]=TailLog1(tail,log_mode); else { double value=MathMin(1.0-MathCumulativeDistributionBeta(p,x_arg+1.0,n-x_arg,err_code),1.0); //--- calculate result depending on arguments result[i]=TailLogValue(value,tail,log_mode); } } else return false; } return true; } //+------------------------------------------------------------------+ //| Binomial cumulative distribution function (CDF) | //+------------------------------------------------------------------+ //| The function returns the value of the Binomial cumulative | //| distribution function with given n and p for values | //| from x[] array. | //| | //| Arguments: | //| x : Array with integer random variables | //| n : Number of trials | //| p : Probability of success for each trial | //| error_code : Variable for error code | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathCumulativeDistributionBinomial(const double &x[],const double n,double p,double &result[]) { return MathCumulativeDistributionBinomial(x,n,p,true,false,result); } //+------------------------------------------------------------------+ //| Binomial distribution quantile function (inverse CDF) | //+------------------------------------------------------------------+ //| The function returns the value of the inverse Binomial cumulative| //| distribution function with parameters n and p for the desired | //| probability. | //| | //| Arguments: | //| probability : The desired probability | //| n : Number of trials | //| p : Probability of success for each trial | //| tail : Lower tail flag (lower tail of probability used) | //| log_mode : Logarithm mode flag (log probability used) | //| error_code : Variable for error code | //| | //| Return value: | //| The value of the inverse cumulative distribution function | //| of the Binomial distribution with parameters n and p. | //+------------------------------------------------------------------+ double MathQuantileBinomial(const double probability,const double n,const double p,const bool tail,const bool log_mode,int &error_code) { //--- check NaN if(!MathIsValidNumber(probability) || !MathIsValidNumber(n) || !MathIsValidNumber(p)) { error_code=ERR_ARGUMENTS_NAN; return QNaN; } //--- check n if(n<0 || n!=MathRound(n)) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } //--- check p range if(p<0.0 || p>1.0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } //--- calculate real probability double prob=TailLogProbability(probability,tail,log_mode); //--- check probability range if(prob<0.0 || prob>1.0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } error_code=ERR_OK; int iterations=0; const int max_iterations=1000; //--- direct cdf calculation double sum=MathProbabilityDensityBinomial(0,n,p,false,error_code); while(sum1.0) return false; int data_count=ArraySize(probability); if(data_count==0) return false; int error_code=0; ArrayResize(result,data_count); const int max_iterations=1000; for(int i=0; i1.0) return false; int iterations=0; //--- direct cdf calculation double sum=MathProbabilityDensityBinomial(0,n,p,false,error_code); while(sum=1.0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } error_code=ERR_OK; //--- return binomial random value return MathRandomBinomial(n,p); } //+------------------------------------------------------------------+ //| Random variate from Binomial distribution | //+------------------------------------------------------------------+ //| The function generates random variables from Binomial | //| distribution with parameters n and p. | //| | //| Arguments: | //| n : Number of trials | //| p : Probability of success for each trial | //| data_count : Number of values needed | //| result : Output array with random values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathRandomBinomial(const double n,const double p,const int data_count,double &result[]) { if(data_count<=0) return false; //--- check NaN if(!MathIsValidNumber(n) || !MathIsValidNumber(p)) return false; //--- check n if(n<=0 || n!=MathRound(n)) return false; //--- check probability if(p<=0 || p>=1.0) return false; //--- prepare output array and calculate random values ArrayResize(result,data_count); for(int i=0; i=1.0) { error_code=ERR_ARGUMENTS_INVALID; return false; } error_code=ERR_OK; //--- prepare factors double np=n*p; double one_mp=(1.0-p); //--- calculate moments mean =np; variance=np*one_mp; skewness=(1-2*p)/MathSqrt(variance); kurtosis=(1-6*p*one_mp)/variance; //--- successful return true; } //+------------------------------------------------------------------+