function [w, r, sigma, opti] = kellycriterion(mu, Sigma, cons)
%KELLYCRITERION 使用凯利判据做资产配置
%
% [w, r, sigma, opti] = kellycriterion(mu, Sigma, cons)
%   输入
%     mu: 资产的预计收益率，为一个向量
%     Sigma: 资产的协方差矩阵，为一个方阵
%     cons: 对资产的限制条件，它是一个矩阵，限制权重 cons(:, 1:end-1)*w <= cons(:, end)
%   输出
%     w: 最优配置的资产权重，为一个向量
%     r: 最优配置的收益率
%     sigma: 最优配置的波动率
%     opti: 最优配置的凯利判据的目标收益率
%
% 关于凯利判据的更多信息参见 http://zhiqiang.org/blog/tag/%E5%87%AF%E5%88%A9%E5%88%A4%E6%8D%AE
%
% author: zhang@zhiqiang.org, 2010
%   
    
N = numel(mu);
mu = mu(:)';

% if nargin <= 2 || isempty(w0)
%     w0 = [1 zeros(1, N-1)]';
% end

if nargin <= 2
    cons = ones(0, N+1);
end

cons = [cons; portcons('Default', N)];

[PortRisk, PortReturn, PortWts] = portopt(mu, Sigma, ...
    100, [], cons);

opti = -100;
for i = 1:numel(PortRisk)
    tmp = log(1+PortReturn(i)) - PortRisk(i)^2/(1+PortReturn(i))^2/2;
    if tmp > opti
        opti = tmp;
        r = PortReturn(i);
        sigma = PortRisk(i);
        w = PortWts(i, :)';
    end
end
    


% options = []; optimset('Algorithm', 'sqp');
% w = fmincon(@(w)(-log(1+mu*w) + w'*Sigma*w/2/(1+mu*w)^2), ...
%     w0, cons(:, 1:end-1), cons(:, end), ones(1, N), 1, zeros(N, 1), ones(N, 1), [], options);
% 
% 
% 
% r = mu*w;
% sigma = sqrt(w'*Sigma*w);
% opti = log(1+mu*w) - w'*Sigma*w/2/(1+mu*w)^2;

% w = sdpvar(N, 1);
% solvesdp([sum(w)==1, w>=0], -log(1+mu*w) + w'*Sigma*w/2/(1+mu*w)^2 );
% % solvesdp(set(sum(w)==1), -mu*w+(mu*w)^2/2-(mu*w)^3/3 + w'*Sigma*w/2/(1+mu*w)^2 );
% w = double(w);