Тематическое исследование распределения активов

Этот пример показывает, как настроить проблему выделения основой фонда, которая использует оптимизацию портфеля среднего отклонения с объектом Portfolio оценить эффективные портфели.

Шаг 1. Определение проблемы портфеля.

Предположим, что вы хотите управлять фондом распределения активов с четырьмя классами активов: связи, акции с большой капитализацией, акции маленькой прописной буквы и появляющиеся акции. Фонд является длинно-единственным без заимствования или рычагов, должен иметь не больше, чем 85% портфеля в акциях, и не больше, чем 35% портфеля в появляющихся акциях. Стоимость, чтобы торговать первыми тремя активами составляет пересчитанных на год 10 пунктов, и стоимость, чтобы торговать появляющимися акциями в четыре раза выше. Наконец, вы хотите гарантировать, что средний оборот - не больше, чем 15%. Чтобы решить эту проблему, вы настроите основную задачу оптимизации портфеля среднего отклонения и затем медленно вводить различные ограничения на проблему добраться до решения.

Чтобы настроить задачу оптимизации портфеля, запустите с основных определений известных количеств, сопоставленных со структурой этой проблемы. Каждый класс активов принят, чтобы иметь tradeable актив с ценой в реальном времени. Такие активы могут быть, например, биржевыми индексными фондами (ETFs). Начальный портфель с активами в каждом активе, который имеет в общей сложности $7,5 миллионов наряду с дополнительной денежной позицией 60 000$. Эти основные количества и затраты для торговли настраиваются в следующих переменных с именами актива в массиве ячеек Asset, текущие цены в векторном Price, текущие активы портфеля в векторном Holding и операционные издержки в векторном UnitCost.

Чтобы анализировать этот портфель, можно настроить промокательную бумагу в объекте dataset помочь отследить цены, активы, веса, и т.д. В частности, можно вычислить начальные веса портфеля и поддержать их в новом поле промокательной бумаги под названием 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 = dataset({Price, 'Price'}, {Holding, 'InitHolding'},'obsnames',Asset);
Wealth = sum(Blotter.Price .* Blotter.InitHolding);
Blotter.InitPort = (1/Wealth)*(Blotter.Price .* Blotter.InitHolding);
Blotter.UnitCost = UnitCost;
disp(Blotter);
                          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   

Шаг 2. Симуляция цен активов.

Поскольку это - гипотетический пример, чтобы моделировать цены активов от данного среднего значения и ковариации ежегодных совокупных доходов актива для классов активов, функция 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');

Шаг 3. Подготовка объекта Portfolio.

Чтобы исследовать портфели на границе эффективности, настройте объект Portfolio с помощью этих спецификаций:

  • Веса портфеля являются неотрицательными и суммируют к 1.

  • Выделение акции - не больше, чем 85% портфеля.

  • Появляющаяся акция - не больше, чем 35% портфеля.

Эти спецификации включены в объект Portfolio p в следующей последовательности использования функций, который запускается с использования объекта Portfolio.

  1. Спецификация начального портфеля от Blotter дает количество активов в вашей вселенной, таким образом, вы не должны задавать свойство NumAssets непосредственно. Затем, настройте ограничения по умолчанию (длинно-единственный с ограничением бюджета). Кроме того, настройте ограничение группы, которое налагает верхнюю границу на акции в портфеле (акции идентифицированы в матрице группы с 1), и ограничение верхней границы на появляющиеся акции. Несмотря на то, что вы, возможно, установили верхнюю границу на появляющихся акциях с помощью функции setBounds, заметьте, как функция addGroups используется, чтобы настроить это ограничение.

  2. Чтобы иметь полностью заданную задачу оптимизации портфеля среднего отклонения, необходимо задать среднее значение, и ковариация актива возвращается. С тех пор начиная с этих моментов в переменных AssetMean и AssetCovar, можно использовать функцию setAssetMoments, чтобы войти, эти переменные в объект Portfolio (помните, что вы принимаете, что ваши необработанные данные являются ежемесячным журналом, возвращается, который является, почему вы делите свои ежегодные входные моменты на 12, чтобы добраться, ежемесячный журнал возвращается).

  3. Используйте цены совокупного дохода с функцией estimateAssetMoments со спецификацией, что ваши данные в Y являются ценами, и не возвращается, чтобы оценить, что актив возвращает моменты для вашего объекта Portfolio.

  4. Несмотря на то, что возвраты в вашем объекте Portfolio находятся в модулях ежемесячного журнала, возвращается, и поскольку последующие затраты пересчитаны на год, удобно задать их как пересчитанные на год совокупные доходы с этим прямым преобразованием свойств AssetMean и AssetCovar вашего объекта Portfolio p.

  5. Отобразите объект 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]

