<jupyter_start><jupyter_text>Construcción y Uso de Una Curva Cero Cupón Se importa la versión de `QC_Financial` compilada para Python3.<jupyter_code>from finrisk import QC_Financial_3 as Qcf<jupyter_output><empty_output><jupyter_text>Librerías adicionales.<jupyter_code>import pandas as pd<jupyter_output><empty_output><jupyter_text>Para formateo de `pandas.DataFrames`.<jupyter_code>format_dict = {'nominal': '{0:,.2f}', 'amort': '{0:,.2f}', 'interes': '{0:,.2f}', 'flujo': '{0:,.2f}', 'amortizacion': '{0:,.2f}',
               'icp_inicial': '{0:,.2f}', 'icp_final': '{0:,.2f}', 'uf_inicial': '{0:,.2f}', 'uf_final': '{0:,.2f}',
               'valor_tasa': '{0:,.4%}', 'spread': '{0:,.4%}', 'gearing': '{0:,.2f}',
               'amort_moneda_pago': '{0:,.2f}', 'interes_moneda_pago': '{0:,.2f}', 'valor_indice_fx': '{0:,.2f}'}<jupyter_output><empty_output><jupyter_text>Construcción de la Curva La construcción de una curva se hace en varios pasos.  Vectores de Float e Int<jupyter_code># Este es un vector de números enteros (grandes, de ahí la l (long))
lvec = Qcf.long_vec()
# Agregar un elemento
lvec.append(1000)
# Este es un vector de números double.
vec = Qcf.double_vec()
# Agregar un elemento
vec.append(.025)
# Obtener ese elemento
print("Tasa: {0:,.2%}".format(vec[0]))<jupyter_output>Tasa: 2.50%<jupyter_text>Objeto Curva Es simplemente un `long_vec` que representa las abscisas de la curva y un `double_vec` que representa las ordenadas. Ambos vectores deben tener el mismo largo.<jupyter_code>zcc = Qcf.QCCurve(lvec, vec)<jupyter_output><empty_output><jupyter_text>Un elemento de una curva se representa como un par abscisa, ordenada.<jupyter_code>zcc.get_values_at(0)<jupyter_output><empty_output><jupyter_text>Se obtiene el plazo en una posición de la curva.<jupyter_code>zcc.get_values_at(0).tenor<jupyter_output><empty_output><jupyter_text>Se obtiene la tasa en una posición de la curva.<jupyter_code>zcc.get_values_at(0).value<jupyter_output><empty_output><jupyter_text>Se agrega un par (plazo, valor) a la curva.<jupyter_code>zcc.set_pair(100, .026)<jupyter_output><empty_output><jupyter_text>Se verifica.<jupyter_code># Plazo
zcc.get_values_at(1).tenor
# Valor
zcc.get_values_at(1).value<jupyter_output><empty_output><jupyter_text>Se agrega un par más.<jupyter_code>zcc.set_pair(370, .03)<jupyter_output><empty_output><jupyter_text>Se itera sobre la curva mostrando sus valores<jupyter_code>for i in range(0, zcc.get_length()):
    pair = zcc.get_values_at(i)
    print("Tenor: {0:} Valor: {1:.4%}".format(pair.tenor, pair.value))<jupyter_output>Tenor: 100 Valor: 2.6000%
Tenor: 370 Valor: 3.0000%
Tenor: 1000 Valor: 2.5000%<jupyter_text>Se define un interpolador. En este caso, un interpolador lineal.<jupyter_code>lin = Qcf.QCLinearInterpolator(zcc)<jupyter_output><empty_output><jupyter_text>Se hace una prueba.<jupyter_code>print("Tasa en {0:} es igual a {1:.4%}".format(10, lin.interpolate_at(10)))<jupyter_output>Tasa en 10 es igual a 2.6000%<jupyter_text>Para completar el proceso se define una fracción de año, un factor de capitalización y un tipo de tasa. Con estos objetos se termina de dar de alta una curva cero.<jupyter_code>yf = Qcf.QCAct360()
wf = Qcf.QCLinearWf()
tasa = Qcf.QCInterestRate(.01, yf, wf)
zz = Qcf.ZeroCouponCurve(lin, tasa)<jupyter_output><empty_output><jupyter_text>El interpolador permite obtener una tasa a cualquier plazo.<jupyter_code>plazo = 365
print("Tasa en {0:} es igual a {1:.4%}".format(plazo, zz.get_rate_at(plazo)))
type(zz)<jupyter_output><empty_output><jupyter_text>TODO: mostrar los otros métodos disponibles.<jupyter_code>zz.get_discount_factor_at(1)<jupyter_output><empty_output><jupyter_text>Otros métodos: Tasa Forward<jupyter_code>d1 = 30
d2 = 90
print("Tasa forward entre los días {0:} y {1:}: {2:.4%}".format(
    d1, d2, zz.get_forward_rate(d1, d2)))<jupyter_output>Tasa forward entre los días 30 y 90: 2.5944%<jupyter_text>Derivada del factor de capitalización de la Tasa Forward. El argumento representa el índice de la tasa de la curva.<jupyter_code>zz.fwd_wf_derivative_at(2)<jupyter_output><empty_output><jupyter_text>Valorizar Se da de alta un objeto `PresentValue`.<jupyter_code>pv = Qcf.PresentValue()<jupyter_output><empty_output><jupyter_text>Depósito a Plazo Se utilizará como instrumento un depósito a plazo en CLP o USD. Este instrumento se modela como un `SimpleCashflow`. Este, a su vez se construye con un monto, una fecha y una moneda.<jupyter_code># Con estas variables vamos a construir
