Пример #1
0
dcomplex G(dcomplex z)
{
    int i;
    dcomplex e[10];
    dcomplex d,sum,dum;

    e[1].r =-10.0/eV2Hartree;
    e[1].i = 0.0;
    e[2].r = -5.0/eV2Hartree;
    e[2].i = 0.0;
    e[3].r = -2.0/eV2Hartree;
    e[3].i = 0.0;
    e[4].r =  5.0/eV2Hartree;
    e[4].i = 0.0;

    sum.r = 0.0;
    sum.i = 0.0;

    for (i=1; i<=4; i++) {
        d = Csub(z,e[i]);
        dum = RCdiv(1.0,d);
        sum.r += dum.r;
        sum.i += dum.i;
    }

    return sum;
}
static int compute_price(double tt, double H, double K, double r_premia, double v0, double kappa, double theta, double sigma, double rho, 
	double L, int M, int Nt )
{
	/*Variables*/
	int j, n, k;
	double r; /*continuous rate*/
	double min_log_price, max_log_price;
	double ds, dt; /*price and time discretization steps*/
	double rho_hat; /*parameter after substitution*/
	double q, factor, discount_factor; /*pde parameters*/
	double treshold = 1e-9; /* when we assume probability to be zero and switch to a different equation*/

	int k_d, k_u; /*n+1 vertice numbers, depending on [n][k]*/
	double sigma_local, gamma; /*wh factors parameters*/
	double beta_minus, beta_plus; /*wh-factors coefficients*/
	double local_barrier; /*a barrier depending on [n][k], to check crossing on each step*/

	//if (2.0 * kappa * theta < pow(sigma, 2))
	//	return 1; /*Novikov condition not satisfied, probability values could be incorrect*/
	/*Body*/
	r = log(1 + r_premia / 100);

	/*building voltree*/
	tree_v(tt, v0, kappa, theta, sigma, Nt);

	/*spacial variable. Price space construction*/
	min_log_price = L*log(0.5) - (rho / sigma)* V[Nt][Nt];
	max_log_price = L*log(2);
	ds = (max_log_price - min_log_price) / double(M);

	for (j = 0; j < M; j++)
	{
		ba_log_prices[j] = min_log_price + j*ds;
		ba_prices[j] = H*exp(ba_log_prices[j] + (rho / sigma)* V[0][0]);
	}
	dt = tt / double(Nt);
	
	/*fft frequences we'll need in every vertice of a tree*/
	fftfreq(M, ds);
	rho_hat = sqrt(1.0 - pow(rho, 2.0));
	q = 1.0 / dt + r;
	factor = pow(q*dt, -1.0);
	//discount_factor = exp(r*dt);
	discount_factor = r - rho / sigma * kappa * theta;

	/*filling F_next matrice by initial (in time T) conditions*/
	for (j = 0; j < M; j++)
		for (k = 0; k < Nt + 1; k++)
		{
			F_next[j][k] = Complex(G(H*exp(ba_log_prices[j] + (rho / sigma)* V[Nt][k]), K), 0);
		}

	/*here the main cycle starts - the backward induction procedure*/
	for (n = Nt - 1; n >= 0; n--)
	{
		printf("Processing: %d of %d\n", n, Nt-1);
		for (k = 0; k <= n; k++)
		{
			/*to calculate the binomial expectation we should use matrices from the tree method.
			After (n,k) vertice one could either get to (n+1,k_u) or (n+1, k_d). The numbers k_u and k_d could be
			read from f_up and f_down matrices, by the rule of addition, for example:
			
			f_down[i][j] = -z;
			Rd = V[i + 1][j - z]

			f_up[i][j] = z;
			Ru = V[i + 1][j + z];
			*/
			k_u = k + f_up[n][k];
			k_d = k + f_down[n][k];
			local_barrier = - (rho / sigma) * V[n][k];

			/*initial conditions of a step*/
			for (j = 0; j < M; j++)
			{
				//f_n_plus_1_k_u[j] = F[j][n+1][k_u];
				//f_n_plus_1_k_d[j] = F[j][n+1][k_d];
				f_n_plus_1_k_u[j] = F_next[j][k_u];
				f_n_plus_1_k_d[j] = F_next[j][k_d];
			}
			/*applying indicator function*/
			for (j = 0; j < M; j++)
			{
				if (ba_log_prices[j] < local_barrier)
				{
					f_n_plus_1_k_u[j].r = 0.0;
					f_n_plus_1_k_u[j].i = 0.0;
					f_n_plus_1_k_d[j].r = 0.0;
					f_n_plus_1_k_d[j].i = 0.0;
				}
			}
			if (V[n][k] >= treshold)
			{
				/*set up variance - dependent parameters for a given step*/
				sigma_local = rho_hat * sqrt(V[n][k]);
				gamma = r - 0.5 * V[n][k] - rho / sigma * kappa * (theta - V[n][k]);  /*also local*/
				/* beta_plus and beta_minus*/
				/*beta_minus = -(gamma + sqrt(gamma^2 + 2 * sigma^2 * q)) / sigma^2
					beta_plus = -(gamma - sqrt(gamma^2 + 2 * sigma^2 * q)) / sigma^2*/
				beta_minus = -(gamma + sqrt(pow(gamma,2) + 2 * pow(sigma_local,2) * q)) / pow(sigma_local,2);
				beta_plus = -(gamma - sqrt(pow(gamma,2) + 2 * pow(sigma_local,2) * q)) / pow(sigma_local,2);

				for (j = 0; j < M; j++)
				{
					/* factor functions
					phi_plus_array = ([beta_plus / (beta_plus - i * 2 * pi*xi) for xi in xi_space])
					phi_minus_array = ([-beta_minus / (-beta_minus + i * 2 * pi*xi) for xi in xi_space]) */
					phi_plus_array[j] = RCdiv(beta_plus, RCsub(beta_plus, RCmul((2.0 * PI * fftfreqs[j]), CI)));
					phi_minus_array[j] = RCdiv(-beta_minus, RCadd(-beta_minus, RCmul((2.0 * PI * fftfreqs[j]), CI)));
				}
				
				/*factorization calculation*/

				/*f_n_k_u = factor * fft.ifft(phi_minus_array *	fft.fft(
				indicator(original_prices_array, 0) * fft.ifft(phi_plus_array * fft.fft(f_n_plus_1_k_u))))*/
				for (int j = 0; j < M; j++)
				{
					f_n_plus_1_k_u_re[j] = f_n_plus_1_k_u[j].r;
					f_n_plus_1_k_u_im[j] = f_n_plus_1_k_u[j].i;

				}
				pnl_fft2(f_n_plus_1_k_u_re, f_n_plus_1_k_u_im, M);
				for (j = 0; j < M; j++) {
					/*putting complex and imaginary part together again*/
					f_n_plus_1_k_u_fft_results[j] = Complex(f_n_plus_1_k_u_re[j], f_n_plus_1_k_u_im[j]);
					/*multiplying by phi_plus*/
					f_n_plus_1_k_u_fft_results[j] = Cmul(phi_plus_array[j], f_n_plus_1_k_u_fft_results[j]);
					/*extracting imaginary and complex parts to use in further fft*/
					f_n_plus_1_k_u_fft_results_re[j] = f_n_plus_1_k_u_fft_results[j].r;
					f_n_plus_1_k_u_fft_results_im[j] = f_n_plus_1_k_u_fft_results[j].i;

				}

				pnl_ifft2(f_n_plus_1_k_u_fft_results_re, f_n_plus_1_k_u_fft_results_im, M);
				/*applying indicator function, after ifft*/
				for (j = 0; j < M; j++)
				{
					if (ba_log_prices[j] < local_barrier)
					{
						f_n_plus_1_k_u_fft_results_re[j] = 0.0;
						f_n_plus_1_k_u_fft_results_im[j] = 0.0;
					}
				}

				/*performing second fft */
				pnl_fft2(f_n_plus_1_k_u_fft_results_re, f_n_plus_1_k_u_fft_results_im, M);
				
				for (j = 0; j < M; j++) {
					/*putting complex and imaginary part together again*/
					f_n_plus_1_k_u_fft_results[j] = Complex(f_n_plus_1_k_u_fft_results_re[j], f_n_plus_1_k_u_fft_results_im[j]);
					/*multiplying by phi_minus*/
					f_n_plus_1_k_u_fft_results[j] = Cmul(phi_minus_array[j], f_n_plus_1_k_u_fft_results[j]);
					/*extracting imaginary and complex parts to use in further fft*/
					f_n_plus_1_k_u_fft_results_re[j] = f_n_plus_1_k_u_fft_results[j].r;
					f_n_plus_1_k_u_fft_results_im[j] = f_n_plus_1_k_u_fft_results[j].i;
				}

				/*the very last ifft*/
				pnl_ifft2(f_n_plus_1_k_u_fft_results_re, f_n_plus_1_k_u_fft_results_im, M);
				/*multiplying by factor*/
				for (j = 0; j < M; j++) {
					f_n_k_u[j].r = factor * f_n_plus_1_k_u_fft_results_re[j];
					f_n_k_u[j].i = factor * f_n_plus_1_k_u_fft_results_im[j];
				}

				/*f_n_k_d = factor * fft.ifft(phi_minus_array * fft.fft(
				indicator(original_prices_array, 0) * fft.ifft(phi_plus_array * fft.fft(f_n_plus_1_k_d))))*/
				for (int j = 0; j < M; j++)
				{
					f_n_plus_1_k_d_re[j] = f_n_plus_1_k_d[j].r;
					f_n_plus_1_k_d_im[j] = f_n_plus_1_k_d[j].i;

				}
				pnl_fft2(f_n_plus_1_k_d_re, f_n_plus_1_k_d_im, M);
				for (j = 0; j < M; j++) {
					/*putting complex and imaginary part together again*/
					f_n_plus_1_k_d_fft_results[j] = Complex(f_n_plus_1_k_d_re[j], f_n_plus_1_k_d_im[j]);
					/*multiplying by phi_plus*/
					f_n_plus_1_k_d_fft_results[j] = Cmul(phi_plus_array[j], f_n_plus_1_k_d_fft_results[j]);
					/*extracting imaginary and complex parts to use in further fft*/
					f_n_plus_1_k_d_fft_results_re[j] = f_n_plus_1_k_d_fft_results[j].r;
					f_n_plus_1_k_d_fft_results_im[j] = f_n_plus_1_k_d_fft_results[j].i;
				}
				pnl_ifft2(f_n_plus_1_k_d_fft_results_re, f_n_plus_1_k_d_fft_results_im, M);
				/*applying indicator function, after ifft*/
				for (j = 0; j < M; j++)
				{
					if (ba_log_prices[j] < local_barrier)
					{
						f_n_plus_1_k_d_fft_results_re[j] = 0.0;
						f_n_plus_1_k_d_fft_results_im[j] = 0.0;
					}
				}
				/*performing second fft */
				pnl_fft2(f_n_plus_1_k_d_fft_results_re, f_n_plus_1_k_d_fft_results_im, M);

				for (j = 0; j < M; j++) {
					/*putting complex and imaginary part together again*/
					f_n_plus_1_k_d_fft_results[j] = Complex(f_n_plus_1_k_d_fft_results_re[j], f_n_plus_1_k_d_fft_results_im[j]);
					/*multiplying by phi_minus*/
					f_n_plus_1_k_d_fft_results[j] = Cmul(phi_minus_array[j], f_n_plus_1_k_d_fft_results[j]);
					/*extracting imaginary and complex parts to use in further fft*/
					f_n_plus_1_k_d_fft_results_re[j] = f_n_plus_1_k_d_fft_results[j].r;
					f_n_plus_1_k_d_fft_results_im[j] = f_n_plus_1_k_d_fft_results[j].i;
				}
				/*the very last ifft*/
				pnl_ifft2(f_n_plus_1_k_d_fft_results_re, f_n_plus_1_k_d_fft_results_im, M);
				/*multiplying by factor*/
				for (j = 0; j < M; j++) {
					f_n_k_d[j].r = factor * f_n_plus_1_k_d_fft_results_re[j];
					f_n_k_d[j].i = factor * f_n_plus_1_k_d_fft_results_im[j];
				}
			}
			else if (V[n][k] < treshold)
			{
				/*applying indicator function*/
				for (j = 0; j < M; j++)
				{
					if (ba_log_prices[j] < local_barrier)
					{
						f_n_plus_1_k_u[j].r = 0.0;
						f_n_plus_1_k_u[j].i = 0.0;
						f_n_plus_1_k_d[j].r = 0.0;
						f_n_plus_1_k_d[j].i = 0.0;
					}
				}
				for (j = 0; j < M; j++)
				{
					//f_n_plus_1_k_u[j] = F[j][n + 1][k_u];
					f_n_plus_1_k_u[j] = F_next[j][k_u];
					f_n_k_u[j] = CRsub(f_n_plus_1_k_u[j], discount_factor * dt);
					f_n_k_d[j] = f_n_k_u[j];

				}
			}
			/*
            f_n_k = pd_f[n, k] * f_n_k_d + pu_f[n, k] * f_n_k_u
			*/
			for (j = 0; j < M; j++)
			{
				f_n_k[j] = Cadd(RCmul(pd_f[n][k], f_n_k_d[j]), RCmul(pu_f[n][k], f_n_k_u[j]));
				F_prev[j][k] = f_n_k[j];
			}						
		}
		for (j = 0; j < M; j++)
		{
			for (int state = 0; state < Nt; state++)
			{
				F_next[j][state] = F_prev[j][state];
				F_prev[j][state] = Complex(0,0);
			}
		}
	}
	/*Preprocessing F before showing out*/
	for (j = 0; j < M; j++)
	{
		if (ba_prices[j] <= H)
		{
			F_next[j][0].r = 0;
		}
		if (F_next[j][0].r < 0.)
		{
			F_next[j][0].r = 0;
		}
	}
	return OK;
}