API 4.2.2.6 несколько вопросов. Blackwood/Fusion

API 4.2.2.6 несколько вопросов. Blackwood/Fusion
Atom
2/7/2014
SlashHammer


Добрый день, в методе подписки на свечки trader.SubscribeCandles(candleSeries, DateTime, DateTime) есть нюанс: он нормально работает только если первый параметр даты (с какой даты получать) находится в промежутке времени с 5:00 до, примерно, 16:10 (в разные дни по разному +/- 10мин). Если время дня этого параметра не попадает в промежуток, то не приходят свечки текущей сессии, только свечки до конца предыдущей. Время указал по Киеву, для Москвы, соответственно +2 Так же пока не ясно как реализовать возможность риалтайм обновления последней свечки и получения новых, исторические свечки загружаются, но последняя остаётся статичной, и не обновляется, ну и новые не появляются, т.е. метод загружает только историю, новых данных не получает. Trader.NewRealTimeCandle - рефлизации такого события в текущем API нет. Неужели надо самому реализовавать формирование свечек на основании NewTrades?

Теперь по событию: trader.SecuritiesChanged В пришедших с событием объектах Security информация есть только в том случае, если ExchangeBoard.Code этого объекта с к-вом символов >= 4. Т.е. если security.ExchangeBoard.Code == "NYSE" || "NASDAQ", то тогда есть все остальные данные в этом объекте, если ExchangeBoard.Code с тремя символами, то все остальные свойства пустые. security.ExchangeBoard.Code с четырмя и более символами приходит только в первых 1-2-ух событиях SecuritiesChanged, только тогда и можно увидеть инфу, дальше это событие приходит всегда только с тремя символами ExchangeBoard.Code, и соответственно, пустое. "NYSE" || "NASDAQ" в инструментах зависит от биржи размещения инструмента, например Майкрософт(MSFT) - NASDAQ, а вот Банк оф Америка (BAC) - NYSE. Дальше идут события с другими площадками, включая даркпулы (ADF), но всё пустое. Вот Скрин Всё то же самое касается и события trader.NewTrades. Скрин

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

  • NewTrades, в которых есть цена сделки и объём, но объект Security содержит только тикер акции и площадку где прошла сделка, никаких ценовых параметров этот объект не содержит (BestAsk, BestBid, BestPair, Asks/BidsCount, Asks/BidsVolume ...).
  • NewSecurities, содержит только ExchangeBoard, все остальные поля либо 0 либо null.
  • SecuritiesChanged содержит только ExchangeBoard, все остальные поля либо 0 либо null. Только первое событие пришедшее после StartExport несёт данные.
  • PortfoliosChanged содержит только RealizedPnL и UnrealizedPnL. Как узнать сколько у меня денег или BuyingPower непонятно.

События связанные со стаканами вообще не приходят, для регистрации стакана использовал инструменты полученные непосредственно через BlackWood, а так-же через IQFeed(реализовывал одновременно два подключения, но стакан пытался зарегить через BlackWood). Кстати, а вот через коннектор IQFeed стакан есть, и события с ним связанные приходят, хотя для регистрации стакана использовал "самодельный" объект Security:


var security = new Security
{
   Code = "MSFT",
   ExchangeBoard = new ExchangeBoard
   {
      Exchange = new Exchange()
   },
};

т.е. полностью пустой объект, указан только тикер, и стакан по всем площадкам начинал обновляться.

Для регистрации получения данных в BlackWoodиспользовал методы:

_trader.SubscribeMarketData(security,MarketDataTypes.LastTrade);
_trader.SubscribeMarketData(security,MarketDataTypes.Trades);
_trader.SubscribeMarketData(security,MarketDataTypes.BestQuotes);
_trader.SubscribeMarketData(security,MarketDataTypes.Candles);
_trader.SubscribeMarketData(security,MarketDataTypes.Level1);
_trader.SubscribeMarketData(security,MarketDataTypes.MarketDepth);
_trader.SubscribeMarketData(security,MarketDataTypes.OrderLog);

