Example #1
0
        private void DelayedAction(Action action, string actionName)
        {
            var delay = RandomGen.GetInt(1, 2);

            Log($"Action '{actionName}' is delayed for {delay:0.##}sec");
            Task.Delay(delay * 1000).ContinueWith(t => Dispatcher.GuiAsync(action));
        }
Example #2
0
            public void UpdateData(Security sec, decimal price)
            {
                var ps = sec.PriceStep ?? 1;

                var msg = new Level1ChangeMessage
                {
                    SecurityId = sec.ToSecurityId(),
                    ServerTime = DateTimeOffset.Now,
                };

                if (RandomGen.GetBool())
                {
                    msg.Changes.TryAdd(Level1Fields.BestBidPrice, price - RandomGen.GetInt(1, 10) * ps);
                }

                if (RandomGen.GetBool())
                {
                    msg.Changes.TryAdd(Level1Fields.BestAskPrice, price + RandomGen.GetInt(1, 10) * ps);
                }

                foreach (var l1Subscriptions in _l1Subscriptions)
                {
                    _level1Received?.Invoke(l1Subscriptions, msg);
                }
            }
Example #3
0
        private void UpdateRealtimeCandles()
        {
            if (!_historyLoaded || !_isRealTime)
            {
                return;
            }

            var nextTick = (ExecutionMessage)_tradeGenerator.Process(new TimeMessage {
                ServerTime = _lastTime
            });

            if (nextTick != null)
            {
                if (_candleTransform.Process(nextTick))
                {
                    var candles = _candleBuilder.Process(_mdMsg, _currCandle, _candleTransform);

                    foreach (var candle in candles)
                    {
                        _currCandle = candle;
                        _updatedCandles.Add((CandleMessage)candle.Clone());
                    }
                }
            }

            _lastTime += TimeSpan.FromMilliseconds(RandomGen.GetInt(100, 2000));
        }
Example #4
0
        private void UpdateRealtimeCandles()
        {
            if (!_historyLoaded || !_isRealTime)
            {
                return;
            }

            var nextTick = (ExecutionMessage)_tradeGenerator.Process(new TimeMessage {
                ServerTime = _lastTime
            });

            if (nextTick != null)
            {
                if (nextTick.TradePrice != null)
                {
                    _testProvider.UpdateData(_security, nextTick.TradePrice.Value);
                }

                if (_candleTransform.Process(nextTick))
                {
                    var candles = _candleBuilder.Process(this, _candleTransform);

                    foreach (var candle in candles)
                    {
                        _updatedCandles.Add(candle.TypedClone());
                    }
                }
            }

            _lastTime += TimeSpan.FromMilliseconds(RandomGen.GetInt(100, 20000));
        }
Example #5
0
        private void ChartUpdateTimerOnTick(object sender, EventArgs eventArgs)
        {
            if (IsRealtime.IsChecked == true && _lastPrice != 0m)
            {
                var step  = PriceStep.Value ?? 10;
                var price = Round(_lastPrice + (decimal)((RandomGen.GetDouble() - 0.5) * 5 * step), (decimal)step);
                AppendTick(_security, new ExecutionMessage
                {
                    ServerTime = _lastTime,
                    TradePrice = price,
                    Volume     = RandomGen.GetInt(50) + 1
                });
                _lastTime += TimeSpan.FromSeconds(10);
            }

            TimeFrameCandle[] candlesToUpdate;
            lock (_updatedCandles.SyncRoot)
            {
                candlesToUpdate = _updatedCandles.OrderBy(p => p.Key).Select(p => p.Value).ToArray();
                _updatedCandles.Clear();
            }

            _allCandles.AddRange(candlesToUpdate);

            candlesToUpdate.ForEach(c =>
            {
                Chart.Draw(c.OpenTime, new Dictionary <IChartElement, object>
                {
                    { _candleElement1, c },
                });
            });
        }
