design_pattern_derivative_exotic_option

本文介绍了一种使用模板模式对路径依赖期权进行定价的方法。通过定义关键类如 PathDependent 和 ExoticEngine,实现了生成股票价格路径、计算现金流及蒙特卡洛模拟等功能。最后给出了一个亚洲期权定价的实例。

Based on payoff, option, mcstatistics and random numbers classes,  we now have basic components to build option pricing applications. This post applies template pattern to price path-dependent options. The framwork

1. generation of the stock price path;
2. generation of cash-flows given a stock price path;
3. discounting and summing of cash-flows for a given path;
4. averaging of the prices over all the paths.

We need a production class, a random number class, a statistics gathering class, and a independent path generating class, which generates stochastic process according to different assumption, say geometric brownian motion, jump diffusion process and stochastic volatility process. The communication among different classes is given by

1. the path generator asks the product what times it needs spot for, and it passes back an array.

2. the accounting part of the engine asks the product what cash-flow times are possible, and it passes back an array. The engine then computes all the possible discount factors.

3. the accounting part of the engine asks the product the maximum number of cash flows it can generate, and sets up a vector of that size.

4. for each path, the engine gets an array of spot values from the path generator.

5. The array of spot values is passed into the product, whch passes back the number of cash-flows, and puts their values into the vector.

6. The cash-flows are discounted appropriately and summed, and the total value is passed into the statistics gatherer.

7. After all the looping  is done, the final results are obtained from the statistics gatherer.

#ifndef PATHDEPENDENT_HPP_INCLUDED
#define PATHDEPENDENT_HPP_INCLUDED

#include<vector>
#include<payoffbridge.hpp>

using namespace std;

class CashFlow {
public:
    double amount;
    unsigned long index;
    CashFlow(double amount_, unsigned long index_):amount(amount_),index(index_){}
};

class PathDependent{
public:
    PathDependent(const vector<double>& LookAtTimes_) : LookAtTimes(LookAtTimes_){}
    const vector<double> getLookAtTimes() const { return LookAtTimes; }
    virtual unsigned long MaxNumberOfCashFlows() const = 0;
    virtual vector<double> PossibleCashFlowTimes() const = 0;
    virtual unsigned long CashFlows(const vector<double>& spots, vector<CashFlow>& cashflows) const = 0;
    virtual PathDependent* clone() const = 0;

    virtual ~PathDependent(){}

private:
    vector<double> LookAtTimes;
};

class PathDependentAsian : public PathDependent {
    /*
    Asian option, the payoff is difference between the mean value of price time series and strike.
    Since the option is European type, there is only one cash flow needed to be calcuated, at the
    delivery time.
    */
public:
    PathDependentAsian(const vector<double>& LookAtTimes_, double deliverytime_, const PayOffBridge& payoff_)
    :PathDependent(LookAtTimes_), deliverytime(deliverytime_), payoff(payoff_), numberoftimes(LookAtTimes_.size()){}

    virtual PathDependent* clone() const {
        return new PathDependentAsian(*this);
    }

    virtual unsigned long CashFlows(const vector<double>& spots, vector<CashFlow>& cashflows) const {
        double sum = 0.0;
        for (unsigned long i=0; i<spots.size(); i++){
            sum += spots[i];
        }
        double mean = sum/numberoftimes;
        cashflows[0].index = deliverytime;
        cashflows[0].amount = payoff(mean);

        return 1;
    }

    virtual unsigned long MaxNumberOfCashFlows() const {
        return 1;
    }

    virtual vector<double> PossibleCashFlowTimes() const{
        vector<double> temp(1);
        temp[0] = deliverytime;
        return temp;
    }

private:
    double deliverytime;
    PayOffBridge payoff;
    unsigned long numberoftimes;
};
#endif // PATHDEPENDENT_HPP_INCLUDED
PathDependent class has several functions, most important ones are PossibleCashFlowTimes, and CashFlows. PossibleCashFlowTimes() generates time index for calculating discount factors and cash flows. CashFlow() calculates cash flows based on the internal payoff structure.

Then we define ExoticEngine using template pattern

#ifndef EXOTICENGINE_HPP_INCLUDED
#define EXOTICENGINE_HPP_INCLUDED

#include<./wrapper.hpp>
#include<./pathdependent.hpp>
#include<./statisticsmc.hpp>
#include<vector>

using namespace std;

class ExoticEngine {
public:
    ExoticEngine(const Wrapper<PathDependent>& product_, double r_):
    product(product_), r(r_), discounts(product_->PossibleCashFlowTimes()){
        for(unsigned long i=0; i<discounts.size(); i++){
            discounts[i] = exp(-r*discounts[i]);
        }
        cashflows.resize(product_->MaxNumberOfCashFlows());
    }

