/// Price at time "s" of a ZC bond maturing at "T" using a trinomial tree.
static double tr_hw1d_zcbond(TreeShortRate* Meth, ModelParameters* ModelParam, ZCMarketData* ZCMarket, double T)
{
    int index_last, index_first;
    double OptionPrice;

    PnlVect* OptionPriceVect1; // Matrix of prices of the option at i
    PnlVect* OptionPriceVect2; // Matrix of prices of the option at i+1
    OptionPriceVect1 = pnl_vect_create(1);
    OptionPriceVect2 = pnl_vect_create(1);


    ///****************** Computation of the vector of payoff at the maturity of the option *******************///
    ZCBond_InitialPayoffHW1D(Meth, OptionPriceVect2);

    ///****************** Backward computation of the option price until time 0 *******************///
    index_last = Meth->Ngrid;
    index_first = 0;

    BackwardIteration(Meth, ModelParam, OptionPriceVect1, OptionPriceVect2, index_last, index_first, &func_model_hw1d);

    OptionPrice = GET(OptionPriceVect1, 0);

    pnl_vect_free(& OptionPriceVect1);
    pnl_vect_free(& OptionPriceVect2);

    return OptionPrice;

}
static void triadiag_scalar_prod_test ()
{
  PnlVect *y, *x;
  PnlTridiagMat *M;
  PnlMat *full;
  int n = 5;
  int gen = PNL_RNG_MERSENNE_RANDOM_SEED;


  pnl_rand_init (gen, 1, 1);
  x = pnl_vect_create (n);
  y = pnl_vect_create (n);
  pnl_vect_rand_normal (x, n, gen);
  pnl_vect_rand_normal (y, n, gen);
  M = create_random_tridiag (n, gen);
  full = pnl_tridiag_mat_to_mat (M);
  pnl_test_eq_abs ( pnl_tridiag_mat_scalar_prod (M, x, y), 
                    pnl_mat_scalar_prod (full, x, y),
                    1E-12, "tridiag_mat_scalar_prod", "");

  
  pnl_vect_free (&x);
  pnl_vect_free (&y);
  pnl_tridiag_mat_free (&M);
  pnl_mat_free (&full); 
}
int CALC(AP_CarmonaDurrleman)(void *Opt, void *Mod, PricingMethod *Met)
{
  TYPEOPT* ptOpt=(TYPEOPT*)Opt;
  TYPEMOD* ptMod=(TYPEMOD*)Mod;
  double r;
  int i, res;
  PnlVect *divid = pnl_vect_create(ptMod->Size.Val.V_PINT);
  PnlVect *spot, *sig;
  
  spot = pnl_vect_compact_to_pnl_vect (ptMod->S0.Val.V_PNLVECTCOMPACT);
  sig = pnl_vect_compact_to_pnl_vect (ptMod->Sigma.Val.V_PNLVECTCOMPACT);
  
  for(i=0; i<ptMod->Size.Val.V_PINT; i++)
    pnl_vect_set (divid, i,
           log(1.+ pnl_vect_compact_get (ptMod->Divid.Val.V_PNLVECTCOMPACT, i)/100.));

  r= log(1.+ptMod->R.Val.V_DOUBLE/100.);

  res=ap_carmonadurrleman(spot,
                          ptOpt->PayOff.Val.V_NUMFUNC_ND,
                          ptOpt->Maturity.Val.V_DATE-ptMod->T.Val.V_DATE,
                          r, divid, sig,
                          ptMod->Rho.Val.V_DOUBLE,
                          &(Met->Res[0].Val.V_DOUBLE),Met->Res[1].Val.V_PNLVECT);
  pnl_vect_free(&divid);
  pnl_vect_free (&spot);
  pnl_vect_free (&sig);
  
  return res;
}  
static void tridiag_lu_syslin_test ()
{
  PnlVect *b, *x, *Mx;
  PnlTridiagMat *M;
  PnlTridiagMatLU *LU;
  int n = 5;
  int gen = PNL_RNG_MERSENNE_RANDOM_SEED;

  pnl_rand_init (gen, 1, 1);
  x = pnl_vect_create (n);
  b = pnl_vect_create (n);
  pnl_vect_rand_normal (b, n, gen);
  M = create_random_tridiag (n, gen);

  LU = pnl_tridiag_mat_lu_new ();
  pnl_tridiag_mat_lu_compute (LU, M);
  pnl_tridiag_mat_lu_syslin (x, LU, b);
  Mx = pnl_tridiag_mat_mult_vect (M, x);
  pnl_test_vect_eq_abs (Mx, b, 1E-12, "tridiag_mat_syslin", "");

  pnl_vect_free (&x);
  pnl_vect_free (&Mx);
  pnl_vect_free (&b);
  pnl_tridiag_mat_free (&M);
  pnl_tridiag_mat_lu_free (&LU);
}
static void tridiag_mv_test ()
{
  PnlVect *y, *x, *Fy;
  PnlMat *FM;
  PnlTridiagMat *M;
  int n = 5;
  int gen = PNL_RNG_MERSENNE_RANDOM_SEED;

  pnl_rand_init (gen, 1, 1);
  x = pnl_vect_create (n);
  y = pnl_vect_create (n);
  pnl_vect_rand_normal (x, n, gen);
  M = create_random_tridiag (n, gen);
  FM = pnl_tridiag_mat_to_mat (M);

  pnl_tridiag_mat_mult_vect_inplace (y, M, x);
  Fy = pnl_mat_mult_vect (FM, x);
  pnl_test_vect_eq_abs (y, Fy, 1E-18, "tridiag_mat_mutl_vect", "");

  pnl_vect_free (&x);
  pnl_vect_free (&y);
  pnl_vect_free (&Fy);
  pnl_mat_free (&FM);
  pnl_tridiag_mat_free (&M);
}
static void tridiag_lAxpby_test ()
{
  PnlVect *y, *x, *Fy;
  PnlTridiagMat *M;
  PnlMat *FM;
  int n = 5;
  int gen = PNL_RNG_MERSENNE_RANDOM_SEED;

  pnl_rand_init (gen, 1, 1);
  x = pnl_vect_create (n);
  y = pnl_vect_create (n);
  pnl_vect_rand_normal (x, n, gen);
  pnl_vect_rand_normal (y, n, gen);
  Fy = pnl_vect_copy (y);
  M = create_random_tridiag (n, gen);
  FM = pnl_tridiag_mat_to_mat (M);

  pnl_tridiag_mat_lAxpby (1.5, M, x, 3., y);
  pnl_mat_lAxpby (1.5, FM, x, 3., Fy);
  pnl_test_vect_eq_abs (y, Fy, 1E-12, "tridiag_mat_lAxpby", "");

  pnl_vect_free (&x);
  pnl_vect_free (&y);
  pnl_vect_free (&Fy);
  pnl_mat_free (&FM);
  pnl_tridiag_mat_free (&M);
}
Exemple #7
0
/*
 * example of how to use  pnl_basis_fit_ls to regress on a basis.
 * regression of the exponential function on the grid [0:0.05:5]
 */
