Пример #1
0
// Conjugate gradient optimization of function f, given its gradient gradf.
// Minimum is stored in min, its location in p. Tolerance is asked :
static void optigc(int dim, PnlVect *p, double tol, double *min,
                   double f(PnlVect *),
                   void gradf(PnlVect *, PnlVect *))
{
  int i, j;
  /* Scalars used to define directions */
  double        gg,gam,fp,dgg;  
  PnlVect   *g     = pnl_vect_create (dim); /* Auxiliary direction :
                                                     gradient at the minimum */
  PnlVect   *h     = pnl_vect_create (dim); /* Conjugate direction along
                                                     which to minimize */
  PnlVect   *grad  = pnl_vect_create (dim); /* Gradient */
  const int     ITMAX = 20000;
  const double  EPS   = 1.0e-18;

  fp=f(p);
  gradf(p,grad);

  pnl_vect_clone (h, grad);
  pnl_vect_clone (g, grad);
  pnl_vect_mult_double (h ,-1.0);
  pnl_vect_mult_double (g ,-1.0);
  pnl_vect_mult_double (grad ,-1.0);

  for(i=0; i<ITMAX; i++) {
    min1dir(dim,p,h,min,f); // Minimizing along direction h
    if(2.0*fabs((*min)-fp) <= tol*(fabs((*min))+fabs(fp)+EPS)) // Done : tolerance reached
      {
        pnl_vect_free (&g);
        pnl_vect_free (&h);
        pnl_vect_free (&grad);
        return;
      }
    fp=(*min);
    gradf(p,grad); // Computes gradient at point p, location of minimum
    dgg=gg=0.0;

    /* Computes coefficients applied to new direction for h */
    gg = pnl_vect_scalar_prod (g, g); /* Denominator */
    dgg = pnl_vect_scalar_prod (grad, grad) + pnl_vect_scalar_prod (g, grad); /* Numerator : Polak-Ribiere */

    if(gg==0.0) // Gradient equals zero : done
      {
        pnl_vect_free (&g);
        pnl_vect_free (&h);
        pnl_vect_free (&grad);
        return;
      }
    gam=dgg/gg;

    for(j=0; j<dim; j++){ // Defining directions for next iteration
      pnl_vect_set (g, j, - pnl_vect_get (grad,  j)); 
      pnl_vect_set (h, j, pnl_vect_get (g,  j)+gam * pnl_vect_get (h,  j));
    }
  }
  perror ("Too many iterations in optigc\n");
}
Пример #2
0
double Barrier::payoff(const PnlMat *path) {
	PnlVect * lastrow = pnl_vect_new();
	pnl_mat_get_row(lastrow, path, TimeSteps_-1);
	double prod = pnl_vect_scalar_prod(lastrow, payOffCoeff_) - S_;
	pnl_vect_free(&lastrow);
	if (std::max(prod,0.0) == 0.0) {
	  return 0.0;
	}
	for (int i = 0; i < size_; i++) {
	  for (int j = 0; j < TimeSteps_; j++) {
	    if (MGET(path, j, i) < GET(lowerBarrier_, i) || MGET(path, j, i) > GET(upperBarrier_, i)) {
	      return 0.0;
	    }
	  }
	}
	return prod;
}
Пример #3
0
 /* European Call/Put price with Bates model */ 
