/// <summary>
        /// Calculate Covariance.
        /// <see href="https://en.wikipedia.org/wiki/Covariance"/>
        /// </summary>
        /// <param name="series">this time series</param>
        /// <param name="other">other time series</param>
        /// <param name="n">number of bars</param>
        /// <param name="subSample">distance between bars</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>covariance time series</returns>
        public static ITimeSeries <double> Covariance(this ITimeSeries <double> series, ITimeSeries <double> other, int n, int subSample = 1,
                                                      CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), other.GetHashCode(), n);

            var x = series;
            var y = other;

            return(IndicatorsBasic.BufferedLambda(
                       (v) =>
            {
                var avgX = Enumerable.Range(0, n)
                           .Average(t => x[t * subSample]);
                var avgY = Enumerable.Range(0, n)
                           .Average(t => y[t * subSample]);
                var covXY = Enumerable.Range(0, n)
                            .Sum(t => (x[t * subSample] - avgX) * (y[t * subSample] - avgY))
                            / (n - 1.0);

                return covXY;
            },
                       0.0,
                       cacheId));
        }
        /// <summary>
        /// Calculate Pearson Correlation Coefficient.
        /// <see href="https://en.wikipedia.org/wiki/Pearson_correlation_coefficient"/>
        /// </summary>
        /// <param name="series">this time series</param>
        /// <param name="other">other time series</param>
        /// <param name="n">number of bars</param>
        /// <param name="subSample">distance between bars</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>correlation coefficient time series</returns>
        public static ITimeSeries <double> Correlation(this ITimeSeries <double> series, ITimeSeries <double> other, int n, int subSample = 1,
                                                       CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), other.GetHashCode(), n);

            var x = series;
            var y = other;

            double sum = n / 2.0 * (n + 1.0);

            return(IndicatorsBasic.BufferedLambda(
                       (v) =>
            {
                var avgX = Enumerable.Range(0, n)
                           .Average(t => x[t * subSample]);
                var avgY = Enumerable.Range(0, n)
                           .Average(t => y[t * subSample]);
                var covXY = Enumerable.Range(0, n)
                            .Sum(t => (x[t * subSample] - avgX) * (y[t * subSample] - avgY)) / n;
                var varX = Enumerable.Range(0, n)
                           .Sum(t => Math.Pow(x[t * subSample] - avgX, 2.0)) / n;
                var varY = Enumerable.Range(0, n)
                           .Sum(t => Math.Pow(y[t * subSample] - avgY, 2.0)) / n;
                var corr = covXY
                           / Math.Max(1e-99, Math.Sqrt(varX) * Math.Sqrt(varY));

                return corr;
            },
                       0.0,
                       cacheId));
        }
示例#3
0
        /// <summary>
        /// Calculate Kaufman's Adaptive Moving Average, as described here:
        /// <see href="https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:kaufman_s_adaptive_moving_average"/>
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="erPeriod">period for efficiency ratio</param>
        /// <param name="fastEma">period for fast EMA</param>
        /// <param name="slowEma">period for slow EMA</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>KAMA as time series</returns>
        public static ITimeSeries <double> KAMA(this ITimeSeries <double> series, int erPeriod = 10, int fastEma = 2, int slowEma = 30,
                                                CacheId parentId = null, [CallerMemberName] string memberName    = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), erPeriod, fastEma, slowEma);

            // TODO: we should be able to remove the try/ catch blocks here
            return(IndicatorsBasic.BufferedLambda(
                       (v) =>
            {
                try
                {
                    double scFast = 2.0 / (1.0 + fastEma);
                    double scSlow = 2.0 / (1.0 + slowEma);

                    double change = Math.Abs(series[0] - series[erPeriod]);
                    double volatility = Enumerable.Range(0, erPeriod)
                                        .Sum(t => Math.Abs(series[t] - series[t + 1]));

                    double efficiencyRatio = change / Math.Max(1e-10, volatility);
                    double smoothingConstant = Math.Pow(efficiencyRatio * (scFast - scSlow) + scSlow, 2);

                    double r = smoothingConstant * (series[0] - v) + v;
                    return double.IsNaN(r) ? 0.0 : r;
                }
                catch (Exception)
                {
                    // we get here when we access bars too far in the past
                    return series[0];
                }
            },
                       series[0],
                       cacheId));
        }
