Поскольку с программированием не на ТЫ, то с большим трудом мною был написан индикатор, показывающий хай и лоу предыдущей торговой сессии. Работал он работал и потом бац - в версии 7.6 перестал - оказывается в квике видите ли решили, что надо бы поменять вывод отсутствующих свечек. Хорошо, потратил кучу времени, разобрался в чём дело, исправил. Опять всё работало-работало, но вот подкатили квик 7.9 и индикатор опять перестал работать. Да сколько блин можно-то??? Это вообще нормально? Что опять поменяли?!? Для меня это реальная проблема, т.к. программировать почти не умею и каждый раз приходится тратить кучу времени на то, чтобы написать самый простенький индикатор.
Индикотр выводит линии, обозначающие максимум и минимум цены предыдущей торговой сессии. На акциях работает нормально, а на фьючерсах выдаёт такую ошибку. Код индикатора:
Код
Settings =
{ Name = "5.Previous session High-Low",
line =
{ { Name = "HIGH",
Color = RGB(255,0,255),
Type = TYPE_DASH,
Width = 1
},
{ Name = "LOW",
Color = RGB(255,0,255),
Type = TYPE_DASH,
Width = 1
}
}
}
function Init()
return #Settings.line
end
local hl =
{ -- year
-- month
-- day
-- high
-- low
}
function OnCalculate(index)
local dt = T(index)
if not dt then
return
end
local trdt = getTradeDate()
if dt.day ~= trdt.day or dt.month ~= trdt.month or dt.year ~= trdt.year then
if dt.day ~= hl.day or dt.month ~= hl.month or dt.year ~= hl.year then
hl.year = dt.year
hl.day = dt.day
hl.month = dt.month
hl.high = H(index)
hl.low = L(index)
else
hl.high = math.max(hl.high,H(index))
hl.low = math.min(hl.low,L(index))
end
else
return hl.high,hl.low
end
end
Изменения были в версии 7.7. Начиная с этой версии, пустые свечки выводят T но не выводят остальные O H L C V. Соответственно, нужно переделать условие
Русский, Банальный пример, когда в одном окне два разных графика. один по нелеквиду, а второй по активно торгующейся бумаге. В таком случае на графике нелеквида будут пустые свечки.
Русский написал: Т.е., если я не совмещаю графики разных инструментов, то для меня проблема пустых свечек не актуальна?
Добрый день. Пустая свечка может появиться и не только при совмещении графиков по разным инструментам, но и на графике по одному инструменту, при условии, что в настройках диаграммы включена галочка 'Показывать пустые интервалы'. Так же пустые интервалы появятся, если на график поместить встроенный индикатор, например, 'Alligator' который рассчитывается 'в будущее', добавляя в конец графика интервалы, при этом на самом графике Цены этих свечек не будет, таки образом для Lua индикатора это будут пустые свечки.
Перед тем как задать вопрос, убедитесь, что решение Вашей задачи не описано в официальном мануале - 'Использование Lua в Рабочем месте QUIK.pdf' https://arqatech.com/upload/Public/quik_lua.zip
Русский, до этих доработок функции C, H, L, O возвращали нули для пустых свечек, и соответственно участвовали в расчетах индикаторов, например, тот же индикатор Moving Average считался некорректно, т.к. учитывал эти пустые свечки при расчете среднего значения, если явно их не отфильтровывать по нулевом объему.
Перед тем как задать вопрос, убедитесь, что решение Вашей задачи не описано в официальном мануале - 'Использование Lua в Рабочем месте QUIK.pdf' https://arqatech.com/upload/Public/quik_lua.zip
Русский написал: А как происходит в программах тех.анализа? Там в коде не надо проверять пустая ли свечка
Русский, к сожалению по данному вопросу я подсказать ничего не могу.
Перед тем как задать вопрос, убедитесь, что решение Вашей задачи не описано в официальном мануале - 'Использование Lua в Рабочем месте QUIK.pdf' https://arqatech.com/upload/Public/quik_lua.zip
Я никак не соображу, может кто подскажет, как теперь переписывать индикатор в связи с CandleExist. Попробовал посчитать количество непустых свечек, но это неверно. Нужно определить номер последней существующей свечки? Если так, то как это сделать, не могу понять.
Settings = {
Name = "*SMA Example",
Period = 9,
line = {{Name = "SMA",Type = TYPE_LINE, Color = RGB(255, 0, 0)}}
}
local Index_tbl = {}
local SUM_TMP={}
function Init()
return #Settings.line
end
function OnCalculate(I)
if I == 1 then
SUM_TMP = {}
Index_tbl = {}
end
if CandleExist(I) then
if (Index_tbl[#Index_tbl]~=I) then Index_tbl[#Index_tbl+1]=I end
else return nil end
I = #Index_tbl
SUM_TMP[I]=(SUM_TMP[I-1] or 0)+C(Index_tbl[I])
if I >= Settings.Period then
return (SUM_TMP[I]-(SUM_TMP[I-Settings.Period] or 0))/Settings.Period
end
return nil
end
Небольшой, комментарий. В частности для SMA, параметр Index_tbl не обязательно должен быть именно таблицей и написать можно проще. Но в некоторых индикаторах требуется "пройтись" по предыдущим свечкам и тогда без таблицы не обойтись. Поэтому в примере используется именно таблица. Ну и конечно-же, критика принимается.
Русский написал: Не могли бы Вы подсказать, как таблицей (вместо цикла) посчитать количество непустых свечей?
А в чем сложность с таблицей Index_tbl? Вопрос чисто синтаксиса Lua, что описано в документации на Lua. К индикаторам вопрос не имеет отношения.
В примере, Index_tbl по порядковому номеру, выдаст настоящий номер свечки. Надо общее количество свечек, пожалуйста #Index_tbl Надо пробежать по непустым свечкам, делается через for i=1, #Index_tbl do
Сергей, а давайте чуточку усложним. Сделаем сдвиг этого SMA индикатора на N свечей вправо Как это сделано например в одной из линий индикатора ишимоку. Для простоты пусть N будет фиксированным параметром.
s_mike@rambler.ru написал: Сергей, а давайте чуточку усложним. Сделаем сдвиг этого SMA индикатора на N свечей вправо Как это сделано например в одной из линий индикатора ишимоку. Для простоты пусть N будет фиксированным параметром.
"вправо"? это легко, с тем ограничением что свечки "в будущее" к сожалению строить нельзя. не поверите но куда сложнее "влево" В том же Ichimoku, линии Senkou, у меня запоминаются в отдельную таблицу, но выводятся не в текущем их значении, а в прошлом (со сдвигом) В старых примерах индикаторов на Lua это видно, в новых будет также.
Про возможность рисовать индикаторы в будущее, уже было зарегистрировано пожелание, оно пока еще не реализовано.
1. всегда рассчитываем свечи по порядку их следования 2. строим буфер исходных данных с фильтрацией пропусков 3. строим буфер рассчитанных данных с фильтрацией пропусков.
для простейших индикаторов подходит.
теперь берем что-то посложнее типа зигзага. вопрос таков. необходимо изменить значение в свече с номером size()-k, где k есть вычисляемое значение. как с этим будете бороться? третий буфер вводить?
s_mike@rambler.ru написал: таким образом, ваш принцип состоит из трех идей. 1. всегда рассчитываем свечи по порядку их следования 2. строим буфер исходных данных с фильтрацией пропусков 3. строим буфер рассчитанных данных с фильтрацией пропусков. для простейших индикаторов подходит.
1. да 2. да, только не "буфер исходных данных", а номера индексов (Index_tbl). 3. да, но не во всех индикаторах это необходимо.
Цитата
s_mike@rambler.ru написал: теперь берем что-то посложнее типа зигзага. вопрос таков. необходимо изменить значение в свече с номером size()-k, где k есть вычисляемое значение. как с этим будете бороться? третий буфер вводить?
если проще, интересует уже сдвиг "влево"? Если так то в том же Ichimoku, на линии Chinkou, для этого используется функция SetValue.
s_mike@rambler.ru, Кажется я Вас понял, вопрос не в том как поменять значение на 5й свечке, когда текущая 10я. а в том как поменять значение на 10й свечке, если текущая только 5я, при условии что мы не знаем, существует ли она вообще. Вариантов несколько: 1) проверять свечки в будущее. (по производительности не очень.) 2) рисовать данные именно на 10й свечке.
2й вариант куда разумней и быстрее. Ничего не мешает запомнить цифру на 5й свече, но нарисовать только когда дело дойдет до 10й. Примерно так и реализовано на линии Chinkou, дальше уже идут вариации, как это оптимальней всего сделать. Если у вас есть свои идеи, готов выслушать.
Ничто -то не мешает. Только неизвестно, будет ли свеча 10 пустой. И опять начинаются проверки, сдвиги и прочая лабуда. И так в каждом индикаторе, который пишешь. А результате ты не программирует индикатор, и занимаешься самоудовлетворением в поисках существующих или несуществующих свечей во всевозможных ситуациях и позах.
если делать по уму -нужно писать прокси для всех функций работы с таблицами qlua. Которые будут отфильтровать пустые свечи, как будто их и нет
Пока писал эту заплатку, увиделась очередная дырка в терминале. При написании индикатора на языке луа невозможно отследить момент полного перерсчета индикатора.
Способ сравнения номера свечи с 1 проблему не решает. Свеча с номером 1 может быть пустой и колбек oncalculate на ней никогда не вызовется. Также ничто не мешает графику состоять просто из одной свечи - в этом случае " полный перерасчет" будет на каждом тике.
Всвязи с этим регистрируйте пожелание. Либо нужно ввести новый колбек либо добавить в вызов oncalculate еще один параметр true/false, отражающий надичие полного перерасчета графика.
Позвольте пару слов : Формализуем задачу в общем виде. ----------------------------------- Имеем исходные данные Y на множестве независимой переменной X. Множества Y,,X имеют пропуски значений. По исходному множеству Y рассчитываем дискретную функцию Z=f(Y,X); Задача: На новое множество X1 , которое имеет пропуски Y1, отобразить Z. При этом начало множеств X и X1 совмещаются линейным сдвигом на X0. --------------------------------- Решение в общем виде состоит в том, чтобы сравнивать X и X1 и либо считать новое значение Z, если его не было, либо не отображать Z на X1 если нет X1. ------------------------------- Поправьте, если не так.
s_mike@rambler.ru написал: При написании индикатора на языке луа невозможно отследить момент полного перерсчета индикатора.
Момент полного перерасчета, это Index==Size(). Дальше, идет уже текущее обновление. Или речь не про полный перерасчет, а про начало расчета? Тогда это Index==1.
Цитата
s_mike@rambler.ru написал: Свеча с номером 1 может быть пустой и колбек oncalculate на ней никогда не вызовется
Это не правда, Вызовется, еще как. Если конечно речь про последние версии терминала.
Цитата
s_mike@rambler.ru написал: Способ сравнения номера свечи с 1 проблему не решает. Свеча с номером 1 может быть пустой и колбек oncalculate на ней никогда не вызовется. Также ничто не мешает графику состоять просто из одной свечи - в этом случае " полный перерасчет" будет на каждом тике.
Не вижу тут каких-либо проблем. И не могу вспомнить ни одного индикатора, где с этим были бы какие-либо сложности.
Да, на свежих версиях колбек онкалкулате вызывается на пустых свечах. Первая причина снята.
Однако вторая причина по-прежнему существует. Представьте себе график, состоящий из одной свечи. Первый день торговли фьючерсом на дневном графике. Или первая неделя на недельном графике. Нам же может захотеться посмотреть например, объемы покупок и объемы продаж за этот день или за неделю соответственно? Может захотеться.
А вот индикатор, который посчитает и нарисует объемы покупок и продаж, построенный на таком графике, состоящем из одной свечи, сойдет с ума - он будет на каждом тике считать, что начался новый перерасчет.
Да и вообще. Такая проверка - самый натуралный официально признанный костыль.
s_mike@rambler.ru написал: А вот индикатор, который посчитает и нарисует объемы покупок и продаж, построенный на таком графике, состоящем из одной свечи, сойдет с ума - он будет на каждом тике считать, что начался новый перерасчет.
Все равно не вижу проблем. На недельном графике, Вы в любом случае, не увидите объем за день, не говоря уже об объемах на покупку и на продажу. Никакой true/false тут не поможет. И потом, если обнулять переменные при Index==1, то в случае графика с одной свечой, всегда будет происходить расчет с нуля, как будто первый раз запустили. Никто с ума не сойдет.
Цитата
s_mike@rambler.ru написал: Да и вообще. Такая проверка - самый натуралный официально признанный костыль.
Приведите реальный пример индикатора, когда это работает не как надо.
s_mike@rambler.ru написал: Однако вторая причина по-прежнему существует. Представьте себе график, состоящий из одной свечи. Первый день торговли фьючерсом на дневном графике. Или первая неделя на недельном графике. Нам же может захотеться посмотреть например, объемы покупок и объемы продаж за этот день или за неделю соответственно? Может захотеться.
Кажется я понял, Вам надо вычесть из текущего значения графика, его значение на начало торгов текущего дня? Нет проблем, делаем такую же, временную таблицу как с индексами, только вместо индексов считаем изменения (тики). Будет тоже самое что индексы.
s_mike@rambler.ru написал: А вот индикатор, который посчитает и нарисует объемы покупок и продаж, построенный на таком графике, состоящем из одной свечи, сойдет с ума - он будет на каждом тике считать, что начался новый перерасчет.
Все равно не вижу проблем. На недельном графике, Вы в любом случае, не увидите объем за день, не говоря уже об объемах на покупку и на продажу. Никакой true/false тут не поможет. И потом, если обнулять переменные при Index==1, то в случае графика с одной свечой, всегда будет происходить расчет с нуля, как будто первый раз запустили. Никто с ума не сойдет.
Цитата
s_mike@rambler.ru написал: Да и вообще. Такая проверка - самый натуралный официально признанный костыль.
Приведите реальный пример индикатора, когда это работает не как надо.
Сергей. Вы совершенно неправильно меня понимаете.
Индикаторы бывают сложными. Не все такие простые как скользящая средняя. Таким сложным индикаторам бывает необходимо перед началом каждого расчета всей таймсерии свечей делать какие-то предварительные действия. В простейшем случае это обнуление внутренних переменных, а в более сложных - просмотр таблиц терминала или вообще инициализация и запуск внешних объектов.
Возвращаемся в примеру, когда на графике есть всего одна свеча.
Например, для того чтобы проинициализировать индикатор, показывающий отдельно объем покупок и объем продаж, необходимо скинуть указатели на таблицу обезличенных сделок и начать сбор информации по ней с самого начала. Это необходимо, так как (в частности) необходимо строить внутренние таблицы исходя их установленного таймфрейма графика. Поскольку при проверке на равенство единице номера текущей свечи мы будем считать, что начат полный перерасчет всех свечей индикатора - мы будем как подорванные сканировать всю таблицу обезличенных сделок на каждом тике. Скрипт не умрет, а вот терминал - непременно )
Вообще странный подход у вас, арочников. Вместо того чтобы вынуть наружу колбек и забыть о всевозможные проблемах, переложив их уже на пользователя, вы начинаете думать, как ему ничего не дать и заставить его понастроить подпорок, чтобы получить тот же самый колбек, но искусственно и не 100%но надежно. Махозизьма прям )
Ваше пожелание зарегистрировано. Мы постараемся рассмотреть его и сообщить Вам результаты анализа. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожелания в будущих версиях ПО.
Например, для того чтобы проинициализировать индикатор, показывающий отдельно объем покупок и объем продаж, необходимо скинуть указатели на таблицу обезличенных сделок и начать сбор информации по ней с самого начала. Это необходимо, так как (в частности) необходимо строить внутренние таблицы исходя их установленного таймфрейма графика. Поскольку при проверке на равенство единице номера текущей свечи мы будем считать, что начат полный перерасчет всех свечей индикатора - мы будем как подорванные сканировать всю таблицу обезличенных сделок на каждом тике. Скрипт не умрет, а вот терминал - непременно )
Тут что-то не так. При смене интервала или еще чего-то и повторной инициализации на первом индексе уже не будет тиков, поэтому ничто не умрет. Для надежности можно поставить флаг и тем более ничего не умрет. по-моему проблема больше недодуманная, т е надуманная.
Sergey Gorokhov написал: Здравствуйте, Пока видится рабочим такой вариант:
Код
Settings = {
Name = "*SMA Example" ,
Period = 9 ,
line = {{Name = "SMA" ,Type = TYPE_LINE, Color = RGB ( 255 , 0 , 0 )}}
}
local Index_tbl = {}
local SUM_TMP = {}
function Init ()
return # Settings.line
end
function OnCalculate (I)
if I = = 1 then
SUM_TMP = {}
Index_tbl = {}
end
if CandleExist(I) then
if (Index_tbl[ # Index_tbl]~ = I) then Index_tbl[ # Index_tbl + 1 ] = I end
else return nil end
I = # Index_tbl
SUM_TMP[I] = (SUM_TMP[I - 1 ] or 0 ) + C(Index_tbl[I])
if I > = Settings.Period then
return (SUM_TMP[I] - (SUM_TMP[I - Settings.Period] or 0 ))/Settings.Period
end
return nil
end
что скажите о таком решении:
Код
Settings = {
Name = "*nk_SMA",
Period = 9,
line = {{Name = "SMA",Type = TYPE_LINE, Color = RGB(255, 0, 0)}}
}
local SUM,i_,SMA,m=0,0,0,0;
function Init() return #Settings.line end
function OnCalculate(I)
if I == 1 then SUM=0; i_=0; SMA=C(I);m=0; end
if I~=i_ then
if m>Settings.Period then m=Settings.Period;
if C(i_-m) then SUM-C(i_-m) end
end
if C(I) then SUM_TMP=SUM +C(I); m=m+1; SMA=SUM/m; end
end
i_o=I;
end
return SMA;
end
Николай Камынин написал: Тут что-то не так. При смене интервала или еще чего-то и повторной инициализации на первом индексе уже не будет тиков, поэтому ничто не умрет. Для надежности можно поставить флаг и тем более ничего не умрет. по-моему проблема больше недодуманная, т е надуманная.
Вы просто не поняли суть проблемы. Если количество свечей на графике == 1, то все приходящие тики имеют номер свечи == 1 в случае продолжения торгов в пределах этой же свечи.
Николай Камынин написал: Тут что-то не так. При смене интервала или еще чего-то и повторной инициализации на первом индексе уже не будет тиков, поэтому ничто не умрет. Для надежности можно поставить флаг и тем более ничего не умрет. по-моему проблема больше недодуманная, т е надуманная.
Вы просто не поняли суть проблемы. Если количество свечей на графике == 1, то все приходящие тики имеют номер свечи == 1 в случае продолжения торгов в пределах этой же свечи.
Подумайте.
Понятно. ---------------- Я реально так не изгалялся, но для решения такой задачи могу предложить следующее. В этой ситуации необходимо ввести некоторую систему координат, которая позволяет нам определять место нахождения внутри этой свечи. ------------------------------ Например, можно определить начальную инициализацию и все остальные. -------------------------- Т е инициализация при загрузки скрипта отличается от инициализации при пересчете. ----------------------- Кроме того, при пересчете мы имеем информацию о количестве тиков от начала свечи. Это значение может быть системой координат внутри свечи. Таким образом, каждый пересчет будет отличаться от предыдущего и поэтому будет управляемым. Полагаю, что лишних телодвижений можно полностью избежать. Примерно так.
Николай Камынин написал: что скажите о таком решении:
Слишком много ошибок
На каком инструменте Вы проверяли. Я на сбербанке. ошибок нет график совпадает со встроенным индикатором. Правда в отличии от Вашего решения ресурсов на порядки надо меньше.
s_mike@rambler.ru, хочу обратить Ваше внимание на то, что "внутри свечи" находится невозможно, так как нет алгоритма расчета свечи (есть лишь картинка на графике четырех индикаторов). Правильно говорить о количестве интервале времени от начала истории (или сессии) и моменте времени внутри текущего интервала. Если Вы будете придерживаться такой системы координат, то нет никакой разницы для вычислений, сколько свечей на графике нарисовано.
Settings = { Name = "*nk_SMA", Period = 9, line = {{Name = "SMA",Type = TYPE_LINE, Color = RGB(255, 0, 0)}} }
local SUM,i_,SMA,m=0,0,0,0; function Init() return #Settings.line end
function OnCalculate(I) if I == 1 then SUM=0; i_=0; SMA=C(I);m=0; end if I~=i_ then if m>Settings.Period then m=Settings.Period; if C(i_-m) then SUM-C(i_-m) end end if C(I) then SUM_TMP=SUM +C(I); m=m+1; SMA=SUM/m; end end i_o=I; end return SMA; end
Settings = {
Name = "nk_SMA",
Period = 9,
line = {{Name = "SMA",Type = TYPE_LINE, Color = RGB(255, 255, 0)}}
}
function Init() return #Settings.line end
local P,i1=0,999; local SMA,SUM=0,0
function jget(Y,i)
local m=i; while(m>1 and Y(m)==0) do m=m-1; end; return m;
end
--расчет скользящей средней на закрытой свече
--- расчет выполняется один раз в момент открытия новой свечи
function OnCalculate(i)
if i~=i1 then
if i1>i then
SUM=C(i); i1=0; SMA=0; P=Settings.Period;
else
x=C(jget(C,i1)); SUM=SUM+x;
if P>=i1 then SMA=SUM/i1;
else
SUM=SUM-C(jget(C,i1-P)); SMA=SUM/P;
end
end
i1=i;
end
return SMA;
end