int MCCuchieroKellerResselTeichmann(double S0, NumFunc_1  *p, double t, double r, double divid, double V0,double kappa,double theta,double sigmav,double rho,double mu,double gamma2,double lambda, long N, int M,int Nb_Degree_Pol,int generator, double confidence,double *ptprice, double *ptdelta, double *pterror_price, double *pterror_delta , double *inf_price, double *sup_price, double *inf_delta, double *sup_delta)
{
  /* Inputs: NumFunc_1 *p  specifies the payoff function (Call or Put),
		         S_0, K, t:  option inputs   
             other inputs: model parameters
             N: number of iterations in the Monte Carlo simulation
             M: number of discretization steps
             Nb_Degree_Pol: degree of approximating polynomial for variance 
                            reduction, between 0 and 8.
      Calculates the price of a European Call/Put option using Monte Carlo 
      with variance reduction. Variance reduction is achieved by approximating 
      the payoff function with a polynomial whose expectation can be calculated 
      analytically and which therefore serves as control variate.       
  */
             
  double mean_price,var_price,mean_delta,mean_delta_novar,var_delta,polyprice, polydelta,mean_price_novar;
  double poly_sample,price_sample_novar,delta_sample,delta_poly_sample,delta_sample_novar;
  int init_mc,i,j,k,n,m1,m2;
  int simulation_dim= 1;
  double alpha, z_alpha;
  double g,g2,h,Xt,Vt;
  double dt,sqrt_dt;
  int nj;
  double poisson_jump=0,mm=0,Eu;
  int matrix_dim, line;
  double K;
  double rhoc;
  PnlMat *A, *eA;
  PnlVect *coeff;
  PnlVect *deltacoeff;
  PnlVect *matcoeff;
  PnlVect *deltamatcoeff;
  PnlVect *b;
  PnlVect *deltab;
  PnlVect *veczero;
  PnlVect *vecX;
  
  rhoc=sqrt(1.-SQR(rho)); 
  Eu= exp(mu+0.5*gamma2)-1.;
  dt=t/(double)M;
  sqrt_dt=sqrt(dt);
  
  K=p->Par[0].Val.V_DOUBLE;
  
  /* Initialisation of vectors and matrices */
  coeff=pnl_vect_create_from_double(Nb_Degree_Pol+1,0.);                                                         
  deltacoeff=pnl_vect_create_from_double(Nb_Degree_Pol+1,0.);
  vecX=pnl_vect_create_from_double(Nb_Degree_Pol+1,0.); 
  
  matrix_dim = (Nb_Degree_Pol+1)*(Nb_Degree_Pol+2)/2;
  matcoeff=pnl_vect_create_from_double(matrix_dim,0.);
  deltamatcoeff=pnl_vect_create_from_double(matrix_dim,0.);
  veczero=pnl_vect_create_from_double(matrix_dim,0.); 
  A=pnl_mat_create_from_double(matrix_dim,matrix_dim,0.);
  eA= pnl_mat_create_from_double(matrix_dim,matrix_dim,0.);
  
  /* Approximation of payoff function */
  pol_approx(p,coeff,S0,K,Nb_Degree_Pol);
  
  /* Calculation of the coefficients of the derivative of the approximating 
     polynomial */
  for (n=0;n<Nb_Degree_Pol;n++)
    LET(deltacoeff,n)=GET(coeff,n+1)*(double)n;
  
  /* Reordering of coefficients, to fit the size of the generator matrix */
  for(n=0;n<Nb_Degree_Pol+1;n++)
  {
    LET(matcoeff,n*(n+1)/2)=GET(coeff,n);
    LET(deltamatcoeff,n*(n+1)/2)=GET(deltacoeff,n);
  }
  
  /* Calculation of the matrix corresponding to the generator of the Bates model */
  matrix_computation(A,Nb_Degree_Pol, r, divid, kappa, theta, lambda, mu, gamma2, sigmav, rho);
  pnl_mat_mult_double(A,t);
  
  /* Matrix exponentiation */
  pnl_mat_exp (eA,A);

  pnl_mat_sq_transpose (eA);
  b=pnl_mat_mult_vect(eA, matcoeff);
  deltab=pnl_mat_mult_vect(eA, deltamatcoeff);

  /* Calculation log(S0)^m1 V0^m2, m1+m2 <=Nb_Degree_Pol */
  for(m1=0;m1<Nb_Degree_Pol+1;m1++)
      for(m2=0;m2<Nb_Degree_Pol+1-m1;m2++)
        {
      line=(m1+m2)*(m1+m2+1)/2+m2;
      LET(veczero,line)=pow(log(S0),(double) m1)*pow(V0, (double) m2);
    }
   
   /* Expectation of approximating polynomial */
  polyprice=pnl_vect_scalar_prod(b,veczero);
  /* Expectation of derivative of approximating polynomial */
  polydelta=pnl_vect_scalar_prod(deltab,veczero);
  
  
  /* Value to construct the confidence interval */
  alpha= (1.- confidence)/2.;
  z_alpha= pnl_inv_cdfnor(1.- alpha);
  
  /*Initialisation*/
  mean_price= 0.0;
  var_price= 0.0;
  mean_delta= 0.0;
  mean_delta_novar= 0.0;
  var_delta= 0.0;
  mean_price_novar=0.;
  
  /*MC sampling*/
  init_mc= pnl_rand_init(generator,simulation_dim,N);

  /* Test after initialization for the generator */
  if(init_mc ==OK)
  {
    /* Begin N iterations */
    for(i=0;i<N;i++)
    {
      Xt=log(S0);
      Vt=V0;
      for(j=0;j<M;j++)
      {
        mm = r-divid-0.5*Vt-lambda*Eu;
         
       /* Generation of standard normal random variables  */
        g= pnl_rand_normal(generator);
        g2= pnl_rand_normal(generator);
       
        
       /* Generation of Poisson random variable */ 
        if(pnl_rand_uni(generator)<lambda*dt)
          nj=1;
        else nj=0;
        
        /* Normally distributed jump size */
        h = pnl_rand_normal(generator);
        poisson_jump=mu*nj+sqrt(gamma2*nj)*h;
       
       /* Euler scheme for log price and variance */
        Xt+=mm*dt+sqrt(MAX(0.,Vt))*sqrt_dt*g+poisson_jump;
        Vt+=kappa*(theta-Vt)*dt+sigmav*sqrt(MAX(0.,Vt))*sqrt_dt*
        (rho*g+rhoc*g2);
      }
      price_sample_novar=(p->Compute)(p->Par,exp(Xt));
      
      /* Creation of vector containing Xt^k, k<=Nb_Degree_Pol */
      for(k=0;k<Nb_Degree_Pol+1;k++)
        {
          LET(vecX,k)=pow(Xt, (double) k);
        }
     
     /* Approximating polynomial evaluated at Xt */
      poly_sample=pnl_vect_scalar_prod(coeff,vecX);
     /* Derivative of approximating polynomial evaluated at Xt */
      delta_poly_sample=pnl_vect_scalar_prod(deltacoeff,vecX);
      
      /*Sum for prices*/
      mean_price_novar+=price_sample_novar;   /* without control variate */
      mean_price+=price_sample_novar-(poly_sample-polyprice);  /* with control variate*/
      
      /* Delta sampling */
     if (price_sample_novar>0.)
        {
          delta_sample_novar=exp(Xt)/S0;//Call Case
          delta_sample= (exp(Xt)-(delta_poly_sample-polydelta))/S0; /* Delta sampling with control variate*/
          if((p->Compute) ==  &Put)
            delta_sample=(-exp(Xt)-(delta_poly_sample-polydelta))/S0;  /* Delta sampling with control variate */
        }
     
     else{
        delta_sample_novar=0;
        delta_sample=0.-(delta_poly_sample-polydelta)/S0;   /* Delta sampling with control variate */
     }
     
     /*Sum for delta*/
      mean_delta_novar+=delta_sample_novar;     /* without control variate */
      mean_delta+=delta_sample;                /* with control variate*/

      /*Sum of squares*/
      var_price+=SQR(price_sample_novar-(poly_sample-polyprice));
      var_delta+=SQR(delta_sample);
    }

    /*Price */
    *ptprice=exp(-r*t)*(mean_price/(double) N);

    /*Error*/
    *pterror_price= sqrt(exp(-2.0*r*t)*var_price/(double)N - SQR(*ptprice))/sqrt(N-1);
     
     /* Price Confidence Interval */
     *inf_price= *ptprice - z_alpha*(*pterror_price);
     *sup_price= *ptprice + z_alpha*(*pterror_price);

     /*Delta*/
      *ptdelta=exp(-r*t)*mean_delta/(double) N;
      *pterror_delta= sqrt(exp(-2.0*r*t)*(var_delta/(double)N-SQR(*ptdelta)))/sqrt((double)N-1);
      
      /* Delta Confidence Interval */
      *inf_delta= *ptdelta - z_alpha*(*pterror_delta);
      *sup_delta= *ptdelta + z_alpha*(*pterror_delta);
    
  }
  
  //Memory desallocation
  pnl_mat_free (&eA);
  pnl_mat_free (&A);
  pnl_vect_free(&coeff);
  pnl_vect_free(&b);
  pnl_vect_free(&matcoeff);
  pnl_vect_free(&veczero);
  pnl_vect_free(&vecX);
  pnl_vect_free(&deltacoeff);
  pnl_vect_free(&deltamatcoeff);
  pnl_vect_free(&deltab);

  return init_mc;
}