/// <summary> /// To update the profile with new value. /// </summary> /// <param name="value">Value.</param> public void Update(ICandleBuilderSourceValue value) { if (value.OrderDirection == null) return; _volumeProfileInfo.SafeAdd(value.Price, key => new PriceLevel(key)).Update(value); }
/// <summary> /// To update the price level with the new value. /// </summary> /// <param name="value">Value.</param> public void Update(ICandleBuilderSourceValue value) { var side = value.OrderDirection; if (side == null) throw new ArgumentOutOfRangeException(); if (side == Sides.Buy) { BuyVolume += value.Volume; BuyCount++; BuyVolumes.Add(value.Volume); } else { SellVolume += value.Volume; SellCount++; SellVolumes.Add(value.Volume); } }
/// <summary> /// Whether the candle is created before data adding. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="candle">Candle.</param> /// <param name="value">Data by which it is decided to end the current candle creation.</param> /// <returns><see langword="true" /> if the candle should be finished. Otherwise, <see langword="false" />.</returns> protected override bool IsCandleFinishedBeforeChange(MarketDataMessage message, RangeCandleMessage candle, ICandleBuilderSourceValue value) { return((decimal)(candle.LowPrice + candle.PriceRange) <= candle.HighPrice); }
/// <summary> /// Whether the candle is created before data adding. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="candle">Candle.</param> /// <param name="value">Data by which it is decided to end the current candle creation.</param> /// <returns><see langword="true" /> if the candle should be finished. Otherwise, <see langword="false" />.</returns> protected override bool IsCandleFinishedBeforeChange(MarketDataMessage message, VolumeCandleMessage candle, ICandleBuilderSourceValue value) { return(candle.TotalVolume >= candle.Volume); }
/// <summary> /// To update the candle data. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="candle">Candle.</param> /// <param name="value">Data.</param> protected override void UpdateCandle(MarketDataMessage message, TickCandleMessage candle, ICandleBuilderSourceValue value) { base.UpdateCandle(message, candle, value); var ticks = candle.TotalTicks; if (ticks == null) { throw new InvalidOperationException(); } candle.TotalTicks = ticks.Value + 1; }
/// <summary> /// To create a new candle. /// </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="value">Data with which a new candle should be created.</param> /// <returns>Created candle.</returns> protected override TickCandleMessage CreateCandle(MarketDataMessage message, TickCandleMessage currentCandle, ICandleBuilderSourceValue value) { return(FirstInitCandle(message, new TickCandleMessage { MaxTradeCount = (int)message.Arg, OpenTime = value.Time, CloseTime = value.Time, HighTime = value.Time, LowTime = value.Time, TotalTicks = 1, }, value)); }
///// <summary> ///// Reset state. ///// </summary> //public override void Reset() //{ // base.Reset(); // _timeoutInfos.Clear(); //} /// <summary> /// To create a new candle. /// </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="value">Data with which a new candle should be created.</param> /// <returns>Created candle.</returns> protected override TimeFrameCandleMessage CreateCandle(MarketDataMessage message, TimeFrameCandleMessage currentCandle, ICandleBuilderSourceValue value) { var timeFrame = (TimeSpan)message.Arg; var board = _exchangeInfoProvider.GetOrCreateBoard(message.SecurityId.BoardCode); var bounds = timeFrame.GetCandleBounds(value.Time, board, board.WorkingTime); if (value.Time < bounds.Min) { return(null); } var openTime = bounds.Min; var candle = FirstInitCandle(message, new TimeFrameCandleMessage { TimeFrame = timeFrame, OpenTime = openTime, HighTime = openTime, LowTime = openTime, CloseTime = openTime, // реальное окончание свечи определяет по последней сделке }, value); return(candle); }
/// <summary> /// Сформирована ли свеча до добавления данных. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="candle">Свеча.</param> /// <param name="value">Данные, с помощью которых принимается решение о необходимости окончания формирования текущей свечи.</param> /// <returns><see langword="true"/>, если свечу необходимо закончить. Иначе, <see langword="false"/>.</returns> protected override bool IsCandleFinishedBeforeChange(CandleSeries series, PnFCandle candle, ICandleBuilderSourceValue value) { var argSize = candle.PnFArg.BoxSize * candle.PnFArg.ReversalAmount; if (candle.Type == PnFTypes.X) { return(candle.ClosePrice - argSize > value.Price); } else { return(candle.ClosePrice + argSize < value.Price); } }
/// <summary> /// Сформирована ли свеча до добавления данных. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="candle">Свеча.</param> /// <param name="value">Данные, с помощью которых принимается решение о необходимости окончания формирования текущей свечи.</param> /// <returns><see langword="true"/>, если свечу необходимо закончить. Иначе, <see langword="false"/>.</returns> protected override bool IsCandleFinishedBeforeChange(CandleSeries series, TimeFrameCandle candle, ICandleBuilderSourceValue value) { return(value.Time < candle.OpenTime || (candle.OpenTime + candle.TimeFrame) <= value.Time); }
/// <summary> /// Обработать новые данные. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="currentCandle">Текущая свеча.</param> /// <param name="value">Новые данные, с помощью которых принимается решение о необходимости начала или окончания формирования текущей свечи.</param> /// <returns>Новая свеча. Если новую свечу нет необходимости создавать, то возвращается <paramref name="currentCandle"/>. /// Если новую свечу создать невозможно (<paramref name="value"/> не может быть применено к свечам), то возвращается null.</returns> protected virtual TCandle ProcessValue(CandleSeries series, TCandle currentCandle, ICandleBuilderSourceValue value) { if (currentCandle == null || IsCandleFinishedBeforeChange(series, currentCandle, value)) { currentCandle = CreateCandle(series, value); this.AddDebugLog("NewCandle {0} ForValue {1}", currentCandle, value); return(currentCandle); } UpdateCandle(series, currentCandle, value); this.AddDebugLog("UpdatedCandle {0} ForValue {1}", currentCandle, value); return(currentCandle); }
/// <summary> /// Заполнить первоначальные параметры свечи. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="candle">Свеча.</param> /// <param name="value">Данные.</param> /// <returns>Свеча.</returns> protected virtual TCandle FirstInitCandle(CandleSeries series, TCandle candle, ICandleBuilderSourceValue value) { if (candle == null) { throw new ArgumentNullException("candle"); } if (value == null) { throw new ArgumentNullException("value"); } candle.Security = value.Security; candle.OpenPrice = value.Price; candle.ClosePrice = value.Price; candle.LowPrice = value.Price; candle.HighPrice = value.Price; //candle.TotalPrice = value.Price; candle.OpenVolume = value.Volume; candle.CloseVolume = value.Volume; candle.LowVolume = value.Volume; candle.HighVolume = value.Volume; //candle.TotalVolume = value.Volume; return(candle); }
/// <summary> /// Сформирована ли свеча до добавления данных. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="candle">Свеча.</param> /// <param name="value">Данные, с помощью которых принимается решение о необходимости окончания формирования текущей свечи.</param> /// <returns><see langword="true"/>, если свечу необходимо закончить. Иначе, <see langword="false"/>.</returns> protected virtual bool IsCandleFinishedBeforeChange(CandleSeries series, TCandle candle, ICandleBuilderSourceValue value) { return(false); }
/// <summary> /// Создать новую свечу. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="value">Данные, с помощью которых необходимо создать новую свечу.</param> /// <returns>Созданная свеча.</returns> protected virtual TCandle CreateCandle(CandleSeries series, ICandleBuilderSourceValue value) { throw new NotSupportedException(LocalizedStrings.Str637); }
private static RenkoCandle NewCandle(CandleSeries series, decimal openPrice, decimal closePrice, ICandleBuilderSourceValue value) { return(new RenkoCandle { OpenPrice = openPrice, ClosePrice = closePrice, HighPrice = Math.Max(openPrice, closePrice), LowPrice = Math.Min(openPrice, closePrice), TotalPrice = openPrice * value.Volume, OpenVolume = value.Volume, CloseVolume = value.Volume, HighVolume = value.Volume, LowVolume = value.Volume, TotalVolume = value.Volume, Security = series.Security, OpenTime = value.Time, CloseTime = value.Time, HighTime = value.Time, LowTime = value.Time, BoxSize = (Unit)series.Arg, RelativeVolume = value.OrderDirection == null ? 0 : (value.OrderDirection == Sides.Buy ? value.Volume : -value.Volume) }); }
/// <summary> /// Обработать новые данные. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="currentCandle">Текущая свеча.</param> /// <param name="value">Новые данные, с помощью которых принимается решение о необходимости начала или окончания формирования текущей свечи.</param> /// <returns>Новая свеча. Если новую свечу нет необходимости создавать, то возвращается <paramref name="currentCandle"/>. /// Если новую свечу создать невозможно (<paramref name="value"/> не может быть применено к свечам), то возвращается null.</returns> protected override RenkoCandle ProcessValue(CandleSeries series, RenkoCandle currentCandle, ICandleBuilderSourceValue value) { if (value == null) { throw new ArgumentNullException("value"); } if (currentCandle == null) { return(NewCandle(series, value.Price, value.Price, value)); } var delta = currentCandle.BoxSize.Value; if (currentCandle.OpenPrice < currentCandle.ClosePrice) { if ((value.Price - currentCandle.ClosePrice) > delta) { // New bullish candle return(NewCandle(series, currentCandle.ClosePrice, currentCandle.ClosePrice + delta, value)); } if ((currentCandle.OpenPrice - value.Price) > delta) { // New bearish candle return(NewCandle(series, currentCandle.OpenPrice, currentCandle.OpenPrice - delta, value)); } } else { if ((value.Price - currentCandle.OpenPrice) > delta) { // New bullish candle return(NewCandle(series, currentCandle.OpenPrice, currentCandle.OpenPrice + delta, value)); } if ((currentCandle.ClosePrice - value.Price) > delta) { // New bearish candle return(NewCandle(series, currentCandle.ClosePrice, currentCandle.ClosePrice - delta, value)); } } return(UpdateRenkoCandle(currentCandle, value)); }
/// <summary> /// To update the profile with new value. /// </summary> /// <param name="value">Value.</param> public void Update(ICandleBuilderSourceValue value) { if (value.OrderDirection == null) return; UpdatePriceLevel(GetPriceLevel(value.Price), value); }
/// <summary> /// To add data for the candle. /// </summary> /// <param name="series">Candles series.</param> /// <param name="candle">The candle for which you need to add data.</param> /// <param name="value">New data.</param> public void AddValue(CandleSeries series, Candle candle, ICandleBuilderSourceValue value) { if (_valuesKeepTime == TimeSpan.Zero) return; GetInfo(series).AddValue(candle, value); }
/// <summary> /// Сформирована ли свеча до добавления данных. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="candle">Свеча.</param> /// <param name="value">Данные, с помощью которых принимается решение о необходимости окончания формирования текущей свечи.</param> /// <returns><see langword="true"/>, если свечу необходимо закончить. Иначе, <see langword="false"/>.</returns> protected override bool IsCandleFinishedBeforeChange(CandleSeries series, TickCandle candle, ICandleBuilderSourceValue value) { return(candle.CurrentTradeCount >= candle.MaxTradeCount); }
/// <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="value">The new data by which it is decided to start or end the current candle creation.</param> /// <returns>A new candle. If there is not necessary to create a new candle, then <paramref name="currentCandle" /> is returned. If it is impossible to create a new candle (<paramref name="value" /> cannot be applied to candles), then <see langword="null" /> is returned.</returns> protected virtual TCandleMessage ProcessValue(MarketDataMessage message, TCandleMessage currentCandle, ICandleBuilderSourceValue value) { if (currentCandle == null || IsCandleFinishedBeforeChange(message, currentCandle, value)) { currentCandle = CreateCandle(message, currentCandle, value); this.AddDebugLog("NewCandle {0} ForValue {1}", currentCandle, value); return(currentCandle); } UpdateCandle(message, currentCandle, value); // TODO performance //this.AddDebugLog("UpdatedCandle {0} ForValue {1}", currentCandle, value); return(currentCandle); }
/// <summary> /// Обновить свечу данными. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="candle">Свеча.</param> /// <param name="value">Данные.</param> protected override void UpdateCandle(CandleSeries series, TickCandle candle, ICandleBuilderSourceValue value) { base.UpdateCandle(series, candle, value); candle.CurrentTradeCount++; }
/// <summary> /// Whether the candle is created before data adding. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="candle">Candle.</param> /// <param name="value">Data by which it is decided to end the current candle creation.</param> /// <returns><see langword="true" /> if the candle should be finished. Otherwise, <see langword="false" />.</returns> protected override bool IsCandleFinishedBeforeChange(MarketDataMessage message, TimeFrameCandleMessage candle, ICandleBuilderSourceValue value) { return(value.Time < candle.OpenTime || (candle.OpenTime + candle.TimeFrame) <= value.Time); }
/// <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="value">The new data by which it is decided to start or end the current candle creation.</param> /// <returns>A new candles changes.</returns> public IEnumerable <CandleMessage> Process(MarketDataMessage message, CandleMessage currentCandle, ICandleBuilderSourceValue value) { var changes = new List <CandleMessage>(); Process(message, currentCandle, value, changes); return(changes); }
/// <summary> /// Whether the candle is created before data adding. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="candle">Candle.</param> /// <param name="value">Data by which it is decided to end the current candle creation.</param> /// <returns><see langword="true" /> if the candle should be finished. Otherwise, <see langword="false" />.</returns> protected override bool IsCandleFinishedBeforeChange(MarketDataMessage message, TickCandleMessage candle, ICandleBuilderSourceValue value) { return(candle.TotalTicks != null && candle.TotalTicks.Value >= candle.MaxTradeCount); }
/// <inheritdoc /> public override void Process(MarketDataMessage message, CandleMessage currentCandle, ICandleBuilderSourceValue value, IList <CandleMessage> changes) { var currentPnFCandle = (PnFCandleMessage)currentCandle; var price = value.Price; var volume = value.Volume; var time = value.Time; var side = value.OrderDirection; var pnf = (PnFArg)message.Arg; var pnfStep = (decimal)(1 * pnf.BoxSize); if (currentPnFCandle == null) { var openPrice = MathHelper.Floor(price, pnfStep); var highPrice = openPrice + pnfStep; changes.Add(CreateCandle(message, pnf, openPrice, highPrice, openPrice, highPrice, price, volume, side, time)); } else { if (currentPnFCandle.LowPrice <= price && price <= currentPnFCandle.HighPrice) { UpdateCandle(currentPnFCandle, price, volume, time, side); changes.Add(currentPnFCandle); } else { var isX = currentPnFCandle.OpenPrice < currentPnFCandle.ClosePrice; if (isX) { if (price > currentPnFCandle.HighPrice) { currentPnFCandle.HighPrice = currentPnFCandle.ClosePrice = MathHelper.Floor(price, pnfStep) + pnfStep; UpdateCandle(currentPnFCandle, price, volume, time, side); changes.Add(currentPnFCandle); } else if (price < (currentPnFCandle.HighPrice - pnfStep * pnf.ReversalAmount)) { currentPnFCandle.State = CandleStates.Finished; changes.Add(currentPnFCandle); var highPrice = currentPnFCandle.HighPrice - pnfStep; var lowPrice = MathHelper.Floor(price, pnfStep); currentPnFCandle = CreateCandle(message, pnf, highPrice, highPrice, lowPrice, lowPrice, price, volume, side, time); changes.Add(currentPnFCandle); } else { UpdateCandle(currentPnFCandle, price, volume, time, side); changes.Add(currentPnFCandle); } } else { if (price < currentPnFCandle.LowPrice) { currentPnFCandle.LowPrice = currentPnFCandle.ClosePrice = MathHelper.Floor(price, pnfStep); UpdateCandle(currentPnFCandle, price, volume, time, side); changes.Add(currentPnFCandle); } else if (price > (currentPnFCandle.LowPrice + pnfStep * pnf.ReversalAmount)) { currentPnFCandle.State = CandleStates.Finished; changes.Add(currentPnFCandle); var highPrice = MathHelper.Floor(price, pnfStep) + pnfStep; var lowPrice = currentPnFCandle.LowPrice + pnfStep; currentPnFCandle = CreateCandle(message, pnf, lowPrice, highPrice, lowPrice, highPrice, price, volume, side, time); changes.Add(currentPnFCandle); } else { UpdateCandle(currentPnFCandle, price, volume, time, side); changes.Add(currentPnFCandle); } } } } }
/// <summary> /// To create a new candle. /// </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="value">Data with which a new candle should be created.</param> /// <returns>Created candle.</returns> protected override VolumeCandleMessage CreateCandle(MarketDataMessage message, VolumeCandleMessage currentCandle, ICandleBuilderSourceValue value) { return(FirstInitCandle(message, new VolumeCandleMessage { Volume = (decimal)message.Arg, OpenTime = value.Time, CloseTime = value.Time, HighTime = value.Time, LowTime = value.Time, }, value)); }
/// <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="value">The new data by which it is decided to start or end the current candle creation.</param> /// <param name="changes">A new candles changes.</param> public virtual void Process(MarketDataMessage message, CandleMessage currentCandle, ICandleBuilderSourceValue value, IList <CandleMessage> changes) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } var candle = ProcessValue(message, (TCandleMessage)currentCandle, value); if (candle == null) { // skip the value that cannot be processed return; } if (candle == currentCandle) { if (message.IsCalcVolumeProfile) { if (candle.VolumeProfile == null) { throw new InvalidOperationException(); } candle.VolumeProfile.Update(value); } //candle.State = CandleStates.Changed; changes.Add(candle); } else { if (currentCandle != null) { currentCandle.State = CandleStates.Finished; changes.Add(currentCandle); } if (message.IsCalcVolumeProfile) { candle.VolumeProfile = new CandleMessageVolumeProfile(); candle.VolumeProfile.Update(value); } candle.State = CandleStates.Active; changes.Add(candle); } }
/// <summary> /// To create a new candle. /// </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="value">Data with which a new candle should be created.</param> /// <returns>Created candle.</returns> protected override RangeCandleMessage CreateCandle(MarketDataMessage message, RangeCandleMessage currentCandle, ICandleBuilderSourceValue value) { return(FirstInitCandle(message, new RangeCandleMessage { PriceRange = (Unit)message.Arg, OpenTime = value.Time, CloseTime = value.Time, HighTime = value.Time, LowTime = value.Time, }, value)); }
/// <inheritdoc /> public override void Process(MarketDataMessage message, CandleMessage currentCandle, ICandleBuilderSourceValue value, IList <CandleMessage> changes) { var currentRenkoCandle = (RenkoCandleMessage)currentCandle; var price = value.Price; var volume = value.Volume; var time = value.Time; var side = value.OrderDirection; var boxSize = (Unit)message.Arg; var renkoStep = (decimal)(1 * boxSize); if (currentRenkoCandle == null) { var openPrice = MathHelper.Floor(price, renkoStep); changes.Add(CreateCandle(message, boxSize, openPrice, renkoStep, price, volume, side, time)); } else { if (currentRenkoCandle.LowPrice <= price && price <= currentRenkoCandle.HighPrice) { currentRenkoCandle.TotalTicks++; if (volume != null) { currentRenkoCandle.TotalVolume += volume.Value; currentRenkoCandle.TotalPrice += volume.Value * price; currentRenkoCandle.RelativeVolume += side == Sides.Buy ? volume : -volume; } currentRenkoCandle.CloseVolume = volume; currentRenkoCandle.CloseTime = time; currentRenkoCandle.VolumeProfile?.Update(price, volume, side); changes.Add(currentRenkoCandle); } else { currentRenkoCandle.State = CandleStates.Finished; changes.Add(currentRenkoCandle); int times; bool isUp; decimal openPrice; if (price < currentRenkoCandle.LowPrice) { times = (int)((currentRenkoCandle.LowPrice - price) / renkoStep) + 1; isUp = false; openPrice = currentRenkoCandle.LowPrice; } else { times = (int)((price - currentRenkoCandle.HighPrice) / renkoStep) + 1; isUp = true; openPrice = currentRenkoCandle.HighPrice; } for (var i = 0; i < times; i++) { if (isUp) { currentRenkoCandle = CreateCandle(message, boxSize, openPrice, renkoStep, price, volume, side, time); changes.Add(currentRenkoCandle); openPrice += renkoStep; } else { currentRenkoCandle = CreateCandle(message, boxSize, openPrice, -renkoStep, price, volume, side, time); changes.Add(currentRenkoCandle); openPrice -= renkoStep; } currentRenkoCandle.State = CandleStates.Finished; } currentRenkoCandle.State = CandleStates.Active; } } }
/// <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="value">The new data by which it is decided to start or end the current candle creation.</param> /// <returns>A new candles changes.</returns> public IEnumerable <CandleMessage> Process(MarketDataMessage message, ICandleBuilderSourceValue value) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } var info = _info.SafeAdd(message, k => new CandleInfo()); if (info == null) { yield break; } var currCandle = info.CurrentCandle; var candle = ProcessValue(message, (TCandleMessage)currCandle, value); if (candle == null) { // skip the value that cannot be processed yield break; } if (candle == currCandle) { if (message.IsCalcVolumeProfile) { if (info.VolumeProfile == null) { throw new InvalidOperationException(); } info.VolumeProfile.Update(value); } //candle.State = CandleStates.Changed; yield return(candle); } else { if (currCandle != null) { info.CurrentCandle = null; info.VolumeProfile = null; currCandle.State = CandleStates.Finished; yield return(currCandle); } info.CurrentCandle = candle; if (message.IsCalcVolumeProfile) { info.VolumeProfile = new VolumeProfile(); info.VolumeProfile.Update(value); candle.PriceLevels = info.VolumeProfile.PriceLevels; } candle.State = CandleStates.Active; yield return(candle); } }
/// <summary> /// To create a new candle. /// </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="value">Data with which a new candle should be created.</param> /// <returns>Created candle.</returns> protected virtual TCandleMessage CreateCandle(MarketDataMessage message, TCandleMessage currentCandle, ICandleBuilderSourceValue value) { throw new NotSupportedException(LocalizedStrings.Str637); }
private void UpdatePriceLevel(CandlePriceLevel level, ICandleBuilderSourceValue value) { if (level == null) throw new ArgumentNullException(nameof(level)); var side = value.OrderDirection; if (side == null) throw new ArgumentException(nameof(value)); if (side == Sides.Buy) { level.BuyVolume += value.Volume; level.BuyCount++; ((List<decimal>)level.BuyVolumes).Add(value.Volume); } else { level.SellVolume += value.Volume; level.SellCount++; ((List<decimal>)level.SellVolumes).Add(value.Volume); } }
/// <summary> /// Whether the candle is created before data adding. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="candle">Candle.</param> /// <param name="value">Data by which it is decided to end the current candle creation.</param> /// <returns><see langword="true" /> if the candle should be finished. Otherwise, <see langword="false" />.</returns> protected virtual bool IsCandleFinishedBeforeChange(MarketDataMessage message, TCandleMessage candle, ICandleBuilderSourceValue value) { return(false); }
/// <summary> /// To fill in the initial candle settings. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="candle">Candle.</param> /// <param name="value">Data.</param> /// <returns>Candle.</returns> protected virtual TCandleMessage FirstInitCandle(MarketDataMessage message, TCandleMessage candle, ICandleBuilderSourceValue value) { if (candle == null) { throw new ArgumentNullException(nameof(candle)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } candle.SecurityId = message.SecurityId; candle.OpenPrice = value.Price; candle.ClosePrice = value.Price; candle.LowPrice = value.Price; candle.HighPrice = value.Price; //candle.TotalPrice = value.Price; candle.OpenVolume = value.Volume; candle.CloseVolume = value.Volume; candle.LowVolume = value.Volume; candle.HighVolume = value.Volume; candle.TotalVolume = value.Volume ?? 0; return(candle); }
/// <summary> /// To update the candle data. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="candle">Candle.</param> /// <param name="value">Data.</param> protected virtual void UpdateCandle(MarketDataMessage message, TCandleMessage candle, ICandleBuilderSourceValue value) { if (candle == null) { throw new ArgumentNullException(nameof(candle)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } Update(candle, value); }
public void AddValue(Candle candle, ICandleBuilderSourceValue value) { if (candle == null) throw new ArgumentNullException("candle"); if (value == null) throw new ArgumentNullException("value"); _candleValues.SafeAdd(candle).AddLast(value); _valuesStat.Add(value); if (_firstValueTime == 0) _firstValueTime = value.Time.UtcTicks; _lastValueTime = value.Time.UtcTicks; RecycleValues(); }
/// <summary> /// Создать новую свечу. /// </summary> /// <param name="series">Серия свечек.</param> /// <param name="value">Данные, с помощью которых необходимо создать новую свечу.</param> /// <returns>Созданная свеча.</returns> protected override PnFCandle CreateCandle(CandleSeries series, ICandleBuilderSourceValue value) { var arg = (PnFArg)series.Arg; var boxSize = arg.BoxSize; if (CandleManager == null) { throw new InvalidOperationException(LocalizedStrings.CandleManagerIsNotSet); } var pnfCandle = (PnFCandle)CandleManager.Container.GetCandle(series, 0); var candle = new PnFCandle { PnFArg = arg, OpenTime = value.Time, CloseTime = value.Time, HighTime = value.Time, LowTime = value.Time, Security = value.Security, OpenVolume = value.Volume, CloseVolume = value.Volume, LowVolume = value.Volume, HighVolume = value.Volume, TotalVolume = value.Volume, TotalPrice = value.Price * value.Volume, Type = pnfCandle == null ? PnFTypes.X : (pnfCandle.Type == PnFTypes.X ? PnFTypes.O : PnFTypes.X), }; if (pnfCandle == null) { candle.OpenPrice = boxSize.AlignPrice(value.Price, value.Price); if (candle.Type == PnFTypes.X) { candle.ClosePrice = (decimal)(candle.OpenPrice + boxSize); } else { candle.ClosePrice = (decimal)(candle.OpenPrice - boxSize); } } else { candle.OpenPrice = (decimal)((pnfCandle.Type == PnFTypes.X) ? pnfCandle.ClosePrice - boxSize : pnfCandle.ClosePrice + boxSize); var price = boxSize.AlignPrice(candle.OpenPrice, value.Price); if (candle.Type == PnFTypes.X) { candle.ClosePrice = (decimal)(price + boxSize); } else { candle.ClosePrice = (decimal)(price - boxSize); } } if (candle.Type == PnFTypes.X) { candle.LowPrice = candle.OpenPrice; candle.HighPrice = candle.ClosePrice; } else { candle.LowPrice = candle.ClosePrice; candle.HighPrice = candle.OpenPrice; } return(candle); }