Главная > Торговый робот > Торговый робот для QUIK «Пробойный». Часть четвертая

Торговый робот для QUIK «Пробойный». Часть четвертая

19 апреля 2009

Функции QPILE

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

FUNC название(параметр1,параметр2,...,параметрN)
код подпрограммы
END FUNC

ORDER(0,LOTS,OP,"LIMIT",TRID)

Это функция из третьей части нашего робота. ORDER — имя, и в скобках мы передаем параметры, обозначенные в описании самой функции:

FUNC ORDER(FPRICE,FLOTS,FDIRECTION,FTYPE,FTRID)

Мы передаем цену, количество лотов, направление, тип заявки, и идентификационный номер транзакции.

Правильное использование функций значительно упрощает программирование, а также визуальное восприятие кода. Я всегда стараюсь правильно организовать код, чтоб если понадобится через год опять его поднять и разобраться — можно было сразу понять что куда.

Итак, вернемся к четвертой части нашего робота для QUIK «Пробойный». Код:

Код на QPILE доступен только зарегистрированным пользователям.

Постарайтесь разобраться в каждой строчке кода. Тут есть уже знакомые нам функции получения котировок из графика QUIK, функции перевода даты и времени в текстовый формат и пр. Если Вы разберетесь с данным кодом, потом сможете менять условия и построить своего собственного робота.

В следующий раз мы обсудим как открывать учебный счет и приступим к тестированию!