fecha_vcto = Qcf.QCDate(12, 1, 2020)
monto = 10000000.0
clp = Qcf.QCCLP()

# Se construye el depósito
depo = Qcf.SimpleCashflow(fecha_vcto, monto, clp)
print("Monto del depósito: {0:,.0f}".format(depo.amount()))<jupyter_output>Monto del depósito: 10,000,000<jupyter_text>Se define una fecha de valorización y se calcula el valor presente del depo.<jupyter_code>fecha_hoy = Qcf.QCDate(17, 1, 2020)
print("Valor presente depo: {0:,.0f}".format(pv.pv(fecha_hoy, depo, zz)))<jupyter_output>Valor presente depo: 0<jupyter_text>Se verifica *a mano* el resultado.<jupyter_code>plazo = fecha_hoy.day_diff(fecha_vcto)
print("Plazo:", plazo)
tasa_int = zz.get_rate_at(plazo)
print("Tasa: {0:,.4%}".format(tasa_int))
valor_presente = monto * (1 + tasa_int)**(-plazo / 365)
print("Valor presente a mano: {0:,.0f}".format(valor_presente))<jupyter_output>Valor presente a mano: 10,003,517<jupyter_text>Renta Fija Local<jupyter_code># Se da de alta los parámetros requeridos
rp = Qcf.RecPay.RECEIVE
fecha_inicio = Qcf.QCDate(1, 3, 2015)
fecha_final = Qcf.QCDate(1, 3, 2026)
bus_adj_rule = Qcf.BusyAdjRules.NO
periodicidad = Qcf.Tenor('6M')
periodo_irregular = Qcf.StubPeriod.NO
calendario = Qcf.BusinessCalendar(fecha_inicio, 20)
lag_pago = 0
nominal = 100.0
amort_es_flujo = True
valor_tasa_fija = .045
tasa_cupon = Qcf.QCInterestRate(
    valor_tasa_fija, Qcf.QC30360(), Qcf.QCLinearWf())
moneda = Qcf.QCCLP()
es_bono = True

# Se da de alta el objeto
pata_bono = Qcf.LegFactory.build_bullet_fixed_rate_leg(
    rp,
    fecha_inicio,
    fecha_final,
    bus_adj_rule,
    periodicidad,
    periodo_irregular,
    calendario,
    lag_pago,
    nominal,
    amort_es_flujo,
    tasa_cupon,
    moneda,
    es_bono
)
tera = Qcf.QCInterestRate(.045466, Qcf.QCAct365(), Qcf.QCCompoundWf())
bono_chileno = Qcf.ChileanFixedRateBond(pata_bono, tera)
fecha_valor = Qcf.QCDate(24, 7, 2020)
tir = Qcf.QCInterestRate(.0147, Qcf.QCAct365(), Qcf.QCCompoundWf())
print(f'Valor presente: {bono_chileno.present_value(fecha_valor, tir):,.8f}')
print(f'Precio: {bono_chileno.price(fecha_valor, tir):,.2%}')
print(f'Valor par: {bono_chileno.valor_par(fecha_valor):,.18f}')
bono = Qcf.FixedRateBond(pata_bono)
print(f'Valor presente: {bono.present_value(fecha_valor, tir):,.8f}')
print(f'Precio: {bono.price(fecha_valor, tir):,.8f}')<jupyter_output>Valor presente: 118.05163190
Precio: 116.26413190<jupyter_text>Curvas Reales Construyamos dos curvas a partir de data real. Primero la curva CAMARACLP.<jupyter_code>curva = pd.read_excel("data/20200305_camaraclp.xlsx")
curva.style.format({"tasa": "{0:,.4%}"})<jupyter_output><empty_output><jupyter_text>Se da de alta un vector con los plazos (variable de tipo `long`) y un vector con las tasas (variable de tipo `double`).<jupyter_code>lvec1 = Qcf.long_vec()
vec1 = Qcf.double_vec()
for index, row in curva.iterrows():
    lvec1.append(int(row['plazo']))
    vec1.append(row['tasa'])<jupyter_output><empty_output><jupyter_text>Luego, con una curva, un interpolador y un objeto `QCInterestRate`(que indica la convención de las tasas de la curva) se construye una curva cupón cero.<jupyter_code>zcc1 = Qcf.QCCurve(lvec1, vec1)
lin1 = Qcf.QCLinearInterpolator(zcc1)
zz1 = Qcf.ZeroCouponCurve(lin1, tasa)<jupyter_output><empty_output><jupyter_text>Luego, la curva LIBORUSD3M.<jupyter_code>curva_libor = pd.read_excel("data/20200122_libor3mbbg.xlsx")
curva_libor.style.format({"tasa": "{0:,.4%}"})
lvec2 = Qcf.long_vec()
vec2 = Qcf.double_vec()
for index, row in curva_libor.iterrows():
    lvec2.append(int(row['plazo']))
    vec2.append(row['tasa'])

zcc2 = Qcf.QCCurve(lvec2, vec2)
lin2 = Qcf.QCLinearInterpolator(zcc2)
zz2 = Qcf.ZeroCouponCurve(lin2, tasa)<jupyter_output><empty_output><jupyter_text>Finalmente, la curva CAMARACLF.<jupyter_code>curva_camara_clf = pd.read_excel("data/20200305_camaraclf.xlsx")
curva_camara_clf.style.format({"tasa": "{0:,.4%}"})
lvec3 = Qcf.long_vec()
vec3 = Qcf.double_vec()
for index, row in curva_camara_clf.iterrows():
    lvec3.append(int(row['plazo']))
    vec3.append(row['tasa'])

zcc3 = Qcf.QCCurve(lvec3, vec3)
lin3 = Qcf.QCLinearInterpolator(zcc3)
zz3 = Qcf.ZeroCouponCurve(lin3, tasa)<jupyter_output><empty_output><jupyter_text>Curvas para Sensibilidad Se define que vértice de la curva se quiere desplazar.<jupyter_code>vertice = 13<jupyter_output><empty_output><jupyter_text>Se construyen las curvas con ese vértice 1 punto básico más arriba y 1 punto básico más abajo.<jupyter_code>bp = .0001
vec_sens_up = Qcf.double_vec()
vec_sens_down = Qcf.double_vec()
for index, row in curva.iterrows():
    if index == vertice:
        vec_sens_up.append(row['tasa'] + bp)
        vec_sens_down.append(row['tasa'] - bp)
    else:
        vec_sens_up.append(row['tasa'])
        vec_sens_down.append(row['tasa'])

zcc_sens_up = Qcf.QCCurve(lvec1, vec_sens_up)
lin_sens_up = Qcf.QCLinearInterpolator(zcc_sens_up)
zz_sens_up = Qcf.ZeroCouponCurve(lin_sens_up, tasa)

zcc_sens_down = Qcf.QCCurve(lvec1, vec_sens_down)
lin_sens_down = Qcf.QCLinearInterpolator(zcc_sens_down)
zz_sens_down = Qcf.ZeroCouponCurve(lin_sens_down, tasa)
vec2_sens_up = Qcf.double_vec()
vec2_sens_down = Qcf.double_vec()
for index, row in curva_libor.iterrows():
    if index == vertice:
        vec2_sens_up.append(row['tasa'] + bp)
        vec2_sens_down.append(row['tasa'] - bp)
    else:
        vec2_sens_up.append(row['tasa'])
        vec2_sens_down.append(row['tasa'])

zcc2_sens_up = Qcf.QCCurve(lvec2, vec2_sens_up)
lin2_sens_up = Qcf.QCLinearInterpolator(zcc2_sens_up)
zz2_sens_up = Qcf.ZeroCouponCurve(lin2_sens_up, tasa)

zcc2_sens_down = Qcf.QCCurve(lvec2, vec2_sens_down)
lin2_sens_down = Qcf.QCLinearInterpolator(zcc2_sens_down)
zz2_sens_down = Qcf.ZeroCouponCurve(lin2_sens_down, tasa)
vec3_sens_up = Qcf.double_vec()
vec3_sens_down = Qcf.double_vec()
for index, row in curva_camara_clf.iterrows():
    if index == vertice:
        vec3_sens_up.append(row['tasa'] + bp)
        vec3_sens_down.append(row['tasa'] - bp)
    else:
        vec3_sens_up.append(row['tasa'])
        vec3_sens_down.append(row['tasa'])

zcc3_sens_up = Qcf.QCCurve(lvec3, vec3_sens_up)
lin3_sens_up = Qcf.QCLinearInterpolator(zcc3_sens_up)
zz3_sens_up = Qcf.ZeroCouponCurve(lin3_sens_up, tasa)

zcc3_sens_down = Qcf.QCCurve(lvec3, vec3_sens_down)
lin3_sens_down = Qcf.QCLinearInterpolator(zcc3_sens_down)
zz3_sens_down = Qcf.ZeroCouponCurve(lin3_sens_down, tasa)<jupyter_output><empty_output><jupyter_text>FixedRateCashflow Leg Se da de alta una pata fija:<jupyter_code># Se da de alta los parámetros requeridos
rp = Qcf.RecPay.RECEIVE
fecha_inicio = Qcf.QCDate(12, 11, 2019)
fecha_final = Qcf.QCDate(12, 11, 2020)
bus_adj_rule = Qcf.BusyAdjRules.MODFOLLOW
periodicidad = Qcf.Tenor('6M')
periodo_irregular = Qcf.StubPeriod.SHORTFRONT
calendario = Qcf.BusinessCalendar(fecha_inicio, 20)
lag_pago = 0
nominal = 20000000.0
amort_es_flujo = True
valor_tasa_fija = .01774
tasa_cupon = Qcf.QCInterestRate(
    valor_tasa_fija, Qcf.QC30360(), Qcf.QCLinearWf())
moneda = Qcf.QCUSD()
es_bono = False

# Se da de alta el objeto
fixed_rate_leg = Qcf.LegFactory.build_bullet_fixed_rate_leg(
    rp,
    fecha_inicio,
    fecha_final,
    bus_adj_rule,
    periodicidad,
    periodo_irregular,
    calendario,
    lag_pago,
    nominal,
    amort_es_flujo,
    tasa_cupon,
    moneda,
    es_bono
)
# Se define un list donde almacenar los resultados de la función show
tabla = []
for i in range(0, fixed_rate_leg.size()):
    tabla.append(Qcf.show(fixed_rate_leg.get_cashflow_at(i)))

