Вопросы по совместной работе, quik junior и доске опционов.

Страницы: 1
RSS
Вопросы по совместной работе, quik junior и доске опционов., Два пользователя за одним терминалом. Программный доступ к доске опционов ...
 
1. Как правильно настроить последовательную работу двух человек на одном терминале quik на одном компьютере в среде Windows7?
2. Subscribe_Level_II_Quotes работает в quik junior на опционах?
3. Как программно(на qlua) можно получить доступ к доске опционов?
 
Цитата
Андрей пишет:
1. Как правильно настроить последовательную работу двух человек на одном терминале quik на одном компьютере в среде Windows7?
Если брокер один, можно объединить ключи доступа от двух учетных записей (просто добавить информацию из одного файла secring.txk в другой) эти файлы открываются обычным блокнотом. При этом логины должны быть разными. После этого, сменить учетную запись можно будет путем смены логина при подключении. Если брокера разные то там немного сложнее, нужно будет дополнительно объединить файлы ip.cfg и pubring.txk
Цитата
Андрей пишет:
2. Subscribe_Level_II_Quotes работает в quik junior на опционах?
Использование функций не зависит от конкретного класса и сервера. Однако, если класс отключен, то работать функции по этому классу не будут.
Цитата
Андрей пишет:
3. Как программно(на qlua) можно получить доступ к доске опционов?
Программного доступа к этой таблице нет. Если интересует расчет греков, могу предложить пример расчета выполненный на LUA
 
Цитата
Sergey Gorokhov пишет:
Если интересует расчет греков, могу предложить пример расчета выполненный на LUA
Если не сложно, дайте пример расчёта греков.
Надо делать так, как надо. А как не надо - делать не надо.
 
Что делает:
  По Таблице текущих параметров строит таблицу опционов с рас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 = "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

 
Sergey Gorokhov, спасибо.
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
Sergey Gorokhov пишет:
Цитата
Андрей пишет:
1. Как правильно настроить последовательную работу двух человек на одном терминале quik на одном компьютере в среде Windows7?
Если брокер один, можно объединить ключи доступа от двух учетных записей (просто добавить информацию из одного файла secring.txk в другой) эти файлы открываются обычным блокнотом. При этом логины должны быть разными. После этого, сменить учетную запись можно будет путем смены логина при подключении. Если брокера разные то там немного сложнее, нужно будет дополнительно объединить файлы ip.cfg и pubring.txk
Цитата
Андрей пишет:
2. Subscribe_Level_II_Quotes работает в quik junior на опционах?
Использование функций не зависит от конкретного класса и сервера. Однако, если класс отключен, то работать функции по этому классу не будут.
Цитата
Андрей пишет:
3. Как программно(на qlua) можно получить доступ к доске опционов?
Программного доступа к этой таблице нет. Если интересует расчет греков, могу предложить пример расчета выполненный на LUA
1. Брокер один. Объединил ключи в одном файле - всё отлично работает. Спасибо.
3. За код большое спасибо!
2. Что-то у меня не выходит. Есть минимальный код:
Код
CLASS="SPBOPT"   --Код класса
SEC="RI95000BF5" --Код инструмента

is_run = true

function getOptionPrice()
    local qtable = getQuoteLevel2(CLASS, SEC)
    local bid = 0
    local offer = 0
    if qtable.bid_count+0 > 0 then
        bid = tonumber(qtable.bid[qtable.bid_count+0].price)    
    end
    if qtable.offer_count+0 > 0 then
        offer = tonumber(qtable.offer[1].price)             
    end
    message(bid .. " - " .. offer,1)
end

function main()
      --Subscribe_Level_II_Quotes(CLASS, SEC)
      while is_run do
            sleep(100)
      end
end

function OnQuote(CLASS, SEC)

    getOptionPrice()
end

function OnStop(stop_flag)
      is_run=false
end
Он работает при открытом стакане. Куда нужно писать Subscribe_Level_II_Quotes(CLASS, SEC)? Там, где я закомментировал выдает ошибку.
 
Цитата
Андрей пишет:
Он работает при открытом стакане. Куда нужно писать Subscribe_Level_II_Quotes(CLASS, SEC) ? Там, где я закомментировал выдает ошибку.
Скорее всего просто версия терминала старая. Эта функция появилась относительно недавно.
Попробуйте обновить версию через меню Связь - "Обновить версии программы"
 
