build_mcov.sh0100775000076400007640000000135710011033161012513 0ustar brianbrian# Compile and link mcov # a utility that determines an option's value # using a Monte Carlo technique # YOU MAY NEED to substitute gcc (or whatever your C++ # compiler is called) for g++, below. Using Red Hat 9, # I found that gcc did not pick the correct libraries. # The header file mcovaluer.h is required. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Use the command that uses the name of your C++ compiler: # cc might be the name of your C++ compiler... # cc -o mcov mcovaluer.cxx mcov.cxx # use the GNU project C/C++ compiler... # gcc -o mcov mcovaluer.cxx mcov.cxx # use the GNU project C/C++ compiler... # (this works on Red Hat 9; gcc picks wrong libraries) g++ -o mcov mcovaluer.cxx mcov.cxx conv_yahoo.sh0100775000076400007640000000167110011033161012533 0ustar brianbrian# conv_yahoo.sh oprice data conversion # from historical data from Yahoo Finance, # Note: raw data is latest first; output in latest last # Output: day_num price_close date-string infil=$1 outfil=$2 first_day_num=$3 if [[ $# != 3 ]]; then echo ' ' echo 'Usage conv_yahoo.sh ' echo ' (by convention: output file type: .mcod)' echo ' ' exit fi if [[ $outfil == $infil ]]; then echo ' ' echo 'ERROR: Output file same as input. Abort.' echo ' ' exit fi tmpbase=tmp.conv_ya.tmp tmp1=${tmpbase}.1 tmp2=${tmpbase}.2 gawk ' BEGIN { iday = 10000 } { if ($0 ~ /^#/ || NF < 7 || $6 == "0") next daystr = sprintf ("%06d", --iday) gsub (",", "",$6) print daystr " " $5 " " $1 # day-num, close, date-string }' $infil >$tmp1 sort $tmp1 >$tmp2 gawk -v iday=$first_day_num ' { daystr = sprintf ("%06d", iday++) print daystr " " substr($0,8) }' $tmp2 >$outfil rm $tmp1 $tmp2 INSTALL.txt0100664000076400007640000000521110011033161011671 0ustar brianbrian================================================================= INSTALL.txt - Installing MCOV - Monte Carlo Option Valuer Contents: Downloading a Distribution File Unpacking a Distribution Compiling the Program (optional) = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Downloading a Distribution File Download an MCOV distribution file for your system (Windows or Unix/Linux) from www.mcov.org. Go to the Download page, click on the appropriate link, and let your browser save the file on your system. Move the distribution file to an empty directory. = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Unpacking the Distribution In Windows, unzip the distribution file with a zip application or, in a command window: unzip mcov080.zip (or whatever the filename is) In Unix/Linux, in a terminal window: tar -xzf mcov.0.8.0.gz (or whatever the filename is) = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Compiling the Program (optional) The program mcov may be compiled with the command: gcc -o mcov mcovaluer.cxx mcov.cxx gcc is the GNU project C++ compiler; you may need to substitute gcc with g++ or cc or whatever your compiler is called. On Red Hat 9, the gcc command has problems picking the correct library, so this command is used: g++ -o mcov mcovaluer.cxx mcov.cxx The mcov program (and any program using mcovaluer.cxx) depend on the header file mcovaluer.h = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Copyright and Open Source License Copyright (c) Brian Marshall 2003 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================= mcovaluer.cxx0100664000076400007640000004357310011033161012560 0ustar brianbrian// ================================================================ // Implementation of functions declared in mcovaluer.h // // See mcovaluer.h for more information. // // See copyright notice and license at end of this file. // // ---------------------------------------------------------------- #include #include #include #include #include "mcovaluer.h" using namespace std; // ================================================================ // mcoOption - Option on an underlying financial instrument // // ---------------------------------------------------------------- // Construct an mcoOption mcoOption::mcoOption (char put_call, double strike_price, long days_to_expiry) : m_put_call(put_call), m_strike_price(strike_price), m_days_to_expiry(days_to_expiry) { m_iday_expiry = -1; } // ---------------------------------------------------------------- // Initialize the option and return true if it can be used // with the passed dayset. // Return true if this option's attributes are reasonable. // // This function is called by an mcoValuer function after the // history is read but before any projection is done. bool mcoOption::initialize (mcoDaySet *dayset) { mcoErr *e = mcoErr::instance(); if (e->is_err()) return false; if (!dayset) { e->err("mcoOption::initialize called with null dayset"); return false; } if (m_put_call == 'p') { m_put_call = 'P'; } else if (m_put_call == 'c') { m_put_call = 'C'; } else if (m_put_call != 'P' && m_put_call != 'C') { e->err("put_call must be P or C"); return false; } if (m_strike_price <= 0.0 || m_strike_price > 100000.0) { e->err("Bad strike-price: "); e->append (m_strike_price); return false; } if (m_days_to_expiry < 1 || m_days_to_expiry > 500) { e->err("Bad Days-to-expiry value: "); e->append (m_days_to_expiry); return false; } if (m_days_to_expiry > dayset->max_proj()) { e->err("Days-to-expiry is too high: "); e->append (m_days_to_expiry); return false; } set_iday_expiry (dayset->iday_hist_last() + m_days_to_expiry); } // ================================================================ // mcoValuer - Object to determine value of an option // // ---------------------------------------------------------------- // Construct an mcoValuer mcoValuer::mcoValuer (const char *hist_file, mcoSellStratBase *ss, mcoPDayStratBase *ps, mcoDayFactoryBase *df, long max_hist, long max_proj) { mcoErr *e = mcoErr::instance(); // There may be a singleton... if (e) delete e; e = mcoErr::instance(); // Create a fresh one. if (df) { m_day_factory = df; m_owns_day_factory = false; } else { m_day_factory = new mcoDayFactory; if (!m_day_factory) { e->err("ERROR allocating day-factory"); cleanup(); return; } m_owns_day_factory = true; } m_dayset = new mcoDaySet (hist_file, m_day_factory, max_hist, max_proj); if (! m_dayset) { if (!e->is_err()) e->err("ERROR creating dayset"); cleanup(); return; } if (ss) { m_sell_strategy = ss; ss->set_dayset(m_dayset); m_owns_sell_strategy = false; } else { m_sell_strategy = new mcoSellStrategy1 (m_dayset); if (!m_sell_strategy) { e->err("ERROR allocating sell-strategy"); cleanup(); return; } m_owns_sell_strategy = true; } if (ps) { m_pday_strategy = ps; ps->set_dayset(m_dayset); m_owns_pday_strategy = false; } else { m_pday_strategy = new mcoPDayStrategy1 (m_dayset); if (!m_pday_strategy) { e->err("ERROR allocating sell-strategy"); cleanup(); return; } m_owns_pday_strategy = true; } } // ---------------------------------------------------------------- // Destruct an mcoValuer mcoValuer::~mcoValuer (void) { cleanup(); } // ---------------------------------------------------------------- // Cleanup the mcoValuer so it can be deleted. void mcoValuer::cleanup (void) { if (m_pday_strategy && m_owns_pday_strategy) { delete m_pday_strategy; } if (m_sell_strategy && m_owns_sell_strategy) { delete m_sell_strategy; } if (m_day_factory && m_owns_day_factory) { delete m_day_factory; } if (m_dayset) delete m_dayset; mcoErr *e = mcoErr::instance(); if (e) delete e; } // ---------------------------------------------------------------- // Determine the value of an option. double mcoValuer::option_value (mcoOption *opt, long num_tries) { mcoErr *e = mcoErr::instance(); if (e->is_err()) return -9999999.99; if ( ! opt->initialize(m_dayset) ) return -9999999.99; if (num_tries < 1 || num_tries > 100000) { e->err("Number of tries must be between 1 and 100000"); return -9999999.99; } double ave_tot = 0.0; double ave_num = 0.0; double ave_val = 0.0; for (long itry=0; itryis_err()) return -9999999.99; ave_tot += do_try(opt); ave_num += 1.0; } // end of loop through tries if (ave_num > 0.0) ave_val = ave_tot / ave_num; return ave_val; } // ---------------------------------------------------------------- // Do a try and return the value of the option. double mcoValuer::do_try (mcoOption *opt) { mcoErr *e = mcoErr::instance(); double opt_val = 0.0; m_dayset->reset_projection(); for (long i=0; idays_to_expiry(); i++) { // Identify day to use as prototype for price movement long iday_proto = m_pday_strategy->prototype_iday(); if (e->is_err()) return -9999999.99; // Apply prototype's action to day being projected m_pday_strategy->apply_prototype(iday_proto); if (e->is_err()) return -9999999.99; // Decide if option should be sold this day double price_if_sold = m_sell_strategy->price_if_sold(opt); if (price_if_sold > 0.0) { // option was sold opt_val = m_sell_strategy->option_bid(opt, price_if_sold); break; } // end of block if option is sold if (e->is_err()) return -9999999.99; } // end of loop through days until option expires. return opt_val; } // ================================================================ // mcoDayBase - Base class for day in underlying instrument. // // ---------------------------------------------------------------- // Note that this day is set (called by set() functions) void mcoDayBase::set_is_set (bool sis) { m_is_set = sis; if (sis) m_parent->note_day_is_set(m_iday); } // ================================================================ // mcoDay - A day for the underlying instrument. // // ---------------------------------------------------------------- // Return a pointer to a specified day, downcast to this type. mcoDay * mcoDay::day (long iday) { return ( (mcoDay*) parent()->day(iday) ); } // ---------------------------------------------------------------- // Calculate m_close_chg1 void mcoDay::calc_close_chg1 (void) { long prev_iday = iday() - 1; if (prev_iday < 0) return; // no previous day double prev_close = day(prev_iday)->price_close(); double prev_daynum = day(prev_iday)->daynum(); if (daynum() != prev_daynum+1) return; // days not continuous if (prev_close >= 0.0) { m_close_chg1 = m_price_close / prev_close; } } // ---------------------------------------------------------------- // Set the values from separate fundamental values. void mcoDay::set (long daynum, double prc_close) { set_daynum(daynum); m_price_close = prc_close; calc_close_chg1(); set_is_set(true); } // ---------------------------------------------------------------- // Set the values from a non-comment record from an xxx.mcod file bool mcoDay::set (const string& str) { mcoErr *e = mcoErr::instance(); istringstream ist (str); long a_daynum; double a_price_close; ist >> a_daynum >> a_price_close; if (a_daynum < -20000 || a_daynum > 20000) { e->err("ERROR: daynum must be between -20000 and 20000 : "); e->append (a_daynum); return false; } if (a_price_close < 0.01 || a_price_close > 10000.0) { e->err("Error in price_close in history: "); e->append(a_price_close); e->append(" (daynum: "); e->append(a_daynum); e->append(")"); return false; } set (a_daynum, a_price_close); return true; } // ================================================================ // mcoDaySet - Set of days - history and projection // // ---------------------------------------------------------------- // Construct a dayset. mcoDaySet::mcoDaySet (const char *hist_file, mcoDayFactoryBase *df, long max_hist_days, long max_proj_days) : m_max_hist(max_hist_days), m_max_proj(max_proj_days) { m_num_hist = m_num_proj = 0; m_day = 0; m_history_is_set = false; mcoErr *e = mcoErr::instance(); if (!hist_file) { e->err("Error: no history file specified"); cleanup(); return; } if (max_hist_days < 2 || max_hist_days > 100000) { e->err("max_hist_days must be between 2 and 100000."); cleanup(); return; } if (max_proj_days < 1 || max_proj_days > 1000) { e->err("max_proj_days must be between 1 and 1000."); cleanup(); return; } m_day = new (mcoDayBase*) [max_day()]; if (!m_day) { e->err("ERROR allocating new day array"); cleanup(); return; } for (long i=0; iis_err()) { e->err("Error: History file: "); e->append (hist_file); e->append (" has fewer than two days"); } cleanup(); return; } m_history_is_set = true; long daynum = m_day[iday_hist_last()]->daynum(); long iday_last = iday_proj_first() + max_proj() - 1; for (long iday=iday_proj_first(); iday<=iday_last; iday++) { m_day[iday] = df->new_day(this,iday); if (!m_day[iday]) { if (!e->is_err()) { e->err("ERROR allocating creating new day"); } cleanup(); return; } m_day[iday]->set_daynum(++daynum); } } // ---------------------------------------------------------------- // Destruct a dayset. mcoDaySet::~mcoDaySet (void) { cleanup(); } // ---------------------------------------------------------------- // Note that the indicated day has been set. void mcoDaySet::note_day_is_set (long iday) { if ( iday < num_set() ) { mcoErr *e = mcoErr::instance(); e->err("Bug: Days set out of order"); return; } if (m_history_is_set) { // projected day if ( (iday+1) > num_set() ) { m_num_proj = (iday+1) - m_num_hist; } } else { // history day if ( (iday+1) > m_num_hist) m_num_hist = iday + 1; } } // ---------------------------------------------------------------- // Cleanup a dayset so that it can be deleted. void mcoDaySet::cleanup (void) { if (m_day) { for (long i=0; ierr("Error opening history file "); e->append (hist_file); return false; } long iday = -1; // index into m_day string str; char buf[501]; while (true) { // records in history file... if (e->is_err()) return false; ifs.getline(buf,500); // read a line into the char-array. if (ifs.eof()) break; if (buf[0] == '#') continue; str = buf; // Move C-style string into C++ string if (m_num_hist >= max_hist()) { e->err("Error: History file has too many days"); return false; } iday++; m_day[iday] = df->new_day(this,iday); if (!m_day[iday]) { e->err("Error creating new day"); return false; } if ( ! m_day[iday]->set(str) ) return false; } // end of loop through records in history file return true; // success } // ---------------------------------------------------------------- // Reset the projection - the projected days void mcoDaySet::reset_projection (void) { if ( num_proj() <= 0 ) return; for (long iday = iday_proj_first(); iday <= iday_proj_last(); iday++) { day(iday)->reset(); } m_num_proj = 0; } // ================================================================ // mcoSellStrategy1 - deciding when to sell and at what price // // ---------------------------------------------------------------- // Decide whether the option was sold during the last projected // day. If it was, return the price of the underlying instrument // at the time of the option sale; otherwise return 0.0. double mcoSellStrategy1::price_if_sold (mcoOption *opt) { if (dayset()->num_proj() >= opt->days_to_expiry() ) { long iday_last = dayset()->iday_proj_last(); double prc = day(iday_last)->price_close(); if (opt->put_call() == 'P') { if (prc < opt->strike_price()) return prc; } else { // option is a call if (prc > opt->strike_price()) return prc; } } return 0.0; } // ---------------------------------------------------------------- // Estimate the time-value component of the bid for the option // at the time the option is sold. Since, in this strategy, // we sell the option just before expiry, time-value is zero. double mcoSellStrategy1::rem_time_value (mcoOption *opt, double price) { return 0.0; } // ---------------------------------------------------------------- // Estimate the bid (the price someone is willing to pay) // for the option which was sold when the underlying instrument // was selling for 'price'. double mcoSellStrategy1::option_bid (mcoOption *opt, double price) { double val = 0.0; val += rem_time_value (opt, price); double strike = opt->strike_price(); if (opt->put_call() == 'P') { // Option is a Put if (price < strike) val += (strike - price); } else { if (price > strike) val += (price - strike); } val *= 0.99; // apply bid/ask spread return val; } // ================================================================ // mcoPDayStrategy1 - pick/apply a prototype day // // This is a simple implementation of the strategy. // // ---------------------------------------------------------------- // Identify a day to use as a prototype for the next day // to be projected. // // In this simple implementation of this strategy: // pick a day of history (after the first) at random. long mcoPDayStrategy1::prototype_iday (void) { long n = dayset()->num_hist() - 2; long iday = mcoRand::randnum(n) + 1; // 1(2nd) to end. return iday; } // ---------------------------------------------------------------- // Apply a prototype day to the next day to be projected. void mcoPDayStrategy1::apply_prototype (long iday_proto) { long iday_prev = dayset()->num_set() - 1; // last day set long daynum_prev = day(iday_prev)->daynum(); long iday_proj = iday_prev + 1; long daynum_proj = daynum_prev + 1; double close_prev = day(iday_prev)->price_close(); double close_chg1 = day(iday_proto)->close_chg1(); if (close_chg1 <= 0.0) close_chg1 = 1.0; // do the projection of the closing-price... double close_proj = close_prev * close_chg1; day(iday_proj)->set(daynum_proj, close_proj); } // ================================================================ // mcoErr - Error status/message - a singleton. // // ---------------------------------------------------------------- // Definition of static data member. mcoErr * mcoErr::m_instance = 0; // ================================================================ // mcoRand - Random number generator - a singleton. // // ---------------------------------------------------------------- // Definition of static data member. bool mcoRand::m_is_setup = false; // ---------------------------------------------------------------- // Return a random number between zero and maxnum. long mcoRand::randnum (long max_num) { if (!mcoRand::m_is_setup) { time_t tt; struct tm *ptm; time (&tt); ptm = localtime(&tt); int seed = ptm->tm_hour * 10000 + ptm->tm_min * 100 + ptm->tm_sec; srand(seed); mcoRand::m_is_setup = true; srand(seed); } return int((double(max_num)*rand())/(RAND_MAX+1.0)); } // ================================================================ // Copyright and Open Source License // // Copyright (c) Brian Marshall 2004 // // Permission is hereby granted, free of charge, to any // person obtaining a copy of this software and associated // documentation files (the "Software"), to deal in the // Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // ================================================================ mcovaluer.h0100664000076400007640000005551610011033161012205 0ustar brianbrian// ================================================================ // mcovaluer.h - Monte Carlo Option Valuer // // mcoValuer (and supporting classes) - // used to determine the value of a financial option // using a Monte Carlo method. // // See copyright notice and license at end of this file. // // 'price' is for the underlying instrument (stock, future, etc.) // 'bid' is what is received when the option is sold #ifndef _mcovalue_h_guard #define _mcovalue_h_guard #include #include using namespace std; // ---------------------------------------------------------------- // Purpose of the Monte Carlo Option Valuer // // An object of the mcoValuer class can be used to estimate // the value of an American-Style option (one that can be // exercised at any time) to a person with a particular // strategy for deciding when to sell the option. // // ------------------------------------------------------ // The Monte Carlo Method // // The MCOV software uses a Monte Carlo method. The price // of the underlying instrument (stock/future/index) is // projected, day by day, until the option is sold or // expires. When this happens, the value of the option // is estimated; if the option was not sold, this value // is zero. This process is repeated many times, // generating many different values for the option. // // The MCOV software estimates the value of the option // as the average of the set of generated values (some // of which are zero). // // A new day is projected from the latest day by: // - picking a 'prototype' day from the price-history // - identifying the changes during the prototype day // (starting from the previous close) // - applying the same changes to the latest day to // project the new day // // The user of the application will generally use // price-history data that includes some amount of the // past up to today, plus, perhaps, additional data from // other periods in the past. // // When an option is sold or expires, and its value is // estimated, a simplistic method is used to estimate // the remaining time value. Therefore, The MCOV // software works best if the option is sold when the // time value is relatively low: // - because the option will expire soon, or, // - because the option is very deep in the money. // // // ------------------------------------------------------ // Strategies and Strategy Objects // // The MCOV software is controlled by strategy objects // that make various decisions or estimations: // - was the option sold in the latest day? // - price of underlying instrument when option sold // - bid for the option when it was sold // - day to use as prototype for next projection // - how to project a day using a prototype day // // Strategies may be modified or replaced by subclassing // the default strategy classes (or the base classes). // Strategy classes depend upon the dayset (the history // and the projected days) being composed of the correct // type of day-object. A day-factory class may be // subclassed to construct the correct type of day. // // Only a very simple set of strategies are currently // included in the MCOV software, and they are used // by default: // - the option is sold just before it expires (if it is // in the money) // - the bid for the option is estimated be 99% of the // the intrinsic value // - prototype days are picked at random from the history // - day-objects store closing-price and change since // previous-close (as a ratio) // - the closing-price of a day being projected is the // previous close multiplied by the change-ratio // of the prototype day // // Much more sophisticated and subtle stategies can be // developed, particularly in relation to the question // of picking prototype days. // // // ------------------------------------------------------ // Application of the MCOV Classes // // In a simple application of the MCOV classes: // // - an mcoValuer object is created, which reads a // specified price-history file // // - an object is created which describes an option // // - the option-object is passed to a function of // the mcoValuer object, which estimates the // value of the option // // - an error-status object is checked, and if an // error occurred, a message is printed; otherwise, // the value of the option is printed. // // // ------------------------------------------------------ // Notes about the C++ // // If an error occurs, the software records the information // in a singleton instance of mcoErr rather than throwing // an exception (which some compilers may not support). // // Downcasting (casting *base to *derived) in classes that KNOW // the type that they require is done with C-style casts rather // than dynamic-casts (which some compilers may not support). // This can only be a problem if an mcoValuer is constructed // with a combination of day-factory and strategies that is // inappropriate. Therefore, testing for this situation should // be done once (per strategy, perhaps), rather than every time // a day (for instance) is referenced. // // ------------------------------------------------------ // Design Patterns and Flexibility // // mcoDay is a very simple subclass of mcoDayBase - the only // fundamental (as opposed to derived) attributes are: // - the day-number, and, // - the closing-price. // mcoDay or mcoDayBase may be subclassed to hold more // information about a day for an underlying instrument. // // A new day subclass is used by passing an instance of a new // new subclass of mcoDayFactoryBase (an Abstract Factory) to // the mcoValuer constructor. // // Functions that answer various questions are encapsulated in // in Strategy classes, which may be subclassed. If the user // of the valuer wants to use their own strategies, Strategy // objects may be passed to the mcoValuer constructor. A // particular strategy subclass will depend on the Valuer's // dayset containing days of a particular subclass. // // Singletons - classes that will have only one instance: // - random number generator // - error-status // // // ---------------------------------------------------------------- // Classes (subclassing shown by indentation) class mcoOption; // An option on a stock/future/index class mcoValuer; // Object to value an option class mcoDayBase; // Base: day of underlying instrument class mcoDay; // Day based on close-price class mcoDaySet; // Days - history and projection class mcoTryStrategy; // Base: strategies used in tries class mcoSellStratBase; // When to sell, results class mcoSellStrategy1; // Simple: sell at expiry class mcoPDayStratBase; // Picking/using prototype days class mcoPDayStrategy1; // Simple: random day class mcoDayFactoryBase; // Base: return a new day class mcoDayFactory; // Default: return new mcoDay class mcoErr; // Error status, message (singleton) class mcoRand; // Random number generator (singleton) class mcoSentry; // Ensure mcoValuer objects deleted // ================================================================ // mcoOption - Option on an underlying financial instrument // // This class will generally not be subclassed; if you want to // maintain data about the (state of) the option, add attributes // to your subclass days and/or strategies. // // initialize() will be called by an mcoValuer function. class mcoOption { char m_put_call; double m_strike_price; long m_days_to_expiry; // At time option bought/created. long m_iday_expiry; // Set by user of object. public: mcoOption (char put_call, double strike_price, long days_to_expiry); virtual ~mcoOption (void) {} void set_iday_expiry (long x) { m_iday_expiry = x; } char put_call (void) const { return m_put_call; } double strike_price (void) const { return m_strike_price; } long days_to_expiry (void) const { return m_days_to_expiry; } long iday_expiry (void) const { return m_iday_expiry; } bool initialize (mcoDaySet *dayset); // called by mcoValuer }; // ================================================================ // mcoValuer - Object to determine the value of an option // // If strategy or factory objects are passed to the constructor, // they are owned by the caller - they will not be deleted upon // destruction. class mcoValuer { mcoDaySet * m_dayset; mcoSellStratBase * m_sell_strategy; mcoPDayStratBase * m_pday_strategy; mcoDayFactoryBase * m_day_factory; bool m_owns_sell_strategy; bool m_owns_pday_strategy; bool m_owns_day_factory; protected: void cleanup (void); double do_try (mcoOption *opt); public: mcoValuer (const char *hist_file, mcoSellStratBase *ss =0, mcoPDayStratBase *ps =0, mcoDayFactoryBase *df =0, long max_hist =5000, long max_proj =100); virtual ~mcoValuer (void); virtual double option_value (mcoOption *opt, long num_tries =2000); }; // ================================================================ // mcoDayBase - Base class for a day. // // An instance of a subclass of mcoDayBase holds information // about one day for the underlying instrument (stock, future). // // Days MUST be created and set in chronological order because // the constructor of a subclass of mcoDayBase may derive values // by referring to other days in the DaySet. // // set() functions in subclasses MUST do the setting by // calling set() functions in the parent-class so that // derived-values and the is_set flag get set. // // Subclasses may override the set(const char *) function // to set the day from a string (such as a record from a file). // // In subclasses, an overriding reset() must call this reset(). class mcoDayBase { // unchanging attributes set during construction mcoDaySet * m_parent; long m_iday; // index used by parent // attributes set when day is 'set' long m_daynum; // -1 if it is not set bool m_is_set; public: mcoDayBase (mcoDaySet *parent, long iday) : m_parent(parent), m_iday(iday) { m_daynum = -1; m_is_set = false; } virtual ~mcoDayBase (void) {} void set_daynum (long x) { m_daynum = x; } void set_is_set (bool sis =true); mcoDaySet * parent (void) const { return m_parent; } long iday (void) const { return m_iday; } long daynum (void) const { return m_daynum; } bool is_set (void) const { return m_is_set; } virtual void reset (void) { set_is_set(false); } virtual bool set (const string& str) { return true; } }; // ================================================================ // mcoDay - a simple day based on the daily close-price // // People wishing to define new day classes may subclass // this class or its parent (mcoDayBase). class mcoDay : public mcoDayBase { // fundamental attributes double m_price_close; // derived attributes (from this and other days) double m_close_chg1; // close / close-1-day-back protected: void calc_close_chg1 (void); mcoDay * day (long iday); // downcast to this type public: mcoDay (mcoDaySet *parent, long iday) : mcoDayBase(parent,iday) {} virtual ~mcoDay (void) {} double price_close (void) const { return m_price_close; } double close_chg1 (void) const { return m_close_chg1; } virtual void reset (void) { m_price_close = m_close_chg1 = 0.0; mcoDayBase::reset(); } void set (long daynum, double prc_close); // set from non-comment record from an xxx.mcod file virtual bool set (const string& str); }; // ---------------------------------------------------------------- // mcoDaySet - Set of days - history and projection // // Days MUST be created and set in chronological order. // Projected days may be reset, and then projected days // may be set again (in chronological order). // // The history some history up until today (or yesterday). // It may also contain days from periods in the past that // the user would like to use in the Monte Carlo simulation. // // history_is_set() MUST be called after all history days // have been set and before the first projected day is set. class mcoDaySet { mcoDayBase ** m_day; // Array of pointers to days. long m_max_hist; // Maximum days of history in m_day. long m_max_proj; // Maximum days that can be projected. long m_num_hist; // Number of days of history. long m_num_proj; // Number of days projected. bool m_history_is_set; protected: void cleanup (void); bool read_hist (const char *histfile, mcoDayFactoryBase *df); public: mcoDaySet (const char *hist_file, mcoDayFactoryBase *df =0, long max_hist_days =5000, long max_proj_days = 100); virtual ~mcoDaySet (void); long max_hist (void) const { return m_max_hist; } long max_proj (void) const { return m_max_proj; } long num_hist (void) const { return m_num_hist; } long num_proj (void) const { return m_num_proj; } long max_day (void) const { return m_max_hist+m_max_proj; } long num_day (void) const { return m_num_hist+m_max_proj; } long num_set (void) const { return m_num_hist+m_num_proj; } long iday_last_set (void) const { return m_num_hist-1; } long iday_hist_first (void) const { return 0; } long iday_hist_last (void) const { return m_num_hist-1; } long iday_proj_first (void) const { return m_num_hist; } long iday_proj_last (void) const { return m_num_hist+m_num_proj-1; } mcoDayBase * day (long iday) const { return (m_day[iday]); } void note_day_is_set (long iday); void history_is_set (void) { m_history_is_set = true; } void reset_projection (void); }; // ================================================================ // mcoTryStrategy - Base class of strategies used in tries. // // If a dayset is not passed into the constructor, it must // be set via set_dayset() before the strategy is used. // // This is a pure virtual base class for the strategy. // // Subclasses will generally depend on a particular subclass // of mcoDayBase being used in the dayset, and they may define // a function to do the downcast. class mcoTryStrategy { mcoDaySet * m_dayset; // not owned by this strategy protected: mcoDaySet * dayset (void) const { return m_dayset; } public: mcoTryStrategy (mcoDaySet *ds =0) : m_dayset(ds) {} virtual ~mcoTryStrategy (void) {} void set_dayset (mcoDaySet *ds) { m_dayset = ds; } }; // ================================================================ // mcoSellStratBase - In a try: Should I sell today? // // The virtual function sell_this_day() is called after // each day is projected. It determines whether the option // was sold during this day: // if sold: return price of underlying instrument (ex. stock) // if not sold: return 0.0 // // The virtual function option_bid() is called, if the option // was sold, after the loop of days - ie. after the day the // option expires has been projected. It returns the bid - the // price received for the option when it was sold. This function // is called after the loop so that, if the option is sold early, // the remaining days can be used in the estimation of time value // received when the option was sold. // // The rem_time_value() function returns the remaining-time-value // component of the bid for the option at the time it is sold. // This is sort of weird, inasmuch as the purpose of this file // of classes is to estimate time-value of the option. This can // be done fairly simply, however, if the strategy is to sell // the option when if is close to expiry; if the option is sold // just before expiry, the time-value is zero. // // Subclasses must beware of 'postdictive errors' - for example, // using the close-price to decide to sell earlier than the close. // It is subtle, however - because we don't store every tick, // we have to use the data we have to make deductions about // the value we want to determine. If all we know are closes, // it might be acceptable to assume that a sale during the day // occurred between the close and the previous close (even // though this is not necessarily true). // // This is a pure virtual base class for the strategy. class mcoSellStratBase : public mcoTryStrategy { public: mcoSellStratBase (mcoDaySet *ds =0) : mcoTryStrategy(ds) {} virtual ~mcoSellStratBase (void) {} virtual double price_if_sold (mcoOption *opt) =0; // or 0.0 virtual double rem_time_value (mcoOption *opt, double price) =0; virtual double option_bid (mcoOption *opt, double price) =0; }; // ---------------------------------------------------------------- // mcoSellStrategy1 - In a try: Should I sell today? // // In this simple implementation of this strategy: // Sell just before option expires // // This strategy uses days of type: mcoDay class mcoSellStrategy1 : public mcoSellStratBase { public: mcoSellStrategy1 (mcoDaySet *ds =0) : mcoSellStratBase(ds) {} virtual ~mcoSellStrategy1 (void) {} mcoDay * day (long iday) const { return ( (mcoDay*) dayset()->day(iday) ); } virtual double price_if_sold (mcoOption *opt); // or 0.0 virtual double rem_time_value (mcoOption *opt, double price); virtual double option_bid (mcoOption *opt, double price); }; // ================================================================ // mcoPDaytStratBase - For a day: pick/apply a prototype day // // prototype_iday() identifies a day to act as a prototype // for deciding what will happen on the day being projected. // // apply_prototype() initializes the day being projected // using the prototype day. // // If a dayset is not passed into the constructor, it must // be set via set_dayset() before the strategy is used. // // This is a pure virtual base class for the strategy. class mcoPDayStratBase : public mcoTryStrategy { public: mcoPDayStratBase (mcoDaySet *ds =0) : mcoTryStrategy(ds) {} virtual ~mcoPDayStratBase (void) {} virtual long prototype_iday (void) =0; virtual void apply_prototype (long iday_proto) =0; }; // ---------------------------------------------------------------- // mcoPDayStrategy1 - For a day: pick/apply a prototype day // // This strategy uses days of type: mcoDay class mcoPDayStrategy1 : public mcoPDayStratBase { public: mcoPDayStrategy1 (mcoDaySet *ds =0) : mcoPDayStratBase(ds) {} virtual ~mcoPDayStrategy1 (void) {} mcoDay * day (long iday) const { return ( (mcoDay*) dayset()->day(iday) ); } virtual long prototype_iday (void); virtual void apply_prototype (long iday_proto); }; // ================================================================ // mcoDayFactoryBase - Base class: return a new day class mcoDayFactoryBase { public: mcoDayFactoryBase (void) {} virtual ~mcoDayFactoryBase (void) {} virtual mcoDayBase * new_day (mcoDaySet *ds, long iday) =0; }; // ---------------------------------------------------------------- // mcoDayFactory - Default factory: return new mcoDay class mcoDayFactory : public mcoDayFactoryBase { public: mcoDayFactory (void) {} virtual ~mcoDayFactory (void) {} virtual mcoDayBase * new_day (mcoDaySet *ds, long iday) { return new mcoDay(ds,iday); } }; // ================================================================ // mcoErr - Error status, message - a singleton. // // ex. if ( mcoErr::instance()->is_err() ) then... class mcoErr { static mcoErr * m_instance; string m_msg; protected: mcoErr (void) { m_msg = ""; } // non-public constructor public: ~mcoErr (void) { m_instance = 0; } static mcoErr *instance (void) { if (!m_instance) m_instance = new mcoErr; return m_instance; } bool is_err (void) const { return m_msg.length(); } char const * msg (void) const { return m_msg.c_str(); } void append (const string& str) { m_msg += str; } void append (long lval) { ostringstream ost; ost << lval; append (ost.str()); } void append (int ival) { long lval = ival; append (lval); } void append (double dval) { ostringstream ost; ost << dval; append (ost.str()); } void append (float fval) { double dval = fval; append (dval); } void err (const string& str) { m_msg = ""; append (str); } }; // ================================================================ // mcoRand - Random number generator - a singleton. // // This is actually an odd sort of singleton in that there is // no need to ever create one; all data and methods are static. // Because the constructor is not public, an instance cannot be // defined (unless this class or a subclass was to do it). class mcoRand { static bool m_is_setup; protected: mcoRand (void) {} // constructor not public. public: virtual ~mcoRand (void) {} static long randnum (long maxnum); // num between 0 and maxnum. }; // ================================================================ // mcoSentry - Ensure that mcoValuer objects are deleted. // // Used by application functions in which an mcoValuer object // should be deleted when the function returns. class mcoSentry { mcoValuer * m_mcov; public: mcoSentry (mcoValuer *mcov) : m_mcov(mcov) {} ~mcoSentry (void) { if (m_mcov) delete m_mcov; } }; // ================================================================ #endif // ================================================================ // Copyright and Open Source License // // Copyright (c) Brian Marshall 2004 // // Permission is hereby granted, free of charge, to any // person obtaining a copy of this software and associated // documentation files (the "Software"), to deal in the // Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // ================================================================ mcov.cxx0100664000076400007640000001057010011033161011516 0ustar brianbrian// ================================================================ // Use a Monte Carlo technique to estimate an option's value. // // See copyright notice and license at end of this file. // // Notes: // // - This file illustrates two ways of creating an mcoValuer // object: // - using default strategies and limits // - using your own strategies and limits // // - Program arguments are not checked here because the // mcoValuer does thorough argument checking. // // ---------------------------------------------------------------- #include #include #include "mcovaluer.h" using namespace std; // ---------------------------------------------------------------- // Estimate an option value using an mcoValuer object. int main (int argc, char *argv[]) { if (argc < 5 || argc > 6) { cout << "\n" << "Usage:\n" << " mcov history_file put-call strike_price " << "days_to_expiry [tries]\n" << " Examples:\n" << " mcov mydata1.opd C 47.50 11\n" << " mcov xiu2003.opd P 45.00 19 1000\n" << " History-File: one line/trading-day, \n" << " Earliest first; may contain gaps;\n" << " Lines: daynum closing-price \n" << " Lines beginning with # are ignored.\n\n"; return 1; } // Note that checking of the arguments is done // by mcoValuer and its associated classes. const char * history_file = argv[1]; char put_call = *(argv[2]); double strike = atof(argv[3]); long days = atol(argv[4]); long tries = (argc>=6) ? atol(argv[5]) : 0; mcoErr *e = mcoErr::instance(); // Singleton // If we wanted to use our own strategies, factories, // and limits, we could declare them like this... mcoSellStrategy1 sell_strategy; mcoPDayStrategy1 proto_strategy; mcoDayFactory day_factory; long max_history_days = 2000; long max_projected_days = 100; bool Use_Default_Algorithms_and_Limits = true; mcoValuer *mcov; // Will point to our option-valuer. if (Use_Default_Algorithms_and_Limits) { mcov = new mcoValuer (history_file); } else { mcov = new mcoValuer (history_file, &sell_strategy, &proto_strategy, &day_factory, max_history_days, max_projected_days); } if (e->is_err()) { // Did an error occur? cout << endl << e->msg() << endl; return 1; } else if (!mcov) { cout << "\nERROR creating mcoValuer object\n\n"; return 1; } mcoSentry mcov_sentry(mcov); // ensure that mcov gets deleted mcoOption opt (put_call, strike, days); // declare the option double val = 0.0; if (tries) { val = mcov->option_value (&opt, tries); } else { val = mcov->option_value (&opt); } if (e->is_err()) { // Did an error occur? cout << endl << e->msg() << endl; return 1; } cout << val << endl; // Don't have to delete mcov; the sentry does it. return 0; } // ================================================================ // Copyright and Open Source License // // Copyright (c) Brian Marshall 2004 // // Permission is hereby granted, free of charge, to any // person obtaining a copy of this software and associated // documentation files (the "Software"), to deal in the // Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // // ================================================================ README.txt0100664000076400007640000000713110011033161011523 0ustar brianbrian================================================================= README.txt - Using MCOV Monte Carlo Option Valuer Software Contents: Compiling MCOV Software Default Strategies Running the mcov Program History Data from Yahoo (Unix) = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Compiling MCOV Software The mcov program is compiled with a command (like): gcc -o mcov mcovaluer.cxx mcov.cxx You may need to change gcc to g++ or whatever your compiler is called. See the file INSTALL.txt for more information. = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Strategies - Default and Custom The MCOV software currently include default strategies in which an option is sold just before expiry. A C++ programmer can define new strategies. See the C++ header file for more information. = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Running the mcov Program Given a file of price-history data, the mcov program will print out the value of an option... Usage: mcov hist put-call strike days_to_expiry [tries] Examples: mcov mydata1.opd C 47.50 11 mcov xiu2003.opd P 45.00 19 1000 The price-history file (for the default strategies): - one line per trading day - earliest first; may contain gaps - lines look like: daynum closing-price [anything] - lines beginning with # are ignored = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = History Data from Yahoo (Unix) For the default strategies, you need a price-history file that contains records of day-number and closing-price (separated by white-space). The records may contain anything after the closing price. On a Unix/Linux system, this file may be created from data from Yahoo Finance... - go to the website: http://finance.yahoo.com - enter a stock symbol in the box and click [GO] - click on Historical Prices at the left - set the date-range and click [Get Prices] (if required) - cut and paste the data into a text editor - save this raw data Pick a day-number for the earliest day of data. In the output history-file, all other trading days will have a day-number that goes up from this initial number. It makes no difference to the software what the number is. Pick a name for the output file. Run this Unix shell script: Usage: conv_yahoo.sh infil outfil first-day-num' Example: conv_yahoo.sh raw_april.txt april.mcod 1000 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Copyright and Open Source License Copyright (c) Brian Marshall 2003 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================= RELEASE.txt0100664000076400007640000000153610011033161011651 0ustar brianbrian================================================================= RELEASE.txt - MCOV Releases and Contribution Credits - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Developers and Contributers [BRM] Brian Marshall bmarshall@cleandb.com CleanDB Calgary - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Release History Release Date Status Contributer ------- ----------- -------------- -------------- 0.8.1 2004-02-06 Beta [BRM] Bug involving # in history-file fixed. Comments in the software were improved. 0.8.0 2004-02-04 Beta [BRM] First release. Default strategy: sell just before the option expires. Includes sample history-files. ================================================================= tiny.mcod0100664000076400007640000000050310011033161011650 0ustar brianbrian# Tiny mcov price-history file for testing #DayNum cls (date as string, but not read by software) 010251 46.48 2-Jan-04 010252 46.95 5-Jan-04 010253 47.00 6-Jan-04 010254 47.19 7-Jan-04 010255 47.10 8-Jan-04 010256 46.94 9-Jan-04 010257 47.06 12-Jan-04 010258 47.04 13-Jan-04 010259 47.35 14-Jan-04 010260 47.50 15-Jan-04 xiu_2003.mcod0100664000076400007640000001331710011033161012145 0ustar brianbrian# Price History File for MCOV software # XIU.TO Toronto S&P 60 Index Units #daynum close (date as string, but not read by software) 010000 38.45 3-Jan-03 010001 39.05 6-Jan-03 010002 38.80 7-Jan-03 010003 38.20 8-Jan-03 010004 38.55 9-Jan-03 010005 38.74 10-Jan-03 010006 38.74 13-Jan-03 010007 38.81 14-Jan-03 010008 38.65 15-Jan-03 010009 38.89 16-Jan-03 010010 38.45 17-Jan-03 010011 38.40 20-Jan-03 010012 38.01 21-Jan-03 010013 38.10 22-Jan-03 010014 38.40 23-Jan-03 010015 37.85 24-Jan-03 010016 37.20 27-Jan-03 010017 37.22 28-Jan-03 010018 37.25 29-Jan-03 010019 37.19 30-Jan-03 010020 37.20 31-Jan-03 010021 37.31 3-Feb-03 010022 37.10 4-Feb-03 010023 36.95 5-Feb-03 010024 36.71 6-Feb-03 010025 36.78 7-Feb-03 010026 36.64 10-Feb-03 010027 36.73 11-Feb-03 010028 36.57 12-Feb-03 010029 36.61 13-Feb-03 010030 36.88 14-Feb-03 010031 37.42 17-Feb-03 010032 37.64 18-Feb-03 010033 37.35 19-Feb-03 010034 37.32 20-Feb-03 010035 37.29 21-Feb-03 010036 37.02 24-Feb-03 010037 37.13 25-Feb-03 010038 37.12 26-Feb-03 010039 37.59 27-Feb-03 010040 37.53 28-Feb-03 010041 37.00 3-Mar-03 010042 36.66 4-Mar-03 010043 36.56 5-Mar-03 010044 36.25 6-Mar-03 010045 36.26 7-Mar-03 010046 36.10 10-Mar-03 010047 36.10 11-Mar-03 010048 35.80 12-Mar-03 010049 36.30 13-Mar-03 010050 36.25 14-Mar-03 010051 36.80 17-Mar-03 010052 37.00 18-Mar-03 010053 37.18 19-Mar-03 010054 37.25 20-Mar-03 010055 37.75 21-Mar-03 010056 36.58 24-Mar-03 010057 36.55 25-Mar-03 010058 36.40 26-Mar-03 010059 36.40 27-Mar-03 010060 36.54 28-Mar-03 010061 36.15 31-Mar-03 010062 36.39 1-Apr-03 010063 36.72 2-Apr-03 010064 36.61 3-Apr-03 010065 36.74 4-Apr-03 010066 36.95 7-Apr-03 010067 36.95 8-Apr-03 010068 36.67 9-Apr-03 010069 36.68 10-Apr-03 010070 36.81 11-Apr-03 010071 37.00 14-Apr-03 010072 37.10 15-Apr-03 010073 36.94 16-Apr-03 010074 37.30 17-Apr-03 010075 37.54 21-Apr-03 010076 37.72 22-Apr-03 010077 37.93 23-Apr-03 010078 37.55 24-Apr-03 010079 37.27 25-Apr-03 010080 37.48 28-Apr-03 010081 37.28 29-Apr-03 010082 37.54 30-Apr-03 010083 37.44 1-May-03 010084 37.66 2-May-03 010085 37.88 5-May-03 010086 38.00 6-May-03 010087 37.86 7-May-03 010088 37.70 8-May-03 010089 37.92 9-May-03 010090 38.30 12-May-03 010091 38.28 13-May-03 010092 38.43 14-May-03 010093 38.63 15-May-03 010094 38.51 16-May-03 010095 38.50 20-May-03 010096 38.42 21-May-03 010097 38.80 22-May-03 010098 38.78 23-May-03 010099 38.79 26-May-03 010100 39.10 27-May-03 010101 39.08 28-May-03 010102 38.95 29-May-03 010103 38.98 30-May-03 010104 39.61 2-Jun-03 010105 39.50 3-Jun-03 010106 39.90 4-Jun-03 010107 40.15 5-Jun-03 010108 40.10 6-Jun-03 010109 39.70 9-Jun-03 010110 40.11 10-Jun-03 010111 40.50 11-Jun-03 010112 40.53 12-Jun-03 010113 39.90 13-Jun-03 010114 40.47 16-Jun-03 010115 40.50 17-Jun-03 010116 40.40 18-Jun-03 010117 40.30 19-Jun-03 010118 40.24 20-Jun-03 010119 39.69 23-Jun-03 010120 39.67 24-Jun-03 010121 39.47 25-Jun-03 010122 39.55 26-Jun-03 010123 39.33 27-Jun-03 010124 39.62 30-Jun-03 010125 39.58 2-Jul-03 010126 39.72 3-Jul-03 010127 39.60 4-Jul-03 010128 40.09 7-Jul-03 010129 40.13 8-Jul-03 010130 40.39 9-Jul-03 010131 40.10 10-Jul-03 010132 40.11 11-Jul-03 010133 40.31 14-Jul-03 010134 40.34 15-Jul-03 010135 40.27 16-Jul-03 010136 40.13 17-Jul-03 010137 40.46 18-Jul-03 010138 40.52 21-Jul-03 010139 40.90 22-Jul-03 010140 41.01 23-Jul-03 010141 41.15 24-Jul-03 010142 41.18 25-Jul-03 010143 41.30 28-Jul-03 010144 40.97 29-Jul-03 010145 40.76 30-Jul-03 010146 41.06 31-Jul-03 010147 40.80 1-Aug-03 010148 40.68 5-Aug-03 010149 40.30 6-Aug-03 010150 40.46 7-Aug-03 010151 40.94 8-Aug-03 010152 41.48 11-Aug-03 010153 41.59 12-Aug-03 010154 41.75 13-Aug-03 010155 41.87 14-Aug-03 010156 41.89 15-Aug-03 010157 42.05 18-Aug-03 010158 42.45 19-Aug-03 010159 42.45 20-Aug-03 010160 42.57 21-Aug-03 010161 42.26 22-Aug-03 010162 42.07 25-Aug-03 010163 42.24 26-Aug-03 010164 42.55 27-Aug-03 010165 42.60 28-Aug-03 010166 42.58 29-Aug-03 010167 42.94 2-Sep-03 010168 42.90 3-Sep-03 010169 43.11 4-Sep-03 010170 43.19 5-Sep-03 010171 43.28 8-Sep-03 010172 42.95 9-Sep-03 010173 42.96 10-Sep-03 010174 43.05 11-Sep-03 010175 42.95 12-Sep-03 010176 42.82 15-Sep-03 010177 43.23 16-Sep-03 010178 43.12 17-Sep-03 010179 42.95 18-Sep-03 010180 43.02 19-Sep-03 010181 42.70 22-Sep-03 010182 43.17 23-Sep-03 010183 42.91 24-Sep-03 010184 42.15 25-Sep-03 010185 41.71 26-Sep-03 010186 41.98 29-Sep-03 010187 41.63 30-Sep-03 010188 42.30 1-Oct-03 010189 42.46 2-Oct-03 010190 42.27 3-Oct-03 010191 42.54 6-Oct-03 010192 42.55 7-Oct-03 010193 42.60 8-Oct-03 010194 42.80 9-Oct-03 010195 43.02 10-Oct-03 010196 43.77 14-Oct-03 010197 44.00 15-Oct-03 010198 43.95 16-Oct-03 010199 43.47 17-Oct-03 010200 43.63 20-Oct-03 010201 43.68 21-Oct-03 010202 43.45 22-Oct-03 010203 43.13 23-Oct-03 010204 42.79 24-Oct-03 010205 43.14 27-Oct-03 010206 43.49 28-Oct-03 010207 43.60 29-Oct-03 010208 43.50 30-Oct-03 010209 43.73 31-Oct-03 010210 44.20 3-Nov-03 010211 44.27 4-Nov-03 010212 44.24 5-Nov-03 010213 44.24 6-Nov-03 010214 44.18 7-Nov-03 010215 43.80 10-Nov-03 010216 43.67 11-Nov-03 010217 43.64 12-Nov-03 010218 43.57 13-Nov-03 010219 43.42 14-Nov-03 010220 43.46 17-Nov-03 010221 43.30 18-Nov-03 010222 43.75 19-Nov-03 010223 43.83 20-Nov-03 010224 43.74 21-Nov-03 010225 44.10 24-Nov-03 010226 43.98 25-Nov-03 010227 44.20 26-Nov-03 010228 44.25 27-Nov-03 010229 44.10 28-Nov-03 010230 44.42 1-Dec-03 010231 44.38 2-Dec-03 010232 44.64 3-Dec-03 010233 44.90 4-Dec-03 010234 44.80 5-Dec-03 010235 44.82 8-Dec-03 010236 44.88 9-Dec-03 010237 44.40 10-Dec-03 010238 44.77 11-Dec-03 010239 44.78 12-Dec-03 010240 44.47 15-Dec-03 010241 44.92 16-Dec-03 010242 45.24 17-Dec-03 010243 45.78 18-Dec-03 010244 45.93 19-Dec-03 010245 45.84 22-Dec-03 010246 45.77 23-Dec-03 010247 45.83 24-Dec-03 010248 46.23 29-Dec-03 010249 45.91 30-Dec-03 010250 46.03 31-Dec-03