AffineDividendStream.java

package net.finmath.equities.marketdata;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * Class to store and handle a stream of affine dividends
 *
 * @author Andreas Grotz
 */
public class AffineDividendStream {

	private final AffineDividend[] dividendStream;

	public AffineDividendStream(final AffineDividend[] dividendStream) {
		final List<AffineDividend> diviList = Arrays.asList(dividendStream);
		diviList.sort(Comparator.comparing(pt -> pt.getDate()));
		this.dividendStream = diviList.toArray(new AffineDividend[0]);
	}

	public ArrayList<LocalDate> getDividendDates() {
		final ArrayList<LocalDate> dates = new ArrayList<LocalDate>();
		for(final AffineDividend divi : dividendStream) {
			dates.add(divi.getDate());
		}
		return dates;
	}

	public double getDividend(final LocalDate date, final double stockPrice) {
		for(final AffineDividend divi : dividendStream) {
			if(divi.getDate() == date) {
				return divi.getDividend(stockPrice);
			}
		}
		return 0.0;
	}

	public double getProportionalDividendFactor(final LocalDate date) {
		for(final AffineDividend divi : dividendStream) {
			if(divi.getDate() == date) {
				return divi.getProportionalDividendFactor();
			}
		}
		return 1.0;
	}

	public double getCashDividend(final LocalDate date) {
		for(final AffineDividend divi : dividendStream) {
			if(divi.getDate() == date) {
				return divi.getCashDividend();
			}
		}
		return 0.0;
	}

	public static AffineDividendStream getAffineDividendsFromCashDividends(
			AffineDividendStream cashDividends,
			Map<LocalDate, Double> conversionRates,
			LocalDate valDate,
			double spot,
			YieldCurve repoCurve) {

		// This method takes a stream of cash dividends and converts them to affine dividends,
		// by transforming a part of each cash dividend to a proportional dividend.
		// The percentage of each cash dividend to be transformed to a proportional dividend
		// is specified in the member propDividendFactor of the dividend.
		// The transformation is done in an arbitrage-free way, i.e. the forward structure is preserved.
		// This method is usefull in practice, where traders use dividend futures as input, and transform
		// a part to a proportional dividend (the further away the dividend, the higher the proportional part
		// and the lower the cash part.

		final List<LocalDate> dates = cashDividends.getDividendDates();

		final List<AffineDividend> affineDividends = new ArrayList<AffineDividend>();

		for(final LocalDate date : dates) {
			if(date.isBefore(valDate)) {
				continue;
			}
			assert cashDividends.getProportionalDividendFactor(date) == 0.0
					: "Proportional dividend different from zero for date " + date;

			final double cashDividend = cashDividends.getCashDividend(date);

			double fwd = spot;
			for(final LocalDate otherDate : dates) {
				if(otherDate.isBefore(date) && !otherDate.isBefore(valDate)) {
					fwd -= cashDividends.getCashDividend(otherDate)
							* repoCurve.getForwardDiscountFactor(valDate, otherDate);
				}
			}

			final double q = conversionRates.get(date) * cashDividend
					* repoCurve.getForwardDiscountFactor(valDate, date) / fwd;

			affineDividends.add(
					new AffineDividend(
							date,
							(1.0 - conversionRates.get(date)) * cashDividend,
							q));
		}

		return new AffineDividendStream(affineDividends.toArray(new AffineDividend[0]));
	}
}