Beispiel #1
0
/**
 * Euler acceleration to recover a CDF using the Laplace transform of its density
 *
 * @param f the Laplace transform with complex values of a real valued
 * density function
 * @param t the point at which the orignal is to be evaluated
 * @param h step size used to discretize the integral
 * @param N series truncation
 * @param M Euler averaging length.
 */
double pnl_ilap_cdf_euler(PnlCmplxFunc *f, double t, double h, int N, int M)
{
  int    i, Cnp;
  double sum, run_sum;

  sum = 0.;

  for(i=1;i<N+1;i++)
    {
      sum += sin(i*h*t) * Creal (PNL_EVAL_FUNC(f, Complex (0., h * i))) / (double)i;
    }
  run_sum = sum; /* partial sum of sn */
  sum = 0.0; /* partial exponential sum */
  Cnp = 1; /* binomial coefficients */

  for(i=0;i<M+1;i++)
    {
      sum += run_sum * (double) Cnp ;
      run_sum += sin ((i + N + 1) * h * t) *
        Creal (PNL_EVAL_FUNC(f, Complex (0., h * (i + N + 1)))) / (double) (i + N + 1);
      Cnp = (Cnp * (M - i)) / (i + 1);
    }

  return(2.0 / M_PI * sum / pow(2.0,M) + h * t / M_PI);
}
Beispiel #2
0
/**
 * Euler acceleration to invert a Laplace transform
 *
 * @param f the Laplace transform with complex values of a real valued
 * function
 * @param t the point at which the orignal is to be evaluated
 * @param N series truncation
 * @param M Euler averaging length.
 */
double pnl_ilap_euler(PnlCmplxFunc *f, double t, int N, int M)
{
  int i, Cnp;
  double  sum, a, pit, run_sum;
  double A;

  A = 13.; /* MIN (13., 13. / t); */

  a = A/(2.0*t);
  pit = M_PI/t;
  sum = 0.5 * Creal (PNL_EVAL_FUNC(f, Complex (a, 0.)));

  for(i=1;i<N+1;i++)
    sum += ALTERNATE(i) * Creal (PNL_EVAL_FUNC(f, Complex (a, pit * i)));

  run_sum = sum; /* partial sum of sn */
  sum = 0.0; /* partial exponential sum */
  Cnp = 1; /* binomial coefficients */

  for(i=0;i<M+1;i++)
    {
      sum +=  run_sum * (double) Cnp ;
      run_sum += ALTERNATE(i+N+1) * Creal (PNL_EVAL_FUNC(f, Complex (a, pit * (i + N + 1))));
      Cnp = (Cnp * (M - i)) / (i + 1);
    }
  return exp (A / 2. - M * M_LN2) * sum / t ;
}
/*We use the Cauchy Gourat theorem to compute the derivatives of the double(Mellin+Laplace) transform */
static dcomplex dermellin(dcomplex l, double sg, double r, int nummom)
{
  dcomplex term, cv, mu;
  int i;
  double r0,sumr, sumi/*,x[NPOINTS_FUSAITAGL+1],w[NPOINTS_FUSAITAGL+1]*/;
  double v;
  double *x,*w;

  x=malloc((NPOINTS_FUSAITAGL+1)*sizeof(double));
  w=malloc((NPOINTS_FUSAITAGL+1)*sizeof(double));

  sumr=0.0;
  sumi=0.0;
  
  gauleg(0, 2*M_PI, x, w,NPOINTS_FUSAITAGL);
	
  v   = 2*r/(sg*sg)-1.0;
  cv = Complex(v,0.0);
  mu = Csqrt(Cadd(Complex(v*v,0), RCmul(2.0,l)));
  r0 = Creal(RCmul(0.5,Csub(mu,cv)));	
  if(r0>1.0) r0=0.25;


  for (i=1;i<=NPOINTS_FUSAITAGL;i++) 
    {
    term = 	RCmul(pow(r0,nummom), Cexp(Complex(0.0, nummom*x[i])));
    sumr += w[i]*Creal(Cdiv(mellintransform(l, RCmul(r0, Cexp(Complex(0.0, x[i]))),  sg, r), term));
    sumi += w[i]*Cimag(Cdiv(mellintransform(l, RCmul(r0, Cexp(Complex(0.0, x[i]))),  sg, r), term));
    }

  free(x);
  free(w);
  
  return Complex(exp(factln(nummom))*sumr/(2.0*M_PI),exp(factln(nummom))*sumi/(2.0*M_PI));
}
Beispiel #4
0
/**
 * FFT algorithm to invert a Laplace transform
 * @param res a real vector containing the result of the inversion. We know that
 * the imaginary part of the inversion vanishes.
 * @param f : the Laplace transform to be inverted
 * @param T : the time horizon up to which the function is to be recovered
 * @param eps : precision required on [0, T]
 */