Example #6
0
        private static Security CreateStrike(decimal strike, decimal oi, decimal iv, OptionTypes type, DateTime expiryDate, Security asset, decimal?lastTrade)
        {
            var s = new Security
            {
                Code                 = "RI {0} {1}".Put(type == OptionTypes.Call ? 'C' : 'P', strike),
                Strike               = strike,
                OpenInterest         = oi,
                ImpliedVolatility    = iv,
                HistoricalVolatility = iv,
                OptionType           = type,
                ExpiryDate           = expiryDate,
                Board                = ExchangeBoard.Forts,
                UnderlyingSecurityId = asset.Id,
                LastTrade            = lastTrade == null ? null : new Trade {
                    Price = lastTrade.Value
                },
                Volume = RandomGen.GetInt(10000),
                Type   = SecurityTypes.Option
            };

            s.BestBid = new Quote(s, s.StepPrice ?? 1m * RandomGen.GetInt(100), s.VolumeStep ?? 1m * RandomGen.GetInt(100), Sides.Buy);
            s.BestAsk = new Quote(s, s.BestBid.Price.Max(s.StepPrice ?? 1m * RandomGen.GetInt(100)), s.VolumeStep ?? 1m * RandomGen.GetInt(100), Sides.Sell);

            return(s);
        }
Example #7
0
        static void Main()
        {
            // creating AAPL security
            var security = new Security
            {
                Id        = "AAPL@NASDAQ",
                PriceStep = 0.1m,
                Decimals  = 1,
            };

            var trades = new List <Trade>();

            // generation 1000 random ticks
            //

            for (var i = 0; i < 1000; i++)
            {
                var t = new Trade
                {
                    Time     = DateTime.Today + TimeSpan.FromMinutes(i),
                    Id       = i + 1,
                    Security = security,
                    Volume   = RandomGen.GetInt(1, 10),
                    Price    = RandomGen.GetInt(1, 100) * security.PriceStep ?? 1m + 99
                };

                trades.Add(t);
            }

            using (var drive = new LocalMarketDataDrive())
            {
                // get AAPL storage
                var aaplStorage = drive.GetSecurityDrive(security);

                // get tick storage
                var tradeStorage = (IMarketDataStorage <Trade>)aaplStorage.GetTickStorage(new CsvMarketDataSerializer <ExecutionMessage>());

                // saving ticks
                tradeStorage.Save(trades);

                // loading ticks
                var loadedTrades = tradeStorage.Load(DateTime.Today, DateTime.Today + TimeSpan.FromMinutes(1000));

                foreach (var trade in loadedTrades)
                {
                    Console.WriteLine(LocalizedStrings.Str2968Params, trade.Id, trade);
                }

                Console.ReadLine();

                // deleting ticks (and removing file)
                tradeStorage.Delete(DateTime.Today, DateTime.Today + TimeSpan.FromMinutes(1000));
            }
        }
Example #8
0
        static void Main()
        {
            // создаем тестовый инструмент
            var security = new Security
            {
                Id        = "TestId",
                PriceStep = 0.1m,
                Decimals  = 1,
            };

            var trades = new List <Trade>();

            // генерируем 1000 произвольных сделок
            //

            for (var i = 0; i < 1000; i++)
            {
                var t = new Trade
                {
                    Time     = DateTime.Today + TimeSpan.FromMinutes(i),
                    Id       = i + 1,
                    Security = security,
                    Volume   = RandomGen.GetInt(1, 10),
                    Price    = RandomGen.GetInt(1, 100) * security.PriceStep + 99
                };

                trades.Add(t);
            }

            var storage = new StorageRegistry();

            // получаем хранилище для тиковых сделок
            var tradeStorage = storage.GetTradeStorage(security);

            // сохраняем сделки
            tradeStorage.Save(trades);

            // загружаем сделки
            var loadedTrades = tradeStorage.Load(DateTime.Today, DateTime.Today + TimeSpan.FromMinutes(1000));

            foreach (var trade in loadedTrades)
            {
                Console.WriteLine(LocalizedStrings.Str2968Params, trade.Id, trade);
            }

            Console.ReadLine();

            // удаляем сделки (очищаем файл)
            tradeStorage.Delete(DateTime.Today, DateTime.Today + TimeSpan.FromMinutes(1000));
        }