<u>а так же аналогичные им _trader.Register...</u> Всё что я регистрирую и субскрайблю данными методами, невозможно потом отрегить или отсубскрайбить соответствующими методами _trader.UnRegister... или _trader.UnSubscribe... (UnSubscribeMarketData, UnSubscribeCandles), хотя применяю весь набор инструментов одного тикера, но всех возможных площадок, полученных с обеих коннекторов. Одним словом, поток данных в программу продолжается и всё время увеличивается с регистрацией на всё новые тикеры.

Заключение: не могу получить хоть какой-нибудь риалтайм минимум данных в программу для принятия торговых решений, прошу помощи.


Tags:


Thanks:


1 2 3  >
tobin

Avatar
Date: 2/7/2014
Reply


Вы, не пробовали получать инструмент через LookupSecurities(criteria)? Ждал минуты три так и не увидел результата поиска. Получилось подписаться через RegisterTrades(Security) на первый пришедший инструмент после подключения (Connected) и начала экспорта (StartExport()) обновления приходят через событие NewTrades (уже можно ваять ленту [biggrin] ). Сейчас пытаюсь разобраться как подписаться не на первый попавшийся а на любой заданный. Тут как я понял фишка вот в чем: разберем на примере тиков, есть метод RegisterTrades(Security) - он позволяет "зарегистрировать" инструмент в списке слежения, новый тик приходит через событие NewTrades, получаем IEnumerable<Trade> и далее чего хотим того с ним и делаем, НО для того, что бы "зарегистрировать" инструмент, не достаточно просто создать его через конструктор, его надо найти на сервере. А вот с поиском тут что-то не ладное (это можно наблюдать и в самом APITester'е, который с библиотеками идет, хотя Тестер от Fusion'а в плане поиска работает совсем шустро, я имею ввиду окно MarketMaker). Как возможное решение проблемы, нашел метод GetSecurity, только же он собака не позволяет себя использовать, говорит "inaccessible Я". Воюем дальше [confused]

Thanks:

SlashHammer

Avatar
Date: 2/7/2014
Reply


LookupSecurities(criteria) - не работает в принципе, вот здесь - Новая версия 4.2.2.5 сказано что ошибка с поиском устранена, хотя о какой ошибке идёт речь, непонятно, оно просто ничего не ищет. Нормально работает только RegisterTrades, трейды исправно приходят, но когда пытаешся из этого пришедшего трейда вытащить объект Security и в нём уже посмотреть BestBid и BestAsk, то они оказываются нулевыми, и даже определить направление этого, пришедшего, трейда не удаётся, ведь определить это можно только сравнив цену трейда с текущими Bid и Ask. А по поводу самого инструмента, то я, как и писал выше, просто создаю объект Security:


var security = new Security
{
   Code = "MSFT",
   ExchangeBoard = new ExchangeBoard
   {
      Exchange = new Exchange()
   },
};

и его использую для регистрации, работает в RegisterTrades и RegisterSecurity, события начинают приходить, при чём со всех доступных для текущего аккаунта Fusion биржевых площадок, только всё с нулевыми Security. А вот в RegisterMarketDepth что только я не применял, ничего не работает, стакана нет!

Для того, чтобы успешно регистрировать заявки на бирже, достаточно создать объект Security вот такого содержания:


var security = new Security
{
   Code = "MSFT",
   Connector = black_trader,  /*Созданный в программе коннектор для подключения*/
   ExchangeBoard = new ExchangeBoard()
   {
      Code = "NYSE",  /*А вот это проблемное место*/
      Exchange = new Exchange()
   }
};

Но очень важная проблема в свойстве ExchangeBoard.Code , там нужно указывать текстовое обозначение площадки, через которую нужно выставить заявку (NYSE, NASDAQ, BATS, EDGA, EDGX ...), на Америке их очень много, и только некоторые можно получить из событий NewSecurity и NewTrades, а кроме площадок ведь существует ещё огромное множество роутов (ASUROUX, NSDQSCAN, NSDQDDOT ...) и даркпулов (XFINDER, DARKPLUS, SMARTDARK ...), они уже просто по имени не выставляются, заявки не проходят с такими именами. Как быть? Что делать? Скорее всего нужны ещё методы типа GetExchangeBoards(), т.к. у разных брокеров они могут отличатся количеством.

