Главная > Торговый робот > Как получить котировки из графика QUIK

Как получить котировки из графика QUIK

29 марта 2009

quoteslogo1Как я обещал в «Плане публикаций», в этой статье мы рассмотрим аспекты получения котировок из графика в QUIK. Для начала прочитаем статью на сайте «Фондовые рынки». Также как и Автор той статьи, я придерживаюсь мнения, что QUIK в чистом виде не удобен для получения котировок, и очень надеюсь, что в будущем разработчики QUIK введут в оборот функции прямого получения котировок, как в большинстве программ теханализа, например HIGH (10), которая даст значение именно хая именно 10 бара. Ну а пока таких функций нет в нашем арсенале — пользуемся своими разработками.

Код, размещенный на сайте «Фондовые рынки» я изменил. В первоначальном виде он рисовал таблицу с перечнем OHLC, и исполнял свою функцию, т.к. и был задуман для «показательного выступления». В моем варианте он получил именно рабочую функцию выдавать OHLC именно нужного нам бара по номеру (считаем с конца, начиная с первого). Теперь эти функции можно использовать в любом роботе, которые работает с котировками, получаемыми из графиков. Думаю, что это оценит любой программист, работающий с QPILE. Указав в настраиваемых данных в начале кода INTERVAL равный нужному, и одновременно доступному в QUIK, таймфрейму и CANDLETOFIND равный номеру искомого нами бара, на выходе получим все данные бара! Не забываем указывать инструмент и код класса. Утомил наверное уже описанием — переходим непосредственно к коду:

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

