/// <summary>Initializes a new instance of the SimpleMovingAverage class with the specified name and period from the left indicator /// </summary> /// <param name="left">The SimpleMovingAverage indicator will be created using the data from left</param> /// <param name="period">The period of the SMA</param> /// <param name="waitForFirstToReady">True to only send updates to the second if first.IsReady returns true, false to always send updates to second</param> /// <returns>The reference to the SimpleMovingAverage indicator to allow for method chaining</returns> public static SimpleMovingAverage SMA <T>(this IndicatorBase <T> left, int period, bool waitForFirstToReady = true) where T : IBaseData { return(new SimpleMovingAverage($"SMA{period}_Of_{left.Name}", period).Of(left, waitForFirstToReady)); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the product of the left to the right /// </summary> /// <remarks> /// value = left*right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <param name="name">The name of this indicator</param> /// <returns>The product of the left to the right indicators</returns> public static CompositeIndicator <T> Times <T>(this IndicatorBase <T> left, IndicatorBase <T> right, string name) where T : IBaseData { return(new CompositeIndicator <T>(name, left, right, (l, r) => l.Current.Value * r.Current.Value)); }
/// <summary>Creates a new Minimum indicator with the specified period from the left indicator /// </summary> /// <param name="left">The Minimum indicator will be created using the data from left</param> /// <param name="period">The period of the Minimum indicator</param> /// <param name="waitForFirstToReady">True to only send updates to the second if left.IsReady returns true, false to always send updates</param> /// <returns>A reference to the Minimum indicator to allow for method chaining</returns> public static Minimum MIN <T>(this IndicatorBase <T> left, int period, bool waitForFirstToReady = true) where T : IBaseData { return(new Minimum($"MIN{period}_Of_{left.Name}", period).Of(left, waitForFirstToReady)); }
/// <summary> /// Initializes a new instance of the <see cref="AverageDirectionalIndex"/> class. /// </summary> /// <param name="name">The name.</param> /// <param name="period">The period.</param> public AverageDirectionalIndex(string name, int period) : base(name) { _period = period; _trueRange = new FunctionalIndicator <IBaseDataBar>(name + "_TrueRange", ComputeTrueRange, isReady => _previousInput != null ); _directionalMovementPlus = new FunctionalIndicator <IBaseDataBar>(name + "_PositiveDirectionalMovement", ComputePositiveDirectionalMovement, isReady => _previousInput != null ); _directionalMovementMinus = new FunctionalIndicator <IBaseDataBar>(name + "_NegativeDirectionalMovement", ComputeNegativeDirectionalMovement, isReady => _previousInput != null ); PositiveDirectionalIndex = new FunctionalIndicator <IndicatorDataPoint>(name + "_PositiveDirectionalIndex", input => { // Computes the Plus Directional Indicator(+DI period). if (_smoothedTrueRange != 0 && _smoothedDirectionalMovementPlus.IsReady) { return(100m * _smoothedDirectionalMovementPlus / _smoothedTrueRange); } return(0m); }, positiveDirectionalIndex => _smoothedDirectionalMovementPlus.IsReady, () => { _directionalMovementPlus.Reset(); _trueRange.Reset(); } ); NegativeDirectionalIndex = new FunctionalIndicator <IndicatorDataPoint>(name + "_NegativeDirectionalIndex", input => { // Computes the Minus Directional Indicator(-DI period). if (_smoothedTrueRange != 0 && _smoothedDirectionalMovementMinus.IsReady) { return(100m * _smoothedDirectionalMovementMinus / _smoothedTrueRange); } return(0m); }, negativeDirectionalIndex => _smoothedDirectionalMovementMinus.IsReady, () => { _directionalMovementMinus.Reset(); _trueRange.Reset(); } ); _smoothedTrueRange = new FunctionalIndicator <IndicatorDataPoint>(name + "_SmoothedTrueRange", input => { // Computes the Smoothed True Range value. var value = Samples > _period + 1 ? _smoothedTrueRange / _period : 0m; return(_smoothedTrueRange + _trueRange - value); }, isReady => Samples > period ); _smoothedDirectionalMovementPlus = new FunctionalIndicator <IndicatorDataPoint>(name + "_SmoothedDirectionalMovementPlus", input => { // Computes the Smoothed Directional Movement Plus value. var value = Samples > _period + 1 ? _smoothedDirectionalMovementPlus / _period : 0m; return(_smoothedDirectionalMovementPlus + _directionalMovementPlus - value); }, isReady => Samples > period ); _smoothedDirectionalMovementMinus = new FunctionalIndicator <IndicatorDataPoint>(name + "_SmoothedDirectionalMovementMinus", input => { // Computes the Smoothed Directional Movement Minus value. var value = Samples > _period + 1 ? _smoothedDirectionalMovementMinus / _period : 0m; return(_smoothedDirectionalMovementMinus + _directionalMovementMinus - value); }, isReady => Samples > period ); _averageDirectionalIndex = new WilderMovingAverage(period); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the difference of the left and right /// </summary> /// <remarks> /// value = left - right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <param name="name">The name of this indicator</param> /// <returns>The difference of the left and right indicators</returns> public static CompositeIndicator <T> Minus <T>(this IndicatorBase <T> left, IndicatorBase <T> right, string name) where T : IBaseData { return(new CompositeIndicator <T>(name, left, right, (l, r) => l - r)); }
/// <summary> /// Initializes a new instance of the MeanAbsoluteDeviation class with the specified period. /// /// Evaluates the mean absolute deviation of samples in the look-back period. /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="period">The sample size of the mean absolute deviation</param> public MeanAbsoluteDeviation(string name, int period) : base(name, period) { Mean = new SimpleMovingAverage($"{name}_Mean", period); }
/// <summary> /// Creates a new SequentialIndicator that will pipe the output of the first into the second /// </summary> /// <param name="first">The first indicator to receive data</param> /// <param name="second">The indicator to receive the first's output data</param> public SequentialIndicator(IndicatorBase <TFirst> first, IndicatorBase <IndicatorDataPoint> second) : base(string.Format("SEQUENTIAL({0}->{1})", first.Name, second.Name)) { First = first; Second = second; }
/// <summary> /// Updates the state of this indicator with the given value and returns true /// if this indicator is ready, false otherwise /// </summary> /// <param name="indicator">The indicator to be updated</param> /// <param name="time">The time associated with the value</param> /// <param name="value">The value to use to update this indicator</param> /// <returns>True if this indicator is ready, false otherwise</returns> public static void Update(this IndicatorBase <IndicatorDataPoint> indicator, DateTime time, decimal value) { indicator.Update(new IndicatorDataPoint(time, value)); }
/// <summary> /// Creates a new SequentialIndicator such that data from 'first' is piped into 'second' /// </summary> /// <param name="second">The indicator that wraps the first</param> /// <param name="first">The indicator to be wrapped</param> /// <param name="name">The name of the new indicator</param> /// <returns>A new SequentialIndicator that pipes data from first to second</returns> public static SequentialIndicator <T> Of <T>(this IndicatorBase <IndicatorDataPoint> second, IndicatorBase <T> first, string name) where T : BaseData { return(new SequentialIndicator <T>(first, second)); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the product of the left and the constant /// </summary> /// <remarks> /// value = left*constant /// </remarks> /// <param name="left">The left indicator</param> /// <param name="constant">The constant value to multiple by</param> /// <returns>The product of the left to the right indicators</returns> public static CompositeIndicator <IndicatorDataPoint> Times(this IndicatorBase <IndicatorDataPoint> left, decimal constant) { var constantIndicator = new ConstantIndicator <IndicatorDataPoint>(constant.ToString(CultureInfo.InvariantCulture), constant); return(left.Times(constantIndicator)); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the product of the left to the right /// </summary> /// <remarks> /// value = left*right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <returns>The product of the left to the right indicators</returns> public static CompositeIndicator <IndicatorDataPoint> Times(this IndicatorBase <IndicatorDataPoint> left, IndicatorBase <IndicatorDataPoint> right) { return(new CompositeIndicator <IndicatorDataPoint>(left, right, (l, r) => l * r)); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the ratio of the left to the right /// </summary> /// <remarks> /// value = left/right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <param name="name">The name of this indicator</param> /// <returns>The ratio of the left to the right indicator</returns> public static CompositeIndicator <IndicatorDataPoint> Over(this IndicatorBase <IndicatorDataPoint> left, IndicatorBase <IndicatorDataPoint> right, string name) { return(new CompositeIndicator <IndicatorDataPoint>(name, left, right, (l, r) => r == 0m ? new IndicatorResult(0m, IndicatorStatus.MathError) : new IndicatorResult(l / r))); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the product of the left to the right /// </summary> /// <remarks> /// value = left*right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <returns>The product of the left to the right indicators</returns> public static CompositeIndicator <T> Times <T>(this IndicatorBase <T> left, IndicatorBase <T> right) where T : IBaseData { return(new CompositeIndicator <T>(left, right, (l, r) => l * r)); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the ratio of the left to the right /// </summary> /// <remarks> /// value = left/right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <returns>The ratio of the left to the right indicator</returns> public static CompositeIndicator <T> Over <T>(this IndicatorBase <T> left, IndicatorBase <T> right) where T : IBaseData { return(new CompositeIndicator <T>(left, right, (l, r) => r == 0m ? new IndicatorResult(0m, IndicatorStatus.MathError) : new IndicatorResult(l / r))); }
/// <summary> /// Updates the state of this indicator with the given value and returns true /// if this indicator is ready, false otherwise /// </summary> /// <param name="indicator">The indicator to be updated</param> /// <param name="time">The time associated with the value</param> /// <param name="value">The value to use to update this indicator</param> /// <returns>True if this indicator is ready, false otherwise</returns> public static bool Update(this IndicatorBase <IndicatorDataPoint> indicator, DateTime time, decimal value) { return(indicator.Update(new IndicatorDataPoint(time, value))); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the sum of the left and right /// </summary> /// <remarks> /// value = left + right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <param name="name">The name of this indicator</param> /// <returns>The sum of the left and right indicators</returns> public static CompositeIndicator <IndicatorDataPoint> Plus(this IndicatorBase <IndicatorDataPoint> left, IndicatorBase <IndicatorDataPoint> right, string name) { return(new CompositeIndicator <IndicatorDataPoint>(name, left, right, (l, r) => l + r)); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be average of a first indicator weighted by a second one /// </summary> /// <param name="value">Indicator that will be averaged</param> /// <param name="weight">Indicator that provides the average weights</param> /// <param name="period">Average period</param> /// <returns>Indicator that results of the average of first by weights given by second</returns> public static CompositeIndicator <IndicatorDataPoint> WeightedBy <T, TWeight>(this IndicatorBase <T> value, TWeight weight, int period) where T : IBaseData where TWeight : IndicatorBase <IndicatorDataPoint> { var x = new WindowIdentity(period); var y = new WindowIdentity(period); var numerator = new Sum("Sum_xy", period); var denominator = new Sum("Sum_y", period); value.Updated += (sender, consolidated) => { x.Update(consolidated); if (x.Samples == y.Samples) { numerator.Update(consolidated.Time, consolidated.Value * y.Current.Value); } }; weight.Updated += (sender, consolidated) => { y.Update(consolidated); if (x.Samples == y.Samples) { numerator.Update(consolidated.Time, consolidated.Value * x.Current.Value); } denominator.Update(consolidated); }; return(numerator.Over(denominator)); }
/// <summary> /// Initializes a new instance of the MeanAbsoluteDeviation class with the specified period. /// /// Evaluates the mean absolute deviation of samples in the lookback period. /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="period">The sample size of the mean absoluate deviation</param> public MeanAbsoluteDeviation(string name, int period) : base(name, period) { Mean = MovingAverageType.Simple.AsIndicator(string.Format("{0}_{1}", name, "Mean"), period); }
/// <summary> /// Creates a new SequentialIndicator that will pipe the output of the first into the second /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="first">The first indicator to receive data</param> /// <param name="second">The indicator to receive the first's output data</param> public SequentialIndicator(string name, IndicatorBase <TFirst> first, IndicatorBase <IndicatorDataPoint> second) : base(name) { First = first; Second = second; }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the difference of the left and right /// </summary> /// <remarks> /// value = left - right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <returns>The difference of the left and right indicators</returns> public static CompositeIndicator <T> Minus <T>(this IndicatorBase <T> left, IndicatorBase <T> right) where T : IBaseData { return(new CompositeIndicator <T>(left, right, (l, r) => l.Current.Value - r.Current.Value)); }
/// <summary> /// Initializes a new instance of the <see cref="DonchianChannel"/> class. /// </summary> /// <param name="name">The name.</param> /// <param name="upperPeriod">The period for the upper channel.</param> /// <param name="lowerPeriod">The period for the lower channel</param> public DonchianChannel(string name, int upperPeriod, int lowerPeriod) : base(name) { UpperBand = new Maximum(name + "_UpperBand", upperPeriod); LowerBand = new Minimum(name + "_LowerBand", lowerPeriod); }
/// <summary> /// Creates a new CompositeIndicator such that the result will be the ratio of the left to the right /// </summary> /// <remarks> /// value = left/right /// </remarks> /// <param name="left">The left indicator</param> /// <param name="right">The right indicator</param> /// <param name="name">The name of this indicator</param> /// <returns>The ratio of the left to the right indicator</returns> public static CompositeIndicator <T> Over <T>(this IndicatorBase <T> left, IndicatorBase <T> right, string name) where T : IBaseData { return(new CompositeIndicator <T>(name, left, right, (l, r) => r.Current.Value == 0m ? new IndicatorResult(0m, IndicatorStatus.MathError) : new IndicatorResult(l.Current.Value / r.Current.Value))); }
/// <summary> /// Creates a new AverageTrueRange indicator using the specified period and moving average type /// </summary> /// <param name="name">The name of this indicator</param> /// <param name="period">The smoothing period used to smooth the true range values</param> /// <param name="movingAverageType">The type of smoothing used to smooth the true range values</param> public AverageTrueRange(string name, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders) : base(name) { _smoother = movingAverageType.AsIndicator(string.Format("{0}_{1}", name, movingAverageType), period); }
/// <summary> /// Initializes a new instance of the <see cref="AverageDirectionalIndex"/> class. /// </summary> /// <param name="name">The name.</param> /// <param name="period">The period.</param> public AverageDirectionalIndex(string name, int period) : base(name) { _period = period; TrueRange = new FunctionalIndicator <TradeBar>(name + "_TrueRange", currentBar => { var value = ComputeTrueRange(currentBar); return(value); }, isReady => _previousInput != null ); DirectionalMovementPlus = new FunctionalIndicator <TradeBar>(name + "_PositiveDirectionalMovement", currentBar => { var value = ComputePositiveDirectionalMovement(currentBar); return(value); }, isReady => _previousInput != null ); DirectionalMovementMinus = new FunctionalIndicator <TradeBar>(name + "_NegativeDirectionalMovement", currentBar => { var value = ComputeNegativeDirectionalMovement(currentBar); return(value); }, isReady => _previousInput != null ); PositiveDirectionalIndex = new FunctionalIndicator <IndicatorDataPoint>(name + "_PositiveDirectionalIndex", input => ComputePositiveDirectionalIndex(), positiveDirectionalIndex => DirectionalMovementPlus.IsReady && TrueRange.IsReady, () => { DirectionalMovementPlus.Reset(); TrueRange.Reset(); } ); NegativeDirectionalIndex = new FunctionalIndicator <IndicatorDataPoint>(name + "_NegativeDirectionalIndex", input => ComputeNegativeDirectionalIndex(), negativeDirectionalIndex => DirectionalMovementMinus.IsReady && TrueRange.IsReady, () => { DirectionalMovementMinus.Reset(); TrueRange.Reset(); } ); SmoothedTrueRange = new FunctionalIndicator <IndicatorDataPoint>(name + "_SmoothedTrueRange", currentBar => ComputeSmoothedTrueRange(period), isReady => _previousInput != null ); SmoothedDirectionalMovementPlus = new FunctionalIndicator <IndicatorDataPoint>(name + "_SmoothedDirectionalMovementPlus", currentBar => ComputeSmoothedDirectionalMovementPlus(period), isReady => _previousInput != null ); SmoothedDirectionalMovementMinus = new FunctionalIndicator <IndicatorDataPoint>(name + "_SmoothedDirectionalMovementMinus", currentBar => ComputeSmoothedDirectionalMovementMinus(period), isReady => _previousInput != null ); }