# Se utiliza tabla para inicializar el Dataframe
columnas = list(Qcf.get_column_names("FixedRateCashflow", ""))
df = pd.DataFrame(tabla, columns=columnas)

# Se despliega la data en este formato
df.style.format(format_dict)<jupyter_output><empty_output><jupyter_text>Se calcula ahora el valor presente:<jupyter_code>vp_fija = pv.pv(fecha_hoy, fixed_rate_leg, zz2)
print("Valor presente de la pata fija es: {0:,.0f}".format(vp_fija))<jupyter_output>Valor presente de la pata fija es: 20,072,981<jupyter_text>Al calcular el valor presente, también se calculan las derivadas del valor presente respecto a cada uno de los vértices de la curva.<jupyter_code>der = pv.get_derivatives()<jupyter_output><empty_output><jupyter_text>Con esas derivadas, se puede calcular la sensibilidad a la curva cupón cero a un movimiento de 1 punto básico.<jupyter_code>i = 0
bp = .0001
total = 0
for d in der:
    total += d * bp
    print("Sensibilidad en {0:}: {1:0,.0f}".format(i, d * bp))
    i += 1
print("Sensibilidad total: {0:,.0f}".format(total))<jupyter_output>Sensibilidad en 0: 0
Sensibilidad en 1: 0
Sensibilidad en 2: 0
Sensibilidad en 3: 0
Sensibilidad en 4: 0
Sensibilidad en 5: 0
Sensibilidad en 6: -1
Sensibilidad en 7: -4
Sensibilidad en 8: 0
Sensibilidad en 9: 0
Sensibilidad en 10: 0
Sensibilidad en 11: 0
Sensibilidad en 12: -282
Sensibilidad en 13: -1,353
Sensibilidad en 14: 0
Sensibilidad en 15: 0
Sensibilidad en 16: 0
Sensibilidad en 17: 0
Sensibilidad en 18: 0
Sensibilidad en 19: 0
Sensibilidad en 20: 0
Sensibilidad en 21: 0
Sensibilidad en 22: 0
Sensibilidad en 23: 0
Sensibilidad en 24: 0
Sensibilidad en 25: 0
Sensibilidad en 26: 0
Sensibilidad en 27: 0
Sensibilidad total: -1,641<jupyter_text>Se puede verificar la sensibilidad por diferencias finitas. Se calcula el valor presente con las curvas desplazadas.<jupyter_code>vp_fija_sens_up = pv.pv(fecha_hoy, fixed_rate_leg, zz_sens_up)
vp_fija_sens_down = pv.pv(fecha_hoy, fixed_rate_leg, zz_sens_down)
print("Valor presente up de la pata fija es: {0:,.0f}".format(vp_fija_sens_up))
print("Valor presente down de la pata fija es: {0:,.0f}".format(
    vp_fija_sens_down))<jupyter_output>Valor presente up de la pata fija es: 20,139,366
Valor presente down de la pata fija es: 20,139,366<jupyter_text>Finalmente, se calcula la sensibilidad (usando la aproximación central por diferencias finitas).<jupyter_code>print("Sensibilidad por diferencias finitas: {0:,.0f}".format(
    (vp_fija_sens_up - vp_fija_sens_down) / 2))<jupyter_output>Sensibilidad por diferencias finitas: 0<jupyter_text>Tanto el VP como la sensibilidad coinciden con lo que muestra FD en la pata fija de la operación 2879.  IcpClpCashflow2 Leg<jupyter_code># Se da de alta los parámetros requeridos
rp = Qcf.RecPay.RECEIVE
fecha_inicio = Qcf.QCDate(10,1,2019)
fecha_final = Qcf.QCDate(10,7,2020)
bus_adj_rule = Qcf.BusyAdjRules.FOLLOW
periodicidad_pago = Qcf.Tenor('2Y')
periodo_irregular_pago = Qcf.StubPeriod.SHORTFRONT
calendario = Qcf.BusinessCalendar(fecha_inicio, 20)
lag_pago = 0
nominal = 38000000000.0
amort_es_flujo = True
spread = .0
gearing = 1.0

icp_clp2_leg = Qcf.LegFactory.build_bullet_icp_clp2_leg(
    rp,
    fecha_inicio,
    fecha_final,
    bus_adj_rule,
    periodicidad_pago,
    periodo_irregular_pago,
    calendario,
    lag_pago,
    nominal,
    amort_es_flujo,
    spread,
    gearing,
    True
)
# Se define un list donde almacenar los resultados de la función show
tabla = []
for i in range(0, icp_clp2_leg.size()):
    tabla.append(Qcf.show(icp_clp2_leg.get_cashflow_at(i)))

# Se utiliza tabla para inicializar el Dataframe
columnas = list(Qcf.get_column_names("IcpClpCashflow2", ""))
df9 = pd.DataFrame(tabla, columns=columnas)

# Se despliega la data en este formato
df9.style.format(format_dict)<jupyter_output><empty_output><jupyter_text>Notar que al dar de alta un Leg con IcpClpCashflow2, los valores futuros de los ICP son los default (=10,000.00). Por lo tanto, el primer paso para valorizar estos cashflows, es calcular los valores forward de los índices.Se comienza dando de alta un objeto de tipo `ForwardRates`.<jupyter_code>fwd_rates = Qcf.ForwardRates()<jupyter_output><empty_output><jupyter_text>Se calculan los índices forward.<jupyter_code>icp_val = 18890.34 # icp a la fecha de proceso
fecha_hoy = Qcf.QCDate(5, 3, 2020)

