Calculo de Ajuste por riesgo de crédito (CVA) según basilea III

Aquí mostraremos un ejemplo de calculo de CVA (credit valuation adjustment, ajuste por riesgo de credito ) para un portafolio de derivados financieros que consiste en un solo swap con Formula de de Basilea iii .También es requerido calcularlo por IFRS 13.Usaremos el método Monte-Carlo y Programa en python con modulo de librería QuantLib .

Algoritmo de calculo de CVA (ajuste riesgo de crédito)

1) simular la curva de tipos para las fechas futuras.

2) calcular NPV (fair value) de portafolio de swaps para cada escenario en cada fecha futura.

3) calcular CVA como suma de EE (expected Exposure) multiplicada por probabilidad de default en cada intervalo según la formula:

$$ CVA = (1-R) \int{DF(t) EE(t) dQ_t} $$

R – Recovery
DF(t) – Factor Descuento

1) en este ejemplo usaremos modelo Hull White de 1 factor para simular la evolucion de la curva en futuro.

modelo de Hull-White tiene la siguiente dinámica para tipo de interés instantáneo $$ r_t $$

$$ dr_t=(\theta_t-ar_t)dt+\sigma dW_t $$

$$ r_t $$ esta distribuido como gaussiana con esperanza y variance condicionados:

$$ E(r_t|r_s)=r_se^{-a(t-s)}+\gamma_t-\gamma_se^{-a(t-s)}$$
$$ Var(r_t|r_s)=\frac{\sigma^2}{2a}(1-e^{-2a(t-s)})$$

donde:

$$ \gamma_t=f_t(0)+\frac{\sigma^2}{2a}(1-e^{-at})^2 $$

2) Para cada fecha futura calcularemos la forma de curva de tipos.

para construir la curva para cada valor de $$ r_t $$ usaremos factores descuento de Hull-White

$$ P_{->T}(t)=A(t,T)e^{-B(t,T)r_t} $$

3) para aproximar CVA usaremos la formula de Basilea III

$$ CVA= (1-R) \sum \frac{EE^{*}_{T_{i}}+EE^{*}_{T_{i-1}}}{2} (e^{-\frac{ST_{i-1}}{1-R}}-e^{-\frac{ST_{i}}{1-R}})^+ $$

En este ejemplo suponemos 500bps constant Credit Default Swap CDS spread.

Código Python para calculo de CVA

Como swap de tipos de interés cojemos
nominal SWAP 10MM EUR
Receiver 5% cada 6 meses
pata fija y pata flotante con day counter Actual/360.
Calendario TARGET.

#(c) 2013 PriceDerivatives.com
# Distributed without any warranty

from  QuantLib import *
import numpy as np
from math import *
from pylab import *

def A(t,T):
    forward = crvToday.forwardRate(t, t,Continuous, NoFrequency).rate()
    value = B(t,T)*forward - 0.25*sigma*B(t,T)*sigma*B(t,T)*B(0.0,2.0*t);
    return exp(value)*crvToday.discount(T)/crvToday.discount(t);

def B(t,T):
    return (1.0-exp(-a*(T-t)))/a;

def gamma(t):
        forwardRate =crvToday.forwardRate(t, t, Continuous, NoFrequency).rate()
        temp = sigma*(1.0 - exp(-a*t))/a
        return (forwardRate + 0.5*temp*temp)

def gamma_v(t):
    res=np.zeros(len(t))
    for i in xrange(len(t)):
        res[i]=gamma(t[i])
    return res

Nsim=100
a=0.1
sigma=0.02

todaysDate=Date(30,12,2013);
Settings.instance().evaluationDate=todaysDate;
crvToday=FlatForward(todaysDate,0.02,Actual360())

r0=forwardRate =crvToday.forwardRate(0,0, Continuous, NoFrequency).rate()
months=range(1,12*5,1)
sPeriods=[str(month)+"m" for month in months]
Dates=[todaysDate]+[todaysDate+Period(s) for s in sPeriods]
T=[0]+[Actual360().yearFraction(todaysDate,Dates[i]) for i in xrange(1,len(Dates))]
T=np.array(T)
rmean=r0*np.exp(-a*T)+ gamma_v(T) -gamma(0)*np.exp(-a*T)

np.random.seed(1)
stdnorm = np.random.standard_normal(size=(Nsim,len(T)-1))

rmat=np.zeros(shape=(Nsim,len(T)))
rmat[:,0]=r0

for iSim in xrange(Nsim):
    for iT in xrange(1,len(T)):
        mean=rmat[iSim,iT-1]*exp(-a*(T[iT]-T[iT-1]))+gamma(T[iT])-gamma(T[iT-1])*exp(-a*(T[iT]-T[iT-1]))
        var=0.5*sigma*sigma/a*(1-exp(-2*a*(T[iT]-T[iT-1])))
        rmat[iSim,iT]=mean+stdnorm[iSim,iT-1]*sqrt(var)

