//+------------------------------------------------------------------+ //| Normal.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "Math.mqh" const static double normal_cdf_a[5]= { 2.2352520354606839287E00,1.6102823106855587881E02, 1.0676894854603709582E03,1.8154981253343561249E04, 6.5682337918207449113E-2 }; const static double normal_cdf_b[4]= { 4.7202581904688241870E01,9.7609855173777669322E02, 1.0260932208618978205E04,4.5507789335026729956E04 }; //--- coefficients for approximation in second interval const static double normal_cdf_c[9]= { 3.9894151208813466764E-1,8.8831497943883759412E00, 9.3506656132177855979E01,5.9727027639480026226E02, 2.4945375852903726711E03,6.8481904505362823326E03, 1.1602651437647350124E04,9.8427148383839780218E03, 1.0765576773720192317E-8 }; const static double normal_cdf_d[8]= { 2.2266688044328115691E01,2.3538790178262499861E02, 1.5193775994075548050E03,6.4855582982667607550E03, 1.8615571640885098091E04,3.4900952721145977266E04, 3.8912003286093271411E04,1.9685429676859990727E04 }; //--- coefficients for approximation in third interval const static double normal_cdf_p[6]= { 2.1589853405795699E-1,1.274011611602473639E-1, 2.2235277870649807E-2,1.421619193227893466E-3, 2.9112874951168792E-5,2.307344176494017303E-2 }; const static double normal_cdf_q[5]= { 1.28426009614491121E00,4.68238212480865118E-1, 6.59881378689285515E-2,3.78239633202758244E-3, 7.29751555083966205E-5 }; //--- coefficients for p close to 0.5 const double normal_q_a0 = 3.3871328727963666080; const double normal_q_a1 = 1.3314166789178437745E+2; const double normal_q_a2 = 1.9715909503065514427E+3; const double normal_q_a3 = 1.3731693765509461125E+4; const double normal_q_a4 = 4.5921953931549871457E+4; const double normal_q_a5 = 6.7265770927008700853E+4; const double normal_q_a6 = 3.3430575583588128105E+4; const double normal_q_a7 = 2.5090809287301226727E+3; const double normal_q_b1 = 4.2313330701600911252E+1; const double normal_q_b2 = 6.8718700749205790830E+2; const double normal_q_b3 = 5.3941960214247511077E+3; const double normal_q_b4 = 2.1213794301586595867E+4; const double normal_q_b5 = 3.9307895800092710610E+4; const double normal_q_b6 = 2.8729085735721942674E+4; const double normal_q_b7 = 5.2264952788528545610E+3; //--- coefficients for p not close to 0, 0.5 or 1 const double normal_q_c0 = 1.42343711074968357734; const double normal_q_c1 = 4.63033784615654529590; const double normal_q_c2 = 5.76949722146069140550; const double normal_q_c3 = 3.64784832476320460504; const double normal_q_c4 = 1.27045825245236838258; const double normal_q_c5 = 2.41780725177450611770E-1; const double normal_q_c6 = 2.27238449892691845833E-2; const double normal_q_c7 = 7.74545014278341407640E-4; const double normal_q_d1 = 2.05319162663775882187; const double normal_q_d2 = 1.67638483018380384940; const double normal_q_d3 = 6.89767334985100004550E-1; const double normal_q_d4 = 1.48103976427480074590E-1; const double normal_q_d5 = 1.51986665636164571966E-2; const double normal_q_d6 = 5.47593808499534494600E-4; const double normal_q_d7 = 1.05075007164441684324E-9; //--- coefficients for p near 0 or 1. const double normal_q_e0 = 6.65790464350110377720E0; const double normal_q_e1 = 5.46378491116411436990E0; const double normal_q_e2 = 1.78482653991729133580E0; const double normal_q_e3 = 2.96560571828504891230E-1; const double normal_q_e4 = 2.65321895265761230930E-2; const double normal_q_e5 = 1.24266094738807843860E-3; const double normal_q_e6 = 2.71155556874348757815E-5; const double normal_q_e7 = 2.01033439929228813265E-7; const double normal_q_f1 = 5.99832206555887937690E-1; const double normal_q_f2 = 1.36929880922735805310E-1; const double normal_q_f3 = 1.48753612908506148525E-2; const double normal_q_f4 = 7.86869131145613259100E-4; const double normal_q_f5 = 1.84631831751005468180E-5; const double normal_q_f6 = 1.42151175831644588870E-7; const double normal_q_f7 = 2.04426310338993978564E-15; //+------------------------------------------------------------------+ //| Normal probability density function (PDF) | //+------------------------------------------------------------------+ //| The function returns the probability density function | //| of the Normal distribution with parameters mu and sigma. | //| | //| Arguments: | //| x : Random variable | //| mu : Mean | //| sigma : Standard deviation (sigma>0) | //| log_mode : Logarithm mode flag, if true it returns Log values | //| error_code : Variable for error code | //| | //| Return value: | //| The probability density evaluated at x. | //+------------------------------------------------------------------+ double MathProbabilityDensityNormal(const double x,const double mu,const double sigma,const bool log_mode,int &error_code) { //--- check NaN if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) { error_code=ERR_ARGUMENTS_NAN; return QNaN; } //--- check sigma if(sigma<=0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } error_code=ERR_OK; //--- prepare argument double y=(x-mu)/sigma; //--- check it if(!MathIsValidNumber(y)) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } //--- check overflow y=MathAbs(y); if(y>=2*MathSqrt(DBL_MAX)) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } //--- return density return TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/sigma,true,log_mode); } //+------------------------------------------------------------------+ //| Normal probability density function (PDF) | //+------------------------------------------------------------------+ //| The function returns the probability density function | //| of the Normal distribution with parameters mu and sigma. | //| | //| Arguments: | //| x : Random variable | //| mu : Mean | //| sigma : Standard deviation (sigma>0) | //| error_code : Variable for error code | //| | //| Return value: | //| The probability density evaluated at x. | //+------------------------------------------------------------------+ double MathProbabilityDensityNormal(const double x,const double mu,const double sigma,int &error_code) { return MathProbabilityDensityNormal(x,mu,sigma,false,error_code); } //+------------------------------------------------------------------+ //| Normal probability density function (PDF) | //+------------------------------------------------------------------+ //| The function calculates the probability density function of | //| the Normal distribution with parameters mu and sigma | //| for values in x. | //| | //| Arguments: | //| x : Array with random variables | //| mu : Mean | //| sigma : Standard deviation (sigma>0) | //| log_mode : Logarithm mode flag, if true it returns Log values | //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathProbabilityDensityNormal(const double &x[],const double mu,const double sigma,const bool log_mode,double &result[]) { //--- check NaN if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) return false; //--- check sigma if(sigma<=0) return false; int data_count=ArraySize(x); if(data_count==0) return false; int error_code=0; ArrayResize(result,data_count); for(int i=0; i=2*MathSqrt(DBL_MAX)) return false; //--- calculate density result[i]=TailLogValue(M_1_SQRT_2PI*MathExp(-0.5*y*y)/sigma,true,log_mode); } return true; } //+------------------------------------------------------------------+ //| Normal probability density function (PDF) | //+------------------------------------------------------------------+ //| The function calculates the probability density function of | //| the Normal distribution with parameters mu and sigma | //| for values in x[] array. | //| | //| Arguments: | //| x : Array with random variables | //| mu : Mean | //| sigma : Standard deviation (sigma>0) | //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathProbabilityDensityNormal(const double &x[],const double mu,const double sigma,double &result[]) { return MathProbabilityDensityNormal(x,mu,sigma,false,result); } //+------------------------------------------------------------------+ //| Normal cumulative distribution function (CDF) | //+------------------------------------------------------------------+ //| The function returns the probability that an observation | //| from the Normal distribution with parameters mu and sigma | //| is less than or equal to x. | //| | //| Arguments: | //| x : The desired quantile | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| tail : Flag to calculate lower tail | //| log_mode : Logarithm mode, if true it calculates Log values | //| error_code : Variable for error code | //| | //| Return value: | //| The value of the Normal cumulative distribution function with | //| parameters mu and sigma, evaluated at x. | //+------------------------------------------------------------------+ //| Comment from original FORTRAN code | //| https://www.netlib.org/toms-2014-06-10/639 | //| https://www.netlib.org/toms-2014-06-10/715 | //| | //| This function evaluates the normal distribution function: | //| | //| / x | //| 1 | -t*t/2 | //| P(x) = ----------- | e dt | //| sqrt(2 pi) | | //| /-oo | //| | //| The main computation evaluates near-minimax approximations | //| derived from those in "Rational Chebyshev approximations for | //| the error function" by W. J. Cody, Math. Comp., 1969, 631-637. | //| This transportable program uses rational functions that | //| theoretically approximate the normal distribution function to | //| at least 18 significant decimal digits. The accuracy achieved | //| depends on the arithmetic system, the compiler, the intrinsic | //| functions, and proper selection of the machine-dependent | //| constants. | //| | //| Author: | //| W. J. Cody, Mathematics and Computer Science Division | //| Argonne National Laboratory, Argonne, IL 60439 | //+------------------------------------------------------------------+ double MathCumulativeDistributionNormal(const double x,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code) { //--- check NaN if(!MathIsValidNumber(x) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) { error_code=ERR_ARGUMENTS_NAN; return QNaN; } //--- check sigma if(sigma<=0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } error_code=ERR_OK; //--- prepare argument double xx=(x-mu)/sigma; //--- mathematical constants //--- sqrpi = 1 / sqrt(2*pi), root32 = sqrt(32), and //--- thrsh is the argument for which anorm = 0.75. const double sqrpi=1.0/MathSqrt(2*M_PI); const double thrsh = 0.66291e0; const double root32= MathSqrt(32); //--- machine-dependent constants //--- data eps/5.96e-8/,xlow/-12.949e0/,xuppr/5.768e0/ const double eps=1.11e-16; const double xlow=-37.519; const double xuppr=8.572; int k; //--- double xsq=0.0; double y=MathAbs(xx); double xnum=0.0; double xden=0.0; double cdf=0.0; double del=0.0; //--- if(y<=thrsh) { //--- evaluate for |x| <= 0.66291 if(y>eps) xsq=xx*xx; xnum = normal_cdf_a[4] * xsq; xden = xsq; for(k=0; k<3; k++) { xnum=(xnum+normal_cdf_a[k])*xsq; xden=(xden+normal_cdf_b[k])*xsq; } cdf = xx*(xnum+normal_cdf_a[3])/(xden+normal_cdf_b[3]); cdf = 0.5 + cdf; } else if(y<=root32) { //--- evaluate for 0.66291 <= |x| <= sqrt(32) xnum = normal_cdf_c[8]*y; xden = y; for(k=0; k<7; k++) { xnum=(xnum+normal_cdf_c[k])*y; xden=(xden+normal_cdf_d[k])*y; } cdf=(xnum+normal_cdf_c[7])/(xden+normal_cdf_d[7]); xsq=int(y*16)/16; del=(y-xsq)*(y+xsq); cdf=MathExp(-xsq*xsq*0.5)*MathExp(-del*0.5)*cdf; if(xx>0.0) cdf=1.0-cdf; } //--- evaluate for |x| > sqrt(32) else { cdf=0.0; if((xx>=xlow) && (xx0.0) cdf=1.0-cdf; } //--- take into account round-off errors for probability return TailLogValue(MathMin(cdf,1.0),tail,log_mode); } //+------------------------------------------------------------------+ //| Normal cumulative distribution function (CDF) | //+------------------------------------------------------------------+ //| The function returns the probability that an observation | //| from the Normal distribution with parameters mu and sigma | //| is less than or equal to x. | //| | //| Arguments: | //| x : The desired quantile | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| error_code : Variable for error code | //| | //| Return value: | //| The value of the Normal cumulative distribution function with | //| parameters mu and sigma, evaluated at x. | //+------------------------------------------------------------------+ double MathCumulativeDistributionNormal(const double x,const double mu,const double sigma,int &error_code) { return MathCumulativeDistributionNormal(x,mu,sigma,true,false,error_code); } //+------------------------------------------------------------------+ //| Normal cumulative distribution function (CDF) | //+------------------------------------------------------------------+ //| The function calculates the cumulative distribution function of | //| the Normal distribution with parameters mu and sigma | //| for values in x[] array. | //| | //| Arguments: | //| x : Array with random variables | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| tail : Flag to calculate lower tail | //| log_mode : Logarithm mode, if true it calculates Log values | //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathCumulativeDistributionNormal(const double &x[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[]) { //--- check NaN if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) return false; //--- check sigma if(sigma<=0) return false; int data_count=ArraySize(x); if(data_count==0) return false; int error_code=0; ArrayResize(result,data_count); for(int i=0; ieps) xsq=xx*xx; xnum = normal_cdf_a[4] * xsq; xden = xsq; for(k=0; k<3; k++) { xnum=(xnum+normal_cdf_a[k])*xsq; xden=(xden+normal_cdf_b[k])*xsq; } cdf = xx*(xnum+normal_cdf_a[3])/(xden+normal_cdf_b[3]); cdf = 0.5 + cdf; } else if(y<=root32) { //--- evaluate for 0.66291 <= |x| <= sqrt(32) xnum = normal_cdf_c[8]*y; xden = y; for(k=0; k<7; k++) { xnum=(xnum+normal_cdf_c[k])*y; xden=(xden+normal_cdf_d[k])*y; } cdf=(xnum+normal_cdf_c[7])/(xden+normal_cdf_d[7]); xsq=int(y*16)/16; del=(y-xsq)*(y+xsq); cdf=MathExp(-xsq*xsq*0.5)*MathExp(-del*0.5)*cdf; if(xx>0.0) cdf=1.0-cdf; } //--- evaluate for |x| > sqrt(32) else { cdf=0.0; if((xx>=xlow) && (xx0.0) cdf=1.0-cdf; } //--- take into account round-off errors for probability result[i]=TailLogValue(MathMin(cdf,1.0),tail,log_mode); } return true; } //+------------------------------------------------------------------+ //| Normal cumulative distribution function (CDF) | //+------------------------------------------------------------------+ //| The function calculates the cumulative distribution function of | //| the Normal distribution with parameters mu and sigma | //| for values in x[] array. | //| | //| Arguments: | //| x : Array with random variables | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathCumulativeDistributionNormal(const double &x[],const double mu,const double sigma,double &result[]) { return MathCumulativeDistributionNormal(x,mu,sigma,true,false,result); } //+------------------------------------------------------------------+ //| Normal distribution quantile function (inverse CDF) | //+------------------------------------------------------------------+ //| The function returns the inverse cumulative distribution | //| function of the Normal distribution with parameters mu and sigma | //| for the desired probability. | //| | //| Arguments: | //| probability : The desired probability | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| tail : Flag to calculate lower tail | //| log_mode : Logarithm mode,if true it calculates for Log values| //| error_code : Variable for error code | //| | //| Return value: | //| The value of the inverse cumulative distribution function | //| of the Normal distribution with parameters mu and sigma. | //+------------------------------------------------------------------+ //| Comment from original FORTRAN code | //| https://www1.fpl.fs.fed.us/ni241.f | //| Produces the normal deviate Z corresponding to a given lower | //| tail area of P; Z is accurate to about 1 part in 10**16. | //| Wichura, M.J. (1988). Algorithm AS 241: The Percentage Points of | //| the Normal Distribution. Applied Statistics, v.37, N3, 477-484. | //+------------------------------------------------------------------+ double MathQuantileNormal(const double probability,const double mu,const double sigma,const bool tail,const bool log_mode,int &error_code) { //--- check NaN if(!MathIsValidNumber(probability) || !MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) { error_code=ERR_ARGUMENTS_NAN; return QNaN; } //--- check sigma if(sigma<=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; } //--- f(0)=-infinity if(prob==0.0) { error_code=ERR_RESULT_INFINITE; return QNEGINF; } //--- f(1)=+infinity if(prob==1.0) { error_code=ERR_RESULT_INFINITE; return QPOSINF; } error_code=ERR_OK; double q=prob-0.5; double r=0; double ppnd16=0.0; //--- if(MathAbs(q)<=0.425) { r=0.180625-q*q; ppnd16=q*(((((((normal_q_a7*r+normal_q_a6)*r+normal_q_a5)*r+normal_q_a4)*r+normal_q_a3)*r+normal_q_a2)*r+normal_q_a1)*r+normal_q_a0)/ (((((((normal_q_b7*r+normal_q_b6)*r+normal_q_b5)*r+normal_q_b4)*r+normal_q_b3)*r+normal_q_b2)*r+normal_q_b1)*r+1.0); //--- error_code=ERR_OK; return mu+sigma*ppnd16; } else { if(q<0.0) r=prob; else r=1.0-prob; //--- r=MathSqrt(-MathLog(r)); //--- if(r<=5.0) { r=r-1.6; ppnd16=(((((((normal_q_c7*r+normal_q_c6)*r+normal_q_c5)*r+normal_q_c4)*r+normal_q_c3)*r+normal_q_c2)*r+normal_q_c1)*r+normal_q_c0)/ (((((((normal_q_d7*r+normal_q_d6)*r+normal_q_d5)*r+normal_q_d4)*r+normal_q_d3)*r+normal_q_d2)*r+normal_q_d1)*r+1.0); } else { r=r-5.0; ppnd16=(((((((normal_q_e7*r+normal_q_e6)*r+normal_q_e5)*r+normal_q_e4)*r+normal_q_e3)*r+normal_q_e2)*r+normal_q_e1)*r+normal_q_e0)/ (((((((normal_q_f7*r+normal_q_f6)*r+normal_q_f5)*r+normal_q_f4)*r+normal_q_f3)*r+normal_q_f2)*r+normal_q_f1)*r+1.0); } //--- if(q<0.0) ppnd16=-ppnd16; } //--- return rescaled/shifted value return mu+sigma*ppnd16; } //+------------------------------------------------------------------+ //| Normal distribution quantile function (inverse CDF) | //+------------------------------------------------------------------+ //| The function returns the inverse cumulative distribution | //| function of Normal distribution with parameters mu and sigma | //| for the desired probability. | //| | //| Arguments: | //| probability : The desired probability | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| error_code : Variable for error code | //| | //| Return value: | //| The value of the inverse cumulative distribution function | //| of the Normal distribution with parameters mu and sigma. | //+------------------------------------------------------------------+ double MathQuantileNormal(const double probability,const double mu,const double sigma,int &error_code) { return MathQuantileNormal(probability,mu,sigma,true,false,error_code); } //+------------------------------------------------------------------+ //| Normal distribution quantile function (inverse CDF) | //+------------------------------------------------------------------+ //| The function calculates the inverse cumulative distribution | //| function of the Normal distribution with parameters mu and sigma | //| for the probability values from array. | //| | //| Arguments: | //| probability : Array with probabilities | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| tail : Flag to calculate lower tail | //| log_mode : Logarithm mode, if true it calculates Log values | //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathQuantileNormal(const double &probability[],const double mu,const double sigma,const bool tail,const bool log_mode,double &result[]) { //--- check NaN if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) return false; //--- check sigma if(sigma<0) return false; int data_count=ArraySize(probability); if(data_count==0) return false; int error_code=0; ArrayResize(result,data_count); //--- case sigma==0 if(sigma==0.0) { for(int i=0; i1.0) return false; //--- f(0)=-infinity, f(1)=+infinity if(prob==0.0 || prob==1.0) { if(prob==0.0) result[i]=QNEGINF; else result[i]=QPOSINF; } else { double q=prob-0.5; double r=0; double ppnd16=0.0; //--- if(MathAbs(q)<=0.425) { r=0.180625-q*q; ppnd16=q*(((((((normal_q_a7*r+normal_q_a6)*r+normal_q_a5)*r+normal_q_a4)*r+normal_q_a3)*r+normal_q_a2)*r+normal_q_a1)*r+normal_q_a0)/ (((((((normal_q_b7*r+normal_q_b6)*r+normal_q_b5)*r+normal_q_b4)*r+normal_q_b3)*r+normal_q_b2)*r+normal_q_b1)*r+1.0); //--- set rescaled/shifted value result[i]=mu+sigma*ppnd16; } else { if(q<0.0) r=prob; else r=1.0-prob; //--- r=MathSqrt(-MathLog(r)); //--- if(r<=5.0) { r=r-1.6; ppnd16=(((((((normal_q_c7*r+normal_q_c6)*r+normal_q_c5)*r+normal_q_c4)*r+normal_q_c3)*r+normal_q_c2)*r+normal_q_c1)*r+normal_q_c0)/ (((((((normal_q_d7*r+normal_q_d6)*r+normal_q_d5)*r+normal_q_d4)*r+normal_q_d3)*r+normal_q_d2)*r+normal_q_d1)*r+1.0); } else { r=r-5.0; ppnd16=(((((((normal_q_e7*r+normal_q_e6)*r+normal_q_e5)*r+normal_q_e4)*r+normal_q_e3)*r+normal_q_e2)*r+normal_q_e1)*r+normal_q_e0)/ (((((((normal_q_f7*r+normal_q_f6)*r+normal_q_f5)*r+normal_q_f4)*r+normal_q_f3)*r+normal_q_f2)*r+normal_q_f1)*r+1.0); } //--- if(q<0.0) ppnd16=-ppnd16; } //--- set rescaled/shifted value result[i]=mu+sigma*ppnd16; } } return true; } //+------------------------------------------------------------------+ //| Normal distribution quantile function (inverse CDF) | //+------------------------------------------------------------------+ //| The function calculates the inverse cumulative distribution | //| function of the Normal distribution with parameters mu and sigma | //| for the probability values from array. | //| | //| Arguments: | //| probability : Array with probabilities | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| result : Array with calculated values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathQuantileNormal(const double &probability[],const double mu,const double sigma,double &result[]) { return MathQuantileNormal(probability,mu,sigma,true,false,result); } //+------------------------------------------------------------------+ //| Random variate from the Normal distribution | //+------------------------------------------------------------------+ //| Compute the random variable from the Normal distribution | //| with given mean mu and standard deviation sigma. | //| | //| Arguments: | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| error_code : Variable for error code | //| | //| Return value: | //| The random value with Normal distribution. | //+------------------------------------------------------------------+ double MathRandomNormal(const double mu,const double sigma,int &error_code) { //--- check NaN if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) { error_code=ERR_ARGUMENTS_NAN; return QNaN; } //--- check sigma if(sigma<0) { error_code=ERR_ARGUMENTS_INVALID; return QNaN; } error_code=ERR_OK; //--- if(sigma==0.0) return mu; //--- generate random number double rnd=MathRandomNonZero(); //--- return normal random using quantile return MathQuantileNormal(rnd,mu,sigma,true,false,error_code); } //+------------------------------------------------------------------+ //| Random variate from the Normal distribution | //+------------------------------------------------------------------+ //| Generates random variables from the Normal distribution with | //| parameters mu and sigma. | //| | //| Arguments: | //| mu : Mean | //| sigma : Standard deviation (must be positive) | //| data_count : Number of values needed | //| result : Output array with random values | //| | //| Return value: | //| true if successful, otherwise false. | //+------------------------------------------------------------------+ bool MathRandomNormal(const double mu,const double sigma,const int data_count,double &result[]) { //--- check NaN if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) return false; //--- check sigma if(sigma<0) return false; //--- prepare output array and calculate random values ArrayResize(result,data_count); if(sigma==0.0) { for(int i=0; i0) | //| mean : Variable for mean value (1st moment) | //| variance : Variable for variance value (2nd moment) | //| skewness : Variable for skewness value (3rd moment) | //| kurtosis : Variable for kurtosis value (4th moment) | //| error_code : Variable for error code | //| | //| Return value: | //| true if moments calculated successfully, otherwise false. | //+------------------------------------------------------------------+ bool MathMomentsNormal(const double mu,const double sigma,double &mean,double &variance,double &skewness,double &kurtosis,int &error_code) { //--- default values mean =QNaN; variance=QNaN; skewness=QNaN; kurtosis=QNaN; //--- check NaN if(!MathIsValidNumber(mu) || !MathIsValidNumber(sigma)) { error_code=ERR_ARGUMENTS_NAN; return false; } //--- check sigma if(sigma<=0) { error_code=ERR_ARGUMENTS_INVALID; return false; } error_code=ERR_OK; //--- calculate moments mean =mu; variance=MathPow(sigma,2); skewness=0; kurtosis=0; //--- successful return true; } //+------------------------------------------------------------------+