for i in range(icp_clp2_leg.size()):
    cashflow = icp_clp2_leg.get_cashflow_at(i)
    if cashflow.get_start_date() <= fecha_hoy <= cashflow.get_end_date():
            index = i

icp_fecha_inicio_cupon_vigente = 18376.69
icp_clp2_leg.get_cashflow_at(index).set_start_date_icp(icp_fecha_inicio_cupon_vigente)

fwd_rates.set_rates_icp_clp_leg(fecha_hoy, icp_val, icp_clp2_leg, zz1)
# Se define un list donde almacenar los resultados de la función show
tabla = []
for i in range(0, icp_clp2_leg.size()):
    tabla.append(Qcf.show(icp_clp2_leg.get_cashflow_at(i)))

# Se utiliza tabla para inicializar el Dataframe
columnas = list(Qcf.get_column_names("IcpClpCashflow2", ""))
df9 = pd.DataFrame(tabla, columns=columnas)

# Se despliega la data en este formato
df9.style.format(format_dict)<jupyter_output><empty_output><jupyter_text>Con esto, podemos calcular el valor presente.<jupyter_code>vp_icp_clp = pv.pv(fecha_hoy, icp_clp2_leg, zz1)
print("Valor presente pata ICPCLP: {0:,.0f}".format(vp_icp_clp))<jupyter_output>Valor presente pata ICPCLP: 39,062,144,488<jupyter_text>También en este caso es posible calcular la sensibilidad a la curva de descuento.<jupyter_code>der = pv.get_derivatives()
i = 0
bp = .0001
for d in der:
    print("Sensibilidad en {0:}: {1:0,.0f}".format(i, d * bp))
    i += 1<jupyter_output>Sensibilidad en 0: 0
Sensibilidad en 1: 0
Sensibilidad en 2: -909,119
Sensibilidad en 3: -462,011
Sensibilidad en 4: 0
Sensibilidad en 5: 0
Sensibilidad en 6: 0
Sensibilidad en 7: 0
Sensibilidad en 8: 0
Sensibilidad en 9: 0
Sensibilidad en 10: 0
Sensibilidad en 11: 0
Sensibilidad en 12: 0
Sensibilidad en 13: 0
Sensibilidad en 14: 0
Sensibilidad en 15: 0
Sensibilidad en 16: 0
Sensibilidad en 17: 0
Sensibilidad en 18: 0<jupyter_text>Podemos ver la sensibilidad total:<jupyter_code>sens_disc = [d * bp for d in der]
print("Sensibilidad de descuento: {0:,.0f} CLP".format(sum(sens_disc)))<jupyter_output>Sensibilidad de descuento: -1,371,131 CLP<jupyter_text>La estructura es la misma que para una pata fija, lo que indica que se debe también incluir la sensibilidad a la curva de proyección.<jupyter_code>import numpy as np
bp = .0001
result = []
for i in range(icp_clp2_leg.size()):
    cshflw = icp_clp2_leg.get_cashflow_at(i)
    amt_der = cshflw.get_amount_derivatives()
    df = zz1.get_discount_factor_at(fecha_hoy.day_diff(cshflw.get_settlement_date()))
    amt_der = [a * bp * df for a in amt_der]
    if len(amt_der) > 0:
        result.append(np.array(amt_der))
total = result[0] * 0

for r in result:
    total += r

for i in range(len(total)):
    print("Sensibilidad en {0:}: {1:0,.0f}".format(i, total[i]))

print("Sensibilidad de proyección: {0:,.0f} CLP".format(sum(total)))<jupyter_output>Sensibilidad en 0: 0
Sensibilidad en 1: 0
Sensibilidad en 2: 909,119
Sensibilidad en 3: 462,011
Sensibilidad en 4: 0
Sensibilidad en 5: 0
Sensibilidad en 6: 0
Sensibilidad en 7: 0
Sensibilidad en 8: 0
Sensibilidad en 9: 0
Sensibilidad en 10: 0
Sensibilidad en 11: 0
Sensibilidad en 12: 0
Sensibilidad en 13: 0
Sensibilidad en 14: 0
Sensibilidad en 15: 0
Sensibilidad en 16: 0
Sensibilidad en 17: 0
Sensibilidad en 18: 0
Sensibilidad de proyección: 1,371,131 CLP<jupyter_text>Como se espera de una pata ICPCLP (con lag de pago igual a 0 y spread igual a 0), ambas sensibilidades se cancelan.  Se verifica la sensibilidad de proyección por diferencias finitas:<jupyter_code>fwd_rates.set_rates_icp_clp_leg(fecha_hoy, icp_val, icp_clp2_leg, zz_sens_up)
vp_icp_clp_up = pv.pv(fecha_hoy, icp_clp2_leg, zz1)

fwd_rates.set_rates_icp_clp_leg(fecha_hoy, icp_val, icp_clp2_leg, zz_sens_down)
vp_icp_clp_down = pv.pv(fecha_hoy, icp_clp2_leg, zz1)

