All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.quantarray.anaheim.finance.VolatilitySurfaceInterpolation.scala Maven / Gradle / Ivy

The newest version!
package com.quantarray.anaheim.finance

import com.quantarray.anaheim.numerics.Interpolate
import org.apache.commons.math3.analysis.BivariateFunction
import org.apache.commons.math3.analysis.interpolation._

import java.time.{LocalDate, ZoneOffset}
import scala.collection.mutable
import scala.util.Try

trait VolatilitySurfaceInterpolation {

  trait Interpolate2[T, S, F] extends Interpolate[(T, S), Option[Double], VolatilitySurface[T, S]] {

    def interpolator: BivariateGridInterpolator

    def tenorAxis(t: T): Double

    def strikeAxis(s: S): Double

    protected def function(f: VolatilitySurface[T, S]): BivariateFunction = {

      val ts = f.points.map(_.tenorAxis).distinct
      val ss = f.points.map(_.strikeAxis).distinct

      val xs = ts.map(tenorAxis).toArray
      val ys = ss.map(strikeAxis).toArray
      val zs = f.points.map(_.volatility).grouped(ss.length).map(_.toArray).toArray

      interpolator.interpolate(xs, ys, zs)
    }

    override def apply(f: VolatilitySurface[T, S], k: (T, S)): Option[Double] = {

      val bf = function(f)
      Try(bf.value(tenorAxis(k._1), strikeAxis(k._2))).toOption
    }
  }

  trait CachingInterpolate2[T, S, F] extends Interpolate2[T, S, VolatilitySurface[T, S]] {

    def interpolator: BivariateGridInterpolator

    def tenorAxis(t: T): Double

    def strikeAxis(s: S): Double

    val cache = mutable.Map.empty[VolatilitySurface[T, S], BivariateFunction]

    override def apply(f: VolatilitySurface[T, S], k: (T, S)): Option[Double] = {

      cache.get(f) match {
        case Some(bf) => Try(bf.value(tenorAxis(k._1), strikeAxis(k._2))).toOption
        case _ =>

          val bf = function(f)
          cache.put(f, bf)
          Try(bf.value(tenorAxis(k._1), strikeAxis(k._2))).toOption
      }
    }
  }

  object bicubic {

    implicit object LocalDateMoneynessInterpolate extends Interpolate2[LocalDate, Moneyness, VolatilitySurface[LocalDate, Moneyness]] {

      val interpolator = new BicubicInterpolator

      override def tenorAxis(t: LocalDate): Double = t.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli.toDouble

      override def strikeAxis(s: Moneyness): Double = s.value
    }

    object caching {

      implicit object CachingLocalDateMoneynessInterpolate extends CachingInterpolate2[LocalDate, Moneyness, VolatilitySurface[LocalDate, Moneyness]] {

        val interpolator = new BicubicInterpolator

        override def tenorAxis(t: LocalDate): Double = t.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli.toDouble

        override def strikeAxis(s: Moneyness): Double = s.value
      }
    }

  }
}

object VolatilitySurfaceInterpolation extends VolatilitySurfaceInterpolation




© 2015 - 2024 Weber Informatics LLC | Privacy Policy