Цитата
Sergey Gorokhov пишет:
Цитата
Андрей пишет:
Он работает при открытом стакане. Куда нужно писать Subscribe_Level_II_Quotes(CLASS, SEC) ? Там, где я закомментировал выдает ошибку.
Скорее всего просто версия терминала старая. Эта функция появилась относительно недавно.
Попробуйте обновить версию через меню Связь - "Обновить версии программы"
Ох, что-то я об этом не подумал. Да, Вы правы версия 6.12, а Subscribe_Level_II_Quotes появился в 6.15. Обновлений нет  :cry: . Плохо мое дело.
 
Цитата
Андрей пишет:
Обновлений нет . Плохо мое дело.
Как нет? У нас на Junior нет? или у брокера нет?
 
Цитата
Sergey Gorokhov пишет:
Цитата
Андрей пишет:
Обновлений нет . Плохо мое дело.
Как нет? У нас на Junior нет? или у брокера нет?
Я, так понимаю, что у брокера нет обновления Junior, только до версии 6.12.4.11...
 
Цитата
Андрей пишет:
Я, так понимаю, что у брокера нет обновления Junior, только до версии 6.12.4.11...
Тогда можете отправить нам запрос на адрес 911@quik.ru с просьбой выслать обновление и мы отправим.
 
Цитата
Sergey Gorokhov пишет:
Цитата
Андрей пишет:
Я, так понимаю, что у брокера нет обновления Junior, только до версии 6.12.4.11...
Тогда можете отправить нам запрос на адрес 911@quik.ru с просьбой выслать обновление и мы отправим.
Это здорово! Т.е. можно будет обновить терминал, и он обновленный сможет работать с игровым сервером моего брокера и проблем совместимости не возникнет?
 
Цитата
Андрей пишет:
Это здорово! Т.е. можно будет обновить терминал, и он обновленный сможет работать с игровым сервером моего брокера и проблем совместимости не возникнет?
с демо сервером не возникнет. а вот с боевым, есть риски что какой-нибудь плагин перестанет работать.
 
Подскажите, а можно ли теоретическую цену получать в реальном времени. Ведь она как-то расчитывается. Не поможете ли еще и с этим?
 
Цитата
Юрий пишет:
Подскажите, а можно ли теоретическую цену получать в реальном времени. Ведь она как-то расчитывается. Не поможете ли еще и с этим?
Добрый день.

Теоретическая цена рассчитывается биржей. Мы ее лишь транслируем.
 
Подписка на тему.
 
Constantin Constantin, чтобы подписаться на тему нет нужды оставлять в ней сообщение. Для этого возле названия темы специально есть слово "Подписаться"
 
Цитата
Дмитрий пишет:
Для этого возле названия темы специально есть слово " Подписаться "
тогда форум начнёт с..рать на e-mail уведомлениями))))
 
Меню "Избранное" в профиле не хватает.
Надо делать так, как надо. А как не надо - делать не надо.
 
Цитата
sam063rus пишет:
форум начнёт с..рать на e-mail уведомлениями
А разве не в этом смысл подписки?
Цитата
Старатель пишет:
Меню "Избранное" в профиле не хватает
Его с успехом может заменить меню "избранное" в браузере.
Если, конечно, не приходится пользоваться при чтении форума разными браузерами или разными компами.
 
Цитата
Дмитрий пишет:
А разве не в этом смысл подписки?
в наше время, определённо - НЕТ. Именно для этого создаются личные профили/кабинеты внутри сайтов - чтоб пользователь мог сам фильтровать поток, а не превращать e-mail в корзину для мусора. Не думаю, что информация здесь находящаяся нуждается в немедленной реакции (сродни смс-уведомлениям). Поэтому, если у пользователя находится время на чтение e-mail - то и на визит в свой личный профиль и "кликанье" по своему "избранному" - тоже найдётся.
Цитата
Дмитрий пишет:
Его с успехом может заменить меню "избранное" в браузере.
могу Вам сказать, что в моём браузере, в "моём избранном" - можно потеряться))))). И ведь, - всё как говорится: "надо" и ничего не выкинешь))))
Страницы: 1
Читают тему
Наверх