Иван Андреевич (diente_de_lion) wrote,
Иван Андреевич
diente_de_lion

Программа для ребалансировки портфеля

Еще один пост в преддверии поста о второй ребалансировке. В первом посте я упоминал специальную программу, которая помогает мне делать эту самую ребалансировку. Чтобы не создавалось впечатления, что это какое-то "секретное оружие" только мне одному доступное я собираюсь этой программой поделиться и написать к ней небольшой пост-инструкцию по применению. Как пишут в таких случаях you can stop reading если вам это не интересно.

Скачать программу можно с яндекс-диска отсюда. По ссылке находится обыкновенный zip-архив, внтури сама программа (allocator.exe), несколько полезных dll (не обращайте внимания), пример конфигурационного файла портфеля (sample.ini) и пример batch-файла, который позволяет отслеживать состояние портфеля, что называется, "в реальном времени" (loop.cmd). Программа изначально писалась под Linux, но вполне нормально работает и в Windows (собранной версии под Linux у меня сейчас нет, но при острой необходимсти это можно поправить). Программа консольная, поэтому для ее использования понадобятся некоторые навыки работы с консолью винды (она же коммандный интерпретатор cmd.exe).

Программа предназначена для формирования или ребалансировки портфеля активов, состоящего из ценных бумаг, которые торгуются на американской фондовой бирже (а может и где-то еще - я не очень разбираюсь в этих тонкостях). В частности она подойдет для портфеля составленного из ETF Vanguard/iShares/SPDR/etc. Насколько я понимаю, для ETF FinEx, которые в последнее время набирают популярность, программа не подходит: те источники котировок, которые мне удалось найти, ничего не знают про эти ETF. Однако, если такой источник все-таки имеется (и это вообще кому-то нужно) - дайте знать, добавить его в программу дело довольно нехитрое.

Строка запуска программы выглядит так: "allocator.exe конфиг.ini [прокси]" (без кавычек, конечно). Второй параметр - прокси - не обязательный, а первый параметр - конфиг.ini - задает имя конфигурационного файла. Конфигруационный файл определяет текущее состояние портфеля (какие активы уже имеются и в каком количестве), целевое распределение активов, которое необходимо получить и количество свободных денег, доступных для покупки новых единиц активов. Результатом работы программы является рекомендация каких активов и сколько нужно продать или купить, чтобы максимально приблизиться к искомому распределению. Пример работы программы из упомянутого выше поста:



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

Работа программы целиком определяется конфигурационным файлом, поэтому здесь я вкраце опишу каким образом формируется этот файл. По внутреннему устройству он представляет собой старый-добрый ini-файл и состоит из нескольких секций, имена которых пишутся в квадратных скобках. Содержимое файла нечувствительно к регистру, т.е., например, "Yes", "yes" и "YES" - это будет одна и та же строка. Внутри секций содержатся строки вида "параметр = значение", например commission=2. Пустые строки игнорируются. Файл может содеражть комментарии, которые начинаются с символа "точка с запятой" (;) и тоже игнорируются. Далее я привожу описание всех возможных секций конфигурационного файла.

Секция [have]: активы, имеющиеся в наличии
Параметр Значение
Тикер актива (строка, например VTI) Количество единиц актива (вещественное число, например 5.1)

Пример:
[have]
SPY = 6
BND = 4
GOOG = 1

Видеть нецелое количество активов в портфеле мне пока не доводилось, но я слышал, что такое возможно при автоматическом реинвестировании дивидендов. Anyway при ребалансировке портфеля программа предлагает покупку и продажу только целых единиц активов. Дробная часть актива продается автоматически при продаже всех целых частей. Опять же, возможность чисто теоретичкеская, на практике пока не сталкивался. Пояснения по поводу тикеров, надеюсь, не требуются, но на всякий случай примеры можно в количествах найти например в этом списке.

Секция [want]: целевое распределение активов
Параметр Значение
Тикер актива Количество единиц актива (вещественное число)
Доля актива в портфеле в процентах (вещественное число и знак процента, например 12.5%)

Пример:
[have]
SPY = 60%
BND = 40%
GOOG = 1