static void exp_regression2()
{
  int n, basis_name, basis_dim, space_dim;
  int i;
  double a, b, h, err;
  PnlMat *t;
  PnlVect *y;
  PnlVect *alpha;

  PnlBasis *basis;


  alpha = pnl_vect_create (0);

  /* creating the grid */
  a=0.0; b=5.0;
  n = 100;
  h = (b-a)/n;
  t = pnl_mat_create_from_double (n+1, 1, h);
  pnl_mat_set (t, 0, 0, 0.0);
  pnl_mat_cumsum (t, 'r');

  /* creating the values of exp on the grid */
  y = pnl_vect_create (n+1);
  for ( i=0 ; i<n+1 ; i++ )
    {
      pnl_vect_set (y, i, function(pnl_mat_get(t, i, 0)));
    }


  basis_name = PNL_BASIS_HERMITIAN; /* PNL_BASIS_TCHEBYCHEV; */
  space_dim = 1; /* real valued basis */
  basis_dim = 5; /* number of elements in the basis */

  basis = pnl_basis_create (basis_name, basis_dim, space_dim);

  pnl_basis_fit_ls (basis, alpha, t, y);
  if ( verbose )
    {
      printf("coefficients of the decomposition : ");
      pnl_vect_print (alpha);
    }
  /* computing the infinity norm of the error */
  err = 0.;
  for (i=0; i<t->m; i++)
    {
      double tmp = function(pnl_mat_get(t, i, 0)) -
        pnl_basis_eval (basis,alpha, pnl_mat_lget(t, i, 0));
      if (fabs(tmp) > err) err = fabs(tmp);
    }

  pnl_test_eq_abs (err, 1.812972, 1E-5, "pnl_basis_eval", "exponential function on [0:0.05:5]");

  pnl_basis_free (&basis);
  pnl_mat_free (&t);
  pnl_vect_free (&y);
  pnl_vect_free (&alpha);
}
Exemple #8
0
static void test_hybrX ()
{
  int j, n, maxfev, info, nfev;
  double xtol, fnorm;
  PnlVect *x, *fvec, *diag;
  PnlRnFuncRnDFunc f;

  n = 9;
  x = pnl_vect_create (n);
  fvec = pnl_vect_create (n);
  diag = pnl_vect_create (n);

  /* the following starting values provide a rough solution. */
  pnl_vect_set_double (x, -1);

  /* default value for xtol */
  xtol = 0;

  maxfev = 2000;
  pnl_vect_set_double (diag, 1);


  /*
   * Test without Jacobian
   */
  printf ("Test of pnl_root_fsolve without user supplied Jacobian.\n\n");
  f.function = fcn_fsolve;
  f.Dfunction = NULL;
  f.params = NULL;
  info = pnl_root_fsolve (&f, x, fvec, xtol, maxfev, &nfev, diag, FALSE);
  fnorm = pnl_vect_norm_two(fvec);
  printf("     final l2 norm of the residuals %15.7g\n\n", fnorm);
  printf("     number of function evaluations  %10i\n\n", nfev);
  printf("     exit parameter                  %10i\n\n", info);
  printf("     final approximate solution\n");
  for (j=1; j<=n; j++) printf("%s%15.7g", j%3==1?"\n     ":"", GET(x,j-1));
  printf("\n\n");
  
  /*
   * Test with Jacobian
   */
  printf ("Test of pnl_root_fsolve without user supplied Jacobian.\n\n");
  f.function = fcn_fsolve;
  f.Dfunction = Dfcn_fsolve;
  f.params = NULL;
  info = pnl_root_fsolve (&f, x, fvec, xtol, maxfev, &nfev, diag, FALSE);
  fnorm = pnl_vect_norm_two(fvec);
  printf("     final l2 norm of the residuals %15.7g\n\n", fnorm);
  printf("     number of function evaluations  %10i\n\n", nfev);
  printf("     exit parameter                  %10i\n\n", info);
  printf("     final approximate solution\n");
  for (j=1; j<=n; j++) printf("%s%15.7g", j%3==1?"\n     ":"", GET(x,j-1));
  printf("\n\n");

  pnl_vect_free (&x);
  pnl_vect_free (&fvec);
  pnl_vect_free (&diag);
}
Exemple #9
0
static void test_lmdif ()
{
  int m, n, info, nfev, maxfev;
  double tol, fnorm;
  PnlVect *x, *fvec;
  PnlRnFuncRmDFunc f;

  m = 15;
  n = 3;

  x = pnl_vect_create (n);
  fvec = pnl_vect_create (m);

  /* the following starting values provide a rough fit. */

  pnl_vect_set_double (x, 1.);
  /* default vlaues */
  tol = 0;
  maxfev = 0;

  /*
   * Test without user supplied Jacobian
   */
  printf ("Test of pnl_root_fsolve_lsq without user supplied Jacobian.\n\n");
  f.function = fcn_lsq;
  f.Dfunction = NULL;
  f.params = NULL;
  info = pnl_root_fsolve_lsq(&f, x, m, fvec, tol, tol, 0., maxfev, &nfev, NULL, TRUE);

  fnorm = pnl_vect_norm_two(fvec);

  printf("      final l2 norm of the residuals%15.7f\n\n",fnorm);
  printf("      exit parameter                %10i\n\n", info);
  printf("      final approximate solution\n\n %15.7f%15.7f%15.7f\n\n",
	 GET(x,0), GET(x,1), GET(x,2));

  /*
   * Test with user supplied Jacobian
   */
  printf ("Test of pnl_root_fsolve_lsq with user supplied Jacobian.\n\n");
  f.function = fcn_lsq;
  f.Dfunction = Dfcn_lsq;
  f.params = NULL;
  info = pnl_root_fsolve_lsq(&f, x, m, fvec, tol, tol, 0., maxfev, &nfev, NULL, TRUE);

  fnorm = pnl_vect_norm_two(fvec);

  printf("      final l2 norm of the residuals%15.7f\n\n",fnorm);
  printf("      exit parameter                %10i\n\n", info);
  printf("      final approximate solution\n\n %15.7f%15.7f%15.7f\n\n",
	 GET(x,0), GET(x,1), GET(x,2));


  pnl_vect_free (&x);
  pnl_vect_free (&fvec);
}
int DeleteZCMarketData(ZCMarketData* ZCMarket)
{
    if(ZCMarket->FlatOrMarket!=0)
    {
        pnl_vect_free(&(ZCMarket->tm));
        pnl_vect_free(&(ZCMarket->Pm));
    }

    return 1;
}
Exemple #11
0
static PnlTridiagMat* create_random_tridiag (n, gen)
{
  PnlVect *dl, *du, *d;
  PnlTridiagMat *M;
  d = pnl_vect_create (n);
  du = pnl_vect_create (n);
  dl = pnl_vect_create (n);
  pnl_vect_rand_uni (d, n, 0., 1., gen);
  pnl_vect_rand_uni (du, n-1, 0., 1., gen);
  pnl_vect_rand_uni (dl, n-1, 0., 1., gen);
  M = pnl_tridiag_mat_create_from_ptr (n, dl->array, d->array, du->array);
  pnl_vect_free (&d);
  pnl_vect_free (&dl);
  pnl_vect_free (&du);
  return M;
}
static int ap_carmonadurrleman(PnlVect *BS_Spot,
                               NumFunc_nd *p,
                               double OP_Maturity,
                               double BS_Interest_Rate,
                               PnlVect *BS_Dividend_Rate,
                               PnlVect *BS_Volatility,
                               double rho,
                               double *LowerPrice,
                               PnlVect *LowerDelta)
{
  int BS_Dimension = BS_Spot->size;
  int put_or_call;
  PnlVect *Weights =  pnl_vect_create_from_double (BS_Dimension, 1./BS_Dimension);
  double Strike=p->Par[0].Val.V_DOUBLE;
    
  *LowerPrice=0.;

  if ((p->Compute)==&CallBasket_nd)
    put_or_call=0;
  else
    put_or_call=1;
    
  lower_basket(put_or_call,BS_Dimension,BS_Volatility,Weights,BS_Spot,BS_Dividend_Rate,rho,BS_Interest_Rate,Strike,OP_Maturity,LowerPrice,LowerDelta);


  /*upper_basket(put_or_call,BS_Dimension,BS_Volatility->array,Weights,BS_Spot->array,BS_Dividend_Rate->array,rho,BS_Interest_Rate,Strike,OP_Maturity,Prixsup,Deltassup);*/
   
  pnl_vect_free (&Weights);
  
  return OK;
}
Exemple #13
0
static void derive_approx_fonction(PnlBasis *B, PnlVect *D, PnlVect *alpha, double t, double x)
{
  double sum0, sum1, sum2, sum3;
  double arg[2];
  PnlMat *Hes = pnl_mat_new();
  PnlVect *grad = pnl_vect_new();
  arg[0] = t; arg[1] = x;
  sum0=0.0;//calcule la valeur de la fonction
  sum1=0.0;//calcule la valeur de sa derivee en x
  sum2=0.0;//calcule la valeur de sa derivee seconde en x
  sum3=0.0;//calcule la valeur de sa derivee en t

  /* sum0 = pnl_basis_eval (B, alpha, arg);
   * sum1 = pnl_basis_eval_D (B, alpha, arg, 1);
   * sum2 = pnl_basis_eval_D2 (B, alpha, arg, 1, 1);
   * sum3 = pnl_basis_eval_D (B, alpha, arg, 0);
   *
   * LET(D,0)=sum0;
   * LET(D,1)=sum1;
   * LET(D,2)=sum2;
   * LET(D,3)=sum3; */

  pnl_basis_eval_derivs (B, alpha, arg, &sum0, grad, Hes);
  LET(D,3) = GET(grad,0);
  LET(D,1) = GET(grad,1);
  LET(D,0) = sum0;
  LET(D,2) = PNL_MGET(Hes, 1, 1);
  LET(D,4) = PNL_MGET(Hes, 0, 1);

  pnl_mat_free (&Hes);
  pnl_vect_free (&grad);

}
static void prix(PnlMat *res, PnlMat *res_no_call, int M, int N, PnlMat *asset, PnlVectInt *res_theta, double spot, double T, param *P, PnlBasis *basis)
{
  int i,j;
  double Sij,mu_ij,v0;
  PnlVect *Si,*V_iplus1,*alpha, *c_iplus1;//(ligne i de la matrice)
  PnlMat MSi;
  double h=T/N;
  Si=pnl_vect_new();
  c_iplus1=pnl_vect_create(M);
  alpha=pnl_vect_new();
  V_iplus1=pnl_vect_new();
  pnl_mat_resize(res,N+1,M);
  prix_no_call(res_no_call,M,N,asset,spot,T,P,basis);
  for(j=0;j<M;j++) pnl_mat_set(res,N,j,(pnl_mat_get(res_no_call,N,j)));
  for(i=N-1;i>=1;i--)
    {
      for(j=0;j<M;j++) pnl_vect_set(c_iplus1,j,c(pnl_mat_get(asset,i+1,j),spot,P)*h);
      pnl_mat_get_row(Si,asset,i);
      pnl_vect_mult_double(Si,1.0/spot);
      pnl_mat_get_row(V_iplus1,res,i+1);
      pnl_vect_plus_vect(V_iplus1,c_iplus1);
      MSi = pnl_mat_wrap_vect(Si);
      pnl_basis_fit_ls(basis,alpha,&MSi,V_iplus1);
      for(j=0;j<M;j++)
        {
          Sij=pnl_mat_get(asset,i,j)/spot;
          mu_ij=mu(spot,spot*Sij,P);
          if(i>=pnl_vect_int_get(res_theta,j)) { pnl_mat_set(res,i,j,pnl_mat_get(res_no_call,i,j));}
          else pnl_mat_set(res,i,j,MAX(low(spot*Sij,P),exp(-mu_ij*h)*pnl_basis_eval(basis,alpha,&Sij)));
        }
    }
  pnl_mat_get_row(V_iplus1,res,1);
  for(j=0;j<M;j++) pnl_vect_set(c_iplus1,j,c(pnl_mat_get(asset,1,j),spot,P)*h);
  pnl_vect_plus_vect(V_iplus1,c_iplus1);
  v0=pnl_vect_sum(V_iplus1)/M;
  v0=MAX(low(spot,P),exp(-mu(spot,spot,P)*h)*v0);
  for(j=0;j<M;j++)
    {
      if(pnl_vect_int_get(res_theta,j)==0) pnl_mat_set(res,0,j,pnl_mat_get(res_no_call,i,j));
      else pnl_mat_set(res,0,j,v0);
    }
  pnl_vect_free(&Si);
  pnl_vect_free(&c_iplus1);
  pnl_vect_free(&V_iplus1);
  pnl_vect_free(&alpha);
}
static int Free_AndersenStruct(AndersenStruct *andersen_struct)
{
  pnl_mat_free(&(andersen_struct->DiscountedPayoff));
  pnl_mat_free(&(andersen_struct->NumeraireValue));
  pnl_vect_free(&(andersen_struct->AndersenParams));
  pnl_vect_int_free(&(andersen_struct->AndersenIndices));

  return OK;
}
Exemple #16
0
/**
 * compute the sum of all element in the row of matrix
 *
 * @param[in] mat matrix
 * @param[in] nb_row the number of row
 * @return sum of all element in the row of matrix
 *
 */