startDate=Date(30,12,2013);

crvMat= [ [ 0 for i in xrange(len(T)) ] for iSim in range(Nsim) ]
npvMat= [ [ 0 for i in xrange(len(T)) ] for iSim in range(Nsim) ]

for row in crvMat:
    row[0]=crvToday

for iT in xrange(1,len(T)):
    for iSim in xrange(Nsim):
        crvDate=Dates[iT];
        crvDates=[crvDate]+[crvDate+Period(k,Years) for k in xrange(1,21)]
        crvDiscounts=[1.0]+[A(T[iT],T[iT]+k)*exp(-B(T[iT],T[iT]+k)*rmat[iSim,iT]) for k in xrange(1,21)]
        crvMat[iSim][iT]=DiscountCurve(crvDates,crvDiscounts,Actual360(),TARGET())

#indexes definitions
forecastTermStructure = RelinkableYieldTermStructureHandle()
index = Euribor(Period("6m"),forecastTermStructure)

#swap 1 definition
maturity = Date(30,12,2018);
fixedSchedule = Schedule(startDate, maturity,Period("6m"), TARGET(),ModifiedFollowing,ModifiedFollowing,DateGeneration.Forward, False)
floatingSchedule = Schedule(startDate, maturity,Period("6m"),TARGET() ,ModifiedFollowing,ModifiedFollowing,DateGeneration.Forward, False)
swap1 = VanillaSwap(VanillaSwap.Receiver, 1000000,fixedSchedule,0.05 , Actual360(),floatingSchedule, index, 0,Actual360())  #0.01215

for iT in xrange(len(T)):
    Settings.instance().evaluationDate=Dates[iT]
    allDates= list(floatingSchedule)
    fixingdates=[index.fixingDate(floatingSchedule[iDate]) for iDate in xrange(len(allDates)) if index.fixingDate(floatingSchedule[iDate])<=Dates[iT]]
    if fixingdates:
        for date in fixingdates[:-1]:
            try:index.addFixing(date,0.0)
            except:pass
        try:index.addFixing(fixingdates[-1],rmean[iT])
        except:pass
    discountTermStructure = RelinkableYieldTermStructureHandle()
    swapEngine = DiscountingSwapEngine(discountTermStructure)
    swap1.setPricingEngine(swapEngine)

    for iSim in xrange(Nsim):
        crv=crvMat[iSim][iT]
        discountTermStructure.linkTo(crv)
        forecastTermStructure.linkTo(crv)
        npvMat[iSim][iT]=swap1.NPV()

npvMat=np.array(npvMat)
npvMat[npvMat<0]=0
EE=np.mean(npvMat,axis=0)

S=0.05 #constant CDS spread
R=0.4  #Recovery rate 40%

sum=0
#calculate CVA
for i in xrange(len(T)-1):
    sum=sum+0.5*(EE[i]*crvToday.discount(T[i])+EE[i+1]*crvToday.discount(T[i+1]))*(exp(-S*T[i]/(1.0-R))-exp(-S*T[i+1]/(1.0-R)))
CVA=(1.0-R)*sum

print "\nCVA=",CVA

plot(T,EE)
print "\nEE\n",npvMat
show()

Output

ajuste por riesgo de credito exposure

CVA expected exposure swap

Publicado en quantlib, valoración derivados Etiquetado con: , , ,

calculadora Black Scholes

Calculadora Black Scholes opción Call

Precio opción Call

introducir variables en celdas amarillas:

– vencimiento (en años)
– tipo interés libre de riesgo
– tasa de dividendos (dividendos en un año dividido entre spot)
– Spot (precio de la acción a la fecha de valoración)
– volatilidad

excel :

calculadora Black Scholes avanzada

la calculadora avanzada online coje los la curva de tipos de interés vigentes en mercado y puede calcular opciones americanas

Calculadora opcion equity avanzada

formula Black Scholes

la formula de Black Scholes es

$$Call=df(F_0N(d_+)-KN(d_-))$$

donde $$F_0$$ es el forward de la accion a tiempo 0 para maturity T

$$F_0=S_0e^{(r-q)T}$$

donde r- tipo de interes
q – dividend yield

$$d_+=\frac{ln(F_0/K)}{\sigma\sqrt{T}}+0.5\sigma\sqrt{T}$$
$$d_-=\frac{ln(F_0/K)}{\sigma\sqrt{T}}-0.5\sigma\sqrt{T}$$

Publicado en valoración derivados

derivación formula Black Scholes

formula Black Scholes

$$S_0$$ – precio de la acción a tiempo 0
$$K$$ – Strike de la opción Call
$$r$$ – tipo interés libre de riesgo
$$T$$ – vencimiento
$$\sigma $$ – volatilidad

$$ Call= S_0 N(d_1)-e^{-rT} K N(d_2) $$

