One - One Code All

Blog Content

java金融包org.ojalgo.finance.portfolio.MarkowitzModel

Java   2013-10-10 18:37:05

参考文档:http://www.ojalgo.org/generated/org/ojalgo/finance/portfolio/MarkowitzModel.html


org.ojalgo.finance.portfolio.MarkowitzModel.setRiskAversion 方法
org.ojalgo.finance.portfolio.MarkowitzModel.getAssetWeights 方法


源码:

public final void setRiskAversion(final Number aFactor) {

    myMarketEquilibrium.setRiskAversion(aFactor);

    this.reset();
}


MarketEquilibrium.java源码:

/*
 * Copyright 2003-2011 Optimatika (www.optimatika.se)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.ojalgo.finance.portfolio;

import java.math.BigDecimal;

import org.ojalgo.ProgrammingError;
import org.ojalgo.array.ArrayUtils;
import org.ojalgo.constant.BigMath;
import org.ojalgo.matrix.BasicMatrix;
import org.ojalgo.scalar.BigScalar;
import org.ojalgo.scalar.PrimitiveScalar;
import org.ojalgo.scalar.Scalar;
import org.ojalgo.type.TypeUtils;

/**
 * MarketEquilibrium translates between the market portfolio weights
 * and the equilibrium excess returns. The only things needed to do
 * those translations are the covariance matrix and the risk aversion
 * factor - that's what you need to supply when you instantiate this
 * class.
 *
 * @see #calculateAssetReturns(BasicMatrix)
 * @see #calculateAssetWeights(BasicMatrix)
 * 
 * @author apete
 */
public class MarketEquilibrium {

    private static final BigDecimal DEFAULT_RISK_AVERSION = BigMath.ONE;
    private static final String STRING_ZERO = "0";
    private static final String SYMBOL = "Asset_";

    /**
     * Calculates the portfolio return using the input instrument
     * weights and returns.
     */
    public static Scalar calculatePortfolioReturn(final BasicMatrix aWeightsVctr, final BasicMatrix aReturnsVctr) {
        return aWeightsVctr.multiplyVectors(aReturnsVctr);
    }

    private static String[] makeSymbols(final int aCount) {

        final String[] retVal = new String[aCount];

        final int tmpMaxLength = Integer.toString(aCount - 1).length();

        String tmpNumberString;
        for (int i = 0; i < aCount; i++) {
            tmpNumberString = Integer.toString(i);
            while (tmpNumberString.length() < tmpMaxLength) {
                tmpNumberString = STRING_ZERO + tmpNumberString;
            }
            retVal[i] = SYMBOL + tmpNumberString;
        }

        return retVal;
    }

    private final BasicMatrix myCovariances;
    private BigDecimal myRiskAversion;
    private final String[] mySymbols;

    public MarketEquilibrium(final BasicMatrix aCovarianceMatrix) {
        this(aCovarianceMatrix, DEFAULT_RISK_AVERSION);
    }

    public MarketEquilibrium(final BasicMatrix aCovarianceMatrix, final Number aRiskAversionFactor) {
        this(MarketEquilibrium.makeSymbols(aCovarianceMatrix.getRowDim()), aCovarianceMatrix, aRiskAversionFactor);
    }

    public MarketEquilibrium(final String[] instrumentNamesOrKeys, final BasicMatrix aCovarianceMatrix, final Number aRiskAversionFactor) {

        super();

        mySymbols = ArrayUtils.copyOf(instrumentNamesOrKeys);
        myCovariances = aCovarianceMatrix;
        myRiskAversion = TypeUtils.toBigDecimal(aRiskAversionFactor);
    }

    @SuppressWarnings("unused")
    private MarketEquilibrium() {

        this(null, null, null);

        ProgrammingError.throwForIllegalInvocation();
    }

    MarketEquilibrium(final MarketEquilibrium aMarket) {
        this(aMarket.getSymbols(), aMarket.getCovariances(), aMarket.getRiskAversion().getNumber());
    }

    /**
     * If the input vector of asset weights are the weights of the market
     * portfolio, then the ouput is the equilibrium excess returns.
     */
    public BasicMatrix calculateAssetReturns(final BasicMatrix aWeightsVctr) {
        final BasicMatrix tmpWeightsVctr = myRiskAversion.compareTo(DEFAULT_RISK_AVERSION) == 0 ? aWeightsVctr : aWeightsVctr.multiply(myRiskAversion);
        return myCovariances.multiplyRight(tmpWeightsVctr);
    }

