// Finds a minimum of a multidimensional function f in direction dir.
// Minimum is stored in min, its location in p :
static void min1dir(int dim, PnlVect * p, PnlVect * dir, double *min, double f(PnlVect *))
{
  int j;
  const double TOL=1.0e-10;
  double xx,xmin,bx,ax;

  // Initialise les variables globales
  _n=dim;
  _p = p;
  _dir = dir;
  func=f;
  
  // [0,1] is the initial bracketing guess
  ax=0.0; 
  xx=1.0;
  minenc(&ax,&xx,&bx,f1dim); // Computes an acutal bracketing triplet
  *min=min1dim(ax,xx,bx,f1dim,TOL,&xmin); // Computes the minimum of function f1dim
  // (which is the minimum of function f in direction dir)

  for(j=0;j<dim;j++){
    double d = pnl_vect_get (dir , j);
    pnl_vect_set (dir,  j,  d*xmin);
    pnl_vect_set (p, j, pnl_vect_get (p,  j) + pnl_vect_get (dir,  j)); // Sets actual position of the minimum
  }

}
// 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");
}
static double f1dim( double x)
{
  int j;
  double val;
  PnlVect * xt = pnl_vect_create (_n);
  for(j=0; j<_n; j++){
    pnl_vect_set (xt, j, pnl_vect_get (_p,  j) + x * pnl_vect_get (_dir,  j));
  }
  val=func(xt);
  pnl_vect_free (&xt);
  return val;
}
//------------------------Sampling the transition probability (v(0)=X_t, v(1)=int_0^t X_s ds) 
//-------------------------dX_t = kappa(theta-X_t)dt + sigma sqrt(X_t)dW_t
//-------------------------------------In the case of the troncation serie
static void Sample_C(  PnlVect* v,double t, double kappa, double sigma, double theta ,int generator)
{
  //----------Declaration of variable
  double gamma, lambda;
  double tmp;
  double tmp2;
  int j,pss;
  int order_tr; // Default value is equal to 20
  //----------Initialization of parammter
  tmp=0.;
  j=0;
  gamma = 4.*kappa/(sigma*sigma*(1.-exp(-kappa*t)));
  lambda = pnl_vect_get(v,0)*gamma*exp(-kappa*t);
  order_tr = 20;
  //----------Begin operations
  //----generate vt --> tmp
  pss = pnl_rand_poisson(lambda*0.5,generator);
  
  for(j=1;j<= pss;j++)
    tmp = tmp + pnl_rand_gamma(1.,2., generator);
  
  tmp = tmp +pnl_rand_gamma(2.*kappa*theta/(sigma*sigma),2.,generator);
  tmp = tmp/gamma;
  //----generate the variable Z

  tmp2 =0.;
  j=0;
  pss = pnl_rand_bessel(2.*theta*kappa/(sigma*sigma)-1.,2.*kappa*sqrt(pnl_vect_get(v,0)*tmp)/(sigma*sigma*sinh(kappa*t*0.5)),generator);

  for(j=1;j<=pss;j++)
    {
      tmp2=tmp2+X_3_sample(  order_tr,  t,  kappa,  sigma,  generator);
    }
  //----generate int_0^t vs = X1 +X2 +X3 --> lambda

  lambda=tmp2+X_2_sample(  order_tr,  t,  kappa,  sigma,  theta ,  generator)+X_1_sample(  order_tr,  t,  kappa,  sigma,  pnl_vect_get(v,0),  tmp,  generator);
  
  //----set the new value 
  pnl_vect_set(v,0,tmp);
  pnl_vect_set(v,1,lambda);
}
/**
 * Solve a tridiagonal system defined by matrix whose three diagonals are
 * defined by three values.
 * @param low the double value of M(i,i-1)
 * @param diag the double value of M(i,i)
 * @param up the double value of M(i,i+1)
 * @param rhs the right and side member of the system
 * @param lhs contains the solution on exit
 */
void pnl_progonka(const double low,
                  const double diag, const double up,
                  const PnlVect * rhs,
                  PnlVect * lhs)
{
  int i;
  double *D,tmp;
  D = malloc((rhs->size)*sizeof(double));
  /* Do Down-Solve L y = rhs  */
  if((D[0]=diag)==0)
    {
      PNL_ERROR("division by zero","pnl_progonka");
    }
  pnl_vect_set(lhs,0,pnl_vect_get(rhs,0));
  for(i=1; i<rhs->size; i++)
    {
      tmp=low/D[i-1];
      if((D[i]=diag-tmp*up)==0)
        {
           PNL_ERROR("division by zero","pnl_progonka");
        }
      pnl_vect_set(lhs,i,pnl_vect_get(rhs,i)-tmp*pnl_vect_get(lhs,i-1));
    }
  /* Do Up-Solve L y = rhs  */
  pnl_vect_set(lhs,rhs->size-1,pnl_vect_get(lhs,rhs->size-1)/D[rhs->size-1]);
  for(i=rhs->size-2;i>=0;i--)
    {
      pnl_vect_set(lhs,i,(pnl_vect_get(lhs,i)-up*pnl_vect_get(lhs,i+1))/D[i]);
    }
  free(D);

}
// Computes the price and the deltas of a claim using the lower bound of the
// price for an option
// that is paying a linear combination of assets :
static void lowlinearprice(int _dim, PnlVect *_eps, PnlVect *_x, PnlMat *_rac_C, PnlVect *_sigma, double _echeance, double *prix, PnlVect *deltas)
{
  int i, j;
  double arg;
  double normv=0;
  double tol=1e-15;
  PnlVect *xopt = pnl_vect_create_from_double ( _dim+2, 1./sqrt(_dim+1.));
  // Starting point for optimization : normalized vector
  pnl_vect_set (xopt,  _dim+1,  0.0);
    
  // Initializing global variables to parameters of the problem
  Dim=_dim;
  Echeance=_echeance;
  Sigma = _sigma;
  Rac_C = _rac_C;
  Eps = _eps;
  X = _x;

  optigc(Dim+2,xopt,tol,prix,Cost,Gradcost);

  *prix = -1.0* (*prix); // Price is the maximum of function

  for (i=0; i<Dim+1; i++)
    {
      double xopt_i = pnl_vect_get (xopt,  i);
      normv += xopt_i * xopt_i;
    }
  normv = sqrt (normv);

  for(i=0; i<Dim; i++){
    double tmp=0;
    for(j=0; j<Dim+1; j++){
      tmp+=pnl_mat_get (_rac_C,  i+1,  j) * pnl_vect_get (xopt,  j);
    }
    arg=pnl_vect_get (xopt,  Dim+1) + pnl_vect_get (Sigma,  i+1) * tmp*sqrt(Echeance)/normv;
    pnl_vect_set (deltas, i, pnl_vect_get (Eps,  i+1) * cdf_nor(arg)); // Computing the deltas
  } 
  pnl_vect_free (&xopt);
}
Exemple #7
0
double call_by_density(double k, params *p)
        {
	int N ;
        double m_dVarianceCurve;
        double m_dGamma ;
        double m_dOmega1 ;
        double m_dOmega2 ;
        double m_dCorrel;

       int path,i ;
       double sup ;
       PnlVect *axis;
double strikeMin, res;

	N = p->n;
        m_dVarianceCurve= p->VarianceCurve;
        m_dGamma =  p->Gamma;
        m_dOmega1 = p->Omega1;
        m_dOmega2 = p->Omega2;
        m_dCorrel = p->Correl;

       path = 2000;
       sup = 12;
       axis = pnl_vect_create(path);

       strikeMin = z(k * k,p);
 

             res = 0;
            
            for (i = 0; i < path; i++)
	      pnl_vect_set(axis,i,strikeMin + sup * i / (double)path);
            for (i = 0; i < path - 1; i++)
	      res += (pnl_vect_get(axis,i+1) - pnl_vect_get(axis,i)) * MAX(sqrt(g(pnl_vect_get(axis,i),p)) - k, 0.0) *
                    exp(-pnl_vect_get(axis,i) * pnl_vect_get(axis,i) / 2.0) / sqrt(2.0 * M_PI);
            return res;
        }
