Программ для анализа и управления портфелями опционов много. Они есть в торговых терминалах, в виде отдельных коммерческих продуктов или сервисов на сайтах. У таких программ есть ряд ограничений: портфели привязаны к торговой платформе, котировки подкачиваются из определённого источника, а рассчитать параметры или сценарии можно только предусмотренные ПО.


Задачу управления портфелями на разных рынках я решил с помощью R. Движок с открытым кодом даёт много возможностей: портфели хранятся в любой СУБД или Excel, или загружаются из терминала (QUIK, TWS, любого другого с API); котировки подкачиваются из своего источника (терминал, база данных или сайт) и доступна любая аналитика по портфелю!


Общее описание


Рыночные данные и портфель загружаются в объекты класса OptPort и OptMarket. Портфель переоценивается по рынку, на основе этих данных рассчитываются текущая прибыль и "греки", а также его профиль. Профиль портфеля (зависимость прибыли или "греков" от цены базисного актива) рассчитывается и хранится в объекте класса OptProfile. Встроенные функции рисуют график профиля и позволяют сравнивать профили нескольких портфелей.


По ссылке (1) в конце статьи — вариант управления портфелем опционов Мосбиржи с подключением к QUIK и Access.


Рыночные котировки OptMarket


Объект класса OptMarket нужен для хранения биржевых котировок опционов, информации о базисном активе, текущей дате.


Без рыночных цен портфель переоценивается по внутренней стоимости.


# Загружаем биржевые котировки (доску опционов) из Access
brd  = GetBoard_fortsdb(ul)

# Создаём объект класса OptMarket
mrkt = OptMarket(ul = 'SiZ9',                     # тикер базисного актива
                 ul_price = brd$ul_price,         # цена базисного актива
                 board = as.tbl(brd$board),       # доска опционов
                 now   = as.Date('2019-11-12'))   # текущая дата

Портфель OptPort


Портфель может состоять из опционов и базисного актива. Конструктор
создаёт портфель на основе таблицы сделок по заданному базовому
активу. Сделки суммируются в общую позицию.


# Загружаем сделки из Access (в базу сделки импортированы из терминала QUIK)
trades = GetTrades_fortsdb()

# Т.к. в сделках указан только тикер, забираем параметры опционов из доски опционов
trades = TickerToParams_fortsboard(trades, mrkt$board)

На основании сделок создаём объект класса OptPort:


port = OptPort(ul = 'SiZ9', 
               trades = trades, 
               name = 'Spread')

Анализ портфеля


Оценка портфеля


Функция PortPricing переоценивает портфель по текущим ценам — выбирает цены опционов из OptMarket и добавляет их в портфель OptPort. Для опционов МосБиржи самое простое — переоценить их по теоретической цене, которую транслирует сама биржа и известна всегда (price_at = 'theor').


port = PortPricing(port, mrkt, price_at = 'theor')

Прибыль и “греки”


Функция PortValuation рассчитывает параметры портфеля — нереализованную прибыль и "греков". Результаты сохраняются в поле total_value объекта OptPort.


port = PortValuation(port)

port$total_value

Профиль портфеля — OptProfile


Объект OptProfile хранит профиль портфеля на интервале цен базисного актива.


Функция PlotProfile строит график профиля на базе ggplot2.


myprofile = OptProfile(optport  = port, 
                       params   = c('pl', 'delta', 'theta', 'vega'),  
                       ul_range = 0.05  # процентное отклонение от максимального и минимального страйков портфеля
                      ) 

PlotProfile(myprofile)


Изменение состава портфеля


Для изменения состава портфеля есть функция AddTrades. Она добавляет сделку в портфель и рассчитывает новую позицию портфеля.



# Непосредственно сделка - продажа одного опциона из портфеля
newtrade = data.frame(ul='SiZ9', ticker='Si63500BX9', xtype='p', strike=63500, 
                      expdate=as.Date('2019-12-19'), tradeprice=500, q=-1 )

# Портфель после изменений
port2 = AddTrades(port = port, 
                  trades = newtrade)

port2$name = 'Changed'

Профиль нового портфеля можно сравнить со старым. Функция JoinProfiles
объединяет данные профилей для построения общего графика.


# Пересчитываем оценку и параметры нового портфеля
port2 = port2 %>% PortPricing(., mrkt, price_at = 'theor') %>% PortValuation(.)

# Профиль нового портфеля
myprofile2 = OptProfile(optport  = port2, params = c('pl', 'delta','theta', 'vega'), ul_range = 0.05) 

# Объединяем профили
profiles = JoinProfiles(list(myprofile, myprofile2))

PlotProfile(profiles)


Итого


Базовые функции решают базовые задачи. Мой решение было разработано для конкретной цели — анализ множества портфелей и моделирование изменений в эти портфели. Исходный код вы найдёте по ссылке ниже. Бонус — база для импорта данных из QUIK и настройки самого QUIK для экспорта.


Ссылки:
(1) Исходный код на GitHub.