anchor.diff:        if w.nobs < 3.0 then nan else
           let adjust = (sqrt (w.nobs * (w.nobs - 1.0))) / (w.nobs - 2.0)
           adjust * (sqrt w.nobs) * w.M3 / (w.M2 ** 1.5) 
  -    applyExpandingStatsTransform toEstSkew series
  +    applyExpandingMomentsTransform toEstSkew series
   
     let expandingKurt (series:Series<'K, float>) : Series<'K, float> =
       // population -> sample estimate
  
positive.code:   // expanding window functions
  
    let expandingCount (series:Series<'K, float>) : Series<'K, float> =
      applyExpandingStatsTransform (fun w -> w.nobs) series
  
    let expandingSum (series:Series<'K, float>) : Series<'K, float> =
      applyExpandingStatsTransform (fun w -> w.sum) series
  
    let expandingMean (series:Series<'K, float>) : Series<'K, float> =
      applyExpandingStatsTransform (fun w -> w.M1) series
  
    let expandingVariance (series:Series<'K, float>) : Series<'K, float> =
      let toVar w = w.M2 / (w.nobs - 1.0)
      applyExpandingStatsTransform toVar series
  
    let expandingStdDev (series:Series<'K, float>) : Series<'K, float> =
      let toStdDev w = w.M2 / (w.nobs - 1.0) |> sqrt
      applyExpandingStatsTransform toStdDev series
  
    let expandingSkew (series:Series<'K, float>) : Series<'K, float> =
      // population -> sample estimate    
  
negative.code:         // invariant: all values in deque are strictly ascending (min) or descending (max)
          i := !i + 1        
          match v with
          | OptionalValue.Present x -> 
            // remove from front any values that fell out of moving window
            while q.Count > 0 && !i >= fst q.[0] do q.RemoveFront() |> ignore
            // remove from back any values >= (min) or <= (max) compared to current obs
            while q.Count > 0 && (cmp (snd q.[q.Count - 1]) x) do q.RemoveBack() |> ignore
            // append new obs to back
            q.AddBack( (!i + winSz, x) )
            // return min/max value at front
            snd q.[0]
          | OptionalValue.Missing -> 
            if q.IsEmpty then nan else snd q.[0] }
  
    // moving window functions
  
    let movingCount winSz (series:Series<'K, float>) : Series<'K, float> =
      applyMovingSumsTransform 0 winSz (fun s -> s.nobs) series
  
    let movingSum winSz (series:Series<'K, float>) : Series<'K, float> =
      applyMovingSumsTransform 1 winSz (fun s -> s.sum) series
  
    let movingMean winSz (series:Series<'K, float>) : Series<'K, float> =
      applyMovingSumsTransform 1 winSz (fun s -> s.sum / s.nobs) series
  
    let movingVariance winSz (series:Series<'K, float>) : Series<'K, float> =
      applyMovingSumsTransform 2 winSz variance series
  
    let movingStdDev winSz (series:Series<'K, float>) : Series<'K, float> =
      applyMovingSumsTransform 2 winSz (variance >> sqrt) series
  
    let movingSkew winSz (series:Series<'K, float>) : Series<'K, float> =
      applyMovingSumsTransform 3 winSz skew series
  
    let movingKurt winSz (series:Series<'K, float>) : Series<'K, float> =
      applyMovingSumsTransform 4 winSz kurt series 
  
    let movingMin winSz (series:Series<'K, float>) : Series<'K, float> =
      applySeriesProj (movingMinMaxHelper winSz (>=)) series
  