Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | 4x 4x 4x 4x 4x 4x 28x 28x 28x 28x 15x 28x 28x 6x 2x 4x 4x 4x 13x 28x 4x 13x 28x 28x 4x | import { calculateExerciseValue } from "../utils/OptionUtils.js";
import { isNumberGreaterThanZero } from "../utils/ValidationUtils.js";
function determineModelParameters(option, timeSteps) {
const deltat = option.timeToMaturity / timeSteps;
const u = Math.exp(option.volatility * Math.sqrt(deltat)); // proportional up movement
const d = Math.exp(-option.volatility * Math.sqrt(deltat)); // proportional down movement
const a = Math.exp((option.riskFreeRate - option.dividendYield) * deltat); // growth factor
const p = (a - d) / (u - d); // probability of an up movement (probability of a down movement is 1 - p)
return [deltat, u, d, p];
}
function createNode(initialSpotPrice, i, j, u, d) {
return {
i,
j,
spotPrice: initialSpotPrice * u ** j * d ** (i - j),
value: 0,
};
}
function calculateNodeOptionValue(option, timeSteps, nodes, i, j, deltat, p) {
const nodeIndex = (i * (i + 1)) / 2 + j; // sum of numbers from 1 to i, plus j
let currentValue = 0;
if (i < timeSteps) {
currentValue =
(p * nodes[nodeIndex + (i + 1) + 1].value +
(1 - p) * nodes[nodeIndex + (i + 1)].value) *
Math.exp(-option.riskFreeRate * deltat);
}
const exerciseValue = calculateExerciseValue(
option,
nodes[nodeIndex].spotPrice,
i === timeSteps ? option.timeToMaturity : i * deltat
);
return [nodeIndex, Math.max(currentValue, exerciseValue)];
}
/**
* Calculates the price of an option using the binomial options pricing model described by Cox, Ross, and Rubinstein (1979) (https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.379.7582).
* @param {Option} option option to price
* @param {object} params
* @param {number} params.timeSteps number of time steps in the tree (> 0)
* @returns {number} price of the option
* @throws if params.timeSteps is not a number greater than zero
*/
function price(option, { timeSteps }) {
if (!isNumberGreaterThanZero(timeSteps)) {
throw new Error(
`invalid time steps (${timeSteps}), must be a number greater than zero.`
);
}
const [deltat, u, d, p] = determineModelParameters(option, timeSteps);
// Create the tree
const nodes = [];
for (let i = 0; i <= timeSteps; i += 1) {
for (let j = 0; j <= i; j += 1) {
nodes.push(createNode(option.initialSpotPrice, i, j, u, d));
}
}
// Work backwards through the tree calculating the option values
for (let i = timeSteps; i >= 0; i -= 1) {
for (let j = 0; j <= i; j += 1) {
const [index, value] = calculateNodeOptionValue(
option,
timeSteps,
nodes,
i,
j,
deltat,
p
);
nodes[index].value = value;
}
}
return nodes[0].value;
}
export { price };
|