Está en la página 1de 78

Introducción a la programación en Python

para finanzas

Software profesional en finanzas

UDC. 2019 − 20
Indice

Programación en Python para finanzas


I Librerı́as para cálculo numérico y cientı́fico: NumPy y SciPy
I Gráficos 2-D y 3-D con Matplotlib
I Simulación de procesos estocásticos y valoración
I Interacción con Excel
I Pandas
I QuantLib
Referencias-Programación en Python para finanzas

Yves Hilpisch, Python for Finance. Analize big financial data, O’Reilly, 2015
Gouthan Balaraman and Luigi Ballagio, QuantLib Python Cookbook, 2019
James Ma Weiming, Mastering Python for Finance, Packt Publishing 2015
https://docs.python.org/3/
https://www.numpy.org/
https://www.scipy.org/
https://matplotlib.org/
http://www.python-excel.org
http://pandas.pydata.org
http://quantlib.org
Python para finanzas cuantitativas
En el mundo de las finanzas es necesario procesar y analizar grandes cantidades de datos.
Python se está utilizando en muchos sectores como la banca, los seguros, etc, para construir
herramientas que permitan obtener precios de activos o gestionar riesgos, por ejemplo.
¿Por qué utilizar Python?
simple sintaxis: los programas resultan fáciles de leer.
Python dispone de una gran variedad de herramientas para realizar cuanquier tipo de
tarea: cálculo cientı́fico, desarrollo de aplicaciones web, tareas de administración de
sistemas, bases de datos, ...
facilidad de integración en aplicaciones desarrolladas con otros lenguajes de programación
como C, C++ o Fortran.
eficiencia y productividad: módulos testeados por amplia comunidad de usuarios y
lenguaje interactivo y dinámico.
disponibilidad de muchas librerı́as para finanzas.
Python para finanzas cuantitativas

Algunas librerı́as para finanzas:


Numpy: librerı́a para cálculo cientı́fico que contiene también algunas funciones para
finanzas. http://numpy.org
SciPy: librerı́a que contiene utilidades para cálculo númerico. http://www.scipy.es
Matplotlib: contiene herramientas para visualización de datos en 2D y 3D.
http://matplotlib.org
Librerı́as que nos permiten interactuar con Excel. http://www.python-excel.org
Pandas: herramientas para manipulación y análisis de datos.
http://pandas.pydata.org
QuantLib: librerı́a para finanzas cuantitativas. http://quantlib.org
NumPy
Python es un lenguaje interpretado, por tanto, trabajar con bucles es, en general, más
lento que en un lenguaje compilado.
La librerı́a NumPy permite, por ejemplo, realizar operaciones vectoriales/matriciales de
una forma eficiente.
Para trabajar con los métodos implementados en la librerı́a, debemos importarla:
1 i m p o r t numpy a s np #i m p o r t a m o s t o d o s l o s métodos / p a q u e t e s de NumPy
2 from numpy i m p o r t *

Algunas de sus funcionalidades son, por ejemplo:


I manejo de arrays n-dimensionales,
I inversión de matrices,
I resolución de sistemas de ecuaciones lineales,
I generación de matrices especiales (matrices nulas, matriz identidad, ...),
I generación de números aleatorios,
I manejo de polinomios,
I funciones para finanzas (Numpy financial).
NumPy
Creación de un array a partir de una lista:
1 a =[ −3 ,1 , −2.4 ,9 ,0]
2 np . a r r a y ( a )
3 Out [ 2 0 4 ] : a r r a y ( [ − 3 . , 1 . , −2.4 , 9. , 0. ])
4 b=[[1 ,2.3] ,[4 ,5.2]]
5 np . a r r a y ( b )
6 Out [ 2 0 6 ] :
7 array ( [ [ 1 . , 2.3] ,
8 [4. , 5.2]])

Creación de una lista a partir de un array :


1 np . a r r a y ( a ) . t o l i s t ( )
2 Out [ 2 0 8 ] : [ − 3 . 0 , 1 . 0 , −2.4 , 9 . 0 , 0 . 0 ]
NumPy
Algunos arrays especiales:
1 np . z e r o s ( 3 )
2 Out [ 2 1 3 ] : a r r a y ( [ 0 . , 0 . , 0 . ] )
3 np . z e r o s ( 3 , ’ i ’ )
4 Out [ 2 1 4 ] : a r r a y ( [ 0 , 0 , 0 ] , d t y p e=i n t 3 2 )
5 np . z e r o s ( [ 4 , 2 ] )
6 np . o n e s ( 2 )
7 Out [ 2 1 6 ] : a r r a y ( [ 1 . , 1 . ] )
8 np . o n e s ( 2 , ’ i ’ )
9 Out [ 2 1 7 ] : a r r a y ( [ 1 , 1 ] , d t y p e=i n t 3 2 )
10 np . o n e s ( [ 3 , 2 ] )
11 np . e y e ( 2 ) #m a t r i z i d e n t i d a d
12 np . l i n s p a c e ( 0 , 2 , 3 ) #l i n s p a c e ( a , b , n ) p o r d e f e c t o n=50
13 Out [ 2 2 0 ] : a r r a y ( [ 0 . , 1 . , 2 . ] )
14 np . l o g s p a c e ( 0 , 2 , 3 ) #l o g s p a c e ( a , b , n ) e s c a l a l o g a rı́ t m i c a
15 Out [ 2 2 1 ] : a r r a y ( [ 1. , 10. , 100.])
NumPy

1 a1=np . a r r a y ( [ 0 . 2 , − 1 . 8 7 , 2 . 3 4 , − 4 . , 2 ] )
2 a2=np . a r r a y ( [ 2 . 2 , − 3 . 7 , 5 . 2 4 , 4 . 1 7 , − 2 . 3 1 ] )
3 np . z e r o s l i k e ( a1 )#c r e a un a r r a y de c e r o s con e l mismo número de e l e m e n t o s que
a1
4 Out [ 1 9 9 ] : a r r a y ( [ 0 . , 0 . , 0 . , 0 . , 0 . ] )
5 np . o n e s l i k e ( a2 )#c r e a un a r r a y de unos con e l mismo número de e l e m e n t o s que a2
6 Out [ 2 0 0 ] : a r r a y ( [ 1 . , 1 . , 1 . , 1 . , 1 . ] )
7 a1 [ a1<a2 ]#d e v u e l v e un a r r a y con l o s e l e m e n t o s de a1 menores que l o s de a2
8 Out [ 2 0 1 ] : a r r a y ( [ 0 . 2 , 2 . 3 4 , −4. ] )
9 a2 [ a1>a2 ]#d e v u e l v e un a r r a y con l o s e l e m e n t o s de a2 que s o n menores que l o s de
a1
10 Out [ 2 0 2 ] : a r r a y ( [ − 3 . 7 , − 2 . 3 1 ] )
NumPy
1 a =[[1 ,3 ,2.6] ,[4 , −2.9 ,5]]
2 a1=np . a r r a y ( a )
3 a1 . s h a p e #d e v u e l v e e l número de f i l a s y c o l u m n a s d e l a r r a y
4 Out [ 2 1 3 ] : ( 2 , 3 )
5 a1 . s h a p e [ 0 ] #d e v u e l v e e l número de f i l a s
6 Out [ 2 1 4 ] : 2
7 a1 . s h a p e [ 1 ] #d e v u e l v e e l número de c o l u m n a s
8 Out [ 2 1 5 ] : 3
9 a1 . s h a p e =(3 ,2) #cambia l a s d i m e n s i o n e s d e l a r r a y
10 a1
11 Out [ 2 1 8 ] :
12 array ( [ [ 1. , 3. ] ,
13 [ 2.6 , 4. ] ,
14 [ −2.9 , 5 . ] ] )
15 a1 . s i z e #d e v u e l v e e l número de e l e m e n t o s d e l a r r a y
16 Out [ 2 1 9 ] : 6
NumPy
1 a2=np . a r r a y ( [ [ 1 . , 3 . 4 , − 4 ] , [ 1 , 3 , − 7 ] , [ 1 . 2 , − 3 . 5 , − 7 ] ] )
2 np . d i a g ( a2 )#d e v u e l v e l a d i a g o n a l de a2
3 Out [ 2 3 3 ] : a r r a y ( [ 1 . , 3 . , −7.])
4 np . t r i u ( a2 )#o b t i e n e una m a t r i z t r i a n g u l a r s u p e r i o r a p a r t i r de a2
5 a r r a y ( [ [ 1 . , 3 . 4 , −4. ] ,
6 [ 0 . , 3 . , −7. ] ,
7 [ 0 . , 0 . , −7. ] ] )
8 np . t r i l ( a2 )#o b t i e n e una m a t r i z t r i a n g u l a r i n f e r i o r a p a r t i r de a2
9 array ( [ [ 1. , 0. , 0. ] ,
10 [ 1. , 3. , 0. ] ,
11 [ 1 . 2 , −3.5 , −7. ] ] )
12 np . l i n a l g . i n v ( a2 ) #c a l c u l a l a i n v e r s a de una m a t r i z
13 a r r a y ( [ [ 2 . 0 8 1 4 2 7 2 6 , −1.72918573 , 0 . 5 3 9 7 9 8 7 2 ] ,
14 [ 0.06404392 , 0.10064044 , −0.13723696] ,
15 [ 0 . 3 2 4 7 9 4 1 4 , −0.34675206 , 0 . 0 1 8 2 9 8 2 6 ] ] )
16 np . t r a n s p o s e ( a2 )#c a l c u l a l a t r a s p u e s t a de una m a t r i z
NumPy