Евгений Торговый робот , , , ,

  1. Dr. Livsey
    3 Май 2009 в 01:41 | #1

    Добрый день. А можно более подробно прокомментировать строчки 8-9. А то никак не могу врубиться. что мы тут делаем.

  2. Евгений
    3 Май 2009 в 10:14 | #2

    Это функция получения котировок по номеру бара.

    в 7 строке мы получаем текущей значение «минут», например 49;

    в 8 строке мы округляем значение минут до нашего интервала(например 5-ти минутки): 5*округлениевниз(49/5)=45:

    в 9 строке мы получаем целочисленное значение окончания цикла, которое зависит от установок DAYTOFIND (сколько дней назад ищем котировки)

    подробнее об этом процессе читайте в статье: www.hirobot.ru/2009/03/ka...iz-grafika-quik/

  3. User
    25 Май 2009 в 15:18 | #3

    Скажите, пожалуйста, а что такое (' ДЕЛАЕМ ПСЕВДОМАРКЕТ)?

    Евгений Reply:

    На рынке ФОРТС нет понятия маркетной, или рыночной заявки, но ее можно имитировать путем завышения, или занижения цены, в зависимости от того, какую операцию нам нужно сделать. Таким образом торговая система, при исполнении таких заявок, собирает нужное нам кол-во лотов по стакану. Обычно я к цене LAST добавляю или отнимаю определенное кол-во пунктов.

  4. User
    25 Май 2009 в 15:50 | #4

    При загрузке портфеля выдает ошибку при расчете:

    Unknown identifier CLASSCODELIST [CANDLE=GET_CANDLE(CLASSCODELIST,INSTRUMENT, "", INTERVAL & "", "PRICE", TEXTDATA, TEXTTIME)]

    там не может быть ошибки в функции OHLC, в самом цикле?

    Евгений Reply:

    CLASSCODELIST="SPBFUT" вставьте эту строку в начало программы, где определяется инструмент. Забыл...

  5. User
    25 Май 2009 в 17:04 | #5

    Спасибо, вроде все по

    TRANS_PARAMS = SET_VALUE (TRANS_PARAMS, «PRICE», (FPRICE+(1000*SIGN))&"")

    а 1000 — это не круто для маркетного отступа?

    или он не здесь задается?

    Кстати, с High, Low тоже самое:

    Unknown identifier HIGH [CURRENTHIGH=HIGH]"

    Может в другом месте их задать надо?

    Евгений Reply:

    1000, или иное значение зависит от лимитов дневной цены.

  6. User
    25 Май 2009 в 18:58 | #6

    Что то я действительно не понял, а как правильно задать переменные —

    HIGH и LOW?

    Снова при расчете портфеля выдает ошибку:

    Unknown identifier

    HIGH [CURRENTHIGH=HIGH]

    кусок из кода:

    OHLC (1) '...ДЛЯ ОПРЕДЕЛЕНИЯ ТЕКУЩЕГО ЗНАЧЕНИЯ HIGH И LOW

    CURRENTHIGH=HIGH ' ПРИСВАИВАЕМ ПЕРЕМЕННЫМ ЗНАЧЕНИЯ ТЕКУЩИХ HIGH И LOW

    CURRENTLOW=LOW

    OHLC (CANDLETOFIND) ' ЗАПРАШИВАЕМ КОТИРОВКИ БАРА ПО УСЛОВИЮ

    IF CURRENTHIGH>HIGH

    HIGH=CURRENTHIGH

    END IF

    IF (CURRENTLOW0)

    LOW=CURRENTLOW

    Евгений Reply:

    OHLC (CANDLETOFIND) — это убираем;

    в начале программы, где определяются переменные, укажите:

    HIGH=0

    LOW=0

    п.с. эти коды — вырезки из более мощной системы, может чего «недорезал» :)

  7. АндрейН
    7 Июнь 2009 в 11:19 | #7

    Евгений, добрый день.

    Скачал в апреле робота «пробойный», стал его изменять, а вот сейчас понадобилось сравнить с оригиналом твоим и не вижу, где он выложен.

    Еще вопрос: если впоследствии обнаруживаются ошибки в кодах роботов, ты их правишь? или они выложены по состоянию на момент выхода статьи?

    Евгений Reply:

    Привет. Ошибки правлю, пишите где. С сайта ничего не удалял, просто «пробойный» в объединенном виде не выкладывал, его надо собирать по частям в публикациях. Вообще я преследую цель научить, а не дать «халяву», прошу прощения за выражение, поэтому выкладываю коды от 99% до 100% готовности, каждый дорабатывает под себя. Я уверен что даю 100% нужной для этого информации.

  8. АндрейН
    9 Июнь 2009 в 01:27 | #8

    А, точно. Я его и собрал из кусочков.

    У меня при копировании со странички вылезли & в тексте робота, убирал руками.

  9. qsn
    8 Октябрь 2009 в 17:54 | #9

    Добрый день Евгений.

    FUNC ORDER (FPRICE,FLOTS,FDIRECTION,FTYPE,FTRID) ' ФУНКЦИЯ ОТПРАВКИ ТРАНЗАКЦИЙ В ТОРГОВУЮ СИСТЕМУ 198.

    199.IF FTYPE="LIMIT" 200.

    201.FPRICE=PRICE

    203.END IF

    Для чего введен префикс F в формальных параметрах и откуда взялся PRICE в строке 201

    И еще. Почему не используете регистр для имен переменных?

    QPILE это позволяет.

    Евгений Reply:

    Привет.

    Префикс F введен чтоб не путаться в переменных, можно не использовать но мне так удобнее, и я знаю что с этим префиксом переменные я использую внутри функции отправки транзакций.

    FPRICE=PRICE — это атавизм от более навороченной функции. Насколько я помню при вызове этой функции мы вместо цены передаем ноль, а внутри функции уже присваиваем FPRICE значение цены последней сделки. Я уже не помню для чего я делал таким образом... В этом случае можно вообще ничего не передавать, а внутри функции вместо FPRICE использовать сразу переменную PRICE. Если PRICE — это цена последней сделки нашего инструмента.

    Насчет регистра не понял... Наверное имеете в виду почему все прописными буквами пишу? Мне так удобнее код читать. :)

  10. qsn
    9 Октябрь 2009 в 10:56 | #10

    Добрый день Евгений.

    Я так и не понял. Price это какая-то глобальная переменная?

    201.FPRICE=PRICE

    Сохранит ли FPRICE присвоенное значение после выхода из функции?

    Про регистр Вы все правильно поняли. Не используете — жаль. Это существенно избавляет от ошибок в листинге еще до отладки. Для QPILE с его отладчиком и редактором крайне важно!

    Евгений Reply:

    PRICE — в самом начале робота этой переменной должна присваиваться цена последней сделки из табл текпарам для нашего инструмента. FPRICE будет сохранять присвоенное значени пока мы его сами не поменяем.

  11. qsn
    9 Октябрь 2009 в 20:08 | #11

    Спасибо, понял — попробую.

  12. pocemon
    22 Ноябрь 2009 в 17:08 | #12

    Евгений, объясните, пожалуйста, функцию FUNC KILLALLSTOP.

    Не очень поимаю зачем там ключ с цифрой 3

    N3=GET_NUMBER_OF («STOP_ORDERS»)

    и в номере транзакции что означает amp

    TRANS_PARAMS = SET_VALUE (TRANS_PARAMS, «TRANS_ID», «0»&TIME)

    Евгений Reply:

    amp — это дурацкий движок блога вписывает вместо «&»

    N3 — ничего не значит, это переменная.

    pocemon Reply:

    Спасибо.

  13. chelny07
    18 Декабрь 2009 в 17:51 | #13

    Евгений я собрал все разделы робота в одно целое и у меня вылетает ошибка, я напишу полностью что вылетает:

    "Произошла ошибка при загрузке формулы расчета портфеля «PROBOY», идентификатор организации «ALL_FIRMS» сообщение об ошибке "File: (null), line: 513. END iif missing "

    уже час ковыряюсь и не могу разобраться в чем дело. Помогите пожалуйста)

    Евгений Reply:

    Где то пропустили оператор END IF. Посчитайте количество «начал» операторов условия IF и их окончаний.

    Евгений Reply:

    В догонку: час — это ничто... Я годы потратил чтоб разбираться в этом языке. Не сдавайтесь и не паникуйте раньше времени :)

    chelny07 Reply:

    спасибо сейчас буду смотреть)

    chelny07 Reply:

    Евгений еще вопросик? теперь ошибка: Unknown identifier DATE [ TRID=DATE&TIME] С этим что делать? Я так понимаю не хватает переменной чтоли?

    Евгений Reply:

    Да.

  14. KentAVP
    24 Декабрь 2009 в 11:09 | #14

    Объясните значение

    OUTPUT=SET_VALUE (OUTPUT,"GO",GO)

    PARAMETER GO;

    PARAMETER_TITLE GO;

    PARAMETER_DESCRIPTION GO;

    PARAMETER_TYPE NUMERIC (10,0);

    END

    программа выдавала ошибку, убрав эти параметры, она заработала

    Евгений Reply:

    GO — гарантийное обеспечение. В первоначальной версии был модуль расчета позиции в % от доступного капитала. Скоро выложу функцию.

    KentAVP Reply:

    С остальными ошибками разобрался. Quik теперь выдает мне сообщение «MUST BUY FIRST» или «MUST SELL FIRST».

    Уже который час мучаюсь, объясните как решить эту проблему?

    Евгений Reply:

    Эти сообщения робот выдает при отправке транзакции, если сделка не проходит то:

    1. неверный код инструмента

    2. нулевое либо не положительное кол-во лотов

    3. неверная цена

    Расширенная диагностика MESSAGE (RESULT,1) должна написать в чем конкретно причина.

    KentAVP Reply:

    у меня пожалуй еще вопрос.

    есть строки

    SIGN=-1

    IF FDIRECTION="B"

    SIGN=1

    END IF

    Получается для OPERATION будет определен только параметр B, а где параметр S?

    может для SIGN=-1 сделать также, т.е.

    FDIRECTION="S"

    SIGN=-1

    END IF

    FDIRECTION="B"

    SIGN=1

    END IF

    Евгений Reply:

    Нет, в первоначальном блоке все верно. Просто это элегантное решение, подсказанное мне моим другом.

    Изначально переменная SIGN=-1 и лишь в том случае если у нас покупка переменная меняет знак, а если продажа то условие не срабатывает и переменная остается отрицательной! Ускорение работы программы, пусть небольшое но все же.

    :)

    KentAVP Reply:

    Я сделал, как Вы сказали. За сообщением «MUST SELL FIRST» шло следющее «110000». Это очень походит на значение TIME, в тот момент времени, когда я работал.

    Как исправить эту ошибку

    Евгений Reply:

    Отследите по коду, какой оператор посылает это сообщение. Расширенная диагностика что пишет? Полистайте окно сообщений. Проследите отладчиком значения переменных.

    KentAVP Reply:

    не могли бы вы помочь пожалуйста? у меня счетчик TP постоянно на нуле, даже при открытой позиции. с чем это может быть связано?

    Евгений Reply:

    1. Неверный код инструмента (если рынок ФОРТС, то у разных брокеров инструменты либо короткие коды либо длинные: RIH0 или RTS-3.10, попробуйте оба кода)

    2. Если площадка ФОРТС — неверная строка в таблице Позиции клиента

    3. Если ММВБ — неверная строка в таблице лимитов по бумагам.

    ...

    Напишите код получения ТП с указанием инструмента и площадки.

    KentAVP Reply:

    INSTRUMENT="SRH0"

    LOTS=2

    CLASSCODELIST="SPBFUT"

    STOPLOSS=10

    INTERVAL=10

    DAYTOFIND=30

    CANDLETOFIND=2

    NEW_GLOBAL («FIRSTRUN»,1)

    NEW_GLOBAL («FLAGSTOP»,1)

    NEW_GLOBAL («FLAGSELL»,1)

    NEW_GLOBAL («FLAGBUY»,1)

    TP=0

    N=GET_NUMBER_OF («FUTURES_CLIENT_HOLDINGS»)+0

    IF N>0

    FOR I FROM 0 TO N

    IF GET_VALUE (GET_ITEM («FUTURES_CLIENT_HOLDINGS», I), «SEC_SHORT_NAME»)=INSTRUMENT

    TP=GET_VALUE (GET_ITEM («FUTURES_CLIENT_HOLDINGS»,I), «TOTAL_NET»)+0

    END IF

    END FOR

    END IF

    насчет кода. но ведь портфель определяет SRH0. и цены, и данные котировок. сделка совершается по алгоритму, но TP остается на нуле, из-за этого программа посылает снова и снова заявки по условию, хотя не должны

    Евгений Reply:

    Попробуйте поменять «SEC_SHORT_NAME» на «SECCODE»

    KentAVP Reply:

    спасибо,проблема решена!

  15. KentAVP
    14 Январь 2010 в 15:22 | #15

    я наверное надоел вам со своими сообщениями :) ) но вот у меня вопрос. я первоначально поставил настройки для SRH0, и потом захотел поменять на SiH0. из квика удалил портфель и заново его загрузил, то есть обновленный.

    так вот для SiH0 пишет что неизвестный параметр HIGH в строке CURRENTHIGH=HIGH. очень странно вернув настройки для SRH0 все работает снова.

    с чем может быть это связано?

    Евгений Reply:

    Попробуйте SIH0 т.е. написать код инструмента ПРОПИСНЫМИ буквами.

    KentAVP Reply:

    пробовал, не помогает. самое интересное, другие контракты работают, например, GZH0, RIH0, а доллар не работет... странно...

    Евгений Reply:

    Может попробовать длинный код?

    KentAVP Reply:

    проблема решена.

    надо между заголовком и телом программы добавить:

    USE_CASE_SENSITIVE_CONSTANTS

  16. alex_davyd
    16 Февраль 2010 в 16:49 | #16

    Добрый день Евгений,пока не удалил OUTPUT=SET_VALUE (OUTPUT,"MONEYCURRENTBALANCE",MONEYCURRENTBALANCE),робот не загружался,в сообщении квик пишет"Unknown identifier MONEYCURRENTBALANCE" не может индефицировать,в коментариях подобной проблемы не нашел, не могу понять что это ,и для чего нужно в масиве

    Евгений Reply:

    MONEYCURRENTBALANCE — это предполагалось получение входящего баланса, приравняйте ее к нулю в начале программы.

  17. alex_davyd
    16 Февраль 2010 в 18:54 | #17

    появилась новая проблема,Unknown identifier DATE [ TRID=DATE&TIME],а куда и какую переменную надо вставитьнепонятно,

    Евгений Reply:

    Ну следовательно нет такой переменной как DATE, приравняйте к ней текущую дату. Учитесь решать задачи!

  18. alex_davyd
    16 Февраль 2010 в 20:42 | #18

    спасибо теперь все понятно,так я и учюсь ,пока не совсем бывает понятно условия,пыхчу ,мучаюсь, я ведь с нуля, но ведь интересно,очень позновательный у вас ресурс,

  19. alex_davyd
    16 Февраль 2010 в 21:58 | #19

    вот я и собрал, не понял как получилось ,но работает,одна маленькая подсказка и все работает,провозился целый день и все сразу стало понятно,задачки восновном на логику

  20. alex_davyd
    17 Февраль 2010 в 16:01 | #20

    Добрый день Евгений,собрал то я собрал,все работает в портфеле все отоброжается,но кагда наступает условие слелки,квик пишет"НЕ указан тип транзикации",я просмотрел все комментарии,просмотрел весь блок отправки транзикации,поменял в строке"TRANS_PARAMS = SET_VALUE (TRANS_PARAMS, «SECCODE», INSTRUMENT),INSTRUMENT на RTS-3.10,я видел у вас такой пример в описаниях функции,хотя от переменны мест слогаемых сумма не меняется,

    А с отсутсвием переменной DATE,решил задачку вот так

    '========= ДАТА И ВРЕМЯ СЕРВЕРНОЕ

    SERVERTIME=GET_INFO_PARAM («SERVERTIME»)

    SERVERDATE=GET_INFO_PARAM («TRADEDATE»)

    TIMESERV=SUBSTR (SERVERTIME,0,2)&SUBSTR (SERVERTIME,3,2)&SUBSTR (SERVERTIME,6,7)

    TIME=TIMESERV+0

    DATE=SUBSTR (SERVERDATE,6,4)&SUBSTR (SERVERDATE,3,2)&SUBSTR (SERVERDATE,0,2)

    TRID=TIME&DATE

    Евгений Reply:

    Дата — все верно.

    Есть два формата написания кода инструмента. точнее код один, но некоторые брокеры вместо когда принимают краткое название бумаги. отсюда некоторая путаница.

  21. alex_davyd
    17 Февраль 2010 в 20:57 | #21

    да я обэтом знаю и всегда меняю,уменя учебный счет в Окрытии,там принято RTS-3.10,а реал уменя атон там RIHO, я пробывл и так и так,но уменя бот все видит ,работает,подсвечивает таблицу, все параметры отраженны в портфеле,но когда должна быть сделка ,квик выдает сообщение «„НЕ указан тип транзикации“, я так думаю квик не может определить bay или sell.

    вот первый блок для открытия;

    PROGRAM

    CLASSCODELIST=»SPBFUT"

    INSTRUMENT="RTS-3.10" ' ИНСТРУМЕНТ

    LOTS=1 ' ОПЕРАЦИОННОЕ КОЛИЧЕСТВО ЛОТОВ

    STOPLOSS=100 ' РАЗМЕР СТОПЛОССА В ПУНКТАХ ФОРТС

    INTERVAL=60' ТАЙМФРЕЙМ НА ГРАФИКЕ

    DAYTOFIND=30 ' СКОЛЬКО ДНЕЙ НАЗАД ИСКАТЬ СВЕЧИ

    CANDLETOFIND=2 ' НОМЕР НУЖНОГО НАМ БАРА, ПРОБОЙ ЭКСТРЕМУМОВ КОТОРОГО ЯВЛЯЕТСЯ СИГНАЛОМ К ПОКУПКЕ/ПРОДАЖЕ

    NEW_GLOBAL («FIRSTRUN»,1) ' ПЕРЕМЕННЫЕ КОТОРЫЕ ПРИГОДЯТСЯ НАМ ПОЗЖЕ

    NEW_GLOBAL («FLAGSTOP»,1)

    NEW_GLOBAL («FLAGSELL»,1)

    NEW_GLOBAL («FLAGBUY»,1)

    HIGH=0

    LOW=0

    MONEYCURRENTBALANCE=0

    TP=0 ' ОБНУЛЯЕМ СЧЕТЧИК ТЕКУЩЕЙ ПОЗИЦИИ,

  22. alex_davyd
    17 Февраль 2010 в 21:38 | #22

    я думаю проблема в нутри в этой функции FUNC ORDER (FPRICE,FLOTS,FDIRECTION,FTYPE,FTRID),где мы передаем цену, количество лотов, направление, тип заявки, и идентификационный номер транзакции,я прям по строчке просмотрел весь блок отправки транзакций,но пока не хватает знаний и опыта, я пересмортрел все ваши предыдущии статьи и нашел отличие в строчке , TRANS_PARAMS = SET_VALUE (TRANS_PARAMS, «SECCODE», INSTRUMENT)в место INSTRUMENT стоял код инсрумента,но это ж без разницы код инструмента у нас прописан в начале программы,

  23. alex_davyd
    18 Февраль 2010 в 15:03 | #23

    Добрый день Евгений,наверно функция FUNC ORDER (FPRICE,FLOTS,FDIRECTION,FTYPE,FTRID) не причем там я все что нужно все правильно прописал,квик выдает сообщение «„НЕ указан тип транзакации“,а транзакции у на это ввод заявок,снятие заявок ,итп,значит транзакции у меня проходят,толко квик не может понять направление выстовления заявки,наверное не хватает строчки вот здесь:

    TRID=TIME&DATE

    OP="« ' ЗАДАЕМ ТЕКСТОВУЮ ПЕРЕМЕННУЮ ОПЕРАЦИИ

    квик не видет,текстовую ПЕРЕМЕННУЮ,не может понять что это „B“или»S".

    Я извеняюсь за назойливость,кроме вас спросить больше не у кого,а разобратся в купайле надо я вери в будущее квика.

    Евгений Reply:

    Тип транзакции это

    TRANS_PARAMS = SET_VALUE (TRANS_PARAMS, «ACTION», «NEW_ORDER»)

    перед строкой

    IF FTYPE="STOP"

    п.с. как нибудь соберусь перепишу этого робота...

  24. alex_davyd
    18 Февраль 2010 в 17:17 | #24

    Евгений ,ситуация патовая загружаю пробойного на реал,и учебный счета, различие лиш только в коде инструмента и ACCOUNT,на реале в графе ISREALTIME значение 1,припятсвий торговать нету,а на учебном счету значение 0,до обеда точнее до14.00 ,было тоже 1.

    Евгений Reply:

    Удаляйте функцию ISREALTIME, вот ее хороший заменитель:

    '========= ПРОВЕРКА СОЕДИНЕНИЯ С СЕРВЕРОМ

    IF IS_CONNECTED ()<>1

    RETURN

    END IF

  25. alex_davyd
    19 Февраль 2010 в 00:54 | #25

    Я добовлял сегодня функцию ПРОВЕРКА СОЕДИНЕНИЯ С СЕРВЕРОМ,я ее нашел в мувинге,только я думал у нее чуть другая функция,а при удалении ISREALTIME, статус изменится он тоже=0,я через отладку посмотрел,

    Евгений Reply:

    ISREALTIME надо совсем удалить и из проверок в т.ч.

  26. alex_davyd
    19 Февраль 2010 в 13:26 | #26

    Добрый день Евгений,попробовал я удалить ISREALTIME ,не получилось,таблица пустая,квик выдоет сообщениее «MUST SELL FIRST,прошелся отладчиком RESULD показывает толко время, вернулся к функция ISREALTIME зароботала,стопы перестали выстовлятся, у меня была открытая позиция бот ее закрыл по стопу,

    может позволите я выложу код полностью и мы в месте разбирем ошибку.

    Евгений Reply:

    выкладывай.

  27. alex_davyd
    26 Февраль 2010 в 22:48 | #27

    Евгений добрый вечер,если добавить строчку

    TRANS_PARAMS = SET_VALUE (TRANS_PARAMS, «TYPE», «L»),после строки

    TRANS_PARAMS = SET_VALUE (TRANS_PARAMS, «ACTION», «NEW_ORDER»)в этом вродебы и есть моя проблема под названием «НЕ указан тип транзикации» ,квик не понимает какая завка лимитированная или рыночная ,сечас у меня до понедельника нет доступа к учебному счету,или с этой строки достаточно IF FTYPE="LIMIT"

Необходимо войти на сайт, чтобы написать комментарий.