print("Sensibilidad en vértice {0:}: {1:,.0f} CLP".format(
    vertice, (vp_icp_clp_up - vp_icp_clp_down) / 2))<jupyter_output>Sensibilidad en vértice 13: 0 CLP<jupyter_text>IborCashflow2 Leg<jupyter_code># Se da de alta los parámetros requeridos
rp = Qcf.RecPay.RECEIVE
fecha_inicio = Qcf.QCDate(12, 11, 2019)
fecha_final = Qcf.QCDate(12, 11, 2020)
bus_adj_rule = Qcf.BusyAdjRules.MODFOLLOW
periodicidad_pago = Qcf.Tenor('3M')
periodo_irregular_pago = Qcf.StubPeriod.NO
calendario = Qcf.BusinessCalendar(fecha_inicio, 20)
lag_pago = 0
periodicidad_fijacion = Qcf.Tenor('3M')
periodo_irregular_fijacion = Qcf.StubPeriod.NO

# vamos a usar el mismo calendario para pago y fijaciones
lag_de_fijacion = 2

# Definición del índice
codigo = 'LIBORUSD3M'
lin_act360 = Qcf.QCInterestRate(.0, Qcf.QCAct360(), Qcf.QCLinearWf())
fixing_lag = Qcf.Tenor('2d')
tenor = Qcf.Tenor('3m')
fixing_calendar = calendario
settlement_calendar = calendario
usd = Qcf.QCUSD()
libor_usd_3m = Qcf.InterestRateIndex(codigo,
                                     lin_act360,
                                     fixing_lag,
                                     tenor,
                                     fixing_calendar,
                                     settlement_calendar,
                                     usd)
# Fin índice

nominal = 20000000.0
amort_es_flujo = True
moneda = usd
spread = .0
gearing = 1.0

# Es la op 2879 en FD
ibor_leg = Qcf.LegFactory.build_bullet_ibor2_leg(
    rp, fecha_inicio, fecha_final, bus_adj_rule, periodicidad_pago,
    periodo_irregular_pago, calendario, lag_pago,
    periodicidad_fijacion, periodo_irregular_fijacion,
    calendario, lag_de_fijacion, libor_usd_3m,
    nominal, amort_es_flujo, moneda, spread, gearing
)
# Se define un list donde almacenar los resultados de la función show
tabla = []
for i in range(0, ibor_leg.size()):
    tabla.append(Qcf.show(ibor_leg.get_cashflow_at(i)))

# Se utiliza tabla para inicializar el Dataframe
columnas = ['fecha_inicial', 'fecha__final', 'fecha_fixing', 'fecha__pago', 'nominal', 'amort', 'interes', 'amort_es_flujo', 'flujo',
            'moneda', 'codigo_indice', 'valor_tasa', 'spread', 'gearing', 'tipo_tasa']
df5 = pd.DataFrame(tabla, columns=columnas)

# Se despliega la data en este formato
df5.style.format(format_dict)
libor = 0.0190063
fecha_hoy = Qcf.QCDate(25, 2, 2020)
ibor_leg.get_cashflow_at(0).set_rate_value(libor)
fwd_rates.set_rates_ibor_leg(fecha_hoy, ibor_leg, zz2)
# Se define un list donde almacenar los resultados de la función show
tabla = []
for i in range(0, ibor_leg.size()):
    tabla.append(Qcf.show(ibor_leg.get_cashflow_at(i)))

# Se utiliza tabla para inicializar el Dataframe
columnas = ['fecha_inicial', 'fecha__final', 'fecha_fixing', 'fecha__pago', 'nominal', 'amort', 'interes', 'amort_es_flujo', 'flujo',
            'moneda', 'codigo_indice', 'valor_tasa', 'spread', 'gearing', 'tipo_tasa']
df5 = pd.DataFrame(tabla, columns=columnas)

# Se despliega la data en este formato
df5.style.format(format_dict)
which_cashflow = 1
d1 = fecha_hoy.day_diff(ibor_leg.get_cashflow_at(which_cashflow).get_start_date())
d2 = fecha_hoy.day_diff(ibor_leg.get_cashflow_at(which_cashflow).get_end_date())
print("d1: {0:,.0f}".format(d1))
print("d2: {0:,.0f}".format(d2))
crv = zz2
w1 = 1 / crv.get_discount_factor_at(d1)
w2 = 1 / crv.get_discount_factor_at(d2)
print("Factor forward: {0:.4%}".format(w2 / w1))
print("Tasa forward: {0:.4%}".format((w2 / w1 - 1) * 360 / (d2 - d1)))
print("Curve method {0:.4%}".format(crv.get_forward_rate_with_rate(libor_usd_3m.get_rate(), d1, d2)))
vp_ibor = pv.pv(fecha_hoy, ibor_leg, zz2)
print("Valor presente pata IBOR: {0:,.0f}".format(vp_ibor))<jupyter_output>Valor presente pata IBOR: 19,923,850<jupyter_text>Es el mismo valor presente que la pata flotante de la operación 2879 en FD.<jupyter_code>der = pv.get_derivatives()
i = 0
bp = .0001
for d in der:
    print("Sensibilidad en {0:}: {1:0,.0f}".format(i, d * bp))
    i += 1
