Example #1
0
        private static RenkoCandleMessage CreateCandle(MarketDataMessage message, DataType buildFrom, ref VolumeProfileBuilder volumeProfile, Unit boxSize, decimal openPrice, decimal renkoStep, decimal price, decimal?volume, Sides?side, DateTimeOffset time, decimal?oi)
        {
            var candle = new RenkoCandleMessage
            {
                SecurityId = message.SecurityId,
                BoxSize    = boxSize,
                BuildFrom  = buildFrom,

                OpenPrice  = openPrice,
                ClosePrice = openPrice + renkoStep,
                //HighPrice = openPrice + renkoStep,
                //LowPrice = openPrice,
                OpenVolume     = volume,
                CloseVolume    = volume,
                HighVolume     = volume,
                LowVolume      = volume,
                OpenTime       = time,
                CloseTime      = time,
                HighTime       = time,
                LowTime        = time,
                RelativeVolume = side == null ? null : (side == Sides.Buy ? volume : -volume),
                TotalTicks     = 1,
                State          = CandleStates.Active,
                OpenInterest   = oi,
            };

            if (volume != null)
            {
                candle.TotalPrice  += price * volume.Value;
                candle.TotalVolume += volume.Value;
            }

            if (renkoStep > 0)
            {
                candle.HighPrice = candle.ClosePrice;
                candle.LowPrice  = candle.OpenPrice;
            }
            else
            {
                candle.HighPrice = candle.OpenPrice;
                candle.LowPrice  = candle.ClosePrice;
            }

            if (message.IsCalcVolumeProfile)
            {
                var levels = new List <CandlePriceLevel>();

                volumeProfile = new VolumeProfileBuilder(levels);
                volumeProfile.Update(price, volume, side);

                candle.PriceLevels = levels;
            }

            return(candle);
        }