Acceso a los componentes de un array:


1 a2 [ 1 , 2 ] #e l e m e n t o de l a s e g u n d a f i l a y t e r c e r a columna
2 Out [ 2 3 8 ] : −7.0
3 a2 [ : , 0 ]#p r i m e r a columna
4 Out [ 2 4 0 ] : a r r a y ( [ 1 . , 1 . , 1 . 2 ] )
5 a2 [ 1 , : ]#s e g u n d a f i l a
6 Out [ 2 4 1 ] : a r r a y ( [ 1 . , 3 . , −7.])
NumPy
Producto de arrays: para multiplicar dos arrays A y B necesitamos que el número de
columnas de A coincida con el número de filas de B.
Ejemplo:
1 A=[[1 ,3 ,7] ,[2 ,9 ,4]]
2 B=[[3 ,5] ,[1 ,7] ,[2 ,8]]
3 np . d o t (A , B) #c a l c u l a e l p r o d u c t o de a r r a y s
Nota: el producto de una matriz A y un vector v no depende de si v es un vector fila o un
vector columna.
Producto interno: el producto escalar de dos vectores (arrays de 1 dimensión) u y v lo
podemos realizar de la siguiente manera:
1 u=np . a r r a y ( [ 1 , − 7 , 3 ] )
2 v=np . a r r a y ( [ − 2 , 6 , 3 ] )
3 np . i n n e r ( u , v ) #c a l c u l a e l p r o d u c t o i n t e r n o
NumPy
Operadores relacionales: <, >, <=, >=, ==, ! =
I si se aplican a arrays con el mismo número de filas y columnas, operan elemento a elemento
y devuelven un array cuyos componentes son True o False.
1 u<v
2 Out [ 2 8 6 ] : a r r a y ( [ F a l s e , True , F a l s e ] )

I si se aplican a un array y a un valor real, comparan cada componente del array con el escalar,
y devuelven un array cuyos componentes son True o False.
1 v>=3
2 Out [ 2 8 7 ] : a r r a y ( [ F a l s e , True , True ] )

Operadores lógicos (and, or, not): se combinan con los operadores relacionales para
comprobar condiciones múltiples.
NumPy

Algunas operaciones con arrays:


1 max ( u )#a r r a y s u n i d i m e n s i o n a l e s
2 min ( v )
3 a2 . max ( )#maximo p a r a a r r a y s b i d i m e n s i o n a l e s
4 a2 . sum ( )#suma e l e m e n t o s d e l a r r a y
5 a2 . cumsum ( )
6 a2 . p r o d ( )#p r o d u c t o e l e m e n t o s d e l a r r a y
7 a2 . cumprod ( )
8 a2 . mean ( )#d e v u e l v e l a media
9 a2 . s t d ( )#d e v u e l v e d e s v i a c i ó n tı́ p i c a
10 a2 . s o r t ( )#o r d e n a f i l a s de menor a mayor
11 np . r o t 9 0 ( a2 , k=1) #r o t a un a r r a y k * 90 g r a d o s a l a i z q u i e r d a
12 np . f l i p u d ( a2 )#m a n t i e n e c o l u m n a s e i n t e r c a m b i a f i l a s
13 np . f l i p l r ( a2 )#m a n t i e n e f i l a s e i n t e r c a m b i a c o l u m n a s
NumPy
Las funciones sin, cos, tan, log, log10, exp, sqrt, arcsin, sinh, ** del módulo NumPy
actúan sobre cada componente de un array.
Podemos implementar nuestros propios módulos: Creamos un módulo en el que definimos
una función:
1 # −*− c o d i n g : u t f −8 −*−
2 #f u n c i o n 1 . py
3 def f1 ( x ) :
4 r e t u r n x ** 2
En el terminal de IPython tecleamos:
1 import funcion1
2 x=np . a r r a y ( [ [ − 4 , 5 ] , [ 7 , − 1 ] ] )
3 funcion1 . f1 ( x )
4 Out [ 3 2 7 ] :
5 array ([[16 , 25] ,
6 [49 , 1 ] ] , d t y p e=i n t 3 2 )
NumPy
Implementamos ahora la siguiente función:
1 i m p o r t numpy a s np
2 def f2 ( x ) :
3 i f x <0:
4 r e t u r n −1
5 else :
6 r e t u r n np . s q r t ( x )

Cuando intentamos aplicar la función a un objeto de tipo array obtenemos un error:


1 x
2 Out [ 3 3 0 ] :
3 array ([[ −4 , 5] ,
4 [ 7 , −1]])
5 f2 ( x )
6 V a l u e E r r o r : The t r u t h v a l u e o f an a r r a y w i t h more t h a n one e l e m e n t i s
ambiguous . Use a . any ( ) o r a . a l l ( )
NumPy

Para solucionar el error anterior utilizamos:


