← Назад

Подскажите по стакану

Код такой:


Security item = (Security)Securities.SelectedItem;
_trader.RegisterMarketDepth(item);
System.Threading.Thread.Sleep(10000);
MarketDepth itt = _trader.GetMarketDepth(item);
if (itt != null)
{
   for (int i = 0; i < 10; i++)
   {
      Console.WriteLine("itt.BestAsk.Price=" + itt.BestAsk.Price);
   }
}

Почему itt.BestAsk принимает значение null при входе в цикл.(стакан выбранного инструмента открывается в Quik) item задается через combobox как в примере.

Комментарии (5)

Вход или Создать аккаунт, Войдите или зарегистрируйтесь, чтобы оставить комментарий

nuan
nuan

Нужно подписаться на событие обновления стакана. P.S. Пользуясь случаем, не могу не спросить, глубина стакана может быть разная в каждую сторону, та, которая передается это минимальная или средняя??

Игорь Бакулин
Игорь Бакулин

что бы получать данные из стаканов в WPF нужно

  1. Подключиться к квику.

  2. Начать получать данные по DDE

  3. прописать грамотное отсоединение от DEE при выходе

вот примерная реализация


        public MainWindow()
        {
            InitializeComponent();
            Loaded += StartCon;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            if (Trder != null)
            {
                Trder.StopExport();
                Trder.Dispose();
            }

            base.OnClosing(e);
        }

        private void StartCon(object sender, RoutedEventArgs e)
        {
                    if (Trder == null)
                    {
                        Trder = new QuikTrader(QuikTerminal.GetDefaultPath());

                        Trder.ReConnectionSettings.Interval = TimeSpan.FromSeconds(10);
                        Trder.ReConnectionSettings.WorkingTime = Exchange.Rts.WorkingTime;
                        Trder.ReConnectionSettings.ConnectionRestored +=
                            () => this.GuiAsync(() => MessageBox.Show(this, "Соединение восстановлено"));
                        Trder.ConnectionError += error => this.GuiAsync(() => MessageBox.Show(this, error.ToString()));

// Тут регистрация инструментов по которым нужны данные
                        Trder.NewSecurities += securities => this.GuiAsync(() => OnNewSecurities(securities));
// Эта процедура будет вызываться каждый раз когда стаканы изменятся. 
                        Trder.MarketDepthsChanged += depths => this.GuiAsync(() => OnMarketDepthsChanged(depths));

                        Trder.ProcessDataError += ex => System.Diagnostics.Debug.WriteLine(ex);
                        Trder.Connected += () => Trder.StartExport();

                        Trder.Connect();
                    }
        }

Для лучшей читабельности вынес регистрацию инструментов в отдельное место


        private void OnNewSecurities(IEnumerable<Security> securities)
        {
            securities.ForEach(s =>
            {
                 if ((s.Id == "SBER@EQBR") || (s.Id == "SRZ2@RTS"))
                 {
                     Trder.RegisterSecurity(s);
                     Trder.RegisterMarketDepth(s);
                 }
            });
        }

Только после этого данные начнут приходить для выбранных инструментов! Ну и как пример обработка изменений стакана.


        private void OnMarketDepthsChanged(IEnumerable<MarketDepth> depths)
        {
            depths.ForEach(d =>
                {
                    if ((d.Security.Id == "SBER@EQBR") || (d.Security.Id == "SRZ2@RTS"))
                    {
                        string blp = "";
                        string btm = "";
                        string bbid = string.Format("{0}", d.Security.BestBid.Price);
                        string bask = string.Format("{0}", d.Security.BestAsk.Price);
                        if (d.Security.LastTrade != null)
                        {
                            blp = string.Format("{0}", d.Security.LastTrade.Price);
                            btm = string.Format("{0}", d.Security.LastTrade.Time);
                        }
// Тут выводим что надо на форму
                        DispData(d.Security.Id, bbid, bask, blp, btm);
                    }
                });
        }
		
        private void DispData(string acapt, string abid, string aask, string alp, string atm)
        {
            if (acapt == "SBER@EQBR")
            {
// EdХХХ это ТекстБоксы в xaml

                EdTikSr.Text = acapt;
                EdAskSr.Text = aask;
                EdBidSr.Text = abid;
                EdLprSr.Text = alp;
                EdTmSr.Text = atm;
            }

            if (acapt == "SRZ2@RTS")
            {
                EdTikVb.Text = acapt;
                EdAskVb.Text = aask;
                EdBidVb.Text = abid;
                EdLprVb.Text = alp;
                EdTmVb.Text = atm;
            }
        }

Геннадий Ванин (Gennady Vanin)
Творог
Творог

