Прислушался к советам, поднял старые наработки, сам поднапрягся, ( ну не все могут быть хирургами или хорошими адвокатами, а я не программист пишу потихоньку для себя).
Спрятать удалось пока только поиск начальной точки для входа в режим теста. Оказалось не все так прозаично, Изменили время начало торгов на секции срочного рынка, в виде добавления еще одной сессии "Аукцион открытия". Полезно делать ревизию старым скриптам! Соответственно изменилась индексация на графике в квике. Несколько удивил подход разработчиков?
Вот так теперь выглядит начало торгов на разных тайм фреймах:
Заглянул на сайт ММВБ, а у них вообще значится "Аукцион открытия" 08:50.
Про свою реализацию, сделал через замыкание. запихнув все интервалы готовые. и что б потом можно добавить свои. На вход подаем дату и время желаемого начала теста, на выходе массив необходимых индексов все банально.
да так примерно и реализовывал вот пример со старого скрипта
if newREJIM then Log:trace( ' =========================' ) Log:trace( 'REJIM: '..REJIM..'; (TEST='..tostring(TEST)..'; AVTO='..tostring(AVTO)..'; EXPERT='..tostring(EXPERT)..')');--..tostring(a) Log:trace( ' =========================' )
if TEST then--REJIM==' Log:trace( 'REJIM: '..REJIM..'; Синхронизация');
---- local i,d,t,hour='0','0',0; ---- Дневной do local countD=getNumCandles(tag[4]); countD = countD - test.count_day; local bar = getCandlesByIndex(tag[4],0,countD-1,1) local td = bar[0] and bar[0].datetime or nil; if td then d=get_date(td); t=get_time(td); end; Index[4]=countD; dd=d; Log:info('Синхронизация Дня: '..d..'=='..dd..'; Index[4]='..Index[4] ); end ---- Часовой - средне срочный для установления тренда на день. local countH=getNumCandles(tag[3]); for i=countH,1,-1 do local bar = getCandlesByIndex(tag[3],0,i-1,1)[0] local td = bar and bar.datetime or nil;
и так далее ...
В начале этот код и хотел перетащить и вставить в новый скрипт. Там я проходил по 4 тайм фреймам , но какое то нагромождение, в общем ревизию не прошел.
Вот я и подумал возможно есть наработки более удобные, ну к примеру двигать через интервалы ведь известно же INTERVAL_D1 == 1440 минут INTERVAL_H1 == 60 минут или через метку там время возвращается.
из Руководство пользователя QLua Версия 10.3: Свечки графика. Описание параметров свечки графика:
Параметр Тип Описание open NUMBER Цена открытия close NUMBER Цена закрытия high NUMBER Максимальная цена сделки low NUMBER Минимальная цена сделки volume NUMBER Объем последней сделки datetime TABLE Формат даты и времени doesExist NUMBER Признак расчета индикатора при наличии свечки. Возможные значения: «0» – индикатор не рассчитан; «1» – индикатор рассчитан
Вопрос, а где тут индекс? Ну зато появляется массив - datetime TABLE Формат даты и времени.
Вот она наконец удача, знаем дату, знаем время (до миллисекунд) можно вернуть интересующею нас нас цену на конкретном баре!
Backtesting - проверка торговых стратегий на исторических (прошлых) данных.
Задача сводится к определению параметров устойчивости стратеги, на разных инструментах, при разных рыночных условиях. И предположению, что будет какое то время, оставаться такой же надежной и в будущем.
Казалось бы, простая реализация задачи сводится: загрузил данные, в цикле прокатился по ним с выполнением правил торговой стратегии. Сохранил результаты сделок, расчитал показатели данной стратегии. Сравнил. При необходимости оптимизировал.
Но каждый раз при реализации задачи на тыкаюсь на одну и туже проблему. Это синхронизация графиков разных таймфремов (система нескольких окон)!
Ну это когда младший график двигается в промежуток времени старшего таймфрема и совместно сдвигаются.
Каждый раз "леплю очередной огород". Возможно есть готовое решение, или идеи по реализации в виде модуля?
Данная ошибка может возникать в случае, если метка создается "пустой", то есть в метке отсутствует текст или путь к изображению. Проверьте, пожалуйста, не меняли ли скрипт? Если ошибка до сих пор сохраняется, то просьба прислать архив с копией рабочего места QUIK без ключей на нашу почту quiksupport@arqatech.com . Перед созданием копии, закройте рабочее место QUIK и подождите несколько секунд.
Почему важно. Встраиваю в проект Backtesting, я им раньше пользовался, по сути перенес функции из старых наработок, изменений минимально и тут началось. Упала визуализация.
В квике 2 варианта визуализации. 1) На открывать графики, наставить индикаторы и получать их скриптом. Сильно зависит от количества графиков и пропускной способности канала. Отказался. 2) Алгоритмически считать индикаторы скриптом и пользоваться сервисом вывода меток на график. Даже удивил (если не считать данную ошибку). Потребление памяти не изменилось это все те же 500кб. Быстродействие отстоял сессию с замедление 1мс. т.е. скрипт отлично чистится не каких протеканий. Правда, лог не смог открыть из за его объема блокнотом (Гб).
local tag={} sec = { 'NGQ3', 'EDU3', -- 9.6 p; ГО 6598; 'RMU3', -- RTSM-9.23 Индекс РТС (мини) Расчетный фьючерс на RTSI. Стоимость пункта цены 18,46 p; ГО 3546; 'NAU3', -- NASD-9.23 Nasdaq 100 Расчетный фьючерс на Invesco QQQ ETF Trust Unit Series Стоимость пункта цены 0,92p; ГО 1799; };
for i=1,#sec do tag[i] = 'J'..string.sub( sec[i], 1,2 ) print(type(tag[i]), tag[i]) end
Так тоже ошибку не давал? string.sub( sec[i], 0,2 )
Сергей написал: В код пришлось вводить много дополнительных условий и переменных, т.к. в процессе написания выяснилось, что иногда бывает несколько одинаковых index на свечу.
Не бывает ни когда. Индекс пришел или не пришел.
Можно отслеживать:
newbar = Индекс > Индекс1 or false; Индекс1=Индекс
Сергей написал: Любой индикатор легко считается в скрипте qlua, сделать там же среднюю по значениям индикатора не проблема, вопрос именно в пристыковке средней к индикатору на графике силами кода индикатора.
Вы сами то понимаете что написали?
Цитата
Сергей написал: Обычно на такое не отвечаю, но просто чтобы не набежала еще толпа желающих просто посотрясать воздух и пофилосовствовать, коих на форуме стала тьма
Вам тут больше на код не кто не скажет, "Белиберда", просто потому что время дороже.
Цитата
Сергей написал: а не посоветовать что-то в конкретном коде:
Цитата
VPM написал: Алгоритмы все известны, пишите сразу RSI, усредняйте (Period RSI + Period Вашего усреднения).
Индикаторы Опубликованы на этом сайте, берите, усредняйте, при вычислении результатов учитывайте два периода усреднения (Период усреднения RSI и Ваш период). Примеров двойного усреднения полно опубликованных. Хотел в своей библиотеке найти где то был сразу не нашел. Но вот пример как я пользуюсь индикаторами через присвоение.
function Cached.RSI__() local log=math.log local exp=math.exp local abs=math.abs local Price={} local EMA={} local Noise,Peak={},{} local UOE={}
local fLaguerre=Cached.Laguerre_Ehlers() local fPeriod=Cached.Period_SineWave()
return function( I,FSettings,ds )
local I = I local ds=ds local FSettings = (FSettings or {})
Cached -- моя библиотека дальше присвоение и создание переменных (для данной ф. это глобальные).
return function( I,FSettings,ds ) - это замыкание в луа, собственно сама функция то что мы считаем. дальше присвоение и создание локальных переменных
Не я не про код! Только маленькая ремарка в отношении смысла. Про постановку вопроса? А зачем?
Вы читаете значение из RSI?, и пытаетесь его ещё дополнительно сгладить, Вы представляете какой период оцениваете?
Нет технических вопросов совсем нет, до нас все придумали ! Вашем исполнении техника мягко говоря хромает,. зачем создавать индикатор в QUIk а потом его читать, (QUIk без Вашей помощи упадет )
Алгоритмы все известны, пишите сразу RSI, усредняйте (Period RSI + Period Вашего усреднения). А зачем? Это из области "Если Все прыгнули в колодец, то и мне пора"
Высказываясь так, "Ни чего личного", хочу чтоб Вы для себя с формулировали задачу. А зачем?
Альфа эквивалентной EMA связана с длиной простой скользящей средней как
Nikolay, Чтоб точно ГО считать мне пока не нужно, достаточно получать его, все равно необходим зазор чтоб позиция дышала. стоимость контракта = price_last * pos_qty* lot ?
Владимир, Этот форум устроен для поддержки, а главное обнаружению и устранению "косяков" QUIK. То что в нём закралась страничка по обмену опытом в программировании на луа, нужно сказать спасибо организаторам и поддерживать ее.
Цитата
Владимир написал: Боря не той помощи искал, которую может дать этот форум. И уж точно не от Вас. Он очень грамотный трейдер, в биржевой торговле понимает гораздо больше, чем подавляющее большинство участников этого форума - включая меня, например.
Не важно кто что ищет, важно кто что дает, а если "очень грамотный трейдер" тои давай такие же советы, я тоже с удовольствием послушаю "очень грамотный трейдер"
uuh написал: В такой ситуации робот перевыставит заявку на те же 10 лотов.И есть шанс вместо 10 купить 17 лотов.Он может не реализоваться, но он есть и далеко не нулевой.
Нет в этой реализации не каких 17 не может быть, ордер знает 10 и пока ему не подтвердит кщлбек исполнение будет стоять 10 или набираться частями до 10.
dofile("hacktrade.lua") ---Загруили
function Robot()
----- Получили т.тек.торгов
feed = MarketData{
market="QJSIM",
ticker="SBER",
}
----- создаем ордера
order = SmartOrder{
account="NL0011100043",
client="74808",
market="QJSIM",
ticker="SBER",
}
----- Получили индикаторы
ind = Indicator{
tag="MAVG",
}
----- Торгуем
while true do
if feed.last > ind[-1] then
order:update(feed.last, 10)
else
order:update(feed.last, -10)
end
Trade()
end
end
"Это пример реверса по скользящей средней.
Пример тривиальный, но надёжный. Робот догоняет цену.
Если снимите заявку, он выставит количество, которое не успел купить/продать."
uuh написал: А если колбэки о сделке еще не пришли, order.position не обновился, то и количество лотов в заявке может быть не тем, которое задумывалось.
uuh написал: Ну так hacktrade набирает позицию в рамках своих знаний о ней. А эти его знания можно посмотреть в order.position.Если обновлять заявку order:update в рамках своих знаний о текущей позиции, то робот то выставит на биржу заявку в соответствии со своими знаниями о позиции.
Ну подождите, по порядку: В начале до основного цикла формируем заявки им присваивается уникальный номер, согласно этого номера и действуем. Нужно при следующем обращении поменять цену, меняем, нужно поменять количество меняем, нужно снять снимаем. Если исполняется у нее есть два статуса активна и исполнена, активная цена ушла снимаем.
На исполнена придет OnTrade мы его отловим, если не вся заявка исполнена она будет добиваться,
Так что два параллельных мира. мы управляем ценой и количеством (т.е денюшкой) в ордере, А hacktrade исполнением ордера и взаимодействует с терминалом.
VPM написал: И что это было 1 час в борьбе за подключение к сервера? Да уж.
А было это графики.
Вернул расчеты алгоритмов в main убрал лишние графики и вот оно чудо. Все грузится. Идея вести расчеты в квик, подходит для для единичных инструментов.
Цитата
Владимир написал: Господи, канал-то здесь при чём?
function OnTrade(trade)
local key = trade.trans_id
if working
and key~=sdelka.id
--and trade.sec_code==symbol
--and trade.class_code==class
then
local i=tonumber(sdelka[0]); i=i+1; ---- новый размер стека сделок из прерывания
sdelka[0]=i; ---- записываем изменение стека:
---- сохраняем новую сделку;
sdelka[i]={}; -- заводим новый элемент стека
sdelka[i][0]=sdelka[0];
sdelka[i][1]=trade.trans_id; -- ID транзакции
sdelka[i][2]=get_date(trade.datetime)
sdelka[i][3]=get_time(trade.datetime)
-- по умолчанию это покупка
sdelka[i][4]="B"; if bit.band(trade.flags,4)~=0 then sdelka[i][4]="S"; end;
local dir = sdelka[i][4]=="B" and 1 or sdelka[i][4]=="S" and -1 or 0;
sdelka[i][5]=trade.qty*dir; -- количество в сделке (в лотах)
sdelka[i][6]=trade.price; -- цена сделки
----- comission
sdelka[i][7]=trade.clearing_comission+trade.exchange_comission+trade.tech_center_comission;
sdelka[i][8]=trade.order_num;
sdelka[i][9]=trade.trade_num;
sdelka[i][10]=trade.sec_code; -- тикер
---- Защита от повторений:
sdelka.id=trade.trans_id;
end
end;