← Atrás

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

Добрый день, в методе подписки на свечки 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), хотя применяю весь набор инструментов одного тикера, но всех возможных площадок, полученных с обеих коннекторов. Одним словом, поток данных в программу продолжается и всё время увеличивается с регистрацией на всё новые тикеры.

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

¿Le resultó útil este tema?

Compartir tema

Comentarios (26)

Iniciar sesión o Crear cuenta, Inicie sesión o regístrese para dejar un comentario

tobin
tobin

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

SlashHammer
SlashHammer Autor

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(), т.к. у разных брокеров они могут отличатся количеством.

Mikhail Sukhov
Mikhail Sukhov

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

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

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

tobin
tobin

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

Mikhail Sukhov
Mikhail Sukhov

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

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

SlashHammer
SlashHammer Autor

Давайте по порядку. Окей, давайте. Самый главный и наболевший вопрос - как <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(" ");
            }
        }


    }
}

Mikhail Sukhov
Mikhail Sukhov

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

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

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

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 не хватает?

SlashHammer
SlashHammer Autor

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

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

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

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

Mikhail Sukhov
Mikhail Sukhov

SlashHammer:

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

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

tobin
tobin

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 (родной). Ну и ничего так, нормально работает (указать свой пароль/логин!!!)

Churchill
1Serg
1Serg

tobin: ...

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

Где взяли IP?

SlashHammer
SlashHammer Autor

Всем привет. Теперь я убеждён на 100% что проблемы с коннектором BlackWood присутствуют. Их описывать надо очень долго, проще сказать что работает, чем что не работает. Главная проблема - инструменты. Закачка инструментов в локальную базу не рациональна, и даже по своей идее - невозможна. Вопросы с этим связанные:

  • как проверить что в базе присутствуют все возможные инструменты?
  • как контролировать изменение инструментов, т.е. актуальность базы?
  • работа с такой базой очень негативно сказывается на производительности приложения я закачивал Гидрой инструменты, как Вы и советовали. Три дня!!! В результате получил базу с ~76к объктов, причём уникальных по тикеру там ~7,5к штук. Т.е. по тикеру почти правильное к-во, но вот если на каждый тикер должно быть по, примерно, 35 площадок, то объектов в базе должно быть 7500 * 35 = 262.500. Как я сказал выше, это качалось три дня, при чём в первый день скачалось ~60к объктов, во второй 10к, в третий 6к, если так и дальше пойдёт, то к лету докачаю 😳 Ввиду этого вижу только два выхода - либо как то всё же реализовывать LookupSecurities, либо генератор инструментов по тикеру, если честно, то в варианте генератора не вижу никаких проблем!!! Но повторюсь, проблем не вижу только потому, что абсолютно нет описания логики работы API, и принципа работы самой торговой системы. И самое главное в этом вопросе - если применять скачанные инструменты, или сгенерированные - результат ОДИН И ТОТ ЖЕ !!! Но об этом дальше.

Вторая проблема - получение данных BestBid и BestAsk. Какие и в каком количестве инструменты я бы не применял (хоть сгенеренные, хоть из базы Гидры), результат один и тот же, данных НЕТ! События SecuritiesChanged, а так же события, в объектах которых есть злосчастный Security приносят этот параметр с BestBid=BestAsk=null. Только изредка бывает проскочит не null, обычно только по одной какой-то площадке в конкретной акции.

Третья проблема - стакан, ну или, если угодно, L2. Событие MarketDepthsChanged не приходит никогда! По вашим путаным объяснениям якобы стакана на американских биржах нет, поэтому и события нет. Вы утверждали что сформировать его (стакан) можно только по ленте событий с Security.BestBid/BestAsk, но...

  • как говорил выше - BestBid=BestAsk=null в 95% событий
  • как по лучшим котировкам(BestBid/BestAsk) можно сформировать глубину???
  • как можно получить стакан в один момент, ведь в терминале тикер ввёл и в доли секунды получил полный стакан, а по BestBid/BestAsk он будет строится заметно дольше. ...и ещё, в IQFeed-коннекторе события MarketDepthsChanged приходят очень активненько, не знаю можно ли по ним построить стакан, но события есть, и не null-евые 😳

Четвёртая проблема - как отправлять заявки не через конкретные площадки, а через роуты и даркпулы. Инструменты с этими параметрами и скачать то нельзя, ведь они в терминал не приходят!

Жду чётких пояснений по каждому пункту. Если хотя бы один из пунктов не разрешится, то использование коннектора BlackwoodTrader можно считать невозможным, а тем более брать за это деньги.