Как должно быть понятно из описания секции целевой объем каждого актива в портфеле можно задать как точным его количством, так и в процентах. Здесь возникает резонный вопрос: от чего считаются проценты при "смешанном" задании распределения? В текущей реализации программа работает так: весь портфель делится на две части: часть заданная в точных единицах и часть, заданная в процентах. И проценты считаются как доля только от той части портфеля, которая задана в процентах. Исходя из этого затем выполняется оптимизация. В целом такой подход к заданию распределения кажется мне нетипичным (более типично задавать все в процентах), но для каких-то особенных ситуаций возможность такая есть.

Секция [commission]: комиссии за сделку
Параметр Значение
Тикер актива Комиссия за сделку (вещественное число, например 2)

Пример:
[commission]
IAU = 2.60

Здесь все предельно просто: для каждого актива можно задать комиссию, которая взимается вашим брокером за сделку с этим активом. Опять же, на практике я не сталкивался с разными комиссиями для разных активов и обычно комиссия одинаковая (ее проще задать в секции [options] для всех активов сразу), но на всякий случай возможность задать разные комиссии для разных активов в программу заложена. На моей практике использовать секцию [commission] пока еще не требовалось.

Секция [trade]: допустимые операции с активами
Параметр Значение
Тикер актива Одно из значений BUY, SELL, KEEP или TRADE

Пример:
[trade]
IEF  = sell
VNQ  = buy
GOOG = keep

Достаточно полезная секция, которая при необходимости позволяет ограничить программу в операциях с определенными активами. При желании определенный актив можно запретить покупать, продавать или вообще что-либо с ним делать. В приведенном примере IEF можно только продавать, VNQ только покупать, GOOG покупать и продвать нельзя вообще. Значение по умолчанию для всех активов - TRADE, т.е. можно и покупать и продавать (по необходимости, конечно).

Секция [cash]: наличные деньги
Параметр Значение
HAVE Количество свободных денег в американских долларах (вещественное число, например 104.26)
WANT Целевое количество свободных денег в долларах или процентах (например 100 или 5%)

Пример:
[cash]
have = 204.96
want = 0%

Со свободными деньгами должно быть в общем понятно, а вот с целевым количеством надо пояснить. В том случае, если оно задано в процентах, остаток денег после ребалансировки будет участвовать в подсчете долей в портфеле наравне с активами, доли которых заданы в процентах, в противном случае - нет. Целевое количество денег вообще необязательно задавать, но в этом случае нужно быть готовым к тому, что программа может потратить не все деньги на активы (если это является необходимым можно еще использовать более жесткое ограничение USE ALL CASH секции [options] о котором будет сказано далее). Есть еще параметр WITHDRAW значение которого отнимается от значения парамтера HAVE, может быть полезен при необходимости извлечь какую-то сумму денег из портфеля, на практике мне пока еще ни разу не был нужен.

Секция [options]: прочие опции работы
Параметр Значение
COMMISSION Комиссия за сделку по умолчанию, если не задано иное в секции [commission]. Если не указана, то считается равной нулю.
USE ALL CASH (или NO MORE DEALS) Булевый параметр, значение YES (или TRUE, или 1) задает, что должны быть по максимуму использованы все свободные деньги таким образом, что после выполнения ребалансировки невозможно будет докупить ни одной единицы какого-либо актива не добавив хотя бы еще один цент денег. По умолчанию имеет значение NO (оно же FALSE, оно же 0)
MAX DEALS Целое число, задает ограничение на максимальное количество сделок, которые можно совершить для выполнения ребалансировки портфеля. Немного теоретический параметр, на практике мне пока ни разу не пригодился. По умолчанию равен нулю, т.е. количетсво сделок не ограничено.
MARKET INFO PROVIDER (или просто PROVIDER) Источник информации о котировках (строка, по умолчанию IEX TRADING)
MODEL Используемая модель оптимизации (возможные значения LAD и LSAPPROX, по умолчанию LAD)

Пример:
[options]
commission = 1
use all cash = true
max deals = 4
model = lsapprox
market info provider = yahoo finance

