WHY XFinChart ?

Professional-Service

Professional-Service

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Threading.Tasks;

namespace XTS.Base.Data.TI
{
    [IndicatorScaleAttribute(IndicatorScale.Custom, 0, 100)]
    [IndicatorAttribute("{95C1C6DA-9495-45DD-8266-33A1D9400107}", "RSI", "Relative Streangth Index", "SYMPH", IndicatorCategory = IndicatorCategoryType.Custom)]
    public class RSI : IndicatorBase
    {
        [Parameter("LengthPeriod", Description = "The length of the RSI", DefaultValue = 12)]
        private int _lengthPeriod = 12;
        [Parameter("UpperLimit", Description = "Over Bought Value", DefaultValue = 70)]
        private int _upperLimit = 70;
        [Parameter("LowerLimit", Description = "Over Sold Value", DefaultValue = 30)]
        private int _lowerLimit = 30;
        private double _lastUpwardPriceChangeSmooth = 0;
        private double _lastDownwardPriceChangeSmooth = 0;
        [Output("RSIValue", DefaultValue = double.NaN, LineColor = "Red")] 
        private DoubleSeries _rsiDoubleValueSeries = new DoubleSeries();
        [Output("UpperLimit", DefaultValue = double.NaN, LineColor = "Gray", LineStyle = DashStyle.DashDot)]
        private DoubleSeries _rsiUpperLimitDoubleValueSeries = new DoubleSeries();
        [Output("LowerLimit", DefaultValue = double.NaN, LineColor = "Gray", LineStyle = DashStyle.DashDot)]
        private DoubleSeries _rsiLowerLimitDoubleValueSeries = new DoubleSeries();
        public RSI(TimeDataSeries timeDataSeries, int lengthPeriod) : base(timeDataSeries){
            if (lengthPeriod <= 0)
                throw new ArgumentException("Invalid RSI length");
            _lengthPeriod = lengthPeriod;
        }
        public RSI() : base(null){}
        public RSI(TimeDataSeries timeDataSeries): base(timeDataSeries){}
        /// <summary>
        /// Calculates the Indicator Function value at the index.
        /// </summary>
        /// <param name="index">The index at which Indicator Function value need to be calculated.</param>
        /// <returns>
        /// The calculated Indicator function value at the index.
        /// </returns>
        protected override double Calculate(int index){
            double priceUpward = 0;
            double priceDownward = 0;
            int checkValue = _lengthPeriod;
            _rsiUpperLimitDoubleValueSeries[index] = _upperLimit;
            _rsiLowerLimitDoubleValueSeries[index] = _lowerLimit;
            if (index < checkValue)
                _rsiDoubleValueSeries[index] = double.NaN;
            else if (index == checkValue){
                int startIndex = Math.Max(index - _lengthPeriod, 1);
                double barPricePrevious = this.TimeDataSeries[startIndex].Close;
                for (int counter = startIndex + 1; counter <= index; counter++){
                    double barPriceCurrent = this.TimeDataSeries[counter].Close;
                    if (barPriceCurrent > barPricePrevious)  // Upward price movement
                        priceUpward += (barPriceCurrent - barPricePrevious);
                    else if (barPriceCurrent < barPricePrevious)  // Downward price movement
                        priceDownward += (barPricePrevious - barPriceCurrent);
                    barPricePrevious = barPriceCurrent;
                }
                _lastUpwardPriceChangeSmooth = priceUpward / _lengthPeriod;
                _lastDownwardPriceChangeSmooth = priceDownward / _lengthPeriod;
                double rsiValue = 100 - (100 / (1 + (_lastUpwardPriceChangeSmooth / _lastDownwardPriceChangeSmooth)));
                _rsiDoubleValueSeries[index] = Math.Round(rsiValue, 2);
            }else{
                double currentDownwardPriceChange;
                double currentUpwardPriceChange;
                double rsiValue = 0.0;
                currentUpwardPriceChange = this.TimeDataSeries[index].Close - this.TimeDataSeries[index - 1].Close;
                if (currentUpwardPriceChange >= 0)
                    currentDownwardPriceChange = 0;
                else{
                    currentDownwardPriceChange = -currentUpwardPriceChange;
                    currentUpwardPriceChange = 0;
                }
                _lastUpwardPriceChangeSmooth = ((_lengthPeriod - 1) * _lastUpwardPriceChangeSmooth + currentUpwardPriceChange) / _lengthPeriod;
                _lastDownwardPriceChangeSmooth = ((_lengthPeriod - 1) * _lastDownwardPriceChangeSmooth + currentDownwardPriceChange) / _lengthPeriod;
                if (_lastUpwardPriceChangeSmooth + _lastDownwardPriceChangeSmooth != 0)
                    rsiValue = 100 * _lastUpwardPriceChangeSmooth / (_lastUpwardPriceChangeSmooth + _lastDownwardPriceChangeSmooth);
                _rsiDoubleValueSeries[index] = Math.Round(rsiValue, 2);
            }
            return _rsiDoubleValueSeries[index];
        }
    }
}

Contact US

Let us help you to achieve your goals!

 
 
 
 
 
By providing Symphony with your contact information Symphony will process your personal data for the purpose of providing you with the information you have requested. For more information regarding Symphony's processing of your personal data, please read Symphony's Privacy Notice here.

  • Get latest updates from Us