O conceito de interpolação, amplamente difundido, pode ser interpretado no mundo de finanças como o método utilizado para definição de uma taxa intermediária entre dois vértices de vencimento já conhecidos em uma curva de juros.
Um simples exemplo:
Para a curva PRÉ-DI do dia 13/04/2020, 2 pontos escolhidos ao acaso são:

Um banco ao cotar uma operação em du252, deveria cobrar qual taxa para os prazos [400,401,…,419]?
Visto que o padrão de interpolação da curva PRÉ-DI é Exponencial Flat Forward, o gráfico destas taxas intermediárias é apresentado:



Como fazer um código simples que consiga interpretar em que local o ponto de interpolação se encontra dentre os vértices disponíveis da curva e que consiga achar o ponto anterior e o posterior para uso nas mais diversas fórmulas de interpolação?
class interpolador:
def __init__(self, p, df, column, dc=252):
self.df = df
self.column = column
self.p = p
self.dc = dc
self.x_axis = list(df.index)
self.y_axis = list(df[column])
self._config(self.p)
def _config(self, p):
"""
Função que configura o objeto para definir o ponto anterior e posterior para interpolar
"""
self.x1 = min(self.df.index, key=lambda a:abs(a-p))
if p-self.x1>0: self.x2 = self.x_axis[self.x_axis.index(self.x1)+1]
elif p-self.x1==0: self.x2 = self.x1
elif p-self.x1<0:
self.x2 = self.x1
self.x1 = self.x_axis[self.x_axis.index(self.x1)-1]
self.y1 = self.y_axis[self.x_axis.index(self.x1)]
self.y2 = self.y_axis[self.x_axis.index(self.x2)]
A função “_config” é responsável por achar os números mais próximos do ponto, sendo o número de limite superior determinado pelo valor da distância encontrada através da função lambda onde a é cada ponto do DataFrame e p é o ponto desejado de interpolação.
Depois de encontrar os pontos o próximo passo é colocá-los na equação apresentada:
def exp(self):
"""
Função de interpolação exponencial flat forward
"""
x1,x2,y1,y2,p,dc = self.x1, self.x2, self.y1, self.y2, self.p, self.dc
if x1-x2!=0:
return ((((1+y1)**(x1/dc))*(((1+y2)**(x2/dc))/((1+y1)**(x1/dc)))**((p-x1)/(x2-x1)))**(dc/p))-1
else:
return y1
Como bônus deixo o código de interpolação linear e o que interpola um vetor de períodos passado:
def lin(self):
"""
Função de interpolação linear nas taxas
"""
x1,x2,y1,y2,p = self.x1, self.x2, self.y1, self.y2, self.p
if x1-x2!=0:
return y1+(p-x1)*(y2-y1)/(x2-x1)
else:
return y1
def multi_intp(self, arr=[], t='exp'):
interpolados=[]
for x in range(len(arr)):
self.p = arr[x]
self._config(arr[x])
if t.lower()=='exp': interpolados.append(self.exp())
elif t.lower()=='lin': interpolados.append(self.lin())
return interpolados
-M.R.