private void AppendTick(Security security, ExecutionMessage tick) { var time = tick.ServerTime; var price = tick.TradePrice.Value; if (_candle == null || time >= _candle.CloseTime) { if (_candle != null) { _candle.State = CandleStates.Finished; lock (_updatedCandles.SyncRoot) _updatedCandles[_candle.OpenTime] = _candle; _lastPrice = _candle.ClosePrice; _tradeGenerator.Process(tick); } //var t = TimeframeSegmentDataSeries.GetTimeframePeriod(time.DateTime, _timeframe); var bounds = _timeframe.GetCandleBounds(time, security.Board); _candle = new TimeFrameCandle { TimeFrame = _timeframe, OpenTime = bounds.Min, CloseTime = bounds.Max, Security = security, }; _volumeProfile = new CandleMessageVolumeProfile(); _candle.PriceLevels = _volumeProfile.PriceLevels; _candle.OpenPrice = _candle.HighPrice = _candle.LowPrice = _candle.ClosePrice = price; } if (time < _candle.OpenTime) { throw new InvalidOperationException("invalid time"); } if (price > _candle.HighPrice) { _candle.HighPrice = price; } if (price < _candle.LowPrice) { _candle.LowPrice = price; } _candle.ClosePrice = price; _candle.TotalVolume += tick.TradeVolume.Value; _volumeProfile.Update(new TickCandleBuilderSourceValue(tick)); lock (_updatedCandles.SyncRoot) _updatedCandles[_candle.OpenTime] = _candle; }
/// <summary> /// The total number of asks in the <see cref="CandleMessageVolumeProfile"/>. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <returns>The total number of asks.</returns> public static decimal TotalSellCount(this CandleMessageVolumeProfile volumeProfile) { if (volumeProfile == null) { throw new ArgumentNullException(nameof(volumeProfile)); } return(volumeProfile.PriceLevels.Select(p => p.SellCount).Sum()); }
private void AppendTick(Security security, ExecutionMessage tick) { var time = tick.ServerTime; var price = tick.TradePrice.Value; if (_candle == null || time >= _candle.CloseTime) { if (_candle != null) { lock (_updatedCandles.SyncRoot) _updatedCandles[_candle.OpenTime] = Tuple.Create(_candle, true); _lastPrice = _candle.ClosePrice; _tradeGenerator.Process(tick); } var bounds = _timeframe.GetCandleBounds(time, security.Board); _candle = new TimeFrameCandle { TimeFrame = _timeframe, OpenTime = bounds.Min, CloseTime = bounds.Max, Security = security, }; _volumeProfile = new CandleMessageVolumeProfile(); _candle.PriceLevels = _volumeProfile.PriceLevels; _candle.OpenPrice = _candle.HighPrice = _candle.LowPrice = _candle.ClosePrice = price; } if (time < _candle.OpenTime) { throw new InvalidOperationException("invalid time"); } if (price > _candle.HighPrice) { _candle.HighPrice = price; } if (price < _candle.LowPrice) { _candle.LowPrice = price; } _candle.ClosePrice = price; _candle.TotalVolume += tick.TradeVolume.Value; lock (_volumeProfile.PriceLevels) _volumeProfile.Update(tick.TradePrice.Value, tick.TradeVolume, tick.OriginSide); lock (_updatedCandles.SyncRoot) _updatedCandles[_candle.OpenTime] = Tuple.Create(_candle, false); }
/// <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 CandleMessageVolumeProfile 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 CandleMessageVolumeProfile 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 CandleMessageVolumeProfile 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 update the profile with new value. /// </summary> /// <param name="volumeProfile">Volume profile.</param> /// <param name="value">Value.</param> public static void Update(this CandleMessageVolumeProfile volumeProfile, ICandleBuilderSourceValue value) { if (volumeProfile == null) { throw new ArgumentNullException(nameof(volumeProfile)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } volumeProfile.Update(value.Price, value.Volume, value.OrderDirection); }
/// <summary> /// To calculate the area for the candles group. /// </summary> /// <param name="candles">Candles.</param> /// <returns>The area.</returns> public static CandleMessageVolumeProfile GetValueArea(this IEnumerable <Candle> candles) { var area = new CandleMessageVolumeProfile(); foreach (var candle in candles) { if (candle.PriceLevels == null) { continue; } foreach (var priceLevel in candle.PriceLevels) { area.Update(priceLevel); } } area.Calculate(); return(area); }
/// <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 CandleMessageVolumeProfile 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 CandleMessageVolumeProfile 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 CandleMessageVolumeProfile 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 CandleMessageVolumeProfile 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 CandleMessageVolumeProfile volumeProfile) { var poc = volumeProfile.PoC(); return(volumeProfile.PriceLevels.Where(p => p.Price > poc.Price).Select(p => p.BuyVolume).Sum()); }