Thanks:

Mikhail Sukhov

Avatar
Date: 2/10/2014
Reply


Давайте по порядку. Что-то все намешано в кучу.

Поиска инструментов у Фьюжена нет. Сама система так сделана. У нас есть эвристика ввиде запроса level2 данных. Как только они начинают приходить, то приходит и информация по инструментам.

Тикер в понятии Фьюжена не совпадает с Security. Security - это тикер на конкретном ESN или MM. Чтобы получить агрегированную информацию со средней температурой по больнице нужно делать группировку по Security.Code.

Thanks:

tobin

Avatar
Date: 2/10/2014
Reply


Подскажите пожалуйста, почему Trade.OrderDirection = null? Ведь остальные данные приходят (Price, Volume, LowPrice и пр)? Где можно найти описание того, как устроена "система Фьюжена" (такая информация помогла бы сократить количество глупых вопросов на порядок)?

Thanks:

Mikhail Sukhov

Avatar
Date: 2/10/2014
Reply


tobin: Где можно найти описание того, как устроена "система Фьюжена" (такая информация помогла бы сократить количество глупых вопросов на порядок)?

Обратитесь к вашему брокеру.

Thanks:

SlashHammer

Avatar
Date: 2/11/2014
Reply


Давайте по порядку. Окей, давайте. Самый главный и наболевший вопрос - как <u>правильно</u> создать базу инструментов для своих программ, чтобы они работали во всех методах регистрации получения данных. Даже вернее сказать, как правильно сохранить. Насобирать их кое-как можно, хотя и через _опу. То что надо применять набор инструментов с одинаковым .Code, но разным .ExchangeBoard, я, как бы, понимаю. Только почему тогда работает регистрация .RegisterTrades с инструментом у которого .ExchangeBoard = new ExchangeBoard() ? Т.е. пустой, лишь бы не null.

Теперь размышления. Если по одной акции надо иметь набор инструментов, которые должны отличаться только ExchangeBoard, при чём ExchangeBoardзаранее известны, почему бы не запрограммерить метод типа:

Security[] AmerSecurityGenerator(stringticker )

который возвратит массив инструментов с одинаковым .Code, но разными .ExchangeBoard и, если надо, .Id ? Может и не надо создавать базу инструментов??? Собсно, я так и делал, потом делал цикл с регистрацией трёх десятков инструментов на получение стакана (.RegisterMarketDepth). И ничего. Стакана так и не было, ни .NewMarketDepth, ни .MarketDepthChanged. Также и .SecuritiesChanged после соответствующей регистрации, приходил пустой, т.е. сам инструмент в событии был, ExchangeBoardв инструменте был заполнен, а все котировки были null.

<u>Вот и вопрос: "Что же всё-таки надо применять для регистрации"???</u>