Si x es un array unidimensional:
I np.any(x): devuelve True is algún elemento del array es distinto de cero, y devuelve False si
todos los elementos del array son iguales a cero.
I np.all(x): devuelve True si todos los elementos del array son distintos de cero, y devuelve
False si al menos uno de los elementos es igual a cero.
Si x es un array multidimensional podemos hacer las llamadas a los métodos de las
siguientes formas: np.any(x), x.any(), np.all(x), x.all()
NumPy
En Python, debemos evitar la utilización de bucles siempre que sea posible:
1 i m p o r t numpy a s np
2 import time
3 n=e v a l ( i n p u t ( ’ I n t r o d u c e N : ’ ) )
4 c1=t i m e . p e r f c o u n t e r ( )
5 p r i n t ( c1 )
6 x=np . z e r o s ( n )
7 f o r i i n r a n g e ( n ) : #u t i l i z a n d o un b u c l e
8 x [ i ]=3.0 −2 * i+i * i
9 c2=t i m e . p e r f c o u n t e r ( )
10 p r i n t ( c2 )
11 i n d=np . l i n s p a c e ( 0 , n −1,n ) #s i n u t i l i z a r un b u c l e
12 y =3.0−2 * i n d+i n d * i n d
13 c3=t i m e . p e r f c o u n t e r ( )
14 p r i n t ( c3 )
15 p r i n t ( ’ Elapsed time : ’ )
16 p r i n t ( ’ Tiempo u t i l i z a n d o b u c l e ’ , c2−c1 , ’ s ’ )
17 p r i n t ( ’ Tiempo s i n u t i l i z a r b u c l e ’ , c3−c2 , ’ s ’ )
NumPy

Objeto Matrix: es una subclase de la clase array. Permite manejar matrices (un objeto
Matrix va a ser siempre un objeto bidimensional). Este objeto se utiliza para realizar
operaciones algebraicas con matrices de forma sencilla.
1 i m p o r t numpy a s np
2 np . m a t r i x ( ’ 1 2 3 ; 4 5 6 ’ ) #c r e a una m a t r i z a p a r t i r de un s t r i n g
3 np . mat ( [ [ 2 , 4 , 1 ] , [ 7 , 3 , 9 ] ] ) #c r e a una m a t r i z a p a r t i r de una s e c u e n c i a
anidada
4 A=np . m a t r i x ( np . random . r a n d ( 3 , 2 ) ) #c r e a una m a t r i z a p a r t i r de un a r r a y
5 B=np . m a t r i x ( np . random . r a n d ( 2 , 3 ) )
6 C=A*B #m u l t i p l i c a m a t r i c e s
7 A . T #t r a s p u e s t a de una m a t r i z
8 C . I #i n v e r s a de una m a t r i z
NumPy
Método asarray(objeto): crea un array que es una copia por referencia de objeto.
1 m=np . mat ( ’ 3 . 1 . 2 5 ; 6 . 2 9 ’ )
2 a=np . a s a r r a y (m) #a e s una c o p i a de m p o r r e f e r e n c i a
3 m[0 ,0]= −25 #s i cambia m t a m b ié n cambia a y v i c e v e r s a
4 m
5 Out [ 3 5 1 ] :
6 matrix ([[ −25. , 1.25] ,
7 [ 6.2 , 9. ]])
8 a
9 Out [ 3 5 2 ] :
10 array ([[ −25. , 1.25] ,
11 [ 6.2 , 9. ]])
12 d e l ( a ) # s e b o r r a a p e r o no m
13 m
14 Out [ 3 5 3 ] :
15 matrix ([[ −25. , 1.25] ,
16 [ 6.2 , 9. ]])
NumPy
Manejo de polinomios en NumPy:
1 p=np . p o l y 1 d ( [ 4 , 2 , 3 , 1 ] ) #c r e a un p o l i n o m i o a p a r t i r de l a l i s t a de
coeficientes
2 p=np . p o l y 1 d ( [ 4 , 2 , 3 , 1 ] , r=True ) #l o c r e a a p a r t i r de una l i s t a de r a i c e s
3 p . r #d e v u e l v e l a s r a i c e s d e l p o l i n o m i o
4 Out [ 3 5 9 ] : a r r a y ( [ 4 . , 3 . , 2 . , 1 . ] )
5 p ( 0 . 5 ) #e v a l ú a e l p o l i n o m i o en un pu n t o
6 p o l y v a l ( p , 0 . 5 ) #e v a l ú a e l p o l i n o m i o en un p u n t o
7 p ( [ 2 , − 3 , 4 ] ) #e v a l ú a e l p o l i n o m i o en una l i s t a de p u n t o s
8 p r i n t ( p . d e r i v (m=2) )#i m p r i m e l a s e g u n d a d e r i v a d a d e l p o l i n o m i o
9 2
10 12 x − 60 x + 70
11 p r i n t ( p . d e r i v (m=1) )
12 3 2
13 4 x − 30 x + 70 x − 50
14 p r i n t ( p . i n t e g ( ) ) #i m p r i m e l a p r i m i t i v a d e l p o l i n o m i o
15 5 4 3 2
16 0 . 2 x − 2 . 5 x + 1 1 . 6 7 x − 25 x + 24 x
NumPy

Manejo de polinomios en NumPy:


1 c=np . p o l y ( [ − 3 , 2 , 5 ] )#d e v u e l v e l o s c o e f i c i e n t e s de un p o l i n o m i o a p a r t i r de
sus r a i c e s
2 q=np . p o l y 1 d ( c )
3 p r i n t ( p+q ) #suma de p o l i n o m i o s ; a l t e r n a t i v a : np . p o l y a d d ( p , q )
4 4 3 2
5 1 x − 9 x + 31 x − 61 x + 54
6
7 p r i n t ( p * q )#p r o d u c t o de p o l i n o m i o s ; a l t e r n a t i v a np . p o l y m u l ( p , q )
8 7 6 5 4 3 2
9 1 x − 14 x + 64 x − 50 x − 461 x + 1504 x − 1764 x + 720
10 p r i n t ( q/p ) #c o c i e n t e de p o l i n o m i o s : d e v u e l v e e l c o c i e n t e y e l r e s t o ;
alternativa
11 #np . p o l y d i v ( q , p )
12 ( poly1d ( [ 0 . ] ) , poly1d ( [ 1. , −4. , −11. , 3 0 . ] ) )
NumPy
Generación de números aleatorios: librerı́a random contenida en NumPy.
Algunas funciones para generar números aleatorios:
I rand(d0,d1,...,dn): devuelve un array de una forma dada con números aleatorios en el
intervalo abierto [0, 1).
1 i m p o r t numpy . random as npr
2 npr . rand (3 ,3)
3 Out [ 3 ] :
4 array ([[0.07856684 , 0.83859696 , 0.64663105] ,
5 [0.9429723 , 0.28707297 , 0.93000611] ,
6 [0.40877077 , 0.68849646 , 0.98013048]])

I randn(d0,d1,...,dn): devuelve un array de una forma dada con muestras de una distribución
normal estándard.
1 npr . randn (3)
2 Out [ 1 1 ] : a r r a y ( [ 0 . 2 3 1 6 0 0 3 6 , −0.67115477 , − 0 . 9 8 5 3 1 4 7 6 ] )
NumPy
Algunas funciones para generar números aleatorios:
I random(size): devuelve un array con números aleatorios en el intervalo abierto [0, 1).
1 n p r . random ( 4 )
2 Out [ 4 ] : a r r a y ( [ 0 . 6 6 5 3 7 0 3 5 , 0 . 9 3 9 2 9 1 1 1 , 0 . 6 5 7 5 6 2 8 4 , 0 . 6 6 0 7 9 5 1 3 ] )

I standard normal(size): devuelve un array con muestras de una distribución normal estándard.
1 npr . standard normal (4)
2 Out [ 6 ] : a r r a y ( [ − 0 . 4 1 5 6 0 9 3 6 , 1 . 1 3 4 3 1 0 9 , −0.02431827 , − 0 . 1 3 1 7 0 5 5 2 ] )

I normal(mean,std,size): devuelve un array con muestras de una distribución normal con media
mean y desviación tı́pica std.
1 npr . normal (100 ,20 ,4)
2 Out [ 1 0 ] : a r r a y ( [ 7 6 . 7 5 6 3 0 0 7 9 , 1 0 0 . 6 9 1 3 2 7 8 4 , 1 3 1 . 3 7 8 4 7 0 5 3 ,
59.46042839])
Numpy financial
Instalación paquete:
1 pip i n s t a l l numpy financial