tobin
tobin

[Михаил Сухов] Я удалил содержимое топика, так как это нарушает условие распространения софта. Публикуйте емейл, пускай туда пишут с вопросами. Но не нужно публиковать несанкционированные доступы к чужому ПО на нашем сайте. Хорошо? Иначе будет бан.🙄

SlashHammer
SlashHammer Autor

tobin, спасибо, щаз поковыряюсь. А на счёт S#, я же за него <u>деньги заплатил</u>, а он не рабочий 😑 . Просто так бросить теперь не могу.

Mikhail Sukhov
Mikhail Sukhov

SlashHammer: tobin, спасибо, щаз поковыряюсь. А на счёт S#, я же за него деньги заплатил, а он не рабочий 😑 . Просто так бросить теперь не могу.

Простите что вмешиваюсь в ваш разговор. Но может мне хоть кто-нибудь сказать, что именно не работает? Пример с голым АПИ делает ровно то же самое, что и коннектор. Юзайте его, но решение первоначальных проблем не будет - ибо идет непонимание маркет данных америки, а не апи. Тут никакой АПИ не поможет.

Абсолютно никто из вас не отписался в теме http://stocksharp.com/forum/4354/Tiestirovaniie-novyi-fichiei/ Я так понимаю, бытует мнение, что разработчики должны бегать за пользователям. К сожалению (или к счастью) это не так. Есть проблемы - пишите. Не пишите - значит нет проблем. Вы используете бесплатный софт. Вы тестеры. Не мы.

И добавлю, что за коннектор деньги никто не платил.

tobin
tobin

[Михаил Сухов] Я удалил содержимое топика, так как это нарушает условие распространения софта. Публикуйте емейл, пускай туда пишут с вопросами. Но не нужно публиковать несанкционированные доступы к чужому ПО на нашем сайте. Хорошо? Иначе будет бан.RollEyes Согласен, не подумал.

Абсолютно никто из вас не отписался в теме http://stocksharp.com/fo...aniie-novyi-fichiei.aspx Я так понимаю, бытует мнение, что разработчики должны бегать за пользователям. К сожалению (или к счастью) это не так. Есть проблемы - пишите. Не пишите - значит нет проблем. Вы используете бесплатный софт. Вы тестеры. Не мы. Я чувствую в какую строну идет этот диалог и хочу кое-что разъяснить: я был бы рад если бы косяк был в моем непонимании "Америки" или в неумении правильно пользоваться вашими инструментами, НО обо всем по порядку.

Код с применением нативного API я ужи приводил чуть выше, вот, что он выдает

Вот код консольки с применением S#

using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StockSharp.Blackwood;
using System.Net;
using StockSharp.BusinessEntities;
using Ecng.Serialization;


namespace blackwoodConosole
{
    class Program
    {
        static void Main(string[] args)
        {
            string login = "FUSDEMO33";
            string password = "d8eej4";

            BlackwoodTrader _trader;

            var ipAddr = BlackwoodAddresses.WetBush;
            _trader = new BlackwoodTrader()
                 {
                     Login = login,
                     Password = password,
                     ExecutionAddress = new IPEndPoint(ipAddr, BlackwoodAddresses.ExecutionPort),
                     MarketDataAddress = new IPEndPoint(ipAddr, BlackwoodAddresses.MarketDataPort),
                     HistoricalDataAddress = new IPEndPoint(ipAddr, BlackwoodAddresses.HistoricalDataPort),
                 };

            _trader.Connected += () =>
                {
                    _trader.StartExport();

                    Console.WriteLine("Connected!!!");


                };

            _trader.LookupSecuritiesResult += smas =>
                {
                    foreach (var sec in smas)
                    {
                        _trader.RegisterSecurity(sec);
                        _trader.RegisterTrades(sec);
                    }
                };

            _trader.NewTrades += _trader_NewTrades;

            _trader.Connect();

            Thread.Sleep(7000);

            var criteria = new Security { Code = "FB" };
            _trader.LookupSecurities(criteria);

            while (Console.Read() != 'e') { }
        }


        static void _trader_NewTrades(IEnumerable<Trade> obj)
        {
            
            Console.WriteLine("{0, -10} {1, -10} {2, -10}", obj.Last().Price, obj.Last().Security.Code, obj.Last().OrderDirection);
        }


    }
}

