/* Equity linked foreign exchange option */ double EquityLinkedFXO( int fCall, double E, double S, double X, double T, double r, double rf, double q, double vS, double vE, double Rho) { double d1, d2, XS, ES; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); d1 = (log(E / X) + (r - rf + Rho * vS * vE + pow2(vE) / 2.0) * T) / (vE * sqrt(T)); d2 = d1 - vE * sqrt(T); XS = X * S * exp((rf - r - q - Rho * vS * vE) * T); ES = E * S * exp(-q * T); if(fCall) return ES * cnd(d1) - XS * cnd(d2); else return XS * cnd(-d2) - ES * cnd(-d1); }
/* Rho for the generalized Black and Scholes formula */ double rho(int fCall, double S, double X, double T, double r, double b, double v) { double result; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); assert_valid_interest_rate(r); assert_valid_cost_of_carry(b); assert_valid_volatility(v); if(b == 0.0) result = -T * gbs(fCall, S, X, T, r, b, v); else { const double vst = v * sqrt(T); const double d1 = (log(S / X) + (b + pow2(v) / 2.0) * T) / (vst); const double d2 = d1 - vst; if(fCall) result = T * X * exp(-r * T) * cnd(d2); else result = -T * X * exp(-r * T) * cnd(-d2); } return result; }
/* Theta for the generalized Black and Scholes formula */ double theta(int fCall, double S, double X, double T, double r, double b, double v) { double st, d1, d2, sbrt, result; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); assert_valid_interest_rate(r); assert_valid_cost_of_carry(b); assert_valid_volatility(v); st = sqrt(T); d1 = (log(S / X) + (b + pow2(v) / 2.0) * T) / (v * st); d2 = d1 - v * st; sbrt= S * exp((b - r) * T); if(fCall) { result = -sbrt * normdist(d1) * v / (2.0 * st) - (b - r) * sbrt * cnd(d1) - r * X * exp(-r * T) * cnd(d2); } else { result = -sbrt * normdist(d1) * v / (2.0 * st) + (b - r) * sbrt * cnd(-d1) + r * X * exp(-r * T) * cnd(-d2); } return result; }
/* Merton (1973) Options on stock indices, page 4. */ double merton73( int fCall, double S, double X, double T, double r, double q, double v) { double d1, d2, result; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); assert_valid_interest_rate(r); assert_valid_volatility(v); d1 = (log(S / X) + (r - q + pow2(v) / 2.0) * T) / (v * sqrt(T)); d2 = d1 - v * sqrt(T); if(fCall) result = S * exp(-q * T) * cnd(d1) - X * exp(-r * T) * cnd(d2); else result = X * exp(-r * T) * cnd(-d2) - S * exp(-q * T) * cnd(-d1); assert(is_sane(result)); return result; }
double black76put(const double stockprice, const double strike, const double rate, const double t, const double v, double *delta) { double put; double d1,d2,dd1,dd2; d1 = (log(stockprice/strike)+((v*v)/2)*t)/(v*sqrt(t)); d2 = d1-(v*sqrt(t)); /* dd1 is the hedge ratio or the option's delta */ dd1 = cnd(-d1); dd2 = cnd(-d2); put = (exp(-rate*t)*((strike*dd2) - (stockprice*dd1))); if(dd1<0) { *delta=0.0; } else { if(dd1>=1) { *delta=-1; } else { *delta= (dd1 - (double) 1.0); } } return put; }
double black76call(const double stockprice, const double strike, const double rate, const double t, const double v, double *delta) { double d1,d2,dd1,dd2,call; d1 = (log(stockprice/strike)+((v*v)/2)*t)/(v*sqrt(t)); d2 = d1-(v*sqrt(t)); /* dd1 is the hedge ratio or the option's delta */ dd1 = cnd(d1); dd2 = cnd(d2); if(dd1<0) { *delta=0.0; } else { if(dd1>=1) { *delta=1; } else { *delta=dd1; } } call = ( exp(-rate*t) * ( (stockprice*dd1)-(strike*dd2) ) ); return call; }
static double CriticalPart3( int id, double I, double t1, double T2, double v) { double result; double z1, z2; const double vT2_t1 = v * sqrt(T2 - t1); const double p2v = pow2(v); const double logI = log(I); if (id == 1) { z1 = (logI + p2v / 2.0 * (T2 - t1)) / vT2_t1; z2 = (logI - p2v / 2.0 * (T2 - t1)) / vT2_t1; result = I * cnd(z1) - cnd(z2); } else if( id == 2) { z1 = (-logI + pow2(v) / 2.0 * (T2 - t1)) / vT2_t1; z2 = (-logI - pow2(v) / 2.0 * (T2 - t1)) / vT2_t1; result = cnd(z1) - I * cnd(z2); } else abort(); return result; }
/* Vasicek: options on zero coupon bonds, page 151-152.*/ double VasicekBondOption( int fCall, double F, double X, double tau, double T, double r, double Theta, double kappa, double v) { double PtT, Pt_tau, vp, H, result; assert_valid_strike(X); assert_valid_time(T); assert_valid_interest_rate(r); assert_valid_volatility(v); X = X / F; PtT = VasicekBondPrice(0.0, T, r, Theta, kappa, v); Pt_tau = VasicekBondPrice(0.0, tau, r, Theta, kappa, v); vp = sqrt(pow2(v) * (1.0 - exp(-2.0 * kappa * T)) / (2.0 * kappa)) * (1.0 - exp(-kappa * (tau - T))) / kappa; H = 1.0 / vp * log(Pt_tau / (PtT * X)) + vp / 2.0; if(fCall) result = F * (Pt_tau * cnd(H) - X * PtT * cnd(H - vp)); else result = F * (X * PtT * cnd(-H + vp) - Pt_tau * cnd(-H)); return result; }
/* Fixed exchange rate foreign equity options-- Quantos */ double Quanto( int fCall, double Ep, double S, double X, double T, double r, double rf, double q, double vS, double vE, double Rho) { double d1, d2, result; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); assert_valid_interest_rate(r); d1 = (log(S / X) + (rf - q - Rho * vS * vE + pow2(vS) / 2.0) * T) / (vS * sqrt(T)); d2 = d1 - vS * sqrt(T); if(fCall) result = Ep * (S * exp((rf - r - q - Rho * vS * vE) * T) * cnd(d1) - X * exp(-r * T) * cnd(d2)); else result = Ep * (X * exp(-r * T) * cnd(-d2) - S * exp((rf - r - q - Rho * vS * vE) * T) * cnd(-d1)); assert(is_sane(result)); return result; }
double EuroBewerter::call(double t, double T, double X0, double Strike, double r, double delta, double sigma) { double rStrich = r - delta; double TStrich = T - t; double d1 = (log(X0 / Strike) + (rStrich + sigma * sigma / 2.) * TStrich) / (sigma * sqrt(TStrich)); double d2 = d1 - sigma * sqrt(TStrich); double wert = (X0 * cnd(d1) - Strike * exp(-rStrich * TStrich) * cnd(d2)); wert *= exp(-(delta) * T); return wert * exp(-t * (r - delta)); }
double EuroBewerter::put(double t, double T, double X0, double Strike, double r, double delta, double sigma) { double rStrich = r - delta; double TStrich = T - t; double d1 = (log(X0 / Strike) + (rStrich + sigma * sigma / 2) * TStrich) / (sigma * sqrt(TStrich)); double d2 = d1 - sigma * sqrt(TStrich); return exp(-r * t) * (exp(-delta * TStrich) * (Strike * exp(-rStrich * TStrich) * cnd(-d2) - X0 * cnd(-d1))); }
//Margrabes Formel double EuroBewerter::exchange_option(double x, double y, double t, double T, double r, double delta, double sigma) { // y to be replaced double TStrich = T - t; double d1 = (log(x / y) + (sigma * sigma) * TStrich) / (sqrt(2.) * sigma * sqrt(TStrich)); double d2 = (log(x / y) - (sigma * sigma) * TStrich) / (sqrt(2.) * sigma * sqrt(TStrich)); double erg = x * exp(-delta * TStrich) * cnd(d1) - y * exp(-delta * TStrich) * cnd(d2); return erg * exp(-r * t); }
extern double blackscholes_put(double S, double X, double T, double r, double v) { double vst, d1; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); assert_valid_interest_rate(r); assert_valid_volatility(v); vst = v * sqrt(T); d1 = (log(S / X) + (r + pow2(v) / 2) * T) / (vst); return X * exp(-r * T) * cnd(-(d1 - vst)) - S * cnd(-d1); }
void S() { //printf("\nEnter <S>"); if(!(strcmp(token,"CONSTANT") && strcmp(token,"FLT_TYP") && strcmp(token,"BOOL_TYP") && strcmp(token,"INT_TYP") && strcmp(token,"STR_TYP"))) D(); else if(!strcmp(token,"ID")) A(); else if(!strcmp(token,"IF_")) cnd(); else if(!strcmp(token,"LOOP_THIS")) cnt(); else if(!(strcmp(token,"INPT_DATA") && strcmp(token,"PRNT_DATA"))) io(); else if(!strcmp(token,"B_START")) { consume(); SL(); if(!strcmp(token,"B_END")) { consume(); } else error("Unmatched {. Expecting }."); } //if(strcmp(token,"B_END")) // { // error("Unterminated Syntax."); // strcpy(token, "B_END"); // } //printf("\nExit <S>"); }
double put_delta(double stockprice, const double strike, const double rate, const double t, const double d, const double dividend) { double d1,dd1; /* no time left this thing is worth nothing */ if( t <= 0 ) { return 0.0; } stockprice = stockprice - stockprice * dividend * exp(-t * rate); d1 = (log(stockprice/strike)+((rate+((d*d)/2))*t))/(d*sqrt(t)); /* dd1 is the hedge ratio or the option's delta */ dd1 = cnd(d1); dd1 = dd1 - (double) 1; if( dd1 > 0 ) { return 0.0; } else { if( dd1 <= -1 ) { return -1; } else { return dd1; } } return dd1; }
double EuroBewerter::put_diff2(double t, double T, double X0, double Strike, double r, double delta, double sigma) { // double r_Strich = r - delta; // double T_Strich = T - t; double d1 = (log(X0 / Strike) + (r - delta + sigma * sigma / 2) * (T - t)) / (sigma * sqrt(T - t)); return exp(-(r - delta) * t) * exp(-T * delta) * (-cnd(-d1)); }
double EuroBewerter::put_diff(double t, double T, double X0, double Strike, double r, double delta, double sigma) { double rStrich = r - delta; double TStrich = T - t; double d1 = (log(X0 / Strike) + (rStrich + sigma * sigma / 2) * TStrich) / (sigma * sqrt(TStrich)); return exp(-r * t - delta * TStrich) * (cnd(d1) - 1.); }
double EuroBewerter::max_call(double t, double T, double* X0, int D, double Strike, double r, double delta, double sigma) { T = T - t; double summe = 0; for (int d = 0; d < D; ++d) { double d_minus = (log(X0[d] / Strike) + (r - delta - sigma * sigma / 2.) * T) / (sigma * sqrt(T)); double d_plus = d_minus + sigma * sqrt(T); Polynom ganz; double eins[1] = { 1. }; ganz.set(eins, 1); double I; double max = -100000; double min = 10000000; for (int dd = 0; dd < D; ++dd) if (dd != d) { // printf("\nd_plus %f, d_minus %f,", d_plus, d_minus); // printf("verschiebefaktor %f\n", // sigma * sqrt(T) // + log(X0[d] / X0[dd]) / (sigma * sqrt(T))); // double pp[18] = { 0.5, 0.3960985, 0, -0.061485, 0, 0.007456, 0, // -5.84946E-4, 0, 2.920034E-5, 0, -9.15823E-7, 0, // 1.740319E-8, 0, -1.826093E-10, 0, 8.10495E-13 }; double pp[10] = { 0.50000000000009, 0.38567951086190133, 0, -0.05010672697589501, 0, 0.004103597701237448, 0, -1.631010612321749E-4, 0, 2.4428290978202304E-6 }; Polynom p; p.set(pp, 10); double v = sigma * sqrt(T) + log(X0[d] / X0[dd]) / (sigma * sqrt(T)); max = v > max ? v : max; min = v < min ? v : min; p.verschieben(v); // printf("I innen%f\n",integralExpQ(&p, maxi(-d_plus, -5. + min), 5. - max)); ganz.multiply_with(&p); } I = integralExpQ(&ganz, maxi(-d_plus, -5. + min), 5. - max); // printf("I aussen%f\n", I); summe += X0[d] * exp(-delta * T) / sqrt(2 * 3.141592654) * I; } double prod = 1; for (int d = 0; d < D; ++d) { double d_minus = (log(X0[d] / Strike) + (r - delta - sigma * sigma / 2.) * T) / (sigma * sqrt(T)); prod *= (1 - (1 - cnd(-d_minus))); } double zu = -Strike * exp(-r * T) + Strike * exp(-r * T) * prod; double ergebnis = (summe + zu) * exp(-r * t); //return erf(0.1); double e1 = 0; for (int d = 0; d < D; ++d) e1 = maxi(e1, call(t, T, X0[d], Strike, r, delta, sigma)); return maxi(ergebnis, e1); }
//auch getestet double EuroBewerter::exchange_option_diff(double x, double y, double t, double T, double r, double delta, double sigma, int re) { double TStrich = T - t; double Wurzel = sqrt(2.) * sigma * sqrt(TStrich); double d1 = (log(x / y) + (sigma * sigma) * TStrich) / Wurzel; double d2 = (log(x / y) - (sigma * sigma) * TStrich) / Wurzel; //if(rand()%100==0) //printf("%f,\n",cnd(d1)); if (re == 0) return exp(-r * t - delta * (T - t)) * (cnd(d1) + (dnd(d1) - y / x * dnd(d2)) / Wurzel); else return exp(-r * t - delta * (T - t)) * (-cnd(d2) + (dnd(d2) - x / y * dnd(d1)) / Wurzel); }
void cnt() { if(!strcmp(token,"LOOP_THIS")) { consume(); if(!strcmp(token,"IF_")) cnd(); else error("Condition statement required after loop rpt"); } }
/* Carry for the generalized Black and Scholes formula */ double carry(int fCall, double S, double X, double T, double r, double b, double v) { double d1, result; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); assert(r >= 0.0); /* Interest rate >= 0.0 */ assert(b >= 0.0); /* cost of carry >= 0.0 */ assert(v > 0.0 && v <= 100.0); /* Volatility between 0 and 100 */ d1 = (log(S / X) + (b + pow2(v) / 2.0) * T) / (v * sqrt(T)); if(fCall) result = T * S * exp((b - r) * T) * cnd(d1); else result = -T * S * exp((b - r) * T) * cnd(-d1); return result; }
/* Black and Scholes (1973) Stock options */ double blackscholes(int fCall, double S, double X, double T, double r, double v) { double vst, d1, d2; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); assert_valid_interest_rate(r); assert_valid_volatility(v); assert(r >= 0.0); /* Interest rate >= 0.0 */ assert(v > 0.0 && v <= 100.0); /* Volatility between 0 and 100 */ vst = v * sqrt(T); d1 = (log(S / X) + (r + pow2(v) / 2.0) * T) / (vst); d2 = d1 - vst; if(fCall) return S * cnd(d1) - X * exp(-r * T) * cnd(d2); else return X * exp(-r * T) * cnd(-d2) - S * cnd(-d1); }
double body(double const* S, double const* X, double const* T, double const* r, double const* v) { // log(S/X)/2.302585 div_op<VW>(S, X, s0); log_op<VW>(s0, s0); divs_op<VW>(s0, 2.302585, s0); // (r+v*v*0.5)*T mul_op<VW>(v, v, s1); muls_op<VW>(s1, 0.5, s1); add_op<VW>(s1, r, s1); // + muladd_op<VW>(s1, T, s0); // v * sqrt(T) sqrt_op<VW>(T, s1); mul_op<VW>(v, s1, s1); // d1 = () / (v*sqrt(T)) div_op<VW>(s0, s1, s0); // d2 = d1 - v*sqrt(T) sub_op<VW>(s0, s1, s1); // S * cnd(d1) mul_op<VW>(S, cnd(s0), s0); // exp(-r * T) neg_op<VW>(r, s2); mul_op<VW>(s2, T, s2); exp_op<VW>(s2, s2); // X * exp(-r * T) * cnd(d2) mul_op<VW>(X, s2, s2); mul_op<VW>(s2, cnd(s1), s2); sub_op<VW>(s0, s2, s0); return sum_op<VW>(s0); }
double CmssoFunction2::operator ()(const double& x) const { // this is Brigo, 13.16.2 with x = v/sqrt(2), v=sqrt(2)*x CumulativeNormalDistribution cnd(0.0,1.0); double mu1_=0.0; double mu2_=0.0; double v_=sqrt(2.0)*x; double h_=strike_+mult1_*swapRate1_*exp((mu1_-0.5*vol1_*vol1_)*t_+vol1_*sqrt(t_)*v_); double phi1_,phi2_; if(mult2_*swapRate2_/h_>0) { phi1_=cnd((double)flavor_*(log(mult2_*swapRate2_/h_)+(mu2_+(0.5-rho_*rho_)*vol2_*vol2_)*t_+rho_*vol2_*sqrt(t_)*v_)/ (vol2_*sqrt(t_*(1.0-rho_*rho_)))); phi2_=cnd((double)flavor_*(log(mult2_*swapRate2_/h_)+(mu2_-0.5*vol2_*vol2_)*t_+rho_*vol2_*sqrt(t_)*v_)/ (vol2_*sqrt(t_*(1.0-rho_*rho_)))); } else { phi1_= flavor_ == 1 ? 1.0 : 0.0; phi2_= phi1_; } double f=mult2_*(double)flavor_*swapRate2_*exp(mu2_*t_-0.5*rho_*rho_*vol2_*vol2_*t_+rho_*vol2_*sqrt(t_)*v_)*phi1_-(double)flavor_*h_*phi2_; double res=1.0/sqrt(M_PI)*exp(-x*x)*f; return res; }
static double CriticalPart2( int id, double I, double t1, double T2, double v) { double result; if (id == 1) { const double z1 = (log(I) + pow2(v) / 2.0 * (T2 - t1)) / (v * sqrt(T2 - t1)); result = cnd(z1); } else if(id == 2) { const double z2 = (-log(I) - pow2(v) / 2.0 * (T2 - t1)) / (v * sqrt(T2 - t1)); result = -cnd(z2); } else abort(); return result; }
inline void black_scholes_equation(float *call, float *put, float stock_price, float option_strike, float option_years, float riskless_rate, float volatility_rate) { float sqrt_t, exp_rt; float d1, d2, cnd1, cnd2; sqrt_t = sqrtf(option_years); d1 = (logf(stock_price / option_strike) + (riskless_rate + 0.5f * volatility_rate * volatility_rate) * option_years) / (volatility_rate * sqrt_t); d2 = d1 - volatility_rate * sqrt_t; cnd1 = cnd(d1); cnd2 = cnd(d2); exp_rt = expf(-riskless_rate * option_years); *call = stock_price * cnd1 - option_strike * exp_rt * cnd2; *put = option_strike * exp_rt * (1.0f - cnd2) - stock_price * (1.0f - cnd1); }
extern double carry_put(double S, double X, double T, double r, double b, double v) { double d1; assert_valid_price(S); assert_valid_strike(X); assert_valid_time(T); assert_valid_interest_rate(r); assert_valid_cost_of_carry(b); assert_valid_volatility(v); d1 = (log(S / X) + (b + pow2(v) / 2.0) * T) / (v * sqrt(T)); return -T * S * exp((b - r) * T) * cnd(-d1); }
void S() { if(!(strcmp("CONSTANT",token) && strcmp("FLT_TYP",token) && strcmp("BOOL_TYP",token) && strcmp("INT_TYP",token) && strcmp("STR_TYP",token))) D(); else if(!strcmp("ID",token)) A(); else if(!strcmp("IF_",token)) cnd(); else if(!strcmp("LOOP_THIS",token)) cnt(); else if(!(strcmp("INPT_DATA",token) && strcmp("PRNT_DATA",token))) io(); else if(!strcmp("B_START",token)) { consume(); SL(); if(!strcmp("B_END",token)) consume(); else error("Expecting } symbol"); } else if(!strcmp("STMNT_END",token)) consume(); else { int once = 1; iLnLast = iLn; error("Unknown statement"); while(strcmp("STMNT_END",token)) { if(once) { printf("\n\t"); once = 0; } printf(" %s",lexeme); consume(); if(atEnd) break; } consume(); printf(";"); } }
void cnt() { consume(); cnd(); }
// This is needed so fin_recipes N() is not used but rather // cnd() in cumulative_norm.c is used double N(const double& z) { return cnd(z); } // double N(const double& z)