Algunas funciones para finanzas del módulo numpy financial


Valor futuro : numpy financial.fv(rate,nper,pmt,pv,when=’end’)
Valor final de una inversión de capital depositado en una cuenta bancaria que paga intereses.
Parámetros de la función:
rate: tipo de interés que nos rendirá el capital inicial o la anualidad por cada perı́odo.
nper: numero de perı́odos.
pmt: el valor de los depósitos que vamos a ir invirtiendo en nuestra anualidad.
pv: capital inicial o anualidad.
when: cuando se van a hacer efectivos los depósitos, al comienzo o al final de cada
perı́odo.
Numpy
Ejemplo 1(interés compuesto anual) : Calcular el valor futuro de un depósito de 1000¿
a 3 años con una tasa de interés anual del 6 %.
1 i m p o r t n u m p y f i n a n c i a l a s n p f #c a p i t a l i z a c i ó n compuesta a n u a l
2 FV=n p f . f v ( r a t e =0.06 , n p e r =3 ,pmt=0 , pv =−1000) #v a l o r f u t u r o
3 FV
4 Out [ 1 ] : 1 1 9 1 . 0 1

Ejemplo 2 (anualidades) : Supongamos que hacemos 10 depósitos anuales de 1000¿ cada


uno al comienzo de cada año. ¿ Cuál será el valor futuro con una tasa de interés anual del
6 %?.
1 i m p o r t n u m p y f i n a n c i a l a s n p f #c á l c u l o a n u a l i d a d e s
2 FV=n p f . f v ( r a t e =0.06 , n p e r =10 ,pmt=−1000, pv =0 ,when= ’ b e g i n ’ ) #v a l o r f u t u r o
3 FV
4 Out [ 2 ] : 1 3 9 7 1 . 6 4 2 6 3 8 9 2 3 7 6 4
Numpy financial

Algunas funciones para finanzas del módulo numpy financial


Valor presente : numpy financial.pv(rate,nper,pmt,fv=0,when=’end’)
Valor actual de una cantidad a recibir en el futuro.
Parámetros de la función:
rate: tipo de interés que nos pagarı́an por los depósitos.
nper: numero de perı́odos.
pmt: el valor de los pagos que vamos a recibir.
fv: pago final.
when: cuando se van a recibir los pagos, al comienzo o al final de cada perı́odo.
Numpy financial
Ejemplo 1(actualización compuesta) : Calcular el valor actualizado de recibir 1000¿
dentro de 3 años para una tasa de interés anual del 6 %.
1 i m p o r t n u m p y f i n a n c i a l a s n p f #a c t u a l i z a c i ó n compuesta a n u a l
2 PV=n p f . pv ( r a t e =0.06 , n p e r =3,pmt=0, f v =1000) #c á l c u l o d e l v a l o r p r e s e n t e
3 PV
4 Out [ 4 ] : −839.6192830323018

Ejemplo 2 (anualidades) : Supongamos que recibimos pagos de 250¿ al final de cada año
durante 5 años. ¿Cuál será el valor presente de esta anualidad si el tipo de interés que nos
ofrece el banco es del 6 %?.
1 i m p o r t n u m p y f i n a n c i a l a s n p f #a n u a l i d a d e s
2 PV=n p f . pv ( r a t e =0.06 , n p e r =5,pmt=250 , f v =0,when= ’ end ’ ) #v a l o r p r e s e n t e
3 PV
4 Out [ 5 ] : −1053.090946391429
Numpy financial

Algunas funciones para finanzas del módulo numpy financial


Valor presente neto : numpy financial.npv(rate,values)
Valor actual de una serie de flujos futuros menos el importe de la inversión.
Parámetros de la función:
rate: tasa de descuento.
values: flujos de fondos para cada perı́odo.
Numpy financial
Ejemplo 1 : Supongamos que vamos a recibir en los próximos 5 años estas cantidades: 500¿
al final del primer año, 750¿ al final del segundo, 1000¿al final del tercer año, 1250¿al final
del cuarto año y 500¿al final del quinto año. ¿Cuál serı́a el valor presente neto de este flujo de
fondos?.
1 import n u m p y f i n a n c i a l as npf
2 NPV=n p f . npv ( r a t e =0.06 , v a l u e s =[0 , 5 0 0 , 7 5 0 , 1 0 0 0 , 1 2 5 0 , 5 0 0 ] )
3 NPV
4 Out [ 7 ] : 3 3 4 2 . 5 6 0 8 9 1 7 3 1 0 8 3

Ejemplo 2 : Supongamos que tenemos que invertir hoy 4000¿ para recibir en los próximos 5
años estas cantidades: 500¿ al final del primer año, 750¿ al final del segundo, 1000¿al final
del tercer año, 1250¿al final del cuarto año y 500¿al final del quinto año. ¿Serı́a rentable la
inversión?.
1 import n u m p y f i n a n c i a l as npf
2 NPV=n p f . npv ( r a t e =0.06 , v a l u e s =[ −4000 , 5 0 0 , 7 5 0 , 1 0 0 0 , 1 2 5 0 , 5 0 0 ] )
3 NPV
4 Out [ 8 ] : −657.4391082689172
Numpy financial

Algunas funciones para finanzas del módulo numpy financial


Tasa interna de rendimiento : numpy financial.irr(values)
Tasa de descuento que hace que el valor presente neto de los flujos de fondos futuros sea igual
a 0. También se puede definir como la tasa de interés compuesto que nos paga nuestra
inversión.
Parámetros de la función:
values: flujos de fondos para cada perı́odo.
Numpy financial

Ejemplo 1 : Supongamos que disponemos de 1000¿para invertir, y que podemos decidir


invertir ese dinero en una compañı́a que nos va a pagar 300¿al final de cada uno de los
próximos 4 años; o por otro lado podemos invertir el dinero en una caja de ahorro de un banco
que nos va a pagar 5 % anual. ¿Donde deberı́amos invertir nuestro dinero?
1 import n u m p y f i n a n c i a l as npf
2 IRR=n p f . i r r ( v a l u e s =[ −1000 , 3 0 0 , 3 0 0 , 3 0 0 , 3 0 0 ] )
3 IRR * 100
4 Out [ 1 0 ] : 7 . 7 1 3 8 4 7 2 9 5 2 0 8 3 4 3

Al ser la tasa interna de rendimiento mayor que la tasa que nos ofrece el banco, deberı́amos
invertir el dinero en la compañı́a.
SciPy

SciPy es una librerı́a de Python para cálculo cientı́fico.


Algunos de sus paquetes son:
I linalg: métodos de álgebra lineal
I interpolate: interpolación y resolvedores de EDOs
I integrate: métodos de cuadratura numérica
I optimize: herramientas de optimización y cálculo de raı́ces
I stats: funciones estadı́sticas
SciPy

SciPy contiene el paquete de álgebra lineal linalg, que contiene más métodos que el
paquete linalg de NumPy.
1 i m p o r t numpy a s np
2 import s c i p y . l i n a l g as s c i l
3 A=np . a r r a y ( [ [ 1 , 0 , 0 , 0 ] , [ 0 , − 1 , − 1 , 0 ] , [ 0 , 0 , − 1 , 0 ] , [ 0 , 0 , 0 , 2 ] ] )
4 b=np . a r r a y ( [ 2 , 3 , 4 , 0 ] )
5 s c i l . d e t (A)#c a l c u l a e l d e t e r m i n a n t e de A
6 s c i l . i n v (A)#c a l c u l a l a i n v e r s a de A
7 s c i l . s o l v e (A , b )#r e s u e l v e e l s i s t e m a l i n e a l
8 s c i l . e i g (A) #c a l c u l a a u t o v a l o r e s y a u t o v e c t o r e s
9 s c i l . e i g v a l s (A) #c a l c u l a s o l o l o s a u t o v a l o r e s
Resolución de sistemas lineales

Factorización LU: dada una matriz A no singular, existen unas matrices L triangular
inferior y U triangular superior tales que: A = LU
1 from s c i p y i m p o r t l i n a l g
2 A=np . a r r a y ( [ [ 4 , − 2 , 1 ] , [ 2 0 , − 7 , 1 2 ] , [ − 8 , 1 3 , 1 7 ] ] )
3 P , L , U= l i n a l g . l u (A) #A=P * L *U
4 PL , U= l i n a l g . l u (A , p e r m u t e l =1) #A=PL *U

Factorización de Cholesky: dada una matriz A simétrica y definida positiva, existe una
matriz L triangular inferior tal que: A = LLT
1 A=np . a r r a y ( [ [ 5 , − 3 , 4 ] , [ − 3 , 3 , − 4 ] , [ 4 , −4, 6 ] ] )
2 L= l i n a l g . c h o l e s k y (A , l o w e r=True )
Resolución de sistemas lineales

Factorización QR: dada una matriz A no singular existen unas matrices Q ortogonal y R
triangular superior tales que: A = QR
1 A=np . a r r a y ( [ [ 1 , − 2 , 1 ] , [ − 1 , 3 , 2 ] , [ 1 , −1, − 4 ] ] )
2 Q, R= l i n a l g . q r (A)
Módulo de interpolación en Scipy

El paquete interpolate de SciPy proporciona dos clases de herramientas de


interpolación:
I interpolación lineal unidimensional.
I Splines cúbicos en una y dos dimensiones.
Interpolación lineal 1-D
Supongamos que queremos representar la gáfica f (x) = sin(x) + x2 en el intervalo [0, 2π],
pero solo conocemos el valor de la función en algunos puntos.
1 from s c i p y i m p o r t i n t e r p o l a t e a s i n t e r
2 i m p o r t numpy a s np
3 i m p o r t math
4 import m a t p l o t l i b . pyplot as p l t
5 x=np . l i n s p a c e ( 0 , 2 * math . p i , 5 )
6 y=np . s i n ( x )+x ** 2
7
8 f=i n t e r . i n t e r p 1 d ( x , y )
9
10 xa=np . l i n s p a c e ( 0 , 2 * math . p i , 5 0 )
11 ya=f ( xa ) #e v a l ú a f en cada pu n t o de xa
12 p l t . p l o t ( x , y , ’ o ’ , xa , ya , ’− ’ )
13 l e g e n d ( [ ’ d a t o s ’ , ’ l i n e a l ’ ] , l o c= ’ b e s t ’ )
Interpolación spline lineal y cúbica

1 from s c i p y i m p o r t i n t e r p o l a t e a s i n t e r
2 i m p o r t numpy a s np
3 i m p o r t math
4 import m a t p l o t l i b . pyplot as p l t
5 x=np . l i n s p a c e ( 0 , 2 * math . p i , 5 )
6 y=np . s i n ( x )+x ** 2
7
8 s l f =i n t e r . s p l r e p ( x , y , k=1) #c á l c u l o s p l i n e l i n e a l
9 s c f=i n t e r . s p l r e p ( x , y ) #c á l c u l o s p l i n e c ú b i c o
10 x s=np . l i n s p a c e ( 0 , 2 * math . p i , 5 0 )
11 y s 1=i n t e r . s p l e v ( xs , s l f ) #e v a l u a c i ó n d e l s p l i n e en l o s p u n t o s
12 y s 3=i n t e r . s p l e v ( xs , s c f )
13 p l t . p l o t ( x , y , ’ o ’ , xs , ys1 , ’− ’ , xs , ys3 , ’−− ’ )
14 l e g e n d ( [ ’ d a t o s ’ , ’ l i n e a l ’ , ’ c ú b i c o ’ ] , l o c= ’ b e s t ’ )
El paquete integrate de SciPy

El paquete integrate permite calcular integrales definidas. Algunas funciones contenidas en


este módulo son:
si pasamos una función como parámetro:
I quad(func,a,b,...): calcula la integral definida de la función func, desde a hasta b.
I dblquad(func,a,b,gfun,hfun,...): calcula la integral doble de la función func.
I tplquad(func,a,b,gfun,hfun,qfun,rfun): calcula la integral triple de la función func.
si pasamos una lista o un objeto ndarray como parámetro:
I trapz(f(ndarray),ndarray): calcula la integral usando la regla del trapecio.
I simps(f(ndarray),ndarray): calcula la integral usando la regla de simpson.
El paquete integrate de SciPy

R 2π
Ejemplo: Calcular 0 (sin(x) + 0,5x) dx:
I pasando como argumento una función:
1 import s c i p y import i n t e g r a t e
2 i m p o r t numpy a s np
3 v a l o r , e r r o r=i n t e g r a t e . quad ( lambda x : np . s i n ( x ) +0.5 * x , 0 , 2 * np . p i )
4 #pasamos como argumento una f u n c i ó n
5
6 valor , error
7 Out [ 4 1 ] : ( 9 . 8 6 9 6 0 4 4 0 1 0 8 9 3 5 8 , 1 . 0 9 5 7 4 6 2 0 5 0 0 3 1 1 8 4 e −13)
El paquete integrate de SciPy

R 2π
Ejemplo: Calcular 0 (sin(x) + 0,5x) dx:
I pasando como argumento un objeto ndarray:
1 x i=np . l i n s p a c e ( 0 , 2 * np . p i )
2 f x i =np . s i n ( x i ) +0.5 * x i
3 #R e g l a t r a p e c i o
4 v a l o r t r a p e c i o=i n t e g r a t e . t r a p z ( f x i , x i ) #pasamos como argumento un
l i s t a u objeto ndarray
5 valor trapecio
6 #r e g l a Simpson
7 v a l o r s i m p s o n=i n t e g r a t e . s i m p s ( f x i , x i )
8 valor simpson
El paquete optimize de SciPy:

Algunas de las funcionalidades del paquete optimize de SciPy son:


Minimización de una función escalar de varias variables con y sin restricciones utilizando
una variedad de algoritmos (por ejemplo, Nelder-Mead simplex, Newton, Gradiente
Conjugado): minimize.
Minimización por mı́nimos cuadrados: least squares
Minimización de funciones escalares de una variable: minimize scalar
Búsqueda de raı́ces de funciones: fsolve
Solución de sistemas de ecuaciones no lineales utilizando diferentes algoritmos (por
ejemplo, Newton-Krylov): root
SciPy-Cálculo de raı́ces de ecuaciones no lineales

Raı́ces de una ecuación no lineal: scipy.optimize.fsolve


1 from s c i p y i m p o r t o p t i m i z e
2 s c i . o p t i m i z e . f s o l v e ( lambda x : x **3+np . exp (−x ) −1.5 , −0.5)
3 Out [ 4 6 ] : a r r a y ( [ − 0 . 4 7 4 0 9 5 9 3 ] )
Gráficos 2-D con Matplotlib
Las principales funciones para realizar gráficos se encuentran en la librerı́a pyplot de
M atplotlib.
Representación de conjuntos de datos de una dimensión:
1 import m a t p l o t l i b . pyplot as p l t
2 p l t . p l o t ( x , y , p r o p i e d a d e s ) #x e y deben s e r v e c t o r e s de l a misma d i m e n s i ó n

