static void findstats(Pos p, Ori o) { /* Recalculate cross assert and score total at 'p' */ Pos left, right; Word lword, rword; Node n; Edge e; int s; lword.n = rword.n = 0; if(EDGE(p)) return; /* find word to the left */ s = 0; for(left=PREV(p,o); HASLETTER(left); left = PREV(left,o)) ; left = NEXT(left,o); while (HASLETTER(left)) { lword.c[lword.n++] = LETTER(left); s += SCORE(left); left = NEXT(left,o); } /* find word to the right */ for(right=NEXT(p,o); HASLETTER(right); right = NEXT(right,o)) { rword.c[rword.n++] = LETTER(right); s += SCORE(right); } if(DBG) { wordprint(&lword); print("X"); wordprint(&rword); print(" [%d] ", s); } SIDE(p,o) = s; ISANCHOR(p) = true; /* calculate cross asserts */ CROSS(p,o) = 0; n = traverse(root, &lword, 0); assert(n>=0); if(n>0) do { e = dict[n++]; if ( (rword.n && isword(NODE(e), &rword)) || (!rword.n && TERM(e)) ) { CROSS(p,o) |= 1 << LET(e); DPRINT("%c, ", LET(e)+'a'); } } while (!(LAST(e))); DPRINT("\n"); }
static SCM expand_let (SCM expr, SCM env) { SCM bindings; const SCM cdr_expr = CDR (expr); const long length = scm_ilength (cdr_expr); ASSERT_SYNTAX (length >= 0, s_bad_expression, expr); ASSERT_SYNTAX (length >= 2, s_missing_expression, expr); bindings = CAR (cdr_expr); if (scm_is_symbol (bindings)) { ASSERT_SYNTAX (length >= 3, s_missing_expression, expr); return expand_named_let (expr, env); } check_bindings (bindings, expr); if (scm_is_null (bindings)) return expand_sequence (CDDR (expr), env); else { SCM var_names, var_syms, inits; transform_bindings (bindings, expr, &var_names, &var_syms, &inits); return LET (SCM_BOOL_F, var_names, var_syms, expand_exprs (inits, env), expand_sequence (CDDR (expr), expand_env_extend (env, var_names, var_syms))); } }
Barrier_u::Barrier_u(double strike, double* bu, double T, int timeStep, int size, double r, double* coeff) : Option(T, timeStep, size, r, coeff){ strike_ = strike; Bu_ = pnl_vect_create(size_); for (int i = 0; i < size_; i++){ LET(Bu_, i) = bu[i]; } }
// Scalar function to be minimized in order to get optimal parameters. static double func_to_minimize(double x, void *andersen_struct) { LET(((AndersenStruct*)andersen_struct)->AndersenParams, ((AndersenStruct*)andersen_struct)->j_start) = x; return -AmOption_Price_Andersen(andersen_struct); }
// Read the ZC price from the file "initialyield.dat" and put it in the structure "ZCMarket". void ReadMarketData(ZCMarketData* ZCMarket) { FILE* Entrees; /*File variable of the code*/ int i, etat; char ligne[20]; char* pligne; double p, tt; char data[MAX_PATH_LEN]; sprintf(data, "%s", init); Entrees=fopen(data, "r"); if(Entrees==NULL) { printf("Le FICHIER N'A PU ETRE OUVERT. VERIFIER LE CHEMIN\n"); abort(); } i=0; // i represents the number of value read in the file pligne=ligne; ZCMarket->Pm = pnl_vect_create(100); ZCMarket->tm = pnl_vect_create_from_double(100, 0); while(1) { pligne=fgets(ligne, sizeof(ligne), Entrees); if(pligne==NULL) { break; } else { sscanf(ligne, "%lf t=%lf", &p, &tt); /* La ligne lue dans le fichier doit etre de la forme "0.943290 t=0.5" ou 0.943290 est un double pour le prix de B(0,t=0.5)*/ LET(ZCMarket->Pm,i) = p; /*enregistre le prix du zero coupon*/ LET(ZCMarket->tm,i) = tt; /*enreristre le temps correspondant*/ i++; } } etat=fclose(Entrees); ZCMarket->Nvalue = i; pnl_vect_resize(ZCMarket->Pm, i); pnl_vect_resize(ZCMarket->tm, i); }
/* 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.; }
void Levy_fourier_stiffness(PnlVectComplex *Levy_sinus,double hx,int bnd,int Nw,double hw,int kmin,int kmax,PnlVect *row_stiffness) { PnlVectComplex *cos_sin_vect; int i,k,m; double tmp; cos_sin_vect=pnl_vect_complex_create(Nw); pnl_vect_resize(row_stiffness,kmax-kmin+1); tmp=-bnd*M_PI; for (i=0;i<Nw;i++) { pnl_vect_complex_set(cos_sin_vect,i,CIexp(tmp)); tmp+=hw; } for(k=-1;k>=kmin;k--) { tmp=0; m=0; for (i=0;i<Nw;i++) { tmp+=GET_REAL(Levy_sinus,i)*GET_REAL(cos_sin_vect,m)+GET_IMAG(Levy_sinus,i)*GET_IMAG(cos_sin_vect,m); m-=k; m=m%(Nw); } LET(row_stiffness,k-kmin)=tmp*hw*1/(M_2PI); } for(k=0;k<=kmax;k++) { tmp=0; m=0; for (i=0;i<Nw;i++) { tmp+=GET_REAL(Levy_sinus,i)*GET_REAL(cos_sin_vect,m)-GET_IMAG(Levy_sinus,i)*GET_IMAG(cos_sin_vect,m); m+=k; m=m%Nw; } LET(row_stiffness,k-kmin)=tmp*hw*1/(M_2PI); } if(bnd%2==1) for(k=kmin;k<=kmax;k++) if(k-kmin%2==0) LET(row_stiffness,k-kmin)*=-1; pnl_vect_complex_free(&cos_sin_vect); }
Option::Option(double T, int timeStep, int size, double r, double *coeff){ T_ = T; timeStep_ = timeStep; size_ = size; r_ = r; Coeff_ = pnl_vect_create(size_); for (int i = 0; i < size_; i++){ LET(Coeff_, i) = coeff[i]; } }
static int cf_swaption_direct_libaff_cir1d(int InitYieldCurve_flag, double R_flat, char *curve, double x0, double lambda, double theta, double eta, double swaption_start, double swaption_end, double swaption_period, double swaption_strike, double swaption_nominal, int swaption_payer_receiver, double *swaption_price) { StructLiborAffine LiborAffine; ZCMarketData ZCMarket; PnlVect *ModelParams=pnl_vect_create(4); ZCMarket.filename = curve; SetInitYieldCurve(InitYieldCurve_flag, R_flat, &ZCMarket); LET(ModelParams, 0) = x0; LET(ModelParams, 1) = lambda; LET(ModelParams, 2) = theta; LET(ModelParams, 3) = eta; CreateStructLiborAffine(&LiborAffine, &ZCMarket, swaption_start, swaption_end, swaption_period, ModelParams, &phi_psi_cir1d, &MaxMgfArg_cir1d); *swaption_price = cf_swaption_direct(&LiborAffine, swaption_start, swaption_end, swaption_period, swaption_strike, swaption_nominal, swaption_payer_receiver); FreeStructLiborAffine(&LiborAffine); return OK; }
/// Computation of the payoff at the final time of the tree (ie the option maturity) static void BermudianSwaption_InitialPayoffHW1D(int swaption_start, TreeHW1dG* Meth, ModelHW1dG* HW1dG_Parameters, ZCMarketData* ZCMarket, PnlVect* OptionPriceVect2, NumFunc_1 *p, double periodicity,double contract_maturity, double SwaptionFixedRate) { double sigma; int jminprev, jmaxprev; // jmin[i], jmax [i] int i,j; double delta_x1; // delta_x1 = space step of the process x at time i double delta_t1; // time step double ZCPrice, SumZC; double current_rate; int NumberOfPayments; double Ti; ZCPrice = 0.0; ///** Calcul du vecteur des payoffs a l'instant de maturite de l'option jminprev = pnl_vect_int_get(Meth->Jminimum, swaption_start); // jmin(swaption_start) jmaxprev = pnl_vect_int_get(Meth->Jmaximum, swaption_start); // jmax(swaption_start) pnl_vect_resize(OptionPriceVect2, jmaxprev-jminprev+1); delta_t1 = GET(Meth->t, swaption_start) - GET(Meth->t,swaption_start-1); sigma = Current_VolatilityHW1dG(HW1dG_Parameters, GET(Meth->t, swaption_start)); delta_x1 = SpaceStepHW1dG(delta_t1, sigma);//SpaceStepHW1dG(delta_t1, a, sigma); NumberOfPayments = (int) floor((contract_maturity-GET(Meth->t, swaption_start) )/periodicity + 0.2); p->Par[0].Val.V_DOUBLE = 1.0; for( j = jminprev ; j<=jmaxprev ; j++) { current_rate = j * delta_x1 + GET(Meth->alpha, swaption_start); // rate(Ngrid, j ) SumZC = 0; for(i=1; i<=NumberOfPayments; i++) { Ti = GET(Meth->t, swaption_start) + i*periodicity; ZCPrice = DiscountFactor(ZCMarket, HW1dG_Parameters, GET(Meth->t, swaption_start), Ti, current_rate); SumZC += ZCPrice; } LET(OptionPriceVect2, j-jminprev) = ((p->Compute)(p->Par, periodicity * SwaptionFixedRate * SumZC + ZCPrice)); } }
/// Computation of the payoff at the final time of the tree (ie the option maturity) static void CapFloor_InitialPayoffLRS1D(TreeLRS1D* Meth, ModelLRS1D* ModelParam, ZCMarketData* ZCMarket, PnlVect* OptionPriceVect2, NumFunc_1 *p, double T1, double T2, double CapFloorFixedRate) { double sigma, rho, kappa, lambda; int j, h; double delta_y, delta_t, sqrt_delta_t; double y_00, y_ih, r_ih, phi_ihj; double ZCPrice; int i_T1; double periodicity; /// Model Parameters kappa = (ModelParam->Kappa); sigma = (ModelParam->Sigma); rho = (ModelParam->Rho); lambda = (ModelParam->Lambda); /// Computation of the vector of payoff at the maturity of the option periodicity = T2 - T1; i_T1 = indiceTimeLRS1D(Meth, T1); pnl_vect_resize(OptionPriceVect2, 6*i_T1 - 3); delta_t = GET(Meth->t, i_T1+1) - GET(Meth->t,i_T1); sqrt_delta_t = sqrt(delta_t); delta_y = lambda * sqrt_delta_t; y_00 = r_to_y(ModelParam, -log(BondPrice(GET(Meth->t, 1), ZCMarket))/GET(Meth->t, 1)); p->Par[0].Val.V_DOUBLE = 1.0 ; for( h=0; h<=2*i_T1; h++) /// h : numero de la box { y_ih = y_00 + (i_T1-h) * delta_y; r_ih = y_to_r(ModelParam, y_ih); for(j=0;j<number_phi_in_box(i_T1, h);j++) /// Boucle sur les valeurs de phi à (i,h) { phi_ihj = phi_value(Meth, i_T1, h, j); ZCPrice = cf_lrs1d_zcb(ZCMarket, T1, r_ih, phi_ihj, kappa, sigma, rho, lambda, T2); LET(OptionPriceVect2, index_tree(i_T1, h, j)) = (p->Compute)(p->Par, (1+periodicity*CapFloorFixedRate)*ZCPrice); } } }
// Use results on trigonometric function. void Levy_process_fourier_stiffness_0(Levy_process * mod,double hx,double bnd_fourier,int Nw,int kmin,int kmax,int Dupire,PnlVect *row_stiffness) { double abserr; int k,neval; RFourierFunc RF; PnlFunc Func; double A=12.56; double epsabs=1e-15; double epsrel=1e-15; RF.Dupire=Dupire; RF.hx=hx; RF.Model=mod; Func.params=&RF; Func.function=&RFourierFuncEvaluation_Void; pnl_vect_resize(row_stiffness,kmax-kmin+1); for(k=kmin;k<=kmax;k++) { RF.k=k; pnl_integration_GK(&Func,-A,A,epsabs,epsrel,&LET(row_stiffness,k-kmin),&abserr,&neval); LET(row_stiffness,k-kmin)/=M_2PI; } printf("sum of Row stiffness %e \n",pnl_vect_sum(row_stiffness)); pnl_vect_print(row_stiffness); }
static SCM expand_cond_clauses (SCM clause, SCM rest, int elp, int alp, SCM env) { SCM test; const long length = scm_ilength (clause); ASSERT_SYNTAX (length >= 1, s_bad_cond_clause, clause); test = CAR (clause); if (scm_is_eq (test, scm_sym_else) && elp) { const int last_clause_p = scm_is_null (rest); ASSERT_SYNTAX (length >= 2, s_bad_cond_clause, clause); ASSERT_SYNTAX (last_clause_p, s_misplaced_else_clause, clause); return expand_sequence (CDR (clause), env); } if (scm_is_null (rest)) rest = VOID (SCM_BOOL_F); else rest = expand_cond_clauses (CAR (rest), CDR (rest), elp, alp, env); if (length >= 2 && scm_is_eq (CADR (clause), scm_sym_arrow) && alp) { SCM tmp = scm_gensym (scm_from_locale_string ("cond ")); SCM new_env = scm_acons (tmp, tmp, env); ASSERT_SYNTAX (length > 2, s_missing_recipient, clause); ASSERT_SYNTAX (length == 3, s_extra_expression, clause); return LET (SCM_BOOL_F, scm_list_1 (tmp), scm_list_1 (tmp), scm_list_1 (expand (test, env)), CONDITIONAL (SCM_BOOL_F, LEXICAL_REF (SCM_BOOL_F, tmp, tmp), CALL (SCM_BOOL_F, expand (CADDR (clause), new_env), scm_list_1 (LEXICAL_REF (SCM_BOOL_F, tmp, tmp))), rest)); } /* FIXME length == 1 case */ else return CONDITIONAL (SCM_BOOL_F, expand (test, env), expand_sequence (CDR (clause), env), rest); }
static void fcn_lsq(const PnlVect *x, PnlVect *fvec, void *p) { int i; double tmp1, tmp2, tmp3; double y[15] = {1.4e-1, 1.8e-1, 2.2e-1, 2.5e-1, 2.9e-1, 3.2e-1, 3.5e-1, 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39}; for (i = 0; i < 15; i++) { tmp1 = i+1; tmp2 = 15 - i; tmp3 = tmp1; if (i > 7) tmp3 = tmp2; LET(fvec,i) = y[i] - (GET(x,0) + tmp1/(GET(x,1)*tmp2 + GET(x,2)*tmp3)); } }
/// 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); }
/// Computation of the payoff at the final time of the tree (ie the option maturity) static void ZCOption_InitialPayoffBK1D(PnlVect* ZCbondPriceVect, PnlVect* OptionPriceVect, NumFunc_1 *p) { int j; double ZCPrice; pnl_vect_resize(OptionPriceVect, ZCbondPriceVect->size); ///** Calcul du vecteur des payoffs a l'instant de maturite de l'option for( j = 0 ; j<ZCbondPriceVect->size ; j++) { ZCPrice = GET(ZCbondPriceVect, j); LET(OptionPriceVect, j) = (p->Compute)(p->Par, ZCPrice); // Payoff of the option } }
static void fcn_fsolve(const PnlVect *x, PnlVect *fvec, void *p) { /* subroutine fcn for hybrd example. */ int k, n; double one=1, temp, temp1, temp2, three=3, two=2, zero=0; n = x->size; pnl_vect_resize (fvec, n); for (k=0; k<n; k++) { temp = (three - two*GET(x,k))*GET(x,k); temp1 = zero; if (k != 0) temp1 = GET(x,k-1); temp2 = zero; if (k != n-1) temp2 = GET(x,k+1); LET(fvec,k) = temp - temp1 - two*temp2 + one; } }
static SCM expand_letstar_clause (SCM bindings, SCM body, SCM env SCM_UNUSED) { if (scm_is_null (bindings)) return expand_sequence (body, env); else { SCM bind, name, sym, init; ASSERT_SYNTAX (scm_is_pair (bindings), s_bad_expression, bindings); bind = CAR (bindings); ASSERT_SYNTAX (scm_ilength (bind) == 2, s_bad_binding, bind); name = CAR (bind); sym = scm_gensym (SCM_UNDEFINED); init = CADR (bind); return LET (SCM_BOOL_F, scm_list_1 (name), scm_list_1 (sym), scm_list_1 (expand (init, env)), expand_letstar_clause (CDR (bindings), body, scm_acons (name, sym, env))); } }
static SCM expand_or (SCM expr, SCM env SCM_UNUSED) { SCM tail = CDR (expr); const long length = scm_ilength (tail); ASSERT_SYNTAX (length >= 0, s_bad_expression, expr); if (scm_is_null (CDR (expr))) return CONST (SCM_BOOL_F, SCM_BOOL_F); else { SCM tmp = scm_gensym (SCM_UNDEFINED); return LET (SCM_BOOL_F, scm_list_1 (tmp), scm_list_1 (tmp), scm_list_1 (expand (CADR (expr), env)), CONDITIONAL (SCM_BOOL_F, LEXICAL_REF (SCM_BOOL_F, tmp, tmp), LEXICAL_REF (SCM_BOOL_F, tmp, tmp), expand_or (CDR (expr), scm_acons (tmp, tmp, env)))); } }
// We interpolate linearly the parameters of exercise strategy between intermidiate exercise dates. static int Interpolate_AndersenParams(AndersenStruct *andersen_struct) { int i, j, q, j1, j2; double a, b; q = andersen_struct->q; for (i=0; i<q; i++) { j1 = pnl_vect_int_get(andersen_struct->AndersenIndices, i); j2 = pnl_vect_int_get(andersen_struct->AndersenIndices, i+1); for (j=j1; j<=j2; j++) { a = ((double)(j-j1))/((double)(j2-j1)); b = ((double)(j2-j))/((double)(j2-j1)); LET(andersen_struct->AndersenParams, j) = a*GET(andersen_struct->AndersenParams, j2) + b*GET(andersen_struct->AndersenParams, j1); } } return OK; }
// Compute the price of a bermudan swaption. static int MC_BermSwpaption_Andersen(NumFunc_1 *p, Libor *ptLib, Swaption *ptBermSwpt, Volatility *ptVol, double Nominal, long NbrMCsimulation_param, long NbrMCsimulation, int NbrStepPerTenor, int generator, int flag_numeraire, int q, double *PriceBermSwp) { int alpha, beta, i, NbrExerciseDates; double tenor, numeraire_0; double ax, bx, cx, tol, xmin; AndersenStruct andersen_struct; PnlFunc FuncToMinimize; Create_AndersenStruct(&andersen_struct); //Nfac = ptVol->numberOfFactors; //N = ptLib->numberOfMaturities; tenor = ptBermSwpt->tenor; alpha = pnl_iround(ptBermSwpt->swaptionMaturity/tenor); // T(alpha) is the swaption maturity beta = pnl_iround(ptBermSwpt->swapMaturity/tenor); // T(beta) is the swap maturity NbrExerciseDates = beta-alpha; numeraire_0 = Numeraire(0, ptLib, flag_numeraire); tol = 1e-10; q = MIN(q, NbrExerciseDates-1); // The maximum number of kink-points that can be used is NbrExerciseDates-1. q = MAX(1, q); // q must be greater than zero. FuncToMinimize.function = &func_to_minimize; FuncToMinimize.params = &andersen_struct; // Initialize the structure andersen_struct using "NbrMCsimulation_param" paths. // We will use these paths to estimates the optimal parameters of exercise strategy. Init_AndersenStruct(&andersen_struct, ptLib, ptBermSwpt, ptVol, p, NbrMCsimulation_param, NbrStepPerTenor, generator, flag_numeraire, Nominal, q); // At maturity, the parameter is null, because we exercise whenever payoff is positif. pnl_vect_set_zero(andersen_struct.AndersenParams); ax = 0; // lower point for GoldenSearch method cx = andersen_struct.H_max; // upper point for GoldenSectionSearch method bx = 0.5*(ax+cx); // middle point for GoldenSectionSearch method for (i=q-1; i>=0; i--) { // Index of exercise date where we compute parameter of exercise strategy. andersen_struct.j_start = pnl_vect_int_get(andersen_struct.AndersenIndices, i); // Find optimal parameter at current exercise date. golden(&FuncToMinimize, ax, bx, cx, tol, &xmin); // Store this parameter in AndersenParams. LET(andersen_struct.AndersenParams, andersen_struct.j_start) = xmin; ax = 0.5*xmin; bx = 0.5*(ax+cx); } // We simulate another set of Libor paths, independants of the ones used to estimate the parameters of exercise strategy. // In general, choose NbrMCsimulation >> NbrMCsimulation_param. Init_AndersenStruct(&andersen_struct, ptLib, ptBermSwpt, ptVol, p, NbrMCsimulation, NbrStepPerTenor, generator, flag_numeraire, Nominal, q); // Finaly, we use the found parameters to estimate the price of bermudan swaption following. andersen_struct.j_start = 0; *PriceBermSwp = numeraire_0*AmOption_Price_Andersen(&andersen_struct); // Free memory. Free_AndersenStruct(&andersen_struct); return OK; }
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); }
/// 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); }
/// Price of a bermudianswaption using a trinomial tree static double tr_hw1dg_bermudianswaption(TreeHW1dG* Meth, ModelHW1dG* HW1dG_Parameters, ZCMarketData* ZCMarket,int NumberOfTimeStep, NumFunc_1 *p, double r, double periodicity,double option_maturity,double contract_maturity, double SwaptionFixedRate) { double delta_t1; // time step double Pup, Pmiddle, Pdown; int i,j; double Ti2, Ti1; int i_Ti2, i_Ti1; double current_rate, NumberOfPayments; double OptionPrice; PnlVect* PayoffVect; PnlVect* OptionPriceVect1; // Vector of prices of the option at i PnlVect* OptionPriceVect2; // Vector of prices of the option at i+1 OptionPriceVect1 = pnl_vect_create(1); OptionPriceVect2 = pnl_vect_create(1); PayoffVect = pnl_vect_create(1); //mean_reversion = (HW1dG_Parameters->MeanReversion); ///****************** Computation of the vector of payoff at the maturity of the option *******************/// Ti1 = contract_maturity-periodicity; i_Ti1 = IndexTimeHW1dG(Meth, Ti1); BermudianSwaption_InitialPayoffHW1D(i_Ti1, Meth, HW1dG_Parameters, ZCMarket, OptionPriceVect2, p, periodicity, contract_maturity, SwaptionFixedRate); ///****************** Backward computation of the option price until initial time s *******************/// NumberOfPayments = (int) floor((contract_maturity-option_maturity )/periodicity + 0.2); for(i=NumberOfPayments-2 ; i>=0 ; i--) { Ti1 = option_maturity + i * periodicity; Ti2 = Ti1 + periodicity; i_Ti2 = IndexTimeHW1dG(Meth, Ti2); i_Ti1 = IndexTimeHW1dG(Meth, Ti1); BackwardIterationHW1dG(Meth, HW1dG_Parameters, OptionPriceVect1, OptionPriceVect2, i_Ti2, i_Ti1); BermudianSwaption_InitialPayoffHW1D(i_Ti1, Meth, HW1dG_Parameters, ZCMarket, PayoffVect, p, periodicity, contract_maturity, SwaptionFixedRate); for(j=0;j<PayoffVect->size;j++) { if(GET(PayoffVect,j)>GET(OptionPriceVect2,j)) { LET(OptionPriceVect2,j)=GET(PayoffVect,j); } } } BackwardIterationHW1dG(Meth, HW1dG_Parameters, OptionPriceVect1, OptionPriceVect2, i_Ti1, 1); Pup = 1.0 / 6.0; Pmiddle = 2.0 /3.0 ; Pdown = 1.0 / 6.0; delta_t1 = GET(Meth->t, 1) - GET(Meth->t,0); current_rate = GET(Meth->alpha, 0); // r(0,j) OptionPrice = exp(-current_rate*delta_t1) * ( Pup * GET(OptionPriceVect2, 2) + Pmiddle * GET(OptionPriceVect2,1) + Pdown * GET(OptionPriceVect2, 0)); pnl_vect_free(& OptionPriceVect1); pnl_vect_free(& OptionPriceVect2); pnl_vect_free(& PayoffVect); return OptionPrice; }
int arch_pdp11_translate_instr(cpu_t *cpu, addr_t pc, BasicBlock *bb) { uint16_t opcode = cpu->RAM[pc]; //LOG("%s:%d PC=$%04X\n", __func__, __LINE__, pc); switch (get_instr(opcode)) { /* flags */ case INSTR_CLC: LET1(cpu->ptr_C, FALSE); break; case INSTR_CLD: LET1(ptr_D, FALSE); break; case INSTR_CLI: LET1(ptr_I, FALSE); break; case INSTR_CLV: LET1(cpu->ptr_V, FALSE); break; case INSTR_SEC: LET1(cpu->ptr_C, TRUE); break; case INSTR_SED: LET1(ptr_D, TRUE); break; case INSTR_SEI: LET1(ptr_I, TRUE); break; /* register transfer */ case INSTR_TAX: SET_NZ(LET(X,R(A))); break; case INSTR_TAY: SET_NZ(LET(Y,R(A))); break; case INSTR_TXA: SET_NZ(LET(A,R(X))); break; case INSTR_TYA: SET_NZ(LET(A,R(Y))); break; case INSTR_TSX: SET_NZ(LET(X,R(S))); break; case INSTR_TXS: SET_NZ(LET(S,R(X))); break; /* load */ case INSTR_LDA: SET_NZ(LET(A,OPERAND)); break; case INSTR_LDX: SET_NZ(LET(X,OPERAND)); break; case INSTR_LDY: SET_NZ(LET(Y,OPERAND)); break; /* store */ case INSTR_STA: STORE(R(A),LOPERAND); break; case INSTR_STX: STORE(R(X),LOPERAND); break; case INSTR_STY: STORE(R(Y),LOPERAND); break; /* stack */ case INSTR_PHA: PUSH(R(A)); break; case INSTR_PHP: PUSH(arch_flags_encode(cpu, bb)); break; case INSTR_PLA: SET_NZ(LET(A,PULL)); break; case INSTR_PLP: arch_flags_decode(cpu, PULL, bb); break; /* shift */ case INSTR_ASL: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, true, false)); break; case INSTR_LSR: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, false, false)); break; case INSTR_ROL: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, true, true)); break; case INSTR_ROR: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, false, true)); break; /* bit logic */ case INSTR_AND: SET_NZ(LET(A,AND(R(A),OPERAND))); break; case INSTR_ORA: SET_NZ(LET(A,OR(R(A),OPERAND))); break; case INSTR_EOR: SET_NZ(LET(A,XOR(R(A),OPERAND))); break; case INSTR_BIT: SET_NZ(OPERAND); break; /* arithmetic */ case INSTR_ADC: SET_NZ(ADC(ptr_A, ptr_A, OPERAND, true, false)); break; case INSTR_SBC: SET_NZ(ADC(ptr_A, ptr_A, COM(OPERAND), true, false)); break; case INSTR_CMP: SET_NZ(ADC(NULL, ptr_A, COM(OPERAND), false, true)); break; case INSTR_CPX: SET_NZ(ADC(NULL, ptr_X, COM(OPERAND), false, true)); break; case INSTR_CPY: SET_NZ(ADC(NULL, ptr_Y, COM(OPERAND), false, true)); break; /* increment/decrement */ case INSTR_INX: SET_NZ(LET(X,INC(R(X)))); break; case INSTR_INY: SET_NZ(LET(Y,INC(R(Y)))); break; case INSTR_DEX: SET_NZ(LET(X,DEC(R(X)))); break; case INSTR_DEY: SET_NZ(LET(Y,DEC(R(Y)))); break; case INSTR_INC: SET_NZ(STORE(INC(OPERAND),LOPERAND)); break; case INSTR_DEC: SET_NZ(STORE(DEC(OPERAND),LOPERAND)); break; /* control flow */ case INSTR_JMP: if (get_addmode(opcode) == ADDMODE_IND) { Value *v = LOAD_RAM16(CONST32(OPERAND_16)); new StoreInst(v, cpu->ptr_PC, bb); } break; case INSTR_JSR: PUSH16(pc+2); break; case INSTR_RTS: STORE(ADD(PULL16, CONST16(1)), cpu->ptr_PC); break; /* branch */ case INSTR_BEQ: case INSTR_BNE: case INSTR_BCS: case INSTR_BCC: case INSTR_BMI: case INSTR_BPL: case INSTR_BVS: case INSTR_BVC: break; /* other */ case INSTR_NOP: break; case INSTR_BRK: arch_6502_trap(cpu, pc, bb); break; case INSTR_RTI: arch_6502_trap(cpu, pc, bb); break; case INSTR_XXX: arch_6502_trap(cpu, pc, bb); break; } return get_length(get_addmode(opcode)); }
//swaption_payer_receiver=0 : Payer //swaption_payer_receiver=1 : Receiver static double cf_swaption_direct(StructLiborAffine *LiborAffine, double swaption_start, double swaption_end, double swaption_period, double swaption_strike, double swaption_nominal, int swaption_payer_receiver) { double x0, lambda, theta, eta, Sqr_eta, Y; double P=0., Q=0., x, deg_freedom, n_centrality_param, bound, price, trm_k; double Tk, a_Ti, b_Ti, dzeta_k, sigma_k, sum=0.; int i, m, k, which=1, status; double psi_d; dcomplex uk, phi, psi; x0 = GET(LiborAffine->ModelParams, 0); lambda = GET(LiborAffine->ModelParams, 1); theta = GET(LiborAffine->ModelParams, 2); eta = GET(LiborAffine->ModelParams, 3); Sqr_eta = SQR(eta); // Static variables Ti = swaption_start; Tm = swaption_end; TN = LET(LiborAffine->TimeDates, (LiborAffine->TimeDates)->size-1); i = indiceTimeLiborAffine(LiborAffine, Ti); m = indiceTimeLiborAffine(LiborAffine, Tm); c_k = pnl_vect_create_from_double(m-i+1, swaption_period*swaption_strike); Phi_i_k = pnl_vect_create(m-i+1); Psi_i_k = pnl_vect_create(m-i+1); LET(c_k, 0) = -1.0; LET(c_k, m-i) += 1.; for (k=i; k<=m; k++) { uk = Complex(GET(LiborAffine->MartingaleParams, k), 0.); phi_psi_t_v(TN-Ti, uk, LiborAffine, &phi, &psi); LET(Phi_i_k, k-i) = Creal(phi); LET(Psi_i_k, k-i) = Creal(psi); } // Zero of the function f if (m==i+1) Y = find_Y_caplet(LiborAffine); else Y = find_Y_swaption(LiborAffine); a_Ti = exp(-lambda*Ti); if (lambda == 0.) b_Ti = Ti; else b_Ti = (1.-a_Ti)/lambda; deg_freedom = lambda*theta/Sqr_eta; sum=0.; Tk=Ti; for (k=i; k<=m; k++) { psi_d = GET(Psi_i_k, k-i); dzeta_k = 1 - 2*Sqr_eta*b_Ti*psi_d; sigma_k = Sqr_eta*b_Ti/dzeta_k; x = Y/sigma_k; n_centrality_param = x0*a_Ti/(Sqr_eta*b_Ti*dzeta_k); if (x<0) { P=0.; Q=1.; } else { pnl_cdf_chn (&which, &P, &Q, &x, °_freedom, &n_centrality_param, &status, &bound); } if (swaption_payer_receiver==0) trm_k = -GET(c_k, k-i)*BondPrice(Tk, LiborAffine->ZCMarket) * Q; else trm_k = GET(c_k, k-i)*BondPrice(Tk, LiborAffine->ZCMarket) * P; sum += trm_k; Tk += swaption_period; } price = swaption_nominal * sum; pnl_vect_free(&c_k); pnl_vect_free(&Phi_i_k); pnl_vect_free(&Psi_i_k); return price; }
int CarrMethod_VectStrike(PnlVect *K, PnlVect * Price, double S0, double T, double B, double CallPut, double r, double divid, double sigma, void * Model, dcomplex (*ln_phi)(dcomplex u,double t,void * model)) { int n; dcomplex dzeta,dzetaBS; double alpha=0.75; int Nlimit = 4*2048;//2048; //>> Should be even => use of real_fft //number of integral discretization steps double mone;//0.010; double Kstep=B*2/(Nlimit); // strike domain is (-B,B) double h = M_2PI/(Nlimit*Kstep); //double B = 0.5*(Nlimit)*Kstep; // strike domain is (-B,B) double vn = 0; dcomplex vn_minus_alpha_plus_uno = Complex(0,-(alpha+1)); dcomplex i_vn_plus_alpha = Complex(alpha,0); dcomplex uno_plus_alpha_plus_ivn =Complex(1+alpha,vn); PnlVectComplex * y = pnl_vect_complex_create(Nlimit); // Should become output pnl_vect_resize(K,Nlimit); pnl_vect_resize(Price,Nlimit); //delta mone=1; //printf("limit integration %7.4f \n",A); for(n=0; n<Nlimit; n++) { dzeta = Cadd(ln_phi(vn_minus_alpha_plus_uno,T,Model),Complex(0,vn*B)); dzetaBS = Cadd(ln_phi_BS(vn_minus_alpha_plus_uno,T,sigma),Complex(0,vn*B)); dzeta = Csub(Cexp(dzeta),Cexp(dzetaBS)); dzeta = Cdiv(dzeta,i_vn_plus_alpha); dzeta = Cdiv(dzeta,uno_plus_alpha_plus_ivn); //>> With Simson rules pnl_vect_complex_set(y,n,RCmul(3+mone-((n==0)?1:0),Conj(dzeta))); //>> Update value vn += h; vn_minus_alpha_plus_uno.r+=h; i_vn_plus_alpha.i+=h; uno_plus_alpha_plus_ivn.i+=h; mone*=-1; } pnl_ifft_inplace(y); for(n=0;n<Nlimit;n++) { LET(K,n)=exp(-B+n*Kstep+(r-divid)*T)*(S0); pnl_cf_call_bs(S0,GET(K,n),T,r,divid,sigma,&LET(Price,n),&vn); LET(Price,n)+=2./3* S0/(Kstep)*exp(alpha*(B-n*Kstep)-divid*T)*GET_REAL(y,n); } if (CallPut==2) for(n=0;n<Nlimit;n++) LET(Price,n)-=S0*exp(-divid*T)+GET(K,n)*exp(-r*T); /* printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2-5),GET(Price,Nlimit/2-5)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2-4),GET(Price,Nlimit/2-4)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2-3),GET(Price,Nlimit/2-3)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2-2),GET(Price,Nlimit/2-2)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2-1),GET(Price,Nlimit/2-1)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+0),GET(Price,Nlimit/2+0)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+1),GET(Price,Nlimit/2+1)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+2),GET(Price,Nlimit/2+2)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+3),GET(Price,Nlimit/2+3)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+4),GET(Price,Nlimit/2+4)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+5),GET(Price,Nlimit/2+5)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+6),GET(Price,Nlimit/2+6)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+7),GET(Price,Nlimit/2+7)); printf("Price K= %7.4f P= %7.4f \n",GET(K,Nlimit/2+8),GET(Price,Nlimit/2+8)); pnl_vect_free(&K); pnl_vect_free(&Price); */ return OK; }
int CarrMethod_onStrikeList(PnlVect *K, PnlVect * Price, double S0, double T, double CallPut, double r, double divid, double sigma, Levy_diffusion * Model) { PnlVect * StrikeFFT,*PriceFFT; int n,error,ancestor,current,next; double delta; double strike_min = GET(K, 0); double strike_max = GET(K,K->size-1); //double nbr_strike = K->size; double strike_bnd = 2*MAX(log(strike_max/S0),fabs(log(strike_min/S0)));//0.25*log(strike_max/strike_min)/nbr_strike; // 2 adjust heuristic parameter, to find four points // in fft in which all real strike value from K // Stored data for homogen grid in strike StrikeFFT=pnl_vect_create(0); PriceFFT=pnl_vect_create(0); error=CarrMethod_VectStrike(StrikeFFT,PriceFFT, S0,T,strike_bnd,CallPut,r,divid,sigma, Model, &Levy_diffusion_ln_characteristic_function_with_cast); ancestor=0; current=0; next=1; n=0; while(n<K->size) { if((GET(StrikeFFT,current)<=GET(K,n))&&(GET(StrikeFFT,next)>GET(K,n))) { quadratic_interpolation(GET(PriceFFT,ancestor), GET(PriceFFT,current), GET(PriceFFT,next), GET(StrikeFFT,ancestor), GET(StrikeFFT,current), GET(StrikeFFT,next), GET(K,n), &LET(Price,n), &delta); n++; } else { ancestor=current;//not ++ for the first step current++; next++; if(next>StrikeFFT->size) PNL_ERROR(" Carr method domain size is too small for interpolation after FFT !","carr.c "); } } LET(Price,n)=GET(PriceFFT,PriceFFT->size); return error; }
/// Backward computation of the price of an option on a Zero Coupon Bond void ZCOption_BackwardIterationBK1D(TreeShortRate* Meth, ModelParameters* ModelParam, PnlVect* ZCbondPriceVect1, PnlVect* ZCbondPriceVect2, PnlVect* OptionPriceVect1, PnlVect* OptionPriceVect2, int index_last, int index_first, NumFunc_1 *p, int Eur_Or_Am) { double a ,sigma; int jmin; // jmin[i+1], jmax[i+1] int jminprev, jmaxprev; // jmin[i], jmax [i] int i, j, k; // i = represents the time index. j, k represents the nodes index double eta_over_delta_x; double delta_x1, delta_x2; // delta_x1 = space step of the process x at time i ; delta_x2 same at time i+1. double delta_t1, delta_t2; // time step double beta_x; // quantity used in the compuation of the probabilities. it depends only on i. double ZCPrice; //ZC price double current_rate; double Pup, Pmiddle, Pdown; ///*******************Parameters of the processes r, u and y *********************//// a = ModelParam->MeanReversion; sigma = ModelParam->RateVolatility; jminprev = pnl_vect_int_get(Meth->Jminimum, index_last); // jmin(index_last) jmaxprev = pnl_vect_int_get(Meth->Jmaximum, index_last); // jmax(index_last) ///** Backward computation of the option price from "index_last-1" to "index_first", knowing those at "index_last"**/// for(i = index_last-1; i>=index_first; i--) { jmin = jminprev; // jmin := jmin(i+1) jminprev = pnl_vect_int_get(Meth->Jminimum, i); // jminprev := jmin(i) jmaxprev = pnl_vect_int_get(Meth->Jmaximum, i); // jmaxprev := jmax(i) pnl_vect_resize(OptionPriceVect1, jmaxprev-jminprev +1); // OptionPrice1 := Prix a l'instant i, if(Eur_Or_Am != 0) { pnl_vect_resize(ZCbondPriceVect1, jmaxprev-jminprev +1); // OptionPrice1 := Prix a l'instant i, } delta_t1 = GET(Meth->t, i) - GET(Meth->t,MAX(i-1,0)); // Pas de temps entre t[i] et t[i-1] delta_t2 = GET(Meth->t, i+1) - GET(Meth->t,i); // Pas de temps entre t[i+1] et t[i] delta_x1 = SpaceStep(delta_t1, a, sigma); // SpaceStep (i) delta_x2 = SpaceStep(delta_t2, a, sigma); // SpaceStep (i+1) beta_x = (delta_x1 / delta_x2) * exp(-a*delta_t2); // Boucle sur les noeuds for(j = jminprev ; j<= jmaxprev ; j++) { k= pnl_iround(j * beta_x); // index of the middle node emanating from (i,j) eta_over_delta_x = j * beta_x - k; // quantity used in the compuation of the probabilities Pup, Pmiddle and Pdown. Pup = ProbaUp(eta_over_delta_x); // Probability of an up move from (i,j) Pmiddle = ProbaMiddle(eta_over_delta_x); // Probability of a middle move from (i,j) Pdown = 1 - Pup - Pmiddle; // Probability of a down move from (i,j) current_rate = func_model_bk1d(j * delta_x1 + GET(Meth->alpha, i)); // r(i,j) LET(OptionPriceVect1,j-jminprev) = exp(-current_rate*delta_t2) * ( Pup * GET(OptionPriceVect2, k+1-jmin) + Pmiddle * GET(OptionPriceVect2, k-jmin) + Pdown * GET(OptionPriceVect2, k-1-jmin)); if(Eur_Or_Am != 0) { LET(ZCbondPriceVect1,j-jminprev) = exp(-current_rate*delta_t2) * ( Pup * GET(ZCbondPriceVect2, k+1-jmin) + Pmiddle * GET(ZCbondPriceVect2, k-jmin) + Pdown * GET(ZCbondPriceVect2, k-1-jmin)); ZCPrice = GET(ZCbondPriceVect1,j-jminprev); // ZC price P(ti, S, r_ti=current rate) // In the case of american option, decide wether to exerice the option or not if( GET(OptionPriceVect1, j-jminprev) < (p->Compute)(p->Par, ZCPrice)) { LET(OptionPriceVect1, j-jminprev) = (p->Compute)(p->Par, ZCPrice); } } } // Copy OptionPrice1 in OptionPrice2 pnl_vect_clone(OptionPriceVect2, OptionPriceVect1); if(Eur_Or_Am != 0) { pnl_vect_clone(ZCbondPriceVect2, ZCbondPriceVect1); } } // END of the loop on i }
// Use results on trigonometric function. // Compute int_R sinc(u)^4 psi(u) exp( i u k ) du void Levy_fourier_stiffness_gradient(PnlVectComplex *Levy_sinus, double hx, int bnd, int Nw, int grad_size, double hw, int kmin, int kmax, PnlVect *row_stiffness) { PnlVectComplex *cos_sin_vect; int i,k,m,j; double tmp1; int bound=kmax-kmin+1; cos_sin_vect=pnl_vect_complex_create(Nw); pnl_vect_resize(row_stiffness,grad_size*(kmax-kmin+1)); tmp1=-bnd*M_PI; for (i=0;i<Nw;i++) { pnl_vect_complex_set(cos_sin_vect,i,CIexp(tmp1)); tmp1+=hw; } pnl_vect_set_double(row_stiffness,0.0); for(k=-1;k>=kmin;k--) { m=0; for (i=0;i<Nw;i++) { for(j=0;j<grad_size;j++) { //LET(row_stiffness,j+grad_size*(k-kmin)) LET(row_stiffness,bound*j+(k-kmin))+=GET_REAL(Levy_sinus,j+i*grad_size)*GET_REAL(cos_sin_vect,m)+ GET_IMAG(Levy_sinus,j+i*grad_size)*GET_IMAG(cos_sin_vect,m); } m-=k; m=m%(Nw); } //for(j=0;j<grad_size;j++) // LET(row_stiffness,j+grad_size*(k-kmin))*=hw*1/(M_2PI); } for(k=0;k<=kmax;k++) { m=0; for (i=0;i<Nw;i++) { for(j=0;j<grad_size;j++) { //LET(row_stiffness,j+grad_size*(k-kmin)) LET(row_stiffness,bound*j+(k-kmin))+=GET_REAL(Levy_sinus,j+i*grad_size)*GET_REAL(cos_sin_vect,m) -GET_IMAG(Levy_sinus,j+i*grad_size)*GET_IMAG(cos_sin_vect,m); } m+=k; m=m%Nw; } //for(j=0;j<grad_size;j++) // LET(row_stiffness,j+grad_size*(k-kmin))*=hw*1/(M_2PI); } if(bnd%2==1) for(j=0;j<grad_size;j++) for(k=kmin;k<=kmax;k++) LET(row_stiffness,bound*j+(k-kmin))*=((k-kmin%2==0)?-1:1)*hw*1/(M_2PI); else for(j=0;j<grad_size;j++) for(k=kmin;k<=kmax;k++) LET(row_stiffness,bound*j+(k-kmin))*=hw*1/(M_2PI); /* for(k=kmin;k<=kmax;k++) if(k-kmin%2==0) for(j=0;j<grad_size;j++) LET(row_stiffness,j+grad_size*(k-kmin))*=-1; */ pnl_vect_complex_free(&cos_sin_vect); }