Example #9
0
        private void NewAnnotation_Click(object sender, RoutedEventArgs e)
        {
            if (_currCandle == null)
            {
                return;
            }

            var values = Enumerator.GetValues <ChartAnnotationTypes>().ToArray();

            _annotation = new ChartAnnotation {
                Type = values[RandomGen.GetInt(1, values.Length - 1)]
            };
            _annotationData = null;

            Chart.AddElement(_areaComb, _annotation);
            ModifyAnnotation(true);
        }
Example #10
0
        private void ChartUpdateTimerOnTick(object sender, EventArgs eventArgs)
        {
            if (IsRealtime.IsChecked == true && _lastPrice != 0m)
            {
                var step  = _priceStep;
                var price = Round(_lastPrice + (decimal)((RandomGen.GetDouble() - 0.5) * 5 * (double)step), step);
                AppendTick(_security, new ExecutionMessage
                {
                    ServerTime  = _lastTime,
                    TradePrice  = price,
                    TradeVolume = RandomGen.GetInt(50) + 1,
                    OriginSide  = Sides.Buy,
                });
                _lastTime += TimeSpan.FromSeconds(10);
            }

            TimeFrameCandle[] candlesToUpdate;
            lock (_updatedCandles.SyncRoot)
            {
                candlesToUpdate = _updatedCandles.OrderBy(p => p.Key).Select(p => p.Value).ToArray();
                _updatedCandles.Clear();
            }

            var lastCandle = _allCandles.LastOrDefault();

            _allCandles.AddRange(candlesToUpdate.Where(c => lastCandle == null || c.OpenTime != lastCandle.OpenTime));

            var hasValue  = false;
            var chartData = new ChartDrawData();

            foreach (var candle in candlesToUpdate)
            {
                chartData.Group(candle.OpenTime).Add(_candleElement1, candle);
                hasValue = true;
            }

            if (hasValue)
            {
                Chart.Draw(chartData);
            }
        }
Example #11
0
        private void Fill_Click(object sender, RoutedEventArgs e)
        {
            var order = SelectedOrder;

            if (IsInFinalState(order))
            {
                Log($"Unable to fill order in state {order.State}");
                return;
            }

            Log($"Fill order: {order}");

            order.Balance -= RandomGen.GetInt(1, (int)order.Balance);

            if (order.Balance == 0)
            {
                order.State = OrderStates.Done;
                _orders.Remove(order);
            }

            Chart.Draw(new ChartDrawData().Add(_activeOrdersElement, order));
        }
Example #12
0
        private void ChartUpdateTimerOnTick(object sender, EventArgs eventArgs)
        {
            if (!_dataIsLoaded || IsRealtime.IsChecked != true || _lastPrice == 0m)
            {
                return;
            }

            _lastTime += TimeSpan.FromSeconds(10);
            var numCandles = _candles.Count;

            AppendTick(new ExecutionMessage
            {
                ServerTime  = _lastTime,
                TradePrice  = Round(_lastPrice + (decimal)((RandomGen.GetDouble() - 0.5) * 5 * _priceStep), _priceStep),
                TradeVolume = RandomGen.GetInt(50) + 1
            });

            TimeFrameCandle candle;
            var             lastLightCandle = _candles[_candles.Count - 1];

            if (_candles.Count != numCandles && _lastCandle != null)
            {
                _lastCandle.State = CandleStates.Finished;
                DrawCandle(_lastCandle);
            }

            if (_candles.Count != numCandles || _lastCandle == null)
            {
                _lastCandle = candle = lastLightCandle.ToCandle(_tfSpan, _security);
            }
            else
            {
                candle = _lastCandle;
                lastLightCandle.UpdateCandle(candle);
            }

            DrawCandle(candle);
        }
