Торговый робот. Шаг за шагом. Шаг 4.
Май 3, 2010 | 12 комментариев
Шаг 4. Переводим алгоритм на язык QPile.
В данном уроке переведем блок-схему первого урока на язык QPile.
В предыдущих уроках мы с вами освоили построение алгоритма и структуру программного кода для торговых роботов, а также научились получать данные индикаторов из графиков с помощью внешних функций. Теперь настало время описать алгоритм на языке QPile.
Ненадолго вернемся к первому уроку и вспомним блок-схему алгоритма для нашего торгового робота, который также описан в первом уроке.
Рис. 4-1 Блок-схема. (Кликабельно)
Блок схема состоит из простых вопросов и однозначных ответов «Да» или «Нет». Для описания этих вопросов и ответов на них будем использовать оператор условия «If».
Синтаксис:
Также будут использованы математические, логические и текстовые операции. Подробно о них можно узнать в главе 8 руководства пользователя Quik
Итак, поехали…
Вопрос1. Портфель пустой?
Используем встроенную функцию DEPO_CURRENT_BALANCE
Внимание!!! Использование возможно лишь на спот-рынке. Для срочных рынков применяются другие функции.
DEPO_CURRENT_BALANCE (STRING client_code, STRING firmid, STRING seccode, STRING account)
STRING client_code – код клиента. Для примера возьмем 56786
STRING firmid – фирма. Для примера возьмем MC0567300
STRING seccode – код инструмента. В нашем случае SBER03
STRING account — торговый счет. Для примера возьмем G01-0005D07
Внимание!!! Подробно о данных переменных читайте в статье «Настройка скриптов под свой торговый счет«
Введем переменную ToolQuantity, которой в начале расчета портфеля будет присвоено числовое значение состояния портфеля. Другими словами, какое количество инструмента имеется в наличии на момент расчета. В случае наличия коротких позиций ToolQuantity будет иметь отрицательное значение.
1 | ToolQuantity = DEPO_CURRENT_BALANCE("56786", "MC0567300", "SBER03", "Y62-000098B01") +0 |
Примечание: «+0» в конце строки переводит переменную ToolQuantity в разряд числовых переменных.
Введем новую переменную в условие.
1 2 3 4 5 | If ToolQuantity ==0 Портфель пустой else Портфель НЕ пустой end if |
Вопрос 2. Можно открыть длинную позицию?
Возвращаясь к первому уроку выясняем условия для входа в длинную позицию. Открывать длинную позицию следует при выполнении трех условий:
- ЕМА_1 > ЕМА_2 (Короткая ЕМА выше длинной ЕМА для последней закрытой свечи)
- АС_С > 0 (Текущее значение АС выше нулевой черты)
- АС_С > АС_С_1 (Текущее значение АС больше предыдущего значения)
Для того, чтобы поставить все 3 условия одновременно используем логическую операцию «И» («AND»). Необходимые для условия переменные были заданы в третьем уроке.
Условие выглядит следующим образом:
1 2 3 | If (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1) Выполнены все условия, выставляем заявку на покупку. End if |
Примечание. Выставление заявок будет рассмотрено в следующих уроках.
Теперь переходим к блоку «Портфель НЕ пустой»
Вопрос 4. Можно закрыть длинную позицию?
По условиям технического задания основание для выхода из длинной позиции служит переход индикатора АС в отрицательную зону, т.е. AC < 0. Так и запишем.
1 2 3 | If (ToolQuantity>0) and (АС_С < 0) Закрываем позицию, выставляя заявку на продажу. End if |
Вопрос 5. Можно закрыть короткую позицию?
Аналогично вопросу 4 получаем:
1 2 3 | If (ToolQuantity<0) and (АС_С > 0) Закрываем позицию, выставляя заявку на покупку. End if |
Итак, мы записали все вопросы блок-схемы на языке QPile. Пришло время сложить все имеющиеся кубики торгового робота воедино.
Кубик с необходимыми переменными:
1 | ToolQuantity = DEPO_CURRENT_BALANCE("56786", "MC0567300", "SBER03", "Y62-000098B01") +0 |
Кубик с вопросами:
1 2 3 4 5 6 7 8 9 10 11 | If ToolQuantity ==0 If (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1) Заявка на покупку End if If (ЕМА_1 < ЕМА_2) and (АС_С < 0) and (АС_С < АС_С_1) Заявка на продажу End if Else If (ToolQuantity>0) and (АС_С < 0) Заявка на продажу End if If (ToolQuantity<0) and (АС_С > 0) Заявка на покупку End if End if |
Общий текст программы будет иметь вид:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | PORTFOLIO_EX EMAvsAC; DESCRIPTION Робот ЕМА и АС; CLIENTS_LIST ALL_CLIENTS; FIRMS_LIST ALL_FIRMS; INCLUDE fGetMA.qpl, fGetAC.qpl; PROGRAM 'Наш первый Портфель на основе ЕМА и АС 'Версия 0.1 DELETE_ALL_ITEMS () 'Благодаря этой функции из таблицы будут удалены старые значения. 'Короткая ЕМА (ЕМА_1) для последней закрытой свечи dataMA9 = fGetMA("SBEREMA9", 2, 15) EMA_1 = get_value (dataMA9,"MA_MAIN")+0 'Длинная ЕМА (ЕМА_2) для последней закрытой свечи dataMA25 = fGetMA("SBEREMA25", 2, 15) EMA_2 = get_value (dataMA25,"MA_MAIN")+0 'Текущее значение AC (АС_С) в незакрытой свече dataAC1 = fGetAC("SBERAC", 1, 15) AC_C = get_value (dataAC1,"AC_MAIN")+0 'Значение АС в последней закрытой свечи (АС_С_1) dataAC2 = fGetAC("SBERAC", 2, 15) AC_C_1 = get_value (dataAC2,"AC_MAIN")+0 ToolQuantity = DEPO_CURRENT_BALANCE("56786", "MC0567300", "SBER03", "Y62-000098B01") +0 If ToolQuantity == 0 If (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1) Заявка на покупку End if If (ЕМА_1 < ЕМА_2) and (АС_С < 0) and (АС_С < АС_С_1) Заявка на продажу End if Else If (ToolQuantity>0) and (АС_С < 0) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | Заявка на продажу End if If (ToolQuantity<0) and (АС_С > 0) Заявка на покупку End if End if Massiv = CREATE_MAP() 'Создали массив с названием Massiv Last_price = GET_VALUE(GET_PARAM_EX("EQBR","SBER03","last"),"param_value") 'Достаем из таблицы текущих параметров цену последней сделки по инструменту Massiv = SET_VALUE(Massiv,"SecCode","СБЕРБАНК") 'Записали в массив наименование инструмента Massiv = SET_VALUE(Massiv,"LastPrice", Last_price) 'Записали в массив цену последней сделки по инструменту Massiv = SET_VALUE(Massiv,"EMA_1", EMA_1) Massiv = SET_VALUE(Massiv,"EMA_2", EMA_2) Massiv = SET_VALUE(Massiv,"AC_C", AC_C) Massiv = SET_VALUE(Massiv,"AC_C_1", AC_C_1) ADD_ITEM(0, Massiv) END_PROGRAM PARAMETER SecCode; PARAMETER_TITLE Инструмент; PARAMETER_DESCRIPTION Наименование инструмента; PARAMETER_TYPE String(10); END PARAMETER LastPrice; PARAMETER_TITLE Цена; PARAMETER_DESCRIPTION Цена последней сделки по инструменту; PARAMETER_TYPE Numeric(10,2); END PARAMETER EMA_1; PARAMETER_TITLE ЕМА_1; PARAMETER_DESCRIPTION MovingAverage с параметрами Exponential, 9; PARAMETER_TYPE Numeric(10,6); END PARAMETER EMA_2; PARAMETER_TITLE ЕМА_2; PARAMETER_DESCRIPTION MovingAverage с параметрами Exponential, 25; PARAMETER_TYPE Numeric(10,6); END PARAMETER AC_C; PARAMETER_TITLE АС незакрытой свечи; PARAMETER_DESCRIPTION АС незакрытой свечи; PARAMETER_TYPE Numeric(10,6); END PARAMETER AC_C_1; PARAMETER_TITLE АС закрытой свечи; PARAMETER_DESCRIPTION АС закрытой свечи; PARAMETER_TYPE Numeric(10,6); END END_PORTFOLIO_EX |
Однако в таком виде мы не можем загрузить наш портфель в Quik. Дело в строках «Заявка на покупку» и «Заявка на продажу».
Но нет худа без добра, не так ли?
Вместо мешающих загрузки портфеля строк поставим команды, которые будут фиксировать наступление того или иного события.
Внимание!!! Подробно о методе можно прочитать в статье «Что он там делает?» Следим за работой робота.
В вышеупомянутой статье рассматривается способ ведения журнала учета всех действия робота. Этим мы и воспользуемся.
Первым делом прикрепим необходимую внешнюю функцию fDebugLog.qpl (Как это сделать читайте в 3м уроке)
Далее определим что же именно мы будем фиксировать в журнале.
1 2 3 4 5 6 7 8 9 10 11 | If ToolQuantity == 0 If (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1) fDebugLog("Портфель пустой. Выполнено условие для ЛОНГа. Ставим заявку на покупку") End if If (ЕМА_1 < ЕМА_2) and (АС_С < 0) and (АС_С < АС_С_1) fDebugLog("Портфель пустой. Выполнено условие для ШОРТа. Ставим заявку на продажу") End if Else If (ToolQuantity>0) and (АС_С < 0) fDebugLog("Открыта позиция ЛОНГ. Выполнено условие для закрытия позиции. Ставим заявку на продажу") End if If (ToolQuantity<0) and (АС_С > 0) fDebugLog("Открыта позиция ШОРТ. Выполнено условие для закрытия позиции. Ставим заявку на покупку") End if End if |
Делаем правки в тексте портфеля и получаем:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | PORTFOLIO_EX EMAvsAC; DESCRIPTION Робот ЕМА и АС; CLIENTS_LIST ALL_CLIENTS; FIRMS_LIST ALL_FIRMS; INCLUDE fGetMA.qpl, fGetAC.qpl, fDebugLog.qpl; PROGRAM 'Наш первый Портфель на основе ЕМА и АС 'Версия 0.1 DELETE_ALL_ITEMS () 'Благодаря этой функции из таблицы будут удалены старые значения. 'Короткая ЕМА (ЕМА_1) для последней закрытой свечи dataMA9 = fGetMA("SBEREMA9", 2, 15) EMA_1 = get_value (dataMA9,"MA_MAIN")+0 'Длинная ЕМА (ЕМА_2) для последней закрытой свечи dataMA25 = fGetMA("SBEREMA25", 2, 15) EMA_2 = get_value (dataMA25,"MA_MAIN")+0 'Текущее значение AC (АС_С) в незакрытой свече dataAC1 = fGetAC("SBERAC", 1, 15) AC_C = get_value (dataAC1,"AC_MAIN")+0 'Значение АС в последней закрытой свечи (АС_С_1) dataAC2 = fGetAC("SBERAC", 2, 15) AC_C_1 = get_value (dataAC2,"AC_MAIN")+0 ToolQuantity = DEPO_CURRENT_BALANCE("56786", "MC0567300", "SBER03", "Y62-000098B01") +0 If ToolQuantity == 0 If (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1) fDebugLog("Портфель пустой. Выполнено условие для ЛОНГа. Ставим заявку на покупку") End if If (ЕМА_1 < ЕМА_2) and (АС_С < 0) and (АС_С < АС_С_1) fDebugLog("Портфель пустой. Выполнено условие для ШОРТа. Ставим заявку на продажу") End if Else If (ToolQuantity>0) and (АС_С < 0) fDebugLog("Открыта позиция ЛОНГ. Выполнено условие для закрытия позиции. Ставим заявку на продажу") End if If (ToolQuantity<0) and (АС_С > 0) fDebugLog("Открыта позиция ШОРТ. Выполнено условие для закрытия позиции. Ставим заявку на покупку") End if End if Massiv = CREATE_MAP() 'Создали массив с названием Massiv Last_price = GET_VALUE(GET_PARAM_EX("EQBR","SBER03","last"),"param_value") 'Достаем из таблицы текущих параметров цену последней сделки по инструменту Massiv = SET_VALUE(Massiv,"SecCode","СБЕРБАНК") 'Записали в массив наименование инструмента Massiv = SET_VALUE(Massiv,"LastPrice", Last_price) 'Записали в массив цену последней сделки по инструменту Massiv = SET_VALUE(Massiv,"EMA_1", EMA_1) Massiv = SET_VALUE(Massiv,"EMA_2", EMA_2) Massiv = SET_VALUE(Massiv,"AC_C", AC_C) Massiv = SET_VALUE(Massiv,"AC_C_1", AC_C_1) ADD_ITEM(0, Massiv) END_PROGRAM PARAMETER SecCode; PARAMETER_TITLE Инструмент; PARAMETER_DESCRIPTION Наименование инструмента; PARAMETER_TYPE String(10); END PARAMETER LastPrice; PARAMETER_TITLE Цена; PARAMETER_DESCRIPTION Цена последней сделки по инструменту; PARAMETER_TYPE Numeric(10,2); END PARAMETER EMA_1; PARAMETER_TITLE ЕМА_1; PARAMETER_DESCRIPTION MovingAverage с параметрами Exponential, 9; PARAMETER_TYPE Numeric(10,6); END PARAMETER EMA_2; PARAMETER_TITLE ЕМА_2; PARAMETER_DESCRIPTION MovingAverage с параметрами Exponential, 25; PARAMETER_TYPE Numeric(10,6); END PARAMETER AC_C; PARAMETER_TITLE АС незакрытой свечи; PARAMETER_DESCRIPTION АС незакрытой свечи; PARAMETER_TYPE Numeric(10,6); END PARAMETER AC_C_1; PARAMETER_TITLE АС закрытой свечи; PARAMETER_DESCRIPTION АС закрытой свечи; PARAMETER_TYPE Numeric(10,6); END END_PORTFOLIO_EX |
Таким образом, в любой момент времени мы можем узнать из журнала, что нам предлагает делать робот в тот или иной момент времени.
P.S. Вы можете скачать представленный код одним файлом, а также вышеуказанную функцию.
Скачать Lesson 4
Метки: qpile / для начинающих / Разработка / самоучитель / структура торговой системы / торговая стратегия / торговый робот / урок / функция QPile
Комментарии
12 ответов to “Торговый робот. Шаг за шагом. Шаг 4.”
Оставить комментарий
Июнь 26th, 2010 @ 11:00
У меня почемуто выдает ошибку на строке 25.
If (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1)
Найти ошибку не смог. Помогите разобраться что не так…
Июнь 27th, 2010 @ 16:41
Можете подробнее описать ошибку?
Июнь 28th, 2010 @ 20:15
http://content.foto.mail.ru/inbox/sotikov/36/i-47.jpg
Июнь 30th, 2010 @ 18:34
У меня тоже выдаёт ошибку в строке условий на покупку
Июнь 30th, 2010 @ 20:27
А при загрузке в Квик не выдает?
Июль 1st, 2010 @ 12:06
Аналогично, при загрузке в Квик не выдает
Июль 8th, 2010 @ 21:38
Ошибка исправлена. Файл перезалит.
Ошибка «Unknown lexema» означает, что в строке имеется неизвестный знак. QPile очень чувствителен к символам, шрифтам.
Июль 9th, 2010 @ 09:16
Сообщите пожалуйста в чём была ошибка. После устранения вами этой ошибки, Квик указывает на аналогичную ошибку в строке If (ToolQuantity 0)
Июль 9th, 2010 @ 09:21
Сообщите пожалуйста в чём была ошибка. После устранения вами этой ошибки, Квик указывает на аналогичную ошибку в строке If (ToolQuantity 0)
Июль 9th, 2010 @ 09:24
Строка почемуто правильно не копируется.
Июль 13th, 2010 @ 10:53
«Ошибка исправлена. Файл перезалит.»
Что-то я не заметил разницы…
Квик все так же ругается…
Январь 12th, 2011 @ 13:57
25 и 36 строки надо вручную переписать, там где-то буква А или С не на латинской раскладке набрана, а на кририллической