SSVI calibration#

[2]:
import torch

Define class with parameters to be calibrated#

[18]:
class SSVI(torch.nn.Module):
  def __init__(self, f):
    super().__init__()

    self.theta = torch.nn.parameter.Parameter(torch.Tensor([0.2]))
    self.beta = torch.nn.parameter.Parameter(torch.Tensor([2.]))
    self.rho = torch.nn.parameter.Parameter(torch.Tensor([0.]))

    self.f = f # Forward

  def forward(self, x):
      return self.theta * torch.sqrt(0.5*(1.+self.rho*self.beta*torch.log(x/f)+torch.sqrt((self.beta*torch.log(x/f)+self.rho)**2+(1-self.rho**2))))
[19]:
f = torch.Tensor([1.])
ssvi = SSVI(f)

x = torch.Tensor([0.5,1.,1.5])
y = torch.Tensor([0.25,0.2,0.25])

optimizer = torch.optim.LBFGS(ssvi.parameters(), lr=1)
[20]:
ssvi.forward(x)
[20]:
tensor([0.2328, 0.2000, 0.2139], grad_fn=<MulBackward0>)
[21]:
def closure():
    optimizer.zero_grad()
    output = ssvi.forward(x)
    loss = torch.nn.MSELoss()(output,y)
    loss.backward()
    return loss
[22]:
optimizer.step(closure)
[22]:
tensor(0.0005, grad_fn=<MseLossBackward>)
[23]:
ssvi.theta
ssvi.beta
ssvi.rho
[23]:
Parameter containing:
tensor([0.1607], requires_grad=True)
[24]:
output = ssvi.forward(x)
output
[24]:
tensor([0.2500, 0.2000, 0.2500], grad_fn=<MulBackward0>)
[25]:
import matplotlib.pyplot as plt
[27]:
x = torch.Tensor([0.5,1.,1.5])
y = torch.Tensor([0.25,0.2,0.25])
[28]:
plt.plot(x,y)
plt.plot(x,output.detach().numpy())
[28]:
[<matplotlib.lines.Line2D at 0x19ddbcee3c8>]
../_images/examples_SSVICalibration_12_1.png