    /**
     * If the input vector of returns are the equilibrium excess returns
     * then the output is the market portfolio weights. This is
     * unconstrained optimisation - there are no constraints on the
     * resulting instrument weights.
     */
    public BasicMatrix calculateAssetWeights(final BasicMatrix aReturnsVctr) {
        final BasicMatrix tmpWeightsVctr = myCovariances.solve(aReturnsVctr);
        if (myRiskAversion.compareTo(DEFAULT_RISK_AVERSION) == 0) {
            return tmpWeightsVctr;
        } else {
            return tmpWeightsVctr.divide(myRiskAversion);
        }
    }

    /**
     * Calculates the portfolio variance using the input instrument
     * weights.
     */
    public Scalar calculatePortfolioVariance(final BasicMatrix aWeightsVctr) {

        BasicMatrix tmpLeft;
        BasicMatrix tmpRight;

        if (aWeightsVctr.getColDim() == 1) {
            tmpLeft = aWeightsVctr.transpose();
            tmpRight = aWeightsVctr;
        } else {
            tmpLeft = aWeightsVctr;
            tmpRight = aWeightsVctr.transpose();
        }

        return myCovariances.multiplyRight(tmpRight).multiplyLeft(tmpLeft).toScalar(0, 0);
    }

    /**
     * Will set the risk aversion factor to the best fit for an observed
     * pair of market portfolio asset weights and equilibrium/historical
     * excess returns.
     */
    public void calibrate(final BasicMatrix aWeightsVctr, final BasicMatrix aReturnsVctr) {
        this.setRiskAversion(this.getImpliedRiskAversion(aWeightsVctr, aReturnsVctr).getNumber());
    }

    public MarketEquilibrium copy() {
        return new MarketEquilibrium(this);
    }

    public BasicMatrix getCovariances() {
        return myCovariances;
    }

    /**
     * Will calculate the risk aversion factor that is the best fit for
     * an observed pair of market portfolio weights and equilibrium/historical
     * excess returns.
     */
    public Scalar getImpliedRiskAversion(final BasicMatrix aWeightsVctr, final BasicMatrix aReturnsVctr) {

        // Least-squares-solve [LHS: unscaled derived returns][X: risk aversion] = [RHS: observed returns]

        BasicMatrix tmpLHS = myCovariances.multiplyRight(aWeightsVctr);
        BasicMatrix tmpRHS = aReturnsVctr;

        final BasicMatrix tmpTranspose = tmpLHS.transpose();

        tmpLHS = tmpLHS.multiplyLeft(tmpTranspose);
        tmpRHS = tmpRHS.multiplyLeft(tmpTranspose);

        return new PrimitiveScalar(tmpRHS.doubleValue(0, 0) / tmpLHS.doubleValue(0, 0));
    }

    public Scalar getRiskAversion() {
        return new BigScalar(myRiskAversion);
    }

    public String[] getSymbols() {
        return ArrayUtils.copyOf(mySymbols);
    }

    public void setRiskAversion(final Number aFactor) {
        myRiskAversion = TypeUtils.toBigDecimal(aFactor);
    }

}


EquilibriumModel.java源码:

