Добрый день. Очень понравилась идея использования Вашей библиотеки для реализации роботов. Подскажите, пожалуйста:
- Как идентифицировать заявку? //например, выставляю заявку buy RIZ0 4 контракта по цене 160500. Каким образом далее смогу ее отслеживать? Вариант с использованием таблицы сделок не подходит - необходимо реализовать контроль исполнения заявок пользуясь исключительно информацией из таблицы заявок. С языком C# только начал разбираться, возможно поэтому не нашел в представленных в дистрибутиве S# проектах примеров контроля состояния заявки по ее уникальному признаку.
- Верно ли я понимаю суть работы с Квиком: для реализации автономного робота необходимо организовать два потока на C#:
- первый: выполняет функции получения данных из Квика через DDE сервер (используя библиотеку S#);
- второй: непосредственно реализует алгоритм выставления и снятия заявок. Можно ли обойтись одним потоком?
Comentários (506)
Os comentários neste tópico estão bloqueados
Так как я то-же только начинаю программировать с использованием S# пишу в этой теме. Вопрос такой: Отчего в примерах (которые идут с S#) подключение классов происходит после команды namespace и обязательно ли подключать именно так?
Посмотреть в увеличенном варианте.
в свойствах проекта какая версия .Net указана ? надо 3.5
я под 4.0 успешно пишу. там главное - чтоб было просто 4.0 а не client profile
Был 4 Фреймворк установлен. Спасибо подправил.
напишу в эту тему, вопрос у меня вроде довольно тривиальный.
Что нужно для отправки заявки? сам синтаксис я посмотрела, с этим вроде все понятно. А как конкретно, по действиям?
Как минимум экспорт инструментов. Если нужно отслеживать состояние заявки и полученные сделки - еще и экспорт заявок + моих сделок. Ну и так далее.
понятно, спасибо, буду пробовать =)
таблица инструментов - это таблица котировок текущего инструмента?
http://stocksharp.com/doc/help/html/5c13da7b-b6e4-4fd4-958a-66c93c58b941.htm (3-ий скрин)
сделала все, как описано (загрузила настройки расположения окон) при попытке отправки заявки получается это
Order.Portfolio чем инициализировали?
Предполагаю, что портфель из выпадающего списка не выбрали.
Действительно, в этот раз при запуске появился номер счета на выбор. Заявка отправилась, спасибо =)
а как экспортировать одновременно и CustomPortfolio и обычные таблицы? у меня в итоге выходит, что с CustomPortfolio все в порядке, а по остальным таблицам нет данных.
и еще вопрос - что-то я совсем запуталась. Есть данные, получаемые из Quik, как раз этот CustomPortfolio, как из примера Sample. Хранятся они в _portfolioWindow.Portfolios; Объявлено оно в классе MainWindow. Как из другого класса получить доступ к полям _portfolioWindow.Portfolios? Объявления экземпляра MainWindow я не нашла.
upd: нашла. Он называется MainWindow.Instance, shame on me.
Вылезает такая ошибка, как в примере, так и у меня, но заявки отправляются. Где нужно посмотреть? В настройке таблиц Quik'а или где-то у себя?
Значит отсутствует информация об инструменте, для которого есть упоминание в таблице бумажных позиций.
То есть, она отсутствует в самом quik, и она не нужна?
Нужна или нет - это Вам решать. Если данный инструмент не нужен - сделайте фильтр на таблицу позиций, чтобы сообщение не выскакивало.
все, понятно, спасибо =)
А что означает "Превышен лимит по инструменту?" отправляю заявку так
Это лучше на сайте Квика поискать.
или откуда вообще вытаскивать Security?
ITrader.Securities, ITrader.NewSecurities. Как использовать показано в примерах.
Просто дело в том, когда я отправляю заявку из окна инструментов, в примере, заявка нормально отправляется, а когда я пытаюсь сделать это программно, так, как я писала выше - вылезает эта ошибка, значит, что-то у меня там с параметрами.
все, поняла, при отправке заявки на продажу (и из примера тоже), вылезает эта ошибка. Оказывается, это возникает при недостатке ресурсов под заявку, то есть продавать нечего. А у Quik'а, как обычно, один ответ на все ошибки =)
Использую S# выставляя ордер в Quik. При создании ордеров явно указываю: Comment = "мой коммент 123" В Квике в таблице "Заявки" в поле "Комментарии" пишет "S#" для любого выставляемого ордера. При проверке: MessageBox.Show("комментарий="+ord.Comment); оказывается, что поле Comment, создаваемого ордера, содержит значение "мой коммент 123". В чем дело? Как сделать так, чтобы в Квике в таблице Заявки в поле "Комментарии" отражалось значение мой коммент 123"?
Это вопрос из топ 10... Я передаю признак кода клиента как "S#", а не комментарий. Квик пишет, что комментарий некоторые брокеры используют для своих расчетов, поэтому его не выставить из кода. Напишите вопрос или брокеру или на форуме Квика.
Каким образом установить код клиента? //например, S#1
Код клиента
Михаил, снова вопросы от меня =) Как определить, что начались новые торговые сутки?
По DateTime.Date
подскажите , как получить значения активная покупка/ продажа и текущие чистые позиции для фьючерсов ФОРТС ?
что такое активная покупка\продажа? Если цена лучшей покупки\продажи в стакане, то Security.BestBid \ Security.BestAsk
Текущие чистые позиции - если по сделкам, совершённым в рамках стратегии, то берётся из PositionManager.Position Если вообще, не учитывая в\вне стратегии - то Trader.GetPosition(Portfolio, Security)
Я торгую только на фортсе с помощью Stock# уже год. Он отлично заточен для торговли деривативами. Trader.GetPosition(Portfolio, Security) возвращает ту позицию, которая соответствует данному портфелю для заданного инструмента. А у вас он не возвращает для того же фьюча РТС позицию данным методом?
Суммируете оставшийся невыполненный объём в активных своих заявках. Если заявка бай - то +n оставшихся контрактов, если селл - то -n.
Alexander просто я подумал , раз есть уже экспортируемая изначально таблица DerivativePositionsTable то можно как то из неё получать данные по текущим чистым позициям и активная покупка/ продажа.....но раз так нельзя будем пробовать ваш способ. Благодарю за помощь
Не то чтобы нельзя - как раз любую таблицу можно получить, как уже ответили. Просто так проще как я написал, без лишних заморочек. :)
Насколько я понял, с помощью s# можно "выудить" любые данные из Квика. Попробуйте использовать CustomTables.
снимал группу заявок по фильтру таким образом : _Trader.CancelOrders(false, _portfolio, null, null, _security); всё работало, но сегодня прямо в процессе работы вырубилось, причем обычные ордера регистрируются , а снять группу заявок на фортс не получается. ошибки не возвращает, причем в квике число полученных внешних транзакций при попытке снять ордера не меняется из чего я делаю вывод что до квика вобще ни чего не доходит. подскажите , в каком направлении копать ?
сам допетрил :) я изначально _portfolio.Name = "11005"; задавал таким неверным способом . непонятно только почему это вначале работало а потом отключилось. примеры из мануала рулят. Михаилу респект за библиотеку !
а как лучше отслеживать заявки? например, отсылается у меня заявка на продажу n лотов с ценой A. Через некоторое время произошла продажа n-2 лотов и мне нужно снять эту заявку и поставить новую, 2 лота по цене B. Искать их по таблице заявок с параметрами n и A? Или есть риск нарваться на другую, такую же?
**upd:**точнее, даже не так. Заявок может быть несколько, самых разных, но по их исполнению (даже частичному) надо их заменять. Как это организовать?
событие NewMyTrades в данном случае как раз то что надо
спасибо! а статус заявки меняется тогда, когда она исполнена целиком (например, куплено 5 лотов), или частично (куплен хотя бы 1 лот)?
Смотрите документацию, раздел Состояния заявок:
я что то не пойму , почему событие Trader.PositionsChanged вызывается и при выставлении заявок и при исполнении их и даже просто, когда ни чего с позициями/заявками не происходит ? причем в последнем случае это событие приходит с периодичностью примерно раз в минуту . подскажите в чем может быть проблема ? читал мануал но так и нашел точного определения - КОГДА НАДО ПОДПИСЫВАТЬСЯ на события Trader.NewPositions Trader.PositionsChanged Trader.OrdersChanged Trader.NewMyTrades Trader.NewOrders
до коннекта с квиком Trader.Connect(); или после ? или вобще без разницы ?
События вызываются всегда, когда Квик через ДДЕ посылает обновление таблицы с позициями. А происходит это не только тогда, когда происходит сделка. В этой таблице есть и поля, которые изменяются постоянно.
в классе Trade есть член ExtensionInfo типа IDictionary<TKey, TValue>. А как узнать, какие ключи там есть? Конкретно мне нужно узнать, по какому лимиту была выставлена сделка
Значение в ExtensionInfo так просто не попадают. Необходимо заранее настраивать ДДЕ метаданные через QuikTrader.TradesTable. Здесь это рассказывается как сделать. И обращаться в последствии нужно так:
var someValue = someTrade.ExtensionInfo[DdeTradeColumns.SomeColumn];
У меня вопрос к знатокам C# и Trans2Quik.
У меня автомат работает с квиком через файловый ввод заявок и работают три разных Квика. Я решил попробовать использовать Trans2Quik. Правильно ли я понимаю, что при этом мне нужно писать разные классы-врапперы Trans2Quik для каждой TRans2Quik.dll ? Ну, например, что то вроде такого:
public interface ITrans2Quik { // члены интерфейса }
// TRANS2QUIK_1.DLL public class Trans2Quik_1 : ITrans2Quik {
private readonly string _pathToQuik;
// и т.д. }
// TRANS2QUIK_2.DLL public class Trans2Quik_2 : ITrans2Quik {
private readonly string _pathToQuik;
// и т.д.
}
Таким образом, в данной реализации для добавления нового Квика, работающего со своей TRans2Quik.dll мне нужно создавать и новый класс Trans2Quik_N. Дело в том, что 1-ый параметр DllImport это const string.
Вопрос: Нельзя ли как то на С# динамически создавать тип Trans2Quik, но с разными значениями поля где храниться значение "TRANS2QUIK.DLL" ?
Или подскажите идею реализации добавления нового враппера при помощи создания нового экземпляра без создания нового класса.
http://stocksharp.com/doc/help/html/9fb00dd4-4f0a-42a9-ab0f-9946b7acf6fe.htm
В Trade есть данные о сделке и об ордере.
а, все, поняла =) спасибо =)
как использовать trader.GuarantyCancelOrder(registeredOrder)? написано, что trader должен быть типа TraderHelper, откуда его взять?
Тоже не нашел то, что описано в документации. Может изменилось что. В S#3.0 применительно к ордеру есть order.GuarantyCancelOrder();
еще вопрос - как определить, что заявка была именно исполнена, а не снята? State будет Done, а что еще посмотреть? При снятии заявки Balance в Order обнуляется или остается?
upd: все, глупый вопрос, есть метод IsMatched() upd2: а у меня нет такого метода для order
Он в TraderHelper, как и GuarantyCancelOrder(). Для этого надо включить using Ecng.Trading.Algo;
Добрый день.
1) В строке:
this.Trader.Trades += trades;
получаю ошибку: "Элемент "trades" не существует в текущем контексте".
В чем может быть дело?
что делаю неверно?
Начинаете изучать S# без предварительного изучения C#. Так ничего не выйдет.
candlemanager работает на основе данных таблицы "Все сделки". Но эта таблица содержит данные только за текущий торговый день.
Как быть если необходимы данные за более поздний период времени? Может быть добавить в candleManager добавить возможность подгрузки данных из текстовых файлов? Например в при старте программы
В разделе Экспорт произвольных таблиц показано, как грузить свечки из Квика.
Не совсем понял, что Вы имеете в виду, либо Вы меня не поняли.
Таймфрем - 5 минут, за торговый день всего 96 свечек (ммвб)
Хотим в 10:36 получить последние 5 свечек, GetTimeFrameCandles(sec, TimeSpan.FromMinutes(5), 5) получим только одну сегодняшнюю свечу. А как получить остальные четыре за вчера?
В разделе Экспорт произвольных таблиц показано, как грузить свечки из Квика за вчерашний день.
О нашел, раньше просто смотрел в файле .chm в архиве с библиотекой. На сайте актуальней информация оказалась. Спасибо =)
Версии новые выходят.
первый вопрос снимается.
по второму: Настроен вывод в Квике таблиц Инструменты, Ордера, Все сделки. При обращении же к Security.Name получаю имя RIH1 (как и требуется). При обращении к числовым полям объекта Security нет обновления информации: Security.MaxPrice = 0 Security.LastTrade = null Пример Sample запускал - все работает как должно. Проверено, что экспорт из Квика таблиц Инструментов и Всех сделок настроен верно. В чем причина, что данные из таблицы Инструменты обновляются, а из таблицы Все Сделки - нет?
Смотрите на ProcessDataError. Убедитесь что NewTrades не вызывается.
NewTrades не вызывается.
this.Trader.Terminal.StartDde(this.Trader.SecuritiesTable, this.Trader.OrdersTable, this.Trader.TradesTable); //... далее следуют проверки, что экспорт всех трех таблиц запущен Security sec_1 = this.Trader.Securities.FirstOrDefault(sec => sec.Code == "RIH1"); AddToLog(this.textBox1, sec_1.Name.ToString()); //вывод на экран названия инструмента while (true) { if(sec_1!=null) { AddToLog(this.textBox1, sec_1.Name.ToString()); AddToLog(this.textBox2, sec_1.LastTrade.ToString()); AddToLog(this.textBox3, sec_1.MaxPrice.ToString()); } Thread.Sleep(1000); } Все сделано как написано в документации и на форуме. Возможно ли такое, что для запуска обновления полей Security.LastTrade и Security.Security.MaxPrice надо явно указать, что для Sec_1 начать обновление?
Sample работает? Verifier что нибудь выводит? ProcessDataError?
Вопрос по ситуации с [FORTS] В операции отказано: Превышен лимит операций от указанного клиента.: Асинхронный режим, отменяется ордер и отправляется новый. Приходит сообщение о флуде(в новом ордере) и потом не приходит сообщение об отмене ордера - заявка остается активной, но TraderHelper.IsCanceled считает заявку отклоненной... Посоветуйте, что можно сделать?
Какая версия?
В 3.0 я чинил снятие заявок в асинхронном режиме. Может это та самая ошибка.
Всем добрый день. Возникла следующая ситауция, мне необходимо получить данные из талицы "Портфель по деривативам" с добавленными колонками.
Код примерно следующий:
//добавляем столбцы trader.DerivativePortfoliosTable.Columns.Insert(2, DdeDerivativePortfolioColumns.CurrentLimitPositionsPrice); trader.DerivativePortfoliosTable.Columns.Insert(5, DdeDerivativePortfolioColumns.ACI); trader.DerivativePortfoliosTable.Columns.Add(DdeDerivativePortfolioColumns.MarketCommission);
//обработчик получения новых записей trader.NewPortfolios += obj => {
};
В обработчик приходит список объектов BusinessEntities.Portfolio, но в свойстве ExtensionInfo нет данных по дополнительным полям, каким образом можно их получить?
Аналогичная проблема была вчера. Версия 3.0.5. Ожидание не помогло (ждал, может вначале портфели приходят из другого места, потом обновляется...).
Да, во первых надо ждать и в NewPortolios и в PortfoliosChanged, так как ExtensionInfo может и позднее заполниться. А вот вторых подтверждаю багу с Insert. С Add у меня работает. Буду фиксить.
Спасибо. Попутно возник еще такой вопрос, в таблице "Портфель по деривативам" есть поле "Тип лимита" и ряд других, но в объекте BusinessEntities.Portfolio таких полей нет, их ожидать тоже в ExtensionInfo?
Тип лимита нет. Смотрится только тип лимита Деньги. Другие - это какие?
Если я правильно понял, то поля отображаются следующим образом.
Портфель по деривативам:
Торговый счет - Name Предыд. лимит откр. поз. - BeginAmount Тек. чист. поз. - CurrentAmount Вариац. маржа - ? Тип лимита - опускаем
Позиции по деривативам:
Торговый счет - Portfolio Код инструмента - Security Вход. чист. поз. - BeginValue Тек. чист. поз. - CurrentValue Акт. покупка - ? Акт. продажа - ?
Да, это недоделка. Было желание вычислять текущее значение денег на ФОРТС, но не потом сдался. Надо это куда-то деть. Предлагаю в Portfolio.Leverage.
Их сумма записывается в Position.BlockedValue
С этим можно сказать разобрались. А вот еще такой вопрос, есть портфель по деривативам, подписываюсь на новую запись в таблице и на изменение данных, событие изменения данных возникает до события новой записи, это нормальная ситуация?
Не могу воспроизвести.
У меня тоже не всегда удается повторить эту ситуацию, если удасться найти что приводит к ней, то отпишусь здесь.
а что произойдет, если пробовать снять заявку, у которой статус Done? кроме сообщения о невозможности сделать это. Как можно отловить подобное событие?
ITrader.OrdersFailed
глупый вопрос, а после этого события и выдачи messagebox, функция, в которой находилась строка CancelOrder продолжает работать дальше?
написано так:
MainWindow.Instance.CancelOrder(MainWindow.Instance._ordersWindow.Orders[orderNum]);
if (MainWindow.Instance._ordersWindow.Orders[orderNum].IsCanceled() == false)
{ ..... //в итоге в том случае, если заявка уже исполнена и возникла ошибка, сюда не приходит }
После вызова _trader.ReRegisterOrder при изменении заявки, TraderHelper.IsCanceled = true. Собственно вопрос как можно различить отмененный ордер от замененного? В обоих OrderStates.Done и order.Balance > 0 Можно конечно last message смотреть как вариант. PS На игровом сервере поле "снята(время)" пустое
Во-первых, это плохой подход, когда требуется такое различать. Потому что не существует такого понятия в бирже как "замененный ордер". Во вторых, успешно замененный ордер можно так же отменить. Какая логика должна быть в этом случае?
Опять про Replace. Попробывал пару вариантов и безуспешно. Верхний вариант с отслеживанием нового ордера (по TransactionId), нижние отслеживание старого ордера
и еще вопрос - можно как-то узнать, что заявка была именно снята, а не исполнена, и наоборот?
upd: ой, я подобный вопрос уже спрашивала. Надо использовать метод TraderHelper..::.IsCanceled
не планирую =) спасибо за информацию =)
Здравствуйте. Все цены инструмента (лучшая покупка, продажа и т.д.) у меня равны нулю почему-то (событие SecuritiesChanged). И даже в примере "Sample". Почему так ? Версия - последняя