Последние два параметра определенно нужнаются в комментариях. Начну с праметра PROVIDER. До последнего времени такого праметра даже и не было, данные брались через полуофициальное API Yahoo Finance. Иногда результаты оттуда приходили странные, но в целом работало. Внезапно в 2017 году Yahoo решило лавочку прикрыть и это полуофициальное API закрыло. После некоторых поисков мне удалось найти другую точку входа в это API, программа была переделана под работу с новым еще более неофициальным API. И все было неплохо пока в начале 2018-го я не начал замечать что от Yahoo приходят какие-то совершенно неадекватные значения bid и ask далекие от реальной цены. Причем это не проблема этого API, такие же точно значения bid и ask показываются и на finance.yahoo.com. Я решил искать замену.

Замена нашлась в виде вполне официального API на iextrading.com с которым по умолчанию теперь и работает программа. Но надо понимать, что на этого поставщика котировок я перешел вот прямо только что и мало ли что. В случае необходимсти вернуться к прежнему варианту работы позволяет значение YAHOO FINANCE параметра PROVIDER.

Теперь пара слов о математическо модели, которая используется в программе. При написании программы я долго бился с разными подходами к построению модели (это совершенно отдельная и очень большая история), но в конечном итоге я остановился на линейной модели. Со всеми вытекающими. Это в том чсиле означает, что и оптимизация выполняется линейная. Что же конкретно это значит?

Оптимизация выполняется при наличии множетсва довольно жестких ограничений (прежде всего это ограничение целочисленности количества покупаемых и продаваемых активов) и идеальный "сферический портфель в вакууме" в общем случае получить невозможно. Т.е. в любом случае мы будем иметь некоторое приближение. Отсюда встает задача оценить близость каждого приближенного портфеля к идеальному. Здесь человечество (кажется) придумало множество критериев, самым популярным из которых является метод наименьших квадратов (Least Squares). Вот только одна проблема: этот критерий нелинейный и в линейную модель не лезет.

Поэтому по умолчанию в программе используется другой - линейный - критерий, метод наименьших модулей (Least Absolute Deviations). Говоря вообще, этот критерий в некоторых ситуациях может давать несколько худший результат, чем метод наименьших квадратов. Но зато он линейный. Большое желание все-таки прикрутить к своей линейной модели квадратичный метод оптимизации привело к тому, что программа поддерживает некую линейную аппроксимацию метода наименьших квадратов. Включается этот метод значением LSAPPROX параметра MODEL. Но будьте осторожны: эта аппроксимация является итеративной, порой может считать очень долго и иногда может зависнуть, сожрать всю память и вылететь. Могу сказать, что на практике результатов линейного критерия обычно хватает и они не отличаются от результатов применения квадратичного критерия.

Замечу так же, что даже при использовании линейного критерия программа все равно работает небыстро и порой надо подождать некоторое время для получения результата. Пример запуска программы с моим текущим портфелем показан на картинке ниже.



Краткие пояснения по "интерфейсу программы". Столбец Asset содерджит активы из которых состоит портфель. Столбцы Bid и Ask определяют рыночные цены активов. Столбец Source - исходное состояние портфеля: посередине количество активов из секции [have], слева это количество пересчитано по курсу Bid, справа - доля в портфеле в процентах. Столбец Change - измения в портфеле, предлагаемые программой. Столбец Result аналогичен столбцу Source, но уже не для исходного, а для оптимизированного портфеля. Столбцец Target содержит целевое распределение из секции [want], Столбцы Buy и Sell отображают информацию из секции [trade], столбец Commission показывает сколько денег потрачено на коммиссии по опреациям и долю в процентах от суммы операции в скобках.

Последняя строка таблицы Cash показывает состояние свободных денег в исходном и в ребалансированном портфелях. Строка внизу под таблицей суммирует значения в столбцах, в скобках под столбцами Source и Result приводятся значения среднего отклонения от идеального портфеля.

На этом, пожалуй, закончу. Если у кого-то есть вопросы - как всегда готов ответить в комментариях. Практический пример использования программы я еще планирую привести в марте при второй ребалансировке портфеля.
Tags: портфель
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments