Más Contenedores, Condiciones y Más Loops#
zip
de 2 variablesList
Variables de tipo
Dict
if ... elif ... else
bool
,and
yor
la instrucción
while
Resolvamos el problema propuesto en la Tarea 1.
zip
de 2 List
#
Consideremos las variables de tipo List
donde están almacenados los flujos y los plazos de los flujos.
flujos = [1, 1, 1, 1, 1, 1, 1, 1, 1, 101]
plazos = [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]
Ahora, podemos juntar las List
notas
y nombres
usando la función zip
.
El zip
de 2 List
es Iterable
y podemos, por lo tanto, recorrer sus elementos con una instrucción for
.
for fp in zip(flujos, plazos):
print(fp)
(1, 182)
(1, 365)
(1, 547)
(1, 730)
(1, 912)
(1, 1095)
(1, 1277)
(1, 1460)
(1, 1642)
(101, 1825)
Notar que los resultados de cada print
aparecen entre (...)
. Esto indica que cada elemento del zip
es una Tuple
.
También se puede hacer de la siguiente forma:
for f, p in zip(flujos, plazos):
print(f, p)
1 182
1 365
1 547
1 730
1 912
1 1095
1 1277
1 1460
1 1642
101 1825
De esta forma, en cada paso del for
, el flujo y plazo correspondiente se almacenan separadamente (sin uasr una Tuple
).
lista1 = [1, 2, 3]
lista2 = ['a', 'b', 'c', 'd']
for ll in zip(lista1, lista2):
print(ll)
(1, 'a')
(2, 'b')
(3, 'c')
Gracias a la instrucción zip
podemos calcular el valor presente de los flujos utilizando el for
.
vp = 0.0 # <--- en esta variable se almacenará el resultado del cálculo
tasa = .02 # <--- este es el valor de la tasa de descuento
for f, p in zip(flujos, plazos):
vp += f * (1 + tasa)**(-p / 365) # vp = vp + f * (1 + tasa)**(-p / 365)
print(f'El valor presente es: {vp:,.4f}')
El valor presente es: 100.0470
En el loop
anterior hay dos elementos nuevos:
La expresión
a += b
es equivalente a escribira = a + b
que, a su vez, quiere decir que el nuevo valor de la variablea
es el actual valor dea
más el valor de la variableb
. En el caso anterior, el nuevo valor devp
es el valor actual devp
más el valor presente del flujof
. Podemos apreciar comovp
es una variable en donde vamos sumando (acumulando) los valores presentes de cada flujo.**
representa elevar a una potencia, como ^ en Excel.
Pregunta#
La tasa de cupón del bono es 2.00% y la tasa de descuento es 2.00% ¿Porqué no está perfectamente a la par (vp = 100)?
Respuesta: por la diferencia en la convención de la tasa de cupón y de la tasa de descuento.
Variables de Tipo Dict
#
En el ejemplo anterior tenemos los flujos de un único bono, sea éste bono_1
. ¿Cómo podemos almacenar flujos de distintos bonos y posteriormente identificarlos con facilidad? Por ejemplo, lo más usual sería usar como identificador el nemotécnico del bono. Para eso sirven las variables de tipo Dict
.
nombre_edad = {
'alvaro': 52,
'thomas': 26,
'daniel': 36
}
nombre_edad_peso = {
'alvaro': [52, 94],
'thomas': [26, 80]
}
dict_bonos = {
"bono_1": [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 101],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]
],
"bono_2": [
[2, 2, 2, 2, 2, 2, 2, 2, 2, 102],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]
]
}
Un dict va entre {}
y cada elemento del Dict
tiene la forma <identificador>: <valor>
. En este caso, el identificador de cada elemento es el nemotécnico del bono (variable de tipo str
) y el valor de cada elemento es una List
que, a su vez, contiene una List
con los flujos y una List
con los plazos de los bonos.
Cómo se Usa un Dict
#
nombre_edad['alvaro']
52
dict_bonos['bono_1'] # los flujos y plazos del bono_1
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 101],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
Si queremos sólo los flujos del bono_1
:
dict_bonos['bono_1'][0]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 101]
Los datos del bono_2
.
dict_bonos['bono_2'] # las notas de Física
[[2, 2, 2, 2, 2, 2, 2, 2, 2, 102],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
Sólo los plazos del bono_2
.
dict_bonos['bono_2'][1]
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]
Un Dict
es una estructura de datos mutable. Si aparece un nuevo bono, podemos agregarlo, por ejemplo:
dict_bonos['bono_3'] = [
[3, 3, 3, 3, 3, 3, 3, 3, 3, 103],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]
]
dict_bonos
{'bono_1': [[1, 1, 1, 1, 1, 1, 1, 1, 1, 101],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]],
'bono_2': [[2, 2, 2, 2, 2, 2, 2, 2, 2, 102],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]],
'bono_3': [[3, 3, 3, 3, 3, 3, 3, 3, 3, 103],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]}
dict_bonos['bono_3'][0][9] = 104
dict_bonos
{'bono_1': [[1, 1, 1, 1, 1, 1, 1, 1, 1, 101],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]],
'bono_2': [[2, 2, 2, 2, 2, 2, 2, 2, 2, 102],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]],
'bono_3': [[3, 3, 3, 3, 3, 3, 3, 3, 3, 104],
[182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]}
Un Dict
también es Iterable
, veamos que pasa cuando lo usamos en un for loop
.
for x in dict_bonos:
print(x)
bono_1
bono_2
bono_3
for x in dict_bonos:
print(dict_bonos[x])
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 101], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
[[2, 2, 2, 2, 2, 2, 2, 2, 2, 102], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
[[3, 3, 3, 3, 3, 3, 3, 3, 3, 104], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
Vemos que x
es el valor de los identificadores del Dict
, en este caso, los nemotécnicos de los bonos.
Para obtener los valores del Dict
usamos lo siguiente:
for x in dict_bonos.values():
print(x)
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 101], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
[[2, 2, 2, 2, 2, 2, 2, 2, 2, 102], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
[[3, 3, 3, 3, 3, 3, 3, 3, 3, 104], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
Para obtener los identificadores (keys
) y valores (values
) usamos lo siguiente:
for x in dict_bonos.items():
print(x)
('bono_1', [[1, 1, 1, 1, 1, 1, 1, 1, 1, 101], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]])
('bono_2', [[2, 2, 2, 2, 2, 2, 2, 2, 2, 102], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]])
('bono_3', [[3, 3, 3, 3, 3, 3, 3, 3, 3, 104], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]])
for k, v in dict_bonos.items():
print(k, v)
bono_1 [[1, 1, 1, 1, 1, 1, 1, 1, 1, 101], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
bono_2 [[2, 2, 2, 2, 2, 2, 2, 2, 2, 102], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
bono_3 [[3, 3, 3, 3, 3, 3, 3, 3, 3, 104], [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]]
O también:
for k, v in dict_bonos.items():
print(f'nemotécnico: {k},\nflujos: {v[0]}\nplazos: {v[1]}\n') # <--- \n significa que lo que sigue empieza
# en una nueva línea. Es como apretar Enter.
nemotécnico: bono_1,
flujos: [1, 1, 1, 1, 1, 1, 1, 1, 1, 101]
plazos: [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]
nemotécnico: bono_2,
flujos: [2, 2, 2, 2, 2, 2, 2, 2, 2, 102]
plazos: [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]
nemotécnico: bono_3,
flujos: [3, 3, 3, 3, 3, 3, 3, 3, 3, 104]
plazos: [182, 365, 547, 730, 912, 1095, 1277, 1460, 1642, 1825]
Ejercicio#
Escribir una función que tenga como argumento una variable como dict_bonos
y una tasa de descuento y devuelva un Dict
donde el identicador es el nemotécnico del bono y el valor es el valor presente del bono.
Primero vamos a definir una función que calcula el valor presente de sólo 1 bono. Aprovechamos de introducir la docstring
de una función.
def vp_bono(flujos, plazos, tasa):
"""
Calcula el valor presente de un bono dada una tasa de descuento.
Parameters
----------
flujos: List[float]
Contiene los flujos del bono.
plazos: List[float]
Contiene los plazos residuales de los flujos expresados en días.
tasa: float
Tasa de descuento del bono. Debe ser en convención Com Act/365.
Returns
-------
float
El valor presente del bono.
"""
result = 0.0
for f, p in zip(flujos, plazos):
result += f * (1 + tasa)**(-p / 365.0)
return result
El docstring
de la función anterior está en formato numpy
. Hay un par más (ver) y se tiene libertad para escoger el que más te gusta. Es importante, eso sí, que una vez que se ha escogido un estilo, mantener consistencia en su uso.
El uso del docstring
me permite investigar una función antes de usarla. Esto es muy útil para funciones de paquetes y librerías externas e incluso para nuestras propias funciones.
print(vp_bono.__doc__)
Calcula el valor presente de un bono dada una tasa de descuento.
Parameters
----------
flujos: List[float]
Contiene los flujos del bono.
plazos: List[float]
Contiene los plazos residuales de los flujos expresados en días.
tasa: float
Tasa de descuento del bono. Debe ser en convención Com Act/365.
Returns
-------
float
El valor presente del bono.
Probemos la función usando las variables definidas al inicio de este notebook.
vp = vp_bono(flujos, plazos, tasa)
print(f'Valor presente: {vp:,.04f}')
Valor presente: 100.0470
Ahora, con esta función, podemos definir una función que valorice muchos bonos.
def vp_bonos(bonos, tasa):
"""
Calcula el valor presente de un conjunto de bonos con una tasa de descuento dada.
Parameters
----------
bonos: Dict[str, List[List[float], List[float]]]
Las `keys` del `Dict` son los nemotécnicos del bono o cualquier otro identificador único, como el CUSIP.
Los `values` son una `List` que, a su vez, contiene dos `List`, una con los flujos del bono en el índice
0 y otra con los plazos residuales de los flujos en días en el índice 1.
tasa: float
Tasa de descuento, debe estar en convención Com Act/365.
Returns
-------
Dict[str, float]
Los `keys` son los mismos del parámetro `bono` y los `values` son los valores presente de los bonos.
"""
result = {} # Dict vacío
for k, v in bonos.items():
result[k] = vp_bono(v[0], v[1], tasa)
return result
Probemos con el Dict
dict_bonos
y la variable tasa
definida al prinicpio del notebook.
vps = vp_bonos(dict_bonos, tasa)
for k, v in vps.items():
print(f'El valor presente de {k} es: {v:,.04f}')
El valor presente de bono_1 es: 100.0470
El valor presente de bono_2 es: 109.5210
El valor presente de bono_3 es: 119.9007
Tarea#
Hacer todos los cambios que estimen necesarios para poder valorizar dict_bonos
usando una tasa de descuento distinta para cada bono.
La Instrucción if ... elif ... else
#
Muchas veces, la función que estamos programando requiere hacer una distinción, o tomar un decisión en función de una o más variables. Veamos un ejemplo muy sencillo. La función
se define de la siguiente forma \(abs(x)=x\) si \(x\geq0\) y \(abs(x)=-x\) si \(x<0\). Para programar esta función, necesitamos una forma de distinguir si si \(x\) es positivo (o cero) o negativo.
La instrucción if ... else
#
Veamos como hacerlo, poner mucha atención en la indentación que viene debajo de los if
y else
.
def abs(x):
if x < 0:
return -x
else:
return x
Probemos …
print(f"El valor absoluto de {2} es: {abs(2)}")
print(f"El valor absoluto de {-2} es: {abs(-2)}")
El valor absoluto de 2 es: 2
El valor absoluto de -2 es: 2
¡Bien! El resultado es el esperado. Existe también una forma breve de escribir esta instrucción. Esta forma breve se puede utilizar en casos sencillos como el anterior.
def abs2(x):
return x if x >= 0 else -x
Probemos esta también … (para recordar, aquí usamos print
con format
)
print("El valor absoluto de {} es: {}".format(2, abs2(2)))
print("El valor absoluto de {} es: {}".format(-2, abs2(-2)))
El valor absoluto de 2 es: 2
El valor absoluto de -2 es: 2
La instrucción if ... elif ... else
#
En ocasiones, debemos distinguir entre más de dos alternativas. Por ejemplo, supongamos que queremos clasificar los bonos de una cartera en las categorías ‘SUBPAR’ si el bono se transa por debajo de 98, ‘PAR’ si el bono se transa entre 98 y 102 y ‘SOBREPAR’ si el bono se transa por sobre 102.
Definimos una función que acepta un número que representa el precio del bono y retorna un str
con la categoría del bono. Este ejemplo nos permite introducir, además, el operador lógico and
, con el cual se puede verificar si 2 condiciones son verdaderas al mismo tiempo.
def categoria(precio):
if precio < 98:
return "SUBPAR"
elif precio >= 98 and precio < 102: # <--- Notar el conector lógico and. Más detalle en lo que sigue.
return "PAR"
else:
return "SOBREPAR"
Probemos …
precios = [96, 97, 98, 99, 100, 101, 102, 103]
for precio in precios:
print(f"El bono de precio {precio:.2f} está en la categoría: {categoria(precio)}")
El bono de precio 96.00 está en la categoría: SUBPAR
El bono de precio 97.00 está en la categoría: SUBPAR
El bono de precio 98.00 está en la categoría: PAR
El bono de precio 99.00 está en la categoría: PAR
El bono de precio 100.00 está en la categoría: PAR
El bono de precio 101.00 está en la categoría: PAR
El bono de precio 102.00 está en la categoría: SOBREPAR
El bono de precio 103.00 está en la categoría: SOBREPAR
Se puede utilizar más de un elif
, por ejemplo, supongamos que necesitamos establecer otra categoría más y dejar las cosas de esta manera:
Menor a 98: “SUBPAR”
Mayor o igual 98 y menor que 101: “PAR”
Mayor o igual a 101 y menor a 103: “SOBREPAR”
Mayor o igual a 103: “MUYSOBREPAR”
Esta categoría se podría implementar de la siguiente forma:
def categoria2(preco):
if precio < 98:
return "SUBPAR"
elif precio >= 98 and precio < 101:
return "PAR"
elif precio >= 101 and precio < 103:
return "SOBREPAR"
else:
return "MUYSOBREPAR"
for precio in precios:
print(f"El bono de precio {precio:.2f} está en la categoría: {categoria2(precio)}")
El bono de precio 96.00 está en la categoría: SUBPAR
El bono de precio 97.00 está en la categoría: SUBPAR
El bono de precio 98.00 está en la categoría: PAR
El bono de precio 99.00 está en la categoría: PAR
El bono de precio 100.00 está en la categoría: PAR
El bono de precio 101.00 está en la categoría: SOBREPAR
El bono de precio 102.00 está en la categoría: SOBREPAR
El bono de precio 103.00 está en la categoría: MUYSOBREPAR
Valores bool
y los Operadores Lógicos and
y or
#
El Tipo bool
#
Hasta ahora hemos visto los tipos de variable int
, float
y str
. Existe otro tipo de variable primitiva, las variables de tipo bool
. Estas variables sólo pueden asumir dos valores True
o False
y aparecen al momento de verificar una condición. De hecho, al verificar una condición, Python retorna una variable de tipo bool
. Veamos un par de ejemplos:
2 > 1
True
2 < 1
False
Cuando queremos verificar si dos valores son iguales, se utiliza el símbolo ==
, el símbolo =
sólo se utiliza para asignar un valor a una variable. Por ejemplo:
a = 3 # asignación
b = 4 # asignación
a == b # comparación
False
El resultado de una comparación, puede almacenarse en una variable.
c = (a == b) # se asigna a c el resultado (bool) de a == b
print("El valor de c es {}".format(c))
El valor de c es False
Operador and
#
Al ejecutar condicion1 and condicion2
se obtendrá True
si y sólo si ambas condiciones son True
.
precio = 101
print("precio: {}".format(precio))
print("¿precio >= 100: {}".format(precio >= 100))
print("¿precio < 102?: {}".format(precio < 102))
print("¿precio >= 100 and precio < 102?: {}".format(precio >= 100 and precio < 102))
precio: 101
¿precio >= 100: True
¿precio < 102?: True
¿precio >= 100 and precio < 102?: True
print("precio: {}".format(precio))
print("¿precio >= 100: {}".format(precio >= 100))
print("¿precio < 101?: {}".format(precio < 101))
print("¿precio >= 100 and precio < 101?: {}".format(precio >= 100 and precio < 101))
precio: 101
¿precio >= 100: True
¿precio < 101?: False
¿precio >= 100 and precio < 101?: False
Operador or
#
Al ejecutar condicion1 or condicion2
se obtendrá False
si y sólo si ambas condiciones son False
.
print("precio: {}".format(precio))
print("¿precio >= 100: {}".format(precio >= 100))
print("¿precio < 101?: {}".format(precio < 101))
print("¿precio >= 100 or precio < 101?: {}".format(precio >= 100 or precio < 101))
precio: 101
¿precio >= 100: True
¿precio < 101?: False
¿precio >= 100 or precio < 101?: True
print("precio: {}".format(precio))
print("¿precio < 101: {}".format(precio < 101))
print("¿precio >= 102?: {}".format(precio >= 102))
print("¿precio < 101 or precio >= 102?: {}".format(precio < 101 or precio >= 102))
precio: 101
¿precio < 101: False
¿precio >= 102?: False
¿precio < 101 or precio >= 102?: False
Ejercicio#
Una universidad ofrece una beca si:
El NEM del alumno es superior a 5.5 y tu ingreso familiar es menor a 1.2 millones de CLP (pesos chilenos) o
El NEM del alumno es superior a 6.0 y tu ingreso familiar es menor a 1.5 millones de CLP (pesos chilenos) o
El NEM del alumno es superior a 6.5
Escribe una función que tenga el NEM y el ingreso familiar como variables y retorne un bool
que indique si es eligible para la beca (True
eres eligible, False
no eres elegible).
def es_elegible(nem: float, ingreso: float) -> bool: # type anotations
"""
Indica si un alumno es elegible para beca.
Parameters
----------
nem: float
Promedio de Notas Enseñanza Media
ingreso: float
Ingreso familiar mensual en pesos.
Returns
-------
`True` si es elegible `False` en caso contrario.
"""
if nem >= 5.5 and ingreso < 1200000:
return True
elif nem >= 6.0 and ingreso < 1500000:
return True
elif nem >= 6.5:
return True
else:
return False
nem = 6.0
ingreso = 1300000
es_elegible(nem, ingreso)
True
if (nem >= 5.5 and ingreso < 1200000) or (nem >= 6.0 and ingreso < 1500000) or (nem >= 6.5):
print(True)
else:
print(False)
True
La Instrucción while
#
El uso de while
permite ejecutar un grupo de instrucciones hasta que una condición sea verdadera.
Ejemplo#
En este caso, se mostrarán por pantalla los números del 0 al 9.
Se inicializa el valor de la variable
i
.Comienza
while
, se evalúa sii < 10
, las instrucciones dentro delwhile
se ejecutarán sólo sii < 10 = True
.Se muestra por pantalla el valor de
i
Se incrementa el valor de
i
en 1 (la instruccióni += 1
es equivalente ai = i + 1
)Se vuelve a ejecutar …
i = 0
while i < 10:
print(f'El valor de i es {i}')
i += 1
El valor de i es 0
El valor de i es 1
El valor de i es 2
El valor de i es 3
El valor de i es 4
El valor de i es 5
El valor de i es 6
El valor de i es 7
El valor de i es 8
El valor de i es 9
La Instrucción continue
#
La instrucción continue
permite volver anticipadamente al inicio del while
. En este caso, cuando i == 3
, no se muestra el valor de i
por pantalla y se vuelve al inicio.
i = 0
while i < 10:
if i == 3:
i += 1
continue
print(f'El valor de i es {i}')
i += 1
El valor de i es 0
El valor de i es 1
El valor de i es 2
El valor de i es 4
El valor de i es 5
El valor de i es 6
El valor de i es 7
El valor de i es 8
El valor de i es 9
Continuar la Ejecución Hasta que el Usuario la Interrumpa#
En este ejemplo, el while
se ejecuta siempre y sólo se interrumpe cuando el usuario ingresa la letra 'q'
. Para este ejemplo utilizamos una nueva función: input
. Esta función permite capturar input del usuario y procesarlo.
while True: # dado que True == True siempre, el while siempre se ejecuta
letra = input('Elige una letra ...')
if letra == 'q':
print('Esa sí.')
break
else:
print('\tNop, esa no ...')
continue
print('\nFuera del while.')
---------------------------------------------------------------------------
StdinNotImplementedError Traceback (most recent call last)
Cell In[52], line 2
1 while True: # dado que True == True siempre, el while siempre se ejecuta
----> 2 letra = input('Elige una letra ...')
3 if letra == 'q':
4 print('Esa sí.')
File /opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/ipykernel/kernelbase.py:1281, in Kernel.raw_input(self, prompt)
1279 if not self._allow_stdin:
1280 msg = "raw_input was called, but this frontend does not support input requests."
-> 1281 raise StdinNotImplementedError(msg)
1282 return self._input_request(
1283 str(prompt),
1284 self._parent_ident["shell"],
1285 self.get_parent("shell"),
1286 password=False,
1287 )
StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
Ejercicio#
Para este ejercicio, vas a necesitar la siguiente función: randint
Primero se debe importar el módulo
random
. Un módulo puede pensarse como programas que otros han escrito y que podemos agregar a nuestros propios programas.random
es un módulo de la librería estándar de Python, eso quiere decir que siempre está disponible.Para agregarlo a nuestros programas, se ejecuta la siguiente instrucción
import random as rnd
Del módulo random
vamos a utilizar la función randint(i, j)
que genera un número entero aleatorio entre i
y j
(ambos inclusive).
Cada vez que se ejecuta esta celda, se obtiene un número entero nuevo de forma aleatoria.
rnd.randint(1, 10)
10
Enunciado del Ejercicio#
Vas a programar un juego muy sencillo utilizando while
y la función randint
.
El computador elige un número entero aleatorio, que llamaremos
num_secreto
, en un rango predeterminado.Tú debes tratar de adivinarlo
Si lo adivinas ganas y tu puntaje es el número de veces que tuviste que jugar para adivinar
num_secreto
Si no lo adivinas, el computador te responderá si el número que dijiste es más alto o más bajo que
num_secreto
y sigues jugandoMientras más bajo tu puntaje, mejor
Tip: el resultado de input es un str
x = input()
x
print(type(x))
<class 'str'>
Para convertirlo a int
hacer lo siguiente:
x = int(x)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-66-6ed577bb1378> in <module>
----> 1 x = int(x)
ValueError: invalid literal for int() with base 10: 'x'
type(x)
Solución#
def jugar():
"""
"""
num_secreto = rnd.randint(1, 51)
while True:
guess = input("Adivina qué número elegí (entre 1 y 50 inclusive):")
try:
int_guess = int(guess)
if num_secreto == int(guess):
return "Ganaste."
else:
if int(guess) > num_secreto:
print("Tú número es mayor ...")
else:
print("Tu número es menor ...")
except NameError:
print("Tienes que ingresar un número entero.")
return "Game Over"
Hacer otra versión con isdecimal()
.
jugar()
Adivina qué número elegí (entre 1 y 50 inclusive):r
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-84-e61132de9759> in <module>
----> 1 jugar()
<ipython-input-83-e889f314c381> in jugar()
6 guess = input("Adivina qué número elegí (entre 1 y 50 inclusive):")
7 try:
----> 8 int_guess = int(guess)
9 if num_secreto == int(guess):
10 return "Ganaste."
ValueError: invalid literal for int() with base 10: 'r'
Encuentra la TIR de un Bono#
Supongamos que tenemos un bono que está transando a un valor presente de 101 y queremos calcular cuál es su TIR de mercado. O sea, queremos determinar qué tasa de descuento hace que el valor presente del bono sea 101. Veamos como hacerlo utilizando los flujos y plazos definidos al principio del notebook.
flujos
plazos
Tenemos que resolver la ecuación:
Para esto vamos a programar un mini BuscarObjetivo
totalmente similar al que usaríamos si resolviéramos este problema con Excel. Utilizaremos el método de Newton-Raphson que nos dice que podemos encontrar la solución a la ecuación anterior si iterativamente calculamos:
Aquí \(V'\left(TIR_n\right)\) es la derivada del valor presente respecto a \(TIR_n\).
La derivada del valor presente la calcularemos de forma numérica con la siguiente aproximación:
def der_vp_bono(flujos, plazos, tasa):
"""
Calcula la derivada del valor presente del bono respecto a la tasa usando la aproximación
por diferencia central.
VP'(tasa) = (VP(tasa + h) - VP(tasa - h)) / 2h
Se utiliza un valor de h = .0001
Parameters
----------
flujos: List[float]
Contiene los flujos del bono.
plazos: List[float]
Contiene los plazos residuales de los flujos expresados en días.
tasa: float
Tasa de descuento del bono. Debe ser en convención Com Act/365.
Returns
-------
float
La derivada del valor presente del bono.
"""
h = .0001
return (vp_bono(flujos, plazos, tasa + h) - vp_bono(flujos, plazos, tasa - h)) / (2 * h)
Realizamos un check:
h = .0001
vp = vp_bono(flujos, plazos, .02)
vp_mas = vp_bono(flujos, plazos, .02 + h)
vp_menos = vp_bono(flujos, plazos, .02 - h)
(vp_mas - vp_menos)/(2 * h)
der_vp_bono(flujos, plazos, .02) # f(x + h) = f(x) + f'(x)*h + error(h), error(h)->0 , h->0
Ahora definimos la función que encuentre la TIR para un cierto precio de mercado.
def encuentra_tir(flujos, plazos, vp, tasa):
"""
Calcula la tasa de descuento o TIR que hace que el valor presente del bono (en base 100)
sea igual a un valor dado.
Parameters
----------
flujos: List[float]
Contiene los flujos del bono.
plazos: List[float]
Contiene los plazos residuales de los flujos expresados en días.
vp: float
Valor presente del bono.
tasa: float
Estimación inicial del valor del resultado.
Returns
-------
float
Tasa de descuento buscada.
"""
epsilon = .000001
diff = 1000
while diff > epsilon:
q = (vp_bono(flujos, plazos, tasa) - vp) / der_vp_bono(flujos, plazos, tasa)
nueva_tasa = tasa - q
diff = abs(nueva_tasa - tasa)
tasa = nueva_tasa
return tasa
tir = encuentra_tir(flujos, plazos, 104, .02)
print(f'El valor de la TIR es: {tir:.8%}')
Hagamos el check:
print(f'El valor presente con la TIR es: {vp_bono(flujos, plazos, tir):,.8f}')