Функция перестановки заявок в торговых роботах
В QUIK есть функционал, позволяющий посредством программы на QPILE переставить заявку, или говоря проще одним разом сделать два действия: отменить активную заявку и выставить вместо нее новую с номым количеством и/или ценой. Родная функция называется MOVE_ORDERS, и работает (в текущей версии) только на площадке ФОРТС. Но неуниверсальность этой функции по наведению (только ФОРТС) а также некоторое неудобство ее работы, а именно то, что посредством этой функции нужно менять только сразу две заявки, подтолкнули меня на создание собственной функции, обладающей большей универсальностью. Алгоритм простой: с помощью пользовательской функции «KILL ALL ORDERS», и функции постановки новой заявки, уже рассмотренных на этом сайте, мы заменяем MOVE_ORDERS:
Код на QPILE доступен только зарегистрированным пользователям.
В итоге, в результате последовательного вызова двух функций мы получаем искомое действие, отменяем активную заявку и выставляем новую с новой ценой и/или количеством. Также хочу заметить, что такая функция очень полезна при реализации торговой стратегии скальпинг.
Функцию можно скачать.
Евгений, большое спасибо за код. Знаете, по нормальному разработчики QUIK должны разрабатывать и выкладывать такие полезные функции, вместо того, чтобы давать подсказки словами на повторяющиеся вопросы.
Единственный вопрос, не лучше ли передавать INSTRUMENT аргументом функции?
Разработчикам QUIK можно сказать спасибо, хотя бы за то, что существует возможность применять торговых роботов. Согласен, что не все удобно, но «доработаем» напильником.
INSTRUMENT можно передавать и как аргумент функции. Но если робот работает с одним и тем инструментом, то на мой взгляд удобнее так. Но тут дело хозяйское
А что делает стандартная квиковская команда ?
Почему она переставляет сразу две заявки ? Хочу реализовать следящий стоп (trailing stop)...
а если не давать значение SECOND_ORDER_NUMBER, SECOND_ORDER_NEW_PRICE ?
С Уважением.
Евгений Reply:
мая 2, 2009 at 18:08
Стандартная команда тоже передвигает заявки, она работает, пользуйтесь. Просто мне удобнее в этом случае использовать свой модуль, т.к. он более функционален.
SECOND_ORDER_NUMBER и SECOND_ORDER_NEW_PRICE — обязательные переменные, попробуйте поэкспериментировать с ними.
П.С. случайно удалил оба ваших комментария с кодом — не могу найти, повторите, пожалуйста.
Здраствуйте, Евгений!
У меня вопрос, идущий в разрез с данной темой.
Возможно ли реализовать ниже приведенные индикаторы на qpile?
Positive Directional Indicator (+DI)
Negative Directional Indicator (-DI)
Если да,то не могли бы вы привести пример програмного кода для данных индикаторов.
Спасибо.
Евгений Reply:
мая 2, 2009 at 18:33
«Индикатор ADX выведен из двух других, которые также разработаны Уайлдером. Один индикатор называется Positive Directional Indicator (в большинстве случаев иногда обозначается „+DI“), второй индикатор это- Negative Directional Indicator (обозначается как „-DI“). На выбранном временном промежутке +DI- показывает силу движений вверх, а -DI наоборот показывает силу движений вниз за определенный период. Индикатор ADX показывает силу тренда и соединяет в себе +DI и -DI сглаживая затем данные скользящей средней. Так как ADX использует данные +DI и -DI не указывает направление тренда.»
Может проще использовать стандартный ADX который есть в QUIK? Если да, то почитайте статью www.hirobot.ru/2009/04/in...orgovyx-robotax/
Если нет — пишите, будем разбираться.
Антон611 Reply:
мая 4, 2009 at 10:42
Спасибо за ответ.
Использование этих индикаторов совместно с ADX показало довольно неплохие результаты в MetaTrader 4.Решил попробовать их написать для Quik.Нашел формулы для расчетов:lenivets-trader.ru/adx.
Но возникли трудности вот с этим:
+DIi = EMAi (+SDI, N)
-DIi = EMAi (-SDI, N)
Не знаю как это реализовать в программном коде.
Заранее спасибо.
Евгений Reply:
мая 4, 2009 at 11:25
По данной Вами ссылке все написано, как получается SDI, EMA мы знаем как получить. Сопоставляйте данные из формулы и такие же данные из QUIK. Пишите формулу обычными слова, что откуда берем — потом напишем код.
Функция LowestLow за NUMBER свечек:
FUNC LOWESTLOW (NUMBER) ' НАША ФУНКЦИЯ
M=0 ' СЧЕТЧИК НАЙДЕННЫХ ЗНАЧЕНИЙ
LOWEST=99999999999
CURYEAR=GET_VALUE (GET_DATETIME (), «YEAR») ' ПОЛУЧАЕМ ЗНАЧЕНИЯ ГОДА, МЕСЯЦА, ДНЯ И Т.Д.
CURMONTH=GET_VALUE (GET_DATETIME (), «MONTH»)
CURDAY=GET_VALUE (GET_DATETIME (), «DAY»)
CURHOUR = GET_VALUE (GET_DATETIME (), «HOUR»)
CURMIN = GET_VALUE (GET_DATETIME (), «MIN»)
CURMIN = INTERVAL*FLOOR (CURMIN/INTERVAL) ' ОКРУГЛЯЕМ МИНУТЫ ДО «ИНТЕРВАЛЬНЫХ»
N=(DAYTOFIND*24)*(FLOOR (60/INTERVAL)) ' ЗНАЧЕНИЕ ОКОНЧАНИЯ ЦИКЛА
FOR I FROM 1 TO N
TEXTDATA=FTEXTDATA (CURYEAR,CURMONTH,CURDAY) &"" ' ВЫЗЫВАЕМ ФУНКЦИИ
TEXTTIME=FTEXTTIME (CURHOUR,CURMIN) & ""
CANDLE=GET_CANDLE (CLASSCODELIST,INSTRUMENT, "", INTERVAL & "", «PRICE», TEXTDATA, TEXTTIME)
LOW=GET_VALUE (CANDLE, «LOW»)+0
IF LOW>0 ' ЕСЛИ ЧТО-ТО НАШЛИ
M=M+1 ' СЧИТАЕМ НАЙДЕННЫЕ ДАННЫЕ СЧЕТЧИКОМ
IF M<=NUMBER
DATE=TEXTDATA ' ПРИСВАИВАЕМ ПЕРЕМЕННЫМ НАЙДЕННЫЕ ДАННЫЕ
TIME=TEXTTIME
LOW=GET_VALUE (CANDLE, «LOW»)+0
IF LOW<LOWEST
LOWEST=LOW+0
END IF
END IF
END IF
' ОТКАТ НА «ИНТЕРВАЛ» НАЗАД, ОБЯЗАТЕЛЬНО РАЗБЕРИТЕСЬ В ЭТОМ КОДЕ — ВАЖНО ДЛЯ ПОНИМАНИЯ РАБОТЫ ВСЕЙ ФУНКЦИИ!
CURMIN=CURMIN-INTERVAL
IF CURMIN<0
CURMIN=60+CURMIN
CURHOUR=CURHOUR-1
IF CURHOUR<0
CURHOUR=23
CURDAY=CURDAY-1
IF CURDAY<1
CURDAY=31
CURMONTH=CURMONTH-1
IF CURMONTH<1
CURMONTH=12
CURYEAR=CURYEAR-1
IF CURYEAR<0
MESSAGE («НЕ НАЙДЕНЫ КОТИРОВКИ ДО РОЖДЕСТВА ХРИСТОВА!
»,1)
END IF
END IF
END IF
END IF
END IF
END FOR
END FUNC
Функция HighestHigh за NUMBER свечек:
FUNC HIGHESTHIGH (NUMBER) ' НАША ФУНКЦИЯ
M=0 ' СЧЕТЧИК НАЙДЕННЫХ ЗНАЧЕНИЙ
HIGHEST=0
CURYEAR=GET_VALUE (GET_DATETIME (), «YEAR») ' ПОЛУЧАЕМ ЗНАЧЕНИЯ ГОДА, МЕСЯЦА, ДНЯ И Т.Д.
CURMONTH=GET_VALUE (GET_DATETIME (), «MONTH»)
CURDAY=GET_VALUE (GET_DATETIME (), «DAY»)
CURHOUR = GET_VALUE (GET_DATETIME (), «HOUR»)
CURMIN = GET_VALUE (GET_DATETIME (), «MIN»)
CURMIN = INTERVAL*FLOOR (CURMIN/INTERVAL) ' ОКРУГЛЯЕМ МИНУТЫ ДО «ИНТЕРВАЛЬНЫХ»
N=(DAYTOFIND*24)*(FLOOR (60/INTERVAL)) ' ЗНАЧЕНИЕ ОКОНЧАНИЯ ЦИКЛА
FOR I FROM 1 TO N
TEXTDATA=FTEXTDATA (CURYEAR,CURMONTH,CURDAY) &"" ' ВЫЗЫВАЕМ ФУНКЦИИ
TEXTTIME=FTEXTTIME (CURHOUR,CURMIN) & ""
CANDLE=GET_CANDLE (CLASSCODELIST,INSTRUMENT, "", INTERVAL & "", «PRICE», TEXTDATA, TEXTTIME)
HIGH=GET_VALUE (CANDLE, «HIGH»)+0
IF HIGH>0 ' ЕСЛИ ЧТО-ТО НАШЛИ
M=M+1 ' СЧИТАЕМ НАЙДЕННЫЕ ДАННЫЕ СЧЕТЧИКОМ
IF MHIGHEST
HIGHEST=HIGH+0
END IF
END IF
END IF
' ОТКАТ НА «ИНТЕРВАЛ» НАЗАД, ОБЯЗАТЕЛЬНО РАЗБЕРИТЕСЬ В ЭТОМ КОДЕ — ВАЖНО ДЛЯ ПОНИМАНИЯ РАБОТЫ ВСЕЙ ФУНКЦИИ!
CURMIN=CURMIN-INTERVAL
IF CURMIN<0
CURMIN=60+CURMIN
CURHOUR=CURHOUR-1
IF CURHOUR<0
CURHOUR=23
CURDAY=CURDAY-1
IF CURDAY<1
CURDAY=31
CURMONTH=CURMONTH-1
IF CURMONTH<1
CURMONTH=12
CURYEAR=CURYEAR-1
IF CURYEAR<0
MESSAGE («НЕ НАЙДЕНЫ КОТИРОВКИ ДО РОЖДЕСТВА ХРИСТОВА!
»,1)
END IF
END IF
END IF
END IF
END IF
END FOR
END FUNC
Евгений Reply:
мая 3, 2009 at 10:17
Отличные функции! Включаем в библиотеку! www.hirobot.ru/skachat/
Евгений Reply:
мая 3, 2009 at 10:21
Только в функции HIGHEST не правилен момент:
IF HIGH>0 ' ЕСЛИ ЧТО-ТО НАШЛИ
M=M+1 ' СЧИТАЕМ НАЙДЕННЫЕ ДАННЫЕ СЧЕТЧИКОМ
IF MHIGHEST
HIGHEST=HIGH+0
END IF
END IF
END IF
Да, действительно... Исходный код взял с этого сайта, отредактировал, но на комментарии не обращал внимания... Не отредактировал, а надо было...
Евгений Reply:
мая 4, 2009 at 11:20
Ждем исправленную версию!