Example #13
0
        private void ChartUpdateTimerOnTick(object sender, EventArgs eventArgs)
        {
            if (_checkRealtime.IsChecked == true && _lastPrice != 0m)
            {
                var step  = _updownPriceStep.Value ?? 10;
                var price = Round(_lastPrice + (decimal)((RandomGen.GetDouble() - 0.5) * 5 * step), (decimal)step);
                AppendTick(new ExecutionMessage
                {
                    ServerTime = _lastTime,
                    TradePrice = price,
                    Volume     = RandomGen.GetInt(50) + 1
                });
                _lastTime += TimeSpan.FromSeconds(10);
            }

            var candlesToUpdate = _updatedCandles.OrderBy(c => c.OpenTime).ToArray();

            _updatedCandles.Clear();

            candlesToUpdate.ForEach(c =>
            {
                _chartCombined.Draw(c.OpenTime, new Dictionary <IChartElement, object> {
                    { _candleElement1, c }
                });
                _chartCombined.Draw(c.OpenTime, new Dictionary <IChartElement, object> {
                    { _bvElement, c }
                });

                _chartBindVisibleRange.Draw(c.OpenTime, new Dictionary <IChartElement, object> {
                    { _candleElement2, c }
                });
                _chartBindVisibleRange.Draw(c.OpenTime, new Dictionary <IChartElement, object> {
                    { _cpElement, c }
                });
            });
        }
        private void StartBtnClick(object sender, RoutedEventArgs e)
        {
            if (_batchEmulation != null)
            {
                _batchEmulation.Resume();
                return;
            }

            if (HistoryPath.Folder.IsEmpty() || !Directory.Exists(HistoryPath.Folder))
            {
                MessageBox.Show(this, LocalizedStrings.Str3014);
                return;
            }

            TestingProcess.Value = 0;
            Curve.Clear();
            Stat.Clear();

            var logManager      = new LogManager();
            var fileLogListener = new FileLogListener("sample.log");

            logManager.Listeners.Add(fileLogListener);

            // SMA periods
            var periods = new List <(int longMa, int shortMa, Color color)>();

            for (var l = 100; l >= 50; l -= 10)
            {
                for (var s = 10; s >= 5; s -= 1)
                {
                    periods.Add((l, s, Color.FromRgb((byte)RandomGen.GetInt(255), (byte)RandomGen.GetInt(255), (byte)RandomGen.GetInt(255))));
                }
            }

            // storage to historical data
            var storageRegistry = new StorageRegistry
            {
                // set historical path
                DefaultDrive = new LocalMarketDataDrive(HistoryPath.Folder)
            };

            var timeFrame = TimeSpan.FromMinutes(1);

            // create test security
            var security = new Security
            {
                Id    = "SBER@TQBR",              // sec id has the same name as folder with historical data
                Code  = "SBER",
                Name  = "SBER",
                Board = ExchangeBoard.Micex,
            };

            var startTime = new DateTime(2020, 4, 1);
            var stopTime  = new DateTime(2020, 4, 20);

            var level1Info = new Level1ChangeMessage
            {
                SecurityId = security.ToSecurityId(),
                ServerTime = startTime,
            }
            .TryAdd(Level1Fields.PriceStep, 0.01m)
            .TryAdd(Level1Fields.StepPrice, 0.01m)
            .TryAdd(Level1Fields.MinPrice, 0.01m)
            .TryAdd(Level1Fields.MaxPrice, 1000000m)
            .TryAdd(Level1Fields.MarginBuy, 10000m)
            .TryAdd(Level1Fields.MarginSell, 10000m);

            // test portfolio
            var portfolio = Portfolio.CreateSimulator();

            // create backtesting connector
            _batchEmulation = new BatchEmulation(new[] { security }, new[] { portfolio }, storageRegistry)
            {
                EmulationSettings =
                {
                    MarketTimeChangedInterval = timeFrame,
                    StartTime = startTime,
                    StopTime  = stopTime,

                    // count of parallel testing strategies
                    // if not set, then CPU count * 2
                    //BatchSize = 3,
                }
            };

            // handle historical time for update ProgressBar
            _batchEmulation.TotalProgressChanged += (currBatch, total) => this.GuiAsync(() => TestingProcess.Value = total);

            _batchEmulation.StateChanged += (oldState, newState) =>
            {
                var isFinished = _batchEmulation.IsFinished;

                if (_batchEmulation.State == ChannelStates.Stopped)
                {
                    _batchEmulation = null;
                }

                this.GuiAsync(() =>
                {
                    switch (newState)
                    {
                    case ChannelStates.Stopping:
                    case ChannelStates.Starting:
                    case ChannelStates.Suspending:
                        SetIsEnabled(false, false, false);
                        break;

                    case ChannelStates.Stopped:
                        SetIsEnabled(true, false, false);

                        if (isFinished)
                        {
                            TestingProcess.Value = TestingProcess.Maximum;
                            MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime));
                        }
                        else
                        {
                            MessageBox.Show(this, LocalizedStrings.cancelled);
                        }

                        break;

                    case ChannelStates.Started:
                        SetIsEnabled(false, true, true);
                        break;

                    case ChannelStates.Suspended:
                        SetIsEnabled(true, false, true);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(newState.ToString());
                    }
                });
            };

            _startEmulationTime = DateTime.Now;

            var strategies = periods
                             .Select(period =>
            {
                var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);

                // create strategy based SMA
                var strategy = new SampleHistoryTesting.SmaStrategy(series)
                {
                    ShortSma = { Length = period.shortMa },
                    LongSma  = { Length = period.longMa },

                    Volume    = 1,
                    Security  = security,
                    Portfolio = portfolio,
                    //Connector = connector,

                    // by default interval is 1 min,
                    // it is excessively for time range with several months
                    UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>()
                };

                this.GuiSync(() =>
                {
                    var curveElem = Curve.CreateCurve(LocalizedStrings.Str3026Params.Put(period.Item1, period.Item2), period.Item3, ChartIndicatorDrawStyles.Line);

                    strategy.PnLChanged += () =>
                    {
                        var data = new ChartDrawData();

                        data
                        .Group(strategy.CurrentTime)
                        .Add(curveElem, strategy.PnL);

                        Curve.Draw(data);
                    };

                    Stat.AddStrategies(new[] { strategy });
                });

                return(strategy);
            });

            // start emulation
            _batchEmulation.Start(strategies, periods.Count);
        }
