com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurveAffineDividends.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurveAffineDividends.java

Source

/**
 * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
 * 
 * Please see distribution for license.
 */
package com.opengamma.analytics.financial.model.interestrate.curve;

import static com.opengamma.analytics.financial.model.volatility.smile.fitting.interpolation.SurfaceArrayUtils.getLowerBoundIndex;

import org.apache.commons.lang.ObjectUtils;

import com.opengamma.analytics.financial.equity.variance.pricing.AffineDividends;
import com.opengamma.analytics.math.curve.ConstantDoublesCurve;
import com.opengamma.analytics.math.curve.Curve;
import com.opengamma.analytics.math.curve.FunctionalDoublesCurve;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.util.serialization.InvokedSerializedForm;
import com.opengamma.util.ArgumentChecker;

/**
 * ForwardCurve for Equity assets that are modelled to pay known discrete dividends 
 * with an affine form: d(i) = alpha[i] + beta[i]*share_price(tau[i])
 */
public class ForwardCurveAffineDividends extends ForwardCurve {

    private final YieldAndDiscountCurve _riskFreeCurve;
    private final AffineDividends _dividends;

    public ForwardCurveAffineDividends(final double spot, final YieldAndDiscountCurve riskFreeCurve,
            final AffineDividends dividends) {
        super(getForwardCurve(spot, riskFreeCurve, dividends));
        _riskFreeCurve = riskFreeCurve;
        _dividends = dividends;
    }

    /**
     * @param spot The spot, greater than zero
     * @param riskFreeCurve The discount curve, not null
     * @param dividends The dividends, not null
     * @return FunctionalDoublesCurve with discrete dividends of an affine form: d(i) = alpha[i] + beta[i]*share_price(tau[i]) 
     */
    protected static Curve<Double, Double> getForwardCurve(final double spot,
            final YieldAndDiscountCurve riskFreeCurve, final AffineDividends dividends) {
        ArgumentChecker.isTrue(spot > 0, "Negative spot. S_0 = {}", spot);
        ArgumentChecker.notNull(riskFreeCurve, "null risk free curve");
        ArgumentChecker.notNull(dividends, "null dividends");
        if (dividends.getNumberOfDividends() == 0) {
            return getForwardCurve(spot, riskFreeCurve, YieldCurve.from(ConstantDoublesCurve.from(0.0)));
        }
        final Function1D<Double, Double> f = new Function1D<Double, Double>() {

            @Override
            public Double evaluate(final Double t) {
                final int n = dividends.getNumberOfDividends();
                final double[] growthFactor = new double[n];
                final double[] accumProd = new double[n];
                final double[] accumSum = new double[n];
                double prod = 1.0;
                double sum = 0.0;
                for (int i = 0; i < n; i++) {
                    prod *= (1 - dividends.getBeta(i));
                    accumProd[i] = prod;
                    growthFactor[i] = prod / riskFreeCurve.getDiscountFactor(dividends.getTau(i));
                    sum += dividends.getAlpha(i) / growthFactor[i];
                    accumSum[i] = sum;
                }
                if (t < dividends.getTau(0)) {
                    return spot / riskFreeCurve.getDiscountFactor(t);
                }
                final int index = getLowerBoundIndex(dividends.getTau(), t);
                final double total = accumSum[index];
                return accumProd[index] / riskFreeCurve.getDiscountFactor(t) * (spot - total);
            }
        };

        return new FunctionalDoublesCurve(f) {
            public Object writeReplace() {
                return new InvokedSerializedForm(ForwardCurveAffineDividends.class, "getForwardCurve", spot,
                        riskFreeCurve, dividends);
            }
        };
    }

    public YieldAndDiscountCurve getRiskFreeCurve() {
        return _riskFreeCurve;
    }

    public AffineDividends getDividends() {
        return _dividends;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + getDriftCurve().hashCode();
        result = prime * result + getForwardCurve().hashCode();
        long temp;
        temp = Double.doubleToLongBits(getSpot());
        result = prime * result + (int) (temp ^ (temp >>> 32));
        result = prime * result + getRiskFreeCurve().hashCode();
        result = prime * result + getDividends().hashCode();
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final ForwardCurveAffineDividends other = (ForwardCurveAffineDividends) obj;
        if (!ObjectUtils.equals(getRiskFreeCurve(), other.getRiskFreeCurve())) {
            return false;
        }
        if (!ObjectUtils.equals(getDividends(), other.getDividends())) {
            return false;
        }
        if (Double.doubleToLongBits(getSpot()) != Double.doubleToLongBits(other.getSpot())) {
            return false;
        }
        return true;
    }

}