понедельник, 30 ноября 2009 г.

Ecng.Trading 1.3

Выложил новую версию Ecng.Trading v1.3. Скачивать отсюда. Теперь по этой ссылке я буду выкладывать все новые релизы.

В новой версии я добавил два, на мой взгляд, главных изменения.

Первое касается того, как экспортировать произвольные таблицы из Квика. В QuikTrader появилось событие ProcessDdeData. Данное событие вызывается тогда, когда Квик послал DDE данные, которые QuikTrader не умеет обрабатывать. В качестве демонстрации я добавил в свое приложением-пример отображение данных по портфелю. Сначала я настроил Квик, добавив в него соответствующую таблицу:



Обновленные info.wld файл идет вместе с архивом.

Затем, добавил в него код обработки и отображения данных:

_trader.ProcessDdeData += (name, rows) =>
{
// узнаем, что пришедшие данные отвечают за портфель
if (string.Compare(name, "portfolio", true) == 0)
{
foreach (var row in rows)
{
var client = (string)row[0];
var portfolio = _portfolioWindow.Portfolios.FirstOrDefault(p => p.Client == client);

if (portfolio == null)
{
portfolio = new Portfolio { Client = client };
_portfolioWindow.Portfolios.Add(portfolio);
}

portfolio.Shorts = (double)row[1];
portfolio.Longs = (double)row[2];
portfolio.Collateral = (double)row[3];
portfolio.Margin = (double)row[4];
portfolio.Money = (double)row[5];
portfolio.PnL = (double)row[6];
}
}
};

Так как QuikTrader уже содержит методы по запуску и остановке DDE экспорта (StartDde и StopDde), то для удобства я перегрузил этим методы, чтобы они могли принимать имя экспортируемой таблицы (имя отображается в заголовке таблицы в Квике). Это позволит не только управлять своим потоком данных, но еще и запускать и останавливать его. Так что, если кто-то еще разрабатывает роботов под Excel, руководствуясь тем, что в него можно передавать данные как угодно, знайте, теперь это можно делать и в Ecng.Trading. Ну, а про преимущества разработки роботов на C# по сравнению с Excel я уже писал здесь.

Второе изменение знаковое. Наконец-то, в Ecng.Trading появился первый торговый алгоритм - котирование заявок. Например, необходимо срочно закрыть позицию, продав или купив по рынку (при минимуме потере профита). При высоколиквидном инструменте посланная из Квика или робота заявка может дойти до рынка уже "неактуальной" (в принципе, можно выставлять и из Квика рыночную заявку, но она работает не на всех биржах). Чтобы решить эту проблему, я написал класс MarketOrderRegistry, в который добавляется заявка. Заявка может быть и как уже ранее зарегистрированная, так и "пустая" (только что созданная и еще не выпущенная на биржу). И уже этот класс двигает эту заявку в стакане так, чтобы продать ее по выгодной рыночной цене. Рыночная цена опирается на текущий BestBid и BestAsk инструмента. Если же задана MarketDelta (передается в метод AddOrder), то цена заявки будет высчитываться как смещение цены последней сделки на эту самую MarketDelta.

Другое применения MarketOrderRegistry - это скальперская стратегия. Класс может сам создавать заявки и контролировать их в стакане.

Сам по себе класс MarketOrderRegistry построен на основе методов из класса TraderHelper:

1. GuarantyCancelOrder - гарантированно отменить заявку. В цикле посылает команду CancelOrder до тех пор, пока заявка не снимется (или не исполниться, если робот не успел снять).
2. ReRegisterOrder - перерегистрировать заявку. Удобен тем, что умеет подстраиваться под особенности биржи. Например, FORTS умеет изменять заявки одной транзакцией. Тогда в метод нужно передавать параметр isForts равный true. Если биржа не поддерживает изменения заявки одной транзакцией, то метод последовательно сначала снимает заявку через GuarantyCancelOrder, а затем регистрирует новую.

В принципе, можно реализовать своего собственного котировщика, вызывая методы TraderHelper. Как я уже упоминал, для той же скальперской стратегии. Сам по себе MarketOrderRegistry не смотрит на то, действительно ли нужно переставлять заявку. Он лишь старается выставить ее на край спреда. Поэтому, низкоуровневый класс TraderHelper для тех, кто реализует скальпинг, будет более полезен, чем сам MarketOrderRegistry. Используя TraderHelper можно написать логику лучше заявки (например, основываясь на ценовом или количественном объеме впереди в стакане).

среда, 18 ноября 2009 г.

Преимущества и недостатки разработки торговых роботов на разных платформах

Меня часто спрашивают, на чем лучше разрабатывать свое собственное МТС, какой язык программирования выбрать или чем моя библиотека Ecng.Trading отличается от других решений. Постараюсь ответить в этом, не побоюсь этого слова, опусе.