void pnl_ilap_fft(PnlVect *res, PnlCmplxFunc *f, double T, double eps)
{
  PnlVectComplex *fft;
  int             i, N, size;
  double          h, time_step, a;
  double          f_a, omega;
  dcomplex        mul, fac;

  h = M_PI / (2 * T); 
  a = h * log (1 + 1. / eps) / (M_2PI); 

  N = MAX (sqrt (exp (a * T) / eps), h / (M_2PI * eps)) ;
  N = pow (2., ceil (log (N) / M_LN2) );
  time_step = M_2PI / (N * h);
  
  fft = pnl_vect_complex_create (N);
  size = floor (T / time_step) + 1;
  pnl_vect_resize (res, size);
  
  fac = CIexp (-M_2PI / N);
  mul = fac;
  f_a = Creal (PNL_EVAL_FUNC (f, Complex (a, 0)));
  omega = h;
  
  for (i=0 ; i<N ; i++)
    {
      pnl_vect_complex_set (fft, i, Cmul(mul,PNL_EVAL_FUNC (f, Complex (a, - omega))));
      omega += h;
      mul = Cmul(mul,fac);
    }
  pnl_fft_inplace (fft);
  mul = CONE;

  for (i=0 ; i<size ; i++)
    {
      double res_i;
      res_i = Creal (Cmul (pnl_vect_complex_get (fft, i), mul));
      mul = Cmul (mul, fac);
      res_i = (h / M_PI) * exp (a * (i + 1) * time_step) * (res_i + .5 * f_a);
      PNL_LET (res, i) = res_i;
    }
  pnl_vect_complex_free (&fft);
}
Beispiel #5
0
double Var_Swap_price(double T,
                      Levy_diffusion * Model,
                      dcomplex (*psi)(dcomplex u,double t,Levy_diffusion * model))
{
  // phi is hermitian :
  // phi(epsilon,0)-phi(-epsilon,0)= 2 Im(phi)(epsilon)
  // phi'(0) == Im(phi)(epsilon)/epsilon
  // phi(epsilon,0)+phi(-epsilon,0)= 2 Re(phi)(epsilon)
  // phi''(0,0)== 2 Re(phi)(epsilon)/epsilon^2
  dcomplex Phi =  (psi(Complex(EPSILON_DIFF,0.),T,Model));
  return 100.0*sqrt(-2.0*Creal(Phi)/(EPSILON_DIFF*EPSILON_DIFF*T));
}
Beispiel #6
0
static int pcons (void) {
    int ci;
    double d;

    ci = 0;
    switch (Ltok) {
    case L_NUMBER:
        d = atof (Lstrtok);
        ci = (d == (double) (long) d) ? Cinteger ((long) d) : Creal (d);
        break;
    case L_STRING:
        ci = Cstring (Lstrtok);
        break;
    default:
        err ("expected scalar constant, found: %s", Lnames[Ltok]);
    }
    Lgtok ();
    return ci;
}
Beispiel #7
0
void newmomentsAM(int model, double rf, double dt, int maxmoment, 
				  int ndates, double parameters[], double **momtable)
{
int i,ii,k;
double sum;

	for(i = 1; i < maxmoment + 1; i++)
      {momtable[1][i] = Creal(cfrn(model,rf, dt, Complex(0,-i), parameters)); }
   
    for(ii = 2;ii < ndates + 1; ii++)
		{for(i = 1; i < maxmoment + 1; i++)
		{
			sum=0;
			for(k=1;k<=i;k++)
			{sum=sum+momtable[ii - 1][ k]*bico(i, i-k); 
			}

		momtable[ii][ i] = momtable[1][ i]*(1 + sum);
		}
	}
}
Beispiel #8
0
/**
 * Complex Modified Bessel function of the first kind
 * divided by exp(|Creal(z)|)
 *
 * @param z a complex number
 * @param v a real number, the order of the Bessel function
 *
 */
