536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
1637 lines
62 KiB
C#
1637 lines
62 KiB
C#
//-------------------------------------------------------------
|
||
// <copyright company=’Microsoft Corporation’>
|
||
// Copyright © Microsoft Corporation. All Rights Reserved.
|
||
// </copyright>
|
||
//-------------------------------------------------------------
|
||
// @owner=victark, alexgor, deliant
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
using System.Globalization;
|
||
using System.Diagnostics;
|
||
|
||
#if Microsoft_CONTROL
|
||
namespace System.Windows.Forms.DataVisualization.Charting.Formulas
|
||
#else
|
||
namespace System.Web.UI.DataVisualization.Charting.Formulas
|
||
#endif
|
||
{
|
||
|
||
#region class FormulaHelper
|
||
/// <summary>
|
||
/// Formula helper is a static utility class implementing common formula related routines.
|
||
/// </summary>
|
||
internal static class FormulaHelper
|
||
{
|
||
#region Static
|
||
/// <summary>
|
||
/// Gets the formula info instance.
|
||
/// </summary>
|
||
/// <param name="formula">The formula.</param>
|
||
/// <returns>FomulaInfo instance</returns>
|
||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
|
||
internal static FormulaInfo GetFormulaInfo(FinancialFormula formula)
|
||
{
|
||
switch (formula)
|
||
{
|
||
//Price indicators
|
||
case FinancialFormula.MovingAverage:
|
||
return new MovingAverageFormulaInfo();
|
||
case FinancialFormula.ExponentialMovingAverage:
|
||
return new ExponentialMovingAverageFormulaInfo();
|
||
case FinancialFormula.WeightedMovingAverage:
|
||
return new WeightedMovingAverageFormulaInfo();
|
||
case FinancialFormula.TriangularMovingAverage:
|
||
return new TriangularMovingAverageFormulaInfo();
|
||
case FinancialFormula.TripleExponentialMovingAverage:
|
||
return new TripleExponentialMovingAverageFormulaInfo();
|
||
case FinancialFormula.BollingerBands:
|
||
return new BollingerBandsFormulaInfo();
|
||
case FinancialFormula.TypicalPrice:
|
||
return new TypicalPriceFormulaInfo();
|
||
case FinancialFormula.WeightedClose:
|
||
return new WeightedCloseFormulaInfo();
|
||
case FinancialFormula.MedianPrice:
|
||
return new MedianPriceFormulaInfo();
|
||
case FinancialFormula.Envelopes:
|
||
return new EnvelopesFormulaInfo();
|
||
case FinancialFormula.StandardDeviation:
|
||
return new StandardDeviationFormulaInfo();
|
||
|
||
// Oscilators
|
||
case FinancialFormula.ChaikinOscillator:
|
||
return new ChaikinOscillatorFormulaInfo();
|
||
case FinancialFormula.DetrendedPriceOscillator:
|
||
return new DetrendedPriceOscillatorFormulaInfo();
|
||
case FinancialFormula.VolatilityChaikins:
|
||
return new VolatilityChaikinsFormulaInfo();
|
||
case FinancialFormula.VolumeOscillator:
|
||
return new VolumeOscillatorFormulaInfo();
|
||
case FinancialFormula.StochasticIndicator:
|
||
return new StochasticIndicatorFormulaInfo();
|
||
case FinancialFormula.WilliamsR:
|
||
return new WilliamsRFormulaInfo();
|
||
|
||
// General technical indicators
|
||
case FinancialFormula.AverageTrueRange:
|
||
return new AverageTrueRangeFormulaInfo();
|
||
case FinancialFormula.EaseOfMovement:
|
||
return new EaseOfMovementFormulaInfo();
|
||
case FinancialFormula.MassIndex:
|
||
return new MassIndexFormulaInfo();
|
||
case FinancialFormula.Performance:
|
||
return new PerformanceFormulaInfo();
|
||
case FinancialFormula.RateOfChange:
|
||
return new RateOfChangeFormulaInfo();
|
||
case FinancialFormula.RelativeStrengthIndex:
|
||
return new RelativeStrengthIndexFormulaInfo();
|
||
case FinancialFormula.MovingAverageConvergenceDivergence:
|
||
return new MovingAverageConvergenceDivergenceFormulaInfo();
|
||
case FinancialFormula.CommodityChannelIndex:
|
||
return new CommodityChannelIndexFormulaInfo();
|
||
|
||
// Forecasting
|
||
case FinancialFormula.Forecasting:
|
||
return new ForecastingFormulaInfo();
|
||
|
||
// Volume Indicators
|
||
case FinancialFormula.MoneyFlow:
|
||
return new MoneyFlowFormulaInfo();
|
||
case FinancialFormula.PriceVolumeTrend:
|
||
return new PriceVolumeTrendFormulaInfo();
|
||
case FinancialFormula.OnBalanceVolume:
|
||
return new OnBalanceVolumeFormulaInfo();
|
||
case FinancialFormula.NegativeVolumeIndex:
|
||
return new NegativeVolumeIndexFormulaInfo();
|
||
case FinancialFormula.PositiveVolumeIndex:
|
||
return new PositiveVolumeIndexFormulaInfo();
|
||
case FinancialFormula.AccumulationDistribution:
|
||
return new AccumulationDistributionFormulaInfo();
|
||
|
||
default:
|
||
Debug.Fail(String.Format(CultureInfo.InvariantCulture, "{0} case is not defined", formula));
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets the data fields of the specified chart type.
|
||
/// </summary>
|
||
/// <param name="chartType">Type of the chart.</param>
|
||
/// <returns>Data fields</returns>
|
||
internal static IList<DataField> GetDataFields(SeriesChartType chartType)
|
||
{
|
||
switch (chartType)
|
||
{
|
||
case SeriesChartType.BoxPlot:
|
||
return new DataField[] {
|
||
DataField.LowerWisker, DataField.UpperWisker,
|
||
DataField.LowerBox, DataField.UpperBox,
|
||
DataField.Average, DataField.Median };
|
||
case SeriesChartType.Bubble:
|
||
return new DataField[] {
|
||
DataField.Bubble, DataField.BubbleSize };
|
||
case SeriesChartType.Candlestick:
|
||
case SeriesChartType.Stock:
|
||
return new DataField[] {
|
||
DataField.High, DataField.Low,
|
||
DataField.Open, DataField.Close };
|
||
case SeriesChartType.ErrorBar:
|
||
return new DataField[] {
|
||
DataField.Center,
|
||
DataField.LowerError, DataField.UpperError};
|
||
case SeriesChartType.RangeBar:
|
||
case SeriesChartType.Range:
|
||
case SeriesChartType.RangeColumn:
|
||
case SeriesChartType.SplineRange:
|
||
return new DataField[] {
|
||
DataField.Top, DataField.Bottom };
|
||
default:
|
||
return new DataField[] { DataField.Y };
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets the default type of the chart associated with this field name.
|
||
/// </summary>
|
||
/// <param name="field">The field.</param>
|
||
/// <returns></returns>
|
||
internal static SeriesChartType GetDefaultChartType(DataField field)
|
||
{
|
||
switch (field)
|
||
{
|
||
default:
|
||
case DataField.Y:
|
||
return SeriesChartType.Line;
|
||
case DataField.LowerWisker:
|
||
case DataField.UpperWisker:
|
||
case DataField.LowerBox:
|
||
case DataField.UpperBox:
|
||
case DataField.Average:
|
||
case DataField.Median:
|
||
return SeriesChartType.BoxPlot;
|
||
case DataField.Bubble:
|
||
case DataField.BubbleSize:
|
||
return SeriesChartType.Bubble;
|
||
case DataField.High:
|
||
case DataField.Low:
|
||
case DataField.Open:
|
||
case DataField.Close:
|
||
return SeriesChartType.Stock;
|
||
case DataField.Center:
|
||
case DataField.LowerError:
|
||
case DataField.UpperError:
|
||
return SeriesChartType.ErrorBar;
|
||
case DataField.Top:
|
||
case DataField.Bottom:
|
||
return SeriesChartType.Range;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Maps formula data field to a chart type specific data field.
|
||
/// </summary>
|
||
/// <param name="chartType">Type of the chart.</param>
|
||
/// <param name="formulaField">The formula field to be mapped.</param>
|
||
/// <returns>The series field</returns>
|
||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
|
||
internal static DataField? MapFormulaDataField(SeriesChartType chartType, DataField formulaField)
|
||
{
|
||
switch (formulaField)
|
||
{
|
||
case DataField.Top:
|
||
case DataField.High:
|
||
switch (chartType)
|
||
{
|
||
default: return null;
|
||
case SeriesChartType.BoxPlot: return DataField.UpperBox;
|
||
case SeriesChartType.Candlestick:
|
||
case SeriesChartType.Stock: return DataField.High;
|
||
case SeriesChartType.ErrorBar: return DataField.UpperError;
|
||
case SeriesChartType.RangeBar:
|
||
case SeriesChartType.Range:
|
||
case SeriesChartType.RangeColumn:
|
||
case SeriesChartType.SplineRange: return DataField.Top;
|
||
}
|
||
|
||
case DataField.Bottom:
|
||
case DataField.Low:
|
||
switch (chartType)
|
||
{
|
||
default: return null;
|
||
case SeriesChartType.BoxPlot: return DataField.LowerBox;
|
||
case SeriesChartType.Candlestick:
|
||
case SeriesChartType.Stock: return DataField.Low;
|
||
case SeriesChartType.ErrorBar: return DataField.LowerError;
|
||
case SeriesChartType.RangeBar:
|
||
case SeriesChartType.Range:
|
||
case SeriesChartType.RangeColumn:
|
||
case SeriesChartType.SplineRange: return DataField.Bottom;
|
||
}
|
||
|
||
case DataField.Open:
|
||
switch (chartType)
|
||
{
|
||
default: return null;
|
||
case SeriesChartType.BoxPlot: return DataField.Average;
|
||
case SeriesChartType.Candlestick:
|
||
case SeriesChartType.Stock: return DataField.Open;
|
||
case SeriesChartType.ErrorBar: return DataField.Center;
|
||
case SeriesChartType.RangeBar:
|
||
case SeriesChartType.Range:
|
||
case SeriesChartType.RangeColumn:
|
||
case SeriesChartType.SplineRange: return DataField.Bottom;
|
||
}
|
||
|
||
case DataField.Close:
|
||
case DataField.Y:
|
||
switch (chartType)
|
||
{
|
||
default: return DataField.Y;
|
||
case SeriesChartType.BoxPlot: return DataField.Average;
|
||
case SeriesChartType.Bubble: return DataField.Bubble;
|
||
case SeriesChartType.Candlestick:
|
||
case SeriesChartType.Stock: return DataField.Close;
|
||
case SeriesChartType.ErrorBar: return DataField.Center;
|
||
case SeriesChartType.RangeBar:
|
||
case SeriesChartType.Range:
|
||
case SeriesChartType.RangeColumn:
|
||
case SeriesChartType.SplineRange: return DataField.Top;
|
||
}
|
||
default:
|
||
return null;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
#endregion
|
||
|
||
#region class FormulaInfo and inherited FormulaSpecific classes
|
||
|
||
/// <summary>
|
||
/// This a base class of the formula metainfo classes.
|
||
/// </summary>
|
||
internal abstract class FormulaInfo
|
||
{
|
||
#region Fields
|
||
DataField[] _inputFields;
|
||
DataField[] _outputFields;
|
||
object[] _parameters;
|
||
#endregion
|
||
|
||
#region Properties
|
||
/// <summary>
|
||
/// Gets the input data fields of the formula.
|
||
/// </summary>
|
||
/// <value>The input fields.</value>
|
||
public DataField[] InputFields
|
||
{
|
||
get { return _inputFields; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets the output data fields of the formula.
|
||
/// </summary>
|
||
/// <value>The output fields.</value>
|
||
public DataField[] OutputFields
|
||
{
|
||
get { return _outputFields; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets the parameters of the formula.
|
||
/// </summary>
|
||
/// <value>The parameters.</value>
|
||
public object[] Parameters
|
||
{
|
||
get { return _parameters; }
|
||
}
|
||
#endregion
|
||
|
||
#region Constructors
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="FormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="inputFields">The input data fields.</param>
|
||
/// <param name="outputFields">The output data fields.</param>
|
||
/// <param name="defaultParams">The default formula params.</param>
|
||
public FormulaInfo(DataField[] inputFields, DataField[] outputFields, params object[] defaultParams)
|
||
{
|
||
_inputFields = inputFields;
|
||
_outputFields = outputFields;
|
||
_parameters = defaultParams;
|
||
}
|
||
#endregion
|
||
|
||
#region Methods
|
||
/// <summary>
|
||
/// Saves the formula parameters to a string.
|
||
/// </summary>
|
||
/// <returns>Csv string with parameters</returns>
|
||
internal virtual string SaveParametersToString()
|
||
{
|
||
StringBuilder sb = new StringBuilder();
|
||
for (int i = 0; i < _parameters.Length; i++)
|
||
{
|
||
if (i > 0) sb.Append(',');
|
||
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", _parameters[i]);
|
||
}
|
||
return sb.ToString();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Loads the formula parameters from string.
|
||
/// </summary>
|
||
/// <param name="parameters">Csv string with parameters.</param>
|
||
internal virtual void LoadParametersFromString(string parameters)
|
||
{
|
||
if (String.IsNullOrEmpty(parameters))
|
||
return;
|
||
|
||
string[] paramStringList = parameters.Split(',');
|
||
int paramStringIndex = 0;
|
||
for (int i = 0; i < _parameters.Length && paramStringIndex < paramStringList.Length; i++)
|
||
{
|
||
string newParamValue = paramStringList[paramStringIndex++];
|
||
if (!String.IsNullOrEmpty(newParamValue))
|
||
{
|
||
_parameters[i] = ParseParameter(i, newParamValue);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Parses the formula parameter.
|
||
/// </summary>
|
||
/// <param name="index">The param index.</param>
|
||
/// <param name="newParamValue">The parameter value string.</param>
|
||
/// <returns>Parameter value.</returns>
|
||
internal virtual object ParseParameter(int index, string newParamValue)
|
||
{
|
||
object param = _parameters[index];
|
||
if (param is int)
|
||
{
|
||
return Convert.ToInt32(newParamValue, CultureInfo.InvariantCulture);
|
||
}
|
||
else if (param is bool)
|
||
{
|
||
return Convert.ToBoolean(newParamValue, CultureInfo.InvariantCulture);
|
||
}
|
||
else if (param is double)
|
||
{
|
||
return Convert.ToDouble(newParamValue, CultureInfo.InvariantCulture);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Checks the formula parameter string.
|
||
/// </summary>
|
||
/// <param name="parameters">The parameters.</param>
|
||
internal virtual void CheckParameterString(string parameters)
|
||
{
|
||
if (String.IsNullOrEmpty(parameters))
|
||
return;
|
||
|
||
string[] paramStringList = parameters.Split(',');
|
||
int paramStringIndex = 0;
|
||
for (int i = 0; i < _parameters.Length && paramStringIndex < paramStringList.Length; i++)
|
||
{
|
||
string newParamValue = paramStringList[paramStringIndex++];
|
||
if (!String.IsNullOrEmpty(newParamValue))
|
||
{
|
||
try
|
||
{
|
||
ParseParameter(i, newParamValue);
|
||
}
|
||
catch (FormatException)
|
||
{
|
||
throw new ArgumentException(SR.ExceptionFormulaDataFormatInvalid(parameters));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// MovingAverage FormulaInfo
|
||
/// </summary>
|
||
internal class MovingAverageFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
public MovingAverageFormulaInfo()
|
||
: this(2, false) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public MovingAverageFormulaInfo(int period, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ExponentialMoving AverageFormulaInfo
|
||
/// </summary>
|
||
internal class ExponentialMovingAverageFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="ExponentialMovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
public ExponentialMovingAverageFormulaInfo()
|
||
: this(2, false) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="ExponentialMovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public ExponentialMovingAverageFormulaInfo(int period, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// WeightedMovingAverageFormulaInfo
|
||
/// </summary>
|
||
internal class WeightedMovingAverageFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="WeightedMovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
public WeightedMovingAverageFormulaInfo()
|
||
: this(2, false) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="WeightedMovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public WeightedMovingAverageFormulaInfo(int period, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// TriangularMovingAverage FormulaInfo
|
||
/// </summary>
|
||
internal class TriangularMovingAverageFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="TriangularMovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
public TriangularMovingAverageFormulaInfo()
|
||
: this(2, false) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="TriangularMovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public TriangularMovingAverageFormulaInfo(int period, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// TripleExponentialMovingAverage FormulaInfo
|
||
/// </summary>
|
||
internal class TripleExponentialMovingAverageFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="TripleExponentialMovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
public TripleExponentialMovingAverageFormulaInfo()
|
||
: this(12) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="TripleExponentialMovingAverageFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
public TripleExponentialMovingAverageFormulaInfo(int period)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// BollingerBands FormulaInfo
|
||
/// </summary>
|
||
internal class BollingerBandsFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="BollingerBandsFormulaInfo"/> class.
|
||
/// </summary>
|
||
public BollingerBandsFormulaInfo()
|
||
: this(3, 2, true) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="BollingerBandsFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="deviation">The deviation.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public BollingerBandsFormulaInfo(int period, double deviation, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Top, DataField.Bottom }, //Output fields
|
||
period, deviation, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// TypicalPrice FormulaInfo
|
||
/// </summary>
|
||
internal class TypicalPriceFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="TypicalPriceFormulaInfo"/> class.
|
||
/// </summary>
|
||
public TypicalPriceFormulaInfo()
|
||
: base(
|
||
new DataField[] { DataField.Close, DataField.High, DataField.Low }, //Input fields
|
||
new DataField[] { DataField.Y }) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// WeightedClose FormulaInfo
|
||
/// </summary>
|
||
internal class WeightedCloseFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="WeightedCloseFormulaInfo"/> class.
|
||
/// </summary>
|
||
public WeightedCloseFormulaInfo()
|
||
: base(
|
||
new DataField[] { DataField.Close, DataField.High, DataField.Low }, //Input fields
|
||
new DataField[] { DataField.Y }) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// MedianPrice FormulaInfo
|
||
/// </summary>
|
||
internal class MedianPriceFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MedianPriceFormulaInfo"/> class.
|
||
/// </summary>
|
||
public MedianPriceFormulaInfo()
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low }, //Input fields
|
||
new DataField[] { DataField.Y }) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Envelopes FormulaInfo
|
||
/// </summary>
|
||
internal class EnvelopesFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="EnvelopesFormulaInfo"/> class.
|
||
/// </summary>
|
||
public EnvelopesFormulaInfo()
|
||
: this(2, 10, true) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="EnvelopesFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="shiftPercentage">The shift percentage.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public EnvelopesFormulaInfo(int period, double shiftPercentage, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Top, DataField.Bottom }, //Output fields
|
||
period, shiftPercentage, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// StandardDeviation FormulaInfo
|
||
/// </summary>
|
||
internal class StandardDeviationFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="StandardDeviationFormulaInfo"/> class.
|
||
/// </summary>
|
||
public StandardDeviationFormulaInfo()
|
||
: this(2, false) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="StandardDeviationFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public StandardDeviationFormulaInfo(int period, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ChaikinOscillatorFormulaInfo
|
||
/// </summary>
|
||
internal class ChaikinOscillatorFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="ChaikinOscillatorFormulaInfo"/> class.
|
||
/// </summary>
|
||
public ChaikinOscillatorFormulaInfo()
|
||
: this(3, 10, false) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="ChaikinOscillatorFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="shortPeriod">The short period.</param>
|
||
/// <param name="longPeriod">The long period.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public ChaikinOscillatorFormulaInfo(int shortPeriod, int longPeriod, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low, DataField.Close, DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
shortPeriod, longPeriod, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// DetrendedPriceOscillator FormulaInfo
|
||
/// </summary>
|
||
internal class DetrendedPriceOscillatorFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="DetrendedPriceOscillatorFormulaInfo"/> class.
|
||
/// </summary>
|
||
public DetrendedPriceOscillatorFormulaInfo()
|
||
: this(2, false) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="DetrendedPriceOscillatorFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="startFromFirst">if set to <c>true</c> [start from first].</param>
|
||
public DetrendedPriceOscillatorFormulaInfo(int period, bool startFromFirst)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period, startFromFirst)
|
||
{
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// VolatilityChaikins FormulaInfo
|
||
/// </summary>
|
||
internal class VolatilityChaikinsFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="VolatilityChaikinsFormulaInfo"/> class.
|
||
/// </summary>
|
||
public VolatilityChaikinsFormulaInfo()
|
||
: this(10, 10) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="VolatilityChaikinsFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="signalPeriod">The signal period.</param>
|
||
public VolatilityChaikinsFormulaInfo(int period, int signalPeriod)
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period, signalPeriod)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// VolumeOscillator FormulaInfo
|
||
/// </summary>
|
||
internal class VolumeOscillatorFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="VolumeOscillatorFormulaInfo"/> class.
|
||
/// </summary>
|
||
public VolumeOscillatorFormulaInfo()
|
||
: this(5, 10, true) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="VolumeOscillatorFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="shortPeriod">The short period.</param>
|
||
/// <param name="longPeriod">The long period.</param>
|
||
/// <param name="percentage">if set to <c>true</c> [percentage].</param>
|
||
public VolumeOscillatorFormulaInfo(int shortPeriod, int longPeriod, bool percentage)
|
||
: base(
|
||
new DataField[] { DataField.Y }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
shortPeriod, longPeriod, percentage)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// StochasticIndicatorFormulaInfo
|
||
/// </summary>
|
||
internal class StochasticIndicatorFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="StochasticIndicatorFormulaInfo"/> class.
|
||
/// </summary>
|
||
public StochasticIndicatorFormulaInfo()
|
||
: this(10, 10) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="StochasticIndicatorFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="periodD">The period D.</param>
|
||
/// <param name="periodK">The period K.</param>
|
||
public StochasticIndicatorFormulaInfo(int periodD, int periodK)
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low, DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y, DataField.Y }, //Output fields
|
||
periodD, periodK)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// WilliamsRFormulaInfo
|
||
/// </summary>
|
||
internal class WilliamsRFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="WilliamsRFormulaInfo"/> class.
|
||
/// </summary>
|
||
public WilliamsRFormulaInfo()
|
||
: this(14) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="WilliamsRFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
public WilliamsRFormulaInfo(int period)
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low, DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// AverageTrueRange FormulaInfo
|
||
/// </summary>
|
||
internal class AverageTrueRangeFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="AverageTrueRangeFormulaInfo"/> class.
|
||
/// </summary>
|
||
public AverageTrueRangeFormulaInfo()
|
||
: this(14) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="AverageTrueRangeFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
public AverageTrueRangeFormulaInfo(int period)
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low, DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// EaseOfMovement FormulaInfo
|
||
/// </summary>
|
||
internal class EaseOfMovementFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="EaseOfMovementFormulaInfo"/> class.
|
||
/// </summary>
|
||
public EaseOfMovementFormulaInfo()
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low, DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y }) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// MassIndex FormulaInfo
|
||
/// </summary>
|
||
internal class MassIndexFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MassIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
public MassIndexFormulaInfo()
|
||
: this(25, 9) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MassIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
/// <param name="averagePeriod">The average period.</param>
|
||
public MassIndexFormulaInfo(int period, int averagePeriod)
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period, averagePeriod)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Performance FormulaInfo
|
||
/// </summary>
|
||
internal class PerformanceFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="PerformanceFormulaInfo"/> class.
|
||
/// </summary>
|
||
public PerformanceFormulaInfo()
|
||
: base(
|
||
new DataField[] { DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y }) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// RateOfChange FormulaInfo
|
||
/// </summary>
|
||
internal class RateOfChangeFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="RateOfChangeFormulaInfo"/> class.
|
||
/// </summary>
|
||
public RateOfChangeFormulaInfo()
|
||
: this(10) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="RateOfChangeFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
public RateOfChangeFormulaInfo(int period)
|
||
: base(
|
||
new DataField[] { DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// RelativeStrengthIndex FormulaInfo
|
||
/// </summary>
|
||
internal class RelativeStrengthIndexFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="RelativeStrengthIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
public RelativeStrengthIndexFormulaInfo()
|
||
: this(10) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="RelativeStrengthIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
public RelativeStrengthIndexFormulaInfo(int period)
|
||
: base(
|
||
new DataField[] { DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// MovingAverageConvergenceDivergence FormulaInfo
|
||
/// </summary>
|
||
internal class MovingAverageConvergenceDivergenceFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MovingAverageConvergenceDivergenceFormulaInfo"/> class.
|
||
/// </summary>
|
||
public MovingAverageConvergenceDivergenceFormulaInfo()
|
||
: this(12, 26) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MovingAverageConvergenceDivergenceFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="shortPeriod">The short period.</param>
|
||
/// <param name="longPeriod">The long period.</param>
|
||
public MovingAverageConvergenceDivergenceFormulaInfo(int shortPeriod, int longPeriod)
|
||
: base(
|
||
new DataField[] { DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
shortPeriod, longPeriod)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// CommodityChannelIndex FormulaInfo
|
||
/// </summary>
|
||
internal class CommodityChannelIndexFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="CommodityChannelIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
public CommodityChannelIndexFormulaInfo()
|
||
: this(10) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="CommodityChannelIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
public CommodityChannelIndexFormulaInfo(int period)
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low, DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Forecasting FormulaInfo
|
||
/// </summary>
|
||
internal class ForecastingFormulaInfo : FormulaInfo
|
||
{
|
||
//Fields
|
||
string _parameters;
|
||
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="ForecastingFormulaInfo"/> class.
|
||
/// </summary>
|
||
public ForecastingFormulaInfo()
|
||
: this(TimeSeriesAndForecasting.RegressionType.Polynomial, 2, 0, true, true) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="ForecastingFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="regressionType">Type of the regression.</param>
|
||
/// <param name="polynomialDegree">The polynomial degree.</param>
|
||
/// <param name="forecastingPeriod">The forecasting period.</param>
|
||
/// <param name="returnApproximationError">if set to <c>true</c> [return approximation error].</param>
|
||
/// <param name="returnForecastingError">if set to <c>true</c> [return forecasting error].</param>
|
||
public ForecastingFormulaInfo(TimeSeriesAndForecasting.RegressionType regressionType, int polynomialDegree, int forecastingPeriod, bool returnApproximationError, bool returnForecastingError)
|
||
: base(
|
||
new DataField[] { DataField.Close }, //Input fields
|
||
new DataField[] { DataField.Close, DataField.High, DataField.Low }, //Output fields
|
||
regressionType, polynomialDegree, forecastingPeriod, returnApproximationError, returnForecastingError)
|
||
{
|
||
}
|
||
|
||
//Methods
|
||
/// <summary>
|
||
/// Loads the formula parameters from string.
|
||
/// </summary>
|
||
/// <param name="parameters">Csv string with parameters.</param>
|
||
internal override void LoadParametersFromString(string parameters)
|
||
{
|
||
_parameters = parameters;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Checks the formula parameter string.
|
||
/// </summary>
|
||
/// <param name="parameters">The parameters.</param>
|
||
internal override void CheckParameterString(string parameters)
|
||
{
|
||
if (String.IsNullOrEmpty(parameters))
|
||
return;
|
||
|
||
string[] paramStringList = parameters.Split(',');
|
||
int paramStringIndex = 1;
|
||
//Don't check the first param
|
||
for (int i = 2; i < Parameters.Length && paramStringIndex < paramStringList.Length; i++)
|
||
{
|
||
string newParamValue = paramStringList[paramStringIndex++];
|
||
if (!String.IsNullOrEmpty(newParamValue))
|
||
{
|
||
try
|
||
{
|
||
ParseParameter(i, newParamValue);
|
||
}
|
||
catch (FormatException)
|
||
{
|
||
throw new ArgumentException(SR.ExceptionFormulaDataFormatInvalid(parameters));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Saves the formula parameters to a string.
|
||
/// </summary>
|
||
/// <returns>Csv string with parameters</returns>
|
||
internal override string SaveParametersToString()
|
||
{
|
||
if (String.IsNullOrEmpty(_parameters))
|
||
return _parameters;
|
||
else
|
||
return "2,0,true,true";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// MoneyFlow FormulaInfo
|
||
/// </summary>
|
||
internal class MoneyFlowFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MoneyFlowFormulaInfo"/> class.
|
||
/// </summary>
|
||
public MoneyFlowFormulaInfo()
|
||
: this(2) //Defaults
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="MoneyFlowFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="period">The period.</param>
|
||
public MoneyFlowFormulaInfo(int period)
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low, DataField.Close, DataField.Y }, //Input fields: High,Low,Close,Volume
|
||
new DataField[] { DataField.Y }, //Output fields
|
||
period)
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// PriceVolumeTrend FormulaInfo
|
||
/// </summary>
|
||
internal class PriceVolumeTrendFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="PriceVolumeTrendFormulaInfo"/> class.
|
||
/// </summary>
|
||
public PriceVolumeTrendFormulaInfo()
|
||
: base(
|
||
new DataField[] { DataField.Close, DataField.Y }, //Input=Close,Volume
|
||
new DataField[] { DataField.Y }) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// OnBalanceVolume FormulaInfo
|
||
/// </summary>
|
||
internal class OnBalanceVolumeFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="OnBalanceVolumeFormulaInfo"/> class.
|
||
/// </summary>
|
||
public OnBalanceVolumeFormulaInfo()
|
||
: base(
|
||
new DataField[] { DataField.Close, DataField.Y }, //Input=Close,Volume
|
||
new DataField[] { DataField.Y }) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// NegativeVolumeIndex FormulaInfo
|
||
/// </summary>
|
||
internal class NegativeVolumeIndexFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="NegativeVolumeIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
public NegativeVolumeIndexFormulaInfo() //Note about parameters: Start value is mandatory so we don't provide the default
|
||
: this(double.NaN)
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="NegativeVolumeIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="startValue">The start value.</param>
|
||
public NegativeVolumeIndexFormulaInfo(double startValue)
|
||
: base(
|
||
new DataField[] { DataField.Close, DataField.Y }, //Input=Close,Volume
|
||
new DataField[] { DataField.Y },
|
||
startValue) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// PositiveVolumeIndex FormulaInfo
|
||
/// </summary>
|
||
internal class PositiveVolumeIndexFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="PositiveVolumeIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
public PositiveVolumeIndexFormulaInfo() //Note about parameters: Start value is mandatory so we don't provide the default
|
||
: this(double.NaN)
|
||
{
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="PositiveVolumeIndexFormulaInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="startValue">The start value.</param>
|
||
public PositiveVolumeIndexFormulaInfo(double startValue)
|
||
: base(
|
||
new DataField[] { DataField.Close, DataField.Y }, //Input=Close,Volume
|
||
new DataField[] { DataField.Y },
|
||
startValue) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// AccumulationDistribution FormulaInfo
|
||
/// </summary>
|
||
internal class AccumulationDistributionFormulaInfo : FormulaInfo
|
||
{
|
||
//Constructor
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="AccumulationDistributionFormulaInfo"/> class.
|
||
/// </summary>
|
||
public AccumulationDistributionFormulaInfo() //Note about parameters: Start value is mandatory so we don't provide the default
|
||
: base(
|
||
new DataField[] { DataField.High, DataField.Low, DataField.Close, DataField.Y }, //Input=High, Low, Close, Volume
|
||
new DataField[] { DataField.Y }) //Output fields
|
||
{
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region enum DataField
|
||
/// <summary>
|
||
/// Chart data fields
|
||
/// </summary>
|
||
internal enum DataField
|
||
{
|
||
X,
|
||
Y,
|
||
LowerWisker,
|
||
UpperWisker,
|
||
LowerBox,
|
||
UpperBox,
|
||
Average,
|
||
Median,
|
||
Bubble,
|
||
BubbleSize,
|
||
High,
|
||
Low,
|
||
Open,
|
||
Close,
|
||
Center,
|
||
LowerError,
|
||
UpperError,
|
||
Top,
|
||
Bottom
|
||
}
|
||
#endregion
|
||
|
||
#region class SeriesFieldInfo
|
||
/// <summary>
|
||
/// SeriesFieldInfo class is a OO representation formula input/output data params ("Series1:Y2")
|
||
/// </summary>
|
||
internal class SeriesFieldInfo
|
||
{
|
||
#region Fields
|
||
private Series _series;
|
||
private string _seriesName;
|
||
private DataField _dataField;
|
||
#endregion
|
||
|
||
#region Properties
|
||
/// <summary>
|
||
/// Gets the series.
|
||
/// </summary>
|
||
/// <value>The series.</value>
|
||
public Series Series
|
||
{
|
||
get { return _series; }
|
||
}
|
||
/// <summary>
|
||
/// Gets the name of the series.
|
||
/// </summary>
|
||
/// <value>The name of the series.</value>
|
||
public string SeriesName
|
||
{
|
||
get { return _series != null ? _series.Name : _seriesName; }
|
||
}
|
||
/// <summary>
|
||
/// Gets the data field.
|
||
/// </summary>
|
||
/// <value>The data field.</value>
|
||
public DataField DataField
|
||
{
|
||
get { return _dataField; }
|
||
}
|
||
#endregion
|
||
|
||
#region Constructors
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="SeriesFieldInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="series">The series.</param>
|
||
/// <param name="dataField">The data field.</param>
|
||
public SeriesFieldInfo(Series series, DataField dataField)
|
||
{
|
||
_series = series;
|
||
_dataField = dataField;
|
||
}
|
||
/// <summary>
|
||
/// Initializes a new instance of the <see cref="SeriesFieldInfo"/> class.
|
||
/// </summary>
|
||
/// <param name="seriesName">Name of the series.</param>
|
||
/// <param name="dataField">The data field.</param>
|
||
public SeriesFieldInfo(string seriesName, DataField dataField)
|
||
{
|
||
_seriesName = seriesName;
|
||
_dataField = dataField;
|
||
}
|
||
#endregion
|
||
}
|
||
#endregion
|
||
|
||
#region class SeriesFieldList
|
||
/// <summary>
|
||
/// SeriesFieldInfo class is a OO representation formula input/output data params ("Series1:Y2,Series2.Y4")
|
||
/// </summary>
|
||
internal class SeriesFieldList : List<SeriesFieldInfo>
|
||
{
|
||
/// <summary>
|
||
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
|
||
/// </summary>
|
||
/// <returns>
|
||
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
|
||
/// </returns>
|
||
public override string ToString()
|
||
{
|
||
StringBuilder sb = new StringBuilder();
|
||
for (int i = 0; i < this.Count; i++)
|
||
{
|
||
SeriesFieldInfo info = this[i];
|
||
|
||
if (i > 0)
|
||
sb.Append(',');
|
||
|
||
SeriesChartType seriesChartType = info.Series != null ?
|
||
info.Series.ChartType :
|
||
FormulaHelper.GetDefaultChartType(info.DataField);
|
||
|
||
IList<DataField> dataFields = FormulaHelper.GetDataFields(seriesChartType);
|
||
|
||
int dataFieldIndex = dataFields.IndexOf(info.DataField);
|
||
if (dataFieldIndex == 0)
|
||
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}:Y", info.SeriesName); //The string field descriptor is 1 based ;-(
|
||
else
|
||
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}:Y{1}", info.SeriesName, dataFieldIndex + 1); //The string field descriptor is 1 based ;-(
|
||
}
|
||
return sb.ToString();
|
||
}
|
||
|
||
//Static
|
||
/// <summary>
|
||
/// Parse the string defining the formula's input/output series and fields.
|
||
/// </summary>
|
||
/// <param name="chart">The chart.</param>
|
||
/// <param name="seriesFields">The series fields list. The series name can be followed by the field names. For example: "Series1:Y,Series1:Y3,Series2:Close"</param>
|
||
/// <param name="formulaFields">The formula fields list.</param>
|
||
/// <returns></returns>
|
||
public static SeriesFieldList FromString(Chart chart, string seriesFields, IList<DataField> formulaFields)
|
||
{
|
||
SeriesFieldList result = new SeriesFieldList();
|
||
if (String.IsNullOrEmpty(seriesFields))
|
||
{
|
||
return result;
|
||
}
|
||
|
||
List<DataField> unmappedFormulaFields = new List<DataField>(formulaFields);
|
||
|
||
//Loop through the series/field pairs
|
||
foreach (string seriesField in seriesFields.Split(','))
|
||
{
|
||
//Stop processing if all the formula fields are mapped
|
||
if (unmappedFormulaFields.Count == 0)
|
||
break;
|
||
|
||
//Split a pair into a series + field
|
||
string[] seriesFieldParts = seriesField.Split(':');
|
||
if (seriesFieldParts.Length > 2)
|
||
{
|
||
throw new ArgumentException(SR.ExceptionFormulaDataFormatInvalid(seriesField));
|
||
}
|
||
|
||
//Get the series and series fields
|
||
string seriesName = seriesFieldParts[0].Trim();
|
||
Series series = chart.Series.FindByName(seriesName);
|
||
if (series != null)
|
||
{
|
||
switch (seriesFieldParts.Length)
|
||
{
|
||
case 1: //Only series name is specified: "Series1"
|
||
AddSeriesFieldInfo(result, series, unmappedFormulaFields);
|
||
break;
|
||
case 2: //Series and field names are provided: "Series1:Y3"
|
||
AddSeriesFieldInfo(result, series, unmappedFormulaFields, seriesFieldParts[1]);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
switch (seriesFieldParts.Length)
|
||
{
|
||
case 1: //Only series name is specified: "Series1"
|
||
AddSeriesFieldInfo(result, seriesName, unmappedFormulaFields);
|
||
break;
|
||
case 2: //Series and field names are provided: "Series1:Y3"
|
||
AddSeriesFieldInfo(result, seriesName, unmappedFormulaFields, seriesFieldParts[1]);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds the series field info.
|
||
/// </summary>
|
||
/// <param name="result">The result.</param>
|
||
/// <param name="series">The series.</param>
|
||
/// <param name="unmappedFormulaFields">The unmapped formula fields.</param>
|
||
private static void AddSeriesFieldInfo(SeriesFieldList result, Series series, IList<DataField> unmappedFormulaFields)
|
||
{
|
||
List<DataField> seriesFields = new List<DataField>(FormulaHelper.GetDataFields(series.ChartType));
|
||
|
||
for (int i = 0; i < unmappedFormulaFields.Count && seriesFields.Count > 0; )
|
||
{
|
||
DataField formulaField = unmappedFormulaFields[i];
|
||
DataField? seriesField = null;
|
||
|
||
// Case 1. Check if the formulaField is valid for this chart type
|
||
if (seriesFields.Contains(formulaField))
|
||
{
|
||
seriesField = formulaField;
|
||
}
|
||
// Case 2. Try to map the formula field to the series field
|
||
if (seriesField == null)
|
||
{
|
||
seriesField = FormulaHelper.MapFormulaDataField(series.ChartType, formulaField);
|
||
}
|
||
|
||
// If the seriesField is found - add it to the results
|
||
if (seriesField != null)
|
||
{
|
||
result.Add(new SeriesFieldInfo(series, (DataField)seriesField));
|
||
seriesFields.Remove((DataField)formulaField);
|
||
unmappedFormulaFields.Remove(formulaField);
|
||
}
|
||
else
|
||
{
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// Adds the series field info.
|
||
/// </summary>
|
||
/// <param name="result">The result.</param>
|
||
/// <param name="series">The series.</param>
|
||
/// <param name="unmappedFormulaFields">The unmapped formula fields.</param>
|
||
/// <param name="seriesFieldId">The series field id.</param>
|
||
private static void AddSeriesFieldInfo(SeriesFieldList result, Series series, IList<DataField> unmappedFormulaFields, string seriesFieldId)
|
||
{
|
||
IList<DataField> seriesFields = FormulaHelper.GetDataFields(series.ChartType);
|
||
|
||
DataField? seriesField = null;
|
||
|
||
seriesFieldId = seriesFieldId.ToUpperInvariant().Trim();
|
||
if (seriesFieldId == "Y")
|
||
{
|
||
seriesField = seriesFields[0];
|
||
}
|
||
else if (seriesFieldId.StartsWith("Y", StringComparison.Ordinal))
|
||
{
|
||
int id = 0;
|
||
if (int.TryParse(seriesFieldId.Substring(1), out id))
|
||
if (id - 1 < seriesFields.Count)
|
||
{
|
||
seriesField = seriesFields[id - 1];
|
||
}
|
||
else
|
||
{
|
||
throw (new ArgumentException(SR.ExceptionFormulaYIndexInvalid, seriesFieldId));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
seriesField = (DataField)Enum.Parse(typeof(DataField), seriesFieldId, true);
|
||
}
|
||
|
||
// Add the seriesField to the results
|
||
if (seriesField != null)
|
||
{
|
||
result.Add(new SeriesFieldInfo(series, (DataField)seriesField));
|
||
if (unmappedFormulaFields.Contains((DataField)seriesField))
|
||
unmappedFormulaFields.Remove((DataField)seriesField);
|
||
else
|
||
unmappedFormulaFields.RemoveAt(0);
|
||
}
|
||
else
|
||
{
|
||
throw new ArgumentException(SR.ExceptionDataPointValueNameInvalid, seriesFieldId);
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds the series field info.
|
||
/// </summary>
|
||
/// <param name="result">The result.</param>
|
||
/// <param name="seriesName">Name of the series.</param>
|
||
/// <param name="unmappedFormulaFields">The unmapped formula fields.</param>
|
||
private static void AddSeriesFieldInfo(SeriesFieldList result, string seriesName, IList<DataField> unmappedFormulaFields)
|
||
{
|
||
SeriesChartType chartType = FormulaHelper.GetDefaultChartType(unmappedFormulaFields[0]);
|
||
List<DataField> seriesFields = new List<DataField>(FormulaHelper.GetDataFields(chartType));
|
||
|
||
for (int i = 0; i < unmappedFormulaFields.Count && seriesFields.Count > 0; )
|
||
{
|
||
DataField formulaField = unmappedFormulaFields[i];
|
||
DataField? seriesField = null;
|
||
|
||
// Check if the formulaField is valid for this chart type
|
||
if (seriesFields.Contains(formulaField))
|
||
{
|
||
seriesField = formulaField;
|
||
}
|
||
|
||
// If the seriesField is found - add it to the results
|
||
if (seriesField != null)
|
||
{
|
||
result.Add(new SeriesFieldInfo(seriesName, (DataField)seriesField));
|
||
seriesFields.Remove((DataField)formulaField);
|
||
unmappedFormulaFields.Remove(formulaField);
|
||
}
|
||
else
|
||
{
|
||
i++;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// Adds the series field info.
|
||
/// </summary>
|
||
/// <param name="result">The result.</param>
|
||
/// <param name="seriesName">Name of the series.</param>
|
||
/// <param name="unmappedFormulaFields">The unmapped formula fields.</param>
|
||
/// <param name="seriesFieldId">The series field id.</param>
|
||
private static void AddSeriesFieldInfo(SeriesFieldList result, string seriesName, IList<DataField> unmappedFormulaFields, string seriesFieldId)
|
||
{
|
||
SeriesChartType chartType = FormulaHelper.GetDefaultChartType(unmappedFormulaFields[0]);
|
||
IList<DataField> seriesFields = FormulaHelper.GetDataFields(chartType);
|
||
|
||
//Find the field
|
||
DataField? seriesField = null;
|
||
|
||
seriesFieldId = seriesFieldId.ToUpperInvariant().Trim();
|
||
|
||
if (seriesFieldId == "Y")
|
||
{
|
||
seriesField = seriesFields[0];
|
||
}
|
||
else if (seriesFieldId.StartsWith("Y", StringComparison.Ordinal))
|
||
{
|
||
int seriesFieldIndex = 0;
|
||
if (int.TryParse(seriesFieldId.Substring(1), out seriesFieldIndex))
|
||
if (seriesFieldIndex < seriesFields.Count)
|
||
{
|
||
seriesField = seriesFields[seriesFieldIndex - 1];
|
||
}
|
||
else
|
||
{
|
||
throw (new ArgumentException(SR.ExceptionFormulaYIndexInvalid, seriesFieldId));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//Try parse the field name
|
||
try
|
||
{
|
||
seriesField = (DataField)Enum.Parse(typeof(DataField), seriesFieldId, true);
|
||
}
|
||
catch (ArgumentException)
|
||
{ }
|
||
}
|
||
|
||
if (seriesField != null)
|
||
{
|
||
result.Add(new SeriesFieldInfo(seriesName, (DataField)seriesField));
|
||
unmappedFormulaFields.Remove((DataField)seriesField);
|
||
}
|
||
else
|
||
{
|
||
throw new ArgumentException(SR.ExceptionDataPointValueNameInvalid, seriesFieldId);
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
}
|
||
|