Example #2
0
        private static void UpdateCandle(PnFCandleMessage currentPnFCandle, decimal price, decimal?volume, DateTimeOffset time, Sides?side, decimal?oi, VolumeProfileBuilder volumeProfile)
        {
            currentPnFCandle.TotalTicks = currentPnFCandle.TotalTicks ?? 0 + 1;

            if (volume != null)
            {
                var v = volume.Value;

                currentPnFCandle.TotalVolume += v;
                currentPnFCandle.TotalPrice  += v * price;

                currentPnFCandle.RelativeVolume = currentPnFCandle.RelativeVolume ?? 0 + (side == Sides.Buy ? v : -v);
            }

            currentPnFCandle.CloseVolume = volume;
            currentPnFCandle.CloseTime   = time;

            volumeProfile?.Update(price, volume, side);

            currentPnFCandle.OpenInterest = oi;
        }
        /// <inheritdoc />
        public override void Process(MarketDataMessage message, CandleMessage currentCandle, ICandleBuilderValueTransform transform, ref VolumeProfileBuilder volumeProfile, IList <CandleMessage> changes)
        {
            var currentRenkoCandle = (RenkoCandleMessage)currentCandle;

            var price  = transform.Price;
            var volume = transform.Volume;
            var time   = transform.Time;
            var side   = transform.Side;
            var oi     = transform.OpenInterest;

            var boxSize   = message.GetArg <Unit>();
            var renkoStep = (decimal)(1 * boxSize);

            if (currentRenkoCandle == null)
            {
                var openPrice = price.Floor(renkoStep);

                changes.Add(CreateCandle(message, ref volumeProfile, boxSize, openPrice, renkoStep, price, volume, side, time, oi));
            }
            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;

                    volumeProfile?.Update(price, volume, side);

                    currentRenkoCandle.OpenInterest = oi;

                    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, ref volumeProfile, boxSize, openPrice, renkoStep, price, volume, side, time, oi);
                            changes.Add(currentRenkoCandle);
                            openPrice += renkoStep;
                        }
                        else
                        {
                            currentRenkoCandle = CreateCandle(message, ref volumeProfile, boxSize, openPrice, -renkoStep, price, volume, side, time, oi);
                            changes.Add(currentRenkoCandle);
                            openPrice -= renkoStep;
                        }

                        currentRenkoCandle.State = CandleStates.Finished;
                    }

                    currentRenkoCandle.State = CandleStates.Active;
                }
            }
        }
        private static PnFCandleMessage CreateCandle(MarketDataMessage message, PnFArg pnfArg, decimal openPrice, decimal highPrice, decimal lowPrice, decimal closePrice, decimal price, decimal?volume, Sides?side, DateTimeOffset time, decimal?oi, ref VolumeProfileBuilder volumeProfile)
        {
            var candle = new PnFCandleMessage
            {
                OpenPrice  = openPrice,
                ClosePrice = closePrice,
                HighPrice  = highPrice,
                LowPrice   = lowPrice,
                OpenVolume = volume,
                //CloseVolume = volume,
                HighVolume = volume,
                LowVolume  = volume,
                SecurityId = message.SecurityId,
                OpenTime   = time,
                //CloseTime = time,
                HighTime = time,
                LowTime  = time,
                PnFArg   = pnfArg,
                State    = CandleStates.Active,
            };

            if (message.IsCalcVolumeProfile)
            {
                var levels = new List <CandlePriceLevel>();
                volumeProfile      = new VolumeProfileBuilder(levels);
                candle.PriceLevels = levels;
            }

            UpdateCandle(candle, price, volume, time, side, oi, volumeProfile);

            return(candle);
        }
        /// <inheritdoc />
        public override void Process(MarketDataMessage message, CandleMessage currentCandle, ICandleBuilderValueTransform transform, ref VolumeProfileBuilder volumeProfile, IList <CandleMessage> changes)
        {
            var currentPnFCandle = (PnFCandleMessage)currentCandle;

            var price  = transform.Price;
            var volume = transform.Volume;
            var time   = transform.Time;
            var side   = transform.Side;
            var oi     = transform.OpenInterest;

            var pnf     = message.GetArg <PnFArg>();
            var pnfStep = (decimal)(1 * pnf.BoxSize);

            if (currentPnFCandle == null)
            {
                var openPrice = price.Floor(pnfStep);
                var highPrice = openPrice + pnfStep;

                changes.Add(CreateCandle(message, pnf, openPrice, highPrice, openPrice, highPrice, price, volume, side, time, oi, ref volumeProfile));
            }
            else
            {
                if (currentPnFCandle.LowPrice <= price && price <= currentPnFCandle.HighPrice)
                {
                    UpdateCandle(currentPnFCandle, price, volume, time, side, oi, volumeProfile);
                    changes.Add(currentPnFCandle);
                }
                else
                {
                    var isX = currentPnFCandle.OpenPrice < currentPnFCandle.ClosePrice;

                    if (isX)
                    {
                        if (price > currentPnFCandle.HighPrice)
                        {
                            currentPnFCandle.HighPrice = currentPnFCandle.ClosePrice = price.Floor(pnfStep) + pnfStep;
                            UpdateCandle(currentPnFCandle, price, volume, time, side, oi, volumeProfile);
                            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  = price.Floor(pnfStep);

                            currentPnFCandle = CreateCandle(message, pnf, highPrice, highPrice, lowPrice, lowPrice, price, volume, side, time, oi, ref volumeProfile);
                            changes.Add(currentPnFCandle);
                        }
                        else
                        {
                            UpdateCandle(currentPnFCandle, price, volume, time, side, oi, volumeProfile);
                            changes.Add(currentPnFCandle);
                        }
                    }
                    else
                    {
                        if (price < currentPnFCandle.LowPrice)
                        {
                            currentPnFCandle.LowPrice = currentPnFCandle.ClosePrice = price.Floor(pnfStep);
                            UpdateCandle(currentPnFCandle, price, volume, time, side, oi, volumeProfile);
                            changes.Add(currentPnFCandle);
                        }
                        else if (price > (currentPnFCandle.LowPrice + pnfStep * pnf.ReversalAmount))
                        {
                            currentPnFCandle.State = CandleStates.Finished;
                            changes.Add(currentPnFCandle);

                            var highPrice = price.Floor(pnfStep) + pnfStep;
                            var lowPrice  = currentPnFCandle.LowPrice + pnfStep;

                            currentPnFCandle = CreateCandle(message, pnf, lowPrice, highPrice, lowPrice, highPrice, price, volume, side, time, oi, ref volumeProfile);
                            changes.Add(currentPnFCandle);
                        }
                        else
                        {
                            UpdateCandle(currentPnFCandle, price, volume, time, side, oi, volumeProfile);
                            changes.Add(currentPnFCandle);
                        }
                    }
                }
            }
        }