static double sum_row_matrix(const PnlMat* mat,int nb_row)
{
  double result;

  PnlVect* V=pnl_vect_create(mat->m);
  pnl_mat_get_row(V,mat,nb_row);
  result= pnl_vect_sum(V);
  pnl_vect_free(&V);

  return result;
}
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;
}
/// Prix at time s of an option, maturing at T, on a ZC, with maturity S, using a trinomial tree.
double tr_bk1d_zcoption(TreeShortRate* Meth, ModelParameters* ModelParam, ZCMarketData* ZCMarket, double T, double S, NumFunc_1 *p, double r, int Eur_Or_Am)
{
    int  i_T;
    double OptionPrice;

    PnlVect* OptionPriceVect1; // Vector of prices of the option at time i
    PnlVect* OptionPriceVect2; // Vector of prices of the option at time i+1

    PnlVect* ZCbondPriceVect1; // Vector of prices of the option at time i
    PnlVect* ZCbondPriceVect2; // Vector of prices of the option at time i+1

    OptionPriceVect1 = pnl_vect_create(1);
    OptionPriceVect2 = pnl_vect_create(1);
    ZCbondPriceVect1 = pnl_vect_create(1);
    ZCbondPriceVect2 = pnl_vect_create(1);

   
    ///****************** Computation of the vector of payoff at the maturity of the option *******************///
    i_T = IndexTime(Meth, T); // Localisation of s on the tree

    ZCBond_InitialPayoffBK1D(Meth, ZCbondPriceVect2);

    ZCOption_BackwardIterationBK1D(Meth, ModelParam, ZCbondPriceVect1, ZCbondPriceVect2, ZCbondPriceVect1, ZCbondPriceVect2, Meth->Ngrid, i_T, p, 0);

    ZCOption_InitialPayoffBK1D(ZCbondPriceVect2, OptionPriceVect2, p);

    ///****************** Backward computation of the option price until initial time s *******************///
    ZCOption_BackwardIterationBK1D(Meth, ModelParam, ZCbondPriceVect1, ZCbondPriceVect2, OptionPriceVect1, OptionPriceVect2, i_T, 0, p, Eur_Or_Am);

    OptionPrice = GET(OptionPriceVect1, 0);

    pnl_vect_free(& OptionPriceVect1);
    pnl_vect_free(& OptionPriceVect2);
    pnl_vect_free(& ZCbondPriceVect1);
    pnl_vect_free(& ZCbondPriceVect2);

    return OptionPrice;

}// FIN de la fonction ZCOption
// 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");
}
Exemple #20
0
static void tridiag_syslin_test ()
{
  PnlVect *b, *x, *Mx;
  PnlTridiagMat *M, *Mcopy;
  int n = 5;
  int gen = PNL_RNG_MERSENNE_RANDOM_SEED;

  pnl_rand_init (gen, 1, 1);
  x = pnl_vect_create (n);
  b = pnl_vect_create (n);
  pnl_vect_rand_normal (b, n, gen);
  M = create_random_tridiag (n, gen);

  Mcopy = pnl_tridiag_mat_copy (M);
  pnl_tridiag_mat_syslin (x, M, b);
  Mx = pnl_tridiag_mat_mult_vect (Mcopy, x);
  pnl_test_vect_eq_abs (Mx, b, 1E-12, "tridiag_mat_syslin", "");

  pnl_vect_free (&x);
  pnl_vect_free (&Mx);
  pnl_vect_free (&b);
  pnl_tridiag_mat_free (&M);
  pnl_tridiag_mat_free (&Mcopy);
}
/// Backward computation of the price of a Zero Coupon Bond
static void ZCBond_BackwardIterationCIRpp1D(TreeCIRpp1D* Meth, ModelCIRpp1D* ModelParam, ZCMarketData* ZCMarket, PnlVect* OptionPriceVect1, PnlVect* OptionPriceVect2, int index_last, int index_first)
{
    double a, b, sigma;

    double delta_t, sqrt_delta_t;

    double current_rate, current_x, x_middle;

    int i, h;
    int NumberNode, index;

    PnlVect* Probas;
    Probas = pnl_vect_create(3);

    ///********* Model parameters *********///
    a = (ModelParam->MeanReversion);
    b = (ModelParam->LongTermMean);
    sigma = (ModelParam->Volatility);

    delta_t = GET(Meth->t, 1) - GET(Meth->t,0); // = t[i] - t[i-1]
    sqrt_delta_t = sqrt(delta_t);

    for(i = index_last-1; i>=index_first; i--)
    {
        NumberNode = (int) ((GET(Meth->Xmax, i) - GET(Meth->Xmin, i)) / (Meth->delta_x) + 0.1);

        pnl_vect_resize(OptionPriceVect1, NumberNode +1);  // OptionPriceVect1 := Price of the bond in the tree at time t(i)

        // Loop over the node at the time i
        for(h = 0 ; h<= NumberNode ; h++)
        {
            current_x = x_value(i, h, Meth);
            current_rate = R(current_x, sigma) + GET(Meth->alpha,i);

            x_middle = MiddleNode(Meth, i, a, b, sigma, current_x, sqrt_delta_t, Probas);

            index = (int) ((x_middle-GET(Meth->Xmin,i+1))/(Meth->delta_x) + 0.1);

            LET(OptionPriceVect1,h) = exp(-current_rate*delta_t) * ( GET(Probas,2) * GET(OptionPriceVect2, index+1) + GET(Probas,1) * GET(OptionPriceVect2, index) + GET(Probas,0) * GET(OptionPriceVect2, index-1)); // Backward computation of the bond price
        }

        pnl_vect_clone(OptionPriceVect2, OptionPriceVect1); // Copy OptionPriceVect1 in OptionPriceVect2

    } // END of the loop on i (time)

    pnl_vect_free(&Probas);
}
Exemple #22
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;
}
Exemple #23
0
/* Approximation of the call/put function by a polynomial*/
static int pol_approx(NumFunc_1  *p,PnlVect *coeff, double S0, double K, int Nb_Degree_Pol)
  {
  /* Input: NumFunc_1 *p  specifies the payoff function (Call or Put),
            PnlVect *coeff  is of dimension Nb_Degree_Pol+1, 
            S0 initial value to determine the interval where the approximation 
            is done,
            K strike, 
            Nb_Degree_Pol corresponds to the degree of the approximating 
            polynomial.
      The coefficients of the polynomial approximating the Call/Put payoff 
      function are calculated and stored in coeff in increasing order starting 
      with the coefficient corresponding to degree 0.    
   */
  PnlMat *x;
  PnlVect *y;
  PnlBasis *f;
  int dim;
  int j;
  
  dim=(int)((log(S0*10)-log(S0/10))/0.01+0.5);  /* [log(S0/10), log(S0*10)] is  
                                                   the interval of approximation*/
                                                  
  x=pnl_mat_create_from_double(dim,1,0.);     
  y=pnl_vect_create_from_double(dim,0.);

  MLET(x,0,0)=log(S0/10);
  LET(y,0)=(p->Compute)(p->Par,S0/10.);
  
 for(j=1;j<dim;j++)
  {
    MLET(x,j,0)=MGET(x,j-1,0)+0.01;                    /* grid of equally spaced points 
                                                          with distance 0.01 in interval
                                                          [log(S0/10), log(S0*10)]  */
    LET(y,j)=(p->Compute)(p->Par,exp(MGET(x,j,0)));   /*  evaluation of the payoff 
                                                          function at x */
  }
 
  f=pnl_basis_create(PNL_BASIS_CANONICAL,Nb_Degree_Pol+1,1);
  pnl_basis_fit_ls(f,coeff,x,y);
  
  pnl_basis_free (&f);
  pnl_mat_free(&x);
  pnl_vect_free(&y);

  return 1.;
  }
