/* Two asset correlation options */
double TwoAssetCorrelation(
	int fCall,
	double S1,
	double S2,
	double X1,
	double X2,
	double T,
	double b1,
	double b2,
	double r,
	double v1,
	double v2,
	double Rho)
{
	double sT, d1, d2, result;

	assert_valid_price(S1);
	assert_valid_price(S2);
	assert_valid_strike(X1);
	assert_valid_strike(X2);
	assert_valid_time(T);
	assert_valid_interest_rate(r);
	assert_valid_cost_of_carry(b1);
	assert_valid_cost_of_carry(b2);
	assert_valid_volatility(v1);
	assert_valid_volatility(v2);

	sT = sqrt(T);
    d1 = (log(S1 / X1) + (b1 - pow2(v1) / 2.0) * T) / (v1 * sT);
    d2 = (log(S2 / X2) + (b2 - pow2(v2) / 2.0) * T) / (v2 * sT);
    
    if (fCall) {
        result 
			= S2 * exp((b2 - r) * T) * cbnd(d2 + v2 * sT, d1 + Rho * v2 * sT, Rho) 
			- X2 * exp(-r * T)       * cbnd(d2, d1, Rho);
    }
	else {
		result 
			= X2 * exp(-r * T)       * cbnd(-d2, -d1, Rho) 
			- S2 * exp((b2 - r) * T) * cbnd(-d2 - v2 * sT, -d1 - Rho * v2 * sT, Rho);
    }

	assert(is_sane(result));
	return result;
}
示例#2
0
/* Complex chooser options */
double ComplexChooser(
    double S,
    double Xc,
    double Xp,
    double T,
    double Tc,
    double Tp,
    double r,
    double b,
    double v)
{
    assert_valid_price(S);
    assert_valid_strike(Xc);
    assert_valid_strike(Xp);
    assert_valid_time(Tc);
    assert_valid_time(Tp);
    assert_valid_interest_rate(r);
    assert_valid_cost_of_carry(b);
    assert_valid_volatility(v);

    {   /* No C99 */

        const double vsT = v * sqrt(T);
        const double vsTc = v * sqrt(Tc);
        const double vsTp = v * sqrt(Tp);
        const double bv2 = b + pow2(v)/2.0;

        const double I = CriticalValueChooser(S, Xc, Xp, T, Tc, Tp, r, b, v);
        const double d1 = (log(S / I) + bv2 * T) / vsT;
        const double d2 = d1 - vsT;
        const double Y1 = (log(S / Xc) + bv2 * Tc) / vsTc;
        const double y2 = (log(S / Xp) + bv2 * Tp) / vsTp;
        const double rho1 = sqrt(T / Tc);
        const double rho2 = sqrt(T / Tp);

        const double result
            =  S * exp((b - r) * Tc) * cbnd(d1, Y1, rho1)
               - Xc * exp(-r * Tc)      * cbnd(d2, Y1 - vsTc, rho1)
               -  S * exp((b - r) * Tp) * cbnd(-d1, -y2, rho2)
               + Xp * exp(-r * Tp)      * cbnd(-d2, -y2 + vsTp, rho2);

        return result;
    } /* No C99 */
}
示例#3
0
int main(void)
{
	size_t i, niter = 300*1000;

	clock_t start, stop;
	double sum = 0.0;


	start = clock();
	for(i = 0; i < niter; i++) {
		sum += cbnd((double)i, 0.1, 0.0);
	}
	stop = clock();
	printf("%'lu clocks for %zu calls\n", (unsigned long)(stop - start), niter);
	return 0;
}
/* Two asset barrier options */
double TwoAssetBarrier(
	int typeflag,
	double S1,
	double S2,
	double X,
	double H,
	double T,
	double r,
	double b1,
	double b2,
	double v1,
	double v2,
	double Rho) 
{
	double sT, v2sT, logHS2, mu1, mu2, d1, d2, d3, d4, e1, e2, e3, e4, w;
    double eta;    /* Binary variable: 1 for call options and -1 for put options */
    double phi;	/* Binary variable: 1 for up options and -1 for down options */

	assert_valid_price(S1);
	assert_valid_price(S2);
	assert_valid_strike(X);
	assert_valid_time(T);
	assert_valid_interest_rate(r);
	assert_valid_cost_of_carry(b1);
	assert_valid_cost_of_carry(b2);
	assert_valid_volatility(v1);
	assert_valid_volatility(v2);
    
    
	sT = sqrt(T);
	v2sT = v2 * sT;
	logHS2 = log(H / S2);
    mu1 = b1 - pow2(v1) / 2.0;
    mu2 = b2 - pow2(v2) / 2.0;
    
/*
 * The book has some errors, including this function. The old, broken version
 * is the original code which matches the testdata in table 2-12. That doesn't
 * help, since the function itself is broken... So we use the new version.
 */
#ifdef USE_OLD_BROKEN_VERSION
    d1 = (log(S1 / X) + (mu1 + pow2(v1) / 2.0) * T) / (v1 * sT);
#else
    d1 = (log(S1 / X) + (mu1 + pow2(v1)) * T) / (v1 * sT);
#endif

    d2 = d1 - v1 * sT;
    d3 = d1 + 2.0 * Rho * logHS2 / v2sT;
    d4 = d2 + 2.0 * Rho * logHS2 / v2sT;
    e1 = (logHS2 - (mu2 + Rho * v1 * v2) * T) / v2sT;
    e2 = e1 + Rho * v1 * sT;
    e3 = e1 - 2.0 * logHS2 / v2sT;
    e4 = e2 - 2.0 * logHS2 / v2sT;
   
	switch(typeflag) {
		case SB_CALL_UP_OUT:
		case SB_CALL_UP_IN:
			eta = phi = 1;
			break;

		case SB_CALL_DOWN_OUT:
		case SB_CALL_DOWN_IN:
			eta = 1;
			phi = -1;
			break;
		case SB_PUT_UP_OUT:
		case SB_PUT_UP_IN:
			eta = -1; 
			phi = 1;
			break;

		case SB_PUT_DOWN_OUT:
		case SB_PUT_DOWN_IN:
			phi = eta = -1;
			break;

		default:
			assert(0);
			abort();
	}

    w	= eta * S1 * exp((b1 - r) * T) * (
			cbnd(eta * d1, phi * e1, -eta * phi * Rho) 
			- exp(2.0 * (mu2 + Rho * v1 * v2) * logHS2 / pow2(v2)) * cbnd(eta * d3, phi * e3, -eta * phi * Rho)
		) 
		- eta * exp(-r * T) * X * (cbnd(eta * d2, phi * e2, -eta * phi * Rho) 
		- exp(2.0 * mu2 * logHS2 / pow2(v2)) * cbnd(eta * d4, phi * e4, -eta * phi * Rho));

	switch(typeflag) {
		case SB_CALL_UP_OUT:
		case SB_CALL_DOWN_OUT:
		case SB_PUT_UP_OUT:
		case SB_PUT_DOWN_OUT:
			return w;

		case SB_CALL_UP_IN:
		case SB_CALL_DOWN_IN:
        return gbs_call(S1, X, T, r, b1, v1) - w;

		case SB_PUT_UP_IN:
		case SB_PUT_DOWN_IN:
			return gbs_put(S1, X, T, r, b1, v1) - w;

		default:
			abort();
	}
}
示例#5
0
/* The cumulative bivariate normal distribution function */
double cbnd(double a, double b, double Rho) 
{
	double result, t, a1, b1;

	assert(is_sane(a));
	assert(is_sane(b));
	assert(is_sane(Rho));

	t = sqrt(2.0 * (1.0 - pow2(Rho)));
	a1 = a / t;
	b1 = b / t;

	if(a <= 0.0 && b <= 0.0 && Rho <= 0.0) {
		double sum = 0.0;
		const double rho20 = Rho * 2.0;
		int i;

		for(i = 0; i < 5; i++) {
			sum += XX[i][0] * exp(a1 * (y2[i] - a1) + (b1 * (y2[0] - b1) ) + (rho20 * (y[i] - a1) * (y[0] - b1)));
			sum += XX[i][1] * exp(a1 * (y2[i] - a1) + (b1 * (y2[1] - b1) ) + (rho20 * (y[i] - a1) * (y[1] - b1)));
			sum += XX[i][2] * exp(a1 * (y2[i] - a1) + (b1 * (y2[2] - b1) ) + (rho20 * (y[i] - a1) * (y[2] - b1)));
			sum += XX[i][3] * exp(a1 * (y2[i] - a1) + (b1 * (y2[3] - b1) ) + (rho20 * (y[i] - a1) * (y[3] - b1)));
			sum += XX[i][4] * exp(a1 * (y2[i] - a1) + (b1 * (y2[4] - b1) ) + (rho20 * (y[i] - a1) * (y[4] - b1)));
		}

		result = sqrt(1.0 - pow2(Rho)) / pi * sum;
	}
	else if(a <= 0.0 && b >= 0.0 && Rho >= 0.0) {
		result = cnd(a) - cbnd(a, -b, -Rho);
	}
	else if(a >= 0.0 && b <= 0.0 && Rho >= 0.0) {
		result = cnd(b) - cbnd(-a, b, -Rho);
	}
	else if(a >= 0.0 && b >= 0.0 && Rho <= 0.0) {
		result = cnd(a) + cnd(b) - 1.0 + cbnd(-a, -b, Rho);
	}
	else if( (a * b * Rho) > 0.0) {
		double rho1, rho2, Delta;
		const double sp2a = sqrt(pow2(a) - (Rho * 2.0 * a * b) + pow2(b));
#if 0
		/*assert(is_sane(sp2a));*/
		if(!is_sane(sp2a) || sp2a == 0.0) {
			fprintf(stderr, "This shouldn't happen :-(\n");
			fprintf(stderr, "----------------------------\n");
			fprintf(stderr, "sp2a == %f\n", sp2a);
			fprintf(stderr, "pow2(a) == %.10g, Rho == %.10g a==%.10g b==%.10g pow2(b) == %.10g\n", pow2(a), Rho, a, b, pow2(b));
			fprintf(stderr, "The arg is %.10f\n", pow2(a) - (Rho * 2.0 * a * b) + pow2(b));
			fprintf(stderr, "The middle part is %.10g\n", (Rho * 2.0 * a * b) );
			fprintf(stderr, "----------------------------\n");
abort();
		}
#endif

		rho1 = (Rho * a - b) * sign(a) / sp2a;
#if 0
		if(!is_sane(rho1)) {
			fprintf(stderr, "Rho==%g a == %g b == %g sign(a) == %g sp2a==%g\n", Rho, a, b, sign(a), sp2a);
		}
		assert(is_sane(rho1));
#endif

		rho2 = (Rho * b - a) * sign(b) / sp2a;
		assert(is_sane(rho2));

		Delta = (1.0 - sign(a) * sign(b)) / 4.0;
		assert(is_sane(Delta));

		result = cbnd(a, 0.0, rho1) + cbnd(b, 0.0, rho2) - Delta;
	}
	else {
		/* Hmm, illegal input? Abort to be on the safe side */
		assert(0);
		abort();
	}

	return result;
}
示例#6
0
int main(void)
{

	/* Testing cbnd() */
	assert_equal(cbnd( 0.0,  0.0,  0.0), 0.250000);
	assert_equal(cbnd( 0.0,  0.0, -0.5), 0.1666667);
	assert_equal(cbnd( 0.0,  0.0,  0.5), 0.333333);
	assert_equal(cbnd( 0.0, -0.5,  0.0), 0.154269);
	assert_equal(cbnd( 0.0, -0.5, -0.5), 0.081660);
	assert_equal(cbnd( 0.0, -0.5,  0.5), 0.226878);
	assert_equal(cbnd( 0.0,  0.5,  0.0), 0.345731);
	assert_equal(cbnd( 0.0,  0.5, -0.5), 0.273122);
	assert_equal(cbnd( 0.0,  0.5,  0.5), 0.418340);

	assert_equal(cbnd(-0.5,  0.0,  0.0), 0.154269);
	assert_equal(cbnd(-0.5,  0.0, -0.5), 0.081660);
	assert_equal(cbnd(-0.5,  0.0,  0.5), 0.226878);
	assert_equal(cbnd(-0.5, -0.5,  0.0), 0.095195);
	assert_equal(cbnd(-0.5, -0.5, -0.5), 0.036298);
	assert_equal(cbnd(-0.5, -0.5,  0.5), 0.163319);
	assert_equal(cbnd(-0.5,  0.5,  0.0), 0.213342);
	assert_equal(cbnd(-0.5,  0.5, -0.5), 0.145218);
	assert_equal(cbnd(-0.5,  0.5,  0.5), 0.272239);

	assert_equal(cbnd( 0.5,  0.0,  0.0), 0.345731);
	assert_equal(cbnd( 0.5,  0.0, -0.5), 0.273122);
	assert_equal(cbnd( 0.5,  0.0,  0.5), 0.418340);
	assert_equal(cbnd( 0.5, -0.5,  0.0), 0.213342);
	assert_equal(cbnd( 0.5, -0.5, -0.5), 0.145218);
	assert_equal(cbnd( 0.5, -0.5,  0.5), 0.272239);
	assert_equal(cbnd( 0.5,  0.5,  0.0), 0.478120);
	assert_equal(cbnd( 0.5,  0.5, -0.5), 0.419223);
	assert_equal(cbnd( 0.5,  0.5,  0.5), 0.546244);
	return 0;
}
/* Exchange options on exchange options */
double ExchangeExchangeOption(
	int TypeFlag,
	double S1,
	double S2,
	double q,
	double t1,
	double T2,
	double r,
	double b1,
	double b2,
	double v1,
	double v2,
	double Rho) 
{
	double result, I, d1, d2, d3, d4, Y1, y2, y3, y4;
	double st1T2, v, I1;
	int id;

	/* TODO: No asserts 20070310 */
	st1T2 = sqrt(t1 / T2);
    v = sqrt(pow2(v1) + pow2(v2) - 2.0 * Rho * v1 * v2);
    I1 = S1 * exp((b1 - r) * (T2 - t1)) / (S2 * exp((b2 - r) * (T2 - t1)));
    
	if (TypeFlag == 1 || TypeFlag == 2) 
        id = 1;
    else
        id = 2;
    
    I = CriticalPrice(id, I1, t1, T2, v, q);
    d1 = (log(S1 / (I * S2)) + (b1 - b2 + pow2(v) / 2.0) * t1) / (v * sqrt(t1));
    d2 = d1 - v * sqrt(t1);
    d3 = (log((I * S2) / S1) + (b2 - b1 + pow2(v) / 2.0) * t1) / (v * sqrt(t1));
    d4 = d3 - v * sqrt(t1);

    Y1 = (log(S1 / S2) + (b1 - b2 + pow2(v) / 2.0) * T2) / (v * sqrt(T2));
    y2 = Y1 - v * sqrt(T2);
    y3 = (log(S2 / S1) + (b2 - b1 + pow2(v) / 2.0) * T2) / (v * sqrt(T2));
    y4 = y3 - v * sqrt(T2);
    
    if (TypeFlag == 1) {
        result 
			= -S2 
			* exp((b2 - r) * T2) 
			* cbnd(d2, y2, st1T2) 
			+ S1 
			* exp((b1 - r) * T2) 
			* cbnd(d1, Y1, st1T2) 
			- q 
			* S2 
			* exp((b2 - r) * t1) 
			* cnd(d2);
    }
	else if( TypeFlag == 2) {
        result 
			= S2 
			* exp((b2 - r) * T2) 
			* cbnd(d3, y2, -st1T2) - S1 
			* exp((b1 - r) * T2) 
			* cbnd(d4, Y1, -st1T2) + q 
			* S2 
			* exp((b2 - r) * t1) 
			* cnd(d3);
    }
	else if( TypeFlag == 3) {
        result 
			= S2 
			* exp((b2 - r) * T2) 
			* cbnd(d3, y3, st1T2) - S1 
			* exp((b1 - r) * T2) 
			* cbnd(d4, y4, st1T2) - q 
			* S2 
			* exp((b2 - r) * t1) 
			* cnd(d3);
    }
	else if( TypeFlag == 4) {
        result 
			= -S2 
			* exp((b2 - r) * T2) 
			* cbnd(d2, y3, -st1T2) + S1 
			* exp((b1 - r) * T2) 
			* cbnd(d1, y4, -st1T2) + q 
			* S2 
			* exp((b2 - r) * t1) 
			* cnd(d2);
    }
	else
		abort();

	return result;
}
/* Options on options */
double OptionsOnOptions(
	int typeflag,
	double S,
	double X1,
	double X2,
	double t1, 
	double T2,
	double r,
	double b,
	double v) 
{
	double result, bv2, vst1, vsT2, I, Rho, _y1, y2, z1, z2;
	int fCall;

	assert_valid_price(S);
	assert_valid_strike(X1);
	assert_valid_strike(X2);
	assert_valid_time(t1);
	assert_valid_time(T2);
	assert_valid_interest_rate(r);
	assert_valid_cost_of_carry(b);
	assert_valid_volatility(v);

	bv2 = b + pow2(v) / 2.0;
	vst1 = v * sqrt(t1);
	vsT2 = v * sqrt(T2);

	assert(typeflag == OOO_CALL_ON_CALL || typeflag == OOO_CALL_ON_PUT || typeflag == OOO_PUT_ON_CALL || typeflag == OOO_PUT_ON_PUT);
    
	if(typeflag == OOO_CALL_ON_CALL || typeflag == OOO_PUT_ON_CALL)
        fCall = 1;
    else
        fCall = 0;
    
    I = CriticalValueOptionsOnOptions(fCall, X1, X2, T2 - t1, r, b, v);
    
    Rho = sqrt(t1 / T2);
    _y1 = (log(S / I) + bv2 * t1) / vst1;
    y2 = _y1 - vst1;
    z1 = (log(S / X1) + bv2 * T2) / vsT2;
    z2 = z1 - vsT2;

	if(typeflag == OOO_CALL_ON_CALL) {
        result 
			=  S * exp((b - r) * T2) * cbnd(z1, _y1, Rho) 
			- X1 * exp(-r * T2)      * cbnd(z2, y2, Rho) 
			- X2 * exp(-r * t1)      * cnd(y2);
    }
	else if(typeflag == OOO_PUT_ON_CALL) {
        result 
			= X1 * exp(-r * T2)      * cbnd(z2, -y2, -Rho) 
			-  S * exp((b - r) * T2) * cbnd(z1, -_y1, -Rho) 
			+ X2 * exp(-r * t1)      * cnd(-y2);
    }
	else if(typeflag == OOO_CALL_ON_PUT) {
        result 
			= X1 * exp(-r * T2)      * cbnd(-z2, -y2, Rho) 
			-  S * exp((b - r) * T2) * cbnd(-z1, -_y1, Rho) 
			- X2 * exp(-r * t1)      * cnd(-y2);
    }
	else if(typeflag == OOO_PUT_ON_PUT) {
        result 
			=  S * exp((b - r) * T2) * cbnd(-z1, _y1, -Rho) 
			- X1 * exp(-r * T2)      * cbnd(-z2, y2, -Rho) 
			+ X2 * exp(-r * t1)      * cnd(y2);
    }
	else {
		/* Abort to be on the safe side */
		abort();
	}

	assert(is_sane(result));
	return result;
}