/*
 * -------------------------------------------------------------------------
 *      $Id: EfficientFrontier.java,v 1.3 2003/04/03 21:31:09 trudisch Exp $
 * -------------------------------------------------------------------------
 *      Copyright (c) 1999 Visual Numerics Inc. All Rights Reserved.
 *
 *      This software is confidential information which is proprietary to
 *      and a trade secret of Visual Numerics, Inc.  Use, duplication or
 *      disclosure is subject to the terms of an appropriate license
 *      agreement.
 *
 *      VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 *      SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 *      BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 *      FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL
 *      NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 *      AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 *      ITS DERIVATIVES.
 *--------------------------------------------------------------------------
 */

package com.imsl.demo.risk;
import com.imsl.math.*;
import com.imsl.chart.*;

/**
 *
 * @author  brophy
 * @created February 7, 2002
 */
public class EfficientFrontier extends JFrameChart {

    /** Creates new EfficientFrontier */
    public EfficientFrontier() throws QuadraticProgramming.InconsistentSystemException {
        double h[][] = {
            {1.134E-4,  4.376E-5,   5.242E-5,   5.173E-8,   1.128E-7},
            {4.376E-5,  2.271E-4,   2.108E-5,   1.109E-5,   3.632E-5},
            {5.242E-5,  2.108E-5,   1.159E-4,  -8.052E-6,  -4.459E-7},
            {5.173E-8,  1.109E-5,  -8.052E-6,   1.168E-4,   1.112E-5},
            {1.128E-7,  3.632E-5,  -4.459E-7,   1.112E-5,   6.373E-4}
        };
        double meanReturns[] = {0.054, 0.046, 0.024, 0.073, 0.065};
        int n = h.length;
        double g[] = new double[n];
        /*
         *  Constraints
         *  1) Portfolio's value must be 100%
         *     sum(x[k]) = 1          ==>  aeq[k] = 1 for all k    beq[0] = 1
         *  2) Meet target
         *     sum(returns[k]*x[k]) >= expectedReturn
         *  3) No shorting allowed
         *     x[k] >= 0 for all k    ==>  ane[i][j] = (i==j ? 1 : 0)  bne[k] = 0
         */
        double aeq[][] = new double[1][n];
        double beq[] = {1};

        double ane[][] = new double[n+1][n];
        double bne[] = new double[n+1];
        for (int i = 0;  i < n;  i++) {
            aeq[0][i] = 1.0;
            ane[i+1][i] = 1.0;
        }
        ane[0] = meanReturns;

        double x[] = new double[20];
        double y[] = new double[x.length];
        for (int k = 0;  k < x.length;  k++) {
            y[k] = 2*0.073*k/x.length;
            bne[0] = y[k];
            try {
                QuadraticProgramming qp = new QuadraticProgramming(h, g, aeq, beq, ane, bne);
                double p[] = qp.getSolution();
                double sum = 0.0;
                for (int i = 0;  i < n;  i++) {
                    for (int j = 0;  j < n;  j++) {
                        sum += p[i]*h[i][j]*p[j];
                    }
                }
                x[k] = Math.sqrt(sum);
                System.out.println(x[k]+"   "+y[k]);
            } catch (Exception e) {
                System.out.println("fail y="+y[k]);
                x[k] = y[k] = Double.NaN;
            }
        }
        // Print the solution and its dual
        //new PrintMatrix("x").print(qp.getSolution());
        //new PrintMatrix("dual").print(qp.getDual());

        Chart chart = getChart();
        chart.setTextColor("blue");
        AxisXY axis = new AxisXY(chart);
        axis.getAxisX().getAxisTitle().setTitle("standard deviation");
        axis.getAxisY().getAxisTitle().setTitle("return");
        axis.getAxisX().getAxisLabel().setTextFormat("0.00%");///java.text.NumberFormat.getPercentInstance());
        Data data = new Data(axis, x, y);
        data.setDataType(Data.DATA_TYPE_LINE | Data.DATA_TYPE_MARKER);
        data.setLineColor("green");
        data.setMarkerColor("green");
        data.setMarkerType(Data.MARKER_TYPE_FILLED_SQUARE);

        y = (double[])meanReturns.clone();
        x = new double[n];
        for (int k = 0;  k < n;  k++) {
            //x[k] *= 100;
            x[k] = Math.sqrt(h[k][k]);
        }
        data = new Data(axis, x, y);
        data.setDataType(Data.DATA_TYPE_MARKER);
        data.setMarkerColor("red");
        data.setMarkerType(Data.MARKER_TYPE_HOLLOW_SQUARE);
    }

    public static void main(String args[]) throws Exception {
        new EfficientFrontier().show();
    }
}