<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[QUIK -> DDE &mdash; Опционы - полезные функции]]></title>
		<link>https://quik2dde.ru/viewtopic.php?id=287</link>
		<atom:link href="https://quik2dde.ru/extern.php?action=feed&amp;tid=287&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «Опционы - полезные функции».]]></description>
		<lastBuildDate>Thu, 20 Aug 2020 16:36:06 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: Опционы - полезные функции]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2824#p2824</link>
			<description><![CDATA[<p>local last = getParamEx(&quot;SPBOPT&quot;, &quot;Si74500BI0&quot;, &quot;last&quot;).param_value<br />нужно понимать, что по опционам может не быть сделок, совсем.</p>]]></description>
			<author><![CDATA[null@example.com (kalikazandr)]]></author>
			<pubDate>Thu, 20 Aug 2020 16:36:06 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2824#p2824</guid>
		</item>
		<item>
			<title><![CDATA[Re: Опционы - полезные функции]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2823#p2823</link>
			<description><![CDATA[<p>Скажите, если несложно, а как получить цену последней сделки опциона?</p>]]></description>
			<author><![CDATA[null@example.com (v-poned)]]></author>
			<pubDate>Thu, 20 Aug 2020 15:25:39 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2823#p2823</guid>
		</item>
		<item>
			<title><![CDATA[Re: Опционы - полезные функции]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2417#p2417</link>
			<description><![CDATA[<p>&quot;Лишнее&quot; убрал<br /></p><div class="codebox"><pre><code>   local e = math.exp(-D) -- Эту хрень убираем из формулы получаем нормальные значения греков

   local Theor_C = 0; local Theor_P = 0
   if Price_Opt then
      Theor_C = round(F * N(d1) - S * N(d2), k) -- Расчетная теоретичексая цена Call
      Theor_P = round(Theor_C + S - F, k) -- Расчетная теоретичексая цена Put
   else
      Theor_C = tonumber(getParamEx(Class_Opt, sec, &quot;theorprice&quot;).param_value) -- Биржевая теоретическая цена Call
      Theor_P = tonumber(getParamEx(Class_Opt, sec, &quot;theorprice&quot;).param_value) -- Биржевая теоретическая цена Put
   end

function Opt(sec) -- Функция считает параметры опциона
   local F = tonumber(getParamEx(&quot;SPBFUT&quot;, Fut, &quot;settleprice&quot;).param_value) -- Цена фьючерса
   local S = tonumber(getParamEx(&quot;SPBOPT&quot;, sec, &quot;strike&quot;).param_value) -- Страйк опциона
   local Vola = Round(tonumber(getParamEx(&quot;SPBOPT&quot;, sec, &quot;volatility&quot;).param_value), 3) -- Волатильность опциона
   local V = tonumber(getParamEx(&quot;SPBOPT&quot;, sec, &quot;volatility&quot;).param_value) / 100 -- Волатильность опциона в долях года
   local D = tonumber(getParamEx(&quot;SPBOPT&quot;, sec, &quot;days_to_mat_date&quot;).param_value) / Year -- Число дней до погашения в долях года
   local d1 = (math.log(F / S) + 0.5 * V * V * D) / (V * math.sqrt(D))
   local d2 = d1 - V * math.sqrt(D)
   local e = math.exp(-D) -- Эту хрень убираем из формулы получаем нормальные значения греков

   local Gamma = Round(100 * pN(d1) / (F * V * math.sqrt(D)), 6)
   local Vega = Round(F * e * pN(d1) * math.sqrt(D) / 100, 0)

   local Theta = (-F * V * e * pN(d1)) / (2 * math.sqrt(D))
   local C_Delta = Round(e * N(d1), 3) -- Дельта Call
   local C_Theta = Round((Theta - (S * e * N(d2)) + F * e * N(d1)) / Year, 0) -- Тета Call
   local C_Rho = S * D * e * N(d2) / 100

   local P_Delta = Round(-e * N(-d1), 3) -- Дельта Put
   local P_Theta = Round((Theta + (S * e * N(-d2)) - F * e * N(-d1)) / Year, 0) -- Тета Put
   local P_Rho = -S * D * e * N(-d2) / 100
   return {[&quot;Vola&quot;] = Vola, [&quot;Gamma&quot;] = Gamma, [&quot;Vega&quot;] = Vega,
           [&quot;C_Delta&quot;] = C_Delta, [&quot;C_Theta&quot;] = C_Theta, [&quot;C_Rho&quot;] = C_Rho,
           [&quot;P_Delta&quot;] = P_Delta, [&quot;P_Theta&quot;] = P_Theta, [&quot;P_Rho&quot;] = P_Rho}
end
function N(x) -- Функция стандартного нормального распределения
   if x &gt; 10 then return 1
   elseif x &lt; -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 &gt; 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 Round(num, idp) -- Функция округляет до указанного количества знаков
   local mult = 10^(idp or 0)
   return math.floor(num * mult + 0.5) / mult
end</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Reym)]]></author>
			<pubDate>Sat, 27 Jul 2019 07:46:18 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2417#p2417</guid>
		</item>
		<item>
			<title><![CDATA[Re: Опционы - полезные функции]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2416#p2416</link>
			<description><![CDATA[<p>С форума квика (если кому греки нужны)<br /></p><div class="codebox"><pre><code>--[[
Что делает:
   По Таблице текущих параметров строит таблицу опционов с расcчитанными греками

Как использовать:
   откройте Таблицу Текущих Параметров (меню Таблицы -&gt; Текущая Таблица)
   Укажите настройки, после чего, запустите скрипт (меню Таблицы - Lua - Доступные скрипты)
   чтобы сохранить в CSV файл, текущее состояние таблицы, нужно нажать комбинацию клавиш Ctrl+S файл сохраняется в папку со скриптом, с именем HHHMMDD.csv
]]
-------------------------------НАСТРОЙКИ-------------------------------
RiskFree=0/100 --безрисковая ставка %, Указывается вручную

BaseClassCode = &quot;SPBFUT&quot; --Класс базового актива
ClassCode = &quot;SPBOPT&quot; --Класс опционов

--Список базовых активов, через запятую, по которым отображать опционы:
BaseSecList = &quot;SRM7&quot; --getClassSecurities(BaseClassCode) --все сразу
 
--Список опционов через запятую:
SecList = getClassSecurities(ClassCode) --все сразу

INTERVAL = 1000 --Интервал обновления таблицы

doLogging=false --включает запись в файл, формата csv. 
log_file=getScriptPath() .. &quot;\\Greek.csv&quot; --путь к csv файлу 

-----------------------------------------------------------------------

-------------------------------ТО ЧТО НИЖЕ, ТРОГАТЬ НЕ НАДО------------------------------------------------------------------
--Параметры таблицы
tbl = {
[&quot;caption&quot;]=&quot;Greek&quot;,
[1]=&quot;Название&quot;,
[2]=&quot;Код опциона&quot;,
[3]=&quot;Тип опциона&quot;,
[4]=&quot;Баз. актив&quot;,
[5]=&quot;Расчетная цена&quot;,
[6]=&quot;Страйк&quot;,
[7]=&quot;Волатильность&quot;,
[8]=&quot;До исполнения&quot;,
[9]=&quot;Дельта&quot;,
[10]=&quot;Гамма(%)&quot;,
[11]=&quot;Тэта&quot;,
[12]=&quot;Вега&quot;,
[13]=&quot;Ро&quot;,
[&quot;t_id&quot;]=0
}

abTable = {}
BaseCol = {}
Sec2row = {}
file = nil
Sep = &quot;;&quot;
YearLen=365.0 --Число дней в году
WORK = true
CALC = false
G_ROW = -1
if (BaseSecList == &quot;&quot;) or (BaseSecList == nil) then
   BaseSecList = getClassSecurities(BaseClassCode)
end

if (SecList == &quot;&quot;) or (SecList == nil) then
   SecList = getClassSecurities(ClassCode)
end

-------------------------------ФУНКЦИИ------------------------------------------------------------------
function Logging(str) --Пишет лог
   if file~=nil and doLogging then
      file:write(str .. &quot;\n&quot;)
      file:flush()
   end
end

function N(x) --Нормальное среднее
    if (x &gt; 10) then
      return 1
   elseif (x &lt; -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 &gt; 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 --&quot;b&quot; волатильность доходности (квадратный корень из дисперсии) базисной акции.
   local S = tmpParam.settleprice --&quot;S&quot; текущая цена базисной акции;
   local Tt = tmpParam.DAYS_TO_MAT_DATE / YearLen --&quot;T-t&quot; время до истечения срока опциона (период опциона);
   local K =  tmpParam.strike --&quot;K&quot; цена исполнения опциона;
   local r = RiskFree --&quot;r&quot; безрисковая процентная ставка;
   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 == &quot;Call&quot; 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 {
   [&quot;Delta&quot;] = Delta,
   [&quot;Gamma&quot;] = 100 * Gamma,
   [&quot;Theta&quot;] = Theta / YearLen,
   [&quot;Vega&quot;] = Vega / 100,
   [&quot;Rho&quot;] = Rho / 100
   }
end

function GetRow(ID,row) --возвращает строку таблицы
local rows, col = GetTableSize(ID)
local result = &quot;&quot;
if rows~=nil and row&lt;=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=&quot;0&quot;.. V
      end
      return V  
   end
local temp = os.date(&quot;*t&quot;)
local Fname =getScriptPath() .. &quot;\\&quot; .. FTEXT(temp.year) .. FTEXT(temp.month) .. FTEXT(temp.day) .. &quot;.csv&quot;
   CSVFile = io.open(Fname, &quot;w+&quot;)
   if CSVFile~=nil then
      local rows, col = GetTableSize(T.t_id)
      for i=1,col do --расставляем заголовки
         CSVFile:write(T[i] .. Sep)
      end
      CSVFile:write(&quot;\n&quot;)
      for i=1,rows do --пишем таблицу
         CSVFile:write(GetRow(T.t_id,i)..&quot;\n&quot;)
      end      
      CSVFile:flush()
      CSVFile:close()
      message(&quot;Файл успешно сохранен:\n&quot;..Fname, 1)
   else 
      message(&quot;Ошибка при сохранении файла:\n&quot;..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,&#039;^([^%d]*%d)(%d*)(.-)$&#039;)
   return left..(num:reverse():gsub(&#039;(%d%d%d)&#039;,&#039;%1 &#039;):reverse())..right
end

function CreateDataSourceEX(Class,Sec,Par)
   local ds,err = CreateDataSource(Class, Sec, INTERVAL_TICK, Par)
   if ds==nil then
      message(&quot;Ошибка при получении параметра &quot;..Par..&quot;:\n&quot;..err, 3)
      return false
   else
      ds:SetEmptyCallback()
      while ds:Size()==0 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&gt;=0) and (do_calc) then

         local T=BaseCol[row]

         local tmpParam ={
            [&quot;Optiontype&quot;] = T.Optiontype,
            [&quot;settleprice&quot;] = getParamEx(BaseClassCode,T.Optionbase,&quot;settleprice&quot;).param_value+0,
            [&quot;strike&quot;] = getParamEx(ClassCode,T.SecCode,&quot;strike&quot;).param_value+0,
            [&quot;volatility&quot;] = getParamEx(ClassCode,T.SecCode,&quot;volatility&quot;).param_value+0,
            [&quot;DAYS_TO_MAT_DATE&quot;] = T.DAYS_TO_MAT_DATE
         }
         local tmpGreek = Greek(tmpParam)
         SetCell(tbl.t_id, row, 5, comma_value(tmpParam.settleprice), tmpParam.settleprice) -- &quot;Расчетная цена&quot;,
         SetCell(tbl.t_id, row, 6, comma_value(tmpParam.strike), tmpParam.strike) --&quot;Страйк&quot;,
         SetCell(tbl.t_id, row, 7, tostring(tmpParam.volatility), tmpParam.volatility) -- &quot;Волатильность&quot;,
         SetCell(tbl.t_id, row, 8, tostring(tmpParam.DAYS_TO_MAT_DATE), tmpParam.DAYS_TO_MAT_DATE) --&quot;До исполнения&quot;,
         SetCell(tbl.t_id, row, 9, tostring(round(tmpGreek.Delta,2)), tmpGreek.Delta) --&quot;Дельта&quot;,
         SetCell(tbl.t_id, row, 10, tostring(round(tmpGreek.Gamma,4)), tmpGreek.Gamma) -- &quot;Гамма(%)&quot;,
         SetCell(tbl.t_id, row, 11, tostring(round(tmpGreek.Theta,2)), tmpGreek.Theta) -- &quot;Тэта&quot;,
         SetCell(tbl.t_id, row, 12, tostring(round(tmpGreek.Vega,2)), tmpGreek.Vega) -- &quot;Вега&quot;,
         SetCell(tbl.t_id, row, 13, tostring(round(tmpGreek.Rho,2)), tmpGreek.Rho) -- &quot;Ро&quot;,
         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(tbl)
   end
   if (msg==QTABLE_CLOSE) then --закрытие окна
      Stop()
   end
end

function OnStop()
   Stop()
   DestroyTable(tbl.t_id)
end

function OnInit()
local STR = &quot;&quot;
   if doLogging then 
      file = io.open(log_file, &quot;w+&quot;) 
   end
   tbl.t_id = AllocTable()
   for i=1,table.maxn(tbl) do --добавляем колонки
      if i&lt;=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(&quot;Дата Время&quot;.. 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&gt;=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, &quot;([^,]+)&quot;) do --перебираем опционы по очереди.
            local Optionbase=getParamEx(ClassCode,SecCode,&quot;optionbase&quot;).param_image
            local Optiontype=getParamEx(ClassCode,SecCode,&quot;optiontype&quot;).param_image
            if (string.find(BaseSecList,Optionbase)~=nil) then
               local row = InsertRow(tbl.t_id,-1)
               local T={
                  [&quot;Name&quot;] = getSecurityInfo(ClassCode,SecCode).name,
                  [&quot;SecCode&quot;] = SecCode,
                  [&quot;Optiontype&quot;] = Optiontype,
                  [&quot;Optionbase&quot;] = Optionbase,
                  [&quot;DAYS_TO_MAT_DATE&quot;] = getParamEx(ClassCode,SecCode,&quot;DAYS_TO_MAT_DATE&quot;).param_value+0
                  }
               BaseCol[row]=T
               --заполняем статичные параметры
               Sec2row[SecCode]=row
               SetCell(tbl.t_id, row, 1, BaseCol[row].Name) -- &quot;Название опциона&quot;,
               SetCell(tbl.t_id, row, 2, BaseCol[row].SecCode) --&quot;Код опциона&quot;,
               SetCell(tbl.t_id, row, 3, BaseCol[row].Optiontype) -- &quot;Тип опциона&quot;,
               SetCell(tbl.t_id, row, 4, BaseCol[row].Optionbase) --&quot;Баз. актив&quot;,
               --заказ данных
               CreateDataSourceEX(BaseClassCode,T.Optionbase,&quot;settleprice&quot;)
               CreateDataSourceEX(ClassCode,T.SecCode,&quot;strike&quot;)
               CreateDataSourceEX(ClassCode,T.SecCode,&quot;volatility&quot;)

               --заполняем динамичные параметры
               CALC=Calculate(row,true) 
            end
   end
WORK = true
while WORK do
   CALC=Calculate(G_ROW,CALC)
   sleep(INTERVAL)
end
end</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Reym)]]></author>
			<pubDate>Sat, 27 Jul 2019 07:40:37 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2416#p2416</guid>
		</item>
		<item>
			<title><![CDATA[Опционы - полезные функции]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2343#p2343</link>
			<description><![CDATA[<p>Недавно занимаюсь опционами, набросал пару функций, может кому пригодится, может кто дополнит.<br /></p><div class="codebox"><pre><code># forts.lua

local tonumber = tonumber
local math_abs, math_sqrt, math_exp, math_max, math_log = math.abs, math.sqrt, math.exp, math.max, math.log
local pi = math.pi

local forts = {}

local function N(x)
    -- Функция стандартного нормального распределения
   if x &gt; 10 then return 1 end
   if x &lt; -10 then return 0 end
   local ax = math_abs(x)
   local t = 1 / (1 + 0.2316419 * ax)
   local d = 1 / math_sqrt(2 * pi) * math_exp(-x * x / 2)
   local p = d * t * ((((1.330274429 * t - 1.821255978) * t + 1.781477937) * t - 0.356563782) * t + 0.31938153)
   if x &gt; 0 then return 1 - p else return p end
end
function forts.Black_Scholes(F, S, V, T)
-- F: Текущая цена фьючерса
-- S: Страйк
-- V: Волатильность
-- T: Время в долях года до окончания срока действия опциона (4 / 365)
    if T &lt;= 0 then
        local Call = math_max(F - S, 0)
        local Put = Call + S - F
        return Call, Put -- теоретические цены
    end
    local d1 = (math_log(F / S) + V * V * T / 2) / (V * math_sqrt(T))
    local d2 = d1 - V * math_sqrt(T)
   
  local Call = round(F * N(d1) - S * N(d2))
  local Put = Call + S - F
  return Call, Put
end

function forts.getFutInfo(base) -- base =  Si or RTS or BR
    --возвращает 2 инструмента, текущий и следующий
    local info = {}
    local count = 0
    for ticker in string.gmatch(getClassSecurities(&quot;SPBFUT&quot;), &quot;(%w+)&quot;) do
        if base == getParamEx(&quot;SPBFUT&quot;, ticker, &quot;optionbase&quot;).param_image then
            local dtmd = 0 + getParamEx(&quot;SPBFUT&quot;, ticker, &quot;days_to_mat_date&quot;).param_value
            if dtmd &gt; -1 then
                count = count + 1
                info[count] = {dtmd, ticker}
                if count == 2 then break end
            end
        end
    end
    --первый элемент info инструмент с наименьшим числом дней до погашения
    --ticker_1 = info[1][2]
    table.sort(info, function(a, b) return a[1] &lt; b[1] end)
    if #info &gt; 0 then return info end
    
    assert(nil,&quot;forts.getFutInfo не найдены фьючерсы по базовому активу &quot;..tostring(base))
end
local function getOptKey(s)
    if not tonumber(s:sub(-1)) then return &quot;W&quot; end
    return &quot;M&quot;
end
function forts.getOptInfo(futcode, opttype, WM, strike)
    -- futcode = &quot;Sim9&quot;
    -- opttype = &quot;Put&quot; or &quot;Call&quot;
    -- WM = &quot;W&quot; or &quot;M&quot; (week/month)
    local info, count = {}, 0
    for ticker in string.gmatch(getClassSecurities(&quot;SPBOPT&quot;), &quot;(%w+)&quot;) do
        if    futcode == getParamEx(&quot;SPBOPT&quot;, ticker, &quot;optionbase&quot;).param_image
        and    tonumber(getParamEx(&quot;SPBOPT&quot;, ticker, &quot;strike&quot;).param_value) == strike then
            
            local dtmd = tonumber(getParamEx(&quot;SPBOPT&quot;, ticker, &quot;days_to_mat_date&quot;).param_value) 
            if dtmd &gt; -1
            and getParamEx(&quot;SPBOPT&quot;, ticker, &quot;optiontype&quot;).param_image == opttype
            and getOptKey(ticker) == WM then
                count = count + 1
                info[count] = {dtmd, ticker}
                if count == 2 then
                    table.sort(info, function(a, b) return a[1] &lt; b[1] end)
                    break
                end
            end
        end
    end
    if #info &gt; 0 then return info end
    
    assert(nil,&quot;forts.getOptInfo не найдены опционы по активу &quot;..tostring(futcode)..
    &quot;\n opttype &quot;..tostring(opttype)..&quot;; WM &quot;..tostring(WM)..&quot;; strike &quot;..tostring(WM))
end
--Коды опционов
--C    P    K    M    Y W

--C – код базового актива, 2 символа;
--P – цена страйк, переменное количество символов;
--К – тип расчетов;
--M – месяц исполнения (а также тип для опциона), 1 символ;
--Y – год исполнения, 1 символ;
--W – признак недельного опциона, 1 символ or nil

local CP = {
    A = &quot;M&quot;, M = &quot;A&quot;,
    B = &quot;N&quot;, N = &quot;B&quot;,
    C = &quot;O&quot;, O = &quot;C&quot;,
    D = &quot;P&quot;, P = &quot;D&quot;,
    E = &quot;Q&quot;, Q = &quot;E&quot;,
    F = &quot;R&quot;, R = &quot;F&quot;,
    G = &quot;S&quot;, S = &quot;G&quot;,
    H = &quot;T&quot;, T = &quot;H&quot;,
    I = &quot;U&quot;, U = &quot;I&quot;,
    J = &quot;V&quot;, V = &quot;J&quot;,
    K = &quot;W&quot;, W = &quot;K&quot;,
    L = &quot;X&quot;, X = &quot;L&quot;,
}
-- что бы не вызывать getOptInfo более 1 го раза
function forts.OppOpt(ticker)
    -- замена инструмента по типу: Call &gt;&gt; Put or Put &gt;&gt; Call
    local x = ticker:sub(-1)
    local W = (tonumber(x) and &quot;&quot;) or x
    local C, P, K, M, Y = ticker:match(&quot;(%a%a)([%d%.]+)(%a)(%a)(%d)(%a-)&quot;)
    return C..P..K..CP[M]..Y..W
end
function forts.OppStrike(ticker, strike)
    -- замена инструмента по страйку: &quot;Si66250BN9A&quot; &gt;&gt; &quot;Si67500BN9A&quot;
    local x = ticker:sub(-1)
    local W = (tonumber(x) and &quot;&quot;) or x
    local C, _, K, M, Y = ticker:match(&quot;(%a%a)([%d%.]+)(%a)(%a)(%d)(%a-)&quot;)
    return C..strike..K..M..Y..W
end

return forts</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (kalikazandr)]]></author>
			<pubDate>Sat, 02 Mar 2019 00:20:42 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2343#p2343</guid>
		</item>
	</channel>
</rss>