А теперь домашнее задание :) попробуйте добавить в таблицу значение объема найденного бара!

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

  1. Сергей
    4 Апрель 2009 в 12:36 | #1

    если можно... делай пож. побольше комментариев

  2. Сергей
    4 Апрель 2009 в 16:22 | #2

    ждем новых уроков. на простых понятных примерах

  3. Евгений
    4 Апрель 2009 в 23:19 | #3

    Постараюсь :)

    Совет, смотрите выложенные коды по дате, я каждый момент комментирую с момента публикации, потом похожие участки комментирую выборочно. Будет более понятно.

  4. 13 Апрель 2009 в 22:58 | #4

    Классный сайт. Правда вышеописанны алгоритм у меня на QUIK 5.12 не захотел работать пока не добавил этот блок инициализации переменных:

    OPEN=0

    HIGH=0

    LOW=0

    CLOSE=0

    после PROGRAM

    P.S. Вообще занимаюсь программированием, если нужна помощь, давайте сотрудничать.

    Может создать библиотеку полезны функций QPILE ? Например:

    'Функция записи сообщений в окно сообщений и в лог-файл

    FUNC LogMessage (MessageText)

    Message (MessageText, 1)

    DateTime=GET_DATETIME ()

    tDate=SUBSTR (Get_Value (DateTime, «DateTime»), 0, 19)

    WRITELN (PathToLogFile, tDate&": "&MessageText)

    END FUNC

  5. Евгений
    14 Апрель 2009 в 09:11 | #5

    Нормально Григорий!

    Инициализацию переменных нужно было добавить сразу — просмотрел, спасибо изменю код.

    Насчет библиотеки функций — хорошая идея, сделаю.

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

  6. Alex
    20 Апрель 2009 в 14:38 | #6

    А что значат выражение &

    Евгений Reply:

    Эээээ... Криво вставилось... Поправил.

  7. Денис
    1 Июнь 2009 в 20:46 | #7

    Всем привет

    OHLC — вызывает некоторые сложности

    написал функцию расчета DI+, DI-

    к сожалению из за регулярного обращения к OHLC все явно начинает подтормаживать

    думаю при вычислении ADX комп — сдохнет

    вижу следующий выход

    создается глобал таблица в которую кидаются все нужные данные по свече — в том числе и данные индикаторов и различные расчетные показатели

    колекция — номер бара

    вложенный мап — все данные по бару

    в конечном итоге вся логика принятия решения строится на этой таблице

    при реализации столкнулся с проблемой

    вставки в глобальную коллекцию нулевого мапа когда в ней уже есть какой либо объем данных

    Женя куда кинуть код и можем ли созвониться для обсуждения

  8. Евгений
    1 Июнь 2009 в 21:55 | #8

    Идея зачот! Насчет создания коллекции из данных по графику. Но насколько это «облегчит» систему пока не берусь судить.

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

  9. Денис
    3 Июнь 2009 в 14:38 | #9

    заработало

    все собирается — не тормозит

    в ближайшее время допишу туда dx+ dx- dx adx

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

    можно будет уже реально строить логику на тех анализе

  10. Денис
    3 Июнь 2009 в 14:41 | #10

    да так же в этом решении будет возможность анализировать разные таймфрэймы по бумаге

  11. Денис
    3 Июнь 2009 в 15:20 | #11

    Женя!

    ресурс последний месяц живет как-то не активно

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

    и выкладывать какие-то базовые наработки уже для тех кто не наполняет

    в принципе это хорошая идея

    думаю это привлечет людей желающих его развивать а не ждать когда кто-то на него выложит готового робота

    Евгений Reply:

    Денис, нового не публикую — не хватает рук — работаю на заказ над большим арбитражным проектом. Основная работа + этот проект занимают все время бордствования.

    Насчет идеи по закрытому разделу — поддерживаю, если Вам не сложно — напишите правила раздела, и если есть желание предлагаю стать его ведущим и модератором. Напишите мне в «личку» мыльник свой — обсудим.

  12. pocemon
    12 Ноябрь 2009 в 21:32 | #12

    Евгений помогите найти ошибку.

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

    PORTFOLIO_EX OHLC;

    DESCRIPTION OHLC;

    CLIENTS_LIST ALL_CLIENTS;

    FIRMS_LIST ALL_FIRMS;

    PROGRAM

    YEAR=GET_VALUE (GET_DATETIME (), «YEAR»)

    MONTH=GET_VALUE (GET_DATETIME (), «MONTH»)

    DAY=GET_VALUE (GET_DATETIME (), «DAY»)

    HOUR = GET_VALUE (GET_DATETIME (), «HOUR»)

    MIN = GET_VALUE (GET_DATETIME (), «MIN»)

    DATA=YEAR&MONTH&DAY+0

    TIME=HOUR&MIN+0

    CANDLE=GET_CANDLE («SPBFUT»,"RIZ9","«,»1","PRICE",DATA,TIME)

    OPEN=GET_VALUE (CANDLE, «OPEN»)+0

    HIGH=GET_VALUE (CANDLE, «HIGH»)+0

    LOW=GET_VALUE (CANDLE, «LOW»)+0

    CLOSE=GET_VALUE (CANDLE, «CLOSE»)+0

    OUTPUT=CREATE_MAP ()

    OUTPUT=SET_VALUE (OUTPUT,"OPEN",OPEN)

    OUTPUT=SET_VALUE (OUTPUT,"HIGH",HIGH)

    OUTPUT=SET_VALUE (OUTPUT,"LOW",LOW)

    OUTPUT=SET_VALUE (OUTPUT,"CLOSE",CLOSE)

    DELETE_ALL_ITEMS ()

    ADD_ITEM (1,OUTPUT)

    END_PROGRAM

    PARAMETER OPEN;

    PARAMETER_TITLE OPEN;

    PARAMETER_DESCRIPTION OPEN;

    PARAMETER_TYPE NUMERIC (10,2);

    END

    PARAMETER HIGH;

    PARAMETER_TITLE HIGH;

    PARAMETER_DESCRIPTION HIGH;

    PARAMETER_TYPE NUMERIC (10,2);

    END

    PARAMETER LOW;

    PARAMETER_TITLE LOW;

    PARAMETER_DESCRIPTION LOW;

    PARAMETER_TYPE NUMERIC (10,2);

    END

    PARAMETER CLOSE;

    PARAMETER_TITLE CLOSE;

    PARAMETER_DESCRIPTION CLOSE;

    PARAMETER_TYPE NUMERIC (10,2);

    END

    END_PORTFOLIO_EX

    pocemon Reply:

    ура) оказывается при расчете свечных данных нахватало секунд.

    добавил

    SEK=00&0

    DATA=YEAR&MONTH&DAY+0

    TIME=HOUR&MIN&SEK+0 и все заработало.

    Евгений подскажите пожалуйста а почему при переходе с одного интервального значения на другое таблица OHLC обнуляется на 5 секунд.

    допустим если у меня минутки то между минутами 5 сек нет данных в таблице, если 5 минутки то между ними нет 5 сек данных в таблице есть только нолики везде.

  13. pocemon
    10 Декабрь 2009 в 19:45 | #13

    Евгений, а можно данную функцию улучшить, как-то чтоб она не все бары пробегала, начиная с первого, а начинала с полностью сформированного бара, т.е. 2 го. Это пожелание вызвано тестами на исторических данных , там сигналы поступают от полностью сформированных баров . Спасибо.

    Евгений Reply:

    Достаточно поставить CANDLETOFIND=2, или если вам нужно несколько баров начиная со второго — сделайте цикл «два и более»

  14. pocemon
    10 Декабрь 2009 в 20:09 | #14

    Мне надо именно данные всех свечек со второй. Цикл 2 и более для CANDLETOFIND тоже выход, но хотелось все изменения сделать внутри этой функции, не вынося из за нее. Возможно ли такое?

    Евгений Reply:

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

  15. pocemon
    10 Декабрь 2009 в 21:57 | #15

    Евгений я кажется нашел решение:

    CURMIN = (INTERVAL*FLOOR (CURMIN/INTERVAL)) -INTERVAL

    Будет ли это то, что мне надо или все-таки придется делать цикл CANDLETOFIND.

    Евгений Reply:

    Это будет работать только исключая первую свечку, а потом запрашивая вторую вы получите третью и т.д. По мне проще сделать цикл.

    pocemon Reply:

    Я сделал цикл для CANDLETOFIND — 2 и более, но сталкнулся с тем что он считает цикл не на одном прогоне т.е.1 сек (как задано в настройках портфеля)а каждый прогон прибавляет к CANDLETOFIND +1.

    Пока не могу понять в чем дело. Сама функция до модификации делала проход по свечкам внутри одного прогона ( 1 сек).

  16. gtsnab
    14 Декабрь 2009 в 22:08 | #16

    Нужна подсказка: дата меняется а значения всегда 0. За графиком слежу — открыт и масштаб нужный. И еще, если число дней назад 0 то ошибка. Вообще, мне надо получить данные всех минутных свечей «сегодня» начиная по порядку с первой. Как ни мучил GET_CANDLE ничего не выходит — нули.

    Может есть смысл пойти в обход этой функции?

    Евгений Reply:

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

  17. gtsnab
    15 Декабрь 2009 в 00:27 | #17

    Интересно, а GET_CANDLE_EX работает нормально...

    Евгений Reply:

    Это несколько расширенная функция, позволяющая получать данные массивом. Разбирайтесь с GET_CANDLE

  18. gtsnab
    15 Декабрь 2009 в 20:17 | #18

    Вот так проверяю, где ошибка? Подскажите плиз.

    CANDLE = GET_CANDLE («SPBFUT», «SIH0», "", «1», «PRICE», 20091215, 160000)

    HIGH = 0 + GET_VALUE (CANDLE, «HIGH»)

    LOW = 0 + GET_VALUE (CANDLE, «LOW»)

    Евгений Reply:

    Верно.

    При таком запросе нули выдает?

    Инструмент в список доступных входит? График по нему минутный открыт?

  19. gtsnab
    15 Декабрь 2009 в 21:20 | #19

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

  20. gtsnab
    17 Декабрь 2009 в 12:30 | #20

    Может кому пригодится: ошибка была тут SiH0. Поскольку i маленькое, в начале кода надо было добавить:

    PORTFOLIO_EX CANDLE_1712_006;

    DESCRIPTION CANDLE;

    CLIENTS_LIST ALL_CLIENTS;

    FIRMS_LIST ALL_FIRMS;

    USE_CASE_SENSITIVE_CONSTANTS — вот это

    PROGRAM

    DELETE_ALL_ITEMS ()

    CANDLE = GET_CANDLE («SPBFUT», «SiH0», "«, „1“,»PRICE", «20091216», «150000» )

    HIGH = 0 + GET_VALUE (CANDLE, «HIGH»)

    LOW = 0 + GET_VALUE (CANDLE, «LOW»)

  21. dimmi
    19 Январь 2010 в 15:39 | #21

    Евгений, подскажите пожалуйста. Реально ли получить с помощью GET_CANDLE несколько свечей. Мне к примеру нужно 20 последних свечей, а т.к. в GET_CANDLE время указано как текущее то получаются данные последней 1 свечи, а нужно данные 20 последних. Подскажите, если не трудно, как можно поэксперементировать со временем?

    Евгений Reply:

    Привет.

    Сделайте цикл от 1 до 20 и в середине цикла используйте общую функцию OHLC из этой статьи. Создайте массив и запишите в него данные по вашим 20 свечкам для последующего использования.

  22. Rem
    2 Апрель 2010 в 16:01 | #22

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

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

    Подскажите, пожалуйста, какой тут может быть выход?

    Евгений Reply:

    Если нет бара, тонет OHLC, и наверное нет даже времени и даты этого бара... сложный вопрос...

    OPEN=GET_VALUE (CANDLE, "OPEN")+0 IF OPEN>0 ' ЕСЛИ ЧТО-ТО НАШЛИ M=M+1 ' СЧИТАЕМ НАЙДЕННЫЕ ДАННЫЕ СЧЕТЧИКОМ IF M=NUMBER ' ЕСЛИ НАШЛИ ИМЕЕНО ТОТ БАР КОТОРЫЙ ИСКАЛИ DATE=TEXTDATA ' ПРИСВАИВАЕМ ПЕРЕМЕННЫМ НАЙДЕННЫЕ ДАННЫЕ TIME=TEXTTIME OPEN=GET_VALUE (CANDLE, "OPEN")+0 HIGH=GET_VALUE (CANDLE, "HIGH")+0 LOW=GET_VALUE (CANDLE, "LOW")+0 CLOSE=GET_VALUE (CANDLE, "CLOSE")+0 I=N ' ЗАКАНЧИВАЕМ ЦИКЛ ELSE т.е. если OPEN не больше нуля (равно нулю) то это потенциально может быть тот самый несуществующий "нулевой" бар в положенном месте. Надо проверить есть ли у этого "нулевого" бара верменные характеристики, для этого нам из массива данных свечи нужно получить время и дату. Для этого нужно уже использовать функцию GET_CANDLE_EX, задавать графику идентификатор и запрашивать у этой свечи ее точное время. Если оно +0 больше нуля то M=M+1 и считаем это баром но с нулевыми значениями. END IF

    Rem Reply:

    Спасибо, Евгений, за подсказку!

    Пока юзал Вашу подсказку, натолкнулся на еще один вариант решения данной проблемы (может кому пригодиться):

    1. Берем высоколиквидный инструмент, например фьючерс РТС, и получаем с помощью функции значения CLOSE для него.

    2. Там же получаем CANDLE и OHLC нужного инструмента.

    3. Преобразовываем полученные нулевые значения нашего инструмента. Например, при CLOSE=0 на каком-то баре, приравниваем его к OPEN на предыдущем баре. Если OPEN предыдущего бара равен 0, то приравниваем CLOSE к OPEN на еще раннем баре (если смотреть справа налево).

    Евгений Reply:

    Отличное и элегантное решение!

    Rem Reply:

    Спасибо, Евгений, ценю Вашу оценку! :) Но проблему на малых тайм-фреймах в вечернюю сессию всё же это не решает. Наверно, правильным было бы, если бы функция использовала данные только за период с 10-30 до 18-45 и соответственно пропускала всю вечернюю сессию. Особенно, если фьючерс идет в связке с акцией. Подскажите, пожалуйста, как задать такое условие в функции.

    Евгений Reply:

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

  23. ShvarcGarberg
    2 Апрель 2010 в 20:51 | #23

    А никого не смущает, что в каждом месяце получается 31 день?

    Евгений Reply:

    А почему это должно смущать?

    ShvarcGarberg Reply:

    Да, Евгений, щас внимательней просмотрел код, врубился. Спасибо.

    ShvarcGarberg Reply:

    Смущал тот момент, что для не существующих дней месяца (иногда это 31 число, а иногда и несколько дней в феврале), а также выходных, цикл проходит все интервалы. Для одного такого дня при минутном графике, мы получаем 24*60 = 1440 пустых интераций. Сопутствующая проблема — сдвиги, о которых написал Rem.

    Сложность вопроса я понял.

    Второй момент касается времени работы биржи, т.е. 2/3 дня мы просчитываем впустую.

    Может это можно учесть так?:

    ...

    IF CURHOUR<10

    CURHOUR = 19

    CURDAY=CURDAY-1

    ...

    Я конечно могу и ошибаться.

    Я не знаю особенностей среды исполнения QUIK,

    но возможно так будет быстрее:

    DATETIME = GET_DATETIME ()

    CURYEAR = GET_VALUE (DATETIME, "YEAR")

    CURMONTH = GET_VALUE (DATETIME, "MONTH")

    CURDAY = GET_VALUE (DATETIME, "DAY")

    CURHOUR = GET_VALUE (DATETIME, "HOUR")

    CURMIN = GET_VALUE (DATETIME, "MIN")

    Евгений Reply:

    Это все здорово, но на ФОРТС, например, сессия заканчивается в 23.50. так что вот это:

    IF CURHOUR<10

    CURHOUR = 19

    CURDAY=CURDAY-1

    уже работать не будет.

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

  24. bower90
    1 Июнь 2010 в 12:37 | #24

    Здравствуйте Евгений!!!

    Не могли бы вы подсказать?? OHLC очень удобная функция, однако у меня возникла такая проблема. Мне для робота нужно грубо говоря 4 значения. (1) Текущая цена и цена 1 интервал назад (закрытия, открытия...не важно) + (2) moving average текущее значение и moving average значение один интервал назад. с помощью OHLC мы можем получить либо 2 мувинга либо 2 цены...а как получить и то и другое в одном роботе??

    Заранее спасибо!!!!!

    Евгений Reply:

    Привет.

    1. Текущая цена берется из таблтекпараметров.

    2. OHLC (1)

    3. moving average — найдите на сайте робота Мувинг. там описано получение его данных

    4. Если мувинг простой, то можно вообще его посчитать «в ручную», т.е. задать цикл для функции OHLC, просуммировать CLOSE и поделить на нужный период мувинга.

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