dcomplex pnl_complex_bessel_i_scaled( double v, dcomplex z ) 
{
  int nz, ierr;
  dcomplex cy;
  int n = 1;
  int kode = 2;
  if (v >= 0)
    {
      pnl_zbesi(CADDR(z), &v,  &kode, &n, CADDR(cy), &nz, &ierr);
      DO_MTHERR("ive:");
    }
  else
    {
      dcomplex aux1, aux2;
      aux1 = pnl_complex_bessel_i_scaled (-v, z);
      aux2 = pnl_complex_bessel_k (-v, z);
      aux2 = CRmul (aux2, M_2_PI * sin(M_PI * -v) * exp ( -fabs ( Creal(z) ) ));
      cy = Cadd (aux1, aux2);
    }
  return cy;
}
Beispiel #9
0
double Var_Swap_price_Levy(Levy_process * Model,
                           dcomplex (*psi)(dcomplex u,Levy_process * model))
{
  /*
    dcomplex Phip =  (psi(Complex(EPSILON_DIFF,0.),Model));
  dcomplex Phi0 = (psi(Complex(0.,0.),Model));
  dcomplex Phim  = (psi(Complex(-EPSILON_DIFF,0.),Model));
  dcomplex dPhi=Csub(Phip,Phim);
  Phi0=Csub(Cadd(Phip,Phim),RCmul(2.,Phi0));
  return 100.0*sqrt((Creal(Phi0)+0.25*Creal(dPhi)*Creal(dPhi))/(EPSILON_DIFF*EPSILON_DIFF));
  */
  // psi is hermitian :
  // psi(epsilon,0)-psi(-epsilon,0)= 2 Im(psi)(epsilon)
  // psi'(0) == Im(psi)(epsilon)/epsilon
  // psi(epsilon,0)+psi(-epsilon,0)= 2 Re(psi)(epsilon)
  // psi''(0,0)== 2 Re(psi)(epsilon)/epsilon^2
  dcomplex Phi =  (psi(Complex(EPSILON_DIFF,0.),Model));
  return 100.0*sqrt(2.0*Creal(Phi)/(EPSILON_DIFF*EPSILON_DIFF));
  

}
//swaption_payer_receiver=0 : Payer
//swaption_payer_receiver=1 : Receiver
static double cf_swaption_direct(StructLiborAffine *LiborAffine, double swaption_start, double swaption_end, double swaption_period, double swaption_strike, double swaption_nominal, int swaption_payer_receiver)
{
    double x0, lambda, theta, eta, Sqr_eta, Y;
    double P=0., Q=0., x, deg_freedom, n_centrality_param, bound, price, trm_k;
    double Tk, a_Ti, b_Ti, dzeta_k, sigma_k, sum=0.;
    int i, m, k, which=1, status;
    double psi_d;
    dcomplex uk, phi, psi;

    x0     = GET(LiborAffine->ModelParams, 0);
    lambda = GET(LiborAffine->ModelParams, 1);
    theta  = GET(LiborAffine->ModelParams, 2);
    eta    = GET(LiborAffine->ModelParams, 3);
    Sqr_eta = SQR(eta);

    // Static variables
    Ti = swaption_start;
    Tm = swaption_end;
    TN = LET(LiborAffine->TimeDates, (LiborAffine->TimeDates)->size-1);

    i = indiceTimeLiborAffine(LiborAffine, Ti);
    m = indiceTimeLiborAffine(LiborAffine, Tm);

    c_k = pnl_vect_create_from_double(m-i+1, swaption_period*swaption_strike);
    Phi_i_k = pnl_vect_create(m-i+1);
    Psi_i_k = pnl_vect_create(m-i+1);

    LET(c_k, 0) = -1.0;
    LET(c_k, m-i) += 1.;

    for (k=i; k<=m; k++)
    {
        uk = Complex(GET(LiborAffine->MartingaleParams, k), 0.);
        phi_psi_t_v(TN-Ti, uk, LiborAffine, &phi, &psi);

        LET(Phi_i_k, k-i) = Creal(phi);
        LET(Psi_i_k, k-i) = Creal(psi);
    }
    // Zero of the function f
    if (m==i+1) Y = find_Y_caplet(LiborAffine);
    else Y = find_Y_swaption(LiborAffine);

    a_Ti = exp(-lambda*Ti);
    if (lambda == 0.) b_Ti = Ti;
    else b_Ti = (1.-a_Ti)/lambda;

    deg_freedom = lambda*theta/Sqr_eta;

    sum=0.;
    Tk=Ti;
    for (k=i; k<=m; k++)
    {
        psi_d = GET(Psi_i_k, k-i);

        dzeta_k = 1 - 2*Sqr_eta*b_Ti*psi_d;
        sigma_k = Sqr_eta*b_Ti/dzeta_k;

        x = Y/sigma_k;

        n_centrality_param = x0*a_Ti/(Sqr_eta*b_Ti*dzeta_k);

        if (x<0)
        {
            P=0.;
            Q=1.;
        }
        else
        {
            pnl_cdf_chn (&which, &P, &Q, &x, &deg_freedom, &n_centrality_param, &status, &bound);
        }

        if (swaption_payer_receiver==0)
            trm_k = -GET(c_k, k-i)*BondPrice(Tk, LiborAffine->ZCMarket) * Q;
        else
            trm_k = GET(c_k, k-i)*BondPrice(Tk, LiborAffine->ZCMarket) * P;

        sum += trm_k;
        Tk += swaption_period;
    }

    price = swaption_nominal * sum;

    pnl_vect_free(&c_k);
    pnl_vect_free(&Phi_i_k);
    pnl_vect_free(&Psi_i_k);

    return price;
}