Fmincon given simple problem, not finding a solution
Show older comments
Hi,
I am having a weird problem where the fmincon functions works 1 second and on the second attempt, with the same inputs, it doesn't find a solution.
The problem I am trying to solve is I am trying to minimize the standard deviation of drifts betweens current and target weights of securities given an upper and lower bound.
Please let me know if I'm making any mistakes. Thanks
Inputs:
cashflow = -1134000;
current_target_weights = [0.0142023954819741,0.0150000000000000;0.0173447886267467,0.0175000000000000;0.0222995676451968,0.0225000000000000;0.0141407877584573,0.0150000000000000;0.0164172914902949,0.0175000000000000;0.00999573276025007,0.0100000000000000;0.00805550070703398,0.00750000000000000;0.0197716177594372,0.0200000000000000;0.0197493382178409,0.0200000000000000;0.0170298088271876,0.0175000000000000];
current_aum = 549922652;
Code:
% set current and target weights
current_weights = current_target_weights(:,1);
target_weights = current_target_weights(:,2);
% set current total values per security and add the cashflow at the end
current_navs = current_target_weights(:,1) .* current_aum;
current_navs(end + 1) = cashflow;
% set the new aum and get the new current weights (need to adjust current weights for the cash flow injection)
new_aum = current_aum + cashflow;
new_current_weights = current_navs ./ sum(new_aum);
% set the cash flow target to 0
target_weights(end + 1) = 0;
%calculate the drift between the target and current
drift = new_current_weights - target_weights;
%set lower and upper bounds.
if cashflow > 0
lower_bound = drift;
upper_bound = 0*new_current_weights; upper_bound(drift>0) = drift(drift>0);
elseif cashflow < 0
upper_bound = drift;
lower_bound = 0*new_current_weights; lower_bound(drift<0) = drift(drift<0);
end
%lock the cash flow bounds at 0 since we want to get rid of it
lower_bound(end) = 0;
upper_bound(end) = 0;
%set the optimization
Aeq = ones(1, length(new_current_weights))*sum(target_weights);
beq = sum(drift);
x0 = drift;
[x,fval,eflg] = fmincon(@(x)std(x),x0,Aeq,beq,[],[],lower_bound,upper_bound,[]);
8 Comments
Walter Roberson
on 22 Sep 2016
Which MATLAB release are you using?
When I try that code on R2016a, I always seem to get the same result, with the message
[x,fval,eflg] = fmincon(@(x)std(x),x0,Aeq,beq,[],[],lower_bound,upper_bound,[])
Converged to an infeasible point.
fmincon stopped because the size of the current step is less than
the default value of the step size tolerance but constraints are not
satisfied to within the default value of the constraint tolerance.
That is, fmincon consistently indicates there is no solution.
Viral Solanki
on 22 Sep 2016
Edited: Walter Roberson
on 22 Sep 2016
Walter Roberson
on 22 Sep 2016
I installed R2012b on Windows 10 and tried your code, copying and pasting from what you posted above. Each time I tried, the result came out exactly the same, each time with the same output that implies there is no feasible solution.
Walter Roberson
on 23 Sep 2016
Please recheck your code. You create Aeq and beq (equality constraints), but you pass them in the positions reserved for A and b (inequality constraints)
Viral Solanki
on 23 Sep 2016
Walter Roberson
on 23 Sep 2016
Do you have a numeric solution for that particular problem? Do you have even one numeric solution that satisfies the constraints?
Viral Solanki
on 23 Sep 2016
Walter Roberson
on 23 Sep 2016
>> xsol = [-0.000768257124602500;-0.000329180586560771;-0.000423578372517913;-0.000829992152425199;-0.00104878432325890;-0.000189708865714259;-0.000153833220027044;-0.000375056025958911;-0.000375100902519659;-0.000435001299370900;0;];
Aeq*xsol <= beq
Aeq*xsol - beq
ans =
0
ans =
0.00443009306846424
Your proposed solution does not satisfy your constraints.
>> beq
beq =
-0.0052309731603196
>> Aeq*xsol
ans =
-0.000800880091855359
Answers (1)
Walter Roberson
on 23 Sep 2016
0 votes
If you examine your lower_bound and upper_bound you will find that they are identical except at positions 6 and 7 (the positions where drift is positive). Those equalities force exact values for all the locations except 6 and 7.
If you substitute those exact values into the linear equation Aeq*X(:) <= beq then you can reduce it down to an equation in two variables, X(6) and X(7). You can solve for X(7) based upon the equation and the upper and lower bound constraints on X(6) . But you will find that the result is that X(7) = - X(6) - 213110080925339615/7493989779944505344 . X(6) is constrained to be non-negative, and any non-negative value you put in for X(6) will result in an negative value for X(7). But X(7) is constrained to be non-negative as well. You therefore have a contradiction. The constraints cannot be satisfied.
Operationally, you should try to write your code to directly put in the values where the upper and lower bound are forced to be equal. If you have the symbolic toolbox, you can put in the constraints symbolically and solve() the linear equality or linear inequality for the feasible regions, and you can then minimize std() over those regions... if you find any region at all.
1 Comment
Viral Solanki
on 23 Sep 2016
Categories
Find more on Systems of Nonlinear Equations in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!