Example #15
0
        private void ModifyAnnotation(bool isNew)
        {
            Brush RandomBrush()
            {
                var b = new SolidColorBrush(Color.FromRgb((byte)RandomGen.GetInt(0, 255), (byte)RandomGen.GetInt(0, 255), (byte)RandomGen.GetInt(0, 255)));

                b.Freeze();
                return(b);
            }

            if (_annotation == null)
            {
                return;
            }

            IComparable x1, x2, y1, y2;

            var mode = RandomGen.GetDouble() > 0.5 ? AnnotationCoordinateMode.Absolute : AnnotationCoordinateMode.Relative;

            if (_annotationData == null)
            {
                if (mode == AnnotationCoordinateMode.Absolute)
                {
                    GetMiddle(out var x0, out var y0);
                    x1 = x0 - TimeSpan.FromMinutes(RandomGen.GetInt(10, 60));
                    x2 = x0 + TimeSpan.FromMinutes(RandomGen.GetInt(10, 60));
                    y1 = y0 - RandomGen.GetInt(5, 10) * _security.PriceStep ?? 0.01m;
                    y2 = y0 + RandomGen.GetInt(5, 10) * _security.PriceStep ?? 0.01m;
                }
                else
                {
                    x1 = 0.5 - RandomGen.GetDouble() / 10;
                    x2 = 0.5 + RandomGen.GetDouble() / 10;
                    y1 = 0.5 - RandomGen.GetDouble() / 10;
                    y2 = 0.5 - RandomGen.GetDouble() / 10;
                }
            }
            else
            {
                mode = _annotationData.CoordinateMode.Value;

                if (mode == AnnotationCoordinateMode.Absolute)
                {
                    x1 = (DateTimeOffset)_annotationData.X1 - TimeSpan.FromMinutes(1);
                    x2 = (DateTimeOffset)_annotationData.X2 + TimeSpan.FromMinutes(1);
                    y1 = (decimal)_annotationData.Y1 + _security.PriceStep ?? 0.01m;
                    y2 = (decimal)_annotationData.Y2 - _security.PriceStep ?? 0.01m;
                }
                else
                {
                    x1 = ((double)_annotationData.X1) - 0.05;
                    x2 = ((double)_annotationData.X2) + 0.05;
                    y1 = ((double)_annotationData.Y1) - 0.05;
                    y2 = ((double)_annotationData.Y2) + 0.05;
                }
            }

            _dataThreadActions.Add(() =>
            {
                var data = new ChartDrawData.AnnotationData
                {
                    X1         = x1,
                    X2         = x2,
                    Y1         = y1,
                    Y2         = y2,
                    IsVisible  = true,
                    Fill       = RandomBrush(),
                    Stroke     = RandomBrush(),
                    Foreground = RandomBrush(),
                    Thickness  = new Thickness(RandomGen.GetInt(1, 5)),
                };

                if (isNew)
                {
                    data.Text = "random annotation #" + (++_annotationId);
                    data.HorizontalAlignment = HorizontalAlignment.Stretch;
                    data.VerticalAlignment   = VerticalAlignment.Stretch;
                    data.LabelPlacement      = LabelPlacement.Axis;
                    data.ShowLabel           = true;
                    data.CoordinateMode      = mode;
                }

                var dd = new ChartDrawData();
                dd.Add(_annotation, data);

                Chart.Draw(dd);
            });
        }
