예제 #1
0
        /// <summary>
        /// Configures the event handlers for Left.Updated and Right.Updated to update this instance when
        /// they both have new data.
        /// </summary>
        private void ConfigureEventHandlers()
        {
            // if either of these are constants then there's no reason
            bool leftIsConstant  = Left.GetType().IsSubclassOfGeneric(typeof(ConstantIndicator <>));
            bool rightIsConstant = Right.GetType().IsSubclassOfGeneric(typeof(ConstantIndicator <>));

            // wire up the Updated events such that when we get a new piece of data from both left and right
            // we'll call update on this indicator. It's important to note that the CompositeIndicator only uses
            // the timestamp that gets passed into the Update function, his compuation is soley a function
            // of the left and right indicator via '_composer'

            IndicatorDataPoint newLeftData  = null;
            IndicatorDataPoint newRightData = null;

            Left.Updated += (sender, updated) =>
            {
                newLeftData = updated;

                // if we have left and right data (or if right is a constant) then we need to update
                if (newRightData != null || rightIsConstant)
                {
                    Update(new T {
                        Time = MaxTime(updated)
                    });
                    // reset these to null after each update
                    newLeftData  = null;
                    newRightData = null;
                }
            };

            Right.Updated += (sender, updated) =>
            {
                newRightData = updated;

                // if we have left and right data (or if left is a constant) then we need to update
                if (newLeftData != null || leftIsConstant)
                {
                    Update(new T {
                        Time = MaxTime(updated)
                    });
                    // reset these to null after each update
                    newLeftData  = null;
                    newRightData = null;
                }
            };
        }
예제 #2
0
        /// <summary>
        /// Updates the state of this indicator with the given value and returns true
        /// if this indicator is ready, false otherwise
        /// </summary>
        /// <param name="input">The value to use to update this indicator</param>
        /// <returns>True if this indicator is ready, false otherwise</returns>
        public bool Update(T input)
        {
            if (_previousInput != null && input.Time < _previousInput.Time)
            {
                // if we receive a time in the past, throw
                throw new ArgumentException(string.Format("This is a forward only indicator: {0} Input: {1} Previous: {2}", Name, input.Time.ToString("u"), _previousInput.Time.ToString("u")));
            }
            if (!ReferenceEquals(input, _previousInput))
            {
                // compute a new value and update our previous time
                Samples++;
                _previousInput = input;

                var nextResult = ValidateAndComputeNextValue(input);
                if (nextResult.Status == IndicatorStatus.Success)
                {
                    Current = new IndicatorDataPoint(input.Time, nextResult.Value);

                    // let others know we've produced a new data point
                    OnUpdated(Current);
                }
            }
            return(IsReady);
        }
예제 #3
0
 /// <summary>
 /// Computes the next value of this indicator from the given state
 /// </summary>
 /// <param name="input">The input given to the indicator</param>
 /// <param name="window">The window for the input history</param>
 /// <returns>A new value for this indicator</returns>
 protected override decimal ComputeNextValue(IReadOnlyWindow <IndicatorDataPoint> window, IndicatorDataPoint input)
 {
     return((decimal)Math.Sqrt((double)base.ComputeNextValue(window, input)));
 }
예제 #4
0
 private DateTime MaxTime(IndicatorDataPoint updated)
 {
     return(new DateTime(Math.Max(updated.Time.Ticks, Math.Max(Right.Current.Time.Ticks, Left.Current.Time.Ticks))));
 }
예제 #5
0
 /// <summary>
 /// AroonUp = 100 * (period - {periods since max})/period
 /// </summary>
 /// <param name="upPeriod">The AroonUp period</param>
 /// <param name="max">A Maximum indicator used to compute periods since max</param>
 /// <param name="input">The next input data</param>
 /// <returns>The AroonUp value</returns>
 private static decimal ComputeAroonUp(int upPeriod, Maximum max, IndicatorDataPoint input)
 {
     max.Update(input);
     return(100m * (upPeriod - max.PeriodsSinceMaximum) / upPeriod);
 }
예제 #6
0
 /// <summary>
 /// AroonDown = 100 * (period - {periods since min})/period
 /// </summary>
 /// <param name="downPeriod">The AroonDown period</param>
 /// <param name="min">A Minimum indicator used to compute periods since min</param>
 /// <param name="input">The next input data</param>
 /// <returns>The AroonDown value</returns>
 private static decimal ComputeAroonDown(int downPeriod, Minimum min, IndicatorDataPoint input)
 {
     min.Update(input);
     return(100m * (downPeriod - min.PeriodsSinceMinimum) / downPeriod);
 }
예제 #7
0
 /// <summary>
 /// Resets this indicator to its initial state
 /// </summary>
 public virtual void Reset()
 {
     Samples        = 0;
     _previousInput = null;
     Current        = new IndicatorDataPoint(DateTime.MinValue, default(decimal));
 }
예제 #8
0
 /// <summary>
 /// Initializes a new instance of the Indicator class using the specified name.
 /// </summary>
 /// <param name="name">The name of this indicator</param>
 protected IndicatorBase(string name)
 {
     Name    = name;
     Current = new IndicatorDataPoint(DateTime.MinValue, 0m);
 }