На данный момент можно выделить следующие группы ПО, где разрабатываются МТС:
1. Средствами внутреннего языка торгующей программы. Например, Quik и его QPILE. Преимущество такого такого подхода в том, что разработчики самой программы стараются максимально расширить свой внутренний язык, добавляя в него новые функции. Написанные скрипты получают данные значительно быстрее, нежели их получать из внешней программы (хотя это довольно спорное преимущество, потому как если написан алгоритм, который критично завязан на скорость исполнения, то такой робот лучше выносить в отдельное приложение, запускать его на сервере, и сервер подключать к торговому протоколу напрямую. Иначе и тормоза в работе, и проскальзование, и лосс). К недостаткам же можно отнести то, что скрипты работают не так быстро. Это и от того, что торговая система отдает преимущественно свои ресурсы своей основой задаче – торговле, и от того, что скриптовый язык разрабатывается под универсальные решения. А универсальность в ИТ мире редко когда идет рядом со скоростью.
2. Excel. Это просто мега система. По моему личному наблюдению, решения на Excel встречается практически во всех отраслях. Тут и бухгалтерия, и учет, и вычисление простых формул. Везде пробрался Excel, так что в инвестиционном бизнесе он не стоит особняком. Преимущество его использования кроется в банальном – на нем легко начать. Сравнительно простое создание формул, масса примеров, простой внутренний язык VBA – и вот уже на компьютере запущено некое решение на Excel. Минусы у данного подхода такие же как и у предыдущего пункта. К этому стоит добавить еще то, что на Excel не так уж тривиально интегрироваться с торговой программой, что для предыдущего пункта делать вообще не нужно. Отдельно можно выделить стабильность - всего один поток, и если он зависнет, зависнут как другие скрипты, так и не будет возможности перезапустить алгоритм (а Excel еще не научился вытаскивать себя из болота за волосы как Мюнхаузен), или даже перезапустить соединение с торгующей программой.
3. Аналитические программы (AmiBroker, WealthLab, MetaStock). Сами торговать не умеют, поэтому необходим некий адаптер подключения к торгующим программам (пункт 1). Преимущества и недостатки такие же как и у пункта 1 (я бы даже сказал, эти два подхода очень близки друг к другу). Дополнительным преимуществом является то, что аналитическая программа предоставляет для своего скрипта более богатый функционал. Плюс есть возможность подключать исторические данные для тестирования стратегий. Минусом является то, что, как и Excel, необходимо подключать к торговым системам, что еще более снижает производительность по сравнению с внутренним языком торгующей программы. И, как правило, нет возможности отследить потерю соединения.
4. Языки программирования (C#, VB, Java, Delphi). Основным плюсом такого подхода является, конечно же, скорость работы системы. Можно оптимизировать как сам алгоритм, использую любой подход, и сами формулы (кстати, формулы в большинстве случаев придется писать с нуля, потому что даже такая распространенная формула как скользящая средняя не будет присутствовать в языке; с другой стороны реализацию формул можно найти в Интернете, где можно найти и более сложные математические формулы, которые вряд ли будут присутствовать в аналитической системе), подстроив их работу под алгоритм, и соединение с торгующей программой. Особо критичные по скорости алгоритмы можно подключать к биржам напрямую, что дает преимущество в скорости отправки заявок и получения необходимой информации. Минусом является то, что из всех вышеперечисленных пунктов данный подход является самым сложным. Для начинающих в программировании я советую его использовать, когда уже есть готовая система, и ее хочется сделать стабильнее и производительнее. Но, еще раз предупреждаю, пройдет немало времени, прежде чем можно будет увидеть хороший результам (есть мнение, что можно этот самый хороший результат и вообще не увидеть – все зависит от знаний в программировании).

На фоне этих четырех пунктов моя библиотека Ecng.Trading относиться к пункту 4. Это именно библиотека для программирования под .NET (платформа содержит в себе языки C#, VB, C++, так что писать можно на любом из них). Преимущество и недостатки у нее точно такие, как и у данного пункта. Поэтому, основной целевой аудиторией при разработке библиотеки я сделал на людей, знакомых с программировании (трейдеров или программистов). Лично я программирую на языке C#, так как это самый перспективный и функциональный язык. Вот ссылки, которые я могу привести, чтобы начать программировать роботов с помощью Ecng.Trading:
1. Visual Studio – средство разработки, где пишется сама программа. Скачивать отсюда.
2. Электронный учебник по языку C# - отсюда.
3. Руководство использования Ecng.Trading - весь мой блог.

воскресенье, 15 ноября 2009 г.

Ecng.Trading v1.2

Обновление! Рекомендую после данного сообщения прочитать это.

Руки окончательно дошли не только до Ecng.Trading, чтобы его расширить, но и выложить в общий доступ. Качайте. Самое главное изменение в этой версии - появились новые свечки. Раньше были свечки, основанные только на тайм-фрейме, причем, жестко определенном: минутка, пяти-, и т.д.. Теперь тайм-фрейм можно задавать любой, через .NET класс TimeSpan (например, TimeSpan.FromMinutes(2) создает двухминутку). И свечки стали вида:

1. TimeFrameCandle - старая добрая тайм-фрейм свечка.
2. TickCandle - свечка, строящаяся на основе количества сделок.
3. VolumeCandle - свечка, строящаяся на основе допустимого объема.
4. RangeCandle - свечка, строящаяся на основе максимального отклонения цены сделки от открытия свечки.

Для свечек я добавил два события в ITrader: NewCandle (вызывается для свечек, которые только что начали формировать), CandlesChanged (вызывается для измененных свечек).

В предыдущей версии свечки сразу формировались по мере поступления новых сделок из Квика, что в свою очередь приводило к проблеме с производительностью. Так как, даже, если робот не использует какой-либо инструмент, все равно для этого инструмента строились свечки по всем тайм-фреймам (напоминаю, раньше тайм-фреймы были жестко заданы размерами, которые нельзя было изменить). Проблема еще острее вставала, когда таких инструментов набиралось с десяток и более. Теперь формирование свечек начнется как только робот вызовет метод регистрации, передав в него конкретный инструмент и параметры свечки. Вот эти методы:

1. RegisterTimeFrameCandles - передается инструмент, и нужный тайм-фрейм. После вызова этого метода, робот начнет получать события NewCandle и CandlesChanged с объектами TimeFrameCandle.
2. RegisterTickCandles - то же самое, что и RegisterTimeFrameCandles, только уже для свечек TickCandle.
3. RegisterVolumeCandles - аналогично.
4. RegisterRangeCandles - аналогично.

И последнее, немаловажное изменение, касается времени последней сделки (я уже писал об этом, пункт 2). Теперь, QuikWrapper принимает по DDE сразу два параметра, "Время последней сделки" и "Время изменения". Вот как выглядит теперь таблица инструментов:



Все скриншоты настроек DDE и файл с настройка окон в Квике я выложил в том же архиве.

пятница, 6 ноября 2009 г.

Особенность построения МТС под Quik, использую Ecng.Trading

Довольно много пришло писем на почту (как-то народ не очень любит писать в комменты, вопрос - почему) с разного рода ошибками. Об ошибках, в которых повинен я, писать не буду, потому как я их буду устранять по мере появления. А вот о тех, которые я устранить не могу (например, особенности работы Квика), я напишу.

1. "System.BadImageFormatException was unhandled" (если установлен .NET Framework русской версии то сообщение будет такое "Была сделана попытка загрузить программу, имеющую неверный формат."). Эта ошибка говорит о том, что запускается программа как 64 битовое приложение. Библиотека же Trans2Quik.dll написана только под 32 битовые приложения. А на дворе уже 21 век, и найти не 64 битовые компьютеры все сложнее и сложнее. Поэтому и возникает подобная путаница. Поэтому, преждем чем начать создавать своего робота на .NET под Квик, нужно зайти в свойства проекта, раздел Build и выставить Platform target в x86:


2. При торговле на FORTS у Security всегда нулевое значение свойства LastTrade. Это происходит потому, что в таблице инструментов Квик для FORST не показывает время последней сделки. Но он умеет показывать время последнего изменения. Ecng.Trading не опирается на названия колонок в таблице при экспорте через DDE, но учитывает порядковый номер. Поэтому, чтобы получать значение последней сделки в Security, нужно заменить колонку "Время последней сделки" на "Время последнего изменения".

3. Неправильно настроены таблицы в Квике. Под пример, который идет в архиве вместе с Ecng.Trading, я выкладываю файл с настройками для Квика скачать. В нем есть различные фильтры, наподобие того, что показаны только A1 ММВБ и пара фьючерсов, но я думаю, отменить этот фильтр в Квике не составит труда.

4. Когда запускается экспорт Всех сделок через DDE, компьютер может подтормаживать. Это связанно с количеством сделок, которое грузится в первый раз (актуально, когда робот запускается не в начале торговой сессии). Так вот, в программе лучше прописать алгоритм так, чтобы он ждал пока все сделки не подгрузятся. Например, брать тот же Security.LastTrade и ждать, пока он не придет через событие ITrader.NewTrades. Или же заставить пользователя смотреть за процессором в Task Manager.

5. "Что умеет моя программа?". Ничего! Потому что у меня не программа. У меня библиотека с API для разработки этих самых программ. Скриншоты с мой якобы программой являются скриншотами примера, которого я создал специально продемонстрировать, что умеет моя библиотека.