完成两个小程序，包括一个Price Simulations，以及Binomial Tree Calculation.

## Q1. Bonds

Download Assignment5Files.zip from study.net

Add Assignment5Q1.cpp to a new project. This contains the main() function you will use for this question. Make sure to submit both your code and the output from running the code. Create a bond.cpp and bond.h header/cpp file combination and add them to your project. You should add the Bond class declaration in the bond.h file and the implementation of methods in the bond.cpp file.

Create a Bond class with a constructor that takes principal, coupon and time to maturity as parameters. Store the parameters as properties. For the purposes of the homework, we will assume that coupons (if any) are paid annually.

Add a public method called double getPrice(double YTM) which returns the bond’s price given its yield to maturity. The formula for price given yield to maturity.

Notice that we count “backwards” from time to maturity to discount coupons. So, if T=5, we discount coupons at 5 years, 4 years, 3 years, 2 years and 1 year. If T=4.75, we discount coupons at 4.75 years, 3.75 years, 2.75 years, 1.75 years and 0.75 years.Add a public method called double getYTM(double price) which returns the bond’s yield to maturity given its price. Note: you will need to use a root-finding method like the secant method to search for the appropriate YTM. Use a function like:

`f(ytm) = price - getPrice(ytm)`

to find the ytm that produces the expected priceAdd a public method called double estimateModifiedDuration(double YTM)which estimates the modified duration of the bond using the following formula.

That is, it estimates the modified duration by adding 1% to the yield-to-maturity and calculating the price differenceAdd a public method called double estimateSimulatedPrice(double hazardRate, double r, int numSimulations)

This method will run a simulation using a Poisson process to simulate bond default times. For each iteration of your simulation loop, use a uniform random variable to simulate a default time (using the hazard rate). Refer to the final slides in Lecture 10 see how to simulate a Poisson Process.

Given this default time, calculate the present value of the bond’s cash flows (discounted by r) following the procedure outlined in slides 64-71 of Lecture 10.

Run the loop numSimulations times and then take the average of the bond’s cash flows. Return this as the bond price.Run the main() function in Assignment5Q1.cpp as a test. Include the output file Assignment5Q1.txt and your code files with your assignment submission.

NOTE: the program also creates a file called Assignment5Q1_SAMPLE.txt. You can check your work with the sample file included in the assignment zip file. Your numbers will not necessarily match exactly, especially the results of simulations.

## Q2. Option Class Hierarchy

For this question, you’ll need to create option.cpp/option.h files in which to store your code.

Create the following class hierarchy, with Option at the top. Option then has derived classes EuropeanOption, AmericanOption, etc. We are going to define methods (some of them virtual functions) within Option that will allow us to value options. Knockout options are described below.

Create a constructor in Option that takes double K, double T, double sigma and double r as strike, time-to-maturity, stock volatility and risk-free rate parameters respectively. This constructor should be used by each of the derived classes in their constructors. Additionally, the Option class should keep protected properties for Strike, TimeToMaturity, Sigma and r.

To Option, add a virtual function double getExerciseValue(double s, double t) that returns the exercise value of the option for spot price s at time t.

Note: for American options, this just returns the intrinsic value of the options. For European options, if t != TimeToMaturity, then the exercise value should be zero (that is, European options can only be exercised at maturity).To Option, add a virtual function:

`double getBlackScholesValue(double s)`

that returns the Black Scholes value of the option. Note: for KnockOutOptions, just return the ‘vanilla’ Black Scholes value, so a KnockOutPut returns the B-S value for a European put and a KnockOutCall returns the B-S value for a European call. This is not strictly correct but is sufficient for the assignment.To Option, add a method:

`double getBinomialTreeValue(double s, int N)`

that returns the value of the option using a binomial tree of depth N. As with`getBlackScholesValue()`

, the value of the option should be taken for a spot of s- a. You should use a single
`vector<double>`

to hold your tree node values. DO NOT USE A 2 DIMENSIONAL ARRAY. - b. The binomial tree should handle early exercise by comparing the current node’s “binomial” value to the exercise value at that time and spot. Look at Lecture 11 + 12 slides 71-72 for an example of this.
- c. The
`getBinomialTreeValue()`

