public void Add_WhenFirstCandleAdded_TrueRangeListIsEmpty() { var adx = new Adx(14); var candle001 = new Candle(273, 274m, 272m, 272.75m, DateTime.UtcNow); adx.Add(candle001); adx.TrueRanges.Should().BeEmpty(); }
private static decimal GetTrueRange(Candle current, Candle previous) { return (new[] { current.FullRange, Math.Abs(current.High - previous.Close), Math.Abs(current.Low - previous.Close) }).Max(); }
public void Add(Candle value) { if (!this.sourceValues.Any()) { this.sourceValues.Add(value); return; } var lastValue = this.sourceValues.LastOrDefault() ?? new Candle(); var upMove = value.High - lastValue.High; var downMove = lastValue.Low - value.Low; var upDm = upMove > 0 && upMove > downMove ? upMove : 0; var downDm = downMove > 0 && downMove > upMove ? downMove : 0; var trueRange = GetTrueRange(value, lastValue); this.upDms.Add(upDm); this.downDms.Add(downDm); this.trueRanges.Add(trueRange); if (this.trueRanges.Count < this.period) { this.trueRangesAccum.Add(this.trueRanges.TakeLast(this.period).Sum()); this.upDmAccum.Add(this.upDms.TakeLast(this.period).Sum()); this.downDmAccum.Add(this.downDms.TakeLast(this.period).Sum()); } else { //Just add the ups and downs with the same technique var previousTr = this.trueRangesAccum.Last(); var currentTr = previousTr - (previousTr / this.period) + trueRange; this.trueRangesAccum.Add(currentTr); var previousUpDm = this.upDmAccum.Last(); var currentUpDm = previousUpDm - (previousUpDm / this.period) + upDm; this.upDmAccum.Add(currentUpDm); var previousDownDm = this.downDmAccum.Last(); var currentDownDm = previousDownDm - (previousDownDm / this.period) + downDm; this.downDmAccum.Add(currentDownDm); this.upDiAccum.Add(this.upDmAccum.Last() / this.trueRangesAccum.Last()); this.downDiAccum.Add(this.downDmAccum.Last() / this.trueRangesAccum.Last()); var delta = Math.Abs(this.upDiAccum.Last() - this.downDiAccum.Last()); var divider = this.upDiAccum.Last() + this.downDiAccum.Last(); var dx = divider > 0 ? delta / divider : 0; this.dxs.Add(dx); } if (this.dxs.Count == this.period) { this.values.Add(this.dxs.Average()); } else if (this.dxs.Count > this.period) { var dxsAccum = (this.values.Last() * (this.period - 1) + this.dxs.Last()) / this.period; this.values.Add(dxsAccum); } this.sourceValues.Add(value); }
public CandleBuilderEventArgs(Candle newCandle) { this.newCandle = newCandle; }
private void AddCandle(Candle newCandle) { if (this.candles.Any(x => x.Timestamp == newCandle.Timestamp)) { return; } var lastCandle = this.candles.LastOrDefault(); if (lastCandle != null) { if ((newCandle.Timestamp - lastCandle.Timestamp).Minutes % this.PeriodInMinutes > 0) { throw new Exception(string.Format("The list of candles do not follow the sequence: {0} to {2}", lastCandle.Timestamp, newCandle.Timestamp)); } } this.candles.Add(newCandle); this.adx.Add(newCandle); this.fastEmaHigh.Add(newCandle.High); this.fastEmaLow.Add(newCandle.Low); this.slowSmaHigh.Add(newCandle.High); this.slowSmaLow.Add(newCandle.Low); }
private static bool ConfirmPreviousCandleForBid(Candle previousCandle, Candle currentCandle) { if (previousCandle == null) { return false; } if (currentCandle == null) { return false; } if (!previousCandle.IsDown) { return false; } return currentCandle.Close < previousCandle.Close; }
public bool ConfirmPreviousCandleForAsk(Candle previousCandle, Candle currentCandle) { if (previousCandle == null) { return false; } if (currentCandle == null) { return false; } if (!previousCandle.IsUp) { return false; } return currentCandle.Close > previousCandle.Close; }