Scenario You are providing support to a trading group that will be selling customized call options. They are looking for some quantitative analysis that will give them a handle on how often to rebalance the underlying hedge.
Action You will be given some new programs for computing Black-Scholes prices and hedges, which you will combine with a modified version of the existing asset allocation program. The resultant simulations should give you a handle on the optimal frequency of hedging.
Concept This is a capstone assignment that combines both option pricing and simulation of a trading strategy. You will be given new programs that compute the Black-Scholes formula and the normal (Gaussian) distribution and density required for the Black-Scholes formula. You will use these programs in conjunction with the hedge simulation program to evaluate the quality of the hedge at different rebalancing frequencies. (This sort of modular construction of programs simplifies debugging and makes it easier to reuse the pieces.) Rebalancing is more important for options than for a fixed-proportions portfolio strategy (since the theoretical hedge ratio varies much more with small changes in the underlying).
Instructions
// // simu1test.cc Asset Allocation test file // #include <iostream.h> #include "simu1.h" main() { int i; aa sim1; termvals y; for(i=0;i<100;i++) { y = sim1.fixprops(.5); cout << y.termstock << " " << y.termwealth << endl;} return(0);}Exhibit B: the header file simu1.h
// // simu1.h Asset Allocation Header // struct termvals { double termstock; double termwealth;}; class aa { public: aa(double ttm=1.0,int nper=120,double r=.05,double mean=.15,double stddev=.2); int restart(double ttm,int nper,double r,double mean,double stddev); termvals fixprops(double inrisky,double initstock=0.0,double initcash=100.0); private: int npers; double tinc, r1per, mean1per, std1persqrt12, wealth, stockpos, cash, stockP, stockret; double stocktotret();};Exhibit C: the implementation file simu1.cc
// // simu1.cc Asset Allocation Simulation // #include <math.h> #include <stdlib.h> #include <iostream.h> #include "simu1.h" #define unifrand() ((double) rand()/((double) RAND_MAX)) aa::aa(double ttm,int nper,double r,double mean,double stddev) { restart(ttm,nper,r,mean,stddev);} int aa::restart(double ttm,int nper,double r,double mean,double stddev) { npers = nper; tinc = ttm/(double) nper; r1per = 1.0 + r*tinc; mean1per = 1.0 + mean*tinc; std1persqrt12 = sqrt((double) 12)*stddev*sqrt(tinc); // cout << " " << npers << " " << tinc << " " << r1per << " " // << mean1per << " " << std1persqrt12 << endl; return(0);} termvals aa::fixprops(double inrisky,double initstock,double initcash) { int i; termvals x; stockpos = initstock; cash = initcash; stockP = 100.0; // cout << npers << endl; for(i=0;i<npers;i++) { wealth = stockpos + cash; stockpos = inrisky * wealth; cash = wealth - stockpos; stockret = stocktotret(); //cout << stockret << " " << tinc << " " << mean1per << " " << std1persqrt12 << //" " << unifrand() <<endl; stockP *= stockret; stockpos *= stockret; cash *= r1per; // cout << stockret << " " << stockP << " " << stockpos << " " << cash << endl; } x.termstock = stockP; x.termwealth = stockpos + cash; return(x);} double aa::stocktotret() { return(mean1per + std1persqrt12 * (unifrand()-0.5));}Exhibit D: the test file bstest.cc
// // bstest.cc Black-Scholes test program // #include <iostream.h> #include "bs.h" main() { double S,X,r,sigma,ttm; valhedge callinfo; bs bspr; while(1) { cin >> S >> X >> r >> sigma >> ttm; bspr.newpars(ttm,r,sigma); callinfo = bspr.call(S,X); cout << callinfo.value << " " << callinfo.delta << endl;}}Exhibit E: the header file bs.h
// // bs.h Black-Scholes header file // #include "gaussian.h" struct valhedge { double value; double delta;}; class bs { public: bs(double ttm=.25,double r=.05,double sigma=.3); void newpars(double ttm,double r,double sigma); valhedge call(double S0,double X); private: valhedge ezcall(double stock,double bond,double vol); double disc,sigsqttm;};Exhibit F: the implementation file bs.cc
// // bs.cc Black-Scholes Pricing Engine // #include <math.h> #include "bs.h" bs::bs(double ttm,double r,double sigma) { sigsqttm = sigma * sigma * ttm; disc = exp(-r * ttm);} void bs::newpars(double ttm,double r,double sigma) { sigsqttm = sigma * sigma * ttm; disc = exp(-r * ttm);} valhedge bs::ezcall(double stock,double bond,double vol) { distdens Nn1,Nn2; valhedge toreturn; Nn1 = Gaussian(log(stock/bond)/vol+vol/2.0); Nn2 = Gaussian(log(stock/bond)/vol-vol/2.0); toreturn.value = stock * Nn1.dist - bond * Nn2.dist; toreturn.delta = Nn1.dist; return(toreturn);} valhedge bs::call(double S0,double X) { return(ezcall(S0,X*disc,sqrt(sigsqttm)));}Exhibit G: the testtest file gausstest.cc
// // Gaussian distribution test file // #include <iostream.h> #include "gaussian.h" main() { double quantity, mean, variance; distdens y; while(1) { cin >> quantity >> mean >> variance; y = Gaussian(quantity, mean, variance); cout << y.dist << " " << y.dens << endl;}}Exhibit H: the header file gaussian.h
// // gaussian.h // // declarations for normal computations // struct distdens { double dist; double dens;}; distdens Gaussian(double quantity,double mean=0.0,double variance=1.0);Exhibit I: the implementation file gaussian.cc
// // gaussian.cc // // C++ program for normal computations // based on the algorithm 26.2.17 in // Abromowitz and Stegun, Handbook of Mathematical // Functions, Dover, NY // #include <math.h> #include "gaussian.h" distdens Gaussian(double quantity,double mean,double variance) { distdens toreturn; double q,sigma,t; sigma = sqrt(variance); q = (quantity - mean)/sigma; toreturn.dens = exp(-q*q/2.0)*.3989422804014327/sigma; if(q>0.0) { t = 1.0/(1.0+0.2316419*q); toreturn.dist = 1.0-exp(-q*q/2.0)*.3989422804014327* t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))));} else { t = 1.0/(1.0-0.2316419*q); toreturn.dist = exp(-q*q/2.0)*.3989422804014327* t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))));} return(toreturn);}