Assignment 3, CSC490, Spring 2009
1 Assignment
This week, we’re going to model the elements of financial analysis by representing them as values in ML.
2 Events
First, we’re going to model a single coin flip using a boolean; we’ll call it an event1:
type event1 = bool;; |
Next, we’re going to model events (that is, whole events) as mappings from timesteps to event1s:
type event = int -> event1;; |
With these definitions, define the events eAllHeads that corresponds to always flipping heads and eAllTails that corresponds to always flipping tails. Next, define the eAlternating event that corresponds to a head on even-numbered timesteps, and a tail otherwise.
Next, we’d like the ability to define a random event. However, a particular event is fixed, so it must be the case that if a given event signals a Head at time 57, that it always signals a Head at time 57. Define the makeERandom function that produces a random event, defined as follows: the mapping from timesteps to flips is random, chosen with Random.bool(), but each flip must be remembered by that event, so that every subsequent query to the event at that timestep produces the same flip that was chosen first for that timestep. You probably want to use a hash table for this.
Operationally, suppose that I define two random events, like this:
let eRandom1 = makeERandom();; |
let eRandom2 = makeERandom();; |
Suppose further that I sample these two events at step 57, twice each.
let t1 = eRandom1 57;; |
let t2 = eRandom1 57;; |
let t3 = eRandom2 57;; |
let t4 = eRandom2 57;; |
The requirement is that t1 = t2 and that t3 = t4, but not that t1 = t3
Finally (this will help with test cases), we’d like to be able to force certain parts of an event to match some given set of outcomes. Define forceEParts that consumes a timestep t and an array of booleans ba and an event and produces a new event that is like the old one but has the sequence of values specified by the array "pasted in" at the given timestep. More specifically, for a timestep n such that t <= n < t + (Array.length ba), the event should contain the flip ba.(n-t) . Note that the original event must be unchanged.
3 Random Variables
A random variable is a map from an event to a real number (remember: this is the one thing that you’re learning in this class).
type rv = event -> float;; |
The simplest random variables are those whose values are constant. Define the floatToRV function that consumes a floating point number and produces the random variable whose value is always the given number.
Next, there’s the random variable that counts the number of heads at time n. Define rvNCountHeads, the random variable that consumes a number n of timesteps and produces the random variable that evaluates to the number of heads that have occurred in the event in time steps 0 through n-1.
For symmetry, define its dual, rvNCountTails.
4 A little statistical analysis
Do these events behave as we’d like them to? Let’s find out.
[f(0);...;f(n-1)] |
Next, define the mean function that consumes a list of floats and produces its mean.
Now, define the sampleVar function that consumes a list of floats and produces its sample variance (you can look this up; in english, it’s the sum of the squares of the differences from the mean, divided by one less than the number of samples).
Using functions you defined earlier, define the sampleHeads function that consumes a number, creates a random event, and applies the rvNCountHeads random variable to it to produce the number of heads in the first n steps of the event.
Next, using all four of these functions, develop sampleHeadsMeanAndVariance that consumes a number of trials n and a timestep t and produces the mean and variance of the result of tabulating n trials, each with t timesteps.
Finally, use tabulateN again to tabulate the results of sampleHeadsMeanAndVariance using 1000 trials over values of t from 0 up to 50. Call the result experiment1. How is the mean correlated with t? How is the variance correlated with t? (Add a comment to your program with the answers to these questions.)
5 Modeling Finance entities
First, let’s define our classic stock model: develop rvNStock, that consumes a number of timesteps, a value for the parameter u that multiplies the stock on the flip of a head, a value for the parameter d that multiplies the stock on the flip of a tail, and an initial value for the stock, and produces a random variable representing the price of the stock on a given event.
Also, we’d like to define a path-dependent random variable rvPathD that consumes a timestep t, whose value is 10 times the number of heads that occurred a multiple of 3 flips ago. So, at time step 102, if the 99th flip was a head and the 93rd flip was a head and all the others were tails, the value of this random variable would be 20.
Next, define rvPutOption, that consumes a float strike representing the strike price and a random variable stock representing the price of a stock at the option’s expiry and returns a random variable representing the value of a put option with the given strike at expiry.
For symmetry, define rvCallOption, with the same type, representing a call option.
Finally, we want to be able to manipulate random variables by plugging them into larger equations. Generally, these larger equations can be represented as functions from one or more floats to another float. Develop the function unaryLiftRV that consumes a unary function on floats and a random variable and "plugs in" the random variable, producing another random variable. For instance, plugging a CountHeads random variable into the function x^2 + 4 should produce a random variable that takes on the value of the square of the number of heads, plus four. After this, define binaryLiftRV, that performs the same service for binary functions.
6 Types and Contracts
Here are the types we defined:
type event1 = bool;; |
type event = int -> event1;; |
type rv = event -> float;; |
Here are the types of the required definitions. Add this to the end of your file to make sure that your definitions have the required types:
(eAllHeads : event);; |
(eAllTails : event);; |
(eAlternating : event);; |
(makeERandom : unit -> event);; |
(forceEParts : int -> bool array -> event -> event);; |
|
(floatToRV : float -> rv);; |
(rvNCountHeads : int -> rv);; |
(rvNCountTails : int -> rv);; |
|
(tabulateN : (int -> 'a) -> int -> 'a list);; |
(mean : float list -> float);; |
(sampleVar : float list -> float);; |
(sampleHeads : int -> float);; |
(sampleHeadsMeanAndVariance : int -> int -> (float * float));; |
(experiment1 : (float * float) list);; |
|
(rvNStock : int -> float -> float -> float -> rv);; |
(rvPathD : int -> rv);; |
(rvPutOption : float -> rv -> rv);; |
(rvCallOption : float -> rv -> rv);; |
(unaryLiftRV : (float -> float) -> rv -> rv);; |
(binaryLiftRV : (float -> float -> float) -> rv -> rv -> rv);; |
7 Testing
You must test your code thoroughly. You will lose credit for functions that are not tested.
8 Handin
Put your code and tests in a single ML file, and hand it in using the DrScheme handin plugin.
9 Disclaimer
There may well be bugs in this assignment. Let me know right away if you find some!