public static MovingAverageResult Ma(decimal[] input,
                                             MovingAverageType maType,
                                             int period,
                                             Func <decimal[], decimal[], IndicatorSignal> maSignalLogic = null)
        {
            try
            {
                double[] output = new double[input.Length];
                var      result = Core.MovingAverage(0,
                                                     input.Length - 1,
                                                     Array.ConvertAll(input, item => (float)item),
                                                     period,
                                                     MovingAverageTypes.ToTaLib(maType),
                                                     out int outBeginIndex,
                                                     out int outElementsCount,
                                                     output);

                if (result == Core.RetCode.Success)
                {
                    var outputDecimal = new decimal[outElementsCount];

                    Array.Reverse(output);
                    Array.ConstrainedCopy(Array.ConvertAll(output, item => (decimal)item), outBeginIndex, outputDecimal, 0, outElementsCount);
                    Array.Reverse(outputDecimal);

                    return(new MovingAverageResult
                    {
                        Success = true,
                        IndicatorSignal = maSignalLogic != null?
                                          maSignalLogic.Invoke(input, outputDecimal) : maDefaultSignalLogic.Invoke(input, outputDecimal),
                                              Ma = outputDecimal
                    });
                }
                else
                {
                    return(new MovingAverageResult
                    {
                        Success = false,
                        IndicatorSignal = IndicatorSignal.Stay,
                        Message = result.ToString()
                    });
                }
            }
            catch (Exception ex)
            {
                return(new MovingAverageResult
                {
                    Success = false,
                    IndicatorSignal = IndicatorSignal.Stay,
                    Message = ex.ToString()
                });
            }
        }
        public static StochasticResult Stochastic(decimal[] inputHigh,
                                                  decimal[] inputLow,
                                                  decimal[] inputClose,
                                                  int fastKPeriod,
                                                  MovingAverageType slowKMaType,
                                                  int slowKPeriod,
                                                  MovingAverageType slowDMaType,
                                                  int slowDPeriod,
                                                  Func <decimal[], decimal[], IndicatorSignal> stochSignalLogic = null)
        {
            try
            {
                var indicatorSignal = IndicatorSignal.Stay;

                double[] outputSlowK = new double[inputHigh.Length];
                double[] outputSlowD = new double[inputHigh.Length];

                var result = Core.Stoch(0,
                                        inputHigh.Length - 1,
                                        Array.ConvertAll(inputHigh, item => (double)item),
                                        Array.ConvertAll(inputLow, item => (double)item),
                                        Array.ConvertAll(inputClose, item => (double)item),
                                        fastKPeriod,
                                        slowKPeriod,
                                        MovingAverageTypes.ToTaLib(slowKMaType),
                                        slowDPeriod,
                                        MovingAverageTypes.ToTaLib(slowDMaType),
                                        out int outBeginIndex,
                                        out int outElementsCount,
                                        outputSlowK,
                                        outputSlowD);

                if (result == Core.RetCode.Success)
                {
                    var outputSlowKDecimal = new decimal[outElementsCount];
                    var outputSlowDDecimal = new decimal[outElementsCount];

                    Array.Reverse(outputSlowKDecimal);
                    Array.Reverse(outputSlowDDecimal);

                    Array.ConstrainedCopy(Array.ConvertAll(outputSlowK, item => (decimal)item), outBeginIndex, outputSlowKDecimal, 0, outElementsCount);
                    Array.ConstrainedCopy(Array.ConvertAll(outputSlowD, item => (decimal)item), outBeginIndex, outputSlowDDecimal, 0, outElementsCount);

                    Array.Reverse(outputSlowKDecimal);
                    Array.Reverse(outputSlowDDecimal);

                    indicatorSignal = stochSignalLogic != null?
                                      stochSignalLogic.Invoke(outputSlowKDecimal, outputSlowDDecimal) :
                                          stochDefaultSignalLogic.Invoke(outputSlowKDecimal, outputSlowDDecimal);

                    return(new StochasticResult
                    {
                        Success = true,
                        IndicatorSignal = indicatorSignal,
                        SlowK = outputSlowKDecimal,
                        SlowD = outputSlowDDecimal
                    });
                }
                else
                {
                    return(new StochasticResult
                    {
                        Success = false,
                        IndicatorSignal = IndicatorSignal.Stay,
                        Message = result.ToString()
                    });
                }
            }
            catch (Exception ex)
            {
                return(new StochasticResult
                {
                    Success = false,
                    IndicatorSignal = IndicatorSignal.Stay,
                    Message = ex.ToString()
                });
            }
        }
        public static MacdResult MacdExt(decimal[] input,
                                         MovingAverageType fastMaType,
                                         int fastPeriod,
                                         MovingAverageType slowMaType,
                                         int slowPeriod,
                                         MovingAverageType signalMaType,
                                         int signalPeriod,
                                         Func <decimal[], decimal[], decimal[], IndicatorSignal> macdExtSignalLogic = null)
        {
            try
            {
                var indicatorSignal = IndicatorSignal.Stay;

                double[] outputMacd      = new double[input.Length];
                double[] outputSignal    = new double[input.Length];
                double[] outputHistogram = new double[input.Length];
                var      result          = Core.MacdExt(0,
                                                        input.Length - 1,
                                                        Array.ConvertAll(input, item => (float)item),
                                                        fastPeriod,
                                                        MovingAverageTypes.ToTaLib(fastMaType),
                                                        slowPeriod,
                                                        MovingAverageTypes.ToTaLib(slowMaType),
                                                        signalPeriod,
                                                        MovingAverageTypes.ToTaLib(signalMaType),
                                                        out int outBeginIndex,
                                                        out int outElementsCount,
                                                        outputMacd,
                                                        outputSignal,
                                                        outputHistogram);

                if (result == Core.RetCode.Success)
                {
                    var outputMacdDecimal      = new decimal[outElementsCount];
                    var outputSignalDecimal    = new decimal[outElementsCount];
                    var outputHistogramDecimal = new decimal[outElementsCount];

                    Array.Reverse(outputMacd);
                    Array.Reverse(outputSignal);
                    Array.Reverse(outputHistogram);

                    Array.ConstrainedCopy(Array.ConvertAll(outputMacd, item => (decimal)item), outBeginIndex, outputMacdDecimal, 0, outElementsCount);
                    Array.ConstrainedCopy(Array.ConvertAll(outputSignal, item => (decimal)item), outBeginIndex, outputSignalDecimal, 0, outElementsCount);
                    Array.ConstrainedCopy(Array.ConvertAll(outputHistogram, item => (decimal)item), outBeginIndex, outputHistogramDecimal, 0, outElementsCount);

                    Array.Reverse(outputMacdDecimal);
                    Array.Reverse(outputSignalDecimal);
                    Array.Reverse(outputHistogramDecimal);

                    indicatorSignal = macdExtSignalLogic != null?
                                      macdExtSignalLogic.Invoke(outputMacdDecimal, outputSignalDecimal, outputHistogramDecimal) :
                                          macdDefaultSignalLogic.Invoke(outputMacdDecimal, outputSignalDecimal, outputHistogramDecimal);

                    return(new MacdResult
                    {
                        Success = true,
                        IndicatorSignal = indicatorSignal,
                        Macd = outputMacdDecimal,
                        Signal = outputSignalDecimal,
                        Histogram = outputHistogramDecimal
                    });
                }
                else
                {
                    return(new MacdResult
                    {
                        Success = false,
                        Message = result.ToString()
                    });
                }
            }
            catch (Exception ex)
            {
                return(new MacdResult
                {
                    Success = false,
                    Message = ex.ToString()
                });
            }
        }
        public static BollingerBandsResult BollingerBands(decimal[] input,
                                                          int period,
                                                          double stdDevUp,
                                                          double stdDevDown,
                                                          MovingAverageType maType,
                                                          Func <decimal[], decimal[], decimal[], decimal[], IndicatorSignal> bBandsSignalLogic = null)
        {
            try
            {
                var indicatorSignal = IndicatorSignal.Stay;

                double[] outputUp     = new double[input.Length];
                double[] outputMiddle = new double[input.Length];
                double[] outputDown   = new double[input.Length];

                var result = Core.Bbands(0,
                                         input.Length - 1,
                                         Array.ConvertAll(input, item => (float)item),
                                         period,
                                         stdDevUp,
                                         stdDevDown,
                                         MovingAverageTypes.ToTaLib(maType),
                                         out int outBeginIndex,
                                         out int outElementsCount,
                                         outputUp,
                                         outputMiddle,
                                         outputDown);

                if (result == Core.RetCode.Success)
                {
                    var outputUpDecimal     = new decimal[outElementsCount];
                    var outputMiddleDecimal = new decimal[outElementsCount];
                    var outputDownDecimal   = new decimal[outElementsCount];

                    Array.Reverse(outputUp);
                    Array.ConstrainedCopy(Array.ConvertAll(outputUp, item => (decimal)item), outBeginIndex, outputUpDecimal, 0, outElementsCount);
                    Array.Reverse(outputUpDecimal);

                    Array.Reverse(outputMiddle);
                    Array.ConstrainedCopy(Array.ConvertAll(outputMiddle, item => (decimal)item), outBeginIndex, outputMiddleDecimal, 0, outElementsCount);
                    Array.Reverse(outputMiddleDecimal);

                    Array.Reverse(outputDown);
                    Array.ConstrainedCopy(Array.ConvertAll(outputDown, item => (decimal)item), outBeginIndex, outputDownDecimal, 0, outElementsCount);
                    Array.Reverse(outputDownDecimal);

                    indicatorSignal = bBandsSignalLogic != null?
                                      bBandsSignalLogic.Invoke(input, outputUpDecimal, outputMiddleDecimal, outputDownDecimal) :
                                          IndicatorSignal.Stay;

                    return(new BollingerBandsResult
                    {
                        Success = true,
                        IndicatorSignal = indicatorSignal,
                        UpperBand = outputUpDecimal,
                        MiddleBand = outputMiddleDecimal,
                        LowerBand = outputDownDecimal
                    });
                }
                else
                {
                    return(new BollingerBandsResult
                    {
                        Success = false,
                        IndicatorSignal = IndicatorSignal.Stay,
                        Message = result.ToString()
                    });
                }
            }
            catch (Exception ex)
            {
                return(new BollingerBandsResult
                {
                    Success = false,
                    IndicatorSignal = IndicatorSignal.Stay,
                    Message = ex.ToString()
                });
            }
        }