Программа истории сделок(свечей) для QPILE

22 апреля, 2011

Автор: Николай Камынин

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

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

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

Мною разработана внешняя программа «NK_Candle», которая формирует в реальном времени на диске файлы с историческими данными в текстовом формате.

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

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

Настройка экспорта осуществляется как для программы технического анализа Metastock.

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

Теоретически глубина истории ограничена лишь объемом диска.

Обращение к свечам истории может осуществляться по номеру свечи.

Программа распространяется на коммерческой основе.



Программа ОБФУСКАТОРА для QPILE QUIK

21 апреля, 2011

Автор: Николай Камынин

Тот факт, что программа на  QPILE для  торгового терминала  QUIK должна быть представлена в текстовом виде, создает определенные проблемы для защиты авторских прав при ее распространении.

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

Программа, осуществляющая такое кодирование называется  ОБФУСКАТОР.

Предлагаю Вашему вниманию результат работы ОБФУСКАТОРА.

Фрагмент исходного текста программы:

‘ *****************************************************
FUNC detect_position()
table = «ORDERS»

max_index = GET_NUMBER_OF(table)
if(co_index > max_index + 1)
co_index = 1
end if

for orders_i from co_index to max_index
if( GET_VALUE(GET_ITEM(table,orders_i),»SECCODE») == SECCODE _
AND GET_VALUE(GET_ITEM(table,orders_i),»STATUS») == «FILLED» _
AND GET_VALUE(GET_ITEM(table,orders_i),»CLASSCODE») == CLASSCODE _
AND GET_VALUE(GET_ITEM(table,orders_i),»ACCOUNT») == ACCOUNT _
AND 0+GET_VALUE(GET_ITEM(table,orders_i),»NUMBER») > last_order_id )

save_needed = 1

last_order_id = 0+GET_VALUE(GET_ITEM(table,orders_i),»NUMBER»)

order_q = 0+GET_VALUE(GET_ITEM(table,orders_i),»QUANTITY»)
order_op = GET_VALUE(GET_ITEM(table,orders_i),»OPERATION»)
‘ ———————————————————————-
trade_q = 0
trade_p = 0
for trades_i from 1 to GET_NUMBER_OF(«TRADES»)
if(0+GET_VALUE(GET_ITEM(«TRADES»,trades_i),»ORDER_NUMBER») == last_order_id)
qq = 0+GET_VALUE(GET_ITEM(«TRADES»,trades_i),»QUANTITY»)
pp = 0+GET_VALUE(GET_ITEM(«TRADES»,trades_i),»PRICE»)

trade_q = trade_q + qq
trade_p = trade_p + (qq*pp)
end if
end for

if(trade_q > 0)
trade_p = trade_p / trade_q
end if
‘ ———————————————————————-
if(order_q != trade_q)
write_log(«Рассинхронизация заявок и сделок: » & last_order_id & «, » & order_q & «/» & trade_q)
last_order_id=last_order_id-1

RETURN
end if
‘ ———————————————————————-
log_action=»»
if( position == «n» )
set_position(order_op,trade_q,trade_p)
log_action=»Открытие позиции » & position & pquantity
else
if( (position == «L» AND order_op == «BUY») OR (position == «S» AND order_op == «SELL») )
log_action=»Наращивание позиции » & position & pquantity
pprice = pprice * pquantity + trade_p * trade_q
pquantity = pquantity + trade_q
pprice = pprice / pquantity
else
if(trade_q == pquantity)
log_action=»Закрытие позиции » & position & pquantity

position = «n»
pquantity = 0
else
if(trade_q < pquantity)
log_action=»Уменьшение позиции » & position & pquantity
pquantity = pquantity — order_q
else
log_action=»Переворот позиции » & position & pquantity
set_position(order_op,trade_q-pquantity,trade_p)
end if
end if
end if
end if

write_log(log_action & «: » & last_order_id & «, » & order_op & » » & order_q & «*» & FLOOR(trade_p*10)/10)

if(STOP_ORDER_MGR == 1)
check_stop_order()
end if
co_index = orders_i
‘ ———————————————————————-
end if
end for
END FUNC
‘ ***************************************************
‘ *                              MAIN PROGRAMM                               *
‘ ***************************************************
DELETE_ALL_ITEMS()
DELETE_ALL_LABELS(GRAPH_TAG)
‘ ***************************************************
get_qdata()
‘ проверим, все ли нужные данные считались из терминала
data_error=0
if(ltime == 0)
data_error = data_error + 1
end if
if(qcap == -1)
data_error = data_error + 2
end if
if(data_error > 0)
output=set_value(output,»A»,»Ожидание»)
add_item(outp_i,output)
output=set_value(output,»A»,»данных… [» & data_error & «]»)
add_item(outp_i,output)
RETURN
end if

if(qcap == 0)
output=set_value(output,»A»,»Ошибка»)
add_item(outp_i,output)
output=set_value(output,»A»,»определения»)
add_item(outp_i,output)
output=set_value(output,»A»,»рабочего»)
add_item(outp_i,output)
output=set_value(output,»A»,»капитала.»)
add_item(outp_i,output)
RETURN
end if
‘ ****************************************************
if(initialized == 0)
if(get_file_len(DATAFILE) == -1)
save_needed = 1
write_log(«Создание файла данных » & DATAFILE)
end if

initialized = 1
init_level_settings()
co_index = GET_NUMBER_OF(«ORDERS») + 1
write_log(«Инициализация: » & SECCODE & «.» & CLASSCODE & » » & co_index)
end if
‘ ***************************************************
if(save_needed == 0)
load_data()
else
save_data()
end if
‘ ***************************************************
detect_position()
get_bar(ldate,ltime)
‘ ***************************************************
if(position == «n»)
if(CALC1_SIZE>0)
exec_calc(CALC1_SIZE,PLOT_CALC1)
end if