Шаг 4. Подтвердите проблему портфеля.

Важный шаг в оптимизации портфеля должен подтвердить это, проблема портфеля выполнима, и основной тест должен гарантировать, что набор портфелей непуст и ограничен. Используйте функцию estimateBounds, чтобы определить границы для набора портфеля. В этом случае, и начиная с lb и начиная с ub конечны, набор ограничен.

[lb, ub] = estimateBounds(p);
display([lb, ub]);
    0.1500    1.0000
         0    0.8500
         0    0.8500
         0    0.3500

Шаг 5. Графический вывод границы эффективности.

Учитывая созданный объект Portfolio, используйте функцию plotFrontier, чтобы просмотреть границу эффективности. Вместо того, чтобы использовать значение по умолчанию 10 портфелей вдоль границы, можно отобразить границу с 40 портфелями. Заметьте, что грубый эффективный портфель возвращает падение приблизительно между 6% и 16% в годы.

plotFrontier(p, 40);

Шаг 6. Оценка общего количества по сравнению с сетевым портфелем возвращается.

p объекта Portfolio не включает операционные издержки так, чтобы задача оптимизации портфеля, заданная в использовании 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]

Шаг 7. Анализ описательных свойств структур Портфеля.

Быть более конкретным об областях значений эффективного портфеля возвращает и рискует, используйте функцию 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%) из-за ограничений на выделения акции.

Шаг 8. Получение Портфеля на заданном уровне возврата на границе эффективности.

Общий подход, чтобы выбрать эффективные портфели должен выбрать портфель, который имеет желаемую часть области значений ожидаемого портфеля, возвращается. Чтобы получить портфель, который составляет 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%.

Шаг 9. Получение Портфеля на заданных уровнях риска на границе эффективности.

Несмотря на то, что вы могли принять этот результат, предположить, что вы хотите к целевым значениям для портфельного риска. А именно, предположите, что у вас есть консервативный целевой риск 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 = 
                          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   


                          Port       Buy     Sell    
    Bonds                 0.18787       0     0.11213
    Large-Cap Equities        0.4       0           0
    Small-Cap Equities    0.16213       0    0.037871
    Emerging Equities        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 = [];

Шаг 10. Отображение конечных результатов.

Конечным результатом является промокательная бумага, которая содержит предложенные отрасли, чтобы добраться от вашего текущего портфеля до портфеля умеренного риска. Чтобы сделать торговлю, вы должны были бы продать 16 049 акций своего актива связи и 8 069 долей вашего актива акции маленькой прописной буквы и должны будете приобрести 23 986 акций вашего появляющегося актива акций.

display(Blotter);
Blotter = 
                          Price    InitHolding    InitPort    Port       Holding
    Bonds                  52.4    42938          0.3         0.18787    26889  
    Large-Cap Equities    122.7    24449          0.4             0.4    24449  
    Small-Cap Equities     35.2    42612          0.2         0.16213    34543  
    Emerging Equities      46.9    15991          0.1            0.25    39977  


                          BuyShare    SellShare
    Bonds                     0        16049   
    Large-Cap Equities        0            0   
    Small-Cap Equities        0       8068.8   
    Emerging Equities     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