Exemple #24
0
/*Matrix correponding to infinitesimal generator of the Bates model */
static int matrix_computation(PnlMat *A, int m, double r, double divid, double kappa, double theta, double lambda, double mu, double gamma2, double sigmav, double rho)
{
   /* Input: PnlMat *A  is of dimension (m+1)(m+2)/2 x (m+1)(m+2)/2, 
             m corresponds to the degree of the polynomial,
             other parameters are the inputs of the Bates model.
     The procedure calculates the matrix corresponding to the infinitesimal generator of a Bates model
     applied to the polynomials x^iv^j, (i+j)<=m, where x corresponds to the 
     logprice and v to the variance. It is stored in A.               
   */
  int i,j,k,row,column;  
  PnlVect *c;

  c=pnl_vect_create_from_double(m,0.);
  moments_normal(c,m,mu,gamma2);   
     
  for(i=0;i<m+1;i++)
  {
    for(j=0;j<m-i+1;j++)
    {
      row=(i+j)*(i+j+1)/2+j;
      for(k=2;k<i+1;k++)
      {
        column=(i-k+j)*(i-k+j+1)/2+j;
        MLET(A,row,column)=(double) pnl_sf_choose (i, k)*GET(c,k-1)*lambda;
      }
      if (i >0)
      {
        MLET(A,row,((i-1+j)*(i+j)/2+j))=i*(r-divid+lambda*(mu-exp(mu+gamma2/2)+1)+j*sigmav*rho);
        MLET(A,row,((i+j)*(i+j+1)/2+j+1))=-(double)i/2;
      }
      MLET(A,row,((i+j)*(i+j+1)/2+j))=-j*kappa;
      if (j >0)
      { 
        MLET(A,row,((i+j-1)*(i+j)/2+j-1))=j*(kappa*theta+(j-1)*sigmav*sigmav/2);
      }
      if (i >1)
      {
        MLET(A,row,((i+j-1)*(i+j)/2+j+1))=(double)i*((double)i-1)/2;
      }
    }
  } 
  pnl_vect_free(&c);

 return 1.;
}
// 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 #26
0
Barrier_u :: ~Barrier_u(){
  pnl_vect_free(&Bu_);
}
Exemple #27
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 #28
0
static void regression_multid()
{
  int n, basis_name, nb_func, nb_variates, degree;
  int i, j;
  double a, b, h, err;
  PnlMat *t;
  PnlVect *y;
  PnlVect *alpha;

  PnlBasis *basis;
  alpha = pnl_vect_create (0);

  /* creating the grid */
  a=-2.0; b=2.0;
  n = 100;
  h = (b-a)/n;
  t = pnl_mat_create ((n+1)*(n+1), 2);

  /* creating the values of exp on the grid */
  y = pnl_vect_create ((n+1)*(n+1));
  for (i=0; i<n+1; i++)
    {
      for (j=0; j<n+1; j++)
        {
          pnl_mat_set (t, i*(n+1)+j, 0, a + i * h);
          pnl_mat_set (t, i*(n+1)+j, 1, a + j * h);
          pnl_vect_set (y, i*(n+1)+j, function2d(pnl_mat_lget(t, i*(n+1)+j, 0)));
        }
    }

  basis_name = PNL_BASIS_HERMITIAN;
  nb_variates = 2; /* functions with values in R^2 */
  nb_func = 15; /* number of elements in the basis */

  basis = pnl_basis_create (basis_name, nb_func, nb_variates);

  pnl_basis_fit_ls (basis, alpha, t, y);
  if ( verbose )
    {
      printf("coefficients of the decomposition : ");
      pnl_vect_print (alpha);
    }

  /* computing the infinity norm of the error */
  err = 0.;
  for (i=0; i<t->m; i++)
    {
      double tmp = function2d(pnl_mat_lget(t, i, 0)) -
        pnl_basis_eval (basis,alpha, pnl_mat_lget(t, i, 0));
      if (fabs(tmp) > err) err = fabs(tmp);
    }

  pnl_test_eq_abs (err, 0.263175, 1E-5, "pnl_basis_eval", "log (1+x[0]*x[0] + x[1]*x[1]) on [-2,2]^2");
  pnl_basis_free (&basis);

  degree = 4; /* total sum degree */
  basis = pnl_basis_create_from_degree (basis_name, degree, nb_variates);

  pnl_basis_fit_ls (basis, alpha, t, y);
  if ( verbose )
    {
      printf("coefficients of the decomposition : ");
      pnl_vect_print (alpha);
    }

  /* computing the infinity norm of the error */
  err = 0.;
  for (i=0; i<t->m; i++)
    {
      double tmp = function2d(pnl_mat_lget(t, i, 0)) -
        pnl_basis_eval (basis,alpha, pnl_mat_lget(t, i, 0));
      if (fabs(tmp) > err) err = fabs(tmp);
    }

  pnl_test_eq_abs (err, 0.263175, 1E-5, "pnl_basis_eval (sum degree)", "log (1+x[0]*x[0] + x[1]*x[1]) on [-2,2]^2");
  pnl_basis_free (&basis);

  degree = 4; /* total product degree */
  basis = pnl_basis_create_from_prod_degree (basis_name, degree, nb_variates);

  pnl_basis_fit_ls (basis, alpha, t, y);
  if ( verbose )
    {
      printf("coefficients of the decomposition : ");
      pnl_vect_print (alpha);
    }

  /* computing the infinity norm of the error */
  err = 0.;
  for (i=0; i<t->m; i++)
    {
      double tmp = function2d(pnl_mat_lget(t, i, 0)) -
        pnl_basis_eval (basis,alpha, pnl_mat_lget(t, i, 0));
      if (fabs(tmp) > err) err = fabs(tmp);
    }

  pnl_test_eq_abs (err, 0.263175, 1E-5, "pnl_basis_eval (prod degree)", "log (1+x[0]*x[0] + x[1]*x[1]) on [-2,2]^2");
  pnl_basis_free (&basis);


  pnl_mat_free (&t);
  pnl_vect_free (&y);
  pnl_vect_free (&alpha);
}
/// Backward computation of the price of a Zero Coupon Bond
static void CapFloor_BackwardIterationLRS1D(TreeLRS1D* Meth, ModelLRS1D* ModelParam, ZCMarketData* ZCMarket, PnlVect* OptionPriceVect1, PnlVect* OptionPriceVect2, int index_last, int index_first)
{
    double sigma, rho, kappa, lambda;

    int i, j, h;
    double delta_y, delta_t, sqrt_delta_t;
    double price_up, price_middle, price_down;
    double y_00, y_ih, r_ih, phi_ihj, phi_next;


    PnlVect* proba_from_ij;

    proba_from_ij = pnl_vect_create(3);


    ///********* Model parameters *********///
    kappa = (ModelParam->Kappa);
    sigma = (ModelParam->Sigma);
    rho = (ModelParam->Rho);
    lambda = (ModelParam->Lambda);

    delta_t = GET(Meth->t, 1) - GET(Meth->t,0);
    y_00 = r_to_y(ModelParam, -log(BondPrice(GET(Meth->t, 1), ZCMarket))/delta_t);

    for(i = index_last-1; i>=index_first; i--)
    {
        pnl_vect_resize(OptionPriceVect1, 6*i-3);  // OptionPriceVect1 := Price of the bond in the tree at time t(i)

        delta_t = GET(Meth->t, i+1) - GET(Meth->t,i);
        sqrt_delta_t = sqrt(delta_t);
        delta_y = lambda * sqrt_delta_t;

        for( h=0; h<=2*i; h++) /// h : numero de la box
        {
            y_ih = y_00 + (i-h) * delta_y;
            r_ih = y_to_r(ModelParam, y_ih);

            for(j=0;j<number_phi_in_box(i, h);j++) /// Boucle sur les  valeurs de phi à (i,h)
            {
                phi_ihj = phi_value(Meth, i, h, j);

                phi_next = phi_ihj * (1-2*kappa*delta_t) + SQR(sigma) * pow(y_to_r(ModelParam, y_ih), (2*rho)) * delta_t;

                price_up     = Interpolation(Meth, i+1, h  , OptionPriceVect2, phi_next);
                price_middle = Interpolation(Meth, i+1, h+1, OptionPriceVect2, phi_next);
                price_down   = Interpolation(Meth, i+1, h+2, OptionPriceVect2, phi_next);

                probabilities(GET(Meth->t,i), y_ih, phi_ihj, lambda, sqrt_delta_t, ModelParam, ZCMarket, proba_from_ij);

                LET(OptionPriceVect1, index_tree(i,h,j)) = exp(-r_ih*delta_t) * (GET(proba_from_ij,0) * price_up + GET(proba_from_ij,1) * price_middle + GET(proba_from_ij,2) * price_down );

            }
        }

        pnl_vect_clone(OptionPriceVect2, OptionPriceVect1); // Copy OptionPriceVect1 in OptionPriceVect2

    } // END of the loop on i (time)

    pnl_vect_free(&proba_from_ij);

}
static double tr_lrs1d_capfloor(TreeLRS1D* Meth, ModelLRS1D* ModelParam, ZCMarketData* ZCMarket, int NumberOfTimeStep, NumFunc_1 *p, double s, double r, double periodicity,double first_reset_date,double contract_maturity, double CapFloorFixedRate)
{
    double lambda;

    double delta_y; // delta_x1 = space step of the process x at time i ; delta_x2 same at time i+1.
    double delta_t, sqrt_delta_t; // time step

    double OptionPrice, OptionPrice1, OptionPrice2;
    int i, i_s, h_r;
    double theta;
    double y_r, y_ih, y_00, r_00;

    double Ti2, Ti1;
    int i_Ti2, i_Ti1, n;

    PnlVect* proba_from_ih;
    PnlVect* OptionPriceVect1; // Matrix of prices of the option at i
    PnlVect* OptionPriceVect2; // Matrix of prices of the option at i+1

    proba_from_ih = pnl_vect_create(3);
    OptionPriceVect1 = pnl_vect_create(1);
    OptionPriceVect2 = pnl_vect_create(1);

    ///********* Model parameters *********///
    lambda = (ModelParam->Lambda);

    ///**************** PAYOFF at the MATURITY of the OPTION : T(n-1)****************///
    Ti2 = contract_maturity;
    Ti1 = Ti2 - periodicity;

    CapFloor_InitialPayoffLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect2, p, Ti1, Ti2, CapFloorFixedRate);


    ///**************** Backward computation of the option price ****************///
    n = (int) ((contract_maturity-first_reset_date)/periodicity + 0.1);

    if(n>1)
    {
        for(i = n-2; i>=0; i--)
        {
            Ti1 = first_reset_date + i * periodicity;
            Ti2 = Ti1 + periodicity;
            i_Ti2 = indiceTimeLRS1D(Meth, Ti2);
            i_Ti1 = indiceTimeLRS1D(Meth, Ti1);

            CapFloor_BackwardIterationLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, OptionPriceVect2, i_Ti2, i_Ti1);

            CapFloor_InitialPayoffLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, p, Ti1, Ti2, CapFloorFixedRate);

            pnl_vect_plus_vect(OptionPriceVect2, OptionPriceVect1);
        }
    }

    ///****************** Price of the option at initial time s *******************///
    i_s = indiceTimeLRS1D(Meth, s); // Localisation of s on the tree

    delta_t = GET(Meth->t, 1) - GET(Meth->t,0);
    sqrt_delta_t = sqrt(delta_t);

    r_00 = -log(BondPrice(GET(Meth->t, 1), ZCMarket))/delta_t;
    y_00 = r_to_y(ModelParam, r_00);

    Ti1 = first_reset_date;
    i_Ti1 = indiceTimeLRS1D(Meth, Ti1);

    if(i_s==0) // If s=0
    {
        CapFloor_BackwardIterationLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, OptionPriceVect2, i_Ti1, 1);

        probabilities(GET(Meth->t,0), y_00, 0, lambda, sqrt_delta_t, ModelParam, ZCMarket, proba_from_ih);

        OptionPrice = exp(-r_00*delta_t) * ( GET(proba_from_ih,0) * GET(OptionPriceVect1, 0) + GET(proba_from_ih,1) * GET(OptionPriceVect1,1) + GET(proba_from_ih,2) * GET(OptionPriceVect1, 2));
    }

    else
    {   // We compute the price of the option as a linear interpolation of the prices at the nodes r(i_s,j_r) and r(i_s,j_r+1)

        delta_t = GET(Meth->t, i_s+1) - GET(Meth->t,i_s);
        sqrt_delta_t = sqrt(delta_t);
        delta_y = lambda * sqrt_delta_t;

        y_r = r_to_y(ModelParam, r);

        h_r = (int) floor(i_s - (y_r-y_00)/delta_y); // y_r between y(h_r) et y(h_r+1) : y(h_r+1) < y_r <= y(h_r)

        y_ih = y_00 + (i_s-h_r) * delta_y;

        if(h_r < 0 || h_r > 2*i_s)
        {
          printf("WARNING : Instantaneous futur spot rate is out of tree\n");
          exit(EXIT_FAILURE);
        }

        CapFloor_BackwardIterationLRS1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, OptionPriceVect2, i_Ti1, i_s);

        theta = (y_ih - y_r)/delta_y;

        OptionPrice1 = MeanPrice(Meth, i_s, h_r, OptionPriceVect2); //Interpolation(Meth, i_s, h_r  , OptionPriceVect2, phi0);

        OptionPrice2 = MeanPrice(Meth, i_s, h_r+1, OptionPriceVect2); // Interpolation(Meth, i_s, h_r+1  , OptionPriceVect2, phi0);

        OptionPrice = (1-theta) * OptionPrice1 + theta * OptionPrice2 ;
    }

    pnl_vect_free(& OptionPriceVect1);
    pnl_vect_free(& OptionPriceVect2);
    pnl_vect_free(&proba_from_ih);

    return OptionPrice;

}