donde x e y son listas o arrays conteniendo los valores de las abscisas y de las ordenadas,
respectivamente.
Propiedad Abrev. Valor
color c Color de matplotlib
label - Cadena de texto opcionalmente usada para la leyenda
linestyle ls Estilo de lı́nea
linewidth lw Un float, ancho de la lı́nea en puntos
marker - Se especifica el tipo de sı́mbolo
markeredgewidth mew Ancho de la lı́nea entorno al sı́mbolo
markeredgecolor mec Color del borde del sı́mbolo usado
markerfacecolor mfc Color del sı́mbolo
markersize ms Tamaño del sı́mbolo
Gráficos 2-D con Matplotlib

Ejemplos:
1 import m a t p l o t l i b . pyplot as p l t
2 y=np . random . s t a n d a r d n o r m a l ( 2 0 ) #g e n e r a m o s 20 números p s e u d o a l e a t o r i o s
3 x=r a n g e ( l e n ( y ) )
4 plt . plot (x , y)
5 p l t . p l o t ( y )# s i no pasamos x toma l o s v a l o r e s de l o s i n d i c e s como
coordenadas x
6 p l t . p l o t ( y . cumsum ( ) )#l o s métodos d e v u e l v e n de nuevo un o b j e t o n d a r r a y con
l o s mismos d a t o s
Gráficos 2-D con Matplotlib

Por defecto la representación se realiza con lı́nea continua azul:


1 plt . plot (x , y)

Podemos especificar propiedades:


1 p l t . p l o t ( x , y , c= ’ r ’ , l s = ’−− ’ , m a r k e r= ’ d ’ , ms=4)

Ejemplo:
1 x=np . a r a n g e ( 0 , 2 . 2 5 , 0 . 2 5 )
2 y=x **3+x ** 2
3 p l t . p l o t ( x , y , c= ’ r ’ , l s = ’−− ’ , m a r k e r= ’ d ’ , ms=4)
Gráficos 2-D con Matplotlib

Sı́mbolo Color Sı́mbolo Marcador


y yellow . puntos
m magenta o cı́rculos
c cyan x marcas en ×
r red + marcas en +
g green s marcas cuadradas (square)
b blue d marcas en diamante (diamond)
w white ˆ triángulo apuntando arriba
k black v triángulo apuntando abajo
0.75 escala de grises [0, 1] > triángulo apuntando a la dcha
#636fb0 RGB en hexadecimal < triángulo apuntando a la izda
(0.9,0.111,1) una tupla RGB p estrella de cinco puntas
h estrella se seis puntas
Sı́mbolo Estilo de lı́nea
- lı́neas continuas
: lı́neas a puntos Todos los sı́mbolos se introducen
-. lı́neas a barra-punto como string, salvo la tupla RGB
-- lı́neas a trazos
Gráficos 2-D con Matplotlib

plt.grid (value), value=True/False: activa/elimina una cuadrı́cula de fondo; por


defecto está desactivado ( False)
plt.box (value), value=True/False: activa/elimina el recuadro de los ejes; por
defecto está activado ( True)

plt.title (’cadena’): añade un tı́tulo en la parte superior del dibujo


plt.xlabel (’cadena’): añade una etiqueta al eje de abscisas
plt.ylabel (’cadena’): idem, pero en el eje de ordenadas
Gráficos 2-D con Matplotlib
plt.text (x,y,’cadena’(,parameters)): introduce la cadena de texto a partir del
punto de coordenadas (x, y); los posibles parámetros (parameters) son:
horizontalalignment = ’left’/’right’/’center’
verticalalignment = ’top’/’bottom’/’center’
rotation = num. de grados
multialignment = ’left’/’right’/’center’

plt.legend (lista-plots, lista-labels, loc=value, shadow=False/True):


define rótulos para las distintas lı́neas o ejes utilizados; si no se especifica lista-plots,
ni lista-labels, coge el orden en que se introducen las gráficas, y las correspondientes
etiquetas.
loc indica la posición que se coloca la leyenda:
loc = ’best’,’center’,’upper’,’right’,’left’,’lower’,
’upper right’,’center right’,’lower right’
Si no se especifica localización sitúa la leyenda en la mejor posición.
Gráficos 2-D con Matplotlib
plt.figure(propiedades): abre una nueva ventana para representación.
Ejemplo:
1 import m a t p l o t l i b . pyplot as p l t
2 y=np . random . s t a n d a r d n o r m a l ( 2 0 ) #g e n e r a m o s 20 números p s e u d o a l e a t o r i o s
3 p l t . f i g u r e ( f i g s i z e =(7 ,4) )
4 p l t . p l o t ( y . cumsum ( ) , c= ’ r ’ , m a r k e r= ’ o ’ )
5 p l t . g r i d ( True )
6 p l t . t e x t ( 2 , 1 . 2 5 , ’ G r á f i c o ’ )#a ñade t e x t o en e l g r á f i c o
7 p l t . x l a b e l ( ’ ı́ n d i c e ’ )
8 plt . ylabel ( ’ valor ’ )
Gráficos 2-D con Matplotlib

Conjuntos de datos de dos dimensiones: si pasamos como parámetro a plot un array de


dos dimensiones, interpreta los datos como conjuntos separados y dibuja varias lı́neas.
1 y=np . random . s t a n d a r d n o r m a l ( ( 1 0 , 3 ) )
2 p l t . p l o t ( y )#d i b u j a 3 l i n e a s
3 p l t . p l o t ( y [ : , 0 ] , c= ’ g ’ , l a b e l= ’ p r i m e r a ’ )
4 p l t . p l o t ( y [ : , 1 ] , c= ’ r ’ , l a b e l= ’ s e g u n d a ’ )
5 p l t . p l o t ( y [ : , 2 ] , c= ’ b ’ , l a b e l= ’ t e r c e r a ’ )
6 p l t . l e g e n d ( l o c= ’ b e s t ’ )
Graficos 2-D con Matplotlib

Representación de datos de dos dimensiones en figuras separadas:


plt.subplot(numrows,numcols,fignum)
I numrows es el número de filas
I numcols es el número de columnas
I fignum es el número de figura

