на фондовом рыке нет такого параметра как "Начало вечерней сессии", он есть на срочном рынке. QUIK умеет работать далеко не с одной биржей и далеко не с одним рынком, а на разных биржах и рынках разный набор доступных параметров. Просто потому что их создавали разные люди. от куда Lua должен взять информацию о том что тип «3» - CHAR если такого параметра просто нет?
QApplication написал: почему то изображение не подтянулось (смотрите QLUA.chm: TABLE getParamEx (STRING class_code, STRING sec_code, STRING param_name))
Вы запрашиваете параметры которых просто нет. Если result = false то и возвращать нечего, а param_type = 0 это просто значение по умолчанию.
QApplication написал: При вызове callback OnParam(args) вызываю getParamEx(args...) со всеми возможными аргументами (описаны в info.chm), часть возвращаемых таблиц имеют не описанное значение param_type в документации («0») . При этом полу result соответствует «0».
Женя Логинов написал: почему в версии 7.27.2.1 на запрос DAYS_TO_MAT_DATE выдает nil? этот параметр уже нельзя запросить? в руководстве пользователя 7.27 этого параметра нет. хотя если строить таблиц текущих торгов, то столбец с количеством дней до погашения есть...
QApplication написал: На сколько я понимаю, у разных аккаунтов могут быть одинаковые Идентификаторы фирм firmid?
Да могут.
Цитата
QApplication написал: Можно привести физическое назначение поля firmid.
Внутри QUIK, фирма это некое объединение (группа) счетов. У брокера может быть несколько фирм.
Цитата
QApplication написал: Что такое фирма во взаимоотношениях клиент-брокер-биржа.
Для пользователя это просто некий идентификатор. Для брокера это раздел к которому принадлежат счета. Для биржи (если говорить про фондовый рынок), это некий Уникальный идентификатор участника торгов. Если говорить про срочный рынок, то это рездел, при чем для одной фирмы в QUIK может быть несколько разделов на бирже.
QApplication написал: Вопрос: как получить код клиента, соответствующий торговому аккаунту.
Для одного кода клиента может быть несколько торговых счетов. Какой считать правильным? Однозначного ответа нет. По этой причине нет однозначной связи между trade_account и client_code. Вы можете по таблице depo_limits подобать нужный Вам счет.
Let_it_go написал: Есть ли риски, что в OnAllTrade прилетит старая сделка из сегодняшних?Ну например при первом старте КВИКа в 13 часов в КВИК начнут сыпаться ранее прошедшие сделки. Они мне не нужны. И только потом начнут поступать новые.
Да риски есть, например тот же перезаказ данных. Надежно обезопасить себя можно только через фильтрацию в самом коде скрипта.
Кирилл написал: Наоборот, это не единственный, а самый неуклюжий вариант. Начинающий инвестор вряд ли является еще и программистом. Итак, если человек каждое утро по бумажке выставляет в программе свои заявки, почему бы не создать такой список в самой программе? Причем тут вообще биржа? Она и не узнает, кто выставил. Вы же сами это и говорите - ручную работу может заменить некий скрипт. И во всех серьезных программах реализована функция автоматического исполнения одних и тех же действий по шаблону. Это называется batch-processing или как-то так. Хоть в редакторах, хоть в конвертерах и т.п. И здесь этого нет только по одной причине - лень программистов создать лишнюю вкладку. Или какая-то выгода. Например, этот костыль к программе могут продавать неопытным людям в виде отдельного скрипта, который человек, изрядно намучившись изо дня в день, рано или поздно купит за любые вменяемые деньги.
В QUIK есть импорт транзакций из файла. Вы можете один раз записать туда нужные Вам транзакции и загружать файл каждый день. К слову обращаем внимание что за транзакции может браться комиссия, и конечные пользователи меньше всех заинтересованы в увеличении количества транзакций. Нам не известно, берет ли Ваш брокер такую комиссию или нет, но биржа точно берет.
AndyJOKER написал: Эммм, несколько странно слышать это от Вас, как от разработчика.
Почему странно? Доступные функции явно описаны в документации: -Индикаторы технического анализа --Функции и глобальные переменные скрипта индикатора --Список функций, доступных из скрипта индикатора
AndyJOKER написал: Весело. Я правильно понимаю, что фактически в индикаторах можно использовать только данные O, H, L, C, V, T , Size ?
Нет, категорически не верно, можно и другие данные, зависит от того что Вам нужно. Если Вам нужно получить данные в индикаторе из другого скрипта, то почему бы не воспользоваться обменом через файлы? Один сприпт пишет в файл, другой читает.
AndyJOKER написал: Валится с ошибкой "attempt to call global 'GetCell' (a nil value)".
В QLUA индикаторах нет такой функции "GetCell" Собственно в QLUA индикаторах вообще нет никаких функций для работы с GUI таблицами, они там не поддерживаются.
Aleksei, Функция нужна только для того чтобы не запоминать все значения в таблицах, а только нужные. Работает просто, есть порядковый индекс I свечки и есть период P за который нужны значения Благодаря функции, вместо того чтобы в таблице sum хранить все значения за все свечки, мы храним для расчетов только значения за несколько последних свечек. Это достигается путем побора индекса через функцию Squeeze
Роман написал: Сразу вопрос - можно это сделать без подключения к серверу? Данные то доступны когда QUIK не подключен.
Да можно. При условии что данные есть в терминале.
Цитата
Роман написал: 1. необходимо получить имя таблицы, к которой обращаться - покопался и выяснил, что, похоже, на QLua это не сделать - он работает только с данными с сервера брокера...блин
QLUA не работает с GUI таблицами, он работает с хранилищем данных для этих таблиц.
Цитата
Роман написал: Я нашел примеры, когда с помощью CreateDataSource создается источник данных и происходит выгрузка исторических данных, а вот для такой таблички?
Если говорить про получение данных из терминала без подключения к серверу, то CreateDataSource не нужен, достаточно обойтись getParamEx подробнее в документации QLUA.chm -Функции взаимодействия скрипта Lua и Рабочего места QUIK --Функции получения значений таблицы «Текущие торги»
Для getParamEx нужно знать имена параметров которые требуются. Получить их можно выведя таблицу по DDE с галкой формальные заголовки. также многие параметры приведены в документации на терминал info.chm -Раздел 8. Алгоритмический язык QPILE --Функции для получения значений Таблицы текущих торгов ---Значения параметров функций
CreateDataSource нужен больше для получения обновлений по параметрам таблиц текущих торгов и по таблице обезличенных сделок, а также по данным графиков.
Олег написал: Тогда индикатор отрисовывает только одну верхнюю линию. Надо еще что-то менять.
Да Вы правы, надо удалить отрисовку горизонтальной линии. Т.е. так: function OnCalculate(Index) return ConvertValue(Settings, func(Index, Settings)),tonumber(Settings.Horizontal_line) end если она все же нужна то ее можно добавлять только первой.
полный код под спойлером
Скрытый текст
Код
Settings = {
Name = "*PC (Price Channel)",
Period = 10,
line = {
{
Name = "PC - upper",
Type = TYPE_LINE,
Color = RGB(0, 206, 0)
},
{
Name = "PC",
Type = TYPE_LINE,
Color = RGB(221, 44, 44)
},
{
Name = "PC - lower",
Type = TYPE_LINE,
Color = RGB(0, 162, 232)
}
--[[,
{
Name = "Horizontal line",
Type = TYPE_LINE,
Color = RGB(140, 140, 140)
}]]
},
Round = "off",
Multiply = 1,
Horizontal_line="off"
}
function Init()
func = PC()
return #Settings.line
end
function OnCalculate(Index)
--return tonumber(Settings.Horizontal_line), ConvertValue(Settings, func(Index, Settings))
return ConvertValue(Settings, func(Index, Settings))
end
function PC() --Price Channel ("PC")
local H_tmp={}
local L_tmp={}
local it = {p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 10)
if (P>0) then
if I == 1 then
H_tmp={}
L_tmp={}
it = {p=0, l=0}
end
if CandleExist(I,ds) then
if I~=it.p then it={p=I, l=it.l+1} end
H_tmp[Squeeze(it.l,P-1)+1] = GetValueEX(it.p,HIGH,ds)
L_tmp[Squeeze(it.l,P-1)+1] = GetValueEX(it.p,LOW,ds)
if it.l >= P then
local val_h = math.max(unpack(H_tmp))
local val_l = math.min(unpack(L_tmp))
return val_h,(val_h+val_l)/2,val_l
--return (val_h+val_l)/2,val_h,val_l
end
end
end
return nil,nil,nil
end
end
SMA,MMA,EMA,WMA,SMMA,VMA = "SMA","MMA","EMA","WMA","SMMA","VMA"
OPEN,HIGH,LOW,CLOSE,VOLUME,MEDIAN,TYPICAL,WEIGHTED,DIFFERENCE,ANY = "O","H","L","C","V","M","T","W","D","A"
function CandleExist(I,ds)
return (type(C)=="function" and C(I)~=nil) or
(type(ds)=="table" and (ds[I]~=nil or (type(ds.Size)=="function" and (I>0) and (I<=ds:Size()))))
end
function Squeeze(I,P)
return math.fmod(I-1,P+1)
end
function ConvertValue(T,...)
local function r(V, R)
if R and string.upper(R)== "ON" then R=0 end
if V and tonumber(R) then
if V >= 0 then return math.floor(V * 10^R + 0.5) / 10^R
else return math.ceil(V * 10^R - 0.5) / 10^R end
else return V end
end
if arg.n > 0 then
for i = 1, arg.n do
arg[i]=arg[i] and r(arg[i] * ((T and T.Multiply) or 1), (T and T.Round) or "off")
end
return unpack(arg)
else return nil end
end
function GetValueEX(I,VT,ds)
VT=(VT and string.upper(string.sub(VT,1,1))) or ANY
if VT == OPEN then --Open
return (O and O(I)) or (ds and ds:O(I))
elseif VT == HIGH then --High
return (H and H(I)) or (ds and ds:H(I))
elseif VT == LOW then --Low
return (L and L(I)) or (ds and ds:L(I))
elseif VT == CLOSE then --Close
return (C and C(I)) or (ds and ds:C(I))
elseif VT == VOLUME then --Volume
return (V and V(I)) or (ds and ds:V(I))
elseif VT == MEDIAN then --Median
return ((GetValueEX(I,HIGH,ds) + GetValueEX(I,LOW,ds)) / 2)
elseif VT == TYPICAL then --Typical
return ((GetValueEX(I,MEDIAN,ds) * 2 + GetValueEX(I,CLOSE,ds))/3)
elseif VT == WEIGHTED then --Weighted
return ((GetValueEX(I,TYPICAL,ds) * 3 + GetValueEX(I,OPEN,ds))/4)
elseif VT == DIFFERENCE then --Difference
return (GetValueEX(I,HIGH,ds) - GetValueEX(I,LOW,ds))
else --Any
return (ds and ds[I])
end
return nil
end
Anton написал: Таким образом, на текущий момент вариантов кроме "ТВС должна быть открытой" я не вижу, на будущее хотелось бы все же видеть что-то более легкое, чем CreateDataSource, без встроенного энквадрата.
Еще раз повторяем (уже третий) Пожелания НЕ будет т.к. описанного поведения НЕ должно быть вообще. Вы описываете проблему с которой надо разобраться. И только если вдруг после разбора окажется что так и должно быть тогда да, будет пожелание. Сейчас это больше выглядит как баг, а не отсутствие функционала. И как уже было сказано, у нас проблема не воспроизводится.
Для анализа просьба прислать на quiksupport@arqatech.com копию всей папки с проблемным терминалом QUIK (без ключей доступа) В письме укажите ссылку на эту ветку форума.
Anton написал: Любопытно, что подписка на дневки в том же самом цикле происходит практически мгновенно, хотя квику приходится несколько тысяч файлов создать в архиве (почистил предварительно). А вот если добавить ds:SetUpdateCallback(), приходится подождать секунд 10 (опять же на все). К сожалению, на ТВС это не влияет, фильтры не устанавливаются и все сделки не едут, а то был бы вариант.
ТОС (он же тики) и интервальные графики едут по разным технологиям. Интервалы генерирует сервер и хранит их у себя в хранилище, в связи с чем на терминал Вы уже получаете все готовое. Тики же едут в сыром виде, как пришли с биржи. Естественно объемы не соизмеримые.
Как уже было сказано, Ваши ~500 сек никуда не идут в сравнении с нашими ~20сек. И как уже было сказано, надо разобраться в начале с этим, а потом уже принимать решение о регистрации пожеланий. Попробуйте собрать больше информации, например провести тестирование на другом компьютере и канале связи. Кроме того, попробуйте провести тест в разное время, утром до торгов, утром при старте торгов, в обед и вечером. Сравните данные и сообщите нам.
Anton написал: Категорически не согласен с пунктом 5. Пример. Юзер в 23:45 запустил квик, чтобы скачать данные за день, запустил скрипт. В 0:15 брокер вырубил сервер. И вдруг внезапно оказывается, что наш скрипт за это время (когда вся ТВС уже приехала бы сто раз) не то чтобы не сохранил данные, а даже еще и не подписался на них. То есть сессия пропала (нет подписки -> нет данныех даже в alltrade.dat), завтра утром на сервере ее уже не будет. Нормальный такой скрипт, удобный. Зато уж компом рычит как зверь по три часа кряду, сразу видно, что важным делом занят.
По этому пункту, дело конечно Ваше, стартовать в конце гонки или в начале. Обычно люди стартуют в начале.
Как же, он добавляет задержку на каждую итерацию каждого цикла.
Цитата
Anton написал: Равно как и сплит тут мало на что влияет, он выполняется один раз на класс, коих в тестовом случае всего 19.
да он тут не причем, это просто один из примеров оптимизации
Цитата
Anton написал: Тогда вопросы другие - а если я в info.ini их из скрипта запишу? Квик это увидит? А если квик со скриптом пересечется на доступе к info.ini, будет ждать анлока или упадет? А если через версию квика вы решите в другом месте фильтры хранить?
Правка info.ini в данном месте саппортом не обслуживается, т.к. не является документированным функционалом.
К слову, тема еще не закрыта. Прежде чем регистрировать пожелание мы должны выяснить а действительно ли оно нужно. Так например на нашем боевом контуре, Ваш код по классу EQOB показал время ~20 сек Это само по себе уже является основанием перейти к разбору проблемы а не регистрации пожеланий.
Anton написал: Как показывает практика, полноценно использовать CreateDataSource для подписки на таблицу обезличенных сделок не представляется возможным
Из переписки совершенно не следует сказанное. Трудности да есть, но "не возможным" использование функции CreateDataSource не делает.
1) Уберите в коде функцию split, она совершенно лишняя. getClassesList и getClassSecurities прекрасно обрабатываются через string.gmatch, без всяких лишних манипуляций с циклами А лишние циклы в борьбе за скорость, это великое зло. Пример кода: for vv in string.gmatch(getClassSecurities(v), "([^,]+)") do -- end
2) в ОС Windows есть свой собственный таймер процессора, который по умолчанию равен 15.625 мс Если вы про него не знали, почитайте про него в интернете В результате на каждую итерацию цикла, кроме обработки самой итерации, вносится указанная задержка. Крайне рекомендуем прочитать текст статьи прежде чем комментировать, это сразу избавит от лишних вопросов.
3) Вам уже говорили что нужно перенести функцию из OnInit в main.
4) зачем делать отдельный цикл для SetEmptyCallback, совершенно не понятно, хотя вопрос не в этом.
5) И последнее, куда важнее с какой скоростью данные поступают и обрабатываются нежели с какой скоростью происходит заказ.
Олег написал: Для внешнего индикатора (архив на скачивание выше):
В скрипте это легко меняется. Указать так: function OnCalculate(Index) return ConvertValue(Settings, func(Index, Settings)),tonumber(Settings.Horizontal_line) end
function PC() --Price Channel ("PC") --какойтокод return val_h,(val_h+val_l)/2,val_l --какойтокод end
Nikolay, В терминале нет такого лога. Однако при падении, по идее должен создаваться dmp файл в папке dmp При должном умении, можно попробовать проанализировать его самостоятельно, однако лучше прислать его нам.
Atom, Во первых, время сервера это время сервера QUIK, а os.date - это время Вашего компьютера. Их часы вполне по честному не обязаны идти синхронно. Т.к. нет никакого способа заставить все компьютеры всего мира идти синхронно.
Во вторых ,сам по себе параметр "время сервера" обновляется по мере поступления данных с сервера. А если быть точнее то каждый пакет данных присланных от сервера, содержит временную метку, которую Вы и видите. Это накладывает помехи при передаче данных. например в случае задержек на канале связи.
Денис, У нас нет опытка написания DLL для LUA и нет каких-либо примеров реализации. Но нам точно известно об успешном опыте наших клиентов. попробуйте поискать в интернете на специализированных форумах посвященных Lua
GET_CLIENT_MARGINAL_BUY_SELL_INFO_EX в QUIK 8.0, Unknown (or illegally called) function при запросе данных GET_CLIENT_MARGINAL_BUY_SELL_INFO_EX в QUIK 8.0
Женя Логинов, Причина проблемы в обновляющихся параметрах Волатильность и Теоретическая цена. Они обновляются по таймауту раз в минуту, даже если инструмент не ликвидный и торгов по нему не было. При их обновлении срабатывает колбек OnParam Чтобы избежать этого, удалите эти параметры из меню "Заказ данных"
Сергей, Так и должно быть, таблица сделок является обновляемой сущностью, при каждом обновлении параметров сделки происходит вызов OnTrade этот вопрос уже не однократно поднимался на форуме
Женя Логинов, Здравствуйте, Проверьте настройки терминала "Программа" - "Получение данных", нет ли там случайно галки "Запрашивать данные раз в ...", если есть то снимите.
GET_CLIENT_MARGINAL_BUY_SELL_INFO_EX в QUIK 8.0, Unknown (or illegally called) function при запросе данных GET_CLIENT_MARGINAL_BUY_SELL_INFO_EX в QUIK 8.0
Виталий, Для того чтобы запустить Lua индикатор компилировать его не требуется. QUIK не увидит Lua индикатор если он не соответствует определенной структуре, которая приведена в документации (см QLUA.chm глава "Индикаторы технического анализа" - "Общие сведения")