Example #16
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.ExecutionType != ExecutionTypes.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 trade = new ExecutionMessage
            {
                SecurityId    = SecurityId,
                TradeId       = IdGenerator.GetNextId(),
                ServerTime    = time,
                LocalTime     = time,
                OriginSide    = GenerateOriginSide ? RandomGen.GetEnum <Sides>() : null,
                TradeVolume   = 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);
        }
Example #17
0
            public void UpdateData(Security sec, decimal price)
            {
                var ps = sec.PriceStep ?? 1;

                var list = new List <KeyValuePair <Level1Fields, object> >();

                if (RandomGen.GetBool())
                {
                    list.Add(new KeyValuePair <Level1Fields, object>(Level1Fields.BestBidPrice, price - RandomGen.GetInt(1, 10) * ps));
                }

                if (RandomGen.GetBool())
                {
                    list.Add(new KeyValuePair <Level1Fields, object>(Level1Fields.BestAskPrice, price + RandomGen.GetInt(1, 10) * ps));
                }

                var now = DateTimeOffset.Now;

                ValuesChanged?.Invoke(sec, list, now, now);
            }
Example #18
0
 private static Color GetRandomColor() => Color.FromRgb((byte)RandomGen.GetInt(0, 255), (byte)RandomGen.GetInt(0, 255), (byte)RandomGen.GetInt(0, 255));
        protected override void OnSendInMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Reset:
                SendOutMessage(new ResetMessage());
                break;

            case MessageTypes.Connect:
                SendOutMessage(new ConnectMessage());
                break;

            case MessageTypes.Disconnect:
                SendOutMessage(new DisconnectMessage());
                break;

            case MessageTypes.SecurityLookup:
            {
                var lookupMsg = (SecurityLookupMessage)message;

                foreach (var id in new[] { "RIZ2@FORTS", "@ES#@CMEMINI" })
                {
                    SendOutMessage(new SecurityMessage
                        {
                            SecurityId            = id.ToSecurityId(),
                            OriginalTransactionId = lookupMsg.TransactionId,
                        });
                }

                SendOutMessage(new SecurityLookupResultMessage {
                        OriginalTransactionId = lookupMsg.TransactionId
                    });
                break;
            }

            case MessageTypes.MarketData:
            {
                var mdMsg = (MarketDataMessage)message;

                switch (mdMsg.DataType)
                {
                case MarketDataTypes.CandleTimeFrame:
                {
                    if (mdMsg.IsSubscribe)
                    {
                        var start = mdMsg.From.Value;
                        var stop  = mdMsg.To.Value;

                        var tf = mdMsg.GetTimeFrame();

                        // sends subscribed successfully
                        SendOutMarketDataReply(mdMsg.TransactionId);

                        const decimal step = 0.01m;

                        for (var curr = start; curr < stop; curr += tf)
                        {
                            var price = RandomGen.GetInt(100, 110);

                            var open  = price + RandomGen.GetInt(10) * step;
                            var high  = open + RandomGen.GetInt(10) * step;
                            var low   = high - RandomGen.GetInt(10) * step;
                            var close = low + RandomGen.GetInt(10) * step;

                            if (high < low)
                            {
                                var d = high;
                                high = low;
                                low  = d;
                            }

                            SendOutMessage(new TimeFrameCandleMessage
                                    {
                                        OriginalTransactionId = mdMsg.TransactionId,
                                        OpenPrice             = open,
                                        HighPrice             = high,
                                        LowPrice   = low,
                                        ClosePrice = close,
                                        OpenTime   = curr,
                                        State      = CandleStates.Finished,
                                    });
                        }

                        SendOutMessage(new MarketDataFinishedMessage {
                                    OriginalTransactionId = mdMsg.TransactionId
                                });
                    }
                    else
                    {
                        // sends unsubscribed successfully
                        SendOutMarketDataReply(mdMsg.TransactionId);
                    }

                    break;
                }

                default:
                    // not supported other data types
                    SendOutMarketDataNotSupported(mdMsg.TransactionId);
                    break;
                }

                break;
            }
            }
        }
        /// <summary>
        /// Обработать сообщение.
        /// </summary>
        /// <param name="message">Сообщение.</param>
        /// <returns>Результат обработки. Если будет возрвщено <see langword="null"/>,
        /// то генератору пока недостаточно данных для генерации нового сообщения.</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>(),
                    Price         = _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.GetVolume());

                    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);
        }
