コード例 #1
0
ファイル: TradeGenerator.cs プロジェクト: ychaim/StockSharp
        /// <summary>
        /// Обработать сообщение.
        /// </summary>
        /// <param name="message">Сообщение.</param>
        /// <returns>Результат обработки. Если будет возрвщено <see langword="null"/>,
        /// то генератору пока недостаточно данных для генерации нового сообщения.</returns>
        protected override Message OnProcess(Message message)
        {
            DateTimeOffset time;

            switch (message.Type)
            {
            case MessageTypes.Board:
                return(null);

            case MessageTypes.Level1Change:
            {
                var l1Msg = (Level1ChangeMessage)message;

                var value = l1Msg.Changes.TryGetValue(Level1Fields.LastTradePrice);

                if (value != null)
                {
                    _lastTradePrice = (decimal)value;
                }

                time = l1Msg.ServerTime;

                break;
            }

            case MessageTypes.Execution:
            {
                var execMsg = (ExecutionMessage)message;

                switch (execMsg.ExecutionType)
                {
                case ExecutionTypes.Tick:
                case ExecutionTypes.Trade:
                    _lastTradePrice = execMsg.TradePrice.Value;
                    break;

                case ExecutionTypes.OrderLog:
                    if (execMsg.TradePrice != null)
                    {
                        _lastTradePrice = execMsg.TradePrice.Value;
                    }
                    break;

                default:
                    return(null);
                }

                time = execMsg.ServerTime;

                break;
            }

            case MessageTypes.Time:
            {
                var timeMsg = (TimeMessage)message;

                time = timeMsg.ServerTime;

                break;
            }

            default:
                return(null);
            }

            if (!IsTimeToGenerate(time))
            {
                return(null);
            }

            var trade = new ExecutionMessage
            {
                SecurityId    = SecurityId,
                TradeId       = IdGenerator.GetNextId(),
                ServerTime    = time,
                LocalTime     = time.LocalDateTime,
                OriginSide    = GenerateDirection ? RandomGen.GetEnum <Sides>() : (Sides?)null,
                Volume        = Volumes.Next(),
                ExecutionType = ExecutionTypes.Tick
            };

            var priceStep = SecurityDefinition.PriceStep ?? 0.01m;

            _lastTradePrice += RandomGen.GetInt(-MaxPriceStepCount, MaxPriceStepCount) * priceStep;

            if (_lastTradePrice <= 0)
            {
                _lastTradePrice = priceStep;
            }

            trade.TradePrice = _lastTradePrice;

            LastGenerationTime = time;

            return(trade);
        }
