sam063rus пишет: честно говоря, ответ на троечку бо как тестируя обращения и пожелания, т.е. выявленные баги от пользователей на, как вы говорите, тестовых серверах, которые не ведут себя, как боевые - вы тем самым потом нам же и пишете, что мол де данная проблема, у вас не воспроизводится.
Расскажите, как по Вашему, что изменило бы в диагностике, если бы проблему воспроизводили на боевом потоке?
PFelix пишет: чтобы сервер QUIK передавал в поле Count номер строки таблицы изменения параметра по инструменту (если она на сервере хранится).
Не хранится
Цитата
PFelix пишет: Если эти предложения не выход, можете изложить в каком виде эти данные на сервере хранятся? Спасибо.
Они хранятся в том виде как приехали. И на рабочее место они приезжают в том же виде. Проблема возникает при попытке воспроизвести ту хронологию в которой эти данные приехали. И как сказал Михаил, сейчас мы УЖЕ работаем над тем чтобы эту проблему преодолеть. В виду сказанного не считаю разумным вести диалог дальше.
Максим Федоров пишет: Фоновый цвет графика, на котором отображаются эти две EMA.
Цвет фона графика менять нельзя. Можно менять цвет линии индикатора. В текущей версии это можно сделать если создать несколько линий, с заранее заданными цветами, и передавать значения только на одну из них, в зависимости от условия, а на остальные nil
Серж пишет: При отсутствии связи сервера с торговой системой клиенту ничего не приходит в ответ на транзакцию? А что со стоп-заявками? Для них ведь связь сервера с торговой системой биржи не нужна? (Мой случай был именно со стоп-заявками)
Не надо делать правила из возможной вероятности. То что у брокера были проблемы, уже говорит о том, что последствия этих проблем могут быть самыми разнообразными. В том числе и отсутствие ответа на транзакцию. Действительно, стоп заявки относятся к серверу брокера, а не к бирже. Однако, так как точно не известно, какие именно были проблемы у брокера, нельзя назвать причины по которым ответ на транзакцию выставления стоп заявки не был получен. Например, если Вы работали через сервер доступа, а основной сервер был недоступен. В любом случае, дальше играть в догадки не вижу смысла.
Не вижу противоречий. Вы сами сказали что были проблемы на стороне брокера. Я же точно указал как важнейшее условие "при наличии связи сервера с торговой системой" Если сможете пример когда ответ на транзакцию не пришел, но при этом у брокера и у Вас со связью было все хорошо, то это повод разбираться отдельно.
Viktor MMM пишет: 1. Всегда ли должен прийти ответ на транзакцию при наличии связи с сервером? Другими словами, значит ли отсутствие ответа в течение какого-то времени (какого?) что связи с сервером нет?
При наличии связи клиента с сервером и при наличии связи сервера с торговой системой, ответ на транзакцию приходит всегда.
Цитата
Viktor MMM пишет: 2. Верна ли логика, что если статус не 3, то значит она отвергнута?
Пользователь решает, вредна она или нет. Кому то, она может оказаться достаточной для решения поставленных задач а кому-то нет.
Цитата
Viktor MMM пишет: 3. Наличие статусов 0 и 1 говорит о том, что заявка подвисла и не обработана, но получена и, теоретически, может быть принята. Значит ли это, что надо просто подождать, получив эти статусы? Сколько ждать?
Пользователь сам должен решать сколько ждать. при синхронной подаче транзакций для этого даже есть специальный отдельный параметр.
Цитата
Viktor MMM пишет: 4. И, как результат, сообщите алгоритм, по которому можно 100% выяснить, что заявка прошла или не прошла.
Не понятно что значит "прошла" и "не прошла" Если Вы говорите про то сработала заявка (были сделки) или нет, извините по транзакции понять это не представляется возможным.
Если Вы имеете в виду, транзакция привела к выставлению заявки или нет, то если есть ответ на транзакцию и в этом ответе есть номер заявки, значит что на 100% эта транзакция была выполнена и привела к появлению заявки.
Дмитрий, Отсутствие функционала не является ошибкой. Ошибкой, можно считать любое девиантное поведение софта. А то, что поставленная Вами задача не решается из за отсутствия технической возможности, это не ошибка. В связи с чем, переквалифицировать мы ничего в этом месте не будем.
Добавить в функцию getQuoteLevel2() дополнительный возвращаемый параметр datetime, Вызывая функцию getQuoteLevel2() хотелось бы точно знать время когда произошли изменения в стакане, не привязываясь к локальному времени на клиенте.
Ваше пожелание зарегистрировано. Мы постараемся рассмотреть его и сообщить Вам результаты анализа. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожелания в будущих версиях ПО.
Серж пишет: В Отчёте по транзакциям фиксируется локальное время сервера QUIK?
Время шлюза.
Цитата
Серж пишет: Т.е., возможна такая ситуация, когда "Время получения на сервере QUIK" и "Время получения ответа торговой системы" больше, чем время заявки в таблице заявок?
Ситуация, когда заявка приходит раньше чем ответ на транзакцию вполне возможна. К стати, именно из за таких ситуаций, на одну заявку может придти повторный колбэк.
Здравствуйте, К сожалению, затруднюсь назвать причины. Возможно что то делаете не так. В соседней ветке, Вам рекомендовали для ознакомления статьи по теме корутинов.
Николай,Вам уже объяснили что информация в файле появится только после выполнения close() или flush() В Вашем коде нету flush() есть только close() который сработает в лучшем случае при остановке скрипта. Рекомендация остается прежней, добавьте команду file:flush() сразу после file:write
Поле "COMMENT" служит для того чтобы снимать заявки по условию, а не для того чтобы задать комментарий. Комментарий задается в параметре CLIENT_CODE после кода клиента, нужно указать знак "/" или "//" (зависит от настроек брокера) а потом уже указывать комментарий.
Создание таблицы текущая прибыль/убыток и высчитывать по позициям в терминале, Сегодня невозможно понять текущее состояние счета, пересчет происходит с долгими задержкам, что добавляет еще большего психологического давления
Интервал расчета вар маржи настраивается на стороне биржи. Для каждого подключения индивидуально. К сожалению, у нас нет возможности повлиять на решение уменьшить интервал расчета. Мы можем только рекомендовать брокеру обратиться на биржу с этим вопросом. Далее уже брокер, совместно со специалистами биржи, решает следовать рекомендациям или нет. Еще, можем предложить пример расчета вариационки:
Цитата
Вариационная маржа (ВМ) по фьючерсу на Индекс РТС рассчитывается по следующим формулам:
В ходе дневной клиринговой сессии:
В случае, если расчет вариационной маржи по контракту ранее не осуществлялся: ВМ1 = (РЦ1 – ЦО) x W1 : R
В случае, если расчет ВМ осуществлялся ранее: ВМ1 = (РЦ1 – РЦП) x W1 : R
В ходе вечерней клиринговой сессии:
В случае, если расчет вариационной маржи по контракту ранее не осуществлялся: ВМ2 = (РЦ2 – ЦO) x W2 : R
В случае, если расчет ВМ осуществлялся ранее: ВМ2 = ВМ – ВМ1
При этом величина ВМ рассчитывается по следующим формулам (и округляется с точностью до копеек по правилам математического округления):
В случае, если расчет вариационной маржи по контракту до дневной клиринговой сессии текущего торгового дня не осуществлялся: ВМ = (РЦ2 – ЦO) x W2 : R
В случае, если расчет ВМ в ходе дневной клиринговой сессии текущего торгового дня осуществлялся: ВМ = (РЦ2– РЦП) x W2 : R
Где: ВМ1 — вариационная маржа по контракту, рассчитанная в ходе дневной клиринговой сессии текущего торгового дня,
ВМ2 — вариационная маржа по контракту, рассчитанная в ходе вечерней клиринговой сессии за вечерний расчетный период текущего торгового дня,
ВМ — вариационная маржа по контракту, рассчитанная в ходе вечерней клиринговой сессии за текущий торговый день,
РЦП — расчетная цена контракта, определенная по итогам вечернего расчетного периода предыдущего торгового дня,
W1 — стоимость минимального шага цены, используемая в ходе дневной клиринговой сессии,
W2 — стоимость минимального шага цены, используемая в ходе вечерней клиринговой сессии,
R — минимальный шаг цены.
В приведенных выше формулах расчета вариационной маржи можно заменить блок, отвечающий за перевод фьючерсных пунктов в рубли, на более привычный долларовый эквивалент: W : R = 0,02 x курс USD/RUR, рассчитанный согласно Методике ФБ РТС (fs.rts.ru/files/5307).
Рассмотрим пример расчета вариационной маржи при проведении операций с фьючерсом на Индекс РТС.
Пример 1 Участник торгов в 14:45 купил 1 фьючерс на Индекс РТС по цене 132 700 пунктов. В 18:45 МСК, перед началом клиринга, расчетная цена (fs.rts.ru/files/2892) (цена последней сделки) инструмента составила 135 200 пунктов. Курс доллара США к российскому рублю, рассчитанный согласно упомянутой выше Методике . (fs.rts.ru/files/5307), на 16:30 МСК составил 30,2765 рубля. По итогам клиринга участник получит следующий финансовый результат: (135 200 – 132 700) x 0,02 x 30,2765 = 1 513,82 рубля. При этом размер гарантийного обеспечения на следующий торговый период (с 19:00 до 14:00 МСК) будет установлен исходя из расчетной цены, определенной по итогам завершившейся сессии (в 18:45 МСК), и будет равен: 135 200 x 0,02 x 30,2765 x 7,5% = 6 140,07 рубля. Поскольку фьючерс на Индекс РТС является расчетным, его исполнение происходит в вечернем клиринговом сеансе в последний день обращения путем перечисления/ списания денежных средств. Это означает, что в день исполнения участники торгов, не закрывшие позиции противоположными (офсетными) сделками перед вечерним клиринговым сеансом, получают положительную или отрицательную вариационную маржу за последний день торгов на основе расчетной цены контракта в этот день.
Пример 2 Участник торгов в 14:30 МСК последнего дня обращения контракта, 11 июня 2010 года, купил фьючерс на Индекс РТС по цене 135 050 пунктов и удерживал позицию до закрытия сессии. Среднее значение Индекса РТС с 15:00 до 16:00 МСК в этот день составило 1 355,10 пункта. Соответственно, расчетная цена была зафиксирована на уровне: 1 355,10 x 100 = 135 510 пунктов. В этом случае вариационная маржа, начисленная участнику торгов в итоговом клиринге, составила: (135 510 – 135 050) x 0,02 x 30,7246 = 282,67 рубля.
Здравствуйте, В одной из старых версий была такая беда, наблюдалась в основном на больших мониторах. Для решения проблемы, обновите терминал до последней версии. На текущий момент это 6.17
Здравствуйте, К сожалению, мы не можем дать консультацию по данному вопросу. Попробуйте поискать ответ на каком-либо форуме посвященному написанию DDE серверов
Создание таблицы текущая прибыль/убыток и высчитывать по позициям в терминале, Сегодня невозможно понять текущее состояние счета, пересчет происходит с долгими задержкам, что добавляет еще большего психологического давления
Вячеслав пишет: Finrise (Инстройинвест), Открытие - также ссылаются на разработчиков ПО. Открытие даже обновление QUIK делают с задержкой 2-3 версии. У них до сих пор 6.16(42)
Вопрос был адресован другому пользователю. Или у Вас тоже задержки в трансляции маржи?
Создание таблицы текущая прибыль/убыток и высчитывать по позициям в терминале, Сегодня невозможно понять текущее состояние счета, пересчет происходит с долгими задержкам, что добавляет еще большего психологического давления
Создание таблицы текущая прибыль/убыток и высчитывать по позициям в терминале, Сегодня невозможно понять текущее состояние счета, пересчет происходит с долгими задержкам, что добавляет еще большего психологического давления
Вариационная маржа, судя по всему, считается на сервере, поэтому и задержки, надо чтобы отдельный скрипт непосредственно в клиентском терминале рассчитывал разницу пунктов с ценой открытия и выводил в таблицу клиентский портфель, например. Можно назвать "оперативная вар. маржа"
Вы не говорили что речь про ФОРТС. Указанная настройка в этом случае и не должна была помочь. Так как она влияет только на клиентский портфель в котором считаются показатели фондовой секции. Вар маржа считается не на сервере, а на бирже. Никаких задержек с расчетом Вар маржи не должно быть, если они имеются это может говорить о проблемах на стороне брокера. Уточните Вы обращались к брокеру? Что он ответил?
Создание таблицы текущая прибыль/убыток и высчитывать по позициям в терминале, Сегодня невозможно понять текущее состояние счета, пересчет происходит с долгими задержкам, что добавляет еще большего психологического давления
rozmin пишет: На сегодняшний день расчет происходит раз в n-ое количество времени, что так-же вносит путаницу в реалиях. Спасибо.
Здравствуйте, Попробуйте в меню Настройки - Основные - Торговля - Клиентский портфель поставить галку "Пересчитывать при изменении позиций" И в поле "Обновлять через каждые … секунд" укажите 0
Андрей пишет: Это здорово! Т.е. можно будет обновить терминал, и он обновленный сможет работать с игровым сервером моего брокера и проблем совместимости не возникнет?
с демо сервером не возникнет. а вот с боевым, есть риски что какой-нибудь плагин перестанет работать.
Серж пишет: Sergey Gorokhov , отметьте также об отсутствии потокобезопасности предложенного вами способа. А то ведь ещё один человек по этим "граблям пройдётся".
да ладно, а как же Потокобезопасные функции для работы с таблицами Lua
Цитата
Одновременная работа с таблицами из функций обратного вызова скрипта и функции main() может приводить к неопределенным ситуациям. Для решения этой проблемы qlua.dll предоставляет потокобезопасные аналоги стандартных функций Lua.
Формат вызова потокобезопасной функции совпадает с форматом вызова аналогичной стандартной функции Lua.
В таблице представлены стандартные функции Lua и соответствующие им потокобезопасные аналоги:
Стандартная функция Lua concat remove insert sort
Потокобезопасная функция sconcat sremove sinsert ssort
Андрей пишет: Он работает при открытом стакане. Куда нужно писать Subscribe_Level_II_Quotes(CLASS, SEC) ? Там, где я закомментировал выдает ошибку.
Скорее всего просто версия терминала старая. Эта функция появилась относительно недавно. Попробуйте обновить версию через меню Связь - "Обновить версии программы"
Еще задачу можно решить через скрипт LUA. Полученную таблицу вынести за пределы главного окна и свернуть
Код
--НАСТРОЙКИ:
CLASS="TQBR" --код класса
SECUR="LKOH" --код инструмента
PARAM="last" --параметр из ТТП
--ТО ЧТО НИЖЕ ТРОГАТЬ НЕ НАДО
not_stopped = nil
t_id=0
ds=nil
lRow=nil
function OnStop(stop_flag)
ds:Close()
DestroyTable(t_id)
not_stopped = false
end
function OnInit(script_path)
t_id=AllocTable()
AddColumn(t_id,1,PARAM,true,QTABLE_STRING_TYPE,30)
CreateWindow(t_id)
lRow = InsertRow(t_id, 1)
SetSelectedRow(t_id, lRow)
not_stopped = true
top, left, bottom, right = GetWindowRect(t_id)
width=227
height=68
SetWindowPos(t_id, left, top, width, height)
ds,err = CreateDataSource(CLASS, SECUR, INTERVAL_TICK, PARAM)
if ds==nil then
message("Ошибка при получении параметра "..PARAM..":\n"..err, 3)
else
ds: SetUpdateCallback(cb)
end
end
function cb(index)
if index==ds:Size() then
SetWindowCaption(t_id,SECUR.."="..tostring(ds:C(index)))
SetCell(t_id, lRow, 1, tostring(ds:C(index)))
end
end
function main()
while not_stopped do
if IsWindowClosed(t_id) then
OnStop()
end
end
end
Иван Кешиков пишет: Это абсолютно не то, что нужно. Вот открыт у меня к примеру браузер на весь экран, или фотошоп - квик не видно, а панель задач всегда на виду.
Если задача стоит смотреть какой-то один параметр, можно вынести таблицу с ним за пределы терминала и сделать поверх всех окон. тогда он будет виден поверх панели задач или браузера.
Как использовать: откройте Таблицу Текущих Параметров (меню Таблицы -> Текущая Таблица) Укажите настройки, после чего, запустите скрипт (меню Таблицы - Lua - Доступные скрипты) чтобы сохранить в CSV файл, текущее состояние таблицы, нужно нажать комбинацию клавиш Ctrl+S файл сохраняется в папку со скриптом, с именем HHHMMDD.csv
Код
-------------------------------НАСТРОЙКИ-------------------------------
RiskFree=0/100 --безрисковая ставка %, Указывается вручную
BaseClassCode = "SPBFUT" --Класс базового актива
ClassCode = "SPBOPT" --Класс опционов
--Список базовых активов, через запятую, по которым отображать опционы:
BaseSecList = "RIZ4" --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 getParamValue(Class,Sec,Par)
local result={}
--делаем предварительный заказ данных
local ds,err = CreateDataSource(Class, Sec, INTERVAL_TICK, Par)
if ds==nil then
message("Ошибка при получении параметра "..Par..":\n"..err, 3)
return 0
else
ds:SetUpdateCallback(function() end)
result=getParamEx(Class,Sec,Par)
ds:Close()
return result.param_value+0
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"] = getParamValue(BaseClassCode,T.Optionbase,"settleprice"),
["strike"] = getParamValue(ClassCode,T.SecCode,"strike"),
["volatility"] = getParamValue(ClassCode,T.SecCode,"volatility"),
["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) -- "Ро",
Logging(os.date().. Sep .. GetRow(tbl.t_id,row))
end
return false
end
-------------------------------Колбэки------------------------------------------------------------------
function f_cb(t_id,msg,par1,par2) --событие на нажатие клавиш
if (msg==QTABLE_CHAR) and (par2==19) then --сохранить в CSV файл текущее состояние таблицы нужно нажать комбинацию клавиш Ctrl+S
CSV(t_id)
end
if (msg==QTABLE_CLOSE) then --закрытие окна
Stop()
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) --"Баз. актив",
--заполняем динамичные параметры
CALC=Calculate(row,CALC)
end
end
WORK = true
while WORK do
CALC=Calculate(G_ROW,CALC)
sleep(INTERVAL)
end
end
Андрей пишет: 1. Как правильно настроить последовательную работу двух человек на одном терминале quik на одном компьютере в среде Windows7?
Если брокер один, можно объединить ключи доступа от двух учетных записей (просто добавить информацию из одного файла secring.txk в другой) эти файлы открываются обычным блокнотом. При этом логины должны быть разными. После этого, сменить учетную запись можно будет путем смены логина при подключении. Если брокера разные то там немного сложнее, нужно будет дополнительно объединить файлы ip.cfg и pubring.txk
Цитата
Андрей пишет: 2. Subscribe_Level_II_Quotes работает в quik junior на опционах?
Использование функций не зависит от конкретного класса и сервера. Однако, если класс отключен, то работать функции по этому классу не будут.
Цитата
Андрей пишет: 3. Как программно(на qlua) можно получить доступ к доске опционов?
Программного доступа к этой таблице нет. Если интересует расчет греков, могу предложить пример расчета выполненный на LUA
Reshpekt Fund Russia пишет: Пользователь нашёл баг и теперь как попка бегает между биржей и аркой, пытаясь достучаться. Мне не важно, из-за кого, мне важно, чтобы пришло в норму.
Виктор, На Ваш вопрос, можно ли застопроприть событие так, чтобы накопиться очередь, а потом она продолжилась, то ответ можно, включив бесконечный цикл в событии. Но это приведет к зависанию всего терминала. Если Вам нужно обрабатывать данные которые поступили за время работы функции main без зависаний, используйте стороннее хранилище поступающих данных
Viktor MMM пишет: Происходит событие. Вы говорите, что терминал подвисает и начинает его обрабатывать. Мне же надо, чтобы при возникновении события сначала доработала какая -то моя функция, а потом уже пошла обработка события. Причем по моему выбору. В каких-то для меня критичных местах. То есть не код в событии продолжал работать, а, например, тот же main. Доработал бы до какого-то места, а потом бы разрешил обработать событие. Это возможно?
Вы можете установить на входе и выходе своей функции какую-нибудь переменную флаг, и пропускать обработку событий пока флаг не примет нужного значение.
Цитата
Viktor MMM пишет: я мог бы конечно отсечь влияние событий глобальным флагом, но хотелось бы, чтоб событие не терялось а в очередь вставало и отработало в итоге.
Это нельзя сделать, так как появление очереди приведет к полному отказу в работе терминала.
Viktor MMM пишет: Работает скрипт, происходит событие. Скрипт прерывается и включается обработка? А потом скрипт продолжает работу?
Все события работают в основном потоке терминала. таким образом пока что-то делается в каком-то событии, в терминале ничего не происходит. Он даже может повиснуть.
Цитата
Viktor MMM пишет: Как сделать так, чтобы пока, например, функция не выполнится, обработка не выполнялась? В тех случаях, когда мне так надо.
Этот вопрос совершенно не понятен. Вы имеете в виду, чтобы "пока код в событии работает, функция main останавливала работу"?
Здравствуйте, Вы можете вынести нужные окна за пределы главного окна терминала и назвать их как угодно В руководстве: -Раздел 2. Основные принципы работы с программой --Работа с окнами ---Вынесенные окна
Eldar пишет: и вопрос про функцию Subscribe_Level_II_Quotes по моему мнению тоже резонный.
На вопрос где лучше использовать Subscribe_Level_II_Quotes у нас нет и не может быть ответа. Так как этот вопрос зависит от Вашего видения работы программы. Можно даже сказать от Вашего вкуса.
Eldar пишет: Спасибо. что-то проясняется. например найден BREAK. но так как документация скудная, появился следующий вопрос.
По поводу документации объясняю. Язык LUA придумали НЕ мы. Мы взяли готовый язык и добавили в него несколько наших функций. Поэтому в НАШЕЙ документации только НАШИ функции. Все функции которые являются стандартными для языка LUA описаны в документации на язык LUA, которая есть в интернете: http://www.lua.org/docs.html
BREAK приводит к выходу из цикла. Подробнее в документации на LUA
Eldar пишет: дело в том, что не понятно как работает функция Subscribe_Level_II_Quotes:
вызов Subscribe_Level_II_Quotes аналогичен открытию стакана в терминале QUIK. Без открытия стакана данные в него не поступают. Соответственно OnQuote и getQuoteLevel2 работать не будут
Цитата
Eldar пишет: в этой функции я могу пометить is_run как false и не обрабатывать в main, но скрипт все еще будет запущен.
Это значит что Вы не понимаете как работает IsWindowClosed Напишите в функции Quotes так:
Код
function Quotes(code)
sleep(150)
for i=1, shares_count do
if IsWindowClosed(t) then
is_run=false
break
end
--остальной код