# Curves

## Installation

using Pkg


## Introduction

A Curve in this package is essentially a collection of points (x, y), together with an interpolation and extrapolation method.

Curve objects have a number of standard calculation function defined (like addition, multiplication, logarithm), thus they can be used in algebraic expressions analogue to scalars.

### How it Works

Operations on Curves alone (e.g. exp(c), log(c)) or with scalars (e.g. c+1 or 2c) are defined point-wise on the y-values of the Curve.

Operations between 2 Curve objects (noted as c1 and c2) are defined as follows:

1. Interpolate c1 to the x-values of c2.
2. Do the operation (e.g. adding) on the y-values of c2 and the interpolated y-values of c1.
3. Repeat steps 1. and 2., but interpolate c2 to the x-values of c1.
4. Combine the results of both interpolations and create a new Curve object for the result.

Technically, this package is based on Interpolations.jl. Support of log-interpolation on both axis is added by this package.

Curve objects are defined to be immutable, thus every operation creates a new Curve object as output.

## Tenors

In financial use cases, the x-axis of curves is often given in maturity tenors, e.g. 1W or 3M. The Tenor type is introduced to support such a notation for the x-axis of curves.

Example:

t = Tenor.(("1D", "3W", "1M", "10y", "12m"))
@assert t == (Tenor(Curves.TDays, 1), Tenor(Curves.TWeeks, 3), Tenor(Curves.TMonths, 1),
Tenor(Curves.TYears, 10), Tenor(Curves.TYears, 1))


Note that the tenor 12M is automatically converted to 1Y to avoid ambiguities.

Tenors can be directly used in Curves:

curve_from_tenors = Curve(["1D", "3W", "1M", "10y"], [0.5, 0.7, 0.75, 0.83])
val = interpolate("1W", curve_from_tenors)


As a shortcut for creating tenor objects, a string macro is provided:

@assert t"1W" == Tenor("1W")


### Use Case

The use case I had in mind was interest rate / FX curves for mathematical finance applications. The Curve objects make it easier to shift market data, e.g. for sensitivity or scenario P&L calculation, or to calculate such shift sizes based on market data time series.

Example:

using Curves
using Plots

# construct zero interest rate curve
c_zero_base = Curve(["2D", "1w", "1M", "3M", "6M", "12M"], [0.5, 0.7, 0.75, 0.83, 1.1, 1.5])

# plotting - package Plots required
plot(c_zero_base.x, c_zero_base.y)

# define zero rate shifts (e.g. for stress testing or sensitivities)
c_shifts = Curve([2, 185, 360], [0.1, -0.1, 0.2])

# shift curve
c_shifted = c_zero_base + c_shifts

# calculate discount factors for the unshifted and shifted curves
c_base_df=apply((x,y) -> exp(-x*y/100/365), c_zero_base, logy=true)
c_shifted_df = apply((x,y) -> exp(-x*y/100/365), c_shifted, logy=true)

# calculate log-returns of discount factors
log_ret = log(c_shifted_df/c_base_df)

# apply log returns to the base curve - this should give the shifted curve back
curve_scenario = *(c_base_df, exp(log_ret), logy=true)
@assert curve_scenario ≈ c_shifted_df

plot(curve_scenario.x, curve_scenario.y)


## Ideas for Further Improvements

• Support of more operations
• Interactions with QuantLib.jl curve objects
• Multi-dimensional structures (especially 2d, e.g. for Volatility surfaces)