FAQ

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

  1. Saboteur
    7 Апрель 2010 в 17:20 | #1

    В статье про тестирование робота на исторических данных Вы писали:

    Итак, мы получили нужные нам данные, теперь приступим к модификации робота, например нашего «Торговый робот пробойный». Во первых нам нужно в самом начале, в первой части переменной PRICE присвоить значение из полученного нами файла с данными. Это делается с помощью функции READ_LINE:

    Если НЕЛЬЗЯ ;) подскажите как? Если все таки можно где про это почитать? Огромное Спасибо за то что тратите время на нас!

    Евгений Reply:

    Привет.

    В смысле «нельзя»?

    Например, у нас есть файл с историческими данными такого формата:

    time;last

    ...

    time;last

    Т.е. время и цена на момент времени, т.е. «тики». с помощью определенной функции узнаем количество строк в этом файле, делаем цикл от 1 до полученного числа. С помощью функции READ_LINE читаем в цикле каждую строку, и опять с помощью цикла разбираем полученную строку на символы. Делаем проверку если символ<>«;»то этот символ соединяем с предыдущим — это у нас будет «время». Как только встречается символ «;» то каждый последующий соединяем в отдельную переменную — это будет цена, до тех поб пока не получаем «пробел» вместо символа — это конец строки из файла. Приводим последнюю в цифровой вид (+0) и в итоге у нас две переменные: время и цена. Для «ПРобойного» этого конечно маловато, т.к. из этих цен нужно формировать бары. но ведь с того же финама можно скачать конкретный таймфрейм с полным OHLC и делать уже не две а пять переменных: время и OHLC.

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

    Вот как то так.

  2. alex_davyd
    7 Апрель 2010 в 20:15 | #2

    Привет,Евгений а по ТР можно по подробне,завели глобальную переменную ТР=0,обнуляем IF TP=0 AND STOPORDERCOUNT=0 ,а вот как присваивать значение текущей позиции не понятно.

    Евгений Reply:

    присваивать:

    ТР=1

    Все, присвоили значение равное единице. И если эта переменная определена как глобальная — значит с каждой итерацией она сохраняет последнее значение.

    IF TP=0 AND STOPORDERCOUNT=0 — это не обнуление!! Это условие.

    ТР=0 — вот обнуление.

    Если далее развивать тему вышеописанного алгоритма по тесту на исторических данных — то если по условиям логики у нас должен быть лонг, мы ТР присваиваем единицу и сразу пишем в файл запись о покупке. если шорт то ТР=-1 и также запись. Потом в экселе. например, загружаем полученный файл и считаем результат. Или де сразу в роботе считаем результат и выводим его в таблицу.

  3. alex_davyd
    7 Апрель 2010 в 20:32 | #3

    теперь понятно, при реал тесте анологично

  4. alegnom
    12 Апрель 2010 в 18:51 | #4

    Здраствуйте.

    Столкнулся с такой проблемой. При получении цены последней сделки:

    PRICE=GET_VALUE (GET_PARAM_EX («SPBFUT»,INSTRUMENT,"LAST"),"PARAM_VALUE")+0

    Программа всегда выдаёт 0. Хотя буквально неделю назад точно эта же программа выдавала правильное значение цены. Значения скользящих средних, фракталов и т.д. всё выдаёт правильно, а цену не могу получить. С чем это может быть связана? Всё уже вроде посмотрел((

    Спасибо.

    Евгений Reply:

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

  5. Rem
    16 Апрель 2010 в 17:08 | #5

    Привет, Евгений!

    Не пойму, что могло случиться: функция READ_LINE не работает. Робот пишет unexpected ошибку.

    Загрузил из справки QUIK пример:

    WRITELN («new.log»,"Hello, world")

    msg=READ_LINE («new.log», GET_FILE_LEN («new.log»), 0))

    MESSAGE (msg,1)

    — та же история.

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

    Rem Reply:

    Связался с техподдержками своего брокера, компании QUIK. В ответ на этот вопрос — тишина.

    Методом тыка все-таки сумел найти какое изменение разработчики внесли в эту функцию, но не внесли его в справку QUIK:

    Вот код из справки QUIK:

    WRITELN («new.log»,"Hello, world")

    msg = READ_LINE («new.log», GET_FILE_LEN («new.log»), error))

    MESSAGE (msg,1)

    Понятно, что вместо error записываем 0.

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

    WRITELN («new.log»,"Hello, world")

    msg= READ_LINE («new.log», GET_FILE_LEN («new.log»), 0)

    MESSAGE (msg,1)

    Вот из-за этой закрывающей скобки — этого своего тихого «усовершенствования» в недавнем обновлении версии QUIK робот не работал несколько дней.

    Евгений Reply:

    Думаю что вместо нуля, надо в функцию прописать заранее объявленную переменную:

    ERROR=0

    WRITELN ("new.log","Hello, world")

    msg=READ_LINE ("new.log", GET_FILE_LEN ("new.log"), ERROR))

    MESSAGE (msg,1)

    MESSAGE (ERROR,1) ' РЕЗУЛЬТАТ ВЫПОЛНЕНИЯ ФУНКЦИИ, ЕСЛИ НОЛЬ - УСПЕШНО.

  6. Rem
    21 Апрель 2010 в 08:00 | #6

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

    Необходимо в нужные моменты выключать робот. Сделать это можно убрав галочку из -> доступные портфели. Если нужно отключить не весь робот, а например, только функцию выставления заявки, то можно в коде задать соответствующее условие, параметры которого будут изменяться в текстовом файле (в текстовый файл вручную записываешь ВЫКЛ. и читаешь это с помощью READ_LINE).

    Но это неудобно, неоперативно, некрасиво и неэлегантно ))

    Вопрос следующий: можно ли в выпадающий список моей таблицы добавить какую-либо активную строчку (ведь во встроенных таблицах QUIK наименование таких строчек вариьируется). Если нет, то может, здесь нужен какой-то привод?

    Евгений Reply:

    ЭЭЭээээ... А правой кнопкой по таблице робота и «Приостановить работу» не устраивает?

    Rem Reply:

    Это крайний вариант, когда пожар бушует...

    Но элегантным было бы отключить только одну из частей робота... :)

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

    Если чего посоветуете, думаю всем будет полезно.

    Евгений Reply:

    Тогда думаю надо на AutoIT написать небольшую прогу, которая создает текстовый файл, в котором пишет построчно кол-во лотов, и вкл/выкл, ну и еще какие то параметры. а робот уже предложенным вами способом читает этот файл и соответствующим образом действует. Но проще сразу писать в файл руками :)

  7. alex_davyd
    22 Май 2010 в 14:38 | #7

    Здравствуйте, Евгений! помогите разобратся написл робота: вход по пробитию экстримума, выход по тэйкпрофиту,ограничения убытка по стопу,

    не могу добится чтобы робот не отпровлял заявки на вход пока не исполнется тэйк или стоп,надо как в Black Hole пока неисполнется тэйк или стоп бот не производит расчет

    Евгений Reply:

    Отправляйте заявки только тогда, когда нет активных заявок и/или стопов, в зависимости от стратегии! Посмотрите, в БХ именно так и сделано.

  8. alex_davyd
    24 Май 2010 в 02:11 | #8

    Срасибо за помощь,я правильно понял:

    IF TP=0 AND ORDERCOUNT=0 AND STOPORDERCOUNT=0

    Евгений Reply:

    Да.

  9. alex_davyd
    24 Май 2010 в 19:26 | #9

    Здравствуйте, Евгений!помогите с решением, при определения уровня пробоя я приравневаю уровень к CURRENT,пример по хаю

    IF CURRENTHIGH>HIGH

    HIGH=CURRENTHIGH

    но придостижении тейка,если цена продолжает движение вверх,выстовляется новая заявка на покупку,если приронять так CURRENTHIGH=HIGH,то при откате назад новая заявка на покупку,а надо чтобы привыполнении тэйка или стопа уровень пробития определялся уже на следущем баре

  10. Евгений
    24 Май 2010 в 19:30 | #10

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

  11. alex_davyd
    24 Май 2010 в 20:42 | #11

    вот здесь мой мозг и закипел,

    IF TP=0 AND ORDERCOUNT=0 AND STOPORDERCOUNT=0 AND NUMBER=2

    Евгений Reply:

    А причем тут номер бара? Вы же его задаете в начале программы, в переменных.

  12. alex_davyd
    24 Май 2010 в 21:09 | #12

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

    Евгений Reply:

    Заведите две переменные под OHLC:

    HIGH

    HIGH_PREV

    т.е. текущий хая и предыдущий. Если вновь получаемый хай не равен предыдущему и одновременно не равен нулю — то факт рождения новой свечи. Теже операции нужно провести и с остальными составляющими OHLC для гарантии. ну и соответственно каждую итерацию программы приравнивать:

    HIGH_PREV=HIGH

    после вышеописанного анализа.

  13. alex_davyd
    24 Май 2010 в 21:22 | #13

    Спасибо, сам не сделал бы очень долго.

    alex_davyd Reply:

    сделал вот так:

    '========= ПОЛУЧАЕМ ДАННЫЕ СВЕЧЕЙ

    OHLC (1)

    HIGH_PREV=HIGH

    LOW_PREV=LOW

    OHLC (NUMBER)

    IF HIGH_PREVHIGH AND HIGH_PREVHIGH0

    HIGH_PREV=HIGH

    END IF

    IF LOW_PREVLOW AND LOW_PREV0

    LOW_PREV=LOW

    END IF

    не работает,CURRENT удалил

    alex_davyd Reply:

    знак неравенство не отобразился

    Евгений Reply:

    Я же написал как сделать! Не выдумывайте.

    alex_davyd Reply:

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

    завел переменные, обнулил,прировнял ,вот так я понял:

    HIGH=0

    HIGH_PREV=0

    OHLC (NUMBER)

    HIGH_PREV=HIGH

    Евгений Reply:

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

    HIGH=0

    NEW_GLOBAL («HIGH_PREV»,0)

    OHLC (NUMBER)

    IF HIGH<>HIGH_PREV AND HIGH_PREV<>0

    ' НОВАЯ СВЕЧА

    END IF

    HIGH_PREV=HIGH

  14. Rem
    30 Июнь 2010 в 11:36 | #14

    Привет, Евгений!

    Что лучше: передвигать заявку, опасаясь превышения лимита по количеству заявок за сессию или продать (купить) по рынку в тот момент, когда bid (offer) достигает заданного уровня?

    Евгений Reply:

    Привет!

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

    Но я сам, в своих роботах как правило отслеживаю бид/оффер, чтоб маркетом открыть\закрыть позицию. Минус — если этот момент попадет на сильное движение — будет проскальзывание.

    Если вы планируете использовать арбитражную стратегию, то там, конечно, надо использовать лимиты на одном инструменте пары. Как вариант рассмотрите вариант увеличения периода расчета портфеля, например при 1 итерации в 10 сек кол-ва бесплатных заявок может хватить на 5-6 часов торгов.

    Rem Reply:

    Спасибо за ответ.

    Думаю, что маркет удобнее, тем более, что можно последить роботом не только за лучшими ценами в стакане (отдельный респект за трепанацию стакана).

    Насчет арбитражных стратегий не понял: какая разница, если спрэд считать не по ценам закрытия, а также по бидам и офферам.

    Евгений Reply:

    В арбитраже по первой бумаге в паре лучше входить лимитом. Это так. к слову :)

  15. snowkam
    6 Июль 2010 в 09:10 | #15

    Добрый день!

    Евгений, а у вас случайно нет скрипта на qpile для отображения котировок.

    Например есть крафик ГАЗПРОМА и чтобы по нему выводить таблицу в виде

    data time open close high low volume

    Или я ошибаюсь может в Квике есть такая возможность?

    Смысл такой хотелось бы эту табличку выводить по DDE в Эксель.

    Евгений Reply:

    Привет.

    Посмотрите тему — www.hirobot.ru/2010/04/ka...grafika-2-chast/

  16. snowkam
    7 Июль 2010 в 09:21 | #16

    Спасибо за предыдущий ответ почти то что нужно!

    А вот еще один вопрос а возможно ли сделать скрипт но чтобы он отрабатывался по команде внешей программы.

    Ну например есть скрипт№1 в нем установлено RETURN= false

    и имеется текстовый файл где находится значение переменной false или true.

    Если в текстовеке false скрипт нечего не делает если true значит скрипт отработался.

    Евгений Reply:

    Конечно можно! У QPILE есть функции записи и чтения из файла, а также обработки этих данных. Почитайте сайт, есть такая публикация www.hirobot.ru/2009/05/kak-sozdavat-log/ и www.hirobot.ru/2009/05/ka...x-dannyx-v-quik/ в них описано как пользоваться этими функциями.

  17. alex_davyd
    20 Июль 2010 в 14:31 | #17

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

    Евгений Reply:

    Привет.

    Как я понял у вас при открытой позиции две активных стопзаявки, одна «стоплосс» вторая «тейкпрофит». И при исполнении одной из них надо чтоб вторая снималась. Решение: при отсутствии открытых позиций и кол-ве активных стопов>0 — удаляйте все стопы.

  18. alex_davyd
    20 Июль 2010 в 19:00 | #18

    Привет уменя сечас реалезованно имено это решение , я использываю именно квиковский текпрофит,TRANS_PARAMS = SET_VALUE (TRANS_PARAMS, «STOP_ORDER_KIND», «TAKE_PROFIT_STOP_ORDER»),хотелось чтоб после активации цены тейка , стоп лимит снимался,и остовался один тейк

    Евгений Reply:

    Отслеживайте в таблице «стопзаявки» свойства этого «тейкпрофита» и при соответствующем изменении снимайте второй стоплимит.

  19. Rem
    2 Август 2010 в 14:18 | #19

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

    Глобальная переменная при рестарте или запуске портфеля (например, с утра) принимает значение, заданное в начальных установках портфеля.

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

    Евгений Reply:

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

    Rem Reply:

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

    Евгений, а где вообще хранятся значения глобальных переменных: на моей машине или где-то на сервере?

    Евгений Reply:

    Привет.

    Значения глобальных переменных хранятся локально. Если вас не устраивает вариант с файлом (хотя на мой взгляд капля в море), не выключайте компьютер и не закрывайте QUIK, в таком случае глобальная переменная сохранит свое значение.

    4 тысячи строк — это много...

  20. Сергей
    1 Сентябрь 2010 в 12:02 | #20

    День добрый!

    Убился, не могу выцепить цену последней сделки по определенному инструменту. Логика такая:

    N=GET_NUMBER_OF («TRADES»)

    IF N>0

    FOR I FROM 0 TO N

    IF (GET_VALUE (GET_ITEM («TRADES», C), «SECCODE»)=INSTRUMENT) AND (GET_VALUE (GET_ITEM («TRADES», C), «TRDACCID»)=ACCOUNT)

    PRICEEND=GET_VALUE (GET_ITEM («TRADES», C),"PRICE")+0 ' ПОЛУЧАЕМ ЦЕНУ КРАЙНЕЙ СДЕЛКИ

    END IF

    END FOR

    END IF

    Чую, где-то не прав и ничего тут нет сложного, но заклинило.

    Помогите, плиз.

    Сергей Reply:

    Прошу прощения, вот так, конечно.

    Но сути это не меняет

    N=GET_NUMBER_OF («TRADES»)

    IF N>0

    FOR I FROM 0 TO N

    IF (GET_VALUE (GET_ITEM («TRADES», I), «SECCODE»)=INSTRUMENT) AND (GET_VALUE (GET_ITEM («TRADES», I), «TRDACCID»)=ACCOUNT)

    PRICEEND=GET_VALUE (GET_ITEM («TRADES», I),"PRICE")+0 ' ПОЛУЧАЕМ ЦЕНУ КРАЙНЕЙ СДЕЛКИ

    END IF

    END FOR

    END IF

    Сергей Reply:

    Нашел проблему.

    Называется для бестолковых — если что-то не работает, читай первоисточник, т.е. справку по алгоритмическому языку.

    Короче — номер торгового счета в таблице сделок функция GET_ITEM возвращает параметром ACCOUNT.

    Может пригодится кому.

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