00001
00002
00003 #include "optionpair.h"
00004
00005 #include <iomanip>
00006 #include <limits>
00007
00008 #include "Bisection.h"
00009 #include "Secant.h"
00010
00011 const double option_pair::NA = std::numeric_limits<double>::quiet_NaN();
00012
00013 void option_pair::init_calc_derived_attributes() const
00014 {
00015 if (_S==0) return;
00016
00017 if (_tau == 0) {
00018 set_call_immediate_exercise();
00019 set_put_immediate_exercise();
00020 return;
00021 }
00022 }
00023
00024 OPTIONPAIRFNC ostream& STDCALL operator << ( ostream& os, const option_pair& rhs) {
00025 os << "S = " << setprecision(3) << rhs._S << endl;
00026 os << "K = " << setprecision(3) << rhs._K << endl;
00027 os << "Tau = " << rhs._tau << endl;
00028 os << "alpha = " << rhs._alpha << endl;
00029 os << "r = " << rhs._r << endl;
00030 os << "sigma = " << rhs._sigma << endl;
00031 os << "C = " << rhs._C << endl;
00032 os << "P = " << rhs._P << endl;
00033 os << "dC_dS = " << rhs._dC_dS << endl;
00034 os << "dP_dS = " << rhs._dP_dS << endl;
00035 os << "d2C_dS2 = " << rhs._d2C_dS2 << endl;
00036 os << "d2P_dS2 = " << rhs._d2P_dS2 << endl;
00037 os << "dC_dsigma = " << rhs._dC_dsigma << endl;
00038 os << "dP_dsigma = " << rhs._dP_dsigma << endl;
00039 os << "dC_dtau = " << rhs._dC_dtau << endl;
00040 os << "dP_dtau = " << rhs._dP_dtau << endl;
00041 return os;
00042 }
00043
00044 double option_pair::C_sigma( double sigma) {
00045 if (sigma != _sigma) put_sigma( sigma);
00046 return _C;
00047 }
00048
00049 double option_pair::P_sigma( double sigma) {
00050 if (sigma != _sigma) put_sigma( sigma);
00051 return _P;
00052 }
00053
00054 void option_pair::set_call_immediate_exercise() const
00055 {
00056 _C = _S - _K;
00057 if (_C > 0) {
00058 _dC_dS = 1.0;
00059 } else {
00060 _C = 0;
00061 _dC_dS = 0;
00062 }
00063
00064 _d2C_dS2 = 0;
00065 _dC_dtau = 0;
00066 _dC_dsigma = 0;
00067 }
00068
00069 void option_pair::set_put_immediate_exercise() const
00070 {
00071 _P = _K - _S;
00072 if (_P > 0) {
00073 _dP_dS = -1.0;
00074 } else {
00075 _P = 0;
00076 _dP_dS = 0;
00077 }
00078
00079 _d2P_dS2 = 0;
00080 _dP_dtau = 0;
00081 _dP_dsigma = 0;
00082 }
00083
00084 #ifdef CHECK
00085 #undef CHECK
00086 #endif
00087 #ifdef linux
00088 #define CHECK(y,z,a) if (y) { _error_msg = __STRING(y)" at line "\
00089 __STRING(z)" in " a "::check_attributes"; \
00090 return (_erno = z);}
00091 #else
00092 #define CHECK(y,z,a) if (y) {_error_msg = #y" at line "\
00093 #z" in " #a"::check_attributes"; \
00094 return (_erno = z);}
00095 #endif
00096
00097 int option_pair::strictly_check_attributes(
00098 double S,
00099 double K,
00100 double Tau,
00101 double Alpha,
00102 double R,
00103 double Sigma)
00104 {
00105 #define Funcname "option_pair::check_attributes"
00106
00107 _error_msg = "";
00108 _erno = 0;
00109
00110 CHECK(S <= 0, __LINE__, Funcname);
00111 CHECK(K <= 0, __LINE__, Funcname);
00112 CHECK(Tau <= 0, __LINE__, Funcname);
00113 CHECK(R < 0, __LINE__, Funcname);
00114 CHECK(Sigma <= 0, __LINE__, Funcname);
00115 CHECK(is_NA(Sigma), __LINE__, Funcname);
00116
00117 return 0;
00118 }
00119
00134 double option_pair::call_implied_sigma(
00135 double call_price,
00136 bool show_iterations)
00137 {
00138 int erno;
00139
00140 erno = strictly_check_attributes(
00141 _S,
00142 _K,
00143 _tau,
00144 _alpha,
00145 _r,
00146 _sigma);
00147
00148 if (erno) {
00149 _C_implied_sigma = NA;
00150 throw std::domain_error( _error_msg);
00151 }
00152
00153 if (call_price < call_intrinsic_value()) {
00154 _C_implied_sigma = NA;
00155 throw std::domain_error( "call_price < call_intrinsic_value in option_pair::call_implied_sigma");
00156 }
00157
00158 _input_call_price = call_price;
00159
00160 double sigma0, sigma1, price_sigma0, price_sigma1;
00161
00162 sigma0 = .01;
00163 sigma1 = .50;
00164
00165 stradle_value(
00166 sigma0,
00167 sigma1,
00168 price_sigma0,
00169 price_sigma1,
00170 call_price,
00171 *this,
00172 &option_pair::C_sigma,
00173 true,
00174 true,
00175 1,
00176 1e-5,
00177 1e5);
00178
00179 Bisection_Secant< option_pair, double >
00180 solution(
00181 sigma0,
00182 sigma1,
00183 price_sigma0,
00184 price_sigma1,
00185 call_price,
00186 .0001,
00187 .0001,
00188 100,
00189 *this,
00190 &option_pair::C_sigma);
00191
00192 solution.do_iteration( show_iterations);
00193
00194 if (!solution.get_converged()) {
00195 _C_implied_sigma = NA;
00196 throw std::domain_error( "sigma did not converge in option_pair::call_implied_sigma");
00197 }
00198
00199 return solution.get_x_mid();
00200 }
00201
00202
00203
00218 double option_pair::put_implied_sigma(
00219 double put_price,
00220 bool show_iterations)
00221 {
00222 int erno;
00223
00224 erno = strictly_check_attributes(
00225 _S,
00226 _K,
00227 _tau,
00228 _alpha,
00229 _r,
00230 _sigma);
00231
00232 if (erno) {
00233 _P_implied_sigma = NA;
00234 throw std::domain_error( _error_msg);
00235 }
00236
00237 if (put_price < put_intrinsic_value()) {
00238 _P_implied_sigma = NA;
00239 throw std::domain_error( "put_price < put_intrinsic_value in option_pair::put_implied_sigma");
00240 }
00241
00242 _input_put_price = put_price;
00243
00244 double sigma0, sigma1, price_sigma0, price_sigma1;
00245
00246 sigma0 = .01;
00247 sigma1 = .50;
00248
00249 stradle_value(
00250 sigma0,
00251 sigma1,
00252 price_sigma0,
00253 price_sigma1,
00254 put_price,
00255 *this,
00256 &option_pair::P_sigma,
00257 true,
00258 true,
00259 1,
00260 1e-5,
00261 1e5);
00262
00263 Bisection_Secant< option_pair, double >
00264 solution(
00265 sigma0,
00266 sigma1,
00267 price_sigma0,
00268 price_sigma1,
00269 put_price,
00270 .0001,
00271 .0001,
00272 100,
00273 *this,
00274 &option_pair::P_sigma);
00275
00276 solution.do_iteration( show_iterations);
00277
00278 if (!solution.get_converged()) {
00279 _P_implied_sigma = NA;
00280 throw std::domain_error( "sigma did not converge in option_pair::put_implied_sigma");
00281 }
00282
00283 return solution.get_x_mid();
00284 }
00285