MCOV |
Open Source Monte Carlo Option Valuer |
|
Home Contact Download Releases Installation Read-Me License Monte Carlo Strategy Objects C++ Classes C++ Files mcovaluer.h mcovaluer.cxx mcov.cxx |
mcovaluer.hC++ Header File for MCOV SoftwareThis is the mcovaluer.h file that comes with a MCOV distribution (without the license section)...
// ================================================================
// 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 <iostream>
#include <sstream>
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 estimates:
// - 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 a prototype to project the next day
// - how to project the next 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-ratio
// ( close / previous-close )
// - 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 process
// 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
// ================================================================
|