method should not be virtual. That is, the tree can be implemented using the getExerciseValue() method and does not need to know specifically what type of option is being valued. Below is some pseudocode that should be helpful. Source: https://en.wikipedia.org/wiki/Binomial_options_pricing_model - d. Again, the getBinomialTreeValue() method should not have logic that in it that says “if I’m a call do this” or “If I’m a put do that”. The virtual getExerciseValue() method enables each lowest-level child class (EuropeanCall, EuropeanPut, AmericanCall, AmericanPut, KnockOutCall, KnockOutPut) encapsulate whether the option has early- exercise (American) or not (European) and whether it is a call or a put and, in the case of the KnockOut options, whether the barrier has been breached.

- a. You should use a single

```
Binomial Tree Calculation
-------------------------
function binomialTree(T, S, K, r, sigma, n) {
' T... expiration time
' S... stock price
' K... strike price
' n... height of the binomial tree
deltaT := T / n;
up := exp(sigma * sqrt(deltaT));
p0 := (up-exp(-r * deltaT)) / (up*up - 1);
p1 := exp(-r * deltaT) - p0;
' initial values at time T
for i := 0 to n {
spot := S* up^(2*i - n);
p[i] := getExerciseValue(spot, T)
if p[i] < 0 then p[i] := 0;
}
t := T;
' move to earlier times
for j := n-1 down to 0 {
t := t - deltaT;
for i := 0 to j {
spot := S*up^(2*i-j)
exercise := getExerciseValue(spot, t)
p[i] := p0 * p[i+1] + p1 * p[i]; ' binomial value
' check for early exercise
if p[i] < exercise then p[i] := exercise;
}
}
return p[0];
}
```

- To Option: add a virtual function: double getValue(double s)that returns the option value for spot value s.

European options should return the Black-Scholes value. American and Knockout options should return the binomial tree value of the option with a tree depth of 250. - KnockOutOption - for the purposes of this assignment, we will look at a simple form of a barrier option known as a knockout. With a knockout, if the stock price crosses the barrier, the value of the option is extinguished (is zero). We will use a binomial tree to value them.

For example, if the barrier is $200 and the current stock price is $100 and we have an up-and- out call option, then the option will behave like a European call option unless the stock price goes above $200. Then, the option will become worthless.

To implement our Knockout options:- a. Create a constructor in the KnockOutOption that takes the standard parameters as well as a barrier B of type double at the end of its parameter list. If
`K > B`

, then the option should be considered a down-and-out option. If`K < B`

, then this is an up-and-out option. - b. In the KnockOutOption class, create a method bool isAcrossBarrier(double s) which returns whether the given spot value s is across the barrier. If we have an up-and-out option, then isAcrossBarrier returns true if
`s > B`

. If we have a down-and-out option, then isAcrossBarrier returns true if`s < B`

. - c. getExerciseValue() should behave the same as a European option with one very important exception. If the stock price is across the barrier, getExerciseValue() should return 0.

NOTE: Given how you are asked to implement getBinomialTreeValue(), the only time the barrier is relevant is at t == T. That is, the Option’s getBinomialTreeValue() will not “knock” the barrier out at earlier times (`t < T`

).

- a. Create a constructor in the KnockOutOption that takes the standard parameters as well as a barrier B of type double at the end of its parameter list. If
- Make sure to implement the virtual functions, at the appropriate level, for all the option classes. For example, if a class can implement the function for all its derived classes (like getValue()), then implement the function within that class. If not, then implement the function within derived classes. Remember that calls and puts have different forms of the Black Scholes formula.
- Download Assignment5Files.zip from study.net. Run the main() function in Assignment5Q2.cpp as a test. Include the output file Assignment5Q2.csv with your assignment submission as well as option.h and option.cpp.
- NOTE: The program also creates a file Assignment5Q2_SAMPLE.csv. There is a version of this file included in Assignment5Files.zip. You can use this to check your work. Your values may not match our values exactly.