{ Function: _StdDevMean (Standard Deviation ) Purpose: Calculate the mean and standard deviation in single function using an alternative algorithm to calculation standard deviation described in Wikipedia. Discussion: The TS standard deviation functions do not ouput the mean used in calculating the standard deviation. Therefore, in many custom routines that use both mean and standard deviation, such as Bollinger Bands and Z-Score, there is duplication of the mean calculation. This routine returns both the mean and the standard deviation in a single function and therefore avoids the necessity of performing a repeat calculation of the mean. Source: Casey (TS forums) found this method, described in Wikipedia. Goose improved the code and created a single version that would permit Length to vary. Author: MarkSanDiego Updated: 08/28/08 original version 02/19/09 alternative method of calculating standard deviation implemented 02/21/09 documentation improved 09/13/09 code cleaned 04/06/10 made Divisor intrabarpersist, since may be initialized during BarStatus(1) <> 2 Usage: Put the following in the calling routine: _______________________________________________________________________________________________________________ inputs: Price(Close), Length(100), // length used to measure average and standard deviation DataType(1), // = 1 for Variance and standard deviation of entire population; // = 2 for Variance and standard deviation of sample of population vars: oMean(0), // average price; oAvg = Average(Price, Length) oStdDev(0); // standard deviation of price; oSD = StandardDev(Price, Length) Usage: value1 = _StdDevMeanFC(Price, Length, DataType, oMean, oStdDev); _______________________________________________________________________________________________________________ } inputs: Price(NumericSeries), Length(NumericSimple), { length used to measure average and standard deviation (MUST BE >= 2 but MAY VARY) } { Numeric or NumericSeries required if Length is allowed to vary } DataType(NumericSimple), { = 1 for Variance and standard deviation of entire population; } { = 2 for Variance and standard deviation of sample of population } { outputs: } oMean(NumericRef), { average price; oMean = Average(Price, Length) } oStdDev(NumericRef); { standard deviation of price series; oSD = StandardDev(Price), Length) } variables: j(0), x(0), LastLength(0), { Length used in prior function call. Allows avoiding using Length[1], which is slower. } rLen(0), { inverse of Length. Multiplication executes slightly faster than division } intrabarpersist Divisor(0), { divisor used for variance of entire/sample population } { must be intrabarpersist since initialization may occur when BarStatus(1) <> 2 } Sum(0), { sum used to calculate Mean } SumSq(0), { sum of squares of (Price - oMean) } MeanSq(0); { INLINE CODE STARTS HERE: Function _StdDevMean } { uncomment this section when extrcting this function for in-line code } { inputs: Price(Close), Length(20), { length used to measure average and standard deviation } DataType(1); { = 1 for Variance and standard deviation of entire population; } { = 2 for Variance and standard deviation of sample of population } vars: Divisor(0), rDiv(0), Sum(0), SumSq(0), rLen(0), MeanSq(0), oMean(0), { average price; oAvg = Average(Price, Length) } oStdDev(0); { standard deviation of price; oSD = StandardDev(Price, Length) } } once begin { adjust Divisor according to DataType and validate } switch DataType begin case 1: { StdDev of entire population requires Length >= 1 } Divisor = Length; case 2: if Length < 2 then RaiseRunTimeError("_StdDevMean: StdDev of sample of population requires Length >= 2"); Divisor = Length - 1; default: RaiseRunTimeError("_StdDevMean: DataType must be 1 (Population) or 2 (Sample)"); end; end; If Length > 0 then begin if Length <> LastLength then begin rLen = 1 / Divisor; Sum = 0; SumSq = 0; for j = 0 to Length - 1 begin x = Price[j]; Sum = Sum + x ; SumSq = SumSq + x * x; end; LastLength = Length; end else begin x = Price[Length]; Sum = Sum + Price - x ; SumSq = SumSq + Price * Price - x * x; end; oMean = Sum * rLen; MeanSq = SumSq * rLen; x = MeanSq - oMean * oMean; if x > 0 then oStdDev = SquareRoot( x ) else oStdDev = 0; { INLINE CODE STOPS HERE } _StdDevMean = oStdDev; { Length < 1 results in no calculation being done. This avoids testing for Length > 1 before calling function } end else begin oMean = 0; oStdDev = 0; _StdDevMean = 0; end;