Вставил такой код для вывода в текстбокс tb1 стакана:


        private void OnMarketDepthsChanged(IEnumerable<MarketDepth> depths)
        {
            depths.ForEach(d =>
            {
                if (((d.Security.Id == "RIH3@RTS")))
                {
                    var md = Trader.GetMarketDepth(d.Security);
                    string ostr = "";
                    string bstr = "";
                    int maxd = md.MaxDepth;

                    for (int i = 0; i < maxd; i++)
                    {
                        ostr = ostr + string.Format("Офер {0} = {1}\n", i, md.GetQuote(1, i));
                        bstr = bstr + string.Format("Бид {0} = {1}\n", i, md.GetQuote(0, i));
                    }
                    tb1.Text = ostr + bstr;
                }
            });
        }

В релультате получаю стакан, но форматированный не по моему шаблону, а типа Бид 11 = Бид 152270 75 Как всё-таки выудить отдельно цену и отдельно объём?

А по оферам в методе GetQuote задан неправильный аргумент, т.е. 0 работает, а единичка нет. Там тип Int должен быть, как правильно задать?

Игорь Бакулин
Игорь Бакулин

Разбор данных в стакане (например запись в файл) можно осуществить по разному. вот пару решений.

Вариант 1. Совсем просто.


   private void OnMarketDepthsChanged(IEnumerable<MarketDepth> depths)
   {
     depths.ForEach(d =>
     {
       if (((d.Security.Id == "RIH3@RTS")))
         { 
            string rstr = "";
            rstr = d.ToString()
            string filename = @"c:\1.txt";  // имя файла задаем
            using (var sw = new StreamWriter(filename))
            {
                sw.WriteLine(rstr);
            }
          }
       });
    }

Можно написать отдельно процедуру разбора строки d.ToString(), если кому надо :) в файл записывется ... Бид 150120 3445 Бид 150130 283 Бид 150140 1328 Бид 150150 614 Оффер 150160 307 Оффер 150170 406 Оффер 150180 3021 ...

Вариант 2. более сложный, но в нам можно весь стакан сохранить в том виде в каком нужно тут получается достаточно компактно.


   private void OnMarketDepthsChanged(IEnumerable<MarketDepth> depths)
   {
     depths.ForEach(d =>
     {
       if (((d.Security.Id == "RIH3@RTS")))
         {
            decimal Bask = 0;
            decimal Bbid = 0;

            DateTime dtCur = DateTime.Now;
            string rstrn = string.Format("{0}:{1}:{2}.{3};", dtCur.Hour, dtCur.Minute, dtCur.Second, dtCur.Millisecond);
            string rstr = rstrn;

            foreach (var qoute in Trder.GetMarketDepth(d.Security))
            {
                if (qoute.OrderDirection == OrderDirections.Sell)
                {
                    if (Bask == 0)
                    {
                        Bask = qoute.Price;
                        rstr = rstr + "\r\n" + rstrn;
                    }
                    rstr = rstr + string.Format("{0}/{1};", qoute.Price, qoute.Volume);
                }
                else
                {   
                    Bbid = qoute.Price;
                        rstr = rstr + string.Format("{0}/{1};", qoute.Price, qoute.Volume);
                }                
            }

	    string filename = @"c:\1.txt";  // имя файла задаем
            using (var sw = new StreamWriter(filename))
            {
                sw.WriteLine(rstr);
            }
        }
    } 
  }); 
 }

в файл записывется (1-я строчка Биды, 2-я оффера) ... 19:40:49.705;143530/139;143540/131;143550/85;143560/70;143570/25;143580/43;143590/18;143600/55;143610/38;143620/17; 19:40:49.705;143640/35;143650/62;143660/39;143670/37;143680/152;143690/139;143700/197;143710/99;143720/125;143730/568; 19:40:50.125;143530/139;143540/131;143550/85;143560/70;143570/25;143580/43;143590/18;143600/50;143610/40;143620/20; 19:40:50.125;143640/35;143650/62;143660/39;143670/34;143680/152;143690/142;143700/197;143710/99;143720/125;143730/568; ...

Творог
Творог
Творог

Спустя полгода сделал свой первый стакан 😀 Как-то так:


                    var md = Trader.GetMarketDepth(d.Security);
                    string ostr = "";
                    string bstr = "";
                    int maxd = 20; // md.MaxDepth / 5;
                    
                    for (int i = 0; i < maxd; i++)
                    {
                        ostr = ostr + string.Format("Офер {0} = {1} - {2}\n",
                            maxd - i - 1, md.GetQuote(OrderDirections.Sell, maxd - i - 1).Price, md.GetQuote(OrderDirections.Sell, maxd - i - 1).Volume);
                        bstr = bstr + string.Format("Бид {0} = {1} - {2}\n",
                            i, md.GetQuote(OrderDirections.Buy, i).Price, md.GetQuote(OrderDirections.Buy, i).Volume);
                    }
                    tb1.Text = ostr + bstr;