1 p l t . f i g u r e ( f i g s i z e =(7 ,4) )
2 y=np . random . s t a n d a r d n o r m a l ( ( 1 0 , 3 ) )
3 p l t . s u b p l o t ( 1 , 2 , 1 )#no s o n n e c e s a r i a s l a s comas
4 p l t . p l o t ( y [ : , 0 ] , c= ’ g ’ , l a b e l= ’ p r i m e r a ’ )
5 p l t . l e g e n d ( l o c= ’ b e s t ’ )
6 plt . subplot (1 ,2 ,2)
7 p l t . p l o t ( y [ : , 1 ] , c= ’ r ’ , l a b e l= ’ s e g u n d a ’ )
8 p l t . l e g e n d ( l o c= ’ b e s t ’ )
Gráficos 2-D con Matplotlib
Otros tipos de gráficos:
I Gráficos de dispersión:
1 p l t . f i g u r e ( f i g s i z e =(7 ,4) )
2 y=np . random . s t a n d a r d n o r m a l ( ( 5 0 0 , 2 ) )
3 p l t . s c a t t e r ( y [ : , 0 ] , y [ : , 1 ] , m a r k e r= ’ o ’ )
4 p l t . x l a b e l ( ’ primero ’ )
5 p l t . y l a b e l ( ’ segundo ’ )
6 p l t . t i t l e ( ’ G r á f i c o de d i s p e r s i ó n ’ )
Gráficos 2-D con Matplotlib
Otros tipos de gráficos
I Histogramas:
1 p l t . f i g u r e ( f i g s i z e =(7 ,4) )
2 y=np . random . s t a n d a r d n o r m a l ( ( 5 0 0 , 3 ) )
3 p l t . h i s t ( y , l a b e l =[ ’ P r i m e r o ’ , ’ Segundo ’ , ’ T e r c e r o ’ ] , b i n s =30)
4 p l t . x l a b e l ( ’ primero ’ )
5 p l t . y l a b e l ( ’ segundo ’ )
6 p l t . t i t l e ( ’ Histograma ’ )
Gráficos 3-D con Matplotlib
Aplicación: representación de una superficie de volatilidades mostrando las volatilidades
implı́citas de manera simultánea para diferentes vencimientos y strikes.
Consideramos:
I Strikes entre 50 y 150
I Vencimientos entre 0.5 y 2.5 años
Por tanto, tenemos un sistema de coordenadas en 2 dimensiones. Utilizamos la función
meshgrid de NumPy para generar dicho sistema de coordenadas a partir de dos objetos
ndarray de 1 dimensión:
1 i m p o r t numpy a s np
2 #from m p l t o o l k i t s . mplot3d i m p o r t Axes3D
3 s t r i k e =np . l i n s p a c e ( 5 0 , 1 5 0 , 2 4 )
4 m a t u r i t y=np . l i n s p a c e ( 0 . 5 , 2 . 5 , 2 4 )
5 s t r i k e , m a t u r i t y=np . m e s h g r i d ( s t r i k e , m a t u r i t y )
6 #r e p i t e l o s v a l o r e s o r i g i n a l e s
Gráficos 3-D con Matplotlib
Generamos ”falsas”volatilidades implı́citas:
1 v i =( s t r i k e −100) * * 2 / ( 1 0 0 * s t r i k e ) / m a t u r i t y #” f a l s a s ” v o l a t i l i d a d e s
i m p lı́ c i t a s

Representamos la superficie:
1 import m a t p l o t l i b . pyplot as p l t
2 f i g =p l t . f i g u r e ( )
3 ax= f i g . gca ( p r o j e c t i o n= ’ 3d ’ ) #o t r a a l t e r n a t i v a ax=Axes3D ( f i g )
4 s u r f=ax . p l o t s u r f a c e ( s t r i k e , m a t u r i t y , v i , cmap=p l t . cm . r a i n b o w )
5 ax . s e t x l a b e l ( ’ s t r i k e ’ )
6 ax . s e t y l a b e l ( ’ v e n c i m i e n t o ’ )
7 ax . s e t z l a b e l ( ’ i m p l i e d v o l a t i l i t y ’ )
8 fig . colorbar ( surf )
Gráficos 3-D con Matplotlib

Superficie de volatilidades:
Simulación de procesos estocásticos-Variables aleatorias

En el modelo de Black-Scholes para para valorar opciones, el precio del activo ST en una fecha
futura T y conocido el valor en tiempo t = t0 , S0 , viene dado por la siguiente ecuación:

 
1 2
ST = S0 exp (r − σ )T + σ T z
2

donde
ST es el precio del activo en tiempo T
r es el tipo de interés libre de riesgo
σ es la volatilidad constante de S
z variable aleatoria con distribución normal
Simulación de procesos estocásticos-Variables aleatorias

Simulación de ST en el modelo de Black-Scholes:


1 i m p o r t numpy a s np
2 import m a t p l o t l i b . pyplot as p l t
3 S0=100 #v a l o r i n i c i a l
4 r =0.05 #t i p o de i n t e r é s c o n s t a n t e
5 s i g m a =0.25 #v o l a t i l i d a d
6 T=1. # en a ñ o s
7 I =10000 #número de t r a y e c t o r i a s
8 ST=S0 * np . exp ( ( r−s i g m a * * 2 / 2 ) *T+
9 s i g m a * np . s q r t (T) * np . random . s t a n d a r d n o r m a l ( I ) )
Simulación de procesos estocásticos-Variables aleatorias
Representación del movimiento Browniano geométrico simulado:
1 plt . h i s t (ST , b i n s =50)
2 plt . x l a b e l ( ’S ’ )
3 plt . ylabel ( ’ frecuencia ’)
4 plt . t i t l e ( ’ S i m u l a c i ó n m o v i m i e n t o Browniano g e o m é t r i c o ’ )
Procesos estocásticos

Movimiento Browniano Geométrico: en el modelo de Black-Scholes el precio del


subyacente está gobernado por la ecuación diferencial estocástica

dSt = rSt dt + σSt dZt (1)

Simulación del precio del subyacente utilizando la solución de la ecuación diferencial


estocástica (1):

 
1 2
St = St−∆t exp (r − σ )∆t + σ ∆tzt
2
donde
I ∆t es el intervalo temporal fijo de discretización
I zt es una variable aleatoria con distribución normal
Procesos estocásticos

Simulación del precio del subyacente utilizando la solución de la ecuación diferencial


estocástica (1): √
St = St−∆t + rSt−∆t ∆t + σSt−∆t ∆tzt
donde
I ∆t es el intervalo temporal fijo de discretización
I zt es una variable aleatoria con distribución normal
Simulación de los precios del subyacente en el modelo de Black-Scholes

Utilizando la solución de la ecuación diferencial estocástica:


1 i m p o r t numpy a s np
2 S0=100 #v a l o r i n i c i a l
3 r =0.05 #t i p o de i n t e r é s c o n s t a n t e
4 s i g m a =0.25 #v o l a t i l i d a d
5 T=1. # en a ñ o s
6 I =10000 #número de s i m u l a c i o n e s
7 M=50 #p a s o s de t i e m p o
8 d e l t a t=T/M
9 S=np . z e r o s ( [M+1 , I ] )
10 S [ 0 ] = S0
11 f o r t i n r a n g e ( 1 ,M+1) :
12 S [ t ]=S [ t −1] * np . exp ( ( r−s i g m a * * 2 / 2 ) * d e l t a t +\
13 s i g m a * np . s q r t ( d e l t a t ) * np . random . s t a n d a r d n o r m a l ( I ) )
Representacion de caminos del movimiento Browniano geométrico
simulado
1 import m a t p l o t l i b . pyplot as p l t
2 p l t . p l o t ( S [ : , : 5 ] ) #d i b u j a m o s l o s p r i m e r o s 5 c a m i n o s
3 p l t . x l a b e l ( ’ tiempo ’ )
4 p l t . y l a b e l ( ’S ’ )
Simulación de los precios del subyacente en el modelo de Black-Scholes

Utilizando la ecuación diferencial estocástica:


1 i m p o r t numpy a s np
2 S0=100 #v a l o r i n i c i a l
3 r =0.05 #t i p o de i n t e r é s c o n s t a n t e
4 s i g m a =0.25 #v o l a t i l i d a d
5 T=1. # en a ñ o s
6 I =10000 #número de s i m u l a c i o n e s
7 M=50 #p a s o s de t i e m p o
8 d e l t a t=T/M
9 S=np . z e r o s ( [M+1 , I ] )
10 S [ 0 ] = S0
11 f o r t i n r a n g e ( 1 ,M+1) :
12 S [ t ]=S [ t −1]+ r * S [ t −1] * d e l t a t +\
13 s i g m a * S [ t −1] * np . s q r t ( d e l t a t ) * np . random . s t a n d a r d n o r m a l ( I )
Representacion de caminos del movimiento Browniano geométrico
simulado
1 import m a t p l o t l i b . pyplot as p l t
2 p l t . p l o t ( S [ : , : 5 ] ) #d i b u j a m o s l o s p r i m e r o s 5 c a m i n o s
3 p l t . x l a b e l ( ’ tiempo ’ )
4 p l t . y l a b e l ( ’S ’ )
Valoración de opciones vainilla europeas de compra

