Portfolio.cpp
#include "Portfolio.h"
#include "CallOption.h"
#include "PutOption.h"
#include "UpAndInOption.h"
#include "UpAndOutOption.h"
#include "ZeroCouponBond.h"
#include "Stock.h"
using namespace std;
/*
* By using an abstract interface class with a factory constructor
* and only having the implementation in the C++ file we increase information
* hiding. Nobody knows about the PortfolioImpl class outside of the C++ file,
* so we can change it without any impact on anything else.
*/
class PortfolioImpl : public Portfolio {
public:
/* Returns the number of items in the portflio */
int size() const;
/* Add a new security to the portfolio, returns the index
at which it was added */
int add( double quantity,
shared_ptr<Priceable> security );
/* Update the quantity at a given index */
void setQuantity( int index, double quantity );
/* Compute the current price */
double price( const BlackScholesModel& model ) const;
//private:
vector<double> quantities;
vector< shared_ptr<Priceable> > securities;
};
int PortfolioImpl::size() const {
return quantities.size();
}
int PortfolioImpl::add( double quantity,
shared_ptr<Priceable> security ) {
quantities.push_back( quantity );
securities.push_back( security );
return quantities.size();
}
double PortfolioImpl::price(
const BlackScholesModel& model ) const {
double ret = 0;
int n = size();
for (int i=0; i<n; i++) {
ret += quantities[i] * securities[i]->price( model );
}
return ret;
}
void PortfolioImpl::setQuantity( int index,
double quantity ) {
quantities[index] = quantity;
}
/**
* Create a Portfolio
*/
shared_ptr<Portfolio> Portfolio::newInstance() {
shared_ptr<Portfolio> ret=make_shared<PortfolioImpl>();
return ret;
}
/////////////////////////////
// Tests
/////////////////////////////
static void testSingleSecurity() {
shared_ptr<Portfolio> portfolio = Portfolio::newInstance();
shared_ptr<CallOption> c=make_shared<CallOption>();
c->setStrike(110);
c->setMaturity(1.0);
portfolio->add( 100, c );
BlackScholesModel bsm;
bsm.volatility = 0.1;
bsm.stockPrice = 100;
double unitPrice = c->price( bsm );
double portfolioPrice = portfolio->price( bsm );
ASSERT_APPROX_EQUAL( 100*unitPrice, portfolioPrice, 0.0001);
}
static void testPutCallParity() {
shared_ptr<Portfolio> portfolio
= Portfolio::newInstance();
shared_ptr<CallOption> c=make_shared<CallOption>();
c->setStrike(110);
c->setMaturity(1.0);
shared_ptr<PutOption> p=make_shared<PutOption>();
p->setStrike(110);
p->setMaturity(1.0);
portfolio->add( 100, c );
portfolio->add( -100, p );
BlackScholesModel bsm;
bsm.volatility = 0.1;
bsm.stockPrice = 100;
bsm.riskFreeRate = 0;
double expected = bsm.stockPrice - c->getStrike();
double portfolioPrice = portfolio->price( bsm );
ASSERT_APPROX_EQUAL(100*expected,portfolioPrice,0.0001);
}
static void testStocksAndBonds() {
shared_ptr<Stock> stock = make_shared<Stock>();
shared_ptr<ZeroCouponBond> bond = make_shared<ZeroCouponBond>();
bond->maturity = 1.0;
shared_ptr<Portfolio> portfolio
= Portfolio::newInstance();
portfolio->add(1, stock);
portfolio->add(1, bond);
BlackScholesModel bsm;
bsm.volatility = 0.1;
bsm.stockPrice = 100;
bsm.riskFreeRate = 0;
double portfolioPrice = portfolio->price(bsm);
ASSERT_APPROX_EQUAL(101.0, portfolioPrice, 0.0001);
}
static void testBarrierOptions() {
double strike = 100;
double barrier = 105;
double maturity = 1.0;
shared_ptr<UpAndOutOption> upAndOut = make_shared<UpAndOutOption>();
shared_ptr<UpAndInOption> upAndIn = make_shared<UpAndInOption>();
shared_ptr<CallOption> option = make_shared<CallOption>();
option->setStrike(strike);
upAndOut->setStrike(strike);
upAndOut->setBarrier(barrier);
upAndIn->setStrike(strike);
upAndIn->setBarrier(barrier);
option->setMaturity(maturity);
upAndOut->setMaturity(maturity);
upAndIn->setMaturity(maturity);
shared_ptr<Portfolio> portfolio
= Portfolio::newInstance();
portfolio->add(1, upAndOut);
portfolio->add(1, upAndIn);
portfolio->add(-1, option);
BlackScholesModel bsm;
bsm.volatility = 0.1;
bsm.stockPrice = 100;
bsm.riskFreeRate = 0;
double portfolioPrice = portfolio->price(bsm);
ASSERT_APPROX_EQUAL(0.0, portfolioPrice, 0.1);
}
void testPortfolio() {
TEST( testSingleSecurity );
TEST( testPutCallParity );
TEST( testStocksAndBonds );
TEST(testBarrierOptions);
}