示例#4
0
        /// <summary>
        /// Calculate Stochastic Oscillator, as described here:
        /// <see href="https://en.wikipedia.org/wiki/Stochastic_oscillator"/>
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">oscillator period</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>Stochastic Oscillator as time series</returns>
        public static _StochasticOscillator StochasticOscillator(this ITimeSeries <double> series, int n = 14,
                                                                 CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);


            var container = Cache <_StochasticOscillator> .GetData(
                cacheId,
                () => new _StochasticOscillator());

            double hh = series
                        .Highest(n, cacheId)[0];

            double ll = series
                        .Lowest(n, cacheId)[0];

            double price = series[0];

            container.PercentK = IndicatorsBasic.BufferedLambda(
                v => 100.0 * (price - ll) / Math.Max(1e-10, hh - ll),
                50.0,
                cacheId);

            container.PercentD = container.PercentK
                                 .SMA(3, cacheId);

            return(container);
        }
示例#5
0
        /// <summary>
        /// Normalize time series over number of bars; 1.0 being the average.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">normalizing period</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>normalized time series</returns>
        public static ITimeSeries <double> Normalize(this ITimeSeries <double> series, int n,
                                                     CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(series.Divide(series.EMA(n, cacheId), cacheId));
        }
示例#6
0
        /// <summary>
        /// Calculate logarithmic regression of time series.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">number of bars for regression</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>regression parameters as time series</returns>
        public static _Regression LogRegression(this ITimeSeries <double> series, int n,
                                                CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(series
                   .Log(cacheId)
                   .LinRegression(n, cacheId));
        }
示例#7
0
        /// <summary>
        /// Cast time series to double
        /// </summary>
        /// <param name="series">input series of long</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>output series of double</returns>
        public static ITimeSeries <double> ToDouble(this ITimeSeries <long> series,
                                                    CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode());

            return(IndicatorsBasic.Lambda(
                       (t) => (double)series[t],
                       cacheId));
        }
        /// <summary>
        /// Calculate addition of time series and constant value.
        /// </summary>
        /// <param name="series">time series</param>
        /// <param name="constValue">constant value</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>time series + constant value</returns>
        public static ITimeSeries <double> Add(this ITimeSeries <double> series, double constValue,
                                               CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), constValue.GetHashCode());

            return(IndicatorsBasic.Lambda(
                       (t) => series[t] + constValue,
                       cacheId));
        }
示例#9
0
        /// <summary>
        /// Calculate historical volatility, based on log-returns.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">length</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>volatility as time series</returns>
        public static ITimeSeries <double> Volatility(this ITimeSeries <double> series, int n = 10,
                                                      CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(series
                   .LogReturn(cacheId)
                   .StandardDeviation(n, cacheId));
        }
示例#10
0
        /// <summary>
        /// Calculate subtraction of two time series.
        /// </summary>
        /// <param name="series1">time series #1</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <param name="series2">time series #2</param>
        /// <returns>time series #1 - time series #2</returns>
        public static ITimeSeries <double> Subtract(this ITimeSeries <double> series1, ITimeSeries <double> series2,
                                                    CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series1.GetHashCode(), series2.GetHashCode());

            return(IndicatorsBasic.Lambda(
                       (t) => series1[t] - series2[t],
                       cacheId));
        }
示例#11
0
        /// <summary>
        /// Delay time series by number of bars.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="delay">delay length</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>delayed time series</returns>
        public static ITimeSeries <double> Delay(this ITimeSeries <double> series, int delay,
                                                 CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), delay);

            return(Lambda(
                       (t) => series[t + delay],
                       cacheId));
        }
示例#12
0
        /// <summary>
        /// Calculate logarithmic return from the previous to the current value
        /// of the time series.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>logarithm of relative return</returns>
        public static ITimeSeries <double> LogReturn(this ITimeSeries <double> series,
                                                     CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode());

            return(Lambda(
                       (t) => Math.Log(series[t] / series[t + 1]),
                       cacheId));
        }
示例#13
0
        /// <summary>
        /// Calculate range over the specified number of past bars.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">number of bars to search</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>range between highest and lowest value of past n bars</returns>
        public static ITimeSeries <double> Range(this ITimeSeries <double> series, int n,
                                                 CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(series
                   .Highest(n, cacheId)
                   .Subtract(series
                             .Lowest(n, cacheId), cacheId));
        }
示例#14
0
        /// <summary>
        /// Calculate simple momentum: m = p[0] / p[n] - 1
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">number of bars for regression</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>simple momentum, as time series</returns>
        public static ITimeSeries <double> SimpleMomentum(this ITimeSeries <double> series, int n = 21,
                                                          CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n.GetHashCode());

            return(IndicatorsBasic.BufferedLambda(
                       prev => series[0] / series[n] - 1.0,
                       0.0,
                       cacheId));
        }
示例#15
0
        /// <summary>
        /// Calculate Simple Moving Average as described here:
        /// <see href="https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average"/>
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">averaging length</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>SMA time series</returns>
        public static ITimeSeries <double> SMA(this ITimeSeries <double> series, int n,
                                               CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(IndicatorsBasic.BufferedLambda(
                       v => Enumerable.Range(0, n)
                       .Sum(t => series[t]) / n,
                       series[0],
                       cacheId));
        }
示例#16
0
        /// <summary>
        /// Calculate lowest value of the specified number of past bars.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">number of bars to search</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>lowest value of past n bars</returns>
        public static ITimeSeries <double> Lowest(this ITimeSeries <double> series, int n,
                                                  CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            int N = Math.Max(1, n);

            return(BufferedLambda(
                       (v) => Enumerable.Range(0, N).Min(t => series[t]),
                       series[0],
                       cacheId));
        }
示例#17
0
        /// <summary>
        /// Calculate Capital Asset Pricing Model parameters.
        /// <see href="http://en.wikipedia.org/wiki/Capital_asset_pricing_model"/>
        /// This indicator uses an exponentially-weighted, incremental method of
        /// calculation, based on Tony Finch, which is very fast and efficient.
        /// /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="benchmark">benchmark time series</param>
        /// <param name="n">length of observation window</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>container w/ CAPM parameters</returns>
        public static _CAPM CAPM(this ITimeSeries <double> series, ITimeSeries <double> benchmark, int n,
                                 CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), benchmark.GetHashCode(), n);

            var functor = Cache <CAPMFunctor> .GetData(
                cacheId,
                () => new CAPMFunctor(series, benchmark, n));

            functor.Calc();

            return(functor);
        }
示例#18
0
        /// <summary>
        /// Calculate standard deviation, based on exponentially weighted filters. This is an
        /// incremental calculation, based on Tony Finch, which is very fast and efficient.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">filtering length</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>variance as time series</returns>
        public static _SemiDeviation SemiDeviation(this ITimeSeries <double> series, int n = 10,
                                                   CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            var container = Cache <_SemiDeviation> .GetData(
                cacheId,
                () => new _SemiDeviation());

            container.Average = series.SMA(n);

            container.Downside = IndicatorsBasic.BufferedLambda(
                v =>
            {
                var downSeries = Enumerable.Range(0, n)
                                 .Where(t => series[t] < container.Average[0]);

                if (downSeries.Count() == 0)
                {
                    return(0.0);
                }
                else
                {
                    return(Math.Sqrt(downSeries
                                     .Average(t => Math.Pow(series[t] - container.Average[0], 2.0))));
                }
            }, 0.0,
                cacheId);

            container.Upside = IndicatorsBasic.BufferedLambda(
                v =>
            {
                var upSeries = Enumerable.Range(0, n)
                               .Where(t => series[t] > container.Average[0]);

                if (upSeries.Count() == 0)
                {
                    return(0.0);
                }
                else
                {
                    return(Math.Sqrt(upSeries
                                     .Average(t => Math.Pow(series[t] - container.Average[0], 2.0))));
                }
            }, 0.0,
                cacheId);

            return(container);
        }
示例#19
0
        /// <summary>
        /// Calculate standard deviation, based on exponentially weighted filters. This is an
        /// incremental calculation, based on Tony Finch, which is very fast and efficient.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">filtering length</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>variance as time series</returns>
        public static ITimeSeries <double> FastStandardDeviation(this ITimeSeries <double> series, int n = 10,
                                                                 CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            var functor = Cache <FunctorStandardDeviation> .GetData(
                cacheId,
                () => new FunctorStandardDeviation(series, n));

            functor.Calc();

            return(functor);
        }
示例#20
0
        /// <summary>
        /// Calculate linear regression of time series.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">number of bars for regression</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>regression parameters as time series</returns>
        public static _Regression LinRegression(this ITimeSeries <double> series, int n,
                                                CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            var functor = Cache <LinRegressionFunctor> .GetData(
                cacheId,
                () => new LinRegressionFunctor(series, n));

            functor.Calc();

            return(functor);
        }
示例#21
0
        /// <summary>
        /// Return current drawdown in percent, as value between 0 and 1.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">length of observation window</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>drawdown as time series</returns>
        public static ITimeSeries <double> Drawdown(this ITimeSeries <double> series, int n,
                                                    CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            // TODO: rewrite this, using buffered lambda, see MaxDrawdown
            return(IndicatorsBasic.Const(1.0, cacheId)
                   .Subtract(
                       series
                       .Divide(
                           series
                           .Highest(n, cacheId),
                           cacheId),
                       cacheId));
        }
示例#22
0
        /// <summary>
        /// Calculate return over maximum drawdown.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">length of observation window</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>RoMaD</returns>
        public static ITimeSeries <double> ReturnOnMaxDrawdown(this ITimeSeries <double> series, int n,
                                                               CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(IndicatorsBasic.BufferedLambda(
                       (p) =>
            {
                double ret = series[0] / series[n] - 1.0;
                double dd = series.MaxDrawdown(n)[0];
                return ret / Math.Max(1e-3, dd);
            },
                       0.0,
                       cacheId));
        }
示例#23
0
        /// <summary>
        /// Calculate volatility estimate from recent trading range.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">length of calculation window</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>volatility as time series</returns>
        public static ITimeSeries <double> VolatilityFromRange(this ITimeSeries <double> series, int n,
                                                               CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(IndicatorsBasic.BufferedLambda(
                       (v) =>
            {
                double hi = series.Highest(n)[0];
                double lo = series.Lowest(n)[0];

                return 0.80 * Math.Sqrt(1.0 / n) * Math.Log(hi / lo);
            },
                       0.0,
                       cacheId));
        }
示例#24
0
        /// <summary>
        /// Calculate Williams %R, as described here:
        /// <see href="https://en.wikipedia.org/wiki/Williams_%25R"/>
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">period</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>Williams %R as time series</returns>
        public static ITimeSeries <double> WilliamsPercentR(this ITimeSeries <double> series, int n = 10,
                                                            CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(IndicatorsBasic.BufferedLambda(
                       (v) =>
            {
                double hh = series.Highest(n)[0];
                double ll = series.Lowest(n)[0];
                double price = series[0];
                return -100.0 * (hh - price) / Math.Max(1e-10, hh - ll);
            },
                       -50.0,
                       cacheId));
        }
示例#25
0
        /// <summary>
        /// Calculate Exponential Moving Average, as described here:
        /// <see href="https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average"/>
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">averaging length</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>EMA time series</returns>
        public static ITimeSeries <double> EMA(this ITimeSeries <double> series, int n,
                                               CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);


            double alpha = 2.0 / (Math.Max(1, n) + 1);

            return(IndicatorsBasic.BufferedLambda(
                       (v) =>
            {
                double r = alpha * (series[0] - v) + v;
                return double.IsNaN(r) ? 0.0 : r;
            },
                       series[0],
                       cacheId));
        }
示例#26
0
        /// <summary>
        /// Calculate Ehlers' Zero Lag Exponential Moving Average, as described here:
        /// <see href="https://en.wikipedia.org/wiki/Zero_lag_exponential_moving_average"/>
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="period">averaging length</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>ZLEMA as time series</returns>
        public static ITimeSeries <double> ZLEMA(this ITimeSeries <double> series, int period,
                                                 CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), period);

            int lag = (int)Math.Round((period - 1.0) / 2.0);

            return(series
                   .Add(
                       series
                       .Subtract(
                           series
                           .Delay(lag, cacheId),
                           cacheId),
                       cacheId)
                   .EMA(period, cacheId));
        }
示例#27
0
        /// <summary>
        /// Calculate MACD, as described here:
        /// <see href="https://en.wikipedia.org/wiki/MACD"/>
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="fast">fast EMA period</param>
        /// <param name="slow">slow EMA period</param>
        /// <param name="signal">signal line period</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns></returns>
        public static _MACD MACD(this ITimeSeries <double> series, int fast = 12, int slow     = 26, int signal = 9,
                                 CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), fast, slow, signal);

            var container = Cache <_MACD> .GetData(
                cacheId,
                () => new _MACD());

            container.Fast       = series.EMA(fast, cacheId);
            container.Slow       = series.EMA(slow, cacheId);
            container.MACD       = container.Fast.Subtract(container.Slow, cacheId);
            container.Signal     = container.MACD.EMA(signal, cacheId);
            container.Divergence = container.MACD.Subtract(container.Signal, cacheId);

            return(container);
        }
示例#28
0
        /// <summary>
        /// Calculate Sharpe Ratio, as described here:
        /// <see href="https://en.wikipedia.org/wiki/Sharpe_ratio"/>
        /// </summary>
        /// <param name="series"></param>
        /// <param name="riskFreeRate"></param>
        /// <param name="n"></param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns></returns>
        public static ITimeSeries <double> SharpeRatio(this ITimeSeries <double> series, ITimeSeries <double> riskFreeRate, int n,
                                                       CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), riskFreeRate.GetHashCode(), n);

            var excessReturn = series
                               .Return(cacheId)
                               .Subtract(riskFreeRate
                                         .Return(cacheId),
                                         cacheId);

            return(excessReturn
                   .EMA(n, cacheId)
                   .Divide(excessReturn
                           .FastStandardDeviation(n, cacheId)
                           .Max(IndicatorsBasic.Const(1e-10, cacheId), cacheId),
                           cacheId));
        }
示例#29
0
        /// <summary>
        /// Calculate Hull Moving Average, as described here:
        /// <see href="https://alanhull.com/hull-moving-average"/>
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">averaging length</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>HMA time series</returns>
        public static ITimeSeries <double> HMA(this ITimeSeries <double> series, int n,
                                               CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            // http://www.incrediblecharts.com/indicators/weighted_moving_average.php
            // Integer(SquareRoot(Period)) WMA [2 x Integer(Period/2) WMA(Price) - Period WMA(Price)]

            int n2 = (int)Math.Round(n / 2.0);
            int n3 = (int)Math.Round(Math.Sqrt(n));

            return(series
                   .WMA(n2, cacheId)
                   .Multiply(2.0, cacheId)
                   .Subtract(
                       series
                       .WMA(n, cacheId),
                       cacheId)
                   .WMA(n3, cacheId));
        }
示例#30
0
        /// <summary>
        /// Return maximum drawdown.
        /// </summary>
        /// <param name="series">input time series</param>
        /// <param name="n">length of observation window</param>
        /// <param name="parentId">caller cache id, optional</param>
        /// <param name="memberName">caller's member name, optional</param>
        /// <param name="lineNumber">caller line number, optional</param>
        /// <returns>maximum drawdown as time series</returns>
        public static ITimeSeries <double> MaxDrawdown(this ITimeSeries <double> series, int n,
                                                       CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0)
        {
            var cacheId = new CacheId(parentId, memberName, lineNumber,
                                      series.GetHashCode(), n);

            return(IndicatorsBasic.BufferedLambda(
                       (p) =>
            {
                double highestHigh = 0.0;
                double maxDrawdown = 0.0;
                for (int t = n - 1; t >= 0; t--)
                {
                    highestHigh = Math.Max(highestHigh, series[t]);
                    maxDrawdown = Math.Max(maxDrawdown, 1.0 - series[t] / highestHigh);
                }
                return maxDrawdown;
            },
                       0.0,
                       cacheId));
        }