<jupyter_start><jupyter_text>Test Autograd  Librerías<jupyter_code>import autograd.numpy as np
from autograd import grad
from functools import partial
from bisect import bisect_right<jupyter_output><empty_output><jupyter_text>First Try<jupyter_code>def present_value(cashflows: np.array, dfs: np.array) -> float:
    return np.dot(cashflows, dfs)
grad_pv = grad(present_value, argnum=0)
valor_tasa = .1

grad_pv(np.array([5.0, 100.0]), np.array([(1+valor_tasa/2)**-1, (1+valor_tasa)**-1]))
(1+valor_tasa/2)**-1
present_value(np.array([5, 100]), np.array(
    [(1+valor_tasa/2)**-1, (1+valor_tasa)**-1]))
pv = partial(present_value, np.array([5.0, 100.0]))
grad_pv2 = grad(pv)
pv(np.array([(1+valor_tasa/2)**-1, (1+valor_tasa)**-1]))
grad_pv2(np.array([(1+valor_tasa/2)**-1, (1+valor_tasa)**-1]))
def two(x, y):
    return x*y
grad_two = grad(two)
grad_two(1.0, 2.0)<jupyter_output><empty_output><jupyter_text>Más Estrucuturado<jupyter_code>tenors = np.array([1.0, 365.0])
rates = np.array([.05, .1])
def lin_interpol(tenors, rates, tenor):
    if tenor >= tenors[len(tenors) - 1]:
        return rates[len(tenors) - 1]
    elif tenor <= tenors[0]:
        return rates[0]
    else:
        i = bisect_right(tenors, tenor) - 1
        m = (rates[i + 1] - rates[i]) / (tenors[i + 1] - tenors[i])
        return rates[i] + m * (tenor - tenors[i])
def df(rate, tenor):
    return (1 + rate)**(-tenor / 365.0) 
def present_value(interp, disc, cashflow, tenor, tenors, rates):
    rate = interp(tenors, rates, tenor)
    return df(rate, tenor) * cashflow
present_value(lin_interpol, df, 100.0, 189.0, tenors, rates)
drates = grad(present_value, argnum=5)
drates(lin_interpol, df, 100.0, 180.0, tenors, rates)
10000*10*4*6/1000/60<jupyter_output><empty_output><jupyter_text>Bootstrapping (1 Sólo Fujo)<jupyter_code>cashflow = 107.5
plazo = 365.0<jupyter_output><empty_output><jupyter_text>**Problema:** encontrar la tasa a 365 días que haga que el valor presente de este flujo sea igual a 100.<jupyter_code>pv = partial(present_value, lin_interpol, df)
pv(cashflow, plazo, tenors, rates)
g = grad(pv, argnum=3)
g(cashflow, plazo, tenors, rates)
rates0 = np.array([.05, 0.0])
def solve(cashflow, tenor, obj, tenors, rates, pv):
    epsilon = .000001
    g = grad(pv, argnum=3)
    rates_ = np.array([rates[0], rates[1]])
    delta = 1
    while delta > epsilon:
        r1 = rates_[1] - (pv(cashflow, tenor, tenors, rates_) - obj) / g(cashflow, tenor, tenors, rates_)[1]
        delta = abs(r1 - rates_[1])
        if type(r1) is np.float64:
            rates_[1] = r1
        else:
            rates_[1] = r1._value
    return r1
solve(cashflow, plazo, 100.0, tenors, rates0, pv)
rates0
gsolve = grad(solve, argnum=0)
gsolve(cashflow, plazo, 100.0, tenors, rates0, pv)<jupyter_output><empty_output><jupyter_text>Bootstrapping (Varios Flujos)<jupyter_code>def kron(i, j):
    return int(i == j)
def dfs(rates, tenors):
    return np.array([df(z[0], z[1]) for z in zip(rates, tenors)])
rates = np.array([.01, .075])
dfs(rates, tenors)
def lin_interpols(tenors, rates, new_tenors):
    return np.array([lin_interpol(tenors, rates, t) for t in new_tenors])