И где взять то что надо применять, и почему его вообще надо где то брать, откуда сам Fusion их берёт? Так же очень хотелось бы понимать механизмы работы методов, да и вообще, описание к API просто "невероятно информативное и подробное", и с " простыми примерами", что не может не радовать :((((

А лучше всего, было бы сделать отдельный видеоурок по Америке, раз уж она так сильно отличается от всего остального. А то деньги за видеоуроки уплачены, а толку от них null. Возникает неприятное чувство "кидалова", извините.

Насканеннные ExchangeBoard : Скрин два списка, первый получен из событий NewTrades после регистрации на 30 первых пришедших инструментов по NewSecurities, второй список из событий NewSecurities, звёздочкой помечены совпадающие

...и програмка:


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using StockSharp.Blackwood;
using StockSharp.BusinessEntities;

namespace CatchExchangeBoards
{
    class Program
    {
        static void Main()
        {
            var EBfromTrades = new List<ExchangeBoard>();
            var EBfromNewSecurs = new List<ExchangeBoard>();

            IConnector trdr = new BlackwoodTrader
            {
                Login = "FUSDEMO01",
                Password = "I8WRgA",
                MarketDataAddress = new IPEndPoint(BlackwoodAddresses.WetBush, BlackwoodAddresses.MarketDataPort),
                ExecutionAddress = new IPEndPoint(BlackwoodAddresses.WetBush, BlackwoodAddresses.ExecutionPort),
                HistoricalDataAddress = new IPEndPoint(BlackwoodAddresses.WetBush, BlackwoodAddresses.HistoricalDataPort)
            };

            trdr.Connected += trdr.StartExport;

            trdr.ExportStarted += () =>
            {
                Debug.WriteLine("Подключено!");

                trdr.NewSecurities += securities =>
                {
                    foreach (var security in securities)
                    {
                        if (trdr.RegisteredTrades.Count() < 30)
                            trdr.RegisterTrades(security);

                        if (EBfromNewSecurs.Find(eb => eb == security.ExchangeBoard) == null)
                        {
                            EBfromNewSecurs.Add(security.ExchangeBoard);
                            EbOnScreen(EBfromTrades, EBfromNewSecurs);
                        }
                    }
                };

                trdr.NewTrades += trdes =>
                {
                    foreach (var trade in trdes)
                    {
                        if (EBfromTrades.Find(eb => eb == trade.Security.ExchangeBoard) == null)
                        {
                            EBfromTrades.Add(trade.Security.ExchangeBoard);
                            EbOnScreen(EBfromTrades,EBfromNewSecurs);
                        }
                    }
                    
                };
            };
            
            trdr.Connect();
            Console.ReadLine();
        }

        static void EbOnScreen(List<ExchangeBoard> ebt, List<ExchangeBoard> ebs)
        {
            Console.Clear();
            Console.SetCursorPosition(0,1);
            Console.Write("From trades({0}): \tFrom NewSecurities({1}):",ebt.Count,ebs.Count);

            var count = ebt.Count > ebs.Count ? ebt.Count : ebs.Count;

            for (var i = 0; i < count; i++)
            {
                Console.SetCursorPosition(0, i+2);
                if (ebt.Count > i)
                {
                    Console.Write(ebt[i].Code);
                    if (ebs.Contains(ebt[i]))
                        Console.Write(" *");
                }
                else
                    Console.Write(" ");

                Console.SetCursorPosition(24, i+2);
                if (ebs.Count > i)
                {
                    Console.Write(ebs[i].Code);
                    if (ebt.Contains(ebs[i]))
                        Console.Write(" *");
                }
                else
                    Console.Write(" ");
            }
        }


    }
}

Thanks:

Mikhail Sukhov

Avatar
Date: 2/11/2014
Reply


Я с вами общался по скайпу, отвечал вам, а вы опять все те же самые вопросы задаете. Хорошо, отвечу еще раз, может быть так нагляднее будет и другие увидят ответы на свои вопросы.

Давайте по порядку. Окей, давайте. Самый главный и наболевший вопрос - как правильно создать базу инструментов для своих программ, чтобы они работали во всех методах регистрации получения данных. Даже вернее сказать, как правильно сохранить. Насобирать их кое-как можно, хотя и через _опу.

Это делает Гидра. Программировать не нужно, нужно ее запустить.

SlashHammer: То что надо применять набор инструментов с одинаковым .Code, но разным .ExchangeBoard, я, как бы, понимаю. Только почему тогда работает регистрация .RegisterTrades с инструментом у которого .ExchangeBoard = new ExchangeBoard() ? Т.е. пустой, лишь бы не null.

Потому что Блэквуд гонит данные со всех площадок и ему достаточно лишь тикера.

SlashHammer: Теперь размышления. Если по одной акции надо иметь набор инструментов, которые должны отличаться только ExchangeBoard, при чём ExchangeBoardзаранее известны, почему бы не запрограммерить метод типа:

Security[] AmerSecurityGenerator(stringticker )

который возвратит массив инструментов с одинаковым .Code, но разными .ExchangeBoard и, если надо, .Id ? Может и не надо создавать базу инструментов???

Потому что одна и та же акция не торгуется на всех площадках.

SlashHammer: Собсно, я так и делал, потом делал цикл с регистрацией трёх десятков инструментов на получение стакана (.RegisterMarketDepth). И ничего. Стакана так и не было, ни .NewMarketDepth, ни .MarketDepthChanged. Также и .SecuritiesChanged после соответствующей регистрации, приходил пустой, т.е. сам инструмент в событии был, ExchangeBoardв инструменте был заполнен, а все котировки были null.

Как я уже говорит вам в скайпе, DOM на америке отсутствует. DOM (MarketDepth) - это чисто российский механизм.

Смотреть нужно на Security BestBid/BestAsk. Котировки в них заполняться как только Блэквуд пришлет обновление.

SlashHammer: Вот и вопрос: "Что же всё-таки надо применять для регистрации"???

Вызвать метод RegisterSecurity.

SlashHammer: И где взять то что надо применять, и почему его вообще надо где то брать, откуда сам Fusion их берёт? Так же очень хотелось бы понимать механизмы работы методов, да и вообще, описание к API просто "невероятно информативное и подробное", и с " простыми примерами", что не может не радовать :((((

SampleBlackwood не хватает?

Thanks:

SlashHammer

Avatar
Date: 2/11/2014
Reply


Как я уже говорит вам в скайпе, DOM на америке отсутствует. DOM (MarketDepth) - это чисто российский механизм.

Смотреть нужно на Security BestBid/BestAsk. Котировки в них заполняться как только Блэквуд пришлет обновление.

Окей, пусть он называется как хочет, мне главное нужно знать, я вот это получить могу или нет??? стакан Fusion

Пускай это не полный стакан, просто это демо-аккаунт, и в нём нет NYSE и NASDAQ, но это не важно, важен сам факт возможности или невозможности.

Thanks:

Mikhail Sukhov

Avatar
Date: 2/11/2014
Reply


SlashHammer:

Да, я уже писал.

Это не стакан в том понимании, что используется в российских биржах. Это level2. Level2 - это лента из последних котировок. Другими словами, чтобы такое получить, нужно выводить строчку за строчкой при обновлении BestBid BestAsk.

Thanks:

tobin

Avatar
Date: 2/20/2014
Reply



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Blackwood.Framework;
using Pacmid.Messages;
using System.Windows.Forms;

namespace BWConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            BWSession m_session = new BWSession();
            BWStock m_stock;
            string password = "??????";                                                                  //пароль указал, да?
            string login = "?????????";                                                                  
            int executionPort = 5000;
            int historicDataPort = 5300;
            int marketDataPort = 5200;
            var bwIP = System.Net.IPAddress.Parse("72.5.42.156");

            try
            {
                m_session.ConnectToOrderRouting(login, password, bwIP, executionPort, true, true, true, true);
                m_session.ConnectToMarketData(login, password, bwIP, marketDataPort, true);
                m_session.ConnectToHistoricData(login, password, bwIP, historicDataPort);
            }
            catch (ClientPortalConnectionException)
            {
                MessageBox.Show("Unable to connect to market data client portal.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            while (!m_session.IsConnectedToBlackwood) { }
            Console.WriteLine("Соединение установлено");                                    //ждемс
            m_stock = m_session.GetStock("CLF");                                            //тикер!!!
            //m_stock.OnSymbolDataUpdate3 += m_stock_OnSymbolDataUpdate3;
            m_stock.OnTrade3 += m_stock_OnTrade3;                                           //пришлите мне пожалста принты
            m_stock.SubscribeLevel2();                                                      //я настаиваю!!!
            while (Console.Read() != 'e') { }
        }

        static void m_stock_OnTrade3(object sender, MsgTrade print)
        {
            Console.WriteLine("{0, -10} {1, -10} {2, -10} {3, -10}", print.Time.Value.ToString("HH:mm:ss"), print.Price.Value.ToString("F"), print.TradeSize, print.Tick.Value);
        }

        static void m_stock_OnSymbolDataUpdate3(object sender, MsgSymbolData quote)
        {
            Console.WriteLine("{0, -10} {1, -10} {2, -10}", quote.LastTrade.Time.Value.ToString("HH:mm:ss"), quote.LastTrade.Price.Value.ToString("F"), quote.Volume.ToString());
        }
    }
}


Blackwood API (родной). Ну и ничего так, нормально работает (указать свой пароль/логин!!!)

Thanks: Churchill
1 2 3  >

Attach files by dragging & dropping, , or pasting from the clipboard.

loading
clippy