Антон Михеев написал: правильно ли я понял- при входе в терминал меня просят ввести логин и пароль, при этом в этом же окошке можно выбрать сервер. таким образом у одного брокера сегодня можно работать на сервере №1, а завтра на сервере №2. при этом количество свечей у одного брокера на сервере №1 и сервере№2 может отличаться? поэтому МСД дает разные значения? мой брокер ВТБ 24 - думал что надежный. кстати у них на разных серверах можно обновлять до разных версий квика- на одном 7,11 на другом 7,12.
Для начала проверьте, а потом делайте выводы. И как уже было сказано и еще раз повторим, если вдруг окажется что графики на разных серверах разные это НЕ нормально и это повод обратиться к брокеру с описанием проблемы.
Цитата
Антон Михеев написал: Если нет, это повод обратиться к брокеру." - вы имеете ввиду на графике нажать правой клавишей мыши на строке "сохранить данные в файл" файл в формате тхт?
Здравствуйте, Сервера разные. Скорее всего графики содержат разный набор свечек. т.к. МАСД считается от EMA то в расчетах участвуют предыдущие значения индикатора. А значит, если где-нибудь в начале графика или середине не хватает свечек, то расчет покажет разные цифры.
Сохраните график в текстовый файл (через контекстное меню) и проверьте совпадают ли графики или нет. Если нет, это повод обратиться к брокеру.
Добавьте логирование в свой код: message(tostring(getInfoParam('TRADEDATE'))) Это нужно чтобы мы могли увидеть в какой момент возникла проблема. При возникновении ошибки, закройте терминал, пришлите нам на quiksupport@arqatech.com архив всей папки с терминалом (без ключей доступа). В теме письма укажите ссылку на эту ветку форума.
Let_it_go написал: Брокер может делать такое ограничение, а может не делать?
Да верно. Это опция, которая настраивается по усмотрению брокера, а НЕ ограничение сервера.
Цитата
Let_it_go написал: Это настраивается для всех клиентов, или брокер может вводить персональные ограничения для отдельных клиентов если видит, что они флудят заявками?
Брокер может указать как глобальную настройку так и индивидуальную, т.е. возможны оба варианта.
Let_it_go написал: Почему оно возникает несколько раз при попытке "Снять все активные заявки" через контекстное меню (клик правой кнопкой по таблице заявок). На скриншоте видно, что команда сгенерировалась 6 раз.
Потому что на бирже нет такой транзакции "Снять все активные заявки", впрочем как и на сервере QUIK. Такая транзакция есть только в терминале, а терминал на сервер все равно отправляет столько транзакций на снятие сколько активных заявок. А раз на сервере настроено ограничение, то сервер не пускает на биржу все транзакции, а только часть.
Денис Климов написал: Каков предельный размер таблицы идентификаторов?
Как такового ограничения нет. Пришлите скриншот свойств проблемного графика, вкладка "Дополнительно" И часть кода скрипта, где происходит обращение к этому графику.
Цитата
Денис Климов написал: И нельзя ли иметь один исходный идентификатор для одного графика на весь квик, обращаться к нему со всех графиков, окон и вкладок?
На всякий случай, код скрипта на котором проверяли:
Скрытый текст
Код
--[[
Что делает:
По Таблице текущих параметров строит таблицу опционов с расcчитанными греками
Формулы взяты отсюда:
http://en.wikipedia.org/wiki/Black%96Scholes
http://en.wikipedia.org/wiki/Greeks_%28finance%29
Как использовать:
откройте Таблицу Текущих Параметров (меню Таблицы -> Текущая Таблица)
Укажите настройки, после чего, запустите скрипт (меню Таблицы - Lua - Доступные скрипты)
чтобы сохранить в CSV файл, текущее состояние таблицы, нужно нажать комбинацию клавиш Ctrl+S файл сохраняется в папку со скриптом, с именем HHHMMDD.csv
]]
-------------------------------НАСТРОЙКИ-------------------------------
RiskFree=0/100 --безрисковая ставка %, Указывается вручную
BaseClassCode = "SPBFUT" --Класс базового актива
ClassCode = "SPBOPT" --Класс опционов
--Список базовых активов, через запятую, по которым отображать опционы:
BaseSecList = "RIU7" --getClassSecurities(BaseClassCode) --все сразу
--Список опционов через запятую:
SecList = getClassSecurities(ClassCode) --все сразу
INTERVAL = 1000 --Интервал обновления таблицы
doLogging=false --включает запись в файл, формата csv.
log_file=getScriptPath() .. "\\Greek.csv" --путь к csv файлу
-----------------------------------------------------------------------
-------------------------------ТО ЧТО НИЖЕ, ТРОГАТЬ НЕ НАДО------------------------------------------------------------------
--Параметры таблицы
tbl = {
["caption"]="Greek",
[1]="Название",
[2]="Код опциона",
[3]="Тип опциона",
[4]="Баз. актив",
[5]="Расчетная цена",
[6]="Страйк",
[7]="Волатильность",
[8]="До исполнения",
[9]="Дельта",
[10]="Гамма(%)",
[11]="Тэта",
[12]="Вега",
[13]="Ро",
["t_id"]=0
}
abTable = {}
BaseCol = {}
Sec2row = {}
file = nil
Sep = ";"
YearLen=365.0 --Число дней в году
WORK = true
CALC = false
G_ROW = -1
if (BaseSecList == "") or (BaseSecList == nil) then
BaseSecList = getClassSecurities(BaseClassCode)
end
if (SecList == "") or (SecList == nil) then
SecList = getClassSecurities(ClassCode)
end
-------------------------------ФУНКЦИИ------------------------------------------------------------------
function Logging(str) --Пишет лог
if file~=nil and doLogging then
file:write(str .. "\n")
file:flush()
end
end
function N(x) --Нормальное среднее
if (x > 10) then
return 1
elseif (x < -10) then
return 0
else
local t = 1 / (1 + 0.2316419 * math.abs(x))
local p = 0.3989423 * math.exp(-0.5 * x * x) * t * ((((1.330274 * t - 1.821256) * t + 1.781478) * t - 0.3565638) * t + 0.3193815)
if x > 0 then
p=1-p
end
return p
end
end
function pN(x) --производная от функции нормального среднего
return math.exp(-0.5 * x * x) / math.sqrt(2 * math.pi)
end
function Greek(tmpParam)
local b = tmpParam.volatility / 100 --"b" волатильность доходности (квадратный корень из дисперсии) базисной акции.
local S = tmpParam.settleprice --"S" текущая цена базисной акции;
local Tt = tmpParam.DAYS_TO_MAT_DATE / YearLen --"T-t" время до истечения срока опциона (период опциона);
local K = tmpParam.strike --"K" цена исполнения опциона;
local r = RiskFree --"r" безрисковая процентная ставка;
local d1 = (math.log(S / K) + (r + b * b * 0.5) * Tt) / (b * math.sqrt(Tt))
local d2 = d1-(b * math.sqrt(Tt))
local Delta = 0
local Gamma = 0
local Theta = 0
local Vega = 0
local Rho = 0
local e = math.exp(-1 * r * Tt)
Gamma = pN(d1) / (S * b * math.sqrt(Tt))
Vega = S * e * pN(d1) * math.sqrt(Tt)
Theta = (-1 * S * b * e * pN(d1)) / (2 * math.sqrt(Tt))
if tmpParam.Optiontype == "Call" then
Delta = e * N(d1)
Theta = Theta - (r * K * e * N(d2)) + r * S * e * N(d1)
----Theta = Theta - (r * K * e * N(d2))
Rho = K * Tt * e * N(d2)
else
Delta = -1 * e * N(-1*d1)
Theta = Theta + (r * K * e * N(-1 * d2)) - r * S * e * N(-1 * d1)
----Theta = Theta + (r * K * e * N(-1 * d2))
Rho = -1 * K * Tt * e * N(-1 * d2)
end
return {
["Delta"] = Delta,
["Gamma"] = 100 * Gamma,
["Theta"] = Theta / YearLen,
["Vega"] = Vega / 100,
["Rho"] = Rho / 100
}
end
function GetRow(ID,row) --возвращает строку таблицы
local rows, col = GetTableSize(ID)
local result = ""
if rows~=nil and row<=rows then
for i=1,col do
result=result..GetCell(ID,row,i).image .. Sep
end
end
return result
end
function CSV(T) --пишет таблицу в csv файл
function FTEXT(V) --ПРОВЕРЯЕМ КОРРЕКТНОСТЬ КОЛИЧЕСТВА СИМОЛОВ ПЕРЕМЕННОЙ
V=tostring(V)
if (string.len(V)==1) or (string.len(V)==5) then
V="0".. V
end
return V
end
local temp = os.date("*t")
local Fname =getScriptPath() .. "\\" .. FTEXT(temp.year) .. FTEXT(temp.month) .. FTEXT(temp.day) .. ".csv"
CSVFile = io.open(Fname, "w+")
if CSVFile~=nil then
local rows, col = GetTableSize(T.t_id)
for i=1,col do --расставляем заголовки
CSVFile:write(T[i] .. Sep)
end
CSVFile:write("\n")
for i=1,rows do --пишем таблицу
CSVFile:write(GetRow(T.t_id,i).."\n")
end
CSVFile:flush()
CSVFile:close()
message("Файл успешно сохранен:\n"..Fname, 1)
else
message("Ошибка при сохранении файла:\n"..Fname, 3)
end
end
function round(num, idp) --округляет до указанного количества знаков
local mult = 10^(idp or 0)
return math.floor(num * mult + 0.5) / mult
end
function comma_value(n) --ставит разделители в числах
local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$')
return left..(num:reverse():gsub('(%d%d%d)','%1 '):reverse())..right
end
function CreateDataSourceEX(Class,Sec,Par)
local ds,err = CreateDataSource(Class, Sec, INTERVAL_TICK, Par)
if ds==nil then
message("Ошибка при получении параметра "..Par..":\n"..err, 3)
return false
else
ds:SetEmptyCallback()
while (ds:Size()==0) and (WORK) do
sleep(100)
end
return true
end
end
function Stop()
if doLogging then
file:close()
end
WORK = false
end
function Calculate(row,do_calc)
if (row~=nil) and (row>=0) and (do_calc) then
local T=BaseCol[row]
local tmpParam ={
["Optiontype"] = T.Optiontype,
["settleprice"] = getParamEx(BaseClassCode,T.Optionbase,"settleprice").param_value+0,
["strike"] = getParamEx(ClassCode,T.SecCode,"strike").param_value+0,
["volatility"] = getParamEx(ClassCode,T.SecCode,"volatility").param_value+0,
["DAYS_TO_MAT_DATE"] = T.DAYS_TO_MAT_DATE
}
local tmpGreek = Greek(tmpParam)
SetCell(tbl.t_id, row, 5, comma_value(tmpParam.settleprice), tmpParam.settleprice) -- "Расчетная цена",
SetCell(tbl.t_id, row, 6, comma_value(tmpParam.strike), tmpParam.strike) --"Страйк",
SetCell(tbl.t_id, row, 7, tostring(tmpParam.volatility), tmpParam.volatility) -- "Волатильность",
SetCell(tbl.t_id, row, 8, tostring(tmpParam.DAYS_TO_MAT_DATE), tmpParam.DAYS_TO_MAT_DATE) --"До исполнения",
SetCell(tbl.t_id, row, 9, tostring(round(tmpGreek.Delta,2)), tmpGreek.Delta) --"Дельта",
SetCell(tbl.t_id, row, 10, tostring(round(tmpGreek.Gamma,4)), tmpGreek.Gamma) -- "Гамма(%)",
SetCell(tbl.t_id, row, 11, tostring(round(tmpGreek.Theta,2)), tmpGreek.Theta) -- "Тэта",
SetCell(tbl.t_id, row, 12, tostring(round(tmpGreek.Vega,2)), tmpGreek.Vega) -- "Вега",
SetCell(tbl.t_id, row, 13, tostring(round(tmpGreek.Rho,2)), tmpGreek.Rho) -- "Ро",
if doLogging then
Logging(os.date().. Sep .. GetRow(tbl.t_id,row))
end
end
return false
end
-------------------------------Колбэки------------------------------------------------------------------
function f_cb(t_id,msg,par1,par2) --событие на нажатие клавиш
if (msg==QTABLE_CHAR) and (par2==19) then --сохранить в CSV файл текущее состояние таблицы нужно нажать комбинацию клавиш Ctrl+S
CSV(tbl)
end
if (msg==QTABLE_CLOSE) then --закрытие окна
Stop()
end
if (msg==QTABLE_VKEY) and (par2==116) then --функция принудительного обновления таблицы при нажатии клавиши Ctrl+F5
for SecCode in string.gmatch(SecList, "([^,]+)") do --перебираем опционы по очереди.
Calculate(Sec2row[SecCode],true)
Highlight(tbl.t_id, Sec2row[SecCode], QTABLE_NO_INDEX, RGB(255,0,0), QTABLE_DEFAULT_COLOR, INTERVAL)
end
end
end
function OnStop()
Stop()
DestroyTable(tbl.t_id)
end
function OnInit()
local STR = ""
if doLogging then
file = io.open(log_file, "w+")
end
tbl.t_id = AllocTable()
for i=1,table.maxn(tbl) do --добавляем колонки
if i<=4 then
AddColumn(tbl.t_id, i, tbl[i], true, QTABLE_CACHED_STRING_TYPE, string.len(tbl[i])*2)
else
AddColumn(tbl.t_id, i, tbl[i], true, QTABLE_DOUBLE_TYPE, 10)
end
if doLogging then
STR=STR..tbl[i]..Sep
end
end
Logging("Дата Время".. Sep .. STR)
CreateWindow(tbl.t_id)
SetWindowCaption(tbl.t_id,tbl.caption)
SetTableNotificationCallback(tbl.t_id, f_cb)
end
function OnParam(class, sec)
if (class==ClassCode) and (WORK) and (string.find(SecList,sec)~=nil) then
G_ROW = Sec2row[sec]
if (G_ROW~=nil) and (G_ROW>=0) then
Highlight(tbl.t_id, G_ROW, QTABLE_NO_INDEX, RGB(255,0,0), QTABLE_DEFAULT_COLOR, INTERVAL)
CALC=true
end
end
end
function main()
WORK = false
CALC=true
for SecCode in string.gmatch(SecList, "([^,]+)") do --перебираем опционы по очереди.
local Optionbase=getParamEx(ClassCode,SecCode,"optionbase").param_image
local Optiontype=getParamEx(ClassCode,SecCode,"optiontype").param_image
if (string.find(BaseSecList,Optionbase)~=nil) then
local row = InsertRow(tbl.t_id,-1)
local T={
["Name"] = getSecurityInfo(ClassCode,SecCode).name,
["SecCode"] = SecCode,
["Optiontype"] = Optiontype,
["Optionbase"] = Optionbase,
["DAYS_TO_MAT_DATE"] = getParamEx(ClassCode,SecCode,"DAYS_TO_MAT_DATE").param_value+0
}
BaseCol[row]=T
--заполняем статичные параметры
Sec2row[SecCode]=row
SetCell(tbl.t_id, row, 1, BaseCol[row].Name) -- "Название опциона",
SetCell(tbl.t_id, row, 2, BaseCol[row].SecCode) --"Код опциона",
SetCell(tbl.t_id, row, 3, BaseCol[row].Optiontype) -- "Тип опциона",
SetCell(tbl.t_id, row, 4, BaseCol[row].Optionbase) --"Баз. актив",
--заказ данных
CreateDataSourceEX(BaseClassCode,T.Optionbase,"settleprice")
CreateDataSourceEX(ClassCode,T.SecCode,"strike")
CreateDataSourceEX(ClassCode,T.SecCode,"volatility")
--заполняем динамичные параметры
CALC=Calculate(row,true)
end
end
WORK = true
while WORK do
CALC=Calculate(G_ROW,CALC)
sleep(INTERVAL)
end
end
На бирже нет рыночных заявок по срочному рынку и никогда не было. То что в QUIK называется "рыночной" для срочного рынка, это обычная лимитированная заявка с признаком "Снять остаток" и указанной ценой. Если пользователь цену не указывает, то автоматом подставляется минимально/максимально возможная цена, в зависимости от направления.
На наш взгляд, Вам уже был дан ответ на этот вопрос с самого начала:
Цитата
Alexandr Shumilin написал: Добрый день! В разделе "Функции для работы с заявками" QPILE есть небольшой комментарий о том, что транзакции, выполняющие групповое снятие заявок, не поддерживаются: «KILL_ALL_ORDERS» – снять все заявки из торговой системы, «KILL_ALL_STOP_ORDERS» – снять все стоп-заявки, «KILL_ALL_NEG_DEALS» – снять все заявки на внебиржевые сделки и заявки на сделки РЕПО.
Алексей написал: 1.убрать ACCOUNT из перечня дополнительных параметров
На наш взгляд, для понимания фразы из документации
Цитата
"Параметр обязателен при «ACTION» = «KILL_ALL_FUTURES_ORDERS». "
вполне достаточно. убрать параметр из обязательных нельзя.
Цитата
Алексей написал: 2. для KILL_ALL_FUTURES_ORDERS указать следующие возможные дополнительные параметры: «OPERATION», «BASE_CONTRACT» и «???»
указать что? Они в документации есть.
Цитата
Алексей написал: Что это за градация заявок на рынке Forts?
Этот вопрос лучше задать специалистам биржи.
Цитата
Алексей написал: Как обозначаются сам параметр и его возможные значения при формировании заявки из qlua?
Для данного параметра константы не предусмотрено. Можно воспользоваться стандартным форматом полей транзакций, который можно увидеть если добавить транзакцию в "Карман транзакций" и от туда сохранить в tri файл. Открыв файл блокнотом Вы увидите как называются поля в стандартном формате. Смешивать форматы нельзя. В русском терминале только на русском, в английском, только на английском, менять нельзя.
Алексей написал: 1. Так все же ACCOUNT - это обязательный параметр или дополнительный? (можно ли не указывать ACCOUNT, чтобы, например, разом сбросить заявки и на основном счете и на инвестиционном?)
Обязательный.
Цитата
Алексей написал: 2. Из qlua KILL_ALL_FUTURES_ORDERS работает или нет?
Работает.
Цитата
Алексей написал: 3. «ACCOUNT», «OPERATION» являются единственными возможными параметрами для KILL_ALL_FUTURES_ORDERS, или можно применять и другие параметры, например, SECCODE?
В данной транзакции нет такого параметра SECCODE, (можно увидеть если откроете форму ввода транзакции в терминале). Есть только базовый актив.
Цитата
Алексей написал: 3-й вопрос обусловлен тем, что в том же руководстве в примерах есть следующее:
Возможность одновременно подключаться одним UID к разным серверам брокера есть. Но как Вы сами подметили это не безопасно, по разным причинам. В связи с чем если брокер не дает такую возможность, то имеет полное право.
Олег, Как уже было сказано указанные функции предназначены только для вызова внутри колбека. От того как Вы переставите слова в вопросе, ответ не поменяется.
Цитата
Олег написал: На момент компиляции CALLBACK функции, я не знаю, какие специальные функции мне понадобится потом вызывать.
Сделайте внутри колбека несколько разных функций, которые будут срабатывать по условию, каждая со своими спец функциями. Не видим проблем в этом.
Василий Артёмов, Функция getFuturesHolding берет данные из таблицы терминал "Позиции по клиентским счетам (фьючерсы)" В этой таблице есть параметр "Фирма", это и есть firm_id
Здравствуйте, Если нужно передать числа строкой, то добавлять значение в таблицу правильно так: SetCell(N, k, 0, tostring(хххххххххх),хххххххххх);
либо вообще переделать тип в строковый: AddColumn(N, 0, "ххххххх", true, QTABLE_CACHED_STRING_TYPE, 15); тогда можно оставить как есть SetCell(N, k, 0, хххххххххх);
но первый вариант лучше т.к. можно будет корректно сортировать/фильтровать данные в таблице через интерфейс, стандартным образом.
Здравствуйте, за формат отвечает строка "%d.%m.%Y" подробней о возможных вариантах можно прочесть по ссылке: http://www.lua.org/pil/22.1.html так, согласно ссылке, если указать
Здравствуйте, InsertRow нужно вызывать до SetCell и потом сама InsertRow умеет возвращает номер строки, который следует передать в SetCell, т.е. конструкция k = k+1 не требуется Для этого в качестве параметра key укажите -1 k=InsertRow(N,-1) SetCell(N, k, 0, хххххххххх); ...
Здравствуйте, Без кода, разобрать подобные обращения не представляется возможным. Что такое "флаг об открытии сделки"? Приведите пример кода, либо пришлите на quiksupport@arqatech.com указав ссылку на эту ветку форума.
Николай Камынин написал: Проблема следующая. Если в одном В одном окне несколько областей, то, при разной длине истории, на более коротких графиках будут пропущены начальные значения. В результате эти графики будут начинаться не с 1 , а с других в общем случае произвольных значений. Т е в скриптах индикаторов на этих графиках никогда не появится индекс равный единицы. Это усложняет обнаружение момента, когда индикатор перерисовывается при изменении его параметров.
Проблема не воспроизводится.
Код
Settings = {Name = "!TEST",line = {{}}}
function Init()
return #Settings.line
end
function OnCalculate(idx)
if idx==1 then
message("idx==1")
end
return C(idx)
end
Николай, В 7.10 в этом месте ничего не менялось. Изменения были, но в 7.7:
Цитата
Изменен вывод информации функциями O, H, L, C, V, T по свечкам, сформированным на пустых интервалах. Теперь, для таких свечек, функция T возвращает время интервала, а функции O, H, L, C, V возвращают nil. Для корректной проверки существования свечи на графике добавлена новая функция CandleExist().
Собственно, у нас на 7.10 ситуация не воспроизводится. Если требуется анализ, опишите подробней при каких обстоятельствах проявляется проблема.
philave написал: 2) Если мне нужно время гарантирующее, что все сделки, совершенные на бирже ранее этого времени уже учтены в quik, нужно использовать LASTRECORDTIME? Или можно SERVERTIME?
Время на сервере не обязано совпадать с биржевым. Попробуйте отказаться от ориентации на время сервера и смотреть скажем время последней сделки. Либо воспользуйтесь рекомендациями по указанной выше ссылке.
Проблемы с получением значения индикаторов., При чтении значения графика (индикатора) считывается "0" Раньше это было редким случаем, а теперь это гораздо больше половины значений!!!
Vadim Ivanov, Только учтите что время сервера также не обязано совпадать с временем биржи. Хотя у топовых брокеров за этим следят, но все же риски есть.