コード例 #2
0
        /// <summary>
        /// Обработать сообщение.
        /// </summary>
        /// <param name="message">Сообщение.</param>
        /// <returns>Результат обработки. Если будет возрвщено <see langword="null"/>,
        /// то генератору пока недостаточно данных для генерации нового сообщения.</returns>
        protected override Message OnProcess(Message message)
        {
            if (_boardDefinition == null)
            {
                if (message.Type == MessageTypes.Board)
                {
                    _boardDefinition = (BoardMessage)message.Clone();
                }

                return(null);
            }

            DateTimeOffset time;

            switch (message.Type)
            {
            case MessageTypes.Level1Change:
            {
                var l1Msg = (Level1ChangeMessage)message;

                var value = l1Msg.Changes.TryGetValue(Level1Fields.LastTradePrice);

                if (value != null)
                {
                    _lastTradePrice = (decimal)value;
                }

                value = l1Msg.Changes.TryGetValue(Level1Fields.BestBidPrice);

                if (value != null)
                {
                    _bestBidPrice = (decimal)value;
                }

                value = l1Msg.Changes.TryGetValue(Level1Fields.BestAskPrice);

                if (value != null)
                {
                    _bestAskPrice = (decimal)value;
                }

                time = l1Msg.ServerTime;

                break;
            }

            case MessageTypes.Execution:
            {
                var execMsg = (ExecutionMessage)message;

                switch (execMsg.ExecutionType)
                {
                case ExecutionTypes.Tick:
                {
                    var tradePrice = execMsg.TradePrice;

                    if (null == _prevTradePrice)
                    {
                        _prevTradePrice = tradePrice;
                        _bestAskPrice   = tradePrice;
                        _bestBidPrice   = tradePrice;
                    }

                    switch (execMsg.OriginSide)
                    {
                    case null:
                    {
                        if (tradePrice > _prevTradePrice)
                        {
                            _bestAskPrice = tradePrice;
                            //BestBid = PrevTrade;
                            _prevTradePrice = tradePrice;
                        }
                        else if (tradePrice < _prevTradePrice)
                        {
                            _bestBidPrice = tradePrice;
                            //BestAsk = PrevTrade;
                            _prevTradePrice = tradePrice;
                        }

                        break;
                    }

                    case Sides.Buy:
                        _bestAskPrice = tradePrice;
                        break;

                    default:
                        _bestBidPrice = tradePrice;
                        break;
                    }

                    _lastTradePrice = tradePrice;
                    _newTrades      = true;

                    break;
                }

                default:
                    return(null);
                }

                time = execMsg.ServerTime;

                break;
            }

            case MessageTypes.Time:
            {
                var timeMsg = (TimeMessage)message;

                time = timeMsg.ServerTime;

                break;
            }

            default:
                return(null);
            }

            if (_currGenerations == 0 || _bestBidPrice == null || _bestAskPrice == null)
            {
                return(null);
            }

            var isTradeTime = _boardDefinition.WorkingTime.IsTradeTime(message.LocalTime);

            var canProcess = GenerateDepthOnEachTrade && _newTrades
                                ? isTradeTime
                                : (IsTimeToGenerate(time) && isTradeTime);

            if (!canProcess)
            {
                return(null);
            }

            _currGenerations = MaxGenerations;

            var depth = new QuoteChangeMessage
            {
                SecurityId = SecurityId,
                ServerTime = time,
                LocalTime  = time.LocalDateTime,
            };

            if (_bestBidPrice == null || _bestAskPrice == null)
            {
                if (_lastTradePrice == null)
                {
                    throw new InvalidOperationException(LocalizedStrings.Str1142);
                }

                _bestBidPrice = _bestAskPrice = _lastTradePrice;
            }

            if (_currGenerations == 0)
            {
                throw new InvalidOperationException(LocalizedStrings.Str1143);
            }

            var bidPrice = _bestBidPrice;
            var askPrice = _bestAskPrice;

            var minSpred  = MinSpreadStepCount * SecurityDefinition.PriceStep;
            var maxStread = MaxSpreadStepCount * SecurityDefinition.PriceStep;

            if ((askPrice - bidPrice) < minSpred)
            {
                if (_bestBidPrice == _lastTradePrice)                 // up trend
                {
                    askPrice = bidPrice + minSpred;
                }
                else
                {
                    bidPrice = askPrice - minSpred;
                }
            }
            else if ((askPrice - bidPrice) > maxStread)
            {
                if (_bestBidPrice == _lastTradePrice)                 // down trend
                {
                    askPrice = bidPrice + maxStread;
                }
                else
                {
                    bidPrice = askPrice - maxStread;
                }
            }

            var bids = new List <QuoteChange>
            {
                new QuoteChange(Sides.Buy, bidPrice.Value, Volumes.Next())
            };

            var count = MaxBidsDepth - bids.Count;

            for (var i = 0; i < count; i++)
            {
                var quote = CreateQuote(bidPrice.Value, Sides.Buy);

                if (quote.Price <= 0)
                {
                    break;
                }

                bids.Add(quote);
                bidPrice = quote.Price;
            }

            var asks = new List <QuoteChange>
            {
                new QuoteChange(Sides.Sell, askPrice.Value, Volumes.Next())
            };

            count = MaxAsksDepth - asks.Count;

            for (var i = 0; i < count; i++)
            {
                var quote = CreateQuote(askPrice.Value, Sides.Sell);

                if (quote.Price <= 0)
                {
                    break;
                }

                asks.Add(quote);
                askPrice = quote.Price;
            }

            depth.Bids = bids;
            depth.Asks = asks;

            _newTrades = false;

            _currGenerations--;

            return(depth);
        }
