123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- // See the LICENSE file in the project root for more information.
- //
- // Purpose: This class is used to calculate oscillator
- // indicators used in Technical Analyses.
- //
- using System;
- using System.Globalization;
- namespace FastReport.DataVisualization.Charting.Formulas
- {
- /// <summary>
- /// This class is used to calculate oscillator
- /// indicators used in Technical Analyses.
- /// </summary>
- internal class Oscillators : PriceIndicators
- {
- #region Properties
- /// <summary>
- /// Formula Module name
- /// </summary>
- override public string Name { get{ return "Oscillators";}}
- #endregion
- #region Formulas
- /// <summary>
- /// The Chaikin Oscillator is created by subtracting a 10 period
- /// exponential moving average of the Accumulation/Distribution
- /// line from a 3 period moving average of the
- /// Accumulation/Distribution Line.
- /// ---------------------------------------------------------
- /// Input:
- /// - 4 Y values ( Hi, Low, Close, Volume ).
- /// Output:
- /// - 1 Y value Chaikin Oscillator
- /// Parameters:
- /// - Short Period for Exponential Moving average (default=3)
- /// - Int64 Period for Exponential Moving average (default=10)
- /// Extra Parameters:
- /// - Start from First
- /// </summary>
- /// <param name="inputValues">Arrays of doubles - Input values</param>
- /// <param name="outputValues">Arrays of doubles - Output values</param>
- /// <param name="parameterList">Array of strings - Parameters</param>
- /// <param name="extraParameterList">Array of strings - Extra parameters</param>
- private void ChaikinOscillator(double [][] inputValues, out double [][] outputValues, string [] parameterList, string [] extraParameterList)
- {
- // There is no enough input series
- if( inputValues.Length != 5 )
- {
- throw new ArgumentException( SR.ExceptionPriceIndicatorsFormulaRequiresFourArrays);
- }
-
- // Different number of x and y values
- CheckNumOfValues( inputValues, 4 );
- // Short Period for Exp moving average
- int shortPeriod;
- if (parameterList.Length < 1 ||
- !int.TryParse(parameterList[0], NumberStyles.Any, CultureInfo.InvariantCulture, out shortPeriod))
- {
- shortPeriod = 3;
- }
-
- // Int64 Period for Exp moving average
- int longPeriod;
- if (parameterList.Length < 2 ||
- !int.TryParse(parameterList[1], NumberStyles.Any, CultureInfo.InvariantCulture, out longPeriod))
- {
- longPeriod = 10;
- }
- if( shortPeriod > longPeriod || longPeriod <= 0 || shortPeriod <= 0 )
- {
- throw new ArgumentException(SR.ExceptionOscillatorObjectInvalidPeriod);
- }
- // Starting average from the first data point or after period.
- bool startFromFirst = bool.Parse( extraParameterList[0] );
- VolumeIndicators volume = new VolumeIndicators();
- double [][] outputDistribution = new double [2][];
- // Accumulation Distribution
- volume.AccumulationDistribution( inputValues, out outputDistribution );
- double [] ExpAvgDistribution;
- // Exponential Moving average of Accumulation Distribution
- ExponentialMovingAverage(outputDistribution[1],out ExpAvgDistribution,longPeriod,startFromFirst);
- double [] ExpAvg;
- // Exponential Moving average of close
- ExponentialMovingAverage(outputDistribution[1],out ExpAvg,shortPeriod,startFromFirst);
- outputValues = new double [2][];
- int period = Math.Min(ExpAvg.Length,ExpAvgDistribution.Length);
- outputValues[0] = new double [period];
- outputValues[1] = new double [period];
- // Accumulation Distribution
- int expIndex = 0;
- for( int index = inputValues[1].Length - period; index < inputValues[1].Length; index++ )
- {
- // Set X values
- outputValues[0][expIndex] = inputValues[0][index];
- // Set Y values
- if(startFromFirst)
- {
- // Number of items in all arays is the same and they are aligned by time.
- outputValues[1][expIndex] = ExpAvg[expIndex] - ExpAvgDistribution[expIndex];
- }
- else if( (expIndex + longPeriod - shortPeriod) < ExpAvg.Length)
- {
- // Number of items in MovingAverages arrays is different and requires adjustment.
- outputValues[1][expIndex] = ExpAvg[expIndex + longPeriod - shortPeriod] - ExpAvgDistribution[expIndex];
- }
- else
- {
- outputValues[1][expIndex] = Double.NaN;
- }
- expIndex++;
- }
- }
- /// <summary>
- /// The Detrended Price Oscillator ("DPO") attempts to
- /// eliminate the trend in prices. Detrended prices allow
- /// you to more easily identify cycles and overbought/oversold
- /// levels. To calculate the DPO, you specify a time period.
- /// Cycles longer than this time period are removed from
- /// prices, leaving the shorter-term cycles.
- /// ---------------------------------------------------------
- /// Input:
- /// - 1 Y value ( Close ).
- /// Output:
- /// - 1 Y value Detrended Price Oscillator
- /// Parameters:
- /// - Period
- /// </summary>
- /// <param name="inputValues">Arrays of doubles - Input values</param>
- /// <param name="outputValues">Arrays of doubles - Output values</param>
- /// <param name="parameterList">Array of strings - Parameters</param>
- private void DetrendedPriceOscillator(double [][] inputValues, out double [][] outputValues, string [] parameterList)
- {
- // There is no enough input series
- if( inputValues.Length != 2 )
- {
- throw new ArgumentException(SR.ExceptionPriceIndicatorsFormulaRequiresOneArray);
- }
-
- // Different number of x and y values
- CheckNumOfValues( inputValues, 1 );
-
- // Short Period for Exp moving average
- int period;
- try
- {period = int.Parse( parameterList[0], System.Globalization.CultureInfo.InvariantCulture );}
- catch( Exception e )
- {
- if (e.Message == SR.ExceptionObjectReferenceIsNull)
- throw new InvalidOperationException(SR.ExceptionPriceIndicatorsPeriodMissing);
- else
- throw new InvalidOperationException(SR.ExceptionPriceIndicatorsPeriodMissing + e.Message);
- }
- if( period <= 0 )
- throw new InvalidOperationException(SR.ExceptionPeriodParameterIsNegative);
- double [] outputAverage;
- // Moving Average
- MovingAverage( inputValues[1], out outputAverage, period, false );
-
- outputValues = new double [2][];
- outputValues[0] = new double [inputValues[0].Length - period*3/2];
- outputValues[1] = new double [inputValues[1].Length - period*3/2];
- // Detrended Price Oscillator
- for( int index = 0; index < outputValues[1].Length; index++ )
- {
- // Set X values
- outputValues[0][index] = inputValues[0][index + period + period/2];
- // Set Y values
- outputValues[1][index] = inputValues[1][index + period + period/2] - outputAverage[index];
- }
- }
- /// <summary>
- /// Chaikin's Volatility indicator compares the spread
- /// between a security's high and low prices.
- /// It quantifies volatility as a widening of the range
- /// between the high and the low price. There are two ways
- /// to interpret this measure of volatility. One method
- /// assumes that market tops are generally accompanied by
- /// increased volatility (as investors get nervous and
- /// indecisive) and that the latter stages of a market
- /// bottom are generally accompanied by decreased volatility
- /// (as investors get bored). Another method (Mr. Chaikin's)
- /// assumes that an increase in the Volatility indicator over
- /// a relatively short time period indicates that a bottom is
- /// near (e.g., a panic sell-off) and that a decrease in
- /// volatility over a longer time period indicates an
- /// approaching top (e.g., a mature bull market). As with
- /// almost all experienced investors, Mr. Chaikin recommends
- /// that you do not rely on any one indicator. He suggests
- /// using a moving average penetration or trading band system
- /// to confirm this (or any) indicator.
- /// ---------------------------------------------------------
- /// Input:
- /// - 2 Y values ( Hi, Low ).
- /// Output:
- /// - 1 Y value Volatility Chaikins
- /// Parameters:
- /// - Periods (default 10)- is used to specify the Shift days, By default this property is set to 10.
- /// - SignalPeriod (default 10)- is used to calculate Exponential Moving Avg of the Signal line, By default this property is set to 10.
- /// </summary>
- /// <param name="inputValues">Arrays of doubles - Input values</param>
- /// <param name="outputValues">Arrays of doubles - Output values</param>
- /// <param name="parameterList">Array of strings - Parameters</param>
- private void VolatilityChaikins(double [][] inputValues, out double [][] outputValues, string [] parameterList)
- {
- // There is no enough input series
- if( inputValues.Length != 3 )
- {
- throw new ArgumentException( SR.ExceptionPriceIndicatorsFormulaRequiresTwoArrays);
- }
-
- // Different number of x and y values
- CheckNumOfValues( inputValues, 2 );
-
- // Period
- int period;
- if (parameterList.Length < 1 ||
- !int.TryParse(parameterList[0], NumberStyles.Any, CultureInfo.InvariantCulture, out period))
- {
- period = 10;
- }
- if( period <= 0 )
- throw new InvalidOperationException(SR.ExceptionOscillatorNegativePeriodParameter);
- // Signal Period for Exp moving average
- int signalPeriod;
- if (parameterList.Length < 2 ||
- !int.TryParse(parameterList[1], NumberStyles.Any, CultureInfo.InvariantCulture, out signalPeriod))
- {
- signalPeriod = 10;
- }
- if( signalPeriod <= 0 )
- throw new InvalidOperationException(SR.ExceptionOscillatorNegativeSignalPeriod);
- double [] outputAverage;
- double [] hiLowInput = new double[inputValues[1].Length];
- // Find Hi - Low
- for( int index = 0; index < inputValues[1].Length; index++ )
- {
- hiLowInput[index] = inputValues[1][index] - inputValues[2][index];
- }
-
- // Exponential Moving Average
- ExponentialMovingAverage( hiLowInput, out outputAverage, signalPeriod, false );
-
- outputValues = new double [2][];
- outputValues[0] = new double [outputAverage.Length - period];
- outputValues[1] = new double [outputAverage.Length - period];
- // Volatility Chaikins
- for( int index = 0; index < outputValues[1].Length; index++ )
- {
- // Set X values
- outputValues[0][index] = inputValues[0][index + period + signalPeriod - 1];
- // Set Y values
- if( outputAverage[index] != 0.0 )
- outputValues[1][index] = ( outputAverage[index + period] - outputAverage[index] ) / outputAverage[index] * 100.0;
- else
- // Div with zero error.
- outputValues[1][index] = 0.0;
- }
- }
- /// <summary>
- /// The Volume Oscillator displays the difference between two
- /// moving averages of a security's volume. The difference
- /// between the moving averages can be expressed in either
- /// points or percentages. You can use the difference between
- /// two moving averages of volume to determine if the overall
- /// volume trend is increasing or decreasing. When the Volume
- /// Oscillator rises above zero, it signifies that the
- /// shorter-term volume moving average has risen above
- /// the longer-term volume moving average, and thus, that
- /// the short-term volume trend is higher (i.e., more volume)
- /// than the longer-term volume trend.
- /// ---------------------------------------------------------
- /// Input:
- /// - 1 Y values ( Volume ).
- /// Output:
- /// - 1 Y value VolumeOscillator
- /// Parameters:
- /// - ShortPeriod (Default 5)= is used to configure the short period.
- /// - LongPeriod (Default 10)= is used to configure the Int64 period.
- /// - Percentage (Default true)= The Volume Oscillator can display the difference between the two moving averages as either points or percentages.
- /// </summary>
- /// <param name="inputValues">Arrays of doubles - Input values</param>
- /// <param name="outputValues">Arrays of doubles - Output values</param>
- /// <param name="parameterList">Array of strings - Parameters</param>
- private void VolumeOscillator(double [][] inputValues, out double [][] outputValues, string [] parameterList)
- {
- // There is no enough input series
- if( inputValues.Length != 2 )
- {
- throw new ArgumentException(SR.ExceptionPriceIndicatorsFormulaRequiresOneArray);
- }
-
- // Different number of x and y values
- CheckNumOfValues( inputValues, 1 );
-
- // Short Period
- int shortPeriod;
- if (parameterList.Length < 1 ||
- !int.TryParse(parameterList[0], NumberStyles.Any, CultureInfo.InvariantCulture, out shortPeriod))
- {
- shortPeriod = 5;
- }
- // Int64 Period
- int longPeriod;
- if (parameterList.Length < 2 ||
- !int.TryParse(parameterList[1], NumberStyles.Any, CultureInfo.InvariantCulture, out longPeriod))
- {
- longPeriod = 10;
- }
- if( shortPeriod > longPeriod || longPeriod <= 0 || shortPeriod <= 0 )
- throw new ArgumentException(SR.ExceptionOscillatorObjectInvalidPeriod);
- // percentage
- bool percentage;
- if (parameterList.Length < 3 ||
- !bool.TryParse(parameterList[2], out percentage))
- {
- percentage = true;
- }
-
- double [] shortAverage;
- double [] longAverage;
- // Find Short moving average
- MovingAverage( inputValues[1], out shortAverage, shortPeriod, false );
- // Find Int64 moving average
- MovingAverage( inputValues[1], out longAverage, longPeriod, false );
- outputValues = new double [2][];
- outputValues[0] = new double [longAverage.Length];
- outputValues[1] = new double [longAverage.Length];
-
- // Volume Oscillator
- for( int index = 0; index < longAverage.Length; index++ )
- {
- // Set X values
- outputValues[0][index] = inputValues[0][index + longPeriod-1];
- // Set Y values
- outputValues[1][index] = shortAverage[index + shortPeriod] - longAverage[index];
- // RecalculateAxesScale difference in %
- if( percentage )
- {
- // Div by zero error.
- if( longAverage[index] == 0.0 )
- outputValues[1][index]=0.0;
- else
- outputValues[1][index] = outputValues[1][index] / shortAverage[index + shortPeriod] * 100;
- }
- }
- }
- /// <summary>
- /// The Stochastic Indicator is based on the observation that
- /// as prices increase, closing prices tend to accumulate ever
- /// closer to the highs for the period. Conversely, as prices
- /// decrease, closing prices tend to accumulate ever closer to
- /// the lows for the period. Trading decisions are made with
- /// respect to divergence between % of "D" (one of the two
- /// lines generated by the study) and the item's price. For
- /// example, when a commodity or stock makes a high, reacts,
- /// and subsequently moves to a higher high while corresponding
- /// peaks on the % of "D" line make a high and then a lower
- /// high, a bearish divergence is indicated. When a commodity
- /// or stock has established a new low, reacts, and moves to a
- /// lower low while the corresponding low points on the % of
- /// "D" line make a low and then a higher low, a bullish
- /// divergence is indicated. Traders act upon this divergence
- /// when the other line generated by the study (K) crosses on
- /// the right-hand side of the peak of the % of "D" line in the
- /// case of a top, or on the right-hand side of the low point
- /// of the % of "D" line in the case of a bottom. The Stochastic
- /// Oscillator is displayed as two lines. The main line is
- /// called "%K." The second line, called "%D," is a moving
- /// average of %K.
- /// ---------------------------------------------------------
- /// Input:
- /// - 3 Y values ( Hi, Low, Close ).
- /// Output:
- /// - 2 Y value ( %K, %D )
- /// Parameters:
- /// - PeriodD (Default 10) = is used for %D calculation as SMA of %K.
- /// - PeriodK (Default 10) = is used to calculate %K.
- /// </summary>
- /// <param name="inputValues">Arrays of doubles - Input values</param>
- /// <param name="outputValues">Arrays of doubles - Output values</param>
- /// <param name="parameterList">Array of strings - Parameters</param>
- internal void StochasticIndicator(double [][] inputValues, out double [][] outputValues, string [] parameterList)
- {
- // There is no enough input series
- if( inputValues.Length != 4 )
- {
- throw new ArgumentException( SR.ExceptionPriceIndicatorsFormulaRequiresThreeArrays);
- }
-
- // Different number of x and y values
- CheckNumOfValues( inputValues, 3 );
-
- // PeriodD for moving average
- int periodD;
- if (parameterList.Length < 2 ||
- !int.TryParse(parameterList[1], NumberStyles.Any, CultureInfo.InvariantCulture, out periodD))
- {
- periodD = 10;
- }
- if( periodD <= 0 )
- throw new InvalidOperationException(SR.ExceptionPeriodParameterIsNegative);
- // PeriodK for moving average
- int periodK;
- if (parameterList.Length < 1 ||
- !int.TryParse(parameterList[0], NumberStyles.Any, CultureInfo.InvariantCulture, out periodK))
- {
- periodK = 10;
- }
- if( periodK <= 0 )
- throw new InvalidOperationException(SR.ExceptionPeriodParameterIsNegative);
- // Output arrays
- outputValues = new double [3][];
- // X
- outputValues[0] = new double [inputValues[0].Length - periodK - periodD + 2];
- // K%
- outputValues[1] = new double [inputValues[0].Length - periodK - periodD + 2];
- // D%
- outputValues[2] = new double [inputValues[0].Length - periodK - periodD + 2];
- double [] K = new double [inputValues[0].Length - periodK + 1];
- // Find K%
- for( int index = periodK - 1; index < inputValues[0].Length; index++ )
- {
- // Find Lowest Low and Highest High
- double minLow = double.MaxValue;
- double maxHi = double.MinValue;
- for( int indexHL = index - periodK + 1; indexHL <= index; indexHL++ )
- {
- if( minLow > inputValues[2][indexHL] )
- minLow = inputValues[2][indexHL];
- if( maxHi < inputValues[1][indexHL] )
- maxHi = inputValues[1][indexHL];
- }
- // Find K%
- K[index - periodK + 1] = ( inputValues[3][index] - minLow ) / ( maxHi - minLow ) * 100;
- // Set X and Y K output
- if( index >= periodK + periodD - 2 )
- {
- outputValues[0][index - periodK - periodD + 2] = inputValues[0][index];
- outputValues[1][index - periodK - periodD + 2] = K[index - periodK + 1];
- }
- }
- // Find D%
- MovingAverage( K, out outputValues[2], periodD, false );
- }
- /// <summary>
- /// Williams’ %R (pronounced "percent R") is a momentum
- /// indicator that measures overbought/oversold levels.
- /// Williams’ %R was developed by Larry Williams. The
- /// interpretation of Williams' %R is very similar to that
- /// of the Stochastic Oscillator except that %R is plotted
- /// upside-down and the Stochastic Oscillator has internal
- /// smoothing. To display the Williams’ %R indicator on an
- /// upside-down scale, it is usually plotted using negative
- /// values (e.g., -20%). Readings in the range of 80 to 100%
- /// indicate that the security is oversold while readings in
- /// the 0 to 20% range suggest that it is overbought.
- /// As with all overbought/oversold indicators, it is best to
- /// wait for the security's price to change direction before
- /// placing your trades. For example, if an overbought/oversold
- /// indicator (such as the Stochastic Oscillator or Williams'
- /// %R) is showing an overbought condition, it is wise to wait
- /// for the security's price to turn down before selling the
- /// security. (The MovingAverageConvergenceDivergence is a good indicator to monitor change
- /// in a security's price.) It is not unusual for
- /// overbought/oversold indicators to remain in an
- /// overbought/oversold condition for a long time period as
- /// the security's price continues to climb/fall. Selling
- /// simply because the security appears overbought may take
- /// you out of the security long before its price shows signs
- /// of deterioration.
- /// ---------------------------------------------------------
- /// Input:
- /// - 3 Y values ( Hi, Low, Close ).
- /// Output:
- /// - 2 Y value ( %R )
- /// Parameters:
- /// - Period (Default 14) = is used to configure the number of periods to calculate the WilliamsR
- /// </summary>
- /// <param name="inputValues">Arrays of doubles - Input values</param>
- /// <param name="outputValues">Arrays of doubles - Output values</param>
- /// <param name="parameterList">Array of strings - Parameters</param>
- internal void WilliamsR(double [][] inputValues, out double [][] outputValues, string [] parameterList)
- {
- // There is no enough input series
- if( inputValues.Length != 4 )
- throw new ArgumentException( SR.ExceptionPriceIndicatorsFormulaRequiresThreeArrays);
-
- // Different number of x and y values
- CheckNumOfValues( inputValues, 3 );
-
- // PeriodD for moving average
- int period;
- if (parameterList.Length < 1 ||
- !int.TryParse(parameterList[0], NumberStyles.Any, CultureInfo.InvariantCulture, out period))
- {
- period = 14;
- }
- if( period <= 0 )
- throw new InvalidOperationException(SR.ExceptionPeriodParameterIsNegative);
- // Output arrays
- outputValues = new double [2][];
- // X
- outputValues[0] = new double [inputValues[0].Length - period + 1];
- // R%
- outputValues[1] = new double [inputValues[0].Length - period + 1];
- // Find R%
- for( int index = period - 1; index < inputValues[0].Length; index++ )
- {
- // Find Lowest Low and Highest High
- double minLow = double.MaxValue;
- double maxHi = double.MinValue;
- for( int indexHL = index - period + 1; indexHL <= index; indexHL++ )
- {
- if( minLow > inputValues[2][indexHL] )
- minLow = inputValues[2][indexHL];
- if( maxHi < inputValues[1][indexHL] )
- maxHi = inputValues[1][indexHL];
- }
- // Set X value
- outputValues[0][index - period + 1] = inputValues[0][index];
- // Find R%
- outputValues[1][index - period + 1] = ( maxHi - inputValues[3][index] ) / ( maxHi - minLow ) * (-100.0);
- }
- }
- #endregion
- #region Methods
- /// <summary>
- /// Constructor
- /// </summary>
- public Oscillators()
- {
- }
- /// <summary>
- /// The first method in the module, which converts a formula
- /// name to the corresponding private method.
- /// </summary>
- /// <param name="formulaName">String which represent a formula name</param>
- /// <param name="inputValues">Arrays of doubles - Input values</param>
- /// <param name="outputValues">Arrays of doubles - Output values</param>
- /// <param name="parameterList">Array of strings - Formula parameters</param>
- /// <param name="extraParameterList">Array of strings - Extra Formula parameters from DataManipulator object</param>
- /// <param name="outLabels">Array of strings - Used for Labels. Description for output results.</param>
- override public void Formula( string formulaName, double [][] inputValues, out double [][] outputValues, string [] parameterList, string [] extraParameterList, out string [][] outLabels )
- {
- string name;
- outputValues = null;
- // Not used for these formulas.
- outLabels = null;
- name = formulaName.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
- try
- {
- switch( name )
- {
- case "STOCHASTICINDICATOR":
- StochasticIndicator( inputValues, out outputValues, parameterList );
- break;
- case "CHAIKINOSCILLATOR":
- ChaikinOscillator( inputValues, out outputValues, parameterList, extraParameterList );
- break;
- case "DETRENDEDPRICEOSCILLATOR":
- DetrendedPriceOscillator( inputValues, out outputValues, parameterList );
- break;
- case "VOLATILITYCHAIKINS":
- VolatilityChaikins( inputValues, out outputValues, parameterList );
- break;
- case "VOLUMEOSCILLATOR":
- VolumeOscillator( inputValues, out outputValues, parameterList );
- break;
- case "WILLIAMSR":
- WilliamsR( inputValues, out outputValues, parameterList );
- break;
- default:
- outputValues = null;
- break;
- }
- }
- catch( IndexOutOfRangeException )
- {
- throw new InvalidOperationException( SR.ExceptionFormulaInvalidPeriod( name ) );
- }
- catch( OverflowException )
- {
- throw new InvalidOperationException( SR.ExceptionFormulaNotEnoughDataPoints( name ) );
- }
- }
- #endregion
-
- }
- }
|