Exemple #8
0
double put_by_density(double k, params *p)
        {
	int N ;
        double m_dVarianceCurve;
        double m_dGamma ;
        double m_dOmega1 ;
        double m_dOmega2 ;
        double m_dCorrel;

       int path,i ;
       double inf ;
       PnlVect *axis;
	double strikeMax, res;

	N = p->n;
        m_dVarianceCurve= p->VarianceCurve;
        m_dGamma =  p->Gamma;
        m_dOmega1 = p->Omega1;
        m_dOmega2 = p->Omega2;
        m_dCorrel = p->Correl;

       path = 2000;
       inf = -12;
       axis = pnl_vect_create(path);

       strikeMax = z(k * k,p);
   
     
         res = 0;

            for (i = 0; i < path; i++)
	      pnl_vect_set(axis,i,inf + (i + 1) * (strikeMax - inf) / (double)path);
            for (i = 0; i < path - 1; i++)
	      res += (pnl_vect_get(axis,i+1) - pnl_vect_get(axis,i)) * MAX(k - sqrt(g(pnl_vect_get(axis,i),p)), 0.0) *
                    exp(-pnl_vect_get(axis,i) * pnl_vect_get(axis,i) / 2.0) / sqrt(2.0 * M_PI);
            return res;
        }
Exemple #9
0
double Barrier_l :: payoff (const PnlMat *path) {
  double sum ;
  PnlVect* final = pnl_vect_create(size_);

  //On met dans final la dernière colonne de Path correspond à la valeur à maturité des sous-jacents.
  pnl_mat_get_col(final, path, TimeSteps_);
  sum = pnl_vect_scalar_prod(final, Coeff_) - Strike_;
  //On vérifie que toutes les valeurs des sous-jacents soient au dessus de la barrière
  //Si on en trouve une alors le prix de l'option est de 0
  for (int i=0; i<TimeSteps_+1; i++){
	for (int d=0; d<size_; d++){
	  if (pnl_mat_get(path,d,i) < pnl_vect_get(Bl_,d)){
		pnl_vect_free(&final);
		return 0;
	  }
	}
  }
Exemple #10
0
double Barrier_u :: payoff (
	double t, 
	const PnlMat* path) const
{
  double sum ;
  //Vecteur utilisé pour effectuer la somme de chaque actif à maturité
  PnlVect* final = pnl_vect_create(size_);

  //On met dans final la dernière colonne de Path correspond à la valeur à maturité des sous-jacents
  pnl_mat_get_col(final, path, timeStep_);
  sum = pnl_vect_scalar_prod(final, Coeff_) - strike_;
  //On vérifie que toutes les valeurs des sous-jacents soient en dessous de la barrière
  //Si on en trouve une alors le prix de l'option est de 0
  for (int i=0; i<timeStep_+1; i++){
	for (int d=0; d<size_; d++){
	  if (MGET(path,d,i) > pnl_vect_get(Bu_,d)){
		pnl_vect_free(&final);
		return 0;
	  }
	}
  }
Exemple #11
0
 double f_by_density(params *p)
        {
 
	int N ;
        double m_dVarianceCurve;
        double m_dGamma ;
        double m_dOmega1 ;
        double m_dOmega2 ;
        double m_dCorrel;

       int path,i ;
       double sup ;
       PnlVect *axis;

double res ;
	N = p->n;
        m_dVarianceCurve= p->VarianceCurve;
        m_dGamma =  p->Gamma;
        m_dOmega1 = p->Omega1;
        m_dOmega2 = p->Omega2;
        m_dCorrel = p->Correl;

       path = 2000;
       sup = 12;
       axis = pnl_vect_create(path);

            

            res = 0;
            
            for ( i = 0; i < path; i++)
                pnl_vect_set(axis,i, -sup + 2 * sup * i / (double)path);  
            
	    for ( i = 0; i < path - 1; i++)
	      res += (pnl_vect_get(axis,i + 1) - pnl_vect_get(axis,i)) *
                    sqrt(m_dVarianceCurve * (1 - m_dGamma) * exp(m_dOmega1 * pnl_vect_get(axis,i) - m_dOmega1 * m_dOmega1 / 2.0) +
                    m_dVarianceCurve * m_dGamma * exp(m_dOmega2 * pnl_vect_get(axis,i) - m_dOmega2 * m_dOmega2 / 2.0)) *
                    exp(-pnl_vect_get(axis,i) * pnl_vect_get(axis,i) / 2.0) / sqrt(2.0 *M_PI);
            return res;
        }
// Auxiliary cost function to minimize used in lowlinearprice :
static double Cost(PnlVect *ksi)
{
  int i, j;
  double p=0,arg=0;
  
  double normv=0;
  for (i=0; i<Dim+1; i++)
    {
      double ksi_i = pnl_vect_get (ksi,  i);
      normv += ksi_i * ksi_i;
    }
  normv = sqrt (normv);

  for(i=0; i<Dim+1;i++){
    double tmp=0;
    for(j=0;j<Dim+1;j++){
      tmp+=pnl_mat_get (Rac_C,  i,  j) * pnl_vect_get (ksi,  j);
    }
    arg=pnl_vect_get (ksi,  Dim+1) + pnl_vect_get (Sigma,  i) * tmp*sqrt(Echeance)/normv;
    p+=pnl_vect_get (Eps,  i) * pnl_vect_get (X,  i) * cdf_nor(arg);
  }

  return (-1.0*p); // The function is to be maximized
}
// Returning the price and the deltas  of a basket option using its lower bound approximation :
static void lower_basket(int put_or_call,int dim, PnlVect *vol, PnlVect *poids,  PnlVect *val_init, PnlVect *div, double cor, double tx_int, double strike, double echeance,  double *prix, PnlVect* deltas)
{
  int i,j;
  // Initializing parameters
  PnlVect *sigma = pnl_vect_create (dim+1);
  PnlVect *x = pnl_vect_create (dim+1);
  PnlVect *eps = pnl_vect_create (dim+1);
  PnlMat *rac_C = pnl_mat_create (dim+1, dim+1);

  pnl_vect_set (sigma,  0,  0);
  for(i=1; i<dim+1;i++){
    pnl_vect_set (sigma, i, pnl_vect_get (vol,  i-1));
  }

  pnl_vect_set (x, 0, strike*exp(-tx_int*echeance));
  for (i=1; i<dim+1; i++){
    pnl_vect_set (x, i, fabs(pnl_vect_get (poids,  i-1)) *
                     pnl_vect_get (val_init,  i-1)*
                     exp(-pnl_vect_get (div,  i-1)*echeance));
  }
  
  pnl_vect_set (eps,  0,  -1);
  for (i=1; i<dim+1; i++){
    if(pnl_vect_get (poids,  i-1)<0) pnl_vect_set (eps,  i,  -1);
    else pnl_vect_set (eps,  i,  1);
  }
  if(put_or_call==1)
    { 
      pnl_vect_mult_double (eps, -1.0);
    }
    
  if(cor != 1){
    PnlMat *C = pnl_mat_create (dim, dim);
    //    double *C=new double[dim*dim]; // Correlation matrix
    for(i=0; i<dim; i++){
      for(j=0; j<dim; j++){
        if(i==j) pnl_mat_set (C,  i,  j,  1);
        else pnl_mat_set (C,  i,  j,  cor);
      }
    }
    pnl_mat_chol (C);
    
    for(i=0; i<dim+1; i++){
      pnl_mat_set (rac_C,  i,  0,  0);
      pnl_mat_set (rac_C,  0,  i, 0);
    }
    for(i=1; i<dim+1; i++){
      for(j=1; j<=i;j++){
        pnl_mat_set (rac_C, i, j, pnl_mat_get (C,  i-1,  j-1));
      }
      for(j=i+1;j<dim+1;j++){
        pnl_mat_set (rac_C,  i,  j ,  0);
      }
    }
    
    /* Correlation was useful only to compute a square root of it */
    pnl_mat_free (&C);
    
  } else {
    for(i=0; i<dim+1;i++){
      pnl_mat_set (rac_C,  i,  0,  0);
      pnl_mat_set (rac_C, i, 1, 1);
      for(j=2; j<dim+1;j++){
        pnl_mat_set (rac_C,  i,  j,  0);
      }
    }
    pnl_mat_set (rac_C,  0,  1,  0);
  }

  lowlinearprice(dim,eps,x,rac_C,sigma,echeance,prix,deltas); // Uses the general formula

  /* In deltas are stored the derivatives along x[i], which differ from those
     along val_init[i] */
  for(i=0;i<dim;i++){
    double d = pnl_vect_get (deltas,  i);
    pnl_vect_set (deltas, i, d * pnl_vect_get (x,  i+1) / pnl_vect_get (val_init,  i)); 
  }

  pnl_vect_free (&eps);
  pnl_vect_free (&x);
  pnl_vect_free (&sigma);
  pnl_mat_free (&rac_C);
  
}
static int SingularPoints_Up(int am,double s,NumFunc_1  *p,double t,double r,double sigma,PnlVect *divid_dates,PnlVect *divid_amounts,int N,double h_up,double *ptprice,double *ptdelta)
{
 
  int n;
  double u,d,h,pu,pd,a1;
  double K=p->Par[0].Val.V_DOUBLE;
  double *v_min,*v_max,*new_vm,*new_vm1,*new_vm2,*new_vpm,*new_vpm1,*new_vpm2;
  double *vect_t;
  int * nb_critical;
  int *divid_steps;
  double value1,value2,value_price1,value_price2;
  double dist1,dist2;
  double TOL1=0.00000000001;
  double TOL2=0.00000000001;
  int i,j,k,l,jj,kk,Nb_div,new_nb_critical,n_k;
  int max_critical=0;
  int i1,index,nb_critical_put;
  double m1,error,errp;
  int  old_nb_critical;
  double x1,x2,y2,y11,a,b;
  int n_max;
  
  /*Number of Dividends Dates*/
  Nb_div=divid_dates->size;

  //Number maximum of singular points
  n_max=50000;
  
  /*Compute steps of the tree*/
  n=N*Nb_div;

  
  /*Memory allocations*/
  divid_steps= malloc((n+1)*sizeof(int));
  nb_critical=(int*)malloc(sizeof(int)*(n+1));
  v_min=(double*)malloc(sizeof(double)*(n+1));
  v_max=(double*)malloc(sizeof(double)*(n+1));
  vm=(double*)malloc(sizeof(double)*(n_max));
  vpm=(double*)malloc(sizeof(double)*(n_max));
  new_vm=(double*)malloc(sizeof(double)*(n_max));
  new_vm1=(double*)malloc(sizeof(double)*(n_max));
  new_vm2=(double*)malloc(sizeof(double)*(n_max));
  new_vpm=(double*)malloc(sizeof(double)*(n_max));
  new_vpm1=(double*)malloc(sizeof(double)*(n_max));
  new_vpm2=(double*)malloc(sizeof(double)*(n_max));
  vect_t= malloc((n+1)*sizeof(double));
  
  /*Up and Down factors*/
  h=t/(double)n;
  a1= exp(h*r);
  u = exp(sigma*sqrt(h));
  d= 1./u;

  /*Risk-Neutral Probability*/
  pu=(a1-d)/(u-d);
  pd=1.-pu;

  if ((pd>=1.) || (pd<=0.))
    return NEGATIVE_PROBABILITY;

  pu*=exp(-r*h);
  pd*=exp(-r*h);

  for(i=0;i<=n;i++)
    vect_t[i]=h*(double)i;

  //Compute steps related to the dividend dates
  for(k=0;k<Nb_div;k++)
    {
      i=0;
      while(vect_t[i]<pnl_vect_get(divid_dates,k)) i++;
      if(fabs(pnl_vect_get(divid_dates,k)-vect_t[i])<1.e-10)
        divid_steps[k]=i;
      else
        {
          dist1=vect_t[i]-pnl_vect_get(divid_dates,k);
          dist2=pnl_vect_get(divid_dates,k)-vect_t[i-1];
          if (dist1<dist2)
            divid_steps[k]=i;
          else
            divid_steps[k]=i-1;
        }
    }

  /*Compute Minimum and Maximum of the stock at each step
   taking in to account of the dividend payements*/
  v_min[0]=s;
  v_max[0]=s;
  j=0;
  for(i=1;i<=n;i++)
    {
      v_min[i]=v_min[i-1]*d;
      v_max[i]=v_max[i-1]*u;

      for(k=0;k<Nb_div;k++)
        if(i==divid_steps[k])
          {   
            v_min[i]=v_min[i]-pnl_vect_get(divid_amounts,Nb_div-k-1);
            v_max[i]=v_max[i]-pnl_vect_get(divid_amounts,Nb_div-k-1);
            
          }
    }
 
  /***Singular points at Maturity****/
  if((v_min[n]<K)&&(v_max[n]>K))
    {
      nb_critical[n]=2;
      //Abscissa
      vm[0]=v_min[n];
      vm[1]=K;
      vm[2]=v_max[n];

      //Ordinate 
      vpm[0]=(p->Compute)(p->Par,vm[0]); 
      vpm[1]=(p->Compute)(p->Par,vm[1]);
      vpm[2]=(p->Compute)(p->Par,vm[2]);
    }
  else
    {
      nb_critical[n]=1;
      //Abscissa
      vm[0]=v_min[n];
      vm[1]=v_max[n];

      //Ordinate 
      vpm[0]=(p->Compute)(p->Par,vm[0]); 
      vpm[1]=(p->Compute)(p->Par,vm[1]);
    }
  
  /***Backward algorithm****/
  for(i=1;i<=n;i++)
    {
      /*Min point*/
      new_vm[0]=v_min[n-i];//Abscissa 
      value1=new_vm[0]*u;  
      value_price1=compute_pricesp(value1,nb_critical[n-i+1]);
      value2=new_vm[0]*d;  
      value_price2=compute_pricesp(value2,nb_critical[n-i+1]);
      new_vpm[0]=pu*value_price1+pd*value_price2;//Ordinate
    
      /*Middle points*/
      n_k=1;
      for(j=1;j<nb_critical[n-i+1];j++)
        {
          for(jj=-1;jj<=1;jj=jj+2)
            {
              new_vm[n_k]=vm[j]*pow(u,(double)jj);//Abscissa
              if((new_vm[n_k]>v_min[n-i])&&(new_vm[n_k]<v_max[n-i]))
                { 
                  value1=new_vm[n_k]*u;
                  value_price1=compute_pricesp(value1,nb_critical[n-i+1]);
                  value2=new_vm[n_k]*d;
                  value_price2=compute_pricesp(value2,nb_critical[n-i+1]);
                  new_vpm[n_k]=pu*value_price1+pd*value_price2;//Ordinate
                  n_k++;		      	      
                }
            }
        }
    
      /*Max point*/
      new_vm[n_k]=v_max[n-i];//Abscissa    
      value1=new_vm[n_k]*u;
      value_price1=compute_pricesp(value1,nb_critical[n-i+1]);  
      value2=new_vm[n_k]*d;  
      value_price2=compute_pricesp(value2,nb_critical[n-i+1]);  
      new_vpm[n_k]=pu*value_price1+pd*value_price2;//Ordinate

      
      //Shift at the dividends dates
      for(k=0;k<Nb_div;k++)
        if(i==divid_steps[k])
          {
            for(j=0;j<=n_k;j++)
              new_vm[j]+=pnl_vect_get(divid_amounts,Nb_div-k-1);
          }
      
      /*Sorting*/
      nb_critical[n-i]=n_k;
      Sort2Vect(nb_critical[n-i],new_vm,new_vpm);
      
      //Remove singular points very close TOL1=e-10,TOL2=e-10
      new_vm1[0]=new_vm[0];
      new_vpm1[0]=new_vpm[0];
      kk=0;
      l=0;
      do {
        do {
          l++;
        }while((new_vm[l]<=new_vm1[kk]+TOL1)&&(l<nb_critical[n-i]));
        kk++;
        new_vm1[kk]=new_vm[l];
        new_vpm1[kk]=new_vpm[l];
      }while((l<nb_critical[n-i]));
	
      new_nb_critical=kk;
      nb_critical[n-i]=kk;
      
      if(fabs(new_vm1[nb_critical[n-i]]-new_vm1[nb_critical[n-i]-1])<TOL2)	
        nb_critical[n-i]=new_nb_critical-1;
     
      //Upper bound
      i1=0;
      index=0;
      new_vm2[0]=new_vm1[0];
      new_vpm2[0]=new_vpm1[0];
      while(i1<nb_critical[n-i]-1)
        {	     
          l=1;
          do 
            {
              l++;
              m1=(new_vpm1[i1+l]-new_vpm1[i1])/(new_vm1[i1+l]-new_vm1[i1]);
              error=0.;
              for(jj=1;jj<=l-1;jj++)
                {
                  errp=m1*(new_vm1[i1+jj]-new_vm1[i1])+new_vpm1[i1]-new_vpm1[i1+jj];
                  if (errp<0) errp=-errp;
                  if (errp>error) error=errp;
                }
            }
          while(!((error>h_up)||((i1+l)==nb_critical[n-i])));
          index++;
          new_vm2[index]=new_vm1[i1+l-1];
          new_vpm2[index]=new_vpm1[i1+l-1];
          i1=i1+l-1;
        }
      while(i1<nb_critical[n-i])
        {
          index++;
          new_vm2[index]=new_vm1[i1+1];
          new_vpm2[index]=new_vpm1[i1+1];
          i1 =i1+1;
        }
      nb_critical[n-i]=index;

      //American Call Case
      if((am==1)&&((p->Compute)==&Call))
        {
          old_nb_critical=nb_critical[n-i];
          if(MAX(0.,new_vm2[0]-K)<=new_vpm2[0])
            {		  
              l=1;
              while((new_vpm2[l]>=MAX(0.,new_vm2[l]-K))&&(l<=nb_critical[n-i]))
                {
                  l++;
                  if(l>nb_critical[n-i])  break;
                }
              if(l<=nb_critical[n-i])
                {
                  nb_critical[n-i]=l+1;
                  x1=new_vm2[l-1];
                  x2=new_vm2[l];
                  y11=new_vpm2[l-1];
                  y2=new_vpm2[l];

                  a=(y2-y11)/(x2-x1);
                  b=(y11*x2-x1*y2)/(x2-x1);
		    
                  new_vm2[l]=(K+b)/(1.-a);

                  new_vpm2[l]=MAX(0.,new_vm2[l]-K);
		    
                  new_vm2[l+1]=new_vm2[old_nb_critical];
                  new_vpm2[l+1]=MAX(0.,new_vm2[l+1]-K);
                }  
            } 	  
        }
      
      
      /*
       //Dynamic Programming:American Put Case
       if((am==1)&&((p->Compute)==&Put))
       for(j=0;j<=nb_critical[n-i];j++)
       {
                
       new_vpm2[j]=MAX(new_vpm2[j],K-new_vm2[j]);
       }*/
      
      //American Put Case
      else
        if((am==1)&&((p->Compute)==&Put))
          {
            
            if(MAX(0.,K-new_vm2[0])>=new_vpm2[0])
              {
                new_vm1[0]=new_vm2[0];
                new_vpm1[0]=MAX(0.,K-new_vm2[0]);
                l=1;
                while((new_vpm2[l]<MAX(0.,K-new_vm2[l]))&&(l<=nb_critical[n-i]))
                  {
                    l++;
                    if(l>nb_critical[n-i])  break;
                  }
              
                if(l>nb_critical[n-i])
                  {
                    new_vm1[1]=new_vm2[nb_critical[n-i]];
                    new_vpm1[1]=MAX(0.,K-new_vm1[1]);
                    nb_critical[n-i]=1;
                
                  }
                else
                  if(l<=nb_critical[n-i])
                    {
                      x1=new_vm2[l-1];
                      x2=new_vm2[l];
                      y11=new_vpm2[l-1];
                      y2=new_vpm2[l];

                      a=(y2-y11)/(x2-x1);
                      b=(y11*x2-x1*y2)/(x2-x1);
		    
                      new_vm1[1]=(K-b)/(1.+a);
                      new_vpm1[1]=MAX(0.,K-new_vm1[1]);
                    
                      j=l;
                      nb_critical_put=1;
                      while((j<=nb_critical[n-i]))
                        {
                          nb_critical_put++;
                          new_vm1[nb_critical_put]=new_vm2[j];
                          new_vpm1[nb_critical_put]=new_vpm2[j];
                          j++;
                        };
                      nb_critical[n-i]=nb_critical_put;
                    }
                  
                for(j=0;j<=nb_critical[n-i];j++)
                  {
                    new_vm2[j]=new_vm1[j];
                    new_vpm2[j]=new_vpm1[j];
                  }
                
              } 	  
          }

      max_critical=MAX(nb_critical[n-i],max_critical);
           
      //Copy
      for(j=0;j<=nb_critical[n-i];j++)
        {
          vm[j]=new_vm2[j];
          vpm[j]=new_vpm2[j];
        }
      /*Delta*/
      if(i==(n-1))
        *ptdelta=(vpm[nb_critical[n-i]]-vpm[0])/(vm[nb_critical[n-i]]-vm[0]);  
            
     
    }
  
  /*Price*/
  *ptprice=vpm[0];
  
 

  //Memory desallocation
  free(nb_critical);
  free(divid_steps);
  free(v_min);
  free(v_max);
  free(vpm);
  free(vm);
  free(new_vm);
  free(new_vm1);
  free(new_vm2);
  free(new_vpm);
  free(new_vpm1);
  free(new_vpm2);
  free(vect_t);
 
  
  return OK;
}
Exemple #15
0
static void pnl_basis_eval_test ()
{
  PnlMat    *X;
  PnlVect   *V, *x, *t, *D, *alpha, *lower, *upper;
  PnlRng    *rng;
  PnlBasis  *basis;
  int        j, deg, n;
  double     t0, x0, tol;

  tol = 1E-8;
  deg=5; //total degree
  n=50;
  D=pnl_vect_create(5);
  x=pnl_vect_create(n);
  t=pnl_vect_create(n);
  t0=0.5;
  x0=2.5;
  rng = pnl_rng_create (PNL_RNG_MERSENNE);
  pnl_rng_sseed (rng, 0);
  
  /*
   * Random points where the function will be evaluted
   */
  pnl_vect_rng_uni(x,n,-5,4,rng);
  pnl_vect_rng_uni(t,n,0,1,rng);
  basis = pnl_basis_create_from_degree (PNL_BASIS_HERMITIAN, deg, 2);
  alpha = pnl_vect_create (basis->nb_func);
  X = pnl_mat_create (n, 2);
  for(j=0;j<n;j++)
    {
      MLET (X, j, 0) = GET(t,j);
      MLET (X, j, 1) = GET(x,j);
    }
  V=pnl_vect_create(n);
  /*
   * Vector of values for the function to recover
   */
  for(j=0;j<n;j++)
    {
      LET(V,j)=fonction_a_retrouver(GET(t,j),GET(x,j));
    }
  pnl_basis_fit_ls (basis, alpha, X, V);
  /*
   * compute approximations of the derivatives (first order in time and
   * second order in space )
   */
  derive_approx_fonction(basis, D, alpha,t0,x0);
  pnl_test_eq_abs (pnl_vect_get(D,0), fonction_a_retrouver(t0,x0), tol,
                   "deriv_approx_fonction", "derivative 0");
  pnl_test_eq_abs (derive_x_approx_fonction(basis, alpha, t0, x0), 
                   derive_x_fonction_a_retrouver(t0,x0), tol, 
                   "deriv_approx_fonction", "derivative %% x");
  pnl_test_eq_abs (pnl_vect_get(D,2), derive_xx_fonction_a_retrouver(t0,x0), 
                   tol, "deriv_approx_fonction", "derivative %% xx");
  pnl_test_eq_abs (pnl_vect_get(D,3), derive_t_fonction_a_retrouver(t0,x0),
                   tol, "deriv_approx_fonction", "derivative %% t");
  pnl_test_eq_abs (pnl_vect_get(D,4), derive_xt_fonction_a_retrouver(t0,x0),
                   tol, "deriv_approx_fonction", "derivative %% tx");

  pnl_basis_free (&basis);

  /* reduced basis */
  basis = pnl_basis_create_from_degree (PNL_BASIS_HERMITIAN, deg, 2);
  lower = pnl_vect_create_from_list (2, 0., -5.);
  upper = pnl_vect_create_from_list (2, 1., 4.);
  pnl_basis_set_domain (basis, lower, upper);
  pnl_basis_fit_ls (basis, alpha, X, V);

  derive_approx_fonction(basis, D, alpha,t0,x0);
  pnl_test_eq_abs (pnl_vect_get(D,0), fonction_a_retrouver(t0,x0), tol,
                   "deriv_approx_fonction (reduced)", "derivative 0");
  pnl_test_eq_abs (derive_x_approx_fonction(basis, alpha, t0, x0), 
                   derive_x_fonction_a_retrouver(t0,x0), tol, 
                   "deriv_approx_fonction (reduced)", "derivative %% x");
  pnl_test_eq_abs (pnl_vect_get(D,2), derive_xx_fonction_a_retrouver(t0,x0), 
                   tol, "deriv_approx_fonction (reduced)",  "derivative %% xx");
  pnl_test_eq_abs (pnl_vect_get(D,3), derive_t_fonction_a_retrouver(t0,x0),
                   tol, "deriv_approx_fonction (reduced)", "derivative %% t");
  pnl_test_eq_abs (pnl_vect_get(D,4), derive_xt_fonction_a_retrouver(t0,x0),
                   tol, "deriv_approx_fonction (reduced)",  "derivative %% tx");

  pnl_basis_free (&basis);
  pnl_rng_free (&rng);
  pnl_vect_free(&alpha);
  pnl_vect_free(&x);
  pnl_vect_free(&t);
  pnl_vect_free(&V);
  pnl_vect_free(&D);
  pnl_vect_free(&lower);
  pnl_vect_free(&upper);
  pnl_mat_free(&X);
}
Exemple #16
0
int MCGlassermanKim(double S0, NumFunc_1  *p, double T, double r, double q, double v0,double kappa,double theta,double sigma,double rho,int Nmc,int generator,double *ptprice, double *ptdelta,double *error_price)
{
   //------------------Declaration of variable
  int j,call_put;
  PnlVect* vv;
  double tmp1, tmp, tmp2, tmp3;
  double tmpvar;
  int  init_mc;
  double mt,sigmat;
  double d1,d2;
  double epsilon;
  double K;

  if ((p->Compute)==&Call)
    call_put=0;
  else
     call_put=1;
  K=p->Par[0].Val.V_PDOUBLE;
  
  //-----------------Initialization of variable
  vv = pnl_vect_create_from_double(2,0.);
  pnl_vect_set(vv,0,v0);
  epsilon = 0.01;
  init_mc= pnl_rand_init(generator,1,(long)Nmc);
  //-----------------Operation begins
  tmp=0.;
  tmp2=0.;
  tmpvar=0.;
  for(j=1;j<= Nmc;j++)
    {
     pnl_vect_set(vv,0,v0);
     pnl_vect_set(vv,1,0.);

     Sample_C( vv, T,  kappa,  sigma,  theta , generator);

     mt= (r-q -kappa*theta*rho/sigma) *T + rho*(pnl_vect_get(vv,0)-v0)/sigma+(kappa*rho/sigma-0.5)*pnl_vect_get(vv,1);

     sigmat = sqrt((1-rho*rho)*pnl_vect_get(vv,1));

    
     
     if(call_put==0)//call pricing
       {
	 d1 = (log(S0/K)+mt)/sigmat+ sigmat;
	 d2 = d1 - sigmat;
	 tmp1 = S0*exp(mt-r*T+0.5*sigmat*sigmat)*cdf_nor(d1)-K*exp(-r*T)*cdf_nor(d2);
	 
	 d1 = (log((S0+epsilon)/K)+mt)/sigmat+ sigmat;
	 d2 = d1 - sigmat;
	 tmp3 = (S0+epsilon)*exp(mt-r*T+0.5*sigmat*sigmat)*cdf_nor(d1)-K*exp(-r*T)*cdf_nor(d2);
	
       }
     else
       {
	 d1 = (log(S0/K)+mt)/sigmat+ sigmat;
	 d2 = d1 - sigmat;
	 tmp1 = K*exp(-r*T)*(1.-cdf_nor(d2))-S0*(1.-exp(mt-r*T+0.5*sigmat*sigmat)*cdf_nor(d1));
	 
	 d1 = (log((S0+epsilon)/K)+mt)/sigmat+ sigmat;
	 d2 = d1 - sigmat;
	 tmp3 =  K*exp(-r*T)*(1.-cdf_nor(d2))-(S0+epsilon)*(1.-exp(mt-r*T+0.5*sigmat*sigmat)*cdf_nor(d1));
       }
     
     tmp = tmp1 +tmp;
     tmp2 = tmp3+ tmp2;

     //--------------confidence interval
     tmpvar = tmp1*tmp1+tmpvar;
    }
 

  tmp  = tmp /((double)Nmc);
  tmp2 = tmp2/ ((double)Nmc);
  tmpvar = tmpvar/((double) Nmc) - tmp*tmp;
  
  *ptprice = tmp;  
  *ptdelta = (tmp2-tmp) /epsilon;
  *error_price=sqrt(tmpvar/((double)Nmc));

  //printf("the interval of confidence is +/- %f\n", 2.* sqrt(tmpvar/((double) Nmc)));

  //-----------Free Memory
  pnl_vect_free(&vv);
  
  return init_mc;
}
Exemple #17
0
/**
 * compute the paths from vector which contains historical price and stock the result in a matrix with dimensions (T+1)*N for GARCH model
 * @param[in] h vector which contain all values history of price
 * @param[out] path matrix stock all path after compute
 * @param[in] T Exercise time
 * @param[in] alpha_zero  garch parameter
 * @param[in] alpha_one  garch parameter
 * @param[in] interest interest rate
 * @param[in] lambda the constant unit risk premium
 * @param[in] beta_one parameter garch
 * @param[in] type_generator the type of generator for random number
 * @return OK if ok otherwise return FAIL
 */
static int calculate_path(const PnlVect* h,PnlMat* path,double interest,int frequency,int N,int T,double alpha_zero,double alpha_one,double lambda,double beta_one,int type_generator)
{

  double sigma,s,sigma_t;
  int size;//size of vector
  double s_t;//price at time t
  double s_0;//price init
  double presigma=alpha_zero/(1-beta_one-alpha_one*(1+pow(lambda,2)));
  double preepsilon=0;
  PnlMat* eps;//matrix contains all variables epsilon with value random
  PnlMat* array_sigma;
  int dimension=N;//colum of matrix
  int samples;//row of matrix
  int i,j;


  interest=(frequency*interest)/252.;
  size=h->size;
  s_0=pnl_vect_get(h,0);
  eps=pnl_mat_create(T-size+1,N);//matrix contains all variables epsilon with value random
  array_sigma=pnl_mat_create(T-size+1,N);
  samples=T-size+1;
  pnl_rand_init(type_generator,dimension,samples);
  pnl_mat_rand_normal(eps,samples,dimension,type_generator);


  if(size==1)
    {
      s_t=s_0;
    }
  else
    {
      s_t=pnl_vect_get(h,size-1);
    }
  if(size>1)
    {
      for(i=0;i<size-1;i++)
        {
          presigma=sqrt(alpha_zero+alpha_one*pow((presigma*preepsilon-lambda*presigma),2)+beta_one*pow(presigma,2));
          preepsilon=(1/presigma)*(log(pnl_vect_get(h,i+1)/pnl_vect_get(h,i))-interest+0.5*pow(presigma,2));
        }
    }

  for(i=0;i<dimension;i++)
    {
      for(j=0;j<samples;j++)
        {
          if(j==0)
            {
              sigma=presigma;
              pnl_mat_set(array_sigma,0,i,sigma);
              if(size>1)
                {
                  s=s_t*pow(M_E,(interest-0.5*pow(pnl_mat_get(array_sigma,0,i),2)+pnl_mat_get(array_sigma,0,i)*preepsilon));
                }
              else
                {
                  s=s_0*pow(M_E,(interest-0.5*pow(pnl_mat_get(array_sigma,0,i),2)+pnl_mat_get(array_sigma,0,i)*pnl_mat_get(eps,0,i)));
                }
              pnl_mat_set(path,0,i,s);
            }
          else
            {
              sigma_t=pnl_mat_get(array_sigma,j-1,i);

              sigma=sqrt(alpha_zero+alpha_one*pow((sigma_t*pnl_mat_get(eps,j-1,i)-lambda*sigma_t),2)+beta_one*pow(sigma_t,2));

              pnl_mat_set(array_sigma,j,i,sigma);
              s=pnl_mat_get(path,j-1,i)*pow(M_E,(interest-0.5*pow(sigma,2)+sigma*pnl_mat_get(eps,j,i)));
              pnl_mat_set(path,j,i,s);
            }
        }
    }

  pnl_mat_free(&eps);
  pnl_mat_free(&array_sigma);
  return OK;
}
// Auxiliary gradient of function Cost, used in routine lowlinearprice :
static void Gradcost(PnlVect *ksi, PnlVect *g)
{
  int i,j,k;
  double normv=0, s;
  for (i=0; i<Dim+1; i++)
    {
      double ksi_i = pnl_vect_get (ksi,  i);
      normv += ksi_i * ksi_i;
    }
  normv=sqrt(normv);
  pnl_vect_set (g,  Dim+1,  0);
  
  for(j=0; j<Dim+1;j++){
    pnl_vect_set (g,  j,  0.);
    for(i=0;i<Dim+1;i++){
      double tmp=0;
      for(k=0; k<Dim+1;k++){
        tmp+=pnl_mat_get (Rac_C,  i,  k) * pnl_vect_get (ksi,  k);
      }
      s=pnl_normal_density(pnl_vect_get (ksi,  Dim+1) + pnl_vect_get (Sigma,  i) *
                  tmp*sqrt(Echeance)/normv);
      s*=pnl_vect_get (Eps,  i) * pnl_vect_get (X,  i);
      if(j==Dim)
        pnl_vect_set (g, Dim+1, pnl_vect_get (g,  Dim+1) + s);
      s*=pnl_vect_get (Sigma,  i) * sqrt(Echeance)/normv;
      s*=pnl_mat_get (Rac_C,  i,  j) - pnl_vect_get (ksi, j) *tmp/(normv*normv);
      pnl_vect_set (g, j, pnl_vect_get (g,  j) + s);
    }
    pnl_vect_set (g , j , -pnl_vect_get (g,  j));
  }
  pnl_vect_set (g , Dim+1 , -pnl_vect_get (g,  Dim+1));
}
Exemple #19
0
void calibToVIXSmiles(double k1, double k2, double Theta , double RhoXY, params *p, FILE* MarketData, FILE* OUTOMEGA)
{
char chaine[TAILLE_MAX] = "";
 int NumberMat,i,j;
PnlMat *Data;
PnlVect *aux;
PnlMat *OMEGA;
double varStateProces,T, Delta;

 if(MarketData != NULL)
    {
if(fgets(chaine, TAILLE_MAX, MarketData) != NULL)
i=0;
//LiborNumber = (int)atof ( chaine );
if(fgets(chaine, TAILLE_MAX, MarketData) != NULL)
NumberMat = (int) atof ( chaine );

Data = pnl_mat_create (NumberMat,7);
OMEGA = pnl_mat_create (2*NumberMat,3);
aux = pnl_vect_create (7);


for(j=0;j<NumberMat;j++)
{
	if(fgets(chaine, TAILLE_MAX, MarketData) != NULL) 
        	{
		 RowFromFile(chaine, NumberMat, aux);
		  for(i=0;i<7;i++)
		  { 
		   pnl_mat_set(Data,j,i,pnl_vect_get(aux,i)/100.0);
		   
		  }

        
		}
}

        fclose(MarketData);
    } 
 
for(i=0;i<NumberMat;i++)
{
p->VarianceCurve=pnl_mat_get(Data,i,1);
p->VIXFuture =pnl_mat_get(Data,i,2);
p->Strike  =pnl_mat_get(Data,i,3);
p->PutVIX  =pnl_mat_get(Data,i,4);

calibSkew(pnl_mat_get(Data,i,5), pnl_mat_get(Data,i,6), p);

if(i<NumberMat-1)
{
T = pnl_mat_get(Data,i+1,0);
Delta = pnl_mat_get(Data,i+1,0) - pnl_mat_get(Data,i,0);
}
else
{
Delta = pnl_mat_get(Data,i,0) - pnl_mat_get(Data,i-1,0);
T = pnl_mat_get(Data,i,0)+ Delta;

}
varStateProces = calcul_var(T, Delta,  k1,  k2,  Theta ,  RhoXY);
	
pnl_mat_set(OMEGA,2*i,0, T-Delta);
pnl_mat_set(OMEGA,2*i,1, p->Omega1);
 pnl_mat_set(OMEGA,2*i,2, p->VarianceCurve);


pnl_mat_set(OMEGA,2*i+1,0, T-p->Gamma*Delta);
pnl_mat_set(OMEGA,2*i+1,1, p->Omega2);
pnl_mat_set(OMEGA,2*i+1,2, p->VarianceCurve);

}
if (OUTOMEGA != NULL)
    {
fprintf( OUTOMEGA, "%d \n", 2*NumberMat ); // Ecriture du caractère A
for(i=0;i<2*NumberMat;i++)
        fprintf( OUTOMEGA, "%f \t %f \t %f \n", pnl_mat_get(OMEGA,i,0), pnl_mat_get(OMEGA,i,1), pnl_mat_get(OMEGA,i,2)); // Ecriture du caractère A
        fclose(OUTOMEGA);
    }

//pnl_mat_print(OMEGA);
}
static void prix_en_0_ls(double *res_prix, PnlMat *asset, int M, int N, int N_trading, double spot, double T, param *P, PnlBasis *basis)
{
  PnlMat *V, *res_beta, *res_no_call;
  PnlMatInt *H, *mod_H;
  PnlVectInt *res_zeta, *res_tau,*res_theta;
  PnlVect *tmp_prix;
  int j, i, zeta_j, tau_j, theta_j;
  double sprix,s;
  double h=T/N;
  //initialisation 
  V=pnl_mat_new();
  res_no_call=pnl_mat_new();
  res_beta=pnl_mat_new();
  res_zeta=pnl_vect_int_new();
  res_theta=pnl_vect_int_new();
  res_tau=pnl_vect_int_new();
  tmp_prix=pnl_vect_create(M);
  H=pnl_mat_int_new();
  mod_H=pnl_mat_int_new();

  //calcul du vecteur H
  calcul_H(H,asset,M,N,N_trading,spot,P);
  calcul_mod_H(mod_H,H,M,N,N_trading,P);
  //calcul du vecteur theta
  theta(res_theta,mod_H,M,N,N_trading,P);

  //calcul du prix_no_call protection
  prix_no_call(res_no_call,M,N,asset,spot,T,P,basis);

  //calcul du prix standard protection
  prix(V,res_no_call,M,N,asset,res_theta,spot,T,P,basis);
  //calcul de tau, zeta et beta
  tau(res_tau,M,N,V,asset,res_theta,P);
  zeta(res_zeta,res_tau,res_theta);
  beta(res_beta,spot,asset,T,N,P);
  //calcul de la somme Monte Carlo
  for(j=0;j<M;j++)
    {
      s=0;
      tau_j=pnl_vect_int_get(res_tau,j);
      theta_j=pnl_vect_int_get(res_theta,j);
      zeta_j=pnl_vect_int_get(res_zeta,j);
      if(tau_j<theta_j)
        {
          pnl_vect_set(tmp_prix,j,pnl_mat_get(res_beta,zeta_j,j)*low(pnl_mat_get(asset,tau_j,j),P));
        }
      else
        {
          pnl_vect_set(tmp_prix,j,pnl_mat_get(res_beta,zeta_j,j)*pnl_mat_get(res_no_call,theta_j,j));
        }
      
      for(i=1;i<=zeta_j;i++) s=s+h*pnl_mat_get(res_beta,i,j)*c(pnl_mat_get(asset,i,j),spot,P);
      pnl_vect_set(tmp_prix,j,pnl_vect_get(tmp_prix,j)+s);    
    }
  sprix=pnl_vect_sum(tmp_prix);
  
  pnl_mat_free(&V);
  pnl_mat_free(&res_beta);
  pnl_mat_int_free(&H);
  pnl_mat_int_free(&mod_H);
  pnl_vect_int_free(&res_zeta);
  pnl_vect_int_free(&res_tau);
  pnl_vect_int_free(&res_theta);
  pnl_vect_free(&tmp_prix);
  *res_prix=sprix/M;
}