$$ d_1=\frac{ln(S_0 e^{rT} /K)}{\sigma \sqrt{T}} + \frac{ \sigma \sqrt{T}}{2} $$

$$ d_1=\frac{ln(S_0 e^{rT} /K)}{\sigma \sqrt{T}} – \frac{ \sigma \sqrt{T}}{2} $$

derivación formula Black Scholes

$$Call = e^{-rT} E (S_T-K)^+ 1_{S_T>K} = e^{-rT} E S_T 1_{S_T>K} – e^{-rT} K E 1_{S_T>K} $$

dinámica Black Scholes:

$$ \frac{dS_t}{S_t}=r dt + \sigma dWt $$

la tendencia es la misma que tipo de interés libre de riesgo porque trabajamos en medida de probabilidad neutral al riesgo (todos los activos tienen la misma tendencia que bank account)

de aquí tenemos:

$$S_T=S_0 e^{ (r-\sigma^2)T+\sigma W_T} $$

así que el segundo termino

$$ E 1_{S_T>K} = P (S_T>K) = P (S_0 e^{ (r-\sigma^2)T+\sigma \sqrt{T} \epsilon}>K)$$

donde $$ \epsilon$$ es la variable estándar gaussiana

reorganizando los términos obtenemos:

$$ P (S_T>K)= P ( -\epsilon < \frac{ln(S_0 e^{rT} /K)}{\sigma \sqrt{T}} - \frac{ \sigma \sqrt{T}}{2}) $$ pero $$ - \epsilon $$ es también variable gaussiana estándar así que esta probabilidad es $$= N(d_2) $$ para calcular el primer termino $$e^{-rT} E S_T 1_{S_T>K}$$ vamos a cambiar la medida de probabilidad con la teorema de Girsanov