/*
 * Copyright 2003-2011 Optimatika (www.optimatika.se)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.ojalgo.finance.portfolio;

import java.math.BigDecimal;
import java.util.List;

import org.ojalgo.ProgrammingError;
import org.ojalgo.matrix.BasicMatrix;
import org.ojalgo.matrix.MatrixFactory;
import org.ojalgo.matrix.PrimitiveMatrix;

abstract class EquilibriumModel extends FinancePortfolio {

    protected static final MatrixFactory FACTORY = PrimitiveMatrix.FACTORY;

    private transient BasicMatrix myAssetReturns;
    private transient BasicMatrix myAssetWeights;
    private final MarketEquilibrium myMarketEquilibrium;
    private transient BigDecimal myMeanReturn;
    private transient BigDecimal myReturnVariance;

    @SuppressWarnings("unused")
    private EquilibriumModel() {

        this(null);

        ProgrammingError.throwForIllegalInvocation();
    }

    protected EquilibriumModel(final MarketEquilibrium aMarketEquilibrium) {

        super();

        myMarketEquilibrium = aMarketEquilibrium.copy();
    }

    public final BasicMatrix getAssetReturns() {
        if (myAssetReturns == null) {
            myAssetReturns = this.calculateAssetReturns();
        }
        return myAssetReturns;
    }

    public final BasicMatrix getAssetWeights() {
        if (myAssetWeights == null) {
            final BasicMatrix tmpAssetWeights = this.calculateAssetWeights();
            if (tmpAssetWeights != null) {
                myAssetWeights = tmpAssetWeights.round(WEIGHT_CONTEXT);
            }
        }
        return myAssetWeights;
    }

    public final BasicMatrix getCovariances() {
        return myMarketEquilibrium.getCovariances();
    }

    public final BigDecimal getImpliedRiskAversion(final BasicMatrix aWeightsVctr, final BasicMatrix aReturnsVctr) {
        return myMarketEquilibrium.getImpliedRiskAversion(aWeightsVctr, aReturnsVctr).toBigDecimal();
    }

    @Override
    public final double getMeanReturn() {
        if (myMeanReturn == null) {
            final BasicMatrix tmpAssetWeights = this.getAssetWeights();
            final BasicMatrix tmpAssetReturns = this.getAssetReturns();
            if ((tmpAssetWeights != null) && (tmpAssetReturns != null)) {
                myMeanReturn = this.calculatePortfolioReturn(tmpAssetWeights, tmpAssetReturns);
            }
        }
        return myMeanReturn.doubleValue();
    }

    @Override
    public final double getReturnVariance() {
        if (myReturnVariance == null) {
            myReturnVariance = this.calculatePortfolioVariance(this.getAssetWeights());
        }
        return myReturnVariance.doubleValue();
    }

    public final BigDecimal getRiskAversion() {
        return myMarketEquilibrium.getRiskAversion().toBigDecimal();
    }

    public final String[] getSymbols() {
        return myMarketEquilibrium.getSymbols();
    }

    @Override
    public final List getWeights() {

        final BasicMatrix tmpAssetWeights = this.getAssetWeights();

        if (tmpAssetWeights != null) {

            return tmpAssetWeights.toBigStore().asList();

        } else {

            return null;
        }
    }

    public final void setRiskAversion(final Number aFactor) {

        myMarketEquilibrium.setRiskAversion(aFactor);

        this.reset();
    }

    protected final BasicMatrix buildColumnVector(final List aColumn) {
        return FACTORY.columns(aColumn);
    }

    protected abstract BasicMatrix calculateAssetReturns();

    protected abstract BasicMatrix calculateAssetWeights();

    protected final BasicMatrix calculateEquilibriumReturns(final BasicMatrix aWeightsVctr) {
        return myMarketEquilibrium.calculateAssetReturns(aWeightsVctr);
    }

    protected final BasicMatrix calculateEquilibriumWeights(final BasicMatrix aReturnsVctr) {
        return myMarketEquilibrium.calculateAssetWeights(aReturnsVctr);
    }

    protected final BigDecimal calculatePortfolioReturn(final BasicMatrix aWeightsVctr, final BasicMatrix aReturnsVctr) {
        return MarketEquilibrium.calculatePortfolioReturn(aWeightsVctr, aReturnsVctr).toBigDecimal();
    }

    protected final BigDecimal calculatePortfolioVariance(final BasicMatrix aWeightsVctr) {
        return myMarketEquilibrium.calculatePortfolioVariance(aWeightsVctr).toBigDecimal();
    }

    protected final void calibrate(final BasicMatrix aWeightsVctr, final BasicMatrix aReturnsVctr) {

        myMarketEquilibrium.calibrate(aWeightsVctr, aReturnsVctr);

        this.reset();
    }

    @Override
    protected void reset() {
        myAssetWeights = null;
        myAssetReturns = null;
        myMeanReturn = null;
        myReturnVariance = null;
    }

    final MarketEquilibrium getMarketEquilibrium() {
        return myMarketEquilibrium;
    }

}

FinancePortfolio.java源码:

/*
 * Copyright 2003-2011 Optimatika (www.optimatika.se)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.ojalgo.finance.portfolio;

import static org.ojalgo.constant.PrimitiveMath.*;

import java.math.BigDecimal;
import java.util.List;

import org.ojalgo.function.implementation.PrimitiveFunction;
import org.ojalgo.random.RandomUtils;
import org.ojalgo.random.process.GeometricBrownianMotion;
import org.ojalgo.type.StandardType;
import org.ojalgo.type.context.NumberContext;

/**
 * 

 * An asset is a financial instrument that can be bought and sold, and  * put in a portfolio. Here, the term is primarily used to describe  * something that can be put in a portfolio. When doing theoretical  * calculations on model portfolios an asset may just as well be an  * index.   * 

 * A portfolio is a collection/combination of assets.  * 

 * Any asset can be viewed as a portfolio containing only itself.  * 

 *  * @author apete  */ public abstract class FinancePortfolio {     protected static final NumberContext WEIGHT_CONTEXT = StandardType.PERCENT;     protected static final boolean BOOLEAN_FALSE = false;     protected FinancePortfolio() {         super();     }     public final GeometricBrownianMotion forecast() {         final double tmpInitialValue = ONE;         final double tmpExpectedValue = ONE + this.getMeanReturn();         final double tmpValueVariance = this.getReturnVariance();         final double tmpHorizon = ONE;         return GeometricBrownianMotion.make(tmpInitialValue, tmpExpectedValue, tmpValueVariance, tmpHorizon);     }     /**      * The mean/expected return of this instrument.       * May return either the absolute or excess return of the instrument.       * The context in which an instance is used should make it clear       * which. Calling {@linkplain #shift(Number)} with an appropriate      * argument will transform between absolute and excess return.       */     public abstract double getMeanReturn();     /**      * The instrument's return variance.      *       * Subclasses must override either {@linkplain #getReturnVariance()} or {@linkplain #getVolatility()}.      */     public double getReturnVariance() {         final double tmpVolatility = this.getVolatility();         return tmpVolatility * tmpVolatility;     }     public final double getSharpeRatio(final Number aRiskFreeReturn) {         if (aRiskFreeReturn != null) {             return (this.getMeanReturn() - aRiskFreeReturn.doubleValue()) / this.getVolatility();         } else {             return this.getMeanReturn() / this.getVolatility();         }     }     /**      * Value at Risk (VaR) is the maximum loss not exceeded with a       * given probability defined as the confidence level, over a given       * period of time.      */     public final double getValueAtRisk(final Number aConfidenceLevel, final Number aTimePeriod) {         final double aReturn = this.getMeanReturn();         final double aStdDev = this.getVolatility();         final double tmpConfidenceScale = SQRT_TWO * RandomUtils.erfi(ONE - (TWO * (ONE - aConfidenceLevel.doubleValue())));         final double tmpTimePeriod = aTimePeriod.doubleValue();         return Math.max(Math.sqrt(tmpTimePeriod) * aStdDev * tmpConfidenceScale - tmpTimePeriod * aReturn, ZERO);     }     /**      * Volatility refers to the standard deviation of       * the change in value of an asset with a specific       * time horizon. It is often used to quantify the risk of the       * asset over that time period.      *       * Subclasses must override either {@linkplain #getReturnVariance()} or {@linkplain #getVolatility()}.      */     public double getVolatility() {         return PrimitiveFunction.SQRT.invoke(this.getReturnVariance());     }     /**      * This method returns a list of the weights of the Portfolio's      * contained assets. An asset weight is NOT restricted to being      * a share/percentage - it can be anything. Most subclasses do      * however assume that the list of asset weights are      * shares/percentages that sum up to 100%. Calling      * {@linkplain #normalise()} will transform any set of weights to      * that form.      */     public abstract List getWeights();     /**      * Normalised weights Portfolio      */     public final FinancePortfolio normalise() {         return new NormalisedPortfolio(this);     }     /**      * Will shift the portfolio mean return (all asset returns)      * upp/down. Can be used to add/remove the risk-free return.      */     public final FinancePortfolio shift(final Number aReturnShift) {         return new ShiftedPortfolio(this, aReturnShift);     }     protected abstract void reset(); }



上一篇:几种redis数据导出导入方式
下一篇:python中pandas的dataframe和numpy的ndarray转换为矩阵

The minute you think of giving up, think of the reason why you held on so long.