tobin
|
Date: 2/7/2014
|
|
|
|
|
Вы, не пробовали получать инструмент через LookupSecurities(criteria)? Ждал минуты три так и не увидел результата поиска. Получилось подписаться через RegisterTrades(Security) на первый пришедший инструмент после подключения (Connected) и начала экспорта (StartExport()) обновления приходят через событие NewTrades (уже можно ваять ленту [biggrin] ). Сейчас пытаюсь разобраться как подписаться не на первый попавшийся а на любой заданный.
Тут как я понял фишка вот в чем: разберем на примере тиков, есть метод RegisterTrades(Security) - он позволяет "зарегистрировать" инструмент в списке слежения, новый тик приходит через событие NewTrades, получаем IEnumerable<Trade> и далее чего хотим того с ним и делаем, НО для того, что бы "зарегистрировать" инструмент, не достаточно просто создать его через конструктор, его надо найти на сервере. А вот с поиском тут что-то не ладное (это можно наблюдать и в самом APITester'е, который с библиотеками идет, хотя Тестер от Fusion'а в плане поиска работает совсем шустро, я имею ввиду окно MarketMaker). Как возможное решение проблемы, нашел метод GetSecurity, только же он собака не позволяет себя использовать, говорит "inaccessible Я". Воюем дальше [confused]
|
|
|
|
Thanks:
|
|
|
|
|
|
SlashHammer
|
Date: 2/7/2014
|
|
|
|
|
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
|
Date: 2/10/2014
Давайте по порядку. Что-то все намешано в кучу.
Поиска инструментов у Фьюжена нет. Сама система так сделана. У нас есть эвристика ввиде запроса level2 данных. Как только они начинают приходить, то приходит и информация по инструментам.
Тикер в понятии Фьюжена не совпадает с Security. Security - это тикер на конкретном ESN или MM. Чтобы получить агрегированную информацию со средней температурой по больнице нужно делать группировку по Security.Code.
|
|
|
|
Thanks:
|
|
|
|
|
|
tobin
|
Date: 2/10/2014
Подскажите пожалуйста, почему Trade.OrderDirection = null? Ведь остальные данные приходят (Price, Volume, LowPrice и пр)? Где можно найти описание того, как устроена "система Фьюжена" (такая информация помогла бы сократить количество глупых вопросов на порядок)?
|
|
|
|
Thanks:
|
|
|
|
|
|
Mikhail Sukhov
|
Date: 2/10/2014
tobin:
Где можно найти описание того, как устроена "система Фьюжена" (такая информация помогла бы сократить количество глупых вопросов на порядок)?
Обратитесь к вашему брокеру.
|
|
|
|
Thanks:
|
|
|
|
|
|
SlashHammer
|
Date: 2/11/2014
|
|
|
|
|
Давайте по порядку.
Окей, давайте.
Самый главный и наболевший вопрос - как <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
|
Date: 2/11/2014
|
|
|
|
|
Я с вами общался по скайпу, отвечал вам, а вы опять все те же самые вопросы задаете. Хорошо, отвечу еще раз, может быть так нагляднее будет и другие увидят ответы на свои вопросы.
Давайте по порядку.
Окей, давайте.
Самый главный и наболевший вопрос - как правильно создать базу инструментов для своих программ, чтобы они работали во всех методах регистрации получения данных. Даже вернее сказать, как правильно сохранить. Насобирать их кое-как можно, хотя и через _опу.
Это делает Гидра. Программировать не нужно, нужно ее запустить.
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
|
Date: 2/11/2014
Как я уже говорит вам в скайпе, DOM на америке отсутствует. DOM (MarketDepth) - это чисто российский механизм.
Смотреть нужно на Security BestBid/BestAsk. Котировки в них заполняться как только Блэквуд пришлет обновление.
Окей, пусть он называется как хочет, мне главное нужно знать, я вот это получить могу или нет???

Пускай это не полный стакан, просто это демо-аккаунт, и в нём нет NYSE и NASDAQ, но это не важно, важен сам факт возможности или невозможности.
|
|
|
|
Thanks:
|
|
|
|
|
|
Mikhail Sukhov
|
Date: 2/11/2014
SlashHammer:
Да, я уже писал.
Это не стакан в том понимании, что используется в российских биржах. Это level2. Level2 - это лента из последних котировок. Другими словами, чтобы такое получить, нужно выводить строчку за строчкой при обновлении BestBid BestAsk.
|
|
|
|
Thanks:
|
|
|
|
|
|
tobin
|
Date: 2/20/2014
|
|
|
|
|
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 (родной). Ну и ничего так, нормально работает (указать свой пароль/логин!!!)
|
|
|
|
|
|