Valor de una opción europea de compra en vencimiento (payoff):

h(ST ) = máx(ST − K, 0)

donde
I ST es el precio del subyacente en vencimiento
I T es el vencimiento de la opción
I K es el precio de ejercicio (strike)
Precio de la opción hoy (t = 0) viene dado por la esperanza:

C0 = e−rT EQ
0 (h(ST ))
El método de Monte Carlo

Estimador del precio de una opción europea:


1X
V0 ≈ e−rT hT (i)
I
I

Procedimiento de valoración:
I Generamos I números aleatorios, z(i), i = 1, ..., I, con una distribución normal estándard.
I Calculamos los precios del subyacente en vencimiento ST (i) para cada z(i) dado.
I Calculamos todos los valores de la opción en vencimiento a partir de la función de pago
(payoff).
I Estimamos el valor presente de la opción utilizando el estimador de Monte Carlo.
Valoración de una opción vainilla europea de compra con el método de
Monte Carlo
1 i m p o r t numpy a s np
2 S0 =100. #v a l o r i n i c i a l
3 K=105. #s t r i k e
4 r =0.05 #t i p o de i n t e r é s c o n s t a n t e
5 s i g m a =0.25 #v o l a t i l i d a d
6 T=1. # en a ñ o s
7 I =10000000 #número de t r a y e c t o r i a s
8 N=50
9 d t=T/N
10 S=np . z e r o s ( [ N+1 , I ] )
11 S [ 0 ] = S0
12 f o r t i n r a n g e ( 1 ,N+1) :
13 S [ t ]=S [ t −1] * np . exp ( ( r−s i g m a * * 2 / 2 ) * d t \
14 +s i g m a * np . s q r t ( d t ) * np . random . s t a n d a r d n o r m a l ( I ) )
15 hT=np . maximum ( S[−1]−K, 0 )
16 V0=np . exp (− r *T) * np . sum ( hT ) / I
17 p r i n t ( ’ E l p r e c i o de l a o p c i ó n e s %f ’ %V0 )
Valoración de una opción vainilla europea de compra con el método de
Monte Carlo

1 #C á l c u l o d e l i n t e r v a l o de c o n f i a n z a a l 95 %
2 s t d=np . s q r t ( sum ( ( np . exp (− r *T) * hT−V0 ) * * 2 ) / I )#d e s v i a c i ó n tı́ p i c a
3 s=r ’ %’
4 p r i n t ( ” I n t e r v a l o de c o n f i a n z a a l 95 ”+s+”( %f , % f ) ” %(V0−1.96 * s t d / np . s q r t ( I ) , V0
+1.96 * s t d / np . s q r t ( I ) ) )
5 E l p r e c i o de l a o p c i ó n e s 1 0 . 0 0 2 8 1 7
6 I n t e r v a l o de c o n f i a n z a a l 9 5 % ( 9 . 9 8 3 8 5 3 , 1 0 . 0 5 0 4 9 0 )
Valoración de una opción vainilla europea de compra con la fórmula
analı́tica de Black-Scholes
Solución exacta del modelo de Black-Scholes:

C(t, S) = S N (d1 ) − K exp(−r(T − t)) N (d2 )

donde r es el interés libre de riesgo, σ es la volatitidad del activo, K el precio de ejercicio, T la


fecha de vencimiento. Además,

log(S/K) + (r + σ 2 /2)(T − t)
d1 = √
σ T −t

log(S/K) + (r − σ 2 /2)(T − t)
d2 = √
σ T −t
Rx
N (x) = √1 2 /2) dy
2π −∞ exp(−y es la función de distribución acumulada de una distribución
normal
Valoración de una opción vainilla europea de compra con la fórmula
analı́tica de Black-Scholes

Solución exacta del modelo de Black-Scholes:


1 d e f b s m c a l l ( S0 , K , T , r , s i g m a ) :
2 i m p o r t math
3 from s c i p y i m p o r t s t a t s
4 d1=(math . l o g ( S0 /K) +( r +0.5 * s i g m a * * 2 ) *T) / ( s i g m a * math . s q r t (T) )
5 d2=(math . l o g ( S0 /K) +(r −0.5 * s i g m a * * 2 ) *T) / ( s i g m a * math . s q r t (T) )
6 v a l o r =(S0 * s t a t s . norm . c d f ( d1 , 0 . 0 , 1 . 0 )−K* math . exp (− r *T) * \
7 s t a t s . norm . c d f ( d2 , 0 . 0 , 1 . 0 ) )#n o r m a l e s t á n d a r d
8 #s t a t s . norm . c d f f u n c i ó n de d i s t r i b u c i ó n acumulada de una d i s t r i b u c i ó n
9 #n o r m a l
10 return valor
11 bsm call (100 ,105 ,1 ,0.05 ,0.25)
12 Out [ 4 7 ] : 1 0 . 0 0 2 2 0 2 1 1 7 1 5 4 8 8
Valoración de opciones vainilla europeas de venta

Valor de una opción europea de venta en vencimiento (payoff):

h(ST ) = máx(K − ST , 0)

donde
I ST es el precio del subyacente en vencimiento
I T es el vencimiento de la opción
I K es el precio de ejercicio (strike)
Precio de la opción hoy (t = 0) viene dado por la esperanza:

P0 = e−rT EQ
0 (h(ST ))

Fórmula analı́tica de Black-Scholes: P (t, S) = K exp(−r(T − t))N (−d2) − S N (−d1)


Valoración de opciones

Ejercicio 1: Implementar el método de Monte Carlo en una función que permita valorar
tanto opciones vainilla europeas de compra como de venta.
Ejercicio 2: Implementar la fórmula analı́tica de Black-Scholes en una función que me
permita valorar tanto opciones vainilla europeas de compra como de venta.
Ejercicio 3: Valorar con ambas funciones una opción europea de compra y otra de venta
con vencimiento 3 meses, precio de ejercicio 15.00, precio del activo hoy 17.00, tipo de
interés 3 % y volatilidad del activo 25 %.
Modelo de Black-Scholes para dividendos continuos

El valor del activo S sigue el camino aleatorio:

dSt = (r − D0 )St dt + σSt dZt

Fórmula analı́tica de Black-Scholes:


I Opciones de compra: C(t, S) = S exp(−D0 (T − t))N (d1) − K exp(−r(T − t))N (d2)
I Opciones de venta: P (t, S) = K exp(−r(T − t))N (−d2) − S exp(−D0 (T − t))N (−d1)

log(S/K) + (r − D0 + σ 2 /2)(T − t)
d1 = √
σ T −t
log(S/K) + (r − D0 − σ 2 /2)(T − t)
d2 = √
σ T −t
Modelo de Black-Scholes con dividendos continuos

Ejercicio 4: Implementar en Python dos funciones que permitan calcular el valor de


opciones vainilla europeas de compra y de venta con dividendos continuos. En una se
calculará el precio con el método de Monte Carlo (calcular también el intervalo de
confianza al 95 %) y en la otra con la fórmula de Black-Scholes. Utilizar dichas funciones
para valorar una opción vainilla europea de compra y otra de venta con los siguientes
datos: vencimiento 3 meses, precio de ejercicio 15.00, precio del activo en el instante
inicial 17.00, tipo de interés 3 %, volatilidad del activo 25 % y tasa de dividendos 1.5 %.

También podría gustarte