if(CALC2_SIZE>0)
exec_calc(CALC2_SIZE,PLOT_CALC2)
end if

if(CALC_SATO>0)
exec_sato()
end if
else
position_calc()
end if
‘ ***************************************************
END_PROGRAM

Данный фрагмент после ОБФУСКАТОРА:

FUNC _17615()
_11352=»ORDERS»
_10735=GET_NUMBER_OF(_11352)
IF(_13740 > _10735+1)
_13740=1
END IF
FOR _15713 FROM _13740 TO _10735
IF(GET_VALUE(GET_ITEM(_11352,_15713),»_14815″)==_14815 AND GET_VALUE(GET_ITEM(_11352,_15713),»STATUS»)==»FILLED»AND GET_VALUE(GET_ITEM(_11352,_15713),»_19441″)==_19441 AND GET_VALUE(GET_ITEM(_11352,_15713),»_12233″)==_12233 AND 0+GET_VALUE(GET_ITEM(_11352,_15713),»NUMBER»)> _11644)
_12176=1
_11644=0+GET_VALUE(GET_ITEM(_11352,_15713),»NUMBER»)
_15951=0+GET_VALUE(GET_ITEM(_11352,_15713),»_18947″)
_15433=GET_VALUE(GET_ITEM(_11352,_15713),»OPERATION»)
_10311=0
_19544=0
FOR _16652 FROM 1 TO GET_NUMBER_OF(«TRADES»)
IF(0+GET_VALUE(GET_ITEM(«TRADES»,_16652),»ORDER_NUMBER»)==_11644)
_19097=0+GET_VALUE(GET_ITEM(«TRADES»,_16652),»_18947″)
_16416=0+GET_VALUE(GET_ITEM(«TRADES»,_16652),»PRICE»)
_10311=_10311+_19097
_19544=_19544+(_19097*_16416)
END IF
END FOR
IF(_10311 > 0)
_19544=_19544/_10311
END IF
IF(_15951 !=_10311)
_12896(«РАССИНХРОНИЗАЦИЯ ЗАЯВОК И СДЕЛОК:»&_11644&»,»&_15951&»/»&_10311)
_11644=_11644-1
RETURN
END IF
_11294=»»
IF(_13275==»N»)
_15519(_15433,_10311,_19544)
_11294=»ОТКРЫТИЕ ПОЗИЦИИ»&_13275&_18661
ELSE
IF((_13275==»L»AND _15433==»BUY»)OR(_13275==»S»AND _15433==»SELL»))
_11294=»НАРАЩИВАНИЕ ПОЗИЦИИ»&_13275&_18661
_13346=_13346*_18661+_19544*_10311
_18661=_18661+_10311
_13346=_13346/_18661
ELSE
IF(_10311==_18661)
_11294=»ЗАКРЫТИЕ ПОЗИЦИИ»&_13275&_18661
_13275=»N»
_18661=0
ELSE
IF(_10311 < _18661)
_11294=»УМЕНЬШЕНИЕ ПОЗИЦИИ»&_13275&_18661
_18661=_18661-_15951
ELSE
_11294=»ПЕРЕВОРОТ ПОЗИЦИИ»&_13275&_18661
_15519(_15433,_10311-_18661,_19544)
END IF
END IF
END IF
END IF
_12896(_11294&»:»&_11644&»,»&_15433&» «&_15951&»*»&FLOOR(_19544*10)/10)
IF(_10340==1)
_18034()
END IF
_13740=_15713
END IF
END FOR
END FUNC
DELETE_ALL_ITEMS()
DELETE_ALL_LABELS(_16060)
_10208()
_16373=0
IF(_15520==0)
_16373=_16373+1
END IF
IF(_19072==-1)
_16373=_16373+2
END IF
IF(_16373 > 0)
_14560=SET_VALUE(_14560,»A»,»ОЖИДАНИЕ»)
ADD_ITEM(_17645,_14560)
_14560=SET_VALUE(_14560,»A»,»ДАННЫХ… [«&_16373&»]»)
ADD_ITEM(_17645,_14560)
RETURN
END IF
IF(_19072==0)
_14560=SET_VALUE(_14560,»A»,»ОШИБКА»)
ADD_ITEM(_17645,_14560)
_14560=SET_VALUE(_14560,»A»,»ОПРЕДЕЛЕНИЯ»)
ADD_ITEM(_17645,_14560)
_14560=SET_VALUE(_14560,»A»,»РАБОЧЕГО»)
ADD_ITEM(_17645,_14560)
_14560=SET_VALUE(_14560,»A»,»КАПИТАЛА.»)
ADD_ITEM(_17645,_14560)
RETURN
END IF
IF(_10180==0)
IF(GET_FILE_LEN(_10529)==-1)
_12176=1
_12896(«СОЗДАНИЕ ФАЙЛА ДАННЫХ»&_10529)
END IF
_10180=1
_14006()
_13740=GET_NUMBER_OF(«ORDERS»)+1
_12896(«ИНИЦИАЛИЗАЦИЯ:»&_14815&».»&_19441&» «&_13740)
END IF
IF(_12176==0)
_17674()
ELSE
_17331()
END IF
_17615()
_10206(_19835,_15520)
IF(_13275==»N»)
IF(_10864>0)
_14614(_10864,_10146)
END IF
IF(_15337>0)
_14614(_15337,_13504)
END IF
IF(_17235>0)
_15263()
END IF
ELSE
_12332()
END IF
END_PROGRAM

Кроме того, данная программа  выполняет сборку  портфеля

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

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

убирает комментарии и выявляет обращение к функциям,

описание которых отсутствует в библиотеках.

Программа распространяется на коммерческой основе.