Exemple #1
0
static int
x_value(TextNode * node)
{
    for (; node != NULL; node = node->next) {
        switch (node->type) {
          case Controlbitmap:
          case Inputbitmap:
          case Inputpixmap:
          case Lsquarebrace:
          case Rsquarebrace:
          case Word:
          case Verbatim:
          case Spadsrctxt:
          case Dash:
          case Punctuation:
          case VSpace:
          case HSpace:
          case Horizontalline:
          case Box:
          case Downlink:
          case Link:
          case Lispwindowlink:
          case Lisplink:
          case Unixlink:
          case Spadcall:
          case Spadcallquit:
          case Qspadcall:
          case Qspadcallquit:
          case LispDownLink:
          case LispMemoLink:
          case Lispcommand:
          case Lispcommandquit:
          case Spadlink:
          case Spaddownlink:
          case Spadmemolink:
          case Spadcommand:
          case Spadgraph:
          case Unixcommand:
          case Space:
          case SimpleBox:
          case Radiobox:
            return node->x;
          default:
#ifdef DEBUG
            fprintf(stderr, "X_value did not know x value of type %d\n", node->type);
#endif
            return x_value(node->next);
        }
    }
    return 0;
}
/// 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 #3
0
static void
center_nodes(TextNode * begin_node, TextNode * end_node)
{
    int begin_x, end_x, wmid_x, offset, mid_x;
    TextNode *node;

    end_x = text_x;
    begin_x = x_value(begin_node);
    mid_x = (int) (end_x + begin_x) / 2;
    wmid_x = (int) (right_margin + indent) / 2;

    if (mid_x > wmid_x)
        offset = 0;
    else
        offset = wmid_x - mid_x;

    for (node = begin_node; node != end_node; node = node->next)
        if (node->x > 0)
            node->x += offset;
}
Interpolator_D2 test_Heston_PDE_solution(int CONFIG_sizeDiscretization_y)
{	
	std::cout << "Model and Product Direction_Parameters" << std::endl;

	//! Heston Direction_Parameters
	double kappa = Heston_params_kappa;
	double theta = Heston_params_theta;
	double sigma = Heston_params_sigma;
	double rho   = Heston_params_rho;
	double r     = Heston_params_r;

	//! Product Direction_Parameters
	double K = Option_params_K;
	double T = Option_params_T; 

	//! FD param
	double S_max = CONFIG_S_max;  // S_max = 2*K is not efficient! 
	double v_max = CONFIG_v_max;

	//! resume: the biggest error is the time! 
	int sizeDiscretization_t = CONFIG_sizeDiscretization_t + 1;  
	int sizeDiscretization_x = CONFIG_sizeDiscretization_x + 1; 
	int sizeDiscretization_y = CONFIG_sizeDiscretization_y + 1;

 //   //! ma model
	//MaModel ma_model(Ma_params_alpha,Ma_params_sigma,Ma_params_rho);
	//Ma_Model_discret ma_model_discret(ma_model);

	//! Range and discretization
	Range range_t(0.0,  T);        
	Range range_x(0.0,  S_max);   
	Range range_y(0.0,  v_max);  


	//! non-uniform 
		//! direction t
	int t_discretization_size = 1;
	std::vector<bool>   if_nonuniform_t(t_discretization_size);//              = OPTIMIZATION_if_nonuniform_sinh_grid_x;
    std::vector<bool>   if_shift_t(t_discretization_size); //                  = OPTIMIZATION_if_shfit_grid_x;
	std::vector<double> t_nonuniform_center_c(t_discretization_size);//        = K; 
	std::vector<double> t_nonuniform_scale_param_c(t_discretization_size);//   = K/5.0; 
	std::vector<double> t_shifting_center(t_discretization_size); //            = K;

	if_nonuniform_t[0]              = OPTIMIZATION_if_nonuniform_sinh_grid_t;
    if_shift_t[0]                   = OPTIMIZATION_if_shfit_grid_t;
	t_nonuniform_center_c[0]        = 0.0; 
	t_nonuniform_scale_param_c[0]   = OPTIMIZATION_nonuniform_t_sinh_scale_param; //1.0/500.0; 
	t_shifting_center[0]            = -999999.9;

	if(if_fwd_PDE == true)
	{
		////! add second time
  //     	if_nonuniform_t.push_back(false);             //           = true;//OPTIMIZATION_if_nonuniform_sinh_grid_t;
		//if_shift_t.push_back(false)    ;              // = OPTIMIZATION_if_shfit_grid_t;
		//t_nonuniform_center_c.push_back(0.0);		  //        = 0.0; 
		//t_nonuniform_scale_param_c.push_back(1.0/50); //   = 1.0/25.0; 
		//t_shifting_center.push_back(-99999.9);        //            = -999999.9;
	}

		//! direction x
	int x_discretization_size = 1;
	std::vector<bool>   if_nonuniform_x(x_discretization_size);//              = OPTIMIZATION_if_nonuniform_sinh_grid_x;
    std::vector<bool>   if_shift_x(x_discretization_size); //                  = OPTIMIZATION_if_shfit_grid_x;
	std::vector<double> x_nonuniform_center_c(x_discretization_size);//        = K; 
	std::vector<double> x_nonuniform_scale_param_c(x_discretization_size);//   = K/5.0; 
	std::vector<double> x_shifting_center(x_discretization_size); //            = K;

	if_nonuniform_x[0]              = OPTIMIZATION_if_nonuniform_sinh_grid_x;
    if_shift_x[0]                   = OPTIMIZATION_if_shfit_grid_x;
	x_nonuniform_center_c[0]        = K; 
	x_nonuniform_scale_param_c[0]   = K/5.0; 
	x_shifting_center[0]            = K;

	if(if_fwd_PDE == true)
	{
		x_nonuniform_center_c[0]      = fwd_PDE_S0; 
		x_nonuniform_scale_param_c[0] = OPTIMIZATION_nonuniform_x_sinh_scale_param; 
		x_shifting_center[0]          = fwd_PDE_S0;
	}

		//! direction y
	int y_discretization_size = 1;
	std::vector<bool>   if_nonuniform_y(y_discretization_size);		    
    std::vector<bool>   if_shift_y(y_discretization_size);				
	std::vector<double> y_nonuniform_center_c(y_discretization_size);   
	std::vector<double> y_nonuniform_scale_param_c(y_discretization_size); 
	std::vector<double> y_shifting_center(y_discretization_size);          

	if_nonuniform_y[0]		      = OPTIMIZATION_if_nonuniform_sinh_grid_y;
    if_shift_y[0]				  = OPTIMIZATION_if_shfit_grid_y; //! for Fwd PDE
	y_nonuniform_center_c[0]      = 0.0;     
	y_nonuniform_scale_param_c[0] = OPTIMIZATION_nonuniform_y_sinh_scale_param;  // V_max/500 is the experienced choice! 
	y_shifting_center[0]          = -99999.9;

	if(if_fwd_PDE == true)
	{
		//! first dimension: 
		if_nonuniform_y[0]			  = OPTIMIZATION_if_nonuniform_sinh_grid_y; // OPTIMIZATION_if_nonuniform_sinh_grid_y;
		if_shift_y[0]				  = OPTIMIZATION_if_shfit_grid_y; // OPTIMIZATION_if_shfit_grid_y; //! for Fwd PDE
		y_nonuniform_center_c[0]      = 0.0;//Heston_params_theta;     
		y_nonuniform_scale_param_c[0] = OPTIMIZATION_nonuniform_y_sinh_scale_param; // OPTIMIZATION_nonuniform_y_sinh_scale_param; //1.0/10000.0;  // V_max/500 is the experienced choice! 
		y_shifting_center[0]          = fwd_PDE_v0;

		////! second dimension:
		//if_nonuniform_y.push_back(false);
		//if_shift_y.push_back(true);					                  
		//y_nonuniform_center_c.push_back(fwd_PDE_v0);			      
		//y_nonuniform_scale_param_c.push_back(1.0/*OPTIMIZATION_nonuniform_y_sinh_scale_param*/);
		//y_shifting_center.push_back(fwd_PDE_v0); 

		////! third
		//if_nonuniform_y.push_back(false);
		//if_shift_y.push_back(true);					                  
		//y_nonuniform_center_c.push_back(Heston_params_theta);			      
		//y_nonuniform_scale_param_c.push_back(1.0/5000.0);
		//y_shifting_center.push_back(fwd_PDE_v0);
	}

	Discretization discret( range_t, sizeDiscretization_t,  
							range_x, sizeDiscretization_x,  
							range_y, sizeDiscretization_y,
							if_nonuniform_t,  t_nonuniform_center_c,  t_nonuniform_scale_param_c,
							if_shift_t,    t_shifting_center,
							if_nonuniform_x,  x_nonuniform_center_c,  x_nonuniform_scale_param_c,
							if_shift_x,    x_shifting_center,
							if_nonuniform_y,  y_nonuniform_center_c,  y_nonuniform_scale_param_c,
							if_shift_y,    y_shifting_center);  


	//! Heston Model
	HestonModel model(r,sigma,kappa,theta,rho);
	//Heston_Model_discret heston_model_discret(model);
	//! Heston discret Model
	PDE_Model_Heston heston_model_discret(model,discret);


    //! Term Structure, Payoff 	&&  Boundary Condition
	//! Don't want to use this one, it will make error in the code ! 
	//! Because Heston model calls directly r() of Heston model :) 
	Term_Structure* cts  = NULL; //new Const_Term_Structure(-999999);  
	PayoffYuan* payoff   = new Put(K);

	//! Backward PDE
	//BoundaryCondition_Heston_Put bc(cts, payoff, model, discret);
	//! Forward PDE
	BoundaryCondition_D2_density_CONSTPTR bc (new BoundaryCondition_D2_density (model, discret,fwd_PDE_S0,fwd_PDE_v0, cts, payoff ));

	//! --------------------------------------------------
	//! 
    //!           Test PDE solver 
	//! 
	//! ---------------------------------------------------
	//! new Scheme class 
	Scheme_ADI* scheme_new_ptr = NULL;
	if(scheme_type ==1)
	{
		scheme_new_ptr= new Scheme_Yanenko(
			discret,
			heston_model_discret,
			bc
			);
	}
	else if(scheme_type ==2)
	{
		scheme_new_ptr = new Scheme_Douglas(
			discret,
			heston_model_discret,
			bc,
			scheme_douglas_theta
			);
	}
	else if (scheme_type == 3)
	{
		scheme_new_ptr = new Scheme_CS(
			discret,
			heston_model_discret,
			bc,
			scheme_douglas_theta,
			scheme_douglas_lambda
			);
	}
	else if(scheme_type == 4)
	{
		scheme_new_ptr = new Scheme_MCS(
			discret,
			heston_model_discret,
			bc,
			scheme_douglas_theta,
			scheme_douglas_lambda
			);
	}
	else if(scheme_type == 5)
	{
		scheme_new_ptr = new Scheme_HV(
			discret,
			heston_model_discret,
			bc,
			scheme_douglas_theta
			);
	}
	else
	{
	    throw ("Error in Test_PDE.cpp, scheme_type  does not take valid value");
	}

	PDE_ADI_Solver   pde_solver(*scheme_new_ptr);

	//! --------------------------------------------------
	//! 
    //!           Test PDE solver extrapolation
	//! 
	//! ---------------------------------------------------
	//PDE_ADI_Extrapolation_Solver pde_extrapolation_solver( scheme_type,
	//													   discret,
	//													   heston_model_discret,
	//													   // --- For constructing: stupid bc (Bad Bad design !!!)
	//													   cts, 
	//													   payoff,
	//													   model,
	//													   // ----
	//													   scheme_douglas_theta, 
	//													   scheme_douglas_lambda);

	clock_t t1 = clock();
	//if(DEBUG_test_PDE_solver_extrapolation == true)
	//{
	//	pde_extrapolation_solver.solve_PDE();
	//}
	//else
	{
 		pde_solver.solve_PDE();	
	}
	clock_t t2 = clock();
	cout << "time = " << (double)(t2-t1)/CLOCKS_PER_SEC << " seconds"<< endl;

	////! Fwd PDE
	////! find initial dirac point
	//int dirac_x_index = -1;
	//int dirac_y_index = -1;
	//vector<double> discret_x_tilde = discret.get_discret_x_tilde();
	//vector<double> discret_y_tilde = discret.get_discret_y_tilde();
	//for(unsigned int i=0; i<discret_x_tilde.size(); ++i)
	//{
	//	double x = discret_x_tilde[i];
	//	if(fabs(x-fwd_PDE_S0)<0.000000001)
	//	{
	//		dirac_x_index = i;  
	//		break;
	//	}
	//}
	//for(unsigned int j=0; j<discret_y_tilde.size(); ++j)
	//{
	//	double y = discret_y_tilde[j];
 //       if(fabs(y-fwd_PDE_v0)<0.000000001)
	//	{
	//		dirac_y_index = j;
	//		break;
	//	}
	//}

	//
	//double inital_proba = 1.0/4
	//	                  *( discret.get_delta_x(dirac_x_index)+discret.get_delta_x(dirac_x_index+1) )
	//					  *( discret.get_delta_y(dirac_y_index)+discret.get_delta_y(dirac_y_index+1) );
	//cout << "inital_proba  = " << inital_proba  << endl;

	double inital_proba = 1.0;

	//! check sum of probability:
	Matrix Fwd_PDE_result (pde_solver.get_result());
	Fwd_PDE_result /= inital_proba;

	double sum_proba          = 0.0;
	double sum_proba_positive = 0.0;
	double sum_proba_negative = 0.0;
	for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
	{
		int index_i = i+1;
		for( int j=0; j<discret.get_sizeDiscret_y_tilde(); ++j)
		{
			int index_j = j+1;
            double density = Fwd_PDE_result[index_i][index_j]; // then it is the density
			double coeff   = 1.0/4
		                    *( discret.get_delta_x(i)+discret.get_delta_x(i+1) )
						    *( discret.get_delta_y(j)+discret.get_delta_y(j+1) );

			double proba   = coeff*density;  
			if(density>0.0)
			{
				sum_proba_positive += coeff*density;  
			}
			else
			{
			   sum_proba_negative  += coeff*density;  
			}
		}
	}
	sum_proba = sum_proba_positive + sum_proba_negative;
	cout << " ---- |||| ---- |||| Sum_Proba          = " << sum_proba << endl;  //<< ",  sum_proba_positive = " << sum_proba_positive << " + " << "sum_proba_negative = " << sum_proba_negative << endl;
	cout << " ---- |||| ---- |||| Sum_Proba_positive = " << sum_proba_positive << endl;
	cout << " ---- |||| ---- |||| Sum_Proba_negative = " << sum_proba_negative << endl;
	cout << " ---- |||| ---- |||| Sum_total_error    = " << fabs(sum_proba_positive - 1) + fabs(sum_proba_negative) << endl;


	//! analytical price
	int num_K = 17;
	double step = 0.05;
	//double K_start = Option_params_K*(num_K-1)/

	vector<double> v_K(num_K);
	vector<double> v_analytical_price(num_K);

	cout << "strike vector: "<< endl;
	cout << Option_params_K << endl;
	v_K[0] = Option_params_K;
	for(unsigned int i=1; i<v_K.size()-1; i+=2)
	{
		v_K[i]   =  Option_params_K *(1+i*step);
		v_K[i+1] =  Option_params_K *(1-i*step);
		cout << v_K[i] << endl;
		cout << v_K[i+1] << endl;
	}

	for(unsigned int i=0; i<v_K.size(); ++i)
	{
		Heston_analytical_pricer pricer_ana(v_K[i]);
		v_analytical_price[i] = pricer_ana.heston_put(fwd_PDE_S0,fwd_PDE_v0, 1024*10);

	}

	vector<double> v_numerical_price(num_K);
	//! first numerical integration price
	for(unsigned int kk=0; kk<v_K.size()-1; ++kk)
	{
		    double KK = v_K[kk];
			double sum_price          = 0.0;
			double sum_price_positive = 0.0;
			double sum_price_negative = 0.0;
			for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
			{
				int index_i = i+1;
				double payoff = 1;
				double x = discret.get_discret_x(index_i);
				if(x<KK)
					payoff = KK - x;
				else
					payoff = 0.0;

				for( int j=0; j<discret.get_sizeDiscret_y_tilde(); ++j)
				{
					int index_j = j+1;
					double density = Fwd_PDE_result[index_i][index_j]; // then it is the density
					double coeff   = 1.0/4
									*( discret.get_delta_x(i)+discret.get_delta_x(i+1) )
									*( discret.get_delta_y(j)+discret.get_delta_y(j+1) );

					double proba   = coeff*density;  
					if(density>0.0)
					{
						sum_price_positive += coeff*density*payoff;  
					}
					else
					{
					   sum_price_negative  += coeff*density*payoff;  
					}
				}
			}
			sum_price_positive *= exp(-Option_params_T*Heston_params_r);
			sum_price_negative *= exp(-Option_params_T*Heston_params_r);
			sum_price = sum_price_positive + sum_price_negative;
			v_numerical_price[kk] = sum_price;
			cout << "1st numerical price = " << sum_price << endl;
			//cout << "price_numerical_positive  = " << sum_price_positive << endl;
			//cout << "price_numerical_negative  = " << sum_price_negative << endl;


			//!second numerical integration price
			vector<double> x_grid(discret.get_discret_x_tilde());
			vector<double> y_grid(discret.get_discret_y_tilde());

			vector<double> x_value(discret.get_sizeDiscret_x_tilde(),0.0);
			vector<double> y_value(discret.get_sizeDiscret_y_tilde(),0.0);

			for(int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
			{
				int index_i = i+1;
				double payoff = 1;
				//double x = discret.get_discret_x(index_i);
				//if(x<KK)
				//	payoff = KK - x;
				//else
				//	payoff = 0.0;

				for(int j=0; j<discret.get_sizeDiscret_y_tilde(); ++j)
				{
					 int index_j = j+1;
					 y_value[j] = Fwd_PDE_result[index_i][index_j];
				}
				Interpolator interp_y(y_grid,y_value);
				x_value[i] = interp_y.calculate_integral_approximation()*payoff;
			}
			Interpolator interp_x(x_grid,x_value);
			double second_analytical_price = interp_x.calculate_integral_approximation();
			//second_analytical_price *= exp(-Option_params_T*Heston_params_r);
			cout << "2nd numerical price = " << second_analytical_price << endl;
			

			//! third numerical integration price
			double third_sum_price          = 0.0;
			vector<double> v_sum_x(discret.get_sizeDiscret_x_tilde(),0.0);
			vector<double> v_sum_x_positive(discret.get_sizeDiscret_x_tilde(),0.0);
			vector<double> v_sum_x_negative(discret.get_sizeDiscret_x_tilde(),0.0);
			for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
			{
				int index_i = i+1;
				double payoff = 1;
				//double x = discret.get_discret_x(index_i);
				//if(x<KK)
				//	payoff = KK - x;
				//else
				//	payoff = 0.0;
				double sum_x          = 0.0;
				double sum_x_positive = 0.0;
				double sum_x_negative = 0.0;
				for( int j=0; j<discret.get_sizeDiscret_y_tilde(); ++j)
				{
					int index_j = j+1;
					double density = Fwd_PDE_result[index_i][index_j]; // then it is the density
					double coeff   = ( discret.get_delta_y(j)+discret.get_delta_y(j+1) )/2;

					double proba   = coeff*density;  
					if(density>0.0)
					{
						sum_x_positive += coeff*density*payoff;  
					}
					else
					{
					   sum_x_negative  += coeff*density*payoff;  
					}
					sum_x = sum_x_positive + sum_x_negative;
				}
				v_sum_x_positive[i] = sum_x_positive;
				v_sum_x_negative[i] = sum_x_negative;
				v_sum_x[i]          = sum_x;
			}

			double hehe = 0.0;
			for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
			{
				double interval = ( discret.get_delta_x(i)+discret.get_delta_x(i+1) )/2.0;
				hehe += v_sum_x[i]*interval;
			}
			cout << "3rd numerical price = " << hehe << endl;
	}
	Interpolator_D2 interp_2d(discret.get_discret_x(), discret.get_discret_y(), Fwd_PDE_result);

			////sum_price_positive *= exp(-Option_params_T*Heston_params_r);
			////sum_price_negative *= exp(-Option_params_T*Heston_params_r);
			//sum_price = sum_price_positive + sum_price_negative;
			//cout << "price_numerical  = " << sum_price << endl;
			//cout << "price_numerical_positive  = " << sum_price_positive << endl;
			//cout << "price_numerical_negative  = " << sum_price_negative << endl;
	


	//! Print one price
	if(DEBUG_PDE_error_print_to_screen == true)
	{
		cout.precision(15); 

		int S_index = 25;
		int v_index = 10;

		double S_check = discret.get_discret_x(S_index);
		double v_check = discret.get_discret_y(v_index);

		//Matrix PDE_result       = pde_solver.get_result();
		Matrix PDE_result(1,1,0);
		//if(DEBUG_test_PDE_solver_extrapolation == true)
		//{
		//	PDE_result = pde_extrapolation_solver.get_result();
		//}
		//else
		{
		    PDE_result = pde_solver.get_result();
		}

		Heston_analytical_pricer analytical_pricer;
		vector<double> discret_x;
		discret_x.push_back(S_check);
		
		cout << "PDE's price for So=" << S_check << ", v=" << v_check <<  "   =   " << PDE_result[S_index][v_index] << endl;

		vector<double> discret_y;
		discret_y.push_back(v_check);
		Matrix analytical_price = analytical_pricer.heston_put_v(discret_x,discret_y, 1024*100);
		cout.precision(15); 
		cout << "analytical formula's price = " << analytical_price[0][0]<< endl;
	}

	if (DEBUG_PDE_error_print_to_file == true)
	{
		std::stringstream ss;
		ss << CONFIG_sizeDiscretization_y;
		string s = ss.str();
		std::string PDE_error_output_file_name = DEBUG_output_path + s + "PDE_error.csv";

		//! get PDE result
		//Matrix PDE_result       = pde_solver.get_result();
		//Matrix PDE_result(1,1,0);
		//if(DEBUG_test_PDE_solver_extrapolation == true)
		//{
		//	PDE_result = pde_extrapolation_solver.get_result();
		//}
		//else
		//{
		//    PDE_result = pde_solver.get_result();
		//}

		Matrix PDE_result = Fwd_PDE_result;

		//! get analytical result 
		Heston_analytical_pricer analytical_pricer;

		vector<double> discret_x(discret.get_discret_x());
		vector<double> discret_y(discret.get_discret_y());

		//! Backward PDE
		//double Error_S_min = 0.5 * Option_params_K;
		//double Error_S_max = 1.5 * Option_params_K;
		//double Error_v_min = 0;
		//double Error_v_max = 1.0;

		//! Fwd PDE
		double Error_S_min = 0;
		double Error_S_max = S_max; // 1.5 * Option_params_K;
		double Error_v_min = 0;
		double Error_v_max = v_max; //1.0;


		vector<double> x_vector_value;  //! For analytical price
		vector<int>    x_vector_index;  
		vector<double> y_vector_value;  //! For PDE price (index) 
		vector<int>    y_vector_index;   

		for( int i=0; i<discret.get_sizeDiscret_x_tilde(); ++i)
		{
			double x = discret_x[i];
		    if(x>=Error_S_min-0.000000001 && x <= Error_S_max+0.000000001)
			{
				x_vector_value.push_back(x);
				x_vector_index.push_back(i);
			}
		}

		for(unsigned int i=0; i<discret_y.size(); ++i)
		{
			double y = discret_y[i];
		    if(y>=Error_v_min-0.000000001 && y <= Error_v_max+0.000000001)
			{
				y_vector_value.push_back(y);
				y_vector_index.push_back(i);
			}
		}
		
		Matrix analytical_price(1,1,0.0);
		if(DEBUG_PDE_test_PDE_vs_analytical == true)
		{
			analytical_price  = analytical_pricer.heston_put_v(x_vector_value,y_vector_value);
		}
		Matrix PDE_error((int)x_vector_value.size(), (int)y_vector_value.size(),-9999.0);  
		for(unsigned int i=0; i<x_vector_value.size(); ++i)
		{
			for(unsigned int j=0; j<y_vector_value.size(); ++j)
			{
			    if(DEBUG_PDE_test_PDE_vs_analytical == true)
				{
				    PDE_error[i][j] = PDE_result[x_vector_index[i]][y_vector_index[j]] - analytical_price [i][j];
				}
				else if (DEBUG_PDE_test_only_PDE == true)
				{
				    PDE_error[i][j] = PDE_result[i][j];
				}
			}
		}
		print_result(PDE_error_output_file_name , x_vector_value, y_vector_value, PDE_error);

		//! find max error
		if(DEBUG_PDE_test_PDE_vs_analytical == true)
		{
			double max_error_value   = 0.0;
			int    max_error_index_S = 0;
			int    max_error_index_v = 0;
			for(unsigned int i=0; i<x_vector_value.size(); ++i)
			{
				for(unsigned int j=0; j<y_vector_value.size(); ++j)
				{
					if(abs(PDE_error[i][j]) > abs(max_error_value))
					{
						max_error_value = PDE_error[i][j];
						max_error_index_S = i;
						max_error_index_v = j;
					}
				}
			}
			//!!!!! I donot know why but Error !!!!  -- Max error = 17
			cout << "---- ---- ---- ---- Max_error_value is at (" << x_vector_value[max_error_index_S]<< ","<< y_vector_value[max_error_index_v] << ")   = " <<  max_error_value  << endl;
		}
	}

	for(unsigned int i=0; i<v_K.size(); ++i)
	{
		cout << "v_K[" << i << "] = "<< v_K[i] << " 's price: " << v_analytical_price[i] << " ~ " << v_numerical_price[i] << endl;
	}

	delete cts;
	delete payoff;
	//delete scheme_ptr;
	delete scheme_new_ptr;

	return interp_2d;
}
/// Price at time "s" of a ZC bond maturing at "T" using a trinomial tree.
static double tr_cirpp1d_zcbond(TreeCIRpp1D* Meth, ModelCIRpp1D* ModelParam, ZCMarketData* ZCMarket, double T, double s, double r)
{
    double sigma;
    double delta_t, delta_r;
    double current_rate, current_x;

    double theta, OptionPrice1, OptionPrice2;
    double OptionPrice;
    int i_s;
    int j_r;

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

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

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

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

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

    ///****************** Backward computation of the option price until time s*******************///

    i_s = indiceTimeCIRpp1D(Meth, s); // Localisation of s on the tree

    if(i_s==0) // If s=0
    {
        ZCBond_BackwardIterationCIRpp1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, OptionPriceVect2, Meth->Ngrid, 1);

        current_rate = R(current_x, sigma) + GET(Meth->alpha,0);

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

    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)

        j_r = (int) ((2 * sqrt(r-GET(Meth->alpha,i_s)) / sigma - GET(Meth->Xmin,i_s)) / (Meth->delta_x) + 0.1); // r between r(j_r) et r(j_r+1)

        if(j_r < 0 || j_r > (GET(Meth->Xmax,i_s)-GET(Meth->Xmin,i_s))/(Meth->delta_x)-1)
        {
          printf("WARNING : Instantaneous futur spot rate is out of tree\n");
          exit(EXIT_FAILURE);
        }

        ZCBond_BackwardIterationCIRpp1D(Meth, ModelParam, ZCMarket, OptionPriceVect1, OptionPriceVect2, Meth->Ngrid, i_s);

        current_x = x_value(i_s, j_r, Meth);

        current_rate = R(current_x, sigma) + GET(Meth->alpha,i_s);

        delta_r = R(x_value(i_s, j_r+1, Meth), sigma) - current_x;

        theta = (r - current_rate)/ delta_r ;

        OptionPrice1 = GET(OptionPriceVect1, j_r);

        OptionPrice2 = GET(OptionPriceVect1, j_r + 1);

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

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

    return OptionPrice;

}