В этом примере показано, как использовать основанный на проблеме подход для решения инвестиционной задачи с детерминированными возвратами в течение фиксированного количества лет T
. Задача состоит в том, чтобы распределить ваши деньги над доступными инвестициями, чтобы максимизировать ваше окончательное богатство. Для основанного на решателе подхода смотрите Максимизируйте Долгосрочные Инвестиции Используя Линейное Программирование: Основанное на решателе.
Предположим, что у вас есть начальная сумма денег Capital_0
инвестировать в течение определенного периода времени T
лет в N
облигации с нулевым купоном. Каждая облигация выплачивает фиксированную процентную ставку, объединяет инвестиции каждый год и выплачивает основной плюс совокупный процент в конце периода погашения. Цель состоит в том, чтобы максимизировать общую сумму денег после T
лет.
Вы можете включить ограничение, что ни одна инвестиция не больше определенной части вашего общего капитала на момент инвестирования.
В этом примере сначала показана настройка задачи в небольшом случае, а затем формулируется общий случай.
Можно смоделировать это как задачу линейного программирования. Поэтому, чтобы оптимизировать свое богатство, сформулируйте задачу с помощью подхода задачи оптимизации.
Начните с небольшого примера:
Стартовая сумма для инвестирования Capital_0
$1000.
Период времени T
составляет 5 лет.
Количество облигаций N
равен 4.
Чтобы смоделировать неинвестированные деньги, имейте одну опцию B0 доступный каждый год, который имеет период погашения 1 год и процентную ставку 0%.
Облигация 1, обозначенная B1, может быть приобретена в 1 году, имеет срок погашения 4 года и процентную ставку 2%.
Облигация 2, обозначенная B2, может быть приобретена в 5 году, имеет срок погашения 1 год и процентную ставку 4%.
Облигация 3, обозначенная B3, может быть приобретена во 2 году, имеет срок погашения 4 года и процентную ставку 6%.
Облигация 4, обозначенная B4, может быть приобретена в году 2, имеет срок погашения 3 года и процентную ставку 6%.
Путем разделения первого B0 опции на 5 облигаций с периодом погашения 1 год и процентной ставкой 0%, эта проблема может быть эквивалентно смоделирована как имеющая в общей сложности 9 доступных облигаций, таких что для k=1..9
Введите k
от вектора PurchaseYears
представляет начало года облигации k
доступно для покупки.
Введите k
от вектора Maturity
представляет период погашения облигационных k
.
Введите k
от вектора MaturityYears
представляет конец года облигации k
доступен для продажи.
Введите k
от вектора InterestRates
представляет процентную ставку облигационных k
.
Визуализируйте эту проблему с помощью горизонтальных стержней, которые представляют доступное время покупки и сроки для каждой облигации.
% Time period in years T = 5; % Number of bonds N = 4; % Initial amount of money Capital_0 = 1000; % Total number of buying oportunities nPtotal = N+T; % Purchase times PurchaseYears = [1;2;3;4;5;1;5;2;2]; % Bond durations Maturity = [1;1;1;1;1;4;1;4;3]; % Bond sale times MaturityYears = PurchaseYears + Maturity - 1; % Interest rates in percent InterestRates = [0;0;0;0;0;2;4;6;6]; % Return after one year of interest rt = 1 + InterestRates/100; plotInvestments(N,PurchaseYears,Maturity,InterestRates)
Представьте свои переменные принятия решений вектором x
, где x(k)
- долларовая сумма инвестиций в облигации k
, для k = 1,...,9
. После погашения, выплата за инвестицию x(k)
является
Определить и определить как общий возврат облигаций k
:
x = optimvar('x',nPtotal,'LowerBound',0); % Total returns r = rt.^Maturity;
Цель состоит в том, чтобы выбрать инвестиции, чтобы максимизировать количество денег, собранных в конце года T
. Из графика видно, что инвестиции собираются в различные промежуточные годы и реинвестируются. В конце года T
, деньги, возвращенные от инвестиций 5, 7 и 8, могут быть собраны и представляют ваше окончательное богатство:
Создайте задачу оптимизации для максимизации и включите целевую функцию.
interestprob = optimproblem('ObjectiveSense','maximize'); interestprob.Objective = x(5)*r(5) + x(7)*r(7) + x(8)*r(8);
Каждый год у вас есть определенная сумма денег для приобретения облигаций. Начиная с 1 года, вы можете инвестировать начальный капитал в опции покупки и , так:
Затем в течение следующих лет вы собираете возвраты от погашения облигаций и реинвестируете их в новые доступные облигации, чтобы получить систему уравнений:
investconstr = optimconstr(T,1); investconstr(1) = x(1) + x(6) == Capital_0; investconstr(2) = x(2) + x(8) + x(9) == r(1)*x(1); investconstr(3) = x(3) == r(2)*x(2); investconstr(4) = x(4) == r(3)*x(3); investconstr(5) = x(5) + x(7) == r(4)*x(4) + r(6)*x(6) + r(9)*x(9); interestprob.Constraints.investconstr = investconstr;
Поскольку каждая инвестированная сумма должна быть положительной, каждая запись в векторе решения должен быть положительным. Включите это ограничение путем установки нижней границы вектора решения . Явная верхняя граница вектора решения отсутствует.
x.LowerBound = 0;
Решите эту проблему без ограничений на сумму, которую вы можете инвестировать в облигацию. Алгоритм внутренней точки может использоваться, чтобы решить этот тип задачи линейного программирования.
options = optimoptions('linprog','Algorithm','interior-point'); [sol,fval,exitflag] = solve(interestprob,'options',options)
Solving problem using linprog. Solution found during presolve.
sol = struct with fields:
x: [9x1 double]
fval = 1.2625e+03
exitflag = OptimalSolution
Выходной флаг указывает, что решатель нашел оптимальное решение. Значение fval
, возвращенный как второй выходной аргумент, соответствует конечному богатству. Посмотрите на окончательную сумму инвестиций и распределение инвестиций с течением времени.
fprintf('After %d years, the return for the initial $%g is $%g \n',... T,Capital_0,fval);
After 5 years, the return for the initial $1000 is $1262.48
plotInvestments(N,PurchaseYears,Maturity,InterestRates,sol.x)
Чтобы диверсифицировать свои инвестиции, вы можете принять решение ограничить сумму вложений в любую одну облигацию определенным процентом Pmax
от общего капитала в том году (включая возвраты по облигациям, которые в настоящее время находятся в периоде погашения). Вы получаете следующую систему неравенств:
% Maximum percentage to invest in any bond
Pmax = 0.6;
constrlimit = optimconstr(nPtotal,1);
constrlimit(1) = x(1) <= Pmax*Capital_0;
constrlimit(2) = x(2) <= Pmax*(rt(1)*x(1) + rt(6)*x(6));
constrlimit(3) = x(3) <= Pmax*(rt(2)*x(2) + rt(6)^2*x(6) + rt(8)*x(8) + rt(9)*x(9));
constrlimit(4) = x(4) <= Pmax*(rt(3)*x(3) + rt(6)^3*x(6) + rt(8)^2*x(8) + rt(9)^2*x(9));
constrlimit(5) = x(5) <= Pmax*(rt(4)*x(4) + rt(6)^4*x(6) + rt(8)^3*x(8) + rt(9)^3*x(9));
constrlimit(6) = x(6) <= Pmax*Capital_0;
constrlimit(7) = x(7) <= Pmax*(rt(4)*x(4) + rt(6)^4*x(6) + rt(8)^3*x(8) + rt(9)^3*x(9));
constrlimit(8) = x(8) <= Pmax*(rt(1)*x(1) + rt(6)*x(6));
constrlimit(9) = x(9) <= Pmax*(rt(1)*x(1) + rt(6)*x(6));
interestprob.Constraints.constrlimit = constrlimit;
Решить проблему путем инвестирования не более 60% в любой один актив. Постройте график полученных покупок. Заметьте, что ваше конечное богатство меньше, чем инвестиции без этого ограничения.
[sol,fval] = solve(interestprob,'options',options);
Solving problem using linprog. Minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the selected value of the function tolerance, and constraints are satisfied to within the selected value of the constraint tolerance.
fprintf('After %d years, the return for the initial $%g is $%g \n',... T,Capital_0,fval);
After 5 years, the return for the initial $1000 is $1207.78
plotInvestments(N,PurchaseYears,Maturity,InterestRates,sol.x)
Создайте модель для общей версии задачи. Проиллюстрировать его используя T
= 30 лет и 400 случайным образом сгенерированных облигаций с процентными ставками от 1 до 6%. Эта настройка приводит к задаче линейного программирования с 430 переменными принятия решений.
% For reproducibility rng default % Initial amount of money Capital_0 = 1000; % Time period in years T = 30; % Number of bonds N = 400; % Total number of buying oportunities nPtotal = N + T; % Generate random maturity durations Maturity = randi([1 T-1],nPtotal,1); % Bond 1 has a maturity period of 1 year Maturity(1:T) = 1; % Generate random yearly interest rate for each bond InterestRates = randi(6,nPtotal,1); % Bond 1 has an interest rate of 0 (not invested) InterestRates(1:T) = 0; % Return after one year of interest rt = 1 + InterestRates/100; % Compute the return at the end of the maturity period for each bond: r = rt.^Maturity; % Generate random purchase years for each option PurchaseYears = zeros(nPtotal,1); % Bond 1 is available for purchase every year PurchaseYears(1:T)=1:T; for i=1:N % Generate a random year for the bond to mature before the end of % the T year period PurchaseYears(i+T) = randi([1 T-Maturity(i+T)+1]); end % Compute the years where each bond reaches maturity at the end of the year MaturityYears = PurchaseYears + Maturity - 1;
Рассчитать время, когда облигации могут быть куплены или проданы. The buyindex
матрица содержит потенциальное время покупки и sellindex
матрица содержит потенциальное время продажи для каждой облигации.
buyindex = false(nPtotal,T); % allocate nPtotal-by-T matrix for ii = 1:T buyindex(:,ii) = PurchaseYears == ii; end sellindex = false(nPtotal,T); for ii = 1:T sellindex(:,ii) = MaturityYears == ii; end
Настройте переменные оптимизации, соответствующие связям.
x = optimvar('x',nPtotal,1,'LowerBound',0);
Создайте задачу оптимизации и целевую функцию.
interestprob = optimproblem('ObjectiveSense','maximize'); interestprob.Objective = sum(x(sellindex(:,T)).*r(sellindex(:,T)));
Для удобства создайте временный массив xBuy, столбцы которого представляют облигации, которые мы можем купить в каждый временной период.
xBuy = repmat(x,1,T).*double(buyindex);
Точно так же создайте временный массив xSell, столбцы которого представляют облигации, которые мы можем продать в каждый временной период.
xSell = repmat(x,1,T).*double(sellindex);
Возврат, сгенерированная для продажи этих границ,
xReturnFromSell = xSell.*repmat(r,1,T);
Создайте ограничение, что сумма, которую вы инвестируете в каждый временной период, является суммой, которую вы продали в предыдущий временной период.
interestprob.Constraints.InitialInvest = sum(xBuy(:,1)) == Capital_0; interestprob.Constraints.InvestConstraint = sum(xBuy(:,2:T),1) == sum(xReturnFromSell(:,1:T-1),1);
Решите проблему.
tic
[sol,fval,exitflag] = solve(interestprob,'options',options);
Solving problem using linprog. Minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the selected value of the function tolerance, and constraints are satisfied to within the selected value of the constraint tolerance.
toc
Elapsed time is 0.205049 seconds.
Насколько хорошо сделали инвестиции?
fprintf('After %d years, the return for the initial $%g is $%g \n',... T,Capital_0,fval);
After 30 years, the return for the initial $1000 is $5167.58
Чтобы создать ограничения, ограничивающие долю инвестиций в каждом активе, настройте матрицу, которая отслеживает активные облигации каждый раз. Чтобы выразить ограничение, что каждая инвестиция должна быть меньше Pmax
умножить общее значение, настроить матрицу, которая отслеживает значение каждой инвестиции в каждый момент времени. Для этой большей задачи установите максимальную дробь, которая может удерживаться, равной 0,4.
Pmax = 0.4;
Создайте active
матрица, соответствующая временам, когда может быть удержана связь, и cactive
матрица, которая содержит совокупную длительность каждой активной связи. Итак, значение облигаций j
во время t
является x(j)*(rt^cactive)
.
active = double(buyindex | sellindex); for ii = 1:T active(:,ii) = double((ii >= PurchaseYears) & (ii <= MaturityYears)); end cactive = cumsum(active,2); cactive = cactive.*active;
Создайте матрицу, запись которой (j, p) представляет значение облигации j в период времени p:
bondValue = repmat(x, 1, T).*active.*(rt.^(cactive));
Определите общее значение инвестиций в каждом временном интервале, чтобы можно было наложить ограничения на ограниченные запасы. mvalue
- деньги, вложенные во все облигации в конце каждого временного периода, nPtotal
-by- T
matrix.moneyavailable - сумма по облигациям денег, вложенных в начале периода времени, означающее значение портфеля каждый раз.
constrlimit = optimconstr(nPtotal,T); constrlimit(:,1) = xBuy(:,1) <= Pmax*Capital_0; constrlimit(:,2:T) = xBuy(:,2:T) <= repmat(Pmax*sum(bondValue(:,1:T-1),1), nPtotal, 1).*double(buyindex(:,2:T)); interestprob.Constraints.constrlimit = constrlimit;
Решите проблему с ограниченными холдингами.
tic
[sol,fval,exitflag] = solve(interestprob,'options',options);
Solving problem using linprog. Minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the selected value of the function tolerance, and constraints are satisfied to within the selected value of the constraint tolerance.
toc
Elapsed time is 1.315237 seconds.
fprintf('After %d years, the return for the initial $%g is $%g \n',... T,Capital_0,fval);
After 30 years, the return for the initial $1000 is $5095.26
Чтобы ускорить решатель, попробуйте алгоритм двойного симплекса.
options = optimoptions('linprog','Algorithm','dual-simplex'); tic [sol,fval,exitflag] = solve(interestprob,'options',options);
Solving problem using linprog. Optimal solution found.
toc
Elapsed time is 0.416850 seconds.
fprintf('After %d years, the return for the initial $%g is $%g \n',... T,Capital_0,fval);
After 30 years, the return for the initial $1000 is $5095.26
В этом случае алгоритму dual-simplex потребовалось меньше времени, чтобы получить одно и то же решение.
Чтобы почувствовать решение, сравните его с количеством fmax
что вы получите, если сможете инвестировать все свои стартовые деньги в одну облигацию с процентной ставкой 6% (максимальная процентная ставка) за полный 30-летний период. Можно также вычислить эквивалентную процентную ставку, соответствующую вашему конечному богатству.
% Maximum amount fmax = Capital_0*(1+6/100)^T; % Ratio (in percent) rat = fval/fmax*100; % Equivalent interest rate (in percent) rsol = ((fval/Capital_0)^(1/T)-1)*100; fprintf(['The amount collected is %g%% of the maximum amount $%g '... 'that you would obtain from investing in one bond.\n'... 'Your final wealth corresponds to a %g%% interest rate over the %d year '... 'period.\n'], rat, fmax, rsol, T)
The amount collected is 88.7137% of the maximum amount $5743.49 that you would obtain from investing in one bond. Your final wealth corresponds to a 5.57771% interest rate over the 30 year period.
plotInvestments(N,PurchaseYears,Maturity,InterestRates,sol.x,false)