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>]