Пришлось сделать запрос после задержки (взял с запасом), потому что LookupSecurities в событии Connected не подхватывался (это особенность внутренней реализации как я понимаю) и вот какой результат можно увидеть Причем интересная особенность (о которой уже упоминалось) первых пару принтов BestAsk и BestBid присутствуют а потом обнуляются.

Скажите пожалуйста, где ошибка?

Mikhail Sukhov
Mikhail Sukhov

tobin: Скажите пожалуйста, где ошибка?

Ошибка в том, что вы не понимаете, что такое площадка. Для вас тикер и инструмент есть одно и то же. Александру я объяснил, так как он купил обучение. А вам не хочется. Если Александр захочет, он вам передаст мою информацию.

SlashHammer
SlashHammer Autor

Всем привет. Mikhail Sukhov только-что продемонстрировал получение событий с <u>котировками</u>, котировки есть, не null, т.е. работает. Правда реализовано через событие NewMessage, пока не разобрался с работой именно с сообщениями, буду разбираться.

tobin
tobin

Забавно получается, мое непонимание не мешает получать данные через родной API, но затрудняет их получение через ваш API 😳 . Впрочем это не столь существенно, задача получения данных решена, остается только выяснить что такое площадка и в чем же разница между тикером и инструментом )). Александр, если вам не трудно, покажите скрин принта, у которого OrderDirection != null, что бы окончательно развеять все сомнения, по поводу и без него.

Mikhail Sukhov
Mikhail Sukhov

tobin: покажите скрин принта, у которого OrderDirection != null, что бы окончательно развеять все сомнения, по поводу и без него.

Покажите как вы получаете это через API и я скажу как это получить через S#.

tobin
tobin

В посте №11 приведен код (я думаю не стоит его сюда снова копировать). Пояснение к коду (по строкам):

16-23 - настройки подключения

25-34 - подключаемся

35 - ждем (если я правильно понимаю подключение происходит в асинхронном режиме и что бы продолжить работу программе необходимо дождаться ответа с сервера IsConnected)

37 - запрашиваем ссылку на инструмент (объект BWStock m_stock = new m_session.GetStock("TIKER") никакой информации не содержит)

39 - подписываемся на принты

40 - запрашиваем данные (запрос на сервер)

С обработчиком я думаю все понятно. Результат работы программы в посте №16 первый скрин. Пример с использованием S# в том же 16м посте (взят из вебинара "Connector Fusion (BlackWood)", переделан под прием принтов).

Mikhail Sukhov
Mikhail Sukhov

Все то же самое получается и через S#. Вы писали про направление тика. Не меняйте тему пожалуйста. Или извинитесь что наврали

tobin
tobin

Во первых, то же самое через S# не получается, внимательно посмотрите на пост №16 второй скрин (перед скрином образец кода, третий раз уже об этом пишу). Во вторых, тема все та же мы говорим о том, при схожих подходах к получению данных результат различен, а именно: через BWAPI приходит side = UP_TICK(DOWN_TICK), через S# приходит OrderDirection = null (и снова отправляю к скринам) И, наконец, в третьих, о каком вранье и извинении идет речь, по вашему мне наверное больше нечем заняться, кроме как устраивать на форуме провокации, если бы все работало так как это описано в справке, меня бы тут не было, допускаю, что я неверно понял описание применения вашего инструмента и поэтому решил обратиться за помощью, что бы выяснить кто и в каком месте не прав. Если мне стоит извиниться за просьбу о помощи, тогда конечно же извините.

Mikhail Sukhov
Mikhail Sukhov

tobin: UP_TICK(DOWN_TICK), через S# приходит OrderDirection = null

И почему вы решили что это одно и то же?

tobin
tobin

StockSharp.chm

Trade.OrderDirection - свойство StockSharp

Направление заявки (покупка или продажа), которая привела к сделке.

Пространство имён: StockSharp.BusinessEntities Сборка: StockSharp.BusinessEntities (в StockSharp.BusinessEntities.dll) Версия: 4.2.2.5 (4.2.2.5) Синтаксис

public Nullable<OrderDirections> OrderDirection { get; set; }

Это описание однозначно говорит о том, свойство должно указывать, была ли сделка совершена по биду, либо по аску. Свойство side указывает указывает на тот же признак.

Mikhail Sukhov
Mikhail Sukhov

tobin: Это описание однозначно говорит о том, свойство должно указывать, была ли сделка совершена по биду, либо по аску. Свойство side указывает указывает на тот же признак.

Посмотрите внимательно апи. И что именно отвечает за признак восходящего и нисходящего тренда. И вообще почитайте про эти термины внимательнее. Тогда может быть вы поймете почему там null.