コード例 #3
0
        /// <summary>
        /// Process message.
        /// </summary>
        /// <param name="message">Message.</param>
        /// <returns>The result of processing. If <see langword="null" /> is returned, then generator has no sufficient data to generate new message.</returns>
        protected override Message OnProcess(Message message)
        {
            DateTimeOffset time;

            switch (message.Type)
            {
            case MessageTypes.Level1Change:
            {
                var l1Msg = (Level1ChangeMessage)message;

                var value = l1Msg.Changes.TryGetValue(Level1Fields.LastTradePrice);

                if (value != null)
                {
                    _lastOrderPrice = (decimal)value;
                }

                TradeGenerator.Process(message);

                time = l1Msg.ServerTime;
                break;
            }

            case MessageTypes.Execution:
            {
                var execMsg = (ExecutionMessage)message;

                switch (execMsg.ExecutionType)
                {
                case ExecutionTypes.Tick:
                    _lastOrderPrice = execMsg.GetTradePrice();
                    break;

                default:
                    return(null);
                }

                time = execMsg.ServerTime;
                break;
            }

            case MessageTypes.Time:
            {
                var timeMsg = (TimeMessage)message;

                time = timeMsg.ServerTime;

                break;
            }

            default:
                return(null);
            }

            if (!IsTimeToGenerate(time))
            {
                return(null);
            }

            // TODO более реалистичную генерацию, так как сейчас объемы, цены и сделки c потолка

            var action = RandomGen.GetInt(0, 5);

            var isNew = action < 3 || _activeOrders.IsEmpty();

            ExecutionMessage item;

            if (isNew)
            {
                var priceStep = SecurityDefinition.PriceStep ?? 0.01m;

                _lastOrderPrice += RandomGen.GetInt(-MaxPriceStepCount, MaxPriceStepCount) * priceStep;

                if (_lastOrderPrice <= 0)
                {
                    _lastOrderPrice = priceStep;
                }

                item = new ExecutionMessage
                {
                    OrderId       = IdGenerator.GetNextId(),
                    SecurityId    = SecurityId,
                    ServerTime    = time,
                    OrderState    = OrderStates.Active,
                    Volume        = Volumes.Next(),
                    Side          = RandomGen.GetEnum <Sides>(),
                    OrderPrice    = _lastOrderPrice,
                    ExecutionType = ExecutionTypes.OrderLog,
                };

                _activeOrders.Enqueue((ExecutionMessage)item.Clone());
            }
            else
            {
                var activeOrder = _activeOrders.Peek();

                item            = (ExecutionMessage)activeOrder.Clone();
                item.ServerTime = time;

                var isMatched = action == 5;

                ExecutionMessage trade = null;

                if (isMatched)
                {
                    trade = (ExecutionMessage)TradeGenerator.Process(message);
                }

                if (isMatched && trade != null)
                {
                    item.Volume = RandomGen.GetInt(1, (int)activeOrder.SafeGetVolume());

                    item.TradeId     = trade.TradeId;
                    item.TradePrice  = trade.TradePrice;
                    item.TradeStatus = trade.TradeStatus;

                    // TODO
                    //quote.Trade = TradeGenerator.Generate(time);
                    //item.Volume = activeOrder.Volume;

                    //if (item.Side == Sides.Buy && quote.Trade.Price > quote.Order.Price)
                    //	item.TradePrice = item.Price;
                    //else if (item.Side == Sides.Sell && quote.Trade.Price < quote.Order.Price)
                    //	item.TradePrice = item.Price;

                    activeOrder.Volume -= item.Volume;

                    if (activeOrder.Volume == 0)
                    {
                        item.OrderState = OrderStates.Done;
                        _activeOrders.Dequeue();
                    }
                    else
                    {
                        item.OrderState = OrderStates.Active;
                    }
                }
                else
                {
                    item.OrderState  = OrderStates.Done;
                    item.IsCancelled = true;
                    _activeOrders.Dequeue();
                }
            }

            LastGenerationTime = time;

            return(item);
        }
コード例 #4
0
        /// <inheritdoc />
        protected override Message OnProcess(Message message)
        {
            DateTimeOffset time;

            switch (message.Type)
            {
            case MessageTypes.Board:
                return(null);

            case MessageTypes.Level1Change:
            {
                var l1Msg = (Level1ChangeMessage)message;

                var value = l1Msg.TryGetDecimal(Level1Fields.LastTradePrice);

                if (value != null)
                {
                    _lastTradePrice = value.Value;
                }

                time = l1Msg.ServerTime;

                break;
            }

            case MessageTypes.Execution:
            {
                var execMsg = (ExecutionMessage)message;

                var price = execMsg.TradePrice;

                if (price != null)
                {
                    _lastTradePrice = price.Value;
                }
                else if (execMsg.DataType != DataType.OrderLog)
                {
                    return(null);
                }

                time = execMsg.ServerTime;

                break;
            }

            case MessageTypes.Time:
            {
                var timeMsg = (TimeMessage)message;

                time = timeMsg.ServerTime;

                break;
            }

            default:
                return(null);
            }

            if (!IsTimeToGenerate(time))
            {
                return(null);
            }

            var v = Volumes.Next();

            if (v == 0)
            {
                v = 1;
            }

            var trade = new ExecutionMessage
            {
                SecurityId  = SecurityId,
                TradeId     = IdGenerator.GetNextId(),
                ServerTime  = time,
                LocalTime   = time,
                OriginSide  = GenerateOriginSide ? RandomGen.GetEnum <Sides>() : null,
                TradeVolume = v * (SecurityDefinition?.VolumeStep ?? 1m),
                DataTypeEx  = DataType.Ticks
            };

            var priceStep = SecurityDefinition.PriceStep ?? 0.01m;

            _lastTradePrice += RandomGen.GetInt(-MaxPriceStepCount, MaxPriceStepCount) * priceStep;

            if (_lastTradePrice <= 0)
            {
                _lastTradePrice = priceStep;
            }

            trade.TradePrice = _lastTradePrice;

            LastGenerationTime = time;

            return(trade);
        }