print("Sensibilidad de descuento: {0:,.0f} USD".format(sum(der) * bp))<jupyter_output>Sensibilidad en 0: 0
Sensibilidad en 1: 0
Sensibilidad en 2: 0
Sensibilidad en 3: 0
Sensibilidad en 4: 0
Sensibilidad en 5: 0
Sensibilidad en 6: 0
Sensibilidad en 7: 0
Sensibilidad en 8: -2
Sensibilidad en 9: -2
Sensibilidad en 10: 0
Sensibilidad en 11: -666
Sensibilidad en 12: -755
Sensibilidad en 13: 0
Sensibilidad en 14: 0
Sensibilidad en 15: 0
Sensibilidad en 16: 0
Sensibilidad en 17: 0
Sensibilidad en 18: 0
Sensibilidad en 19: 0
Sensibilidad en 20: 0
Sensibilidad en 21: 0
Sensibilidad en 22: 0
Sensibilidad en 23: 0
Sensibilidad en 24: 0
Sensibilidad en 25: 0
Sensibilidad en 26: 0
Sensibilidad en 27: 0
Sensibilidad de descuento: -1,425 USD<jupyter_text>Se verifica la sensibilidad de descuento por diferencias finitas.<jupyter_code>vp_ibor_up = pv.pv(fecha_hoy, ibor_leg, zz2_sens_up)
print("Valor presente up pata IBOR: {0:,.0f}".format(vp_ibor_up))

vp_ibor_down = pv.pv(fecha_hoy, ibor_leg, zz2_sens_down)
print("Valor presente down pata IBOR: {0:,.0f}".format(vp_ibor_down))

print("Sensibilidad de descuento en el vértice {0:}: {1:,.0f}".format(vertice, (vp_ibor_up - vp_ibor_down) / 2))<jupyter_output>Valor presente up pata IBOR: 19,923,850
Valor presente down pata IBOR: 19,923,850
Sensibilidad de descuento en el vértice 13: 0<jupyter_text>Se calcula también la sensibilidad a la curva de proyección.<jupyter_code>import numpy as np
bp = .0001
result = []

for i in range(ibor_leg.size()):
    cshflw = ibor_leg.get_cashflow_at(i)
    df = zz2.get_discount_factor_at(fecha_hoy.day_diff(cshflw.get_settlement_date()))
    amt_der = cshflw.get_amount_derivatives()
    if len(amt_der) > 0:
        amt_der = [a * bp * df for a in amt_der]
        result.append(np.array(amt_der))

total = result[0] * 0
for r in result:
    total += r

for i in range(len(total)):
    print("Sensibilidad en {0:}: {1:0,.0f}".format(i, total[i]))

print("Sensibilidad de proyección: {0:,.0f} USD".format(sum(total)))<jupyter_output>Sensibilidad en 0: 0
Sensibilidad en 1: 0
Sensibilidad en 2: 0
Sensibilidad en 3: 0
Sensibilidad en 4: 0
Sensibilidad en 5: -192
Sensibilidad en 6: -233
Sensibilidad en 7: 0
Sensibilidad en 8: 2
Sensibilidad en 9: 2
Sensibilidad en 10: 0
Sensibilidad en 11: 666
Sensibilidad en 12: 755
Sensibilidad en 13: 0
Sensibilidad en 14: 0
Sensibilidad en 15: 0
Sensibilidad en 16: 0
Sensibilidad en 17: 0
Sensibilidad en 18: 0
Sensibilidad en 19: 0
Sensibilidad en 20: 0
Sensibilidad en 21: 0
Sensibilidad en 22: 0
Sensibilidad en 23: 0
Sensibilidad en 24: 0
Sensibilidad en 25: 0
Sensibilidad en 26: 0
Sensibilidad en 27: 0
Sensibilidad de proyección: 1,000 USD<jupyter_text>Se verifica la sensibilidad de proyección por diferencias finitas.<jupyter_code>fwd_rates.set_rates_ibor_leg(fecha_hoy, ibor_leg, zz2_sens_up)
vp_ibor_up = pv.pv(fecha_hoy, ibor_leg, zz2)
print("Valor presente up pata IBOR: {0:,.0f}".format(vp_ibor_up))

fwd_rates.set_rates_ibor_leg(fecha_hoy, ibor_leg, zz2_sens_down)
vp_ibor_down = pv.pv(fecha_hoy, ibor_leg, zz2)
print("Valor presente down pata IBOR: {0:,.0f}".format(vp_ibor_down))

print("Sensibilidad de proyección en el vértice {0:}: {1:,.0f}".format(vertice, (vp_ibor_up - vp_ibor_down) / 2))<jupyter_output>Valor presente up pata IBOR: 19,923,850
Valor presente down pata IBOR: 19,923,850
Sensibilidad de proyección en el vértice 13: 0<jupyter_text>IcpClfCashflow Leg<jupyter_code># Se da de alta los parámetros requeridos
rp = Qcf.RecPay.RECEIVE
fecha_inicio = Qcf.QCDate(31, 5, 2018)
fecha_final = Qcf.QCDate(9, 5, 2026) 
bus_adj_rule = Qcf.BusyAdjRules.FOLLOW
periodicidad_pago = Qcf.Tenor('6M')
periodo_irregular_pago = Qcf.StubPeriod.SHORTFRONT
calendario = Qcf.BusinessCalendar(fecha_inicio, 20)
lag_pago = 0
nominal = 600000.0
amort_es_flujo = True 
spread = .0
gearing = 1.0

icp_clf_leg = Qcf.LegFactory.build_bullet_icp_clf_leg(rp, fecha_inicio, fecha_final, bus_adj_rule, periodicidad_pago,
                                                     periodo_irregular_pago, calendario, lag_pago,
                                                     nominal, amort_es_flujo, spread, gearing)
