Chart is one of the most important component of any trading system development process. XFinChart is a lightweight, flexible, interactive, feature rich and developer-friendly stock market data visualization charting and technical analysis library for .NET . The chart library also provides inbuilt framework for technical indicator and real-time data rendering. The technical analysis library provides a number of technical indicators that can be used to build trading strategies for stock markets, futures, forex etc.
XTALib is a flexible and powerful Technical Analysis Indicator framework library implemented in C#. It is indeed a library for programmers to develop custom indicators for financial market analysis, charting and developing a full featured trading application in .NET compatible with XFinChart. XTALib currently implements 50+ most frequently used indicators as an open source for your reference and provides an open framework to easily develop a proprietary indicator.
@Quant Developers and Data Scientists can use pre-built standard indicators or use their knowledge to develop their proprietary indicators using XTALib framework and combine them to build their proprietary trading strategies. Additionally, leveraging Symphony XTS API, users can retrieve historical and real-time market data and route orders connecting to a broker from their application.
Regardless of hundreds of standard indicators, traders want to make their own custom indicators or create a graphical display for making a better trading decision. Creating your own custom indicator is very simple. Following example provides a sample code to develop a Relative Strength Index (RSI) Indicator.
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]; } } }
Discover why XFinChart.NET is the best financial software component before making a purchase