Подскажите по стакану
Atom Ответить
13.11.2012


Код такой:

Код

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

Фотография
Дата: 14.11.2012
Ответить


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

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

Фотография
Дата: 30.11.2012
Ответить


что бы получать данные из стаканов в 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)

Творог

Фотография
Дата: 19.12.2012
Ответить


Вставил такой код для вывода в текстбокс 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 должен быть, как правильно задать?
Спасибо:

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

Фотография
Дата: 20.12.2012
Ответить


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

Вариант 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;
...
Спасибо: Творог

Творог

Фотография
Дата: 20.12.2012
Ответить


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

Код

                    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;
Спасибо:


Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy