Как известно, торговый терминал QUIK имеет встроенный интерпретатор  программ , написанных на языке программирования QPILE

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

Кроме того, если Вас устраивает время реакции робота на событие на рынке в пределах 0.5-5 секунд, то QPILE – может обеспечить такое  решение.

Создание программ на языке QPILE имеет ряд особенностей. Учет этих особенностей позволяет не только быстро создавать и отлаживать программы, но и ускорить их дальнейшее исполнение интерпретатором.

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

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

Например, четыре пустых строки или строки комментарии, занимают столько же времени на исполнение,  как оператор цикла FOR.

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

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

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

Это означает, что если некоторой переменной ”U” Вы присвоите значение в некоторой функции func_1, то это  значение будет доступно и в других функциях, а также в основной программе.

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

Для этого заранее определите названия переменных и их функциональное назначение.

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

Макросы применяются для обеспечения наглядности и компактности исходного текста программы.

Функции применяются для сокращения размеров исполняемого кода.

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

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

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

В качестве примера написания функций для программы на QPILE рассмотрим набор функций, обеспечивающих обработку времени и даты.

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

HHMMSS – время в формате HHMMSS

HHMM – время с точность до минуты

_H – часы

_M- минуты

_S-секунды

YYYYMMDD – дата в формате YYYYMMDD

Y_ –год

M_ — месяц

D_ — дата

 

Время и дата в форматах  HHMMSS и YYYYMMDD  необходимы для обращения к свечам, получаются при чтении таблиц сделок и заявок, передаются в транзакциях.

Однако, получение торговой и текущей даты и времени, возможны в формате DD.MM.YYYY. и в формате HH:MM:SS

Поэтому, для начала, получим текущее время и дату и разделим  их на составляющие.

X= GET_VALUE(GET_DATETIME (),”DATETIME”)

D_=substr(X,0,2)

M_= substr(X,3,2)

Y_= substr(X,5,4)

_H= substr(X,11,2)

_M= substr(X,15,2)

_S= substr(X,18,2)

Дата и время в форматах, необходимых для работы с графиками запишутся в виде:

YYYYMMDD=100*(100*_Y_+M_)+D_

HHMMSS=100*(100*_H+_M)+_S

 

Теперь рассмотрим алгоритм управления временем.

Так как графики истории сделок со свечами имеют интервал , кратный минуте, то рекомендую ввести переменную в формате HHMM

Рассмотрим алгоритм  изменения времени для выбора свечей и индикаторов с графиков

            Уменьшить время на T минут

_M=_M-T

If _M<0

_M=_M+60

H=H-1

END IF

            Увеличить время на T минут

_M=_M+T

If _M>60

_M=_M-60

_H=H+1

END IF

Время в формате HHMM=100*_H+_M

Для обеспечения наглядности программы без потери быстродействия, я оформляю алгоритмы изменения времени в виде макросов  #DEC_T и #INC_T.

            С потерей быстродействия, можно оформить их в виде функций без параметров:

 FUNC DEC_T()

_M=_M-T

If _M<0

_M=_M+60

H=H-1

END IF

END FUNC

И

FUNC INC_T()

_M=_M-T

If _M<0

_M=_M+60

H=H-1

END IF

END FUNC

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

Таким образом, если к указанным функциям  будет обращение из основной программы лишь один раз, то применение функций для наглядного оформления программы приведет к увеличению кода каждого из алгоритмов на 60% и примерно в 1.5 раза увеличит время исполнения данных фрагментов изменения времени.

 

This entry was posted on Суббота, 14 апреля, 2012 at 22:34 and is filed under QUIK и QPILE, торговые роботы (МТС). You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.

3 comments so far

Aleks
 1 

Статья супер! Я делаю все наоброт — пустые строчки, куча комментов, длинные названия…Потом смотрю как все это еле ползает! Открыли глаза.
Будьте добры, объясните подробнее, что значит оформить функцию в Qpile в виде макроса? Как это выглядит?

28 апреля, 2012 at 00:27
Aleks
 2 

Вопрос снимаю. Увидел ранее.

28 апреля, 2012 at 00:46
vAndrey
 3 

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

http://quik.ru/forum/qpile/84008/88034/
“имена переменных длинною в 30 символов сильно замедляют работу.”

Я смоделировал на Qpile с целью оценить величину этого замедления:

PORTFOLIO_EX NameTime;
DESCRIPTION NameTime;
CLIENTS_LIST ALL_CLIENTS;
FIRMS_LIST ALL_FIRMS;
USE_CASE_SENSITIVE_CONSTANTS;

PROGRAM
NEW_GLOBAL(«RunCount», 0)
RunCount=RunCount+1 ‘счетчик итераций портфеля
S=0 ‘короткое имя переменной, 1 символ
Nu_Ochen_Dlinnoe_Imya_Peremennoy=0 ‘длинное имя переменной, 32 символа
SEC1=GET_VALUE(GET_DATETIME(),»SEC»)&».»&GET_VALUE(GET_DATETIME(),»MILLISEC»)+0

FOR I FROM 1 TO 100000
S=S+1
END FOR

SEC2=GET_VALUE(GET_DATETIME(),»SEC»)&».»&GET_VALUE(GET_DATETIME(),»MILLISEC»)+0

FOR I FROM 1 TO 100000
Nu_Ochen_Dlinnoe_Imya_Peremennoy=Nu_Ochen_Dlinnoe_Imya_Peremennoy+1
END FOR

SEC3=GET_VALUE(GET_DATETIME(),»SEC»)&».»&GET_VALUE(GET_DATETIME(),»MILLISEC»)+0

‘учитываем цикличность секунд
IF SEC2<SEC1
SEC2=SEC2+60
END IF

IF SEC3<SEC2
SEC3=SEC3+60
END IF

'NN Короткое, длинное
WRITELN("NameTime.txt", RunCount&" "&(SEC2-SEC1)&", "&(SEC3-SEC2)&" секунд")

OUTPUT=CREATE_MAP()
OUTPUT=SET_VALUE(OUTPUT,"RunCount", RunCount)
DELETE_ALL_ITEMS()
ADD_ITEM(1,OUTPUT)
END_PROGRAM

PARAMETER RunCount;
PARAMETER_TITLE RunCount;
PARAMETER_DESCRIPTION RunCount;
PARAMETER_TYPE NUMERIC(10,0);
END

END_PORTFOLIO_EX

В файл NameTime.txt в течении 10 итераций портфеля выводилось время выполнения циклов в секундах с миллисекундами:
1 11.965, 12.136
2 11.905, 12.176
3 11.917, 12.184
4 11.946, 12.152
5 11.919, 12.155
6 11.941, 12.499
7 11.538, 13.002
8 11.211, 11.994
9 12.803, 11.315
10 11.99, 12.231
или 11.91, 12.18 среднеарифметическое за 10 итераций портфеля.

Учитывая, что среднеарифметическое за 10 итераций время выполнения пустого цикла FOR I FROM 1 TO 100000…END FOR составляет 8.83 секунды, то длинное имя переменной обрабатывается в (12.18-8.83)/(11.91-8.83)=3.35/3.08=1.088 раз или на 9% медленнее, что в критичных по быстродействию фрагментах кода может иметь значение.

5 мая, 2012 at 11:23