RectangleRulePricer.cpp

#include "RectangleRulePricer.h"

#include "RealFunction.h"
#include "matlib.h"
#include "geometry.h"
#include "CallOption.h"
#include <cmath>

using namespace std;

/*
*  C++11 contains an isfinite function already, but we have
*  written our own so the code can work on older versions of
*  Visual Studio
*/
bool isfinitenumber(double arg) {
	return arg == arg &&
		arg != std::numeric_limits<double>::infinity() &&
		arg != -std::numeric_limits<double>::infinity();
}

double RectangleRulePricer::price(const PathIndependentOption& option,
	const BlackScholesModel& model) const {
	return price([&] (double stockPrice) {
			return option.payoffAtMaturity( Matrix(stockPrice) )(0);
		},
		option.getMaturity(),
		model);
}

double RectangleRulePricer::price(function<double(double)> payoffFunction,
	double maturity,
	const BlackScholesModel& model) const {

	auto integrand = [&]( double x) {
		double sigma = model.volatility;
		double muTilde = model.riskFreeRate - 0.5*sigma*sigma;
		double S0 = model.stockPrice;
		double t = maturity;

		double probDensity = 1 / (sigma*sqrt(2 * PI*t)) * exp(-pow(x - log(S0) - muTilde*t, 2) / (2 * sigma*sigma*t));
		double payoff = payoffFunction(exp(x));
		if (isfinitenumber(payoff)) {
			return payoff * probDensity;
		}
		else {
			// payoffs that can't be evaluated, given
			// the computer's precision are taken to be zero.
			return 0.0;
		}
		return 0.0;
	};

	double expectation = integralOverR(integrand, 1000);
	return exp(-model.riskFreeRate*maturity)*expectation;

}

static void testPriceCallOption() {
	BlackScholesModel m;
	m.stockPrice = 100.0;
	m.volatility = 0.1;
	m.drift = 0.0;
	m.riskFreeRate = 0.1;
	CallOption c;
	c.setStrike(100.0);
	c.setMaturity(2.0);
	double expected = c.price(MultiStockModel(m));
	RectangleRulePricer pricer;
	double actual = pricer.price(c, m);
	ASSERT_APPROX_EQUAL(actual, expected, 0.01);
}


void testRectangleRulePricer() {
	TEST(testPriceCallOption);
}