Тема: Опционы - полезные функции
Недавно занимаюсь опционами, набросал пару функций, может кому пригодится, может кто дополнит.
# 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 > 10 then return 1 end
if x < -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 > 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 <= 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("SPBFUT"), "(%w+)") do
if base == getParamEx("SPBFUT", ticker, "optionbase").param_image then
local dtmd = 0 + getParamEx("SPBFUT", ticker, "days_to_mat_date").param_value
if dtmd > -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] < b[1] end)
if #info > 0 then return info end
assert(nil,"forts.getFutInfo не найдены фьючерсы по базовому активу "..tostring(base))
end
local function getOptKey(s)
if not tonumber(s:sub(-1)) then return "W" end
return "M"
end
function forts.getOptInfo(futcode, opttype, WM, strike)
-- futcode = "Sim9"
-- opttype = "Put" or "Call"
-- WM = "W" or "M" (week/month)
local info, count = {}, 0
for ticker in string.gmatch(getClassSecurities("SPBOPT"), "(%w+)") do
if futcode == getParamEx("SPBOPT", ticker, "optionbase").param_image
and tonumber(getParamEx("SPBOPT", ticker, "strike").param_value) == strike then
local dtmd = tonumber(getParamEx("SPBOPT", ticker, "days_to_mat_date").param_value)
if dtmd > -1
and getParamEx("SPBOPT", ticker, "optiontype").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] < b[1] end)
break
end
end
end
end
if #info > 0 then return info end
assert(nil,"forts.getOptInfo не найдены опционы по активу "..tostring(futcode)..
"\n opttype "..tostring(opttype).."; WM "..tostring(WM).."; strike "..tostring(WM))
end
--Коды опционов
--C P K M Y W
--C – код базового актива, 2 символа;
--P – цена страйк, переменное количество символов;
--К – тип расчетов;
--M – месяц исполнения (а также тип для опциона), 1 символ;
--Y – год исполнения, 1 символ;
--W – признак недельного опциона, 1 символ or nil
local CP = {
A = "M", M = "A",
B = "N", N = "B",
C = "O", O = "C",
D = "P", P = "D",
E = "Q", Q = "E",
F = "R", R = "F",
G = "S", S = "G",
H = "T", T = "H",
I = "U", U = "I",
J = "V", V = "J",
K = "W", W = "K",
L = "X", X = "L",
}
-- что бы не вызывать getOptInfo более 1 го раза
function forts.OppOpt(ticker)
-- замена инструмента по типу: Call >> Put or Put >> Call
local x = ticker:sub(-1)
local W = (tonumber(x) and "") or x
local C, P, K, M, Y = ticker:match("(%a%a)([%d%.]+)(%a)(%a)(%d)(%a-)")
return C..P..K..CP[M]..Y..W
end
function forts.OppStrike(ticker, strike)
-- замена инструмента по страйку: "Si66250BN9A" >> "Si67500BN9A"
local x = ticker:sub(-1)
local W = (tonumber(x) and "") or x
local C, _, K, M, Y = ticker:match("(%a%a)([%d%.]+)(%a)(%a)(%d)(%a-)")
return C..strike..K..M..Y..W
end
return forts