# Se define un list donde almacenar los resultados de la función show
tabla = []
for i in range(0, icp_clf_leg.size()):
    tabla.append(Qcf.show(icp_clf_leg.get_cashflow_at(i)))

# Se utiliza tabla para inicializar el Dataframe
columnas = ['fecha_inicial', 'fecha__final', 'fecha__pago', 'nominal', 'amort', 'amort_es_flujo', 'flujo',
            'moneda', 'icp_inicial', 'icp_final', 'uf_inicial', 'uf_final',
            'valor_tasa', 'interes', 'spread', 'gearing', 'tipo_tasa']
df8 = pd.DataFrame(tabla, columns=columnas)

# Se despliega la data en este formato
df8.style.format(format_dict)
icp_hoy = 18882.07
uf_hoy = 28440.19
fwd_rates.set_rates_icp_clf_leg(fecha_hoy, icp_hoy, uf_hoy, icp_clf_leg, zz1, zz1, zz3)
cshflw = icp_clf_leg.get_cashflow_at(3)
cshflw.set_start_date_uf(28080.26)
cshflw.set_start_date_icp(18786.13)
print(fecha_hoy)
# Se define un list donde almacenar los resultados de la función show
tabla = []
for i in range(0, icp_clf_leg.size()):
    tabla.append(Qcf.show(icp_clf_leg.get_cashflow_at(i)))

# Se utiliza tabla para inicializar el Dataframe
columnas = ['fecha_inicial', 'fecha__final', 'fecha__pago', 'nominal', 'amort', 'amort_es_flujo', 'flujo',
            'moneda', 'icp_inicial', 'icp_final', 'uf_inicial', 'uf_final',
            'valor_tasa', 'interes', 'spread', 'gearing', 'tipo_tasa']
df8 = pd.DataFrame(tabla, columns=columnas)

# Se despliega la data en este formato
df8.style.format(format_dict)
vp_icp_clf = pv.pv(fecha_hoy, icp_clf_leg, zz3)
print("Valor presente en UF: {0:,.2f}".format(vp_icp_clf))
print("Valor presente en CLP: {0:,.0f}".format(vp_icp_clf * uf_hoy))
print("Dif %: {0:.4%}".format(12940.56/12943.45-1))
der = pv.get_derivatives()
i = 0
bp = .0001
for d in der:
    print("Sensibilidad en {0:}: {1:0,.2f}".format(i, d * bp))
    i += 1
print("Sensibilidad de descuento: {0:,.2f} CLF".format(sum(der) * bp))
bp = .0001
result = []

for i in range(icp_clf_leg.size()):
    cshflw = icp_clf_leg.get_cashflow_at(i)
    df = zz3.get_discount_factor_at(fecha_hoy.day_diff(cshflw.date()))
    amt_der = cshflw.get_amount_ufclf_derivatives()
    if len(amt_der) > 0:
        amt_der = [a * bp * df for a in amt_der]
        result.append(np.array(amt_der))

total = result[0] * 0
for r in result:
    total += r

for i in range(len(total)):
    print("Sensibilidad en {0:}: {1:0,.2f}".format(i, total[i]))

print("Sensibilidad de proyección: {0:,.2f} CLF".format(sum(total)))<jupyter_output>Sensibilidad en 0: 0.00
Sensibilidad en 1: 0.00
Sensibilidad en 2: 0.00
Sensibilidad en 3: -0.10
Sensibilidad en 4: -0.06
Sensibilidad en 5: 0.00
Sensibilidad en 6: 0.00
Sensibilidad en 7: 0.00
Sensibilidad en 8: 0.00
Sensibilidad en 9: -0.27
Sensibilidad en 10: -0.12
Sensibilidad en 11: 0.00
Sensibilidad en 12: 0.00
Sensibilidad en 13: 0.00
Sensibilidad en 14: 0.00
Sensibilidad en 15: -0.32
Sensibilidad en 16: -0.18
Sensibilidad en 17: 0.00
Sensibilidad en 18: 0.00
Sensibilidad en 19: 0.00
Sensibilidad en 20: -0.65
Sensibilidad en 21: -1.63
Sensibilidad en 22: -2.15
Sensibilidad en 23: -1.29
Sensibilidad en 24: 0.26
Sensibilidad en 25: 335.81
Sensibilidad en 26: 82.41
Sensibilidad en 27: 0.00
Sensibilidad en 28: 0.00
Sensibilidad en 29: 0.00
Sensibilidad en 30: 0.00
Sensibilidad en 31: 0.00
Sensibilidad en 32: 0.00
Sensibilidad de proyección: 411.73 CLF
{'fraction_non_alphanumeric': 0.1163324513023241, 'fraction_numerical': 0.047470271304236936, 'mean_word_length': 5.302591922845087, 'pattern_counts': {'":': 3, '<': 184, '<?xml version=': 0, '>': 185, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '51', 'dir': 'jupyter-structured-clean-dedup', 'id': '422916', 'license': 'Unlicense', 'n_tokens_mistral': 14421, 'n_tokens_neox': 13254, 'n_words': 2950, 'path': 'docs/Docs_QC_Financial_3.ipynb', 'repo_name': 'adiaz-efaa/mif-2021', 'size': '31367'}