В этом примере показано, как настроить проблему выделения основой фонда, которая использует оптимизацию портфеля среднего отклонения с Portfolio
возразите, чтобы оценить эффективные портфели.
Предположим, что вы хотите управлять фондом распределения активов с четырьмя классами активов: связи, акции с большой капитализацией, акции маленького дна и появляющиеся акции. Фонд является длинно-единственным без заимствования или рычагов, должен иметь не больше, чем 85% портфеля в акциях, и не больше, чем 35% портфеля в появляющихся акциях. Стоимость, чтобы торговать первыми тремя активами составляет пересчитанных на год 10 пунктов, и стоимость, чтобы торговать появляющимися акциями в четыре раза выше. Наконец, вы хотите гарантировать, что средний оборот - не больше, чем 15%. Чтобы решить эту задачу, вы настроите основную задачу оптимизации портфеля среднего отклонения и затем медленно вводить различные ограничения на проблему добраться до решения.
Чтобы настроить задачу оптимизации портфеля, запустите с основных определений известных количеств, сопоставленных со структурой этой проблемы. Каждый класс активов принят, чтобы иметь tradeable актив с ценой в реальном времени. Такие активы могут быть, например, биржевыми индексными фондами (ETFs). Начальный портфель с активами в каждом активе, который имеет в общей сложности $7,5 миллионов наряду с дополнительной денежной позицией 60 000$. Эти основные количества и затраты для торговли настраиваются в следующих переменных с именами актива в массиве ячеек Asset
, текущие цены в векторном Price
, текущие активы портфеля в векторном Holding
, и операционные издержки в векторном UnitCost
.
Чтобы анализировать этот портфель, можно настроить промокательную бумагу в table
возразите, чтобы помочь отследить цены, активы, веса, и т.д. В частности, можно вычислить начальные веса портфеля и обеспечить их в новом поле промокательной бумаги под названием InitPort
.
Asset = { 'Bonds', 'Large-Cap Equities', 'Small-Cap Equities', 'Emerging Equities' }; Price = [ 52.4; 122.7; 35.2; 46.9 ]; Holding = [ 42938; 24449; 42612; 15991 ]; UnitCost = [ 0.001; 0.001; 0.001; 0.004 ]; Blotter = table('RowNames', Asset); Blotter.Price = Price; Blotter.InitHolding = Holding; Wealth = sum(Blotter.Price .* Blotter.InitHolding); Blotter.InitPort = (1/Wealth)*(Blotter.Price .* Blotter.InitHolding); Blotter.UnitCost = UnitCost; Blotter
Blotter=4×4 table
Price InitHolding InitPort UnitCost
_____ ___________ ________ ________
Bonds 52.4 42938 0.3 0.001
Large-Cap Equities 122.7 24449 0.4 0.001
Small-Cap Equities 35.2 42612 0.2 0.001
Emerging Equities 46.9 15991 0.1 0.004
Поскольку это - гипотетический пример, чтобы симулировать цены активов от данного среднего значения и ковариации ежегодных совокупных доходов актива для классов активов, portsim
функция используется, чтобы создать актив, возвращается с желаемым средним значением и ковариацией. А именно, portsim
используется, чтобы симулировать пять лет ежемесячных совокупных доходов и затем строится, чтобы показать журнал симулированных цен совокупного дохода
Среднее значение и ковариация ежегодных совокупных доходов актива обеспечены в переменных AssetMean
и AssetCovar
. Симулированные цены совокупного дохода актива (которые являются составленными совокупными доходами) обеспечены в переменной Y
. Все начальные цены совокупного дохода актива нормированы к 1
в этом примере.
AssetMean = [ 0.05; 0.1; 0.12; 0.18 ]; AssetCovar = [ 0.0064 0.00408 0.00192 0; 0.00408 0.0289 0.0204 0.0119; 0.00192 0.0204 0.0576 0.0336; 0 0.0119 0.0336 0.1225 ]; X = portsim(AssetMean'/12, AssetCovar/12, 60); % monthly total returns for 5 years (60 months) [Y, T] = ret2tick(X, [], 1/12); % form total return prices
Warning: This syntax will be removed in a future release. See the documentation for recommended usage.
plot(T, log(Y)); title('\bfSimulated Asset Class Total Return Prices'); xlabel('Year'); ylabel('Log Total Return Price'); legend(Asset,'Location','best');
Чтобы исследовать портфели на границе эффективности, настройте Portfolio
объект с помощью этих спецификаций:
Веса портфеля являются неотрицательными и суммируют к 1
.
Выделение акции - не больше, чем 85% портфеля.
Появляющаяся акция - не больше, чем 35% портфеля.
Эти спецификации включены в Portfolio
объект p
в следующей последовательности использования функций, который запускается с использования Portfolio
объект.
Спецификация начального портфеля от Blotter
дает количество активов в вашей вселенной, таким образом, вы не должны задавать NumAssets
свойство непосредственно. Затем настройте ограничения по умолчанию (длинно-единственный с ограничением бюджета). Кроме того, настройте ограничение группы, которое налагает верхнюю границу на акции в портфеле (акции идентифицированы в матрице группы с 1
) и ограничение верхней границы на появляющиеся акции. Несмотря на то, что вы, возможно, установили верхнюю границу на появляющихся акциях с помощью setBounds
функция, заметьте как addGroups
функция используется, чтобы настроить это ограничение.
Чтобы иметь полностью заданную задачу оптимизации портфеля среднего отклонения, необходимо задать среднее значение, и ковариация актива возвращается. С тех пор начиная с этих моментов в переменных AssetMean
и AssetCovar
, можно использовать setAssetMoments
функция, чтобы ввести эти переменные в ваш Portfolio
объект (помнят, что вы принимаете, что ваши необработанные данные являются ежемесячным журналом, возвращается, который является, почему вы делите свои ежегодные входные моменты на 12, чтобы добраться, ежемесячный журнал возвращается).
Используйте цены совокупного дохода с estimateAssetMoments
функция со спецификацией, что ваши данные в Y
цены, и не возвращается, чтобы оценить, что актив возвращает моменты для вашего Portfolio
объект.
Несмотря на то, что возвраты в вашем Portfolio
объект находится в модулях ежемесячного журнала, возвращается, и поскольку последующие затраты пересчитаны на год, удобно задать их как пересчитанные на год совокупные доходы с этим прямым преобразованием AssetMean
и AssetCovar
свойства вашего Portfolio
объект p
.
Отобразите объект Portfolio p
.
p = Portfolio('Name', 'Asset Allocation Portfolio', ... 'AssetList', Asset, 'InitPort', Blotter.InitPort); p = setDefaultConstraints(p); p = setGroups(p, [ 0, 1, 1, 1 ], [], 0.85); p = addGroups(p, [ 0, 0, 0, 1 ], [], 0.35); p = setAssetMoments(p, AssetMean/12, AssetCovar/12); p = estimateAssetMoments(p, Y, 'DataFormat', 'Prices'); p.AssetMean = 12*p.AssetMean; p.AssetCovar = 12*p.AssetCovar; display(p);
p = Portfolio with properties: BuyCost: [] SellCost: [] RiskFreeRate: [] AssetMean: [4x1 double] AssetCovar: [4x4 double] TrackingError: [] TrackingPort: [] Turnover: [] BuyTurnover: [] SellTurnover: [] Name: 'Asset Allocation Portfolio' NumAssets: 4 AssetList: {1x4 cell} InitPort: [4x1 double] AInequality: [] bInequality: [] AEquality: [] bEquality: [] LowerBound: [4x1 double] UpperBound: [] LowerBudget: 1 UpperBudget: 1 GroupMatrix: [2x4 double] LowerGroup: [] UpperGroup: [2x1 double] GroupA: [] GroupB: [] LowerRatio: [] UpperRatio: [] MinNumAssets: [] MaxNumAssets: [] BoundType: [4x1 categorical]
Важный шаг в оптимизации портфеля должен подтвердить это, проблема портфеля выполнима, и основной тест должен гарантировать, что набор портфелей непуст и ограничен. Используйте estimateBounds
функция, чтобы определить границы для набора портфеля. В этом случае, начиная с обоих lb
и ub
конечны, набор ограничен.
[lb, ub] = estimateBounds(p); display([lb, ub]);
0.1500 1.0000 0 0.8500 0 0.8500 0 0.3500
Учитывая созданный Portfolio
объект, используйте plotFrontier
функционируйте, чтобы просмотреть границу эффективности. Вместо того, чтобы использовать значение по умолчанию 10 портфелей вдоль границы, можно отобразить границу с 40 портфелями. Заметьте, что грубый эффективный портфель возвращает падение приблизительно между 6% и 16% в годы.
plotFrontier(p, 40);
Portfolio
объект p
не включает операционные издержки так, чтобы задача оптимизации портфеля задала в p
портфель общего количества использования возвращается как прокси возврата. Чтобы обработать сетевые возвраты, создайте второй Portfolio
объект q
это включает операционные издержки.
q = setCosts(p, UnitCost, UnitCost); display(q);
q = Portfolio with properties: BuyCost: [4x1 double] SellCost: [4x1 double] RiskFreeRate: [] AssetMean: [4x1 double] AssetCovar: [4x4 double] TrackingError: [] TrackingPort: [] Turnover: [] BuyTurnover: [] SellTurnover: [] Name: 'Asset Allocation Portfolio' NumAssets: 4 AssetList: {1x4 cell} InitPort: [4x1 double] AInequality: [] bInequality: [] AEquality: [] bEquality: [] LowerBound: [4x1 double] UpperBound: [] LowerBudget: 1 UpperBudget: 1 GroupMatrix: [2x4 double] LowerGroup: [] UpperGroup: [2x1 double] GroupA: [] GroupB: [] LowerRatio: [] UpperRatio: [] MinNumAssets: [] MaxNumAssets: [] BoundType: [4x1 categorical]
Быть более конкретным об областях значений эффективного портфеля возвращает и рискует, используйте estimateFrontierLimits
функция, чтобы получить портфели в конечных точках границы эффективности. Учитывая эти портфели, вычислите их моменты с помощью estimatePortMoments
функция. Следующий код генерирует таблицу, которая перечисляет риск, и возвратитесь из начального портфеля, а также грубые и сетевые моменты портфеля возвращается для портфелей в конечных точках границы эффективности:
[prsk0, pret0] = estimatePortMoments(p, p.InitPort); pret = estimatePortReturn(p, p.estimateFrontierLimits); qret = estimatePortReturn(q, q.estimateFrontierLimits); displayReturns(pret0, pret, qret);
Annualized Portfolio Returns ... Gross Net Initial Portfolio Return 9.70 % 9.70 % Minimum Efficient Portfolio Return 5.90 % 5.77 % Maximum Efficient Portfolio Return 13.05 % 12.86 %
Результаты показывают, что стоимость, чтобы торговать диапазонами от 14 до 19 пунктов, чтобы добраться от текущего портфеля до эффективных портфелей в конечных точках границы эффективности (эти затраты являются различием между грубым и сетевым портфелем, возвращается.), Кроме того, заметьте, что максимальный эффективный портфель возвращается (13%) меньше, максимальный актив возвращаются (18%) из-за ограничений на выделения акции.
Общий подход, чтобы выбрать эффективные портфели должен выбрать портфель, который имеет желаемую часть области значений ожидаемого портфеля, возвращается. Чтобы получить портфель, который составляет 30% диапазона от минимума до максимального возврата на границе эффективности, получите область значений сети, возвращается в qret
использование Portfolio
объект q
и интерполируйте, чтобы получить 30%-й уровень с interp1
функция, чтобы получить портфель qwgt
.
Level = 0.3; qret = estimatePortReturn(q, q.estimateFrontierLimits); qwgt = estimateFrontierByReturn(q, interp1([0, 1], qret, Level)); [qrsk, qret] = estimatePortMoments(q, qwgt); displayReturnLevel(Level, qret, qrsk);
Portfolio at 30% return level on efficient frontier ... Return Risk 7.90 9.09
display(qwgt);
qwgt = 4×1
0.6252
0.1856
0.0695
0.1198
Целевой портфель, который составляет 30% диапазона от минимума до максимальных сетевых возвратов, имеет возврат 7,9% и риск 9,1%.
Несмотря на то, что вы могли принять этот результат, предположить, что вы хотите к целевым значениям для портфельного риска. А именно, предположите, что у вас есть консервативный целевой риск 10%, умеренный целевой риск 15% и агрессивный целевой риск 20%, и вы хотите получить портфели, которые удовлетворяют каждой цели риска. Используйте estimateFrontierByRisk
функция, чтобы получить предназначенные риски, заданные в переменной TargetRisk
. Результант три эффективных портфеля получен в qwgt
.
TargetRisk = [ 0.10; 0.15; 0.20 ]; qwgt = estimateFrontierByRisk(q, TargetRisk); display(qwgt);
qwgt = 4×3
0.5407 0.2020 0.1500
0.2332 0.4000 0.0318
0.0788 0.1280 0.4682
0.1474 0.2700 0.3500
Используйте estimatePortRisk
функция, чтобы вычислить портфельные риски для этих трех портфелей, чтобы подтвердить, что целевые риски были достигнуты:
display(estimatePortRisk(q, qwgt));
0.1000 0.1500 0.2000
Предположим, что вы хотите переключить от текущего портфеля до умеренного портфеля. Можно оценить, что покупки и продажи добираются до этого портфеля:
[qwgt, qbuy, qsell] = estimateFrontierByRisk(q, 0.15);
Если вы насчитываете покупки и продажи для этого портфеля, вы видите, что средний оборот составляет 17%, который больше цели 15%:
disp(sum(qbuy + qsell)/2)
0.1700
Поскольку вы также хотите гарантировать, что средний оборот - не больше, чем 15%, можно добавить ограничение среднего оборота в Portfolio
объект с помощью setTurnover
:
q = setTurnover(q, 0.15); [qwgt, qbuy, qsell] = estimateFrontierByRisk(q, 0.15);
Можно ввести предполагаемый эффективный портфель с покупками и продажами в Промокательную бумагу:
qbuy(abs(qbuy) < 1.0e-5) = 0;
qsell(abs(qsell) < 1.0e-5) = 0; % zero out near 0 trade weights
Blotter.Port = qwgt;
Blotter.Buy = qbuy;
Blotter.Sell = qsell;
display(Blotter);
Blotter=4×7 table
Price InitHolding InitPort UnitCost Port Buy Sell
_____ ___________ ________ ________ _______ ____ ________
Bonds 52.4 42938 0.3 0.001 0.18787 0 0.11213
Large-Cap Equities 122.7 24449 0.4 0.001 0.4 0 0
Small-Cap Equities 35.2 42612 0.2 0.001 0.16213 0 0.037871
Emerging Equities 46.9 15991 0.1 0.004 0.25 0.15 0
Buy
и Sell
элементы Промокательной бумаги являются изменениями в весах портфеля, которые должны быть преобразованы в изменения в активах портфеля, чтобы определить отрасли. Поскольку вы работаете с сетевым портфелем, возвращается, необходимо сначала вычислить стоимость, чтобы торговать от начального портфеля до нового портфеля. Это может быть выполнено можно следующим образом:
TotalCost = Wealth * sum(Blotter.UnitCost .* (Blotter.Buy + Blotter.Sell))
TotalCost = 5.6248e+03
Стоимость для торговли составляет 5 625$, так, чтобы в целом необходимо было бы настроить начальное богатство соответственно перед подготовкой новых весов портфеля. Однако, чтобы сохранить анализ простым, обратите внимание, что у вас есть достаточные наличные деньги (60,0000$), отложенные, чтобы оплатить торговые издержки и что вы не коснетесь денежной позиции, чтобы создать любые положения в вашем портфеле. Таким образом можно заполнить промокательную бумагу с новыми активами портфеля и отраслями, чтобы добраться до нового портфеля, не внося изменений в общем инвестированном богатстве. Во-первых, вычислите содержание портфеля:
Blotter.Holding = Wealth * (Blotter.Port ./ Blotter.Price);
Вычислите количество долей к Buy
и Sell
в вашей Промокательной бумаге:
Blotter.BuyShare = Wealth * (Blotter.Buy ./ Blotter.Price); Blotter.SellShare = Wealth * (Blotter.Sell ./ Blotter.Price);
Заметьте, как вы использовали оперативное правило усечения, чтобы получить модульные количества долей, чтобы купить и продать. Очистите промокательную бумагу путем удаления себестоимости единицы продукции и покупки и продайте веса портфеля:
Blotter.Buy = []; Blotter.Sell = []; Blotter.UnitCost = [];
Конечным результатом является промокательная бумага, которая содержит предложенные отрасли, чтобы добраться от вашего текущего портфеля до портфеля умеренного риска. Чтобы сделать торговлю, вы должны были бы продать 16 049 акций своего актива связи и 8 069 долей вашего актива акции маленького дна и должны будете приобрести 23 986 акций вашего появляющегося актива акций.
display(Blotter);
Blotter=4×7 table
Price InitHolding InitPort Port Holding BuyShare SellShare
_____ ___________ ________ _______ _______ ________ _________
Bonds 52.4 42938 0.3 0.18787 26889 0 16049
Large-Cap Equities 122.7 24449 0.4 0.4 24449 0 0
Small-Cap Equities 35.2 42612 0.2 0.16213 34543 0 8068.8
Emerging Equities 46.9 15991 0.1 0.25 39977 23986 0
Итоговый график использует plotFrontier
функционируйте, чтобы отобразить границу эффективности и начальный портфель для полностью заданной задачи оптимизации портфеля. Это также добавляет местоположение умеренного риска или итогового портфеля на границе эффективности.
plotFrontier(q, 40); hold on scatter(estimatePortRisk(q, qwgt), estimatePortReturn(q, qwgt), 'filled', 'r'); h = legend('Initial Portfolio', 'Efficient Frontier', 'Final Portfolio', 'location', 'best'); set(h, 'Fontsize', 8); hold off
function displayReturns(pret0, pret, qret) fprintf('Annualized Portfolio Returns ...\n'); fprintf(' %6s %6s\n','Gross','Net'); fprintf('Initial Portfolio Return %6.2f %% %6.2f %%\n',100*pret0,100*pret0); fprintf('Minimum Efficient Portfolio Return %6.2f %% %6.2f %%\n',100*pret(1),100*qret(1)); fprintf('Maximum Efficient Portfolio Return %6.2f %% %6.2f %%\n',100*pret(2),100*qret(2)); end function displayReturnLevel(Level, qret, qrsk) fprintf('Portfolio at %g%% return level on efficient frontier ...\n',100*Level); fprintf('%10s %10s\n','Return','Risk'); fprintf('%10.2f %10.2f\n',100*qret,100*qrsk); end