Оптимизация портфеля ценных бумаг средствами Python
На финансовом рынке обращается, как правило, несколько типов ценных бумаг: государственные ценные бумаги, муниципальные облигации, корпоративные акции и т.п.
Если у участника рынка есть свободные деньги, то их можно отнести в банк и получать проценты или купить на них ценные бумаги и получать дополнительный доход. Но в какой банк отнести? Какие ценные бумаги купить?
Ценные бумаги с низкими рисками, как правило, малодоходны, а высокодоходные, как правило, более рискованны. Экономическая наука может дать некоторые рекомендации для решения этого вопроса, но для этого необходимо иметь соответствующие программные средства, желательно с простым интерфейсом и бесплатные.
Программные средства для анализа портфелей ценных бумах должны работать с матрицами доходности и решать задачи нелинейного программирования с ограничениями в виде строгих и нестрогих неравенств. Символьное решение на Python некоторых типов задач нелинейного программирования мною уже рассматривалось в публикации [1]. Однако, применить предложенные в указанной публикации методы для анализа портфеля ценных бумаг нельзя из-за ограничений в виде строгих неравенств.
Целью настоящей публикации является разработка методов оптимизации портфелей ценных бумаг с использованием библиотеки scipy.optimize. Пришлось исследовать и применить при программировании такие мало известные возможности указанной библиотеки, как введение дополнительных ограничений в функцию цели [2].
Постановка задачи об оптимальном портфеле МарковицаРассмотрим общую задачу распределения капитала, который участник рынка хочет потратить на приобретение ценных бумаг. Цель инвестора – вложить деньги так, чтобы сохранить свой капитал, а при возможности и нарастить его.
Набор ценных бумаг, находящихся у участника рынка, называется его портфелем. Стоимость портфеля – это суммарная стоимость всех составляющих его бумаг. Если сегодня его стоимость есть Р, а через год она окажется равной Р', то (Р'- Р)/Р естественно назвать доходностью портфеля в процентах годовых. Доходность портфеля – это доходность на единицу его стоимости.
Пусть xi – доля капитала, потраченная на покупку ценных бумаг i-го вида. Весь выделенный капитал принимается за единицу. Пусть di – доходность в процентах годовых бумаг i-го вида в расчете на одну денежную единицу.
Доходность колеблется во времени, так что будем считать ее случайной величиной. Пусть mi, ri – средняя ожидаемая доходность и среднее квадратическое отклонение, называемое риском. Через CVij обозначим ковариацию доходностей ценных бумаг i – го и j – го видов.
Каждый владелец портфеля ценных бумаг сталкивается с дилеммой: хочется иметь эффективность больше, а риск меньше. Однако, поскольку “нельзя поймать двух зайцев сразу”, необходимо сделать определенный выбор между эффективностью и риском.
Модель оптимального портфеля Марковица, которая обеспечивает минимальный риск и заданную доходностьТакая модель в виде системы из уравнений и неравенств имеет вид [3]:
Необходимо определить: x1,x2…xn.
Исходными данными для расчета является матрица доходности ценных бумаг следующей формы (заполненный пример матрицы в листинге программы):
Для реализации модели минимального риска на Python нужно выполнить следующие этапы разработки: 1.Определение средней доходности акций 1-6:
Средняя доходность акций 1-6:
[[ 12.19916667] [ 13.17116667] [ 13.98283333] [ 13.73466667] [ 13.46983333] [ 14.84666667]]
2. Построение ковариационной матрицы (m=n=6).
CV= np.zeros([m,n]) for i in np.arange(0,m): for j in np.arange(0,n): x=np.array(D[0:m,j]).T y=np.array(D[0:m,i]).T X = np.vstack((x,y)) CV[i,j]=round(np.cov(x,y,ddof=0)[1,0],3) print(«Ковариационная матрица CV: \n %s»%CV)
Ковариационная матрица CV:
[[ 2.117 1.773 2.256 2.347 2.077 1.975] [ 1.773 1.903 1.941 2.049 1.888 1.601] [ 2.256 1.941 2.901 2.787 2.701 2.761] [ 2.347 2.049 2.787 3.935 2.464 2.315] [ 2.077 1.888 2.701 2.464 2.723 2.364] [ 1.975 1.601 2.761 2.315 2.364 3.067]]
3. Символьное определение функции для определения дисперсии доходности портфеля (функции риска).
Дисперсия доходности портфеля (функция риска):
2.117*x1**2 + 3.546*x1*x2 + 4.512*x1*x3 + 4.694*x1*x4 + 4.154*x1*x5 + 3.95*x1*x6 + 1.903*x2**2 + 3.882*x2*x3 + 4.098*x2*x4 + 3.776*x2*x5 + 3.202*x2*x6 + 2.901*x3**2 + 5.574*x3*x4 + 5.402*x3*x5 + 5.522*x3*x6 + 3.935*x4**2 + 4.928*x4*x5 + 4.63*x4*x6 + 2.723*x5**2 + 4.728*x5*x6 + 3.067*x6**2
4. Определение оптимального портфеля акций для минимального риска и доходности mp=13.25
Минимум функции риска -1.846 Акция 1 доля- 0.141, доходность- 1.721 Акция 2 доля- 0.73, доходность- 9.616 Акция 3 доля- 0.0, доходность- 0.0 Акция 4 доля- 0.0, доходность- 0.0 Акция 5 доля- 0.0, доходность- 0.0 Акция 6 доля- 0.129, доходность- 1.914
Доходными являются 1,2,6 акции. Это и есть часть ответа на вопросы, поставленные в начале публикации.
Оптимальный портфель Марковица максимальной доходности и заданного, (приемлемого) рискаСистема уравнений и неравенств имеет вид:
Часть приведенного листинга не требует пояснений, поскольку всё подробно изложено в предыдущем примере. Однако есть отличия. Столбец средней доходности d и функция условия def constraint2(x) взяты из предыдущего примера, причем в предыдущем примере это была функция минимального риска. Кроме того, для определения максимума перед выводом значения новой функции цели – def objective(x), поставлен знак минус.
Максимум функции доходности --14.1 Акция 1 доля- 0.0, доходность- 0.0 Акция 2 доля- 0.72, доходность- 9.489 Акция 3 доля- 0.0, доходность- 0.0 Акция 4 доля- 0.0, доходность- 0.0 Акция 5 доля- 0.0, доходность- 0.0 Акция 6 доля- 0.311, доходность- 4.611
Акции 2,6 доходны. Но это не единственный результат оптимизации средствами scipy optimize minimize. Я решил сравнить результаты с решением той же задачи средствами Mathcad и вот что получил:
Mathcad указывает на те же номера 2,6 доходных акций, но доли другие. В Python 0.720,0.311 в Mathcad 0.539, 0.461, при этом разные значения максимальной доходности соответственно 14.1 и 13.9. Для того чтобы окончательно убедиться какая программа вычисляет оптимум правильно, подставим полученные в Python значения долей в Mathcad, получим:
Вывод: на Python оптимум функции, а следовательно доли и доходность вычисляется более точно, чем при использовании Mathcad.
Формирование оптимального портфеля ценных бумаг по модели ТобинаПортфель Тобина минимального риска:
где d0 – эффективность без рисковых бумаг; x0 – доля капитала вложенная в без рисковые бумаги; xi,xj — доля капитала вложенная в ценные бумаги i-го и j–го видов; di – математическое ожидание (среднее арифметическое) доходности i — й ценной бумаги; vij – корреляционный момент между эффективностью бумаг i-го и j –го видов.
Подбираем долю капитала заданной доходности, задаём общую доходность, приняв для примера следующие числовые значения x0=0.3, d0 =10, dp=12.7.
Минимум функции риска: 0.728 Акция 1 доля- -0.023, доходность: -0.286 Акция 2 доля- 0.666, доходность: 8.778 Акция 3 доля- -1.0, доходность: -13.983 Акция 4 доля- 0.079, доходность: 1.089 Акция 5 доля- 0.3, доходность: 4.048 Акция 6 доля- 0.677, доходность: 10.054
Доходными являются акции 2,4,5,6.
Портфель Тобина максимальной эффективностигде rp – риск портфеля.
Максимум функции доходности: -11.657 Акция 1 доля- 0.09, доходность: 1.096 Акция 2 доля- 0.196, доходность: 2.583 Акция 3 доля- -1.0, доходность: -13.983 Акция 4 доля- 0.113, доходность: 1.552 Акция 5 доля- 0.411, доходность: 5.538 Акция 6 доля- 0.463, доходность- 6.872
Доходными являются акции 1,2,4,5.
Выводы:Впервые средствами Python решена задача оптимизации портфеля ценных бумаг по моделям Марковица и Тобина. На сравнительном примере c математическим пакетом Mathcad показаны преимущества библиотеки scipy optimize minimize.