Example #21
0
 private void Move_Click(object sender, RoutedEventArgs e)
 {
     Chart_OnMoveOrder(SelectedOrder, SelectedOrder.Price + RandomGen.GetInt(-3, 3) * _priceStep);
 }
Example #22
0
        private void ChartUpdateTimerOnTick(object sender, EventArgs eventArgs)
        {
            if (_historyLoaded && IsRealtime.IsChecked == true)
            {
                var nextTick = (ExecutionMessage)_tradeGenerator.Process(new TimeMessage {
                    ServerTime = _lastTime
                });

                if (nextTick != null)
                {
                    if (_candleTransform.Process(nextTick))
                    {
                        var candles = _candleBuilder.Process(_mdMsg, _currCandle, _candleTransform);

                        lock (_lock)
                        {
                            foreach (var candle in candles)
                            {
                                _currCandle = candle;
                                _updatedCandles[candle.OpenTime] = Tuple.Create(candle, candle.State == CandleStates.Finished);
                            }
                        }
                    }
                }

                _lastTime += TimeSpan.FromSeconds(RandomGen.GetInt(1, 10));
            }

            Tuple <Candle, bool>[] candlesToUpdate;
            lock (_updatedCandles.SyncRoot)
            {
                candlesToUpdate = _updatedCandles.OrderBy(p => p.Key).Select(p => Tuple.Create(p.Value.Item1.ToCandle(_security), p.Value.Item2)).ToArray();
                _updatedCandles.Clear();
            }

            var lastCandle = _allCandles.LastOrDefault();

            _allCandles.AddRange(candlesToUpdate.Where(c => lastCandle == null || c.Item1.OpenTime != lastCandle.OpenTime).Select(t => t.Item1));

            ChartDrawData chartData = null;

            foreach (var tuple in candlesToUpdate)
            {
                var candle       = tuple.Item1;
                var needToFinish = tuple.Item2;

                if (chartData == null)
                {
                    chartData = new ChartDrawData();
                }

                if (needToFinish && candle.State != CandleStates.Finished)
                {
                    candle.State = CandleStates.Finished;
                }

                var chartGroup = chartData.Group(candle.OpenTime);

                lock (_lock)
                {
                    chartGroup.Add(_candleElement, candle);
                }

                foreach (var pair in _indicators.CachedPairs)
                {
                    chartGroup.Add(pair.Key, pair.Value.Process(candle));
                }
            }

            if (chartData != null)
            {
                Chart.Draw(chartData);
            }
        }