Package com.opengamma.analytics.financial.covariance

Source Code of com.opengamma.analytics.financial.covariance.ExponentialWeightedMovingAverageHistoricalVolatilityCalculator

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

import java.util.Iterator;

import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opengamma.analytics.financial.timeseries.returns.ContinuouslyCompoundedTimeSeriesReturnCalculator;
import com.opengamma.analytics.financial.timeseries.returns.TimeSeriesReturnCalculator;
import com.opengamma.timeseries.date.localdate.LocalDateDoubleTimeSeries;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.CalculationMode;

/**
*
* Exponentially weighted moving average (EWMA) volatility calculations put
* variable weight on the values in a time series. The weight is controlled by
* a parameter $\lambda$ which can take any positive value: in most markets,
* the most suitable range is between 0.75 and 1.
* <p>
* The exponential moving average of a time series is given by:
* $$
* \begin{eqnarray*}
* \frac{x_{t-1} + \lambda x_{t-2} + \lambda^2 x_{t-3} + \dots + \lambda^{n-1} x_{t-n}}{1 + \lambda + \lambda^2 + \dots + \lambda^{n-1}}
* \end{eqnarray*}
* $$
* where $x_i$ is the $i^\text{th}$ value in the time series and $\lambda$ is
* the weight.
* <p>
* The exponential weighted volatility is:
* $$
* \begin{eqnarray*}
* \sigma_t = \sqrt{\lambda \sigma_{t-1}^2 + (1 - \lambda)r_t^2}
* \end{eqnarray*}
* $$
* where $\sigma_{t-1}$ is the previous volatility calculation and $r_t$ is the
* continuously compounded return over a single period.  As with other
* historical volatility calculations, the volatility can be annualized by
* scaling by the square root of the number of periods in a year.
*/
public class ExponentialWeightedMovingAverageHistoricalVolatilityCalculator extends HistoricalVolatilityCalculator {
  /** The logger */
  private static final Logger s_logger = LoggerFactory.getLogger(ExponentialWeightedMovingAverageHistoricalVolatilityCalculator.class);
  /** The return calculator */
  private final TimeSeriesReturnCalculator _returnCalculator;
  /** Lambda, the volatility weighting parameter */
  private final double _lambda;
  /** Lambda minus one */
  private final double _lambdaM1;

  /**
   * Although the return calculator can be any {@link TimeSeriesReturnCalculator}, to obtain correct results a {@link ContinuouslyCompoundedTimeSeriesReturnCalculator} should be
   * used. The calculation mode is set to be the default (strict). Although the weight parameter can take any positive value, for most use the range should be $\lambda < 1$;
   * if a value higher outside of this range is used then greater weight will be placed on older return values.
   * @param lambda The weight parameter, not negative
   * @param returnCalculator The return calculator, not null
   */
  public ExponentialWeightedMovingAverageHistoricalVolatilityCalculator(final double lambda, final TimeSeriesReturnCalculator returnCalculator) {
    this(lambda, returnCalculator, getDefaultCalculationMode());
  }

  /**
   * Although the return calculator can be any {@link TimeSeriesReturnCalculator}, to obtain correct results a {@link ContinuouslyCompoundedTimeSeriesReturnCalculator} should be
   * used. Although the weight parameter can take any positive value, for most use the range should be $\lambda < 1$; if a value higher outside of this range is used then
   * greater weight will be placed on older return values.
   * @param lambda The weight parameter, not negative
   * @param returnCalculator The return calculator, not null
   * @param mode The calculation mode, not null
   */
  public ExponentialWeightedMovingAverageHistoricalVolatilityCalculator(final double lambda, final TimeSeriesReturnCalculator returnCalculator, final CalculationMode mode) {
    super(mode);
    ArgumentChecker.notNull(returnCalculator, "return calculator");
    ArgumentChecker.notNull(mode, "calculation mode");
    ArgumentChecker.notNegative(lambda, "lambda");
    if (lambda > 1) {
      s_logger.warn("Weight for EWMA series is greater than one: this is probably not what was intended");
    }
    _lambda = lambda;
    _lambdaM1 = 1 - lambda;
    _returnCalculator = returnCalculator;
  }

  /**
   * @param x The array of price time series. The first time series should be the price; any other arrays are assumed to be a timeseries of dividend payments.
   * @return The exponential weighted historical volatility
   * @throws IllegalArgumentException If x is null, empty or if the first element of the array is null; if the number of values in the time series is less than three; if the
   * dates in the different time series do not coincide
   */
  @Override
  public Double evaluate(final LocalDateDoubleTimeSeries... x) {
    testTimeSeries(x, 3);
    final LocalDateDoubleTimeSeries returnTS = _returnCalculator.evaluate(x);
    final Iterator<Double> iter = returnTS.valuesIterator();
    double returnValue = iter.next();
    double variance = returnValue * returnValue;
    while (iter.hasNext()) {
      returnValue = iter.next();
      variance = _lambda * variance + _lambdaM1 * returnValue * returnValue;
    }
    return Math.sqrt(variance);
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = super.hashCode();
    long temp;
    temp = Double.doubleToLongBits(_lambda);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    result = prime * result + ((_returnCalculator == null) ? 0 : _returnCalculator.hashCode());
    return result;
  }

  @Override
  public boolean equals(final Object obj) {
    if (this == obj) {
      return true;
    }
    if (!super.equals(obj)) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    final ExponentialWeightedMovingAverageHistoricalVolatilityCalculator other = (ExponentialWeightedMovingAverageHistoricalVolatilityCalculator) obj;
    if (Double.doubleToLongBits(_lambda) != Double.doubleToLongBits(other._lambda)) {
      return false;
    }
    return ObjectUtils.equals(_returnCalculator, other._returnCalculator);
  }
}
TOP

Related Classes of com.opengamma.analytics.financial.covariance.ExponentialWeightedMovingAverageHistoricalVolatilityCalculator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.