/// <summary> /// The total number of bids in the <see cref="VolumeProfileBuilder"/>. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>The total number of bids.</returns> public static decimal TotalBuyCount(this VolumeProfileBuilder volumeProfile) { if (volumeProfile == null) { throw new ArgumentNullException(nameof(volumeProfile)); } return(volumeProfile.PriceLevels.Select(p => p.BuyCount).Sum()); }
/// <summary> /// POC (Point Of Control) returns <see cref="CandlePriceLevel"/> which had the maximum volume. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>The <see cref="CandlePriceLevel"/> which had the maximum volume.</returns> public static CandlePriceLevel PoC(this VolumeProfileBuilder volumeProfile) { if (volumeProfile == null) { throw new ArgumentNullException(nameof(volumeProfile)); } var max = volumeProfile.PriceLevels.Select(p => p.BuyVolume + p.SellVolume).Max(); return(volumeProfile.PriceLevels.FirstOrDefault(p => p.BuyVolume + p.SellVolume == max)); }
/// <summary> /// It returns the price level at which the minimum <see cref="Delta"/> is passed. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>The price level.</returns> public static CandlePriceLevel PriceLevelOfMinDelta(this VolumeProfileBuilder volumeProfile) { if (volumeProfile == null) { throw new ArgumentNullException(nameof(volumeProfile)); } var delta = volumeProfile.PriceLevels.Select(p => p.BuyVolume - p.SellVolume).Min(); return(volumeProfile.PriceLevels.FirstOrDefault(p => p.BuyVolume - p.SellVolume == delta)); }
/// <summary> /// To update the profile with new value. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <param name="transform">The data source transformation.</param> public static void Update(this VolumeProfileBuilder volumeProfile, ICandleBuilderValueTransform transform) { if (volumeProfile == null) { throw new ArgumentNullException(nameof(volumeProfile)); } if (transform == null) { throw new ArgumentNullException(nameof(transform)); } volumeProfile.Update(transform.Price, transform.Volume, transform.Side); }
/// <summary> /// To process the new data. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="currentCandle">The current candle.</param> /// <param name="transform">The data source transformation.</param> /// <param name="volumeProfile">Volume profile.</param> /// <param name="changes">A new candles changes.</param> public virtual void Process(MarketDataMessage message, CandleMessage currentCandle, ICandleBuilderValueTransform transform, ref VolumeProfileBuilder volumeProfile, IList <CandleMessage> changes) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (transform == null) { throw new ArgumentNullException(nameof(transform)); } var candle = ProcessValue(message, (TCandleMessage)currentCandle, transform); if (candle == null) { // skip the value that cannot be processed return; } if (candle == currentCandle) { if (message.IsCalcVolumeProfile) { if (volumeProfile == null) { throw new InvalidOperationException(); } volumeProfile.Update(transform); } //candle.State = CandleStates.Changed; changes.Add(candle); } else { if (currentCandle != null) { currentCandle.State = CandleStates.Finished; changes.Add(currentCandle); } if (message.IsCalcVolumeProfile) { var levels = new List <CandlePriceLevel>(); volumeProfile = new VolumeProfileBuilder(levels); volumeProfile.Update(transform); candle.PriceLevels = levels; } candle.State = CandleStates.Active; changes.Add(candle); } }
/// <inheritdoc /> public IEnumerable <CandleMessage> Process(MarketDataMessage message, CandleMessage currentCandle, ICandleBuilderValueTransform transform, ref VolumeProfileBuilder volumeProfile) { if (!IsTimeValid(message, transform.Time)) { return(Enumerable.Empty <CandleMessage>()); } var changes = new List <CandleMessage>(); Process(message, currentCandle, transform, ref volumeProfile, changes); return(changes); }
/// <summary> /// The total Delta which was below <see cref="PoC"/>. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>Delta.</returns> public static decimal DeltaBelowPoC(this VolumeProfileBuilder volumeProfile) { return(volumeProfile.BuyVolBelowPoC() - volumeProfile.SellVolBelowPoC()); }
/// <summary> /// The difference between <see cref="TotalBuyVolume"/> and <see cref="TotalSellVolume"/>. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>Delta.</returns> public static decimal Delta(this VolumeProfileBuilder volumeProfile) { return(volumeProfile.TotalBuyVolume() - volumeProfile.TotalSellVolume()); }
/// <summary> /// The total volume which was above <see cref="PoC"/>. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>Total volume.</returns> public static decimal VolumeAbovePoC(this VolumeProfileBuilder volumeProfile) { return(volumeProfile.BuyVolAbovePoC() + volumeProfile.SellVolAbovePoC()); }
/// <summary> /// The total volume of asks which was below <see cref="PoC"/>. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>The total volume of asks.</returns> public static decimal SellVolBelowPoC(this VolumeProfileBuilder volumeProfile) { var poc = volumeProfile.PoC(); return(volumeProfile.PriceLevels.Where(p => p.Price < poc.Price).Select(p => p.SellVolume).Sum()); }
/// <summary> /// The total volume of bids which was above <see cref="PoC"/>. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>The total volume of bids.</returns> public static decimal BuyVolAbovePoC(this VolumeProfileBuilder volumeProfile) { var poc = volumeProfile.PoC(); return(volumeProfile.PriceLevels.Where(p => p.Price > poc.Price).Select(p => p.BuyVolume).Sum()); }