si pasamos de la medida de probabilidad neutral al riesgo (donde numeraire es bank account = $$N(t)= e^{rt}$$ a la medida forward , donde numeraire es el precio de la acción $$ N(t)=S_t $$
asi que $$ \frac{1}{e^{rT}} d P_{RN} = \frac{S_0}{S_T} d P_{S} $$

asi que

$$e^{-rT} E S_T 1_{S_T>K} = e^{-rT} \int S_T 1_{S_T>K} d P_{RN} = S_0 \int 1_{S_T>K} d P_{S} = S_0 P (S_T>K)$$

la ultima probabilidad esta en medida de probabilidad con numeraire $$N(t)=S_t$$ asi que la tendencia de $$ d S_t $$ va a ser diferente de $$r$$ (con cambios de medida la volatilidad queda la misma, solo cambia la tendencia)

para calcular nuevo drift de $$S_t$$ cojemos un activo financiero , por ejemplo bank account $$=e^{rt}$$ y su valor dividido por numeraire tiene que ser martingala (tendencia = 0)
asi que suponemos que tendencia de $$S_t$$ es $$\mu$$

asi que bajo la medida de probabilidad $$P_S$$ S_t tiene dinamica:

$$ \frac{dS_t}{S_t}=\mu dt + \sigma dWt $$

la variable $$Y_t=\frac{e^{rt}}{S_t}$$ tiene que tener la tendencia 0 (es activo dividido entre numeraire)

asi que aplicando lema de Ito tenemos

$$\frac{dY_t}{Y_t} = dt ( r + \sigma^2 – \mu) + … $$

de aqui $$\mu=r+\sigma^2$$
asi que en la formula de $$P(S_T>K)$$ solo tenemos que sustituir $$r$$ por $$r+\sigma^2$$ y asi obtenemos el primer termino de formula Black Scholes

calculadora online Black Scholes

calculadora Black-Scholes

Publicado en math

como valorar la pata default de CDS (credit default swap) y probabilidades de default

0—-t1—–t2—-t3—–t4—–….—T

si suponemos que default (en tiempo $$\tau $$) puede ocurrir solo en tiempos discretos t1,t2,t3,..
y Qi=survival proba hasta tiempo ti
entonces:

$$ \tau – tiempo default {=t_1,=t_2,=t_3 …} $$

$$ Q_i=P(\tau>t_i) – survival proba $$

$$ P(\tau=t_3)=1-P(\tau\neq t_3)=1-( P(\tau<3 | \tau>=4) ) $$

$$ = 1 – ( 1-Q_2 + Q_3)= Q_2-Q_3 $$

asi que la pata default de CDS paga:

$$ discounted payoff = (1-R) ( df_1 E{\bf1}(\tau=t_1) + df_2 E{\bf1}(\tau=t_2)+ …) $$
$$=(1-R) ( df_1 P(\tau=t_1)+df_2 P(\tau=t_2)+ …) $$
$$=(1-R) ( df_1(1-Q_1)+df_2(Q_1-Q_2)+df_3(Q_2-Q_3) … ) $$

donde $$df_1$$ es factor descuento para t1 y R – recovery rate (normalmente 40%)

para pasar al tiempo continuo usamos intensity :
$$P(\tau>t+dt | \tau>t) = \lambda(t)dt $$
donde suponemos que defaul es el primer salto del proceso Poisson y
$$ Q(t)=exp( -\int_{0}^{T}\lambda(s)ds) $$
en practica usaremos \(\lambda\) piecewise-constant segun maturities de CDS de mercado

Publicado en math, valoración derivados

como valorar un swap con dos curvas en QuantLib

Ejemplo de contrato de derivado financiero: Swap de tipos de interés:

Si este derivado financiero esta colateralizado con cash EUR tendriamos aplicar curva descuento EONIA. (market practice IFRS)

Swap de tipos de interés

maturity: 20 nov 2022
nominal: 1M
fecha inicio: 20 nov 2012
pata variable paga: Euribor 3meses + 2% cada 3 meses
pata fija paga:4% anualmente

calendario: TARGET
calculo días pata fija: 30/360
calculo días pata variable: Actual/360

Datos de mercado :

ultima fijación de tipo Euribor 3m : 1%

para descontar flujos del swap usaremos la curva EONIA (podemos obtener desde reuters o bloomberg):

(datos de mercado ficticios)

31 Dec 2013 0.99
31 Dec 2024 0.80

para calcular forwards curva de tipos de proyección Euribor 3m:

31 dec 2013 0.999
31 dec 2024 0.89

ejemplo de código QuantLib swap en C++ para valoración del swap a 31/dec/2012

 
#include 

using namespace std;
using namespace QuantLib;
using namespace boost;

int main()
{
vector dates; 
vector discountFactor; 

Date valuationDate(31,December,2012);
Settings::instance().evaluationDate()=valuationDate;

dates.push_back(valuationDate); discountFactor.push_back(1.0); 
dates.push_back(Date(31,December, 2013));  discountFactor.push_back(0.99); 
dates.push_back(Date(31,December, 2024));  discountFactor.push_back(0.80); 
shared_ptr forwardCurve(new InterpolatedDiscountCurve(dates,discountFactor,Actual360())); 

discountFactor.pop_back();discountFactor.pop_back();

discountFactor.push_back(0.999);
discountFactor.push_back(0.89);

shared_ptr oisCurve(new InterpolatedDiscountCurve(dates,discountFactor,Actual360())); 

Handle discountingTermStructure(oisCurve);
Handle forwardingTermStructure(forwardCurve);

Real nominal = 1000000.0;
Date previousResetDate(20,November,2012);
Date maturity(20,November,2022);
double spread = 0.02;
double fixedRate=0.04;

shared_ptr euribor(new Euribor(3*Months,forwardingTermStructure));
euribor->addFixing(euribor->fixingDate(previousResetDate),0.01,true);
		
VanillaSwap::Type swapType = VanillaSwap::Payer;

Schedule fixedSchedule(previousResetDate, maturity,1*Years,
                               TARGET(), ModifiedFollowing,ModifiedFollowing,
                               DateGeneration::Forward, false);

Schedule floatSchedule(previousResetDate,maturity,3*Months,
                               TARGET(),ModifiedFollowing ,ModifiedFollowing,
                               DateGeneration::Forward, false);
        
VanillaSwap swap(VanillaSwap::Payer, nominal,fixedSchedule, fixedRate, Thirty360(),
            floatSchedule, euribor, spread,Actual360());
     
shared_ptr swapEngine(new DiscountingSwapEngine(discountingTermStructure));

swap.setPricingEngine(swapEngine);
       
double res=swap.NPV();

}
Publicado en quantlib

curso c++ finanzas [parte 5] – opciones cesta con monte carlo c++

Parte 5

curso c++ finanzas

Monte-Carlo c++ – opciones cesta

Objectivos

-implementar valoración opciones cesta (basket, himalaya, rainbow , spread options, autocallables)

Opcion Cesta

vamos a ver como calcular con c++ opciones cesta con 2 subyacentes con payoff:

$$ ( w_1S_1+w_2S_2-K)^+ $$
donde $$ w_i $$ son pesos de cada acción en el payoff (lo normal es pesos iguales que suman 1)
como siempre consideramos tipos de interés 0 y las acciones no pagan dividendos (sino hay que añadir termino $$ (r-q)dt$$ en la dinámica

$$dS_1=S_1 \sigma_1 dW_1(t)$$
$$dS_2=S_2 \sigma_2 dW_2(t)$$

$$ dW_i dW_j=\rho_{i,j} dt$$

donde $$\rho_{i,j}$$ es la matriz de correlaciones.
una vez tenemos la matriz de correlaciones construimos su descomposición Cholesky.
la podemos hacer con boost o con Quantlib , con quantlib es mas facil.ya que usamos quantlib usaremos sus clases para matrices y vectores.
QuantLib::Matrix para matrices y QuantLib::Array para Así podemos escribir A=B*x para multiplicar matriz por vector.

para obtener las gaussianas con matriz correlación dada generaremos primero las gaussianas independientes $$\vec{\epsilon}= (\epsilon_1, \epsilon_2)$$ .
Asi que el vector de gaussianas correladas sera $$M_{cholesky} \vec{\epsilon}$$

aqui viene el codigo (con pesos=1)

#include 
#include 
#include 
#include 
#include 


double pp(double x) //positive part   x+   
{
if(x>0) return x;
return 0;
}

void main()
{

	boost::mt19937 mt; 
    boost::normal_distribution<> distribution;
    boost::variate_generator>* normal(new boost::variate_generator>(mt,distribution));
	
	int numberSimulations=10000;

	std::vector S0(2);
	S0[0]=100.0;// S1(0) - spot price of first stock
	S0[1]=100.0;//S2(0) - spot price of second stock

	std::vector sigma(2);
	sigma[0]=0.2; //volatility of S1
	sigma[1]=0.2;//volatility of S2

	double T=1.0;//maturity in years
	double K=100.0;//strike of option
	double sum=0;//for monte-carlo averaging
	double payoff=0;
	double NT=100;//number of time intervals
	double dt=T/NT;
	
	QuantLib::Matrix rho(2,2);//correlation matrix

	rho[0][0]=1;rho[0][1]=0.5;
	rho[1][0]=0.5;rho[1][1]=1;

	QuantLib::Matrix cholesky=QuantLib::CholeskyDecomposition(rho);
	
	for(int iSim=0;iSim Sprev(S0); //create a vector equal to S0 with its values
		std::vector Snext(2);//create vector with 2 elemens

		for(double t=0;t
		Publicado en curso c++ finanzas			

curso c++ finanzas [parte 4] – Monte Carlo c++ opcion asiatica y lookback

Parte 4

curso c++ finanzas

Monte-Carlo c++ – payoffs asiática y lookback

Objetivos

– implementar opcion asiática con c++
– implementar opcion lookback

Aquí mostraremos como extender el programa precedente a las opciones que dependen del camino

Opción Asiática

empezaremos con la opción asiática:
payoff:

$$ payoff=(\frac{1}{T}\int_0^T S_t dt – K)^+ $$

1) en vez de calcular la integral continua calcularemos la media aritmética del precio de la acción S
2) para calcular la media dividimos el intervalo de tiempo [0..T] en N partes , cada una dt

0–dt–2td–3dt–…. T

tendremos que simular cada camino de la acción paso a paso
para pasar del paso precedente al paso siguiente de la acción usaremos dinámica Black Scholes con tipos de interés 0 (para simplificar las formulas)

$$S_0=100$$
$$S_{dt}=S_0 exp( -0.5 \sigma^2 dt + \sigma \sqrt{dt} x )$$
$$S_{next}=S_{prev} exp( -0.5 \sigma^2 dt + \sigma \sqrt{dt} x )$$

monte carlo c++

monte carlo c++

Aqui esta el código para la opción asiática

#include 
#include 
#include 
#include 


double pp(double x) //positive part   x+   
{
if(x>0) return x;
return 0;
}

void main()
{

	boost::mt19937 mt; 
    boost::normal_distribution<> distribution;
    boost::variate_generator>* normal(new boost::variate_generator>(mt,distribution));
	
	int numberSimulations=1000;

	double S0=100.0;
	double sigma=0.2;
	double T=1.0;
	double K=100.0;
	double sum=0;
	double payoff=0;
	double NT=100;
	double dt=T/NT;
	
	for(int iSim=0;iSim
#include 
#include 
#include 
#include 


double pp(double x) //positive part   x+   
{
if(x>0) return x;
return 0;
}

void main()
{

	boost::mt19937 mt; 
    boost::normal_distribution<> distribution;
    boost::variate_generator>* normal(new boost::variate_generator>(mt,distribution));
	
	int numberSimulations=1000;

	double S0=100.0;
	double sigma=0.2;
	double T=1.0;
	double K=100.0;
	double sum=0;
	double payoff=0;
	double NT=100;
	double dt=T/NT;
	
	for(int iSim=0;iSim
		Publicado en curso c++ finanzas			

curso c++ finanzas [parte 3] – Monte Carlo c++

Parte 3

curso c++ finanzas

Monte-Carlo c++

Objetivos

– generar números aleatorios
– Calcular una opción Call con Monte – Carlo
– intro a std::vector

Aquí vamos a ver cómo utilizar contenedores std::vector en C++

en muchos libros de c++ usan c++ arrays (por ejemplo, double x[10]) para almacenar variables.Esto tiene bastantes inconvenientes para los principiantes, así que aquí vamos a utilizar std::vector para almacenar números reales.
std::vector es un objeto – esto significa que se puede añadir un punto «.» después del nombre del objeto y se podra ver que tiene no sólo un valor, sino muchas diferentes «sub-variables» y «sub-funciones»

generación de números aleatorios gaussianas

Para implementar el motor de Monte-Carlo en C++ necesitaremos números gaussianos estándar.
C++ tiene una función de generar los números aleatorios, pero no son buenos para la ingeniería financiera (funcion random() ).

Uno de los más utilizados generadores de numeros seudo-aleatorios con buenas características es algoritmo Mersenne Twister
Ya esta implementado en Boost. Después de que tengamos números aleatorios uniformes podemos generar las variables gaussianas con una function. Esta también esta implementada en Boost.
aquí está el código para generar 100 gaussianas estándar:

#include 
#include 
#include 
#include 



void main()
{

    boost::mt19937 mt; //create object of mersenne twister generator
    boost::normal_distribution<> distribution; // create distribution object
    boost::variate_generator>* normal(new boost::variate_generator>(mt,distribution)); //create variate generator which will generate gaussians
	
	for (int i=0;i<100;i++)
           std::cout<< (*normal)()<>dummy;
}

aquí hemos usado puntero a variable.
puntero es básicamente la dirección de la variable en la memoria.
para acceder a las variables por punteros se utiliza asterisco *
leer más sobre punteros aquí

Almacenamiento de datos en std::vector

para almacenar estos números podemos utilizar la clase std::vector
leer más sobre esta clase
Aqui

aquí vamos a ilustrar su uso común:


#include 
#include 
#include 
#include 
#include 


void main()
{

    boost::mt19937 mt; 
    boost::normal_distribution<> distribution;
    boost::variate_generator>* normal    (new boost::variate_generator>(mt,distribution));
	
    std::vector v;

    for (int i=0;i<100;i++)
	v.push_back( (*normal)() ) ;
	
     for (int i=0;i<100;i++)
	std::cout<>dummy;
}

ahora vamos a hacer una funcion para calcular la media de los elementos de este vector:

#include 
#include 
#include 
#include 
#include 


double mean(std::vector& v) //here we use &  to indicate that we pass value of variable to function by address and not by creating new variable and copying data into it
{
	int N=v.size();
	double sum=0;
	for(int i=0;i distribution;
    boost::variate_generator>* normal(new boost::variate_generator>(mt,distribution));
	
	std::vector v;

	for (int i=0;i<100;i++)
		v.push_back( (*normal)() ) ;
	
	for (int i=0;i<100;i++)
		std::cout<
std::vector v;//crear vector vacio
std::vector v(10);//create vector de 10 elementos  primer elemento es v[0]
v[0]=4;//asignar valor al primer elemento del vector
v.resize(100);//resize vector to have 100 elements;
v.size();//retorna numero de elementos en el vector

si se quiere hacer operaciones simples de vectores hay posibilidades de que estas operaciones ya están implementadas en STL o en Boost.
por ejemplo, nuestro programa anterior para calcular la media de conjunto podría reescribirse utilizando algoritmos de STL de la siguiente manera:

sum =std::accumulate(v.begin(),v.end(),0.0); //need to #include 

so before writing a function to do simple things on vector google first somthing among the lines «std::vector sum of elements»

Ejercicio

– cambiar el programa precedente para calcular la varianza de los números aleatorios

Ya que tenemos numeros gaussianos ya estamos listos para implementar pricing de la opcion call con Monte Carlo

opción Call con monte carlo c++

suponemos la dinamica de Black-Scholes con tipos de interes cero
asi que:

$$S_T=S_0 exp(-0.5 \sigma^2 T + \sigma \sqrt{T} x )$$
donde x es la gaussiana estándar

Precio monte carlo de call es la media de los payoffs obtenidos
$$ (S_T(x)-K)^+$$

#include 
#include 
#include 
#include 


double pp(double x) //positive part   x+   
{
if(x>0) return x;
return 0;
}

void main()
{

	boost::mt19937 mt; 
	boost::normal_distribution<> distribution;
	boost::variate_generator>* normal(new boost::variate_generator>(mt,distribution));
	
	int numberSimulations=100000;

	double S0=100.0;
	double sigma=0.2;
	double T=1.0;
	double K=100.0;
	double sum=0;
	double payoff=0;

	for(int iSim=0;iSim
		Publicado en curso c++ finanzas			

curso c++ finanzas [parte 2] – opcion Call via integracion

C++ finanzas curso – parte 2 – Black-Scholes a través de la integración numérica

objetivo

cálculo de opción de compra (Call) de Black-Scholes con c++

C++ y QuantLib tienen muchos tipos de variables. En las finanzas cuantitativas los tipos más útiles son:

double – para almacenar números reales
int – para almacenar números enteros
QuantLib :: Date – para almacenar fechas
QuantLib :: Array – guardar array de doubles
QuantLib :: Matrix – para almacenar la matriz 2D de doubles

vamos a empezar haciendo con integración numérica

borrar todos los contenidos del fichero source.cpp copiar y pegar el código siguiente

ejemplo – la integración numérica Call

este código calculará integral
$$ \int_ {0} ^ {1} e^x dx $$

#include  
#include  //for using math functions

//everything after // is a comment

double f(double x) //declaration of function f(x)=exp(x)
{
return std::exp(x);
}

void main() 
{
	
	double dt=0.0001; //integration step
	double sum=0; //current value of integral
	for(double t=0;t<1.0;t+=dt) //for loop    t+=dt means t=t+dt
	{
	sum+=f(t)*dt; // its equivalent to write sum=sum+f(t)*dt;
	}
std::cout<<"integral "<< sum; //output

int dummy;std::cin>>dummy;//screen delay
}

leer acerca de las estructuras de control de bucle y otra aquí: http://www.cplusplus.com/doc/tutorial/control/

Notas importantes:
utilizar 1.0 en vez de 1
en c + + 1.0 y 1 son diferentes números 1.0 es el número real y 1 es el número entero
que significa que 1/2 = 0. mientras que 1.0/2 es 0.5

al hacer comparaciones de dobles no lo uses si (x == 0)
utilizar si (std :: abs (x) <epsilon) donde épsilon es su precisión (por ejemplo 10 ^ -8)

la variable t es «visible» sólo dentro loop
Consulte «Variables scope» aquí http://www.cplusplus.com/doc/tutorial/variables/

Aquí hemos utilizado la forma más simple de integración numérica
para un integratoin rápido / más precisa puede utilizar otros métodos
muchos de ellos se describen en el libro gratis «recetas numéricas en c»
este libro es para C, pero la estructura del código sería el mismo

ejemplo

– opción Call en Black Scholes usando integración

Ahora vamos a cambiar el programa anterior para calcular opción Call en modelo Black-Scholes con tasas de interés cero

dinámica neutral al riesgo:
$$ dS_t = S_t \sigma dWt $$
así
$$ S_T S_0 = exp (-0.5 \sigma^2 + \sigma \sqrt x T) $$
donde x es un estándar gaussiano
por lo que el precio de la opción llamada será
$$ Call = \int_{-\infty}^{+\infty} (S_0 e ^ {-0,5 \sigma ^ 2 + \sigma \sqrt T x} – K) ^ + \phi (x) dx $$
donde $$ \phi(x) = \frac {1} {\sqrt {2 \pi}} exp (-0.5 x ^ 2) $$ densidad gaussiana estándar
S0 = 100
volatilidad = 20%
vencimiento = T = 1 año

#include 
#include 
#include 

double density(double x) //normal density 
{
	const double pi = boost::math::constants::pi();
	return 1.0/sqrt(2.0*pi)*std::exp(-0.5*x*x);
}

double pp(double x) //positive part   x+   
{
if(x>0) return x;
return 0;
}

double f(double K,double S0,double T,double sigma,double x) //function to integrate  
{
return pp(S0*std::exp(-0.5*sigma*sigma*T+sigma*std::sqrt(T)*x)-K)*density(x);  
}

void main()
{
	double S0=100.0;
	double sigma=0.2;
	double T=1.0;
	double K=80.0;
	double dx=0.0001;
	double sum=0;

	for(double x=-10.0;x<10.0;x+=dx)
	{
	sum+=f(K,S0,T,sigma,x)*dx;
	}
std::cout<<"call= "<< sum;

int dummy;std::cin>>dummy;
}

Notas:

tenemos que pasar argumentos de nuevo a la función integrada debido a que su alcance original está dentro main () , por lo que las variables K, S0 etc no son visibles en el interior función f (x)
usamos impulsar aquí para extraer constante Pi, por lo que será más fácil de portar a programas linux por ejemplo (estándar de C++ no tiene constantes matemáticas)

ejercicios

– Debugear primer programa mediante el establecimiento de puntos de interrupción y ver las variables de suma y t valor del cambio
– Cambiar el primer programa para integrar a través de regla trapezoidal , compruebe los resultados con respuesta conocida $$ e^1-1 $$
– Cambie segundo programa para incluir los tipos de interés no cero
– Cambie segundo programa para calcular el precio puesto
– Verificar llama poner la paridad

algunos trucos

si tienes un error siempre comienza corrigiendo primer error de compilación (doble clic en la línea de error de compilación)
algunos mensajes de error de + c + son bastante crípticos y son el resultado de errores anteriores

por ejemplo, eliminar el «;» después sentencia return
pulse F7 para compilar
Ahora haga doble clic en el primer error:

black scholes c++

black scholes c++

Publicado en curso c++ finanzas

curso c++ finanzas [parte 1] – instalacion quantlib y visual studio

curso c++ finanzas para principiantes – Parte 1 – hola mundo

REQUISITOS del curso c++ finanzas
:
– Experiencia en programación en otro lenguaje
– conocimientos en finanzas cuantitativas básicas

Los objetivos del curso :

– valorar diferentes derivados financieros utilizando código en C++
– Usar funciones basicas de QuantLib y Boost utiles en la ingeniería financiera

instalación C++, Boost y QuantLib

1) instalar Visual Studio 2012 Express:

http://www.microsoft.com/visualstudio/eng/downloads # d-express-windows-desktop

debugging c++ program

debugging c++ program

2) instalar Boost

Hello world finance c++

Hello world finance c++

– Descargar la última versión de Boost de http://www.boost.org

c++ boost download

c++ boost download

– Descomprimirlo en la unidad C:
[asi que la libreria estara en c:\boost_1_53_0]

– Ir al directorio c:\boost_1_53_0 y ejecutar bootstrap.bat
– Ejecutar b2.exe
puede tardar mucho tiempo en ejecutarlo – es normal.

build boost library

build boost library

– Ir al directorio c:\boost_1_53_0\stage
mover directorio «lib» en c:\boost_1_53_0\ para que todas las bibliotecas construidas se encuentren dentro de c:\boost_1_53_0\lib

3) instalar QuantLib

descargar QuantLib
http://sourceforge.net/projects/quantlib/files/

quantlib download

quantlib download

descomprimir a C:\

– Abrir Visual Studio Express for Desktop

File-> abrir proyecto QuantLib_vc10.sln (esta en directorio QuantLib)

quantlib solution

quantlib solution

Seleccione la opción «update» en el siguiente diálogo. Esto convertira los archivos a formato de Visual Studio 2012

en el Explorador de soluciones seleccione QuantLib
pulse Shift-F4 (o Menu-> View-> properties)

añadir a la variable «include directories» la ruta de boost
añadir a la variable «library directories» la ruta de boost\lib

set boost directories

set boost directories

ahora eliminar todos los proyectos, excepto QuantLib de la solución (haga clic en cada proyecto en el Explorador de soluciones y pulse «del»)

pulse F7 para compilar QuantLib [o Menu->build solution]

Programa Hello world

Menu>New Project

elija Visual C++ -> Win32 Console Application

new win32 console app

new win32 console app

presione OK->NEXT (NO presionar FINISH aún)

marque «Empty Project»
desmarque la opción «Security …»

new empty project

new empty project

haga clic en Finalizar

Haga clic derecho sobre ConsoleApplication1 y incluir directorios QuantLib y Boost:

hello world c++ finance

hello world c++ finance

haga clic derecho en «Sources» -> Add -> Add new Item

add new c++ file

add new c++ file

en la ventana que aparece pegar el siguiente código:

#include 
#include 

using namespace QuantLib;

void main()
{
	
	Date date1(30,January,2013);
	Date date2;
	date2=date1+1*Years;

std::cout<>dummy;
}
hello world quantlib

hello world quantlib

pulse F7 para compilar

haga doble clic en el error:

quantlib compile error visual studio 2012

quantlib compile error visual studio 2012

y cambiar la siguiente línea:

#  error "unknown Microsoft compiler"

por

#  define QL_LIB_TOOLSET "vc100"

para que se vea así:

quantlib compile error

quantlib compile error

pulse F7 para construir proyectos y F5 para ejecutar

hello world quantlib

hello world quantlib

rápida explicación del código:

#include <ql/quantlib.hpp>
#include

estas líneas simplemente insertar archivos denominados quantlib.hpp y iostream en el archivo de origen
se necesita quantlib.hpp tener funciones QuantLib y definiciones (Fecha objeto)
y iostream se utiliza para escribir en la consola de salida

using namespace QuantLib;

sin que esta línea que te tenías que escribir «QuantLib ::» antes de cada objeto QuantLib

void main()
{

	Date date1(30,January,2013);
	Date date2;
	date2=date1+1*Years;

std::cout<>dummy;
}

estas líneas definen la función principal
en c + +, cuando se inicia programa de consola que se inicia la ejecución de la función main ()

	Date date1(30,January,2013);
	Date date2;

Aquí se definen dos objetos QuantLib (variables) date1 y date2 y asignamos un valor de la primera variable

date2=date1+1*Years;
std::cout<

aquí se le asigna el valor de date2 se que es 1 año a partir de date1

y std :: cout parte imprime el resultado a la consola

int dummy;std::cin>>dummy;

esto es necesario para poner en pausa la pantalla

depuración del programa

para depurar haga clic en el area donde aparece el punto rojo y presione F5

debugging c++ program

debugging c++ program

se iniciará la depuración y puede flotar cursor sobre la variable para ver su valor.

como se puede ver date1 es un número en vez de fecha . Es porque QuantLib internamente utiliza el formato de Excel para las fechas.

pulse F10 para ejecutar las instrucciones de una en una y F5 de nuevo para continuar con el programa hasta el siguiente breakpoint

Publicado en curso c++ finanzas