В этом примере показано, как использовать проблемный подход для решения инвестиционной проблемы с детерминированной доходностью в течение фиксированного количества лет. 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/100 и определить rk как общий возврат облигацииk:
= βkmk.
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. Явная верхняя граница для вектора решения отсутствует.
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 общего капитала в этом году (включая доходность по облигациям, которые в настоящее время находятся в сроке погашения). Получается следующая система неравенств:
x9≤Pmax× (β1x1 +β6x6)
% 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;
Вычислите время, когда облигации могут быть куплены или проданы. 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около-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
В этом случае алгоритму двойного симплекса потребовалось меньше времени для получения того же решения.
Чтобы почувствовать решение, сравните его с суммой 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)
