Федеральное агентство по образованию ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Факультет информатики Кафедра прикладной информатики

advertisement
Федеральное агентство по образованию
ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
Факультет информатики
Кафедра прикладной информатики
УДК 681.3.06
ДОПУСТИТЬ К ЗАЩИТЕ В ГАК
Зав. кафедрой, проф., д.т.н.
_______________ С. П. Сущенко
«___»____________ 2008 г.
Машковский Андрей Борисович
РАЗРАБОТКА ПРОГРАММЫ-РОБОТА ДЛЯ
АВТОМАТИЧЕСКОГО ВЫПОЛНЕНИЯ БИРЖЕВЫХ
ОПЕРАЦИЙ С ЦЕННЫМИ БУМАГАМИ
Дипломная работа
Научные руководители:
д. э. н., профессор
Е.А.Ерохина
К. ф.-м.н., профессор
Б.А.Гладких
Исполнитель, студ. гр. 1432
А.Б. Машковский
Электронная версия дипломной работы помещена
В электронную библиотеку. Файл
Администратор
Томск – 2008
Реферат
Дипломная работа 54 с., 28 рис., 8 источников.
ТОРГОВЫЙ РОБОТ, QUIK, РЫНОК ЦЕННЫХ БУМАГ, ТЕХНИЧЕСКИЙ АНАЛИЗ, C#
Объект исследования – автоматизация процесса торговли на рынке ценных бумаг в
реальном времени.
Цель работы – разработка торгового робота (автомата), работающего в связке с
торговой платформой QUIK, генерирующего сигналы для входа и/или выхода в короткие
и/или длинные позиции, с возможностью установки стоп-заявок.
Разработано приложение, автоматически выставляющее в реальном времени заявки
на покупку или продажу ценных бумаг. Сигналом для выставления новой заявки может
служить пересечение индикатора с ценой или пересечение двух индикаторов. В приложении реализован механизм трейлинга стоп-заявок.
Прогноз о развитии: планируется дальнейшее развитие приложения в направлении расширения такой функциональности, как самостоятельное создание пользовательских индикаторов.
2
Содержание
Введение ........................................................................................................................................4
1 Принципы торговли на фондовой бирже.…………..…………………..…………………5
2 Интернет-трейдинг с помощью торгового терминала QUIK…………………………12
2.1 Функции выполняемые системой QUIK……………………………………..…..12
2.2 Устройство интернет-трейдинга……………………………………………….….13
2.3 Виды заявок в QUIK……………………………………………….………….……15
2.4 Импорт транзакций………………………………………….…………….………..17
2.5 Выводы……………………………………………………………………………...18
3 Системы поддержки принятия решения в интернет-торговле………..……………..19
3.1 RoboBar……………………………………………………….………………..…...19
3.2 Piadviser ……………………………………………………………………..……...20
3.3 MetaStock ………………….………………………………………………….…….21
3.4 Выводы………………….…………………………………………………….…….21
4. Разработка торгового робота. Общая структура……………………………….……..23
5 Детали реализации…………………………………………………………….……..……..26
5.1 Реализация торгового робота……………………………….……………………...26
5.2 Реализация экспорта сформированных заявок …………………………….…….33
5.3 Реализация импорта биржевых данных ….…….…………………………….…..34
5.4 Реализация формирования простых заявок ………………………………………34
5.5 Реализация формирования стоп - заявок …………………………………………35
5.6 Реализация сигнала на основе индикаторов ……………………………………...39
Заключение………………………………………………………………………………….....40
Список использованных источников……………………………………………...……….41
Приложение А. Руководство пользователя…………………………………………...…...42
Приложение Б. Руководство программиста………..………………………...…….……...49
3
Введение
Торговля вручную на фондовой бирже постепенно уходит в прошлое. На смену
идёт прогресс информационных технологий. Ещё существуют успешные трейдеры, добившиеся высоких результатов при совершений спекулятивных операций на рынке ценных бумаг. Но на их торговые решения влияет множество психологических факторов.
Альтернативой человеческим эмоциям на бирже могут быть только торговые автоматы,
или, торговые роботы. Торговый робот (автомат) – это программный комплекс, в который
заложен алгоритм совершения операций на рынке ценных бумаг. Автоматы исключают
любой вид риска. У компьютерной программы отсутствуют эмоции, присущие человеку, а
значит, принятое программой решение является верным в рамках заданного алгоритма,
созданного человеком.
Данная работа посвящена разработке и созданию удобного и полезного с точки
зрения пользователя приложения для автоматической торговли на фондовой бирже через
торговый терминал QUIK. Программа QUIK – самая первая из современных программ,
используемых для непосредственной работы на бирже. Соответственно она является одной из наиболее широко применяемых биржевых программ. Посредством этой программы
трейдер получает он-лайн доступ к биржевой торговле и может сам принимать в ней активное участие. В качестве сигнала на покупку или продажу ценной бумаги используется
пересечение двух индикаторов или пересечение индикатора с ценой. В ходе работы удалось разработать механизм взаимодействия внешней программы с платформой QUIK, механизм трейлинга стоп-заявок, механизм контроля исполнения зависших заявок.
Дипломная работа состоит из пяти глав: основные понятия торговли на фондовой,
обзор программы интернет-трейдинга QUIK, обзор существующих аналогов, общая
структура и детальная реализация приложения. В первой повествуются основные определения биржы и интернет-трейдинга. Вторая глава содержит краткое описание программы
QUIK в рамках выполняемой работы. В третьей главе рассматриваются существующие на
сегодняшний день аналогичные программы, выявляются их недостатки. Четвёртая глава
посвящена структуре приложения. Пятая глава содержит описание архитектуры, базовые
моменты приложения, созданного в ходе дипломной работы.
Приложения содержат подробное руководство пользователя и руководство программиста.
4
1 Принципы торговли на фондовой бирже
Биржа — юридическое лицо, обеспечивающее регулярное функционирование организованного рынка товаров, валют, ценных бумаг, производных финансовых инструментов. Сейчас торги большей частью проходят в электронном виде. На бирже стоит торговый сервер, к которому подключены аккредитованные брокерские компании через специальные глобальные линии связи. Брокеры в своих интересах или интересах клиентов
выставляют в торговые системы заявки на покупку или продажи ценной бумаги, валюты,
товара. Таким образом, биржа предоставляет возможность встретиться покупателям и
продавцам, но уже не в своем здании, а на одном сервере, и заключать сделки куплипродажи.
Другая важная функция биржи — организация и гарантирование расчетов по сделкам, обеспечение механизма «поставка против платежа» (Delivery against payment). Российские биржи (ММВБ, РТС, МБЦМ) получают комиссионный сбор с каждой заключенной сделки, и это основной источник их доходов. Другим источником могут быть членские взносы, плата за доступ к торгам, продажа биржевой информации.
В зависимости от торгуемых активов биржи подразделяются на следующие виды:
1. товарные;
2. фондовые;
3. валютные;
4. фьючерсные;
5. универсальные
В данной работе рассматривается только фондовая биржа.
Брокер на рынке ценных бумаг — торговый представитель, юридическое лицо,
профессиональный участник рынка ценных бумаг, имеющий право совершать операции с
ценными бумагами по поручению клиента и за его счёт.
Понятие длиной и короткой позиции:
Длинная позиция – это обычная ситуация, когда ценная бумага покупается по одной цене с последующей перепродажей по более высокой.
5
Рисунок 1. Длинная позиция.
Поскольку брокер может предоставить в заём не только деньги, но и ценные бумаги, можно зарабатывать не только на росте стоимости ценных бумаг, но и на падении.
Рисунок 2. Короткая позиция.
Такая операция называется “продажа без покрытия”, или “короткая позиция”.
Трейдеры, которые совершают такие операции, ещё называют “медведями”.
Способ представления цены:
Технический анализ (ТА) – это графический способ изучения рынка в целом и поведения котировок ценных бумаг в частности. Технический анализ – это система правил,
по которым интерпретируются рыночные движения и которые приводят к определенным
выводам относительно возможных движений в будущем. Соответственно, основная зада6
ча, которую решает технический анализ – это определение фазы текущего состояния рынка и прогноз его будущего развития. Специальные термины, используемые техническими
аналитиками, позволяют кратко представить очищенную от новостей и случайных факторов картину рынка даже без графической визуализации. То есть технический анализ – это
еще и язык, на котором можно описать поведение рынка, и на котором общается между
собой громадное число трейдеров и аналитиков.
Существует несколько способов представления цены и один из них, график в «барах». Сначала ось времени делится на равные интервалы – периоды. Затем, для каждого
периода рисуют т.н. «бар» определенного вида. Ниже на рисунке приведены два типичных бара. Рисунки довольно прозрачно и интуитивно понятно определяют поведение цены торгуемого актива внутри выбранного периода.
Фигуры баров
Рисунок 3. Короткая позиция.
Ниже приведен пример часового графика НК ЛУКОЙЛ в барах.
Рисунок 4. Короткая позиция.
7
Внизу графика, в отдельном окне в виде столбчатой диаграммы показан объем торгов бумагами за соответствующий период торгов в штуках.
Основной стратегией торговли на бирже, является определение точек входа и выхода из рынка. Большинство трейдеров в качестве сигнала используют индикаторы(математическая функция от цены). Для примера рассмотрим такой индикатор, как
скользящее среднее.
Индикатор Скользящее Среднее показывает среднее значение цены инструмента за
некоторый период времени. При расчете этого индикатора производится математическое
усреднение цены инструмента за данный период. По мере изменения цены ее среднее значение либо растет, либо падает. Существует несколько типов скользящих средних: простое (его также называют арифметическим), экспоненциальное, сглаженное и взвешенное.В своей работе я использую простую скользящую среднюю. Этот индикатор можно
рассчитывать для любого последовательного набора данных, включая цены открытия и
закрытия, максимальную и минимальную цены, объем торгов или значения других индикаторов. Нередко используются и скользящие средние самих скользящих средних. Единственное, чем Moving Average разных типов существенно отличаются друг от друга, —
это разные весовые коэффициенты, которые присваиваются последним данным. В случае
Простого Скользящего Среднего все цены рассматриваемого периода имеют равный вес.
Экспоненциальные и взвешенные скользящие средние делают более весомыми последние
цены.
Рассмотри формулу этого индикатора:
n 1
SMAn 
где Pt
P
t i
i 0
n
- текущая цена, i – бегущая переменная, n – период усреднения.
Период усреднения показывает, за какое число временных интервалов будет производится усреднение цен. Чтобы получить временной период усреднения, необходимо
умножать период усреднения на величину временного интервала графика.
8
Сигналы, подаваемые одиночным скользящим средним:
1. Разворот скользящего среднего. Разворот вверх – сигнал к покупке, разворот
вниз – к продаже. У этого типа сигналов два недостатка: он слабый и всегда
несколько запаздывающий.
2. Пересечение ценой скользящего среднего. Пересечение ценой снизу вверх –
сигнал к покупке, сверху вниз – к продаже. Этот сигнал запаздывает гораздо
меньше предыдущего.
На практике часто используют, как сигнал для входа выхода в рынок пересечение двух
скользящих средних с разными периодами.
Если быстрая(с меньшим периодом) скользящая средняя пересекает медленную(с меньшим периодом) снизу вверх – это сигнал к покупке. Т.е. вход в длинную позицию или выход из короткой.
Если быстрая скользящая средняя пересекает медленную сверху вниз, то это сигнал к
продаже. Выход из короткой или вход в длинную позицию.
Рисунок 5. Сигналы входа и выхода в длинную позицию.
9
Рисунок 6. Сигнал входа и выхода в короткую позицию.
Во время торгов необходимо всегда высчитывать Stop Loss и Take Profit.
Stop Loss - это приказ закрыть позицию, когда рыночная цена достигнет уровня ордера.
Ордер Stop Loss предназначен для минимизации потерь в том случае, если цена финансового инструмента начала двигаться в противоположном направлении.
Take Profit - предназначен для закрытия позиции в том случае, если цена финансового инструмента начала двигаться в нужном направлении. Проще говоря это условная заявка,
которая позволяет получить гарантированную прибыль при благоприятном поведении
рынка.
Благодаря этим заявкам можно сформировать некий коридор, в котором можно торговать.
Ниже представлен пример этих заявок.
10
Рисунок 7. Stop Loss и Take Profit.
Трейлинг Стоп
Stop Loss предназначен для минимизации потерь в том случае, если цена финансового инструмента начала двигаться в убыточном направлении. Когда же открытая позиция становится прибыльной, Stop Loss можно перемещать вручную на безубыточный уровень для фиксации прибыли.
11
2 Интернет-трейдинг с помощью торгового терминала QUIK
2.1 Функции выполняемые системой QUIK
Программа QUIK – самая первая из современных программ, используемых для
непосредственной работы на бирже. Соответственно она является одной из наиболее широко применяемых биржевых программ. Посредством этой программы трейдер получает
он-лайн доступ к биржевой торговле и может сам принимать в ней активное участие.
Программа предоставляет все преимущества интернет-торговли: взаиморасчёты, а также
проверка платежеспособности при выставлении заявок в программе происходит автоматически. Таким образом, временные издержки на осуществление сделки ничто малы, что
особенно удобно для активной внутри-дневной торговли. При исполнение заявки клиент
сразу же видит отчёт по сделке и ему в любой момент доступна информация по текущему
состоянию его счёта.
Функции:
1. Обеспечение доступа к торгам на фондовом и срочном рынках, организуемым ведущими биржами страны:
•
Московская межбанковская валютная биржа (ММВБ): Фондовая биржа, включая режим переговорных сделок (РПС) и операции РЕПО, Рынок государственных ценных бумаг, Валютный рынок, Секция срочного рынка.
•
Фондовая биржа РТС: Биржевой рынок акций, включая операции РЕПО, Срочный рынок FORTS, Классический рынок акций в информационном режиме.
•
Фондовая биржа «Санкт-Петербург»: Фондовая секция.
•
Биржа «Санкт-Петербург»: Срочный рынок.
•
Санкт-Петербургская валютная биржа (СПВБ): Фондовый рынок.
2. Получение биржевой информации в режиме реального времени, включая очереди
котировок ценных бумаг.
3. Обеспечение участника торгов и его клиентов информацией о собственных заявках
и сделках.
4. Сбор поручений клиентов и их передача в торговую систему биржи.
5. Возможность подачи стоп-заявок, отложенных заявок (Карман транзакций) с их
пакетным выставлением в торговую систему.
12
6. Возможность маржинального кредитования брокером своих клиентов и автоматический контроль заданных лимитов кредитования. Мониторинг показателей маржинального кредитования встроенными средствами, а также специализированным
рабочим местом риск-менеджера (система «CoLibri»).
7. Возможность автоматизации торговых операций с использованием механизма импорта подготовленных транзакций из внешней программы.
8. Поддержка торговых операций на внебиржевом рынке.
9. Аутентификация пользователя системы и защита передаваемой информации от постороннего вмешательства.
10. Возможность применения сертифицированных ФАПСИ средств криптографической защиты информации для электронной цифровой подписи транзакций клиентов.
11. Графическое отображение динамики торгов по любым выбранным биржевым инструментам и их параметрам.
12. Динамический экспорт полученной информации в MS Excel, произвольные базы
данных (используя ODBC) и системы технического анализа Equis Metastock,
Wealth-Lab Developer и Omega TradeStation/ProSuite 2000.
13. Программирование вычислений с использованием встроенного языка QPILE.
14. Получение дополнительного информационного обеспечения в виде лент новостей
информационных агентств и котировок финансовых инструментов на других (в
том числе зарубежных) рынках.
15. Обмен текстовыми сообщениями с администратором системы и другими пользователями.
16. Автоматическое обновление версии программы и получение файлов по защищенному соединению.
2.3 Устройство интернет-трейдинга
Центральным звеном системы является сервер QUIK. Сервер подключен к торговым системам бирж через специальные «шлюзы», передающие серверу информацию о
торгах и средствах брокера на бирже, и принимающие поручения на покупку/продажу.
Сервер осуществляет сбор информации с торговых систем и ее трансляцию всем активным (подключенным) клиентам с минимально возможной задержкой.
13
Рисунок 8. Схема работы QUIK
Администратор системы регистрирует пользователей, устанавливает для них права на
пользование информацией, а также определяет лимиты средств клиента, в пределах которых он может совершать сделки.
Пользователь системы соединяется с сервером системы через Интернет, получает биржевую информацию о ходе биржевых торгов, доступных для торговли средствах и может
самостоятельно участвовать в торгах, посылая заявки в торговую систему непосредственно с рабочего места QUIK.
Использование для доставки финансовой информации практически повсеместно
доступной сети интернет накладывает жесткие требования на обеспечение защиты данных от постороннего вмешательства.
Вся передаваемая информация между сервером и клиентом находится в зашифрованном
виде, раскодировать ее можно только при наличии ключа доступа, индивидуального для
каждого пользователя системы. Ключ доступа создается самостоятельно каждым пользователем и хранится отдельно от самой программы на сменном носителе – дискете. Таким
образом, на одном компьютере с установленной системой QUIK могут работать разные
пользователи, каждый со своим персональным и конфиденциальным доступом к информации. Во избежание несанкционированного использования дискета с ключом доступа
дополнительно защищена паролем.
14
2.3 Виды заявок в QUIK
Заявки (транзакции) в программе QUIK бывают трёх видов: рыночные, лимитированные и условные, так называемые «стоп-заявки». Рыночная от лимитированной заявки
отличается тем, что рыночная заявка исполняется по рыночной цены, а лимитированная,
соответственно, по конкретно заданной цене. Особое внимание стоит уделить «стопзаявкам».
Условные заявки можно разделить на три вида: “stop-loss”, “take-profit” и связанная условная заявка. “stop-loss”- это заявка, которая ограничивает убытки. Необходимость в условной заявке возникает при выставление ордеров “stop-lose”(стопов). Другими
словами, условная заявка выставляется в случае, если трейдер желает купить выше существующей рыночной цены(например, в случае закрытия короткой позиции по стопу), или
продать ниже рынка(например, в случае закрытия длинной позиции по стопу). Целью выставления условной заявки является ее исполнение только по достижению рынком заданного уровня.
“Take-profit” – это заявка с условием вида "исполнить при ухудшении цены на заданную величину от достигнутого максимума (на продажу) или минимума (на покупку)".
Заявка работает следующим образом (пример для заявки на продажу): после достижения
ценой последней сделки условия стоп-цены начинается определение максимума цены последней сделки. Если цена последней сделки снижается от максимума на величину, превышающую установленный "отступ", то создается лимитированная заявка с ценой, меньшей цены последней сделки на величину "защитного спрэда". Величины "отступа" и "защитного спрэда" могут указываться как в значениях цены, так и в процентах. Назначение:
Закрытие позиции по инструменту с максимальной прибылью.
Пример 1 (продажа). Предположим, мы купили акции по 10р., а хотим продать не
ниже 11-и. Мы ставим “take-profit” на продажу, в котором в условии активации стопзаявки указываем 11р. Также указываем два дополнительных параметра — "отступ от
max" — этот параметр указывает, насколько цена последней сделки может стать ниже локального максимума цены, и "защитный спрэд" — насколько меньше, чем цена срабатывания “take-profit”, будет цена породженной им лимитированной заявки на продажу.
Предположим, что мы задаем "отступ от ma"=5коп., "защитный спрэд"=2коп. Допустим,
что наши ожидания оправдались, и рынок пошел в выгодную для нас сторону, т.е. растет.
Цена достигла 11р. — на этой точке наш “take-profit” активируется и начинает проверять,
15
будет расти цена дальше, или нет. При этом он проверяет, не стала ли цена последней
сделки по бумаге ниже, чем "локальный максимум цены" - "отступ от max". Предположим, цена растет, и достигла 11.30, после чего упала до 11.26 и опять начала расти. “Takeprofit” в этом случае не превратится в лимитированную заявку, ведь цена упала от максимума на 4 коп, а мы задали"отступ от max"= 5коп., т.е. условие исполнения достигнуто не
было. Дальше цена выросла до 11.40 и упала до 11.35 - вот тут наш “take-profit” активируется и породит лимитированную заявку на продажу с ценой, вычисляемой по следующей
формуле: "текущая цена последней сделки" - "защитный спрэд".
Т.е. цена заявки на продажу будет 11.35–0.02=11.33. "Защитный спрэд" нужно указать для защиты от "проскальзывания" рынка ниже цены порожденной тэйк-профитом заявки. Для ситуации с покупкой — все с точностью "до наоборот".
Пример 2 (покупка). Предположим, мы продали акции по 11р., а хотим купить не
выше 10-и. Мы ставим “take-profit” на покупку, в котором в условии активации стопзаявки указываем 10р. Также указываем два дополнительных параметра — "отступ от
min" — этот параметр указывает, на сколько цена последней сделки может стать выше локального минимума цены, "защитный спрэд" — на сколько больше, чем цена срабатывания “take-profit”, будет цена порожденной им лимитированной заявки на покупку. Предположим, что мы задаем "отступ от min"=5коп., "защитный спрэд"=2коп. Допустим, что
наши ожидания оправдались, и рынок падает. Цена достигла 10р. На этой точке наш “takeprofit” активируется и начинает проверять, будет падать цена дальше, или нет. При этом
он проверяет — не стала ли цена последней сделки по бумаге больше, чем "локальный
минимум цены" - "отступ от min". Предположим, цена падает, и достигла 9.30, после чего
выросла до 9.34 и опять начала падать. “Take-profit” в этом случае не превратится в лимитированную заявку, ведь цена выросла от минимума на 4коп, а мы задали "отступ от
min"=5коп., т.е. условие исполнения достигнуто не было. Дальше цена упала до 9.60 и выросла до 09.65, вот тут наш “take-profit” активируется и породит лимитированную заявку
на покупку с ценой, вычисляемой по следующей формуле:
"текущая цена последней сделки" + "защитный спрэд".
Т.е. цена заявки на покупку будет 9.65+0.02=9.67
"Защитный спрэд" нужно указать для защиты от "проскальзывания" рынка выше
цены порожденной “take-profit” заявки.
16
Связанная заявка – это говоря простым языком, одновременно “stop-lose” и “takeprofit”. Т.е. одновременно выставляются две заявки и при выполнение одной из них, вторая снимается автоматически.
2.4 Импорт транзакций
Назначение: Автоматический ввод в торговую систему подготовленных какой-либо внешней программой транзакций. Получение отчета о результате ввода транзакции. Для обмена информацией между QUIK и внешней программой используются текстовые файлы
фиксированной структуры:
•
*.tri – файл с параметрами транзакций. Файл представляет собой последовательность строк, каждая из которых содержит информацию по отдельной транзакции.
Параметры транзакции описываются в виде «НАЗВАНИЕ_ПАРАМЕТРА= значение_параметра» и разделяются символом «;». Пример: Заявка на покупку ЛУКОЙЛ,
лимитированная, 3 лота по 253.3 руб. В сам файле эта заявка будет выглядеть следующим образом: ACCOUNT=NL0080000043; CLIENT_CODE=467; TYPE=L;
TRANS_ID=2; CLASSCODE=EQBR; SECCODE=LKOH; ACTION=NEW_ORDER;
OPERATION=B; PRICE=253,3; QUANTITY=3;
•
*.tro – файл с результатами посылки транзакций в торговую систему,
•
*.trr – файл, содержащий журнал обработки транзакций.
Схема взаимодействия между программами выглядит следующим образом:
1. Внешняя программа формирует транзакцию с заданными параметрами и записывает ее в виде новой строки в .tri-файл. Транзакции идентифицируются по дополнительному целочисленному параметру TRANS_ID, содержащему уникальный номер.
2. Система QUIK опрашивает с определенной периодичностью .tri-файл с параметрами транзакций и передает в торговую систему ранее не обработанные транзакции.
Если описание транзакции не соответствует принятому формату, то она отвергается.
3. Результат действий записывается в .tro-файл в формате, приемлемом для чтения
внешней программой. Каждая строка файла содержит информацию об обработке
отдельной транзакции, различаемые по параметру TRANS_ID.
17
4. При обработке внешней программой результатов операции (на ММВБ), выводимых в .tro-файл, регистрационный номер заявки в торговой системе указывается в
текстовом сообщении, возвращаемом торговой системой (поле «DESCRIPTION»), а
также параметром ORDER_NUMBER.
2.5 Выводы
Платформа QUIK позволяет автоматически выставлять заявки трейдера посредством записи каждого ордера в определенный файл. Этот файл содержит текст, каждая строка которого представляет собой требования к торговой платформе о выставлении ордера. Далее
платформа сообщает о результате выставленного ордера в другой файл, содержащий
сведения о том, выполнен или нет запрос на выставление ордера.
В торговой платформе QUIK применяется наиболее последовательный подход к автоматической торговле. Заключается он в следующем. Экспорт биржевых котировок происходит непосредственно через ODBC, что позволяет передавать их в любую из баз данных,
поддерживающих интерфейс ODBC. А такой интерфейс поддерживают все распространенные базы данных, включая и «свободные». Экспорт любой таблицы с результатами
торговых операций происходит через ODBC. Следовательно, платформа QUIK наиболее
приспособлена к автоматической торговле, т.к. включает в себя все необходимые функции
для любых внешних программных решений.
18
3 Системы поддержки принятия решения в интернет - торговле
На данный момент существуют несколько программы взаимодействии с QUIK для поддержки принятия решения при торговле. Все эти программы можно разделить на два вида:
программы-советчики, которые не совершают торговых операций, а только советуют, и
программы-роботы, которые совершают торговые операции по заданному алгоритму
3.1 RoboBar
RoboBar – это индикаторный робот открытого типа. Программа не является «черным
ящиком» - трейдер самостоятельно настраивает робота, контролирует его, вмешивается в
процесс торговли и т.д. Для того, чтобы робот начал совершать торговые операции, для
него необходимо создать задание. Заданий по одной и нескольким бумагам может быть
создано и одновременно запущено любое разумное количество. Работа программы над
заданием функционально распадается на четыре этапа:
1. Создание торгового сигнала;
2. Формирование торгового сигнала;
3. Отработка торгового сигнала;
4. Контроль над исполнением;
Рисунок 9. RoboBar.
В программе реализован механизм пошагового закрытия и разворота позиции.
19
1. Торговый сигнал.
Торговый сигнал может быть сформирован на основе любого потока биржевых данных.
Это реальное событие, наступившее на бирже. Например – цена пересекла заданный уровень. Торговый сигнал, построенный на объективных данных, никак не корректируется и
непрерывно читается программой в режиме он-лайн.
2. Торговое задание.
Торговое задание базируется на основе торгового сигнала любого происхождения как в
обоих направления, на куплю и продажу, так и только в одном. Трейдер определяет объем
входа и ценовой режим.
3. Отработка торгового сигнала.
Торговый сигнал может быть очень нестабильным и создавать ряд сложностей при прочтении. Программа корректно анализирует его поведение и своевременно принимает решение о совершении торговых действий.
4. Исполнение и контроль. Получив торговый сигнал, машина, исходя из настроек трейдера, формирует заявку, отправляет ее в торговую систему и контролирует процесс исполнения.
3.2 PIAdviser
PIAdviser - программа, которая помогает принимать инвестиционные и спекулятивные
торговые решения на российском рынке акций, фьючерсов и валютном рынке FOREX. С
ее помощью Вы легко сможете найти и оценить те инструменты, которые могут принести
доход в ближайшее время.
В арсенале PIAdviser существует множество торговых тактик, которые позволяют "ловить" большинство ценовых движений на рынке акций. Кроме выбора наиболее подходящего момента для открытия позиции, программа подскажет уровень для ее оптимального
закрытия, что позволяет существенно снизить риски потери капитала и повышает вероятность получения дохода при работе на фондовом рынке.
Преимущества, которые получают начинающие инвесторы:
- Эффективное обучение принципам и технологиям инвестирования.
- Концентрация внимания только на перспективных акциях и фьючерсах.
20
- Повышение доходности собственных сделок.
- Существенно понижает вероятность больших потерь и разорения.
Преимущества, которые получают профессиональные трейдеры:
- Возможность следить за перспективными инструментами сразу по нескольким рынкам.
- Дополнительная поддержка при принятии торгового решения.
- Существенное сокращение времени, необходимого для принятия торгового решения.
Торговые алгоритмы PIAdviser успешно прошли испытания при реальной торговле и используются многими ведущими трейдерами и аналитиками.
3.3 MetaStock
Самая известная программа для технического анализа рынка. Представляет собой
новый стандарт для профессиональных трейдеров, позволяющий проводить торговые
операции в реальном времени.
При помощи этой программы трейдеры могут создавать, тестировать и полностью автоматизировать свои торговые системы, достигая тем самым максимальной прибыльности
при проведении сделок. В дополнение они смогут пользоваться всеми популярными возможностями программы MetaStock, такими как гибкое графопостроение, полная коллекция торговых индикаторов, мощная поисковая система возможных персональных консультаций с экспертами торговли и многое другое.
Самое значительное новшество по сравнению с предыдущей версией - кардинально переработанный тестер систем, который стал удобнее и функционально насыщеннее. Это полнофункциональная профессиональная версия с поддержкой внутридневных интервалов и
обновлением графиков в реальном времени.
3.4 Выводы
PIAdviser и MetaStock могут принимать данные через ODBC. Но выставлять заявки
они не умеют, потому что главное их предназначением является анализ рынка. Стоимость
использования программы PIAdviser 6000 руб (12 мес),повторное приобретение подписки
на 12 мес. - 3600 руб. Цена на Metostock порядка 1000$.
21
RoboBar напрямую связан с QUIK, эта программа обрабатывает экспортируемые данные и генерирует сигналы. Недостатком этой программы является, то что она не умеет
ставить стоп-заявки и в ней не предусмотрена функция трейлинга стоп-заявок. Стоимость
программы 10900 рублей, с ежемесячной платой 3000 рублей.
Таким образом, крайне актуальным является созданием приложения для автоматической торговли в реальном времени на бирже. При этом к ней предъявляются следующие
требования:
1. Индивидуальная настройка задания по каждой бумаге
2. Возможность автоматического выставления стоп-заявок
3. Механизм трейлинга стоп-заявок
4. Механизм контроля зависших заявок. Т.е. Возможна такая ситуация, что при
выставление заявки по определённой цене текущая цена может резко изменится, и на бирже будет находиться не исполненная заявка, или «зависшая» заявка.
Такие ситуации необходимо исключать.
22
4 Разработка торгового робота. Общая структура
Перед описанием структуры системы необходимо определить место торгового робота на
бирже. Ниже приведена схема взаимодействия торгового робота с биржей.
импорт
экспорт
БД (ODBC)
Торговый
Робот
“QUIK”
Брокер
Биржа
импорт
экспорт
Файлы
транзакций
Рисунок 10. Схема взаимодействия торгового робота с биржей
Из этой схемы видно, что торговый терминал QUIK взаимодействует с биржей через
брокера. QUIK позволяет экспортировать биржевые данные в некое хранилище по ODBC,
торговый робот принимает эти данные, обрабатывает по определённому заданию эти данные и генерирует заявку в файл транзакций. QUIK с определённой периодичностью читает файл транзакций и при появлении новой строки автоматически выставляет заявку на
бирже.
Структуру системы можно представить в виде следующих частей:
1. Импорт биржевых данных
2. Пользовательский интерфейс
3. Экспорт сформированных заявок
4. Формирование простых заявок
5. Формирование стоп-заявок
6. Механизм торгового робота
7. Индикаторы технического анализа
23
Импорт биржевых данных служит для получения в реальном времени биржевых
данных, с последующие передачей этих данных в другие части структуры. Из QUIK экспортируются следующие таблицы:
1. “Текущая таблица параметров” – отображение информации о выбранных
бумагах. Главные значение из этой таблицы это “текущая цена”, “лучшая
цена спрос”, “лучшая цена предложения”.
2. “Текущая таблица параметров” – отображение информации о выбранных
бумагах. Главные значение из этой таблицы это “текущая цена”, “лучшая
цена спрос”, “лучшая цена предложения”.
3. “Клиентский портфель” – отображение остатка средства клиента.
4. “Таблица всех сделок” - получение обезличенной (без указания сторон) информации по всем заключенным сделкам. По этой таблице формируется бар
с последующим применением его в индикаторах.
5. “Таблица сделок”- реестр сделок, совершенных в отношении счетов клиента.
6. “Таблица заявок” - контроль состояния исполнения заявок, отправленных на
биржу. Управление активными заявками.
7. “Таблица стоп-заявок”- контроль состояния исполнения стоп-заявок.
Пользовательский интерфейс служит для взаимодействия пользователя с приложением. Позволяет настраивать задание для торгового робота по конкретной бумаге. Кроме того предоставляет возможность просмотр уже запущенного торгового
робота по конкретной бумаге и отображение текущего состояния робота.
Экспорт сформированных заявок отвечает за передачу сформированной заявки
в QUIK. Заявки записываются в файл *.tri, а результат экспорта этой заявки в QUIK
в *.tro.
Формирование простых заявок необходим для формирования простой заявки в
понятном для QUIK виде и для контроля ее исполнения на бирже.
24
Формирование стоп-заявок отвечает за формирование стоп-заявок в понятном
для QUIK виде. Эта часть так же контролирует исполнение установки стор-заявки
и позволяет применить механизм трейлинга стоп-заявок.
Механизм торгового робота отвечает за последовательную работу торгового робота по конкретной бумаге. Позволяет оповещать пользователя при изменении состояния автомата
Индикаторы технического анализа необходим для отображения сигнала торгового автомата в виде взаимодействии индикаторов технического анализа. Результатом работы является конкретный индикатор как параметр сигнала.
Польз.Интрефейс
Automaton
TechAnalyse
DBFile
StopOrder
Order
TrFile
Рисунок 11. Диаграмма пакетов
25
5 Детали реализации
5.1 Реализация торгового робота
Торговый робот, получает данные с биржи из файла базы данных, в который в реальном времени происходит экспорт из QUIK. После получения торгового сигнала, автомат формирует заявку в понятном для QUIK виде и записывает её файле с расширением
*.tri. QUIK с заданной периодичностью опрашивает этот файл (к примеру, каждые 0,3 секунды), и при появлении новой записи в этом файле, он пытается сформировать заявку.
Далее в файле *.tro записывается результат совершённой операции.
Торговый робот должен уметь работать индивидуально для каждой выбранной бумаги, на длинных и/или коротких позициях (это зависит от выбранных настроек). Поэтому
для каждой торгуемой бумаги инициализируется собственный автомат. Для входа и выхода в позицию можно использовать разные сигналы. Общая диаграмма деятельности приложения представлена ниже:
запустить
приложение
Заполнить
настройки
робота
Выбрать ценную
бумагу
Проверить
настройки
ошибка
Запустить робота
Закрыть
приложения
Проверить
состояние
выбрать новую
бумагу
робот не
остановлен
«стоп»
Закрыть
приложения
Остановить
робота
Проверить
работоспособность
биржи
откр.
позиция
активно
Получить данные
с биржи
Закрыть позицию
Устан.состояние
«стоп»
Проверить
сигнал
закрыть
нет
да
Установить
заявку
Проверить
исполнение
заявки
не
исполнена
исполнена
Устан. новое
состояние робота
Рисунок 12. Общая диаграмма деятельности приложения.
26
Граф переходов торгового робота изображен на рисунке 13.
Long
Ok Enter
Exit Long,
Stop
preEnterLong
Cancel Exit
preExitLong
Cancel Enter
ReleaseStopOrder
Ok stop
Enter Long
Run
Start
Ok Exit
Not Market
Stop robot
Stop
Enter Short
Ok Exit
Cancel Enter
Ok stop
ReleaseStopOrder
preEnterShort
Cancel Exit
Ok Enter
Short
preExitShort
Exit Short,
Stop
Рисунок 13. Схема функционирования торгового робота.
По схеме видно, что автомат имеет 6 состояний: Start, NotMarket, Long, Short, preEnterLong, preExitLong, preEnterShort, preExitShort, Stop.
1. Start – начальное состояние автомата, задается при инициализации. Возможен
только один единственный переход из этого состояния – по событию “Run” (т.е запуск автомата)
2. NotMarket (Не в рынке) – в этом состояние нет никаких сделок с торгуемой бумагой. Переходы в другие состояния только по событиям “Enter Long”, “Enter Short”,
“Stop robot”.
3. preEnterLong – при переходе в это состояние происходит попытка установки заявок
на бирже. При успешном исполнение заявки автомат по событию “Ok Enter” переходит в состояние Long, иначе возврат в предыдущее состояние по событию “Cancel Enter”.
27
4. Long – смысл в том, что торгуемая бумага находится в длинной позиции. 3 события
перехода в другие состояния. По событию “ReleaseStopOrder”(исполнилась стопзаявка) автомат переходит в состояние NotMarket. “ExitLong”- сигнал о выходе из
длинной позиции. “ Stop”(произошло нажатие кнопки «Остановить» или закрытие
программы) завершение работы автомата, автомат не сразу переходит в состояние
Stop, вначале закрывает позицию по лучшей цене предложения и только потом
прекращает работу.
5. preExitLong – состояние выхода и позиции Long. Переходы осуществляются по событию “Ok exit” и “Ok stop”.
6. preEnterShort – аналогично preEnterLong, но только для короткой позиции.
7. Short – торгуемая бумага находится в короткой позиции. Здесь так же как и в Long
3 события для перехода в другие состояния. По событию “ReleaseStopOrder” (исполнилась стоп-заявка) автомат переходит в состояние NotMarket. “ExitShort”- сигнал о выходе из короткой позиции. “ Stop”(произошло нажатие кнопки «Остановить» или закрытие программы) завершение работы автомата, автомат не сразу переходит в состояние Stop, вначале закрывает позицию по лучшей цене спроса и
только потом прекращает работу.
8. preExitShort – аналогично preExitShort, но только для короткой позиции.
9. Stop – в этом состояние работа автомата прекращается.
Ниже описан простой пример торговли по такому автомату:
Параметры торговли: торг только на длинной позиции. Со стоп-заявками stop-loss.
1. запуск автомата при нажатии по кнопке «Запуск». Start,RUN ->NotMarket;
2. ждём сигнал на вход в длинную позицию, получили сигнал: NotMarket,ENTER_LONG ->preEnterLong;
3. формирование и запись заявки о покупке ценой бумаги по лучшей цене предложения. Установка stop-loss. Обе заявки приняты: preEnterLong,OK_ENTER ->
Long;
4. ждём
сигнал
о
выходе
из
длинной
позиции,
получили
сигнал:
Long,EXIT_LONG->preExitLong;
28
5. продаем купленную бумагу по лучшей цене спроса, формирование и запись заявки, снятие stop-loss. Бумага продана и стоп-заявка снята: preExitLong,
OK_EXIT -> NotMarket;
6. выключаем
автомат
при
нажатии
на
кнопке
“Остановить”:
NotMarket,STOP->Stop;
Для программной реализации такого автомата, я воспользовался паттерном STATE MACHINE.
Паттерн State Machine предназначен для создания объектов, поведение которых варьируется в зависимости от состояния. При этом для клиента создается впечатление, что изменился класс объекта. Таким образом, назначение предлагаемого паттерна фактически
совпадает с таковым для паттерна State.
Основная идея паттерна State Machine заключается в разделении классов, реализующих
логику переходов (контекст), конкретных состояний и модели данных. Для осуществления взаимодействия конкретных состояний с контекстом используются события, представляющие собой объекты, передаваемые состояниями контексту. Отличие от паттерна
State состоит в методе определения следующего состояния при осуществлении перехода.
Если в паттерне State следующее состояние указывается текущим состоянием, то в паттерне State Machine это выполняется путем уведомления класса контекста о наступлении
события. После этого, в зависимости от события и текущего состояния, контекст устанавливает следующее состояние в соответствии с графом переходов. Преимуществом такого
подхода является то, что классам, реализующим состояния, не требуется «знать» друг о
друге, так как выбор состояния, в которое производится переход, осуществляется контекстом в зависимости от текущего состояния и события.
В работе [2] приведена реализация этого паттерна на языке Java. Где событиями
является конкретный объект. Мне этот подход не понравился тем, что приходится разрабатывать свой собственный класс События. Для устранения этого недостатка, я использовал язык C#. Этот язык содержит понятие события на синтаксическом уровне. События этого языка решено использовать в качестве событий, которые порождаются
состояниями для извещения контекста. В реализации паттерна State Machine на языке Java
обработка событий происходила в одном методе castEvent, который был методом интерфейса IEventSink. В этом методе следующее состояние определялось либо с использованием хэш-таблиц, либо при помощи оператора switch. Первое решение
не
29
позволяет
задавать действия
на переходах
и проверять дополнительные условия,
а второе делает код метода громоздким. Реализация на языке C# использует по одному методу для каждого перехода. Этот метод – обработчик события перехода
для состояния. В метод можно добавить проверку дополнительных условий для перехода и действия на переходе (код, который должен выполняться при переходе). Ниже
описана диаграмма классов торгового робота:
GenSignal
-CurrentState : object
-isLong : bool
-isShort : bool
+StateChanged : event
+start()
+...()
«interface»
IGenSignal.
+start()
+stop()
+enterLong()
+exitLong()
+releaseStopOrder()
+okEnter()
+okExit()
+CancelEnter()
+CancelExit()
1
1
1
1
1
StartState
1
+StateName : string
+START : event
#dm : dmGenSignal
+start()
+stop()
+enterLong()
+exitLong()
+releaseStopOrder()
+okExit()
+okEnter()
+CancelEnter()
+CancelExit()
LongState
preExitLongState
+StateName : string
-EXIT_LONG : event
-STOP_BOT : event
-STOP_ORDER : event
#dm : dmGenSignal
+start()
+stop()
+enterLong()
+exitLong()
+releaseStopOrder()
+okExit()
+okEnter()
1
+CancelEnter()
+CancelExit()
+StateName : string
+OK_STOP : event
+OK_EXIT : event
+CANCEL_EXIT_LONG : event
#dm : dmGenSignal
+strat()
+stop()
+enterLong()
+exitLong()
+releaseStopOrder()
+okExit()
+okEnter()
+CancelEnter()
+CancelExit()
NotMarketState
1
+StateName : string
+ENTER_LONG : event
+ENTER_SHORT : event
+STOP_BOT : event
#dm : dmGenSignal
+start()
+stop()
+enterLong()
+exitLong()
+releaseStopOrder()
+okEnter()
+okExit()
+CancelEnter()
+CancelExit()
dmGenSignal
-_param : Param
+WaitEnterLong()
+WaitExitLong()
+WaitEnterShort()
+WaitExitShort()
+...()
Param
+seccode : string
+clientcode : string
+...
1
«interface»
IIndicator
+Current_Value() : float
+Last_Value() : float
+Step()
Signal
4
-indicator1 : IIndicator
-indicator2 : IIndicator
-period_bar : int
+Signal(in ind1 : IIndicator, in ind2 : IIndicator, in period_bar : int)
+Check()
Рисунок 14. Диаграмма классов автомата
Для того чтобы не загромождать рисунок, на нем не отражены такие классы состояний,
как preExitLong, ShortState, StopState, preEnterShort, preExitShort.
30
Участники:
1. IGenSignal (Интерфейс автомата) – реализуется контекстом и является единственным способом взаимодествия клиента и автомата. Этот же интефейс реализуется
классами состояний.
2. GenSignal (Контекст) – класс в котором инкапсулирована логика переходов. Он реализует интерфейс IGenSignal хранит экземпляры модели данных и текущего состояния.
3. StartState, LongState, NotMrketState, preEnterLong, StopState (классы состояний) –
определяют поведение в конкретном состоянии. Реализует интерфейс IGenSignal. В
каждом из этих классов есть собственные события, на которые подписывается контекст.
4. dmGenSignal (Модель данных) – класс предназначен, для обмена данными между
состояниями.
5. Param – класс в котором инкапсулированы основные значения переданные автомату в качестве параметров. К примеру такие параметры как, код клиента, счёт
клиента, код бумаги, код класса, описание сигнала для входа или выхода из позиции и т.д.
6. Signal – определяет сигнал для входа или выхода из рынка. В качестве сигнала используется пересечение двух индикаторов или пересечение индикатора с ценой.
При инициализации контекст создает экземпляр модели данных и использует его при
конструировании экземпляров состояний. В процессе работы контекст делегирует вызовы методов интерфейса текущему экземпляру состояния. При исполнении делегированного метода объект, реализующий состояние, может сгенерировать событие уведомить об этом контекст.
Решение о смене состояния принимает контекст на основе
события, пришедшего от конкретного объекта состояния. Ниже приведёт отрывок код
действия на переходах:
public class GenSignal : IGenSignal
{
StartState Start;
NotMarketState NotMarket;
protected object CurrentState;
31
…
public GenSignal(dmGenSignal dm)
{
this.dm = dm;
Start = new StartState(dm);
NotMarket = new NotMarketState(dm);
CurrentState = Start;
...
Start.RUN_BOT += new EventHandler(Start_RUN_BOT);
NotMarket.STOP_BOT += new EventHandler(NotMarket_STOP_BOT);
…}
public void start()
{
((IGenSignal)CurrentState).start();
}
public void enterLong()
{
((IGenSignal)CurrentState).enterLong();
}
…
public void NotMarket_ENTER_LONG(object send, EventArgs e)
{
if (Object.ReferenceEquals(CurrentState, NotMarket))
{
CurrentState = preEnterLong;
if (StateChanged != null)
{
StateChanged(this, new
StateChangedEventArgs(NotMarket.StateName, preEnterLong.StateName));
} // извещение о смене состояния автомата
this.SetTransaction();// установка заявок
}
}
32
5.2 Реализация экспорта сформированных заявок
Особое значение играет механизм экспорта сформированных заявок в файлы транзакций. Для записи и передачи заявки в программу QUIK был разработан класс TrFile.cs.
Атрибуты:
file_name – строка, обозначающая название файла транзакций.
trans_id – целочисленная переменная. Используется для подставления номера
транзакции в QUIK. Каждая заявки имеет свой уникальный номер и с помощью
этой переменой происходит заполнение кода заявки. После каждой сформированной транзакции переменная увеличивается на единицу.
timer – объект класса Timer, с помощью которою происходит переодическое чтение файла с результатами обработки транзакций(*.tro).
OnTroChanged – событие, информирующее о появление новой строки в файле
результатов обработки транзакций.
Методы:
TriFile – конструктор, инициализирует переменные класса.
SaveTri - функция записи заявки в файл *.tri. Внутри метода используется блокировка переменной tri. Это предусмотрена для того чтобы избежать ошибок при
одновременной записи в файл из разных потоков.
SaveTriReturnId – аналогично SaveTri, но возвращая trans_id сформированной заявки.
ReedTro – функия периодического чтения файла результата обработки транцакций, которая генерирует событие при появление новой строки в файле.
Dispose – функция, останавливающая таймер и закрывающая все открытые ресурсы.

Класс TransactionStatusEventArgs.cs – класс, объекты которого используются для
передачи информации о результате обработки транзакции.
Атрибуты:
33
DESCRIPTION – текстовый комментарий к полю STATUS, содержащий ответ сервера QUIK или торговой системы.
ORDER_NUMBER – Регистрационный номер заявки в торговой системе.
STATUS – Результат выполнения операции.
TRANS_DESCRIPTION – Описание выполняемой транзакции, например «Ввод заявки».
TRANS_ID – уникальный идентификационный номер заявки.
Методы:
TransactionStatusEventArg – конструктор, инициализирует все параметры.
5.3 Реализация импорта биржевых данных
Получение биржевых данных реализовано при помощи подключения к экспортируемой базе данных по ODBC. Для работы с этими данными был разработан класс
DBFile.cs, который подключается по ODBC к этой базе данных и периодически запрашивает новые записи. При получение данных отличных от предыдущих генерируется соответствующее событие. Так же в этом классе реализованы методы для формирования конкретного по таблице «Все сделки».
5.4 Реализация формирования простых заявок
Каждая заявка должна выставляться с определёнными параметрами. Торговый
терминал QUIK позволяет экспортировать такие данные по каждой бумаге, как лучшая
цена спроса (best_bid) и лучшая цена предложения (best_offer) , благодаря этим ценам,
можно сформировать заявку по благоприятной цене. Ниже приведён механизм контроля
исполнения выставленных заявок, а также формирование заявки с соответствующим объёмом и ценой. Ниже представлен алгоритм работы.
34
Входные данные:
1. Тип позиции
2. Направление сделки
3. Объём входа
4. Спрос
5. Предложение
Запрос
формирования
заявки
длинная позиция (Long)
покупка(вход)
Сформировать заявку по
лучшей цене спроса с
заданным объёмом
короткая позиция (Short)
Тип
позиции?
Направление продажа (выход)
сделки?
продажа(вход) Направление
сделки?
Сформировать заявку по
лучшей цене предложения
с заданным объёмом
Сформировать заявку по
лучшей цене спроса с
заданным объёмом
покупка (выход)
Сформировать заявку по
лучшей цене предложения
с заданным объёмом
Запись в файл
транзакций
не исполнена
Результат?
исполнена
полностью
исполнена
Как
исполнена?
исполнена
частично
Подождать опр.
время
Сообщить
роботу
исполнена
полностью
Как
исполнена?
исполнена
частично
Запомнить
исполненный
объём
Снять заявку на
оставшейся
объём
Рисунок 15. Механизм работы формирования простых заявок
5.5 Реализация формирования стоп - заявок
Известно, что трейдеры часто «забывают» ставить защитные стоп-приказы, а порой просто ленятся. С весьма плачевными последствиями. Особенно трейдеры, исповедующие
агрессивную внутри дневную торговлю. При необходимости единовременно контролировать рыночную ситуацию по нескольким инструментам, анализировать показания технических индикаторов, следить за новостями и обстановкой на зарубежных рынках, поду35
мать о защите позиции порой просто не остается времени. Итак, главный принцип – открытая позиция ВСЕГДА должна быть защищена стоп-заявкой, исходя из параметров, заданных трейдером. Поэтому основная функция этой подсистемы это автоматическое выставление стоп-заявок и трейлинг стоп-заявок. За все эти функции отвечает класс
StopOrder.cs. Подсистема сама не совершает торговых операций, это важный момент, она
только выставляет стоп-заявки для защиты открытой роботом позиции. Рыночная инициатива всегда остается за пользователем. В подсистему не заложены торговые стратегии, ее
задача – поддержка работы трейдера. При использовании подсистемы автоматического
выставления стоп-заявок, при открытии позиции торговым роботом подсистема немедленно выставляет стоп-заявку ( со связанной заявкой, или без), исходя из заданных параметров: величины просадки, проскальзывания, размера прибыли, которую нужно зафиксировать и т.д. Объем стоп-заявки будет зависеть от величины позиции. Подсистема автоматически заменит или снимет стоп-заявку при условии:
1. Изменился объем позиции. При этом StopOrder, пересчитав средную цену, изменит
значение стоп-цены.
2. Изменилась текущая цена бумаги. В этом случае если используется трейлинг стопзаявок, то происходит определение процента изменения цены и в случае выполнения условия темпа трейлинга происходит замена стоп-заявки с новой стоп-ценой.
Основной задачей являлось разделение логики формирования простых заявок и стопзаявок, т.к. простые заявки регистрируются на сервере биржи, а стоп-заявки регистрируются и периодически проверяются на сервере брокера. При реализации этого подхода
было введено такое понятие, как текущий объём позиции. Текущий объём позиции – это
общее количество всех проданных или купленных бумаг внутри позиции На рисунке16
представлен алгоритм работы выставления стоп-заявок на длиной позиции (практически
аналогично и для короткой).
36
Входные данные:
1. Тип позиции
2. Объём сделки
Новая сделка
Авто-стоп
запущен?
Остановить
авто-стоп
нет
да
покупка(вход)
продажа (выход)
Направление
сделки?
Текущий объём
позиции -= объём
сделки
Текущий объём
позиции <= 0
Текущий объём
позиции += объём
сделки
нет
Снять старую
стоп-заявку
нет
Связанная
заявка?
да
да
Авто-стоп = не
запущен
нет
TakeProfit
заявка?
да
Сформировать
связанную
заявку
Сформировать
TP заявку
Сформировать
StopLoss заявку
Записать в файл
нет
Зарегистрирована
заявку?
да
Запомнить номер
заявки
Ждать новой
сделки
Исполнена?
да
Сообщить об
этом робот
нет
Рисунок 16. Механизм работы выставления стоп-заявок.
37
Ниже
представлен
алгоритм
работы
трейлинга
стоп-заявки
для
длиной
позиции(практически аналогично для короткой позиции):
Входные данные:
1. Новая текущая цена
нет
(последняя текущая цена * % темпа
трейлинга) < Новыя текущая цена
да
Снять старую
стоп-заявку
Связанная
заявка?
да
Сформировать
связанную заявку с
новой нижней ценой, но
старой верхней
Сформировать
StopLoss заявку
с новой нижней
ценой
Записать в файл
нет
нет
Последняя текущая
цена = Новая
текущая цена
Зарегистрирована
заявку?
да
Запомнить номер
заявки
Ждать новую
текущую цену
Исполнена?
да
Сообщить об
этом робот
нет
Рисунок 17. Алгоритм работы трейлинга стоп-заявок на длиной позиции.
38
5.6 Реализация сигнала на основе индикаторов
Как уже говорилось выше, в качестве сигнала для входа или выхода в рынок
используется пересечение двух индикаторов или пересечение индикатора с ценой.
Архитектура сигнала на основе индикаторов представлена ниже:
Signal
-indicator1 : IIndicator
-indicator2 : IIndicator
-period_bar : int
+Signal(in ind1 : IIndicator, in ind2 : IIndicator, in period_bar : int)
+Check()
«interface»
IIndicator
+Current_Value() : float
+Last_Value() : float
+Step()
indMA
indParabolicSAR
-...
-...
+Current_Value() : float
+Last_Value() : float
+Step()
+Calculate()
+indParabolicSAR()
+Current_Value() : float
+Last_Value() : float
+Step()
+Calculate()
+IndMA()
Price
-...
+Current_Value() : float
+Last_Value() : float
+Step()
+Price()
Bar
-period_bars
-...
+GetBar()
+Bar()
+CountBars() : int
Рисунок 18. Архитектура сигнала на основе индикаторов
Большим плюсом такой архитектуры - является простота добавления нового
технического индикатора в систему.
39
Заключение
В результате работы было создано приложение, которое в связке с программой
QUIK автоматически выставляет заявки на покупку и продажу ценных бумаг, с возможностью ограничения убытков и взятия гарантированной прибыли. Сигналом для входа в
рынок служит пересечение двух индикаторов или пересечение индикатора с ценой. Также
в приложение реализован механизм трейлинга стоп-заявок, механизм контроля зависших
заявок. На данном этапе программа полностью пригодная для автоматической торговли.
Планируется дальнейшее развитие приложения в направлении расширения такой
функциональности, как добавления новых индикаторов для генерирования сигналов о покупке или продаже.
40
Список использованных источников
1. Биржевая торговля: [Электронный ресурс]. – 2006. – Режим доступа: http://finam.ru,
свободный
2. Шамгунов Н, Корнеев Г. State Machine- новый паттерн объектно-ориентированного
программирования – СПб:, 2001.- с9
3. Сафин В. Создание и оптимизация торговых систем в Metastock - М: ДМК Пресс,
2001.- 178с.
4.
Классика программирования, алгоритмы, языки, автоматы –СПб.;Наука и Техника,
2006.-320с
5. Троелсен .Э. С# и платформа .NET. - CПб.: Питер, 2004, 796 с.
6. Джесс Либерти. Создание .NET приложений .Программирование на C#/, 2-е издание. - М.: Изд. дом «O'REILLY», 2004, 684 с.
7. Хестанов С. Методическое пособие по основам биржевой торговли - М:, 2007.- 44с.
8. Notepad++ [Электронный ресурс]. - [Электронный ресурс].- 2007.-Режим доступа:
http://sourceforge.net/projects/notepad-plus/ , свободный
41
Приложение А.
Руководство пользователя
Установка программы
Для установки приложения запустите файл Setup.exe и следуйте указаниям
программы установки.
Работа с приложением
При запуске программы появится сообщение с уведомлением о первом запуск,
после чего необходимо внести основные настройки.
Рисунок 19. Уведомление о первом запуске.
Рисунок 20. Установка настроек
В полях “% от оборота бирже” и “% от оборота брокера” указываются
соответствующие параметры. Так же необходимо внести номер счёт и код клиента, в
дальнейшем эти параметры будут использоваться для формирования заявок в QUIK.
42
Рисунок 21. Настройки путей
В этой вкладке указывается точный путь к базе данных *.mdb, в которую будут
экспортироваться данные из QUIK. Эти параметры необходимо для правильного
функционирования программы.
Настройки программы закончились, теперь необходимо настроить “QUIK”.
Создать экспорт данных очень легко – для этого нужно загрузить в Ваш QUIK
прилагаемый к программе настроечный файл config.wnd . Выберите пункт меню
«Настройки» «Загрузить настройки из файла». Далее укажите путь к файлу настроек.
Рисунок 22. Загрузка настроек “QUIK”
43
Восстановление настройки счетов.
После загрузки в QUIK настроек у Вас
может сбиться настройка активных счетов. Ее придется восстановить. Дляэ того
выберите пункт меню«Торговля» «Настройка счетов»
Выберите нужные счета,
нажав кнопку «Добавить» так чтобы они появились в
перечне «Выбранные счета депо»
справа и нажмите «Да».
Проверка таблиц.
Нужно проверить часть таблиц на закладке Diplom на
наличие тех или иных фильтров. Для этого нужно поочередно просмотреть окна
настроек соответствующих таблиц и снять/установить флаги фильтров. Внимание!
При
просмотре настроек таблиц обязательно проверьте, что фильтры фирм, счетов депо и
клиентов не блокируют те данные, по которым будет работать в торговый автомат. В
таблице “Текущая таблица параметров Quotes” нужно выбрать бумаги по которым вы
хотите запустить автомат. В таблице “Таблица всех сделок AllTrades” необходимо
настроить фильтр вывода для бумаг, которые Вы выбрали. Вся информация из таблицы
“Таблица всех сделок AllTrades” нужна для построения минутных баров и для расчета по
ним значений скользящих средних.
Настройка импорта данных в торговый терминал QUIK Завершающий этап
настройки: настройка импорта транзакций в QUIK. Для этого нужно выполнить
следующие шаги:
1. Открыть QUIK и подключиться к брокеру.
2. Выбрать пункт меню «Торговля» «Импорт транзакций из файла».
3. В появившемся окне нужно снять галочку «Оповещать об обработке файла
звуковым сигналом», а в поле «Обрабатывать через» указываем период
обращения к файлу сделок. Рекомендуемое значение - 0.2 секунды.
44
Рисунок 23. Импорт транзакций
4. Затем указываем пути к файлам с расширениями TRI, TRO и TRR.
Нажимаем кнопку «…» напротив поля «Файл с исходными данными о транзакциях»
и выбираем: файл с transaction.tri
Аналогичным образом в поля «Файл с данными об
успешно отправленных транзакциях» и «Файл с журналом отправляемых транзакций»
выбрать файлы TRO и TRR соответственно. Все три файла располагаются в каталоге
программы торгового автомата.
5. После завершение настройки нажмите кнопку «Закрыть»
Запуск торгового автомата. Запускаем автомат и переходим «Файл»
«Подключиться к Quik»
45
Рисунок 24. Подключение к QUIK
При удачном подключении в правой части окна появится дерево выбранных
ценных бумаг в «QUIK». Так же внизу напротив «Время ММВБ» появится таймер, с
отображением текущего времени на сервере биржи. Выберите нужную бумагу, по которой
хотите запустить автомат. Во вкладке «Основные» укажите название торгуемой позиций,
автомат может работать и на длиной, и на короткой позиции, и одновременно в двух
позициях.
46
Рисунок 25. Окно настройки параметров торговли
В следующей вкладке задаются параметры сигнала. Можно определить
совершенно разные сигналы для каждой позиции.
Рисунок 26. Настройка параметров для индикаторов скользящих средних.
47
Во вкладке «Стоп-заявки» можно настроить использование stop-loss и take-profit, а
так же включить процесс трейлинга стоп-заявок.
Рисунок 27. Настройки стоп-заявок
После настройки всех параметров для запуска торгового автомата необходимо
нажать на кнопку «Старт». В поле “Статус автомата” можно увидеть текущее состояние
автомата по ценной бумаге.
Рисунок 28. Запуск торгового автомата.
Торговый автомат можно настроить индивидуально по конкретной бумаге.
48
Приложение Б.
Руководство программиста
Автоматная часть
Класс GenSignal
public delegate IGenSignal EnterLongHandler(ref GenSignal gs);
public delegate void EnterLongHandler1(ref GenSignal gs);
public delegate void EnterLongHandler2(ref GenSignal gs);
public class GenSignal : IGenSignal
{
StartState Start;
NotMarketState NotMarket;
StopState Stop;
LongState Long;
preEnterLongState preEnterLong;
preExitLongState preExitLong;
ShortState Short;
preEnterShortState preEnterShort;
preExitShortState preExitShort;
public GenSignal(dmGenSignal dm)
{
this.dm = dm;
Start = new StartState(dm);
NotMarket = new NotMarketState(dm);
Stop = new StopState(dm);
if (dm.Param._long) //проверка для длинной позиции
{
Long = new LongState(dm);
preEnterLong = new preEnterLongState(dm);
preExitLong = new preExitLongState(dm);
}
if (dm.Param._short) //проверка для короткой позиции
{
Short = new ShortState(dm);
preEnterShort = new preEnterShortState(dm);
preExitShort = new preExitShortState(dm);
}
init();
}
public event StateChangedEventHandler StateChanged;
protected object CurrentState; //текущее состояние
private bool isInit;
public dmGenSignal dm; //объект модели данных
public string GetStateName
{
get
{
return ((IState)CurrentState).StateName;
}
}
49
protected void init()
{
if (isInit) return;
isInit = true;
CurrentState = Start; //Начальное состояние
#region Определение обработчиков событий автомата
Start.RUN_BOT += new EventHandler(Start_RUN_BOT);
NotMarket.STOP_BOT += new EventHandler(NotMarket_STOP_BOT);
if (dm.Param._long == true) //проверка для длиной позиции
{
NotMarket.ENTER_LONG += new
EventHandler(NotMarket_ENTER_LONG);
preEnterLong.OK_ENTER_LONG += new
EventHandler(preEnteLong_OK_ENTER);
preEnterLong.CANCEL_ENTER_LONG += new
EventHandler(preEnteLong_CANCEL_ENTER);
Long.EXIT_LONG += new EventHandler(Long_EXIT_LONG);
Long.STOP_BOT += new EventHandler(Long_STOP_BOT);
if (dm.Param._stop_lose == true || dm.Param._take_profit ==
true)
Long.STOP_ORDER += new EventHandler(Long_STOP_ORDER);
preExitLong.CANCEL_EXIT_LONG += new
EventHandler(preExitLong_CANCEL_EXIT);
preExitLong.OK_EXIT_LONG += new
EventHandler(preExitLong_OK_EXIT);
preExitLong.OK_STOP += new
EventHandler(preExitLong_STOP_BOT);
}
if (dm.Param._short) //проверка для короткой позиции
{
NotMarket.ENTER_SHORT += new
EventHandler(NotMarket_ENTER_SHORT);
preEnterShort.OK_ENTER_SHORT += new
EventHandler(preEnterShort_OK_ENTER);
preEnterShort.CANCEL_ENTER_SHORT += new
EventHandler(preEnterShort_CANCEL_ENTER);
Short.EXIT_SHORT += new EventHandler(Short_EXIT_SHORT);
Short.STOP_BOT += new EventHandler(Short_STOP_BOT);
if (dm.Param._stop_lose == true || dm.Param._take_profit ==
true)
Short.STOP_ORDER += new EventHandler(Short_STOP_ORDER);
preExitShort.CANCEL_EXIT_SHORT += new
EventHandler(preExitShort_CANCEL_EXIT);
preExitShort.OK_EXIT_SHORT += new
EventHandler(preExitShort_OK_EXIT);
preExitShort.OK_STOP += new
EventHandler(preExitShort_STOP_BOT);
}
#endregion
}
#region IGenSignal Members
public void start()
{
((IGenSignal)CurrentState).start();
}
50
public void enterLong()
{
((IGenSignal)CurrentState).enterLong();
}
public void exitLong()
{
((IGenSignal)CurrentState).exitLong();
}
public void stop()
{
((IGenSignal)CurrentState).stop();
}
public void releaseStopOrder()
{
((IGenSignal)CurrentState).releaseStopOrder();
}
public void enterShort()
{
((IGenSignal)CurrentState).enterShort();
}
public void exitShort()
{
((IGenSignal)CurrentState).exitShort();
}
public void cancelEnter()
{
((IGenSignal)CurrentState).cancelEnter();
}
public void cancelExit()
{
((IGenSignal)CurrentState).cancelExit();
}
public void okEnter()
{
((IGenSignal)CurrentState).okEnter();
}
public void okExit()
{
((IGenSignal)CurrentState).okExit();
}
#endregion
#region Временно
private void EnterLongCheck(object data)
{
if (data is GenSignal)
{
this.dm.WaitEnterLong();
this.enterLong();
}
}
private void ExitLongCheck(object data)
{
if (data is GenSignal)
{
this.dm.WaitExitLong();
this.exitLong();
}
}
51
private void EnterShortCheck(object data)
{
if (data is GenSignal)
{
this.dm.WaitEnterShort();
this.enterLong();
}
}
private void ExitShortCheck(object data)
{
if (data is GenSignal)
{
this.dm.WaitExitShort();
this.exitLong();
}
}
#endregion
#region Переходы
public void Start_RUN_BOT(object send, EventArgs e)
{
if (Object.ReferenceEquals(CurrentState, Start))
{
CurrentState = NotMarket;
if (StateChanged != null)
{
StateChanged(this, new
StateChangedEventArgs(Start.StateName, NotMarket.StateName));
}
if (this.dm.Param._long == true) //запуск потока для
определения сигнал входа в длинную позицию
{
Thread t1 = new Thread(new
ParameterizedThreadStart(EnterLongCheck));
t1.Name =
this.dm.Param.seccode+"_"+this.dm.Param.classcode +
"_Enter_long_from_NotMarket";
t1.Start(this);
}
if (this.dm.Param._short == true) //запуск потока для
определения сигнала входа в короткую позицию
{
Thread t2 = new Thread(new
ParameterizedThreadStart(EnterShortCheck));
t2.Name = this.dm.Param.seccode + "_" +
this.dm.Param.classcode + "_Enter_short_from_NotMarket";
t2.Start(this);
}
}
}
…
#endregion
}
Классы состояний StartState, NotMarketState …StopState
public class StartState : IGenSignal
{
52
protected dmGenSignal dm;
#region События
public event EventHandler RUN_BOT; //Событие
#endregion
private string _StateName = "Start";//название состояния
public string StateName
{
get {
return _StateName;
}
}
public StartState(dmGenSignal dm)
{
this.dm = dm;
}
#region IGenSignal Members
public void start()
{
if (RUN_BOT != null) //оповестить контекст
{
RUN_BOT(this, new EventArgs());
}
}
public void enterLong(){}
public void exitLong() { }
public void stop() { }
public void releaseStopOrder() { }
public void enterShort() { }
public void exitShort() { }
public void cancelEnter() { }
public void cancelExit() { }
public void okEnter() { }
public void okExit() { }
#endregion
}
Интерфейс IGenSignal
public interface IGenSignal
{
void start();
void enterLong();
void exitLong();
void stop();
void releaseStopOrder();
void enterShort();
void exitShort();
void cancelEnter();
void cancelExit();
void okEnter();
void okExit();
}
Класс dmGenSignal
public class dmGenSignal
{
private Param param;
public dmGenSignal(Param param)
{
this.param = param;
}
public Param Param
{
get { return param; }
}
public bool WaitEnterLong()
{
53
float[] d_sma1 = param.MA1 .GetData();
float[] d_sma2 = param.MA2.GetData();
while (Function.cross(d_sma1, d_sma2) == false)
{
Thread th = Thread.CurrentThread;
Thread.Sleep(60000);
d_sma1 = param.MA1.GetData();
d_sma2 = param.MA2.GetData();
}
return true;
}
public bool WaitExitLong()
{
float[] d_sma1 = param.MA1.GetData();
float[] d_sma2 = param.MA2.GetData();
while (Function.cross(d_sma2, d_sma1) == false)
{
Thread th = Thread.CurrentThread;
Thread.Sleep(60000);
d_sma1 = param.MA1.GetData();
d_sma2 = param.MA2.GetData();
}
return true;
}
public bool WaitEnterShort()
{
float[] d_sma1 = param.MA1.GetData();
float[] d_sma2 = param.MA2.GetData();
while (Function.cross(d_sma2, d_sma1) == false)
{
Thread th = Thread.CurrentThread;
Thread.Sleep(60000);
d_sma1 = param.MA1.GetData();
d_sma2 = param.MA2.GetData();
}
return true;
}
public bool WaitExitShort()
{
float[] d_sma1 = param.MA1.GetData();
float[] d_sma2 = param.MA2.GetData();
while (Function.cross(d_sma1, d_sma2) == false)
{
Thread th = Thread.CurrentThread;
Thread.Sleep(60000);
d_sma1 = param.MA1.GetData();
d_sma2 = param.MA2.GetData();
}
return true;
}
…
}
54
Download