lin_interpols(tenors, rates, [90.0, 180.0, 270.0])
def fixed_rate_leg(nocional, tasa, num_cupones):
    return np.array([.5 * 365.0 * i for i in range(1, num_cupones + 1)]), \
        np.array([nocional * (kron(i, num_cupones) + tasa / 2.0)
                  for i in range(1, num_cupones + 1)])
fixed_rate_leg(100, .06, 2)
def present_value_2(interp, disc, cashflows_tenors, cashflows, curve_tenors, curve_rates):
    cashflow_rates = interp(curve_tenors, curve_rates, cashflows_tenors)
    return np.dot(dfs(cashflow_rates, cashflows_tenors), cashflows)
present_value_2(lin_interpols, dfs, fixed_rate_leg(100, .06, 2)[0],
               fixed_rate_leg(100, .06, 2)[1], tenors, rates)
def pv_fixed_leg(interp, disc, nocional, tasa, num_cupones, curve_tenors, curve_rates):
    plazos, flujos = fixed_rate_leg(nocional, tasa, num_cupones)
    return present_value_2(interp, disc, plazos, flujos, curve_tenors, curve_rates)
pv_fixed_leg(lin_interpols, dfs, 100.0, .06, 2, tenors, rates)
pv_2 = partial(pv_fixed_leg, lin_interpols, dfs)
pv_2(100.0, .06, 2, tenors, rates)
gpvleg = grad(pv_2, argnum=1)
gpvleg(100.0, .06, 2, tenors, rates)
def solve_2(nocional, tasa, num_cupones, obj, tenors, rates, pv):
    epsilon = .000001
    g = grad(pv, argnum=4)
    rates_ = np.array([r for r in rates] + [0.0,])
    print(rates_)
    which = len(rates_) - 1
    print(f'which: {which}')
    delta = 1
    while delta > epsilon:
        q = (pv(nocional, tasa, num_cupones, tenors, rates_) - obj)
        q /= g(nocional, tasa, num_cupones, tenors, rates_)[which]
        r1 = rates_[which] - q
        print(r1)
        delta = abs(r1 - rates_[which])
        print(f'delta: {delta}')
        if type(r1) is np.float64:
            rates_ = np.array([r for r in rates] + [r1,])
        else:
            rates_ = np.array([r for r in rates] + [r1._value,])
    return r1
rates0 = np.array([.05,])
r_sol = solve_2(100.0, .06, 2, 100.0, tenors, rates0, pv_2)
print(f'sol: {r_sol}')
rates_sol = np.array([rates0[0], r_sol])
pv_2(100.0, .06, 2, tenors, rates_sol)
gs2 = grad(solve_2, argnum=1)
gs2(100.0, .06, 2, 100.0, tenors, rates0, pv_2)
grad(solve_2, argnum=5)(100.0, .06, 2, 100.0, tenors, rates0, pv_2)
tenors0 = [1.0, 365.0, 730.0]
rates0 = [0.05, r_sol]
solve_2(100.0, .062, 4, 100.0, tenors0, rates0, pv_2)
grad(solve_2, argnum=1)(100.0, .062, 4, 100.0, tenors0, rates0, pv_2)<jupyter_output>[0.05       0.06098168 0.        ]
which: 2
Autograd ArrayBox with value 0.05760642144390602
delta: Autograd ArrayBox with value 0.05760642144390602
Autograd ArrayBox with value 0.06303452556938739
delta: Autograd ArrayBox with value 0.005428104125481371
Autograd ArrayBox with value 0.06307638835226625
delta: Autograd ArrayBox with value 4.186278287886258e-05
Autograd ArrayBox with value 0.06307639080868392
delta: Autograd ArrayBox with value 2.456417666496513e-09
{'fraction_non_alphanumeric': 0.15309012160586374, 'fraction_numerical': 0.08662335498917208, 'mean_word_length': 4.171403962101636, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '504324', 'license': 'MIT', 'n_tokens_mistral': 2818, 'n_tokens_neox': 2505, 'n_words': 560, 'path': 'test_autograd.ipynb', 'repo_name': 'adiaz-efaa/Curves', 'size': '6003'}