    virtual ~ExoticEngine(){}

    virtual void getPath(vector<double>& spots) = 0; // choice of stochastic process and model

    double doPath(const vector<double>& spots) const{
        product->CashFlows(spots, cashflows);
        double value = 0.0;
        for (unsigned long i=0; i<cashflows.size(); i++){
            value += cashflows[i].amount*discounts[i];
        }
        return value;
    }

    void simulation(StatisticsMC& gather, unsigned long numberpaths){
        vector<double> spots(product->getLookAtTimes().size());
        double thisValue;

        for(unsigned long i=0; i<numberpaths; i++){
            getPath(spots);
            thisValue = doPath(spots);
            gather.DumpOneResult(thisValue);
        }
    }

private:
    Wrapper<PathDependent> product;
    double r; //interest rate
    vector<double> discounts;
    mutable vector<CashFlow> cashflows;
};

class ExoticBSEngine : public ExoticEngine {
public:
    ExoticBSEngine(const Wrapper<PathDependent>& product_, double r, double d, double vol, const Wrapper<RandomBase>& generator_, double spot)
    :ExoticEngine(product_, r), generator(generator_){
        vector<double> times(product_->getLookAtTimes());
        numberoftimes = times.size();
        generator->setDimension(numberoftimes);
        drifts.resize(numberoftimes);
        standarddeviations.resize(numberoftimes);
        logspot = log(spot);
        variates.resize(numberoftimes);

        double thisvariance = vol*vol*times[0];
        drifts[0] = (r-d)*times[0] - 0.5*thisvariance;
        standarddeviations[0] = sqrt(thisvariance);
        for(unsigned long i=1; i<numberoftimes; i++){
            thisvariance = vol*vol*(times[i]-times[i-1]);
            drifts[i] = (r-d)*(times[i]-times[i-1])-0.5*thisvariance;
            standarddeviations[i] = sqrt(thisvariance);
        }
    }

    virtual void getPath(vector<double>& spots){
        generator->getGaussians(variates);
        double currentlogspot = logspot;

        for(unsigned long i=0; i<numberoftimes; i++){
            currentlogspot += drifts[i];
            currentlogspot += standarddeviations[i]*variates[i];
            spots[i] = exp(currentlogspot);
        }
    }

    virtual ~ExoticBSEngine(){}

private:
    Wrapper<RandomBase> generator;
    vector<double> drifts;
    vector<double> standarddeviations;
    double logspot;
    unsigned long numberoftimes;
    vector<double> variates;
};
#endif // EXOTICENGINE_HPP_INCLUDED

The most important one in ExoticEngine class is simulation(), which calls getPath(), doPath(). getPath() wll generate one realization of stock price dynamics based on the stochastic model we assume, then doPath() will calculate discount cash flows, and sum them to get the option price, the result is passed to statistics gathering tool for further usage.

We have defined the random generator class, therefore, combining them together, the main function is

#include <iostream>
#include <cmath>
#include <./montecarlo.hpp>
#include <./payoff.hpp>
#include <./statisticsmc.hpp>
#include <./vanillaoption.hpp>
#include <./wrapper.hpp>
#include <./pathdependent.hpp>
#include <./ExoticEngine.hpp>

int main(){
    // set parameters
    double spot = 15.0;
    double expiry = 1.0;
    double strike = 15.0;
    double volatility = 0.4;
    double r = 0.01;
    double d = 0.0;
    unsigned long NumberPaths = 20000;

    PayOffCall payoffcall(strike);
    StatisticsMean gather;
    ConvergenceTable ct(gather);

    double numberofdates = 252;
    std::vector<double> times(numberofdates);
    for(unsigned long i=0; i<numberofdates; i++){
        times[i] = (i+1.0)*expiry/numberofdates;
    }

    PathDependentAsian option(times, expiry, payoffcall);

    RandomParkMiller generator(numberofdates);
    AntiThetic atgenerator(generator);

    // calculate option price and generate statistics
    ExoticBSEngine engine(option, r, d, volatility, atgenerator, spot);
    engine.simulation(ct, NumberPaths);

    // print results
    std::vector<std::vector<double>> results = ct.GetResultsSoFar();
    std::cout << "For Call Option Price: " << std::endl;
    for (unsigned long i=0; i<results.size(); i++){
        for (unsigned long j=0; j<results[i].size(); j++){
            std::cout << results[i][j] << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}
Output


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值