Xamarin Public Jenkins (auto-signing) 536cd135cc Imported Upstream version 5.4.0.167
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
2017-08-21 15:34:15 +00:00

1637 lines
62 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//-------------------------------------------------------------
// <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
}