Lognormal curve not prints properly

This commit is contained in:
Kevin
2017-09-19 19:36:40 -04:00
parent a5b5f64428
commit e628db236b

View File

@@ -1,25 +1,31 @@
"use strict";
var optionResults; var optionResults;
const MAX_PLOT_ELEMENTS = 100000;
$(document).ready(function() { $(document).ready(function () {
"use strict";
$("#option-terms").on("submit", function(e) { $("#option-terms").on("submit", function (e) {
// //
e.preventDefault(); e.preventDefault();
sendRequest(); sendRequest();
}) });
}); });
function serializeForm(id) { function serializeForm(id) {
"use strict";
// //
return $(id).serializeArray() return $(id).serializeArray()
.reduce(function(a, x) { a[x.name] = x.value; return a; }, {}); .reduce(function (a, x) {
a[x.name] = x.value;
return a;
}, {});
} }
function sendRequest() { function sendRequest() {
"use strict";
// //
var inputData = serializeForm("#option-terms"); var inputData = serializeForm("#option-terms");
// Get the right data-types // Get the right data-types
inputData.ExpiryDate = new Date(inputData.ExpiryDate).toJSON(); inputData.ExpiryDate = new Date(inputData.ExpiryDate).toJSON();
inputData.OptType = parseInt(inputData.OptType); inputData.OptType = parseInt(inputData.OptType);
@@ -33,54 +39,57 @@ function sendRequest() {
// Send request // Send request
var startTime; var startTime;
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: "http://localhost:8080", url: "http://localhost:8080",
data: JSON.stringify(inputData), data: JSON.stringify(inputData),
beforeSend: function(request, settings) { beforeSend: function () {
startTime = new Date().getTime(); startTime = Date.now();
}, },
success: function(e) { success: function (e) {
optionResults = e; optionResults = e;
updateTable(); updateTable();
updateGraph(); updateGraph();
let requestTime = new Date().getTime() - startTime; var requestTime = Date.now() - startTime;
console.log("Request time(s):", requestTime / 1000); console.log("Request time(s):", requestTime / 1000);
}, }
}); });
} }
function updateTable() { function updateTable() {
"use strict";
// TODO // TODO
$("#results-table > tbody > tr").each(function(idx, el) { $("#results-table > tbody > tr").each(function (idx, el) {
$($(el).children()[1])[0].innerText = $($(el).children()[1])[0].innerText =
optionResults["ClosedForm"][$($(el).children()[0]).text()].toFixed(4); optionResults.ClosedForm[$($(el).children()[0]).text()].toFixed(4);
$($(el).children()[2])[0].innerText = $($(el).children()[2])[0].innerText =
optionResults["MonteCarlo"][$($(el).children()[0]).text()].toFixed(4); optionResults.MonteCarlo[$($(el).children()[0]).text()].toFixed(4);
}); });
} }
function updateGraph() { function updateGraph() {
"use strict";
// TODO // TODO
var strippedData = optionResults.MonteCarlo.Levels.map(function(i) { var strippedData = optionResults.MonteCarlo.Levels.map(function (i) {
return Number(i.toFixed(0)); return Number(i.toFixed(0));
}); });
strippedData = strippedData.slice(0, MAX_PLOT_ELEMENTS);
// Count the elements // Count the elements
var counts = {}; var counts = {};
var minY = 0; var num;
for (var i=0; i<strippedData.length; i++) { for (var i=0; i<strippedData.length; i++) {
var num = strippedData[i]; num = strippedData[i];
counts[num] = counts[num] ? counts[num] + 1 : 1; counts[num] = counts[num] ? counts[num] + 1 : 1;
} }
var summaryData = []; var summaryData = [];
Object.keys(counts).forEach( function(key) { Object.keys(counts).forEach(function (key) {
summaryData.push({'key': key, 'value': counts[key]}); summaryData.push({"key": key, "value": counts[key]});
}); });
var margin = {top: 10, right: 20, bottom: 20, left: 40}, var margin = {top: 10, right: 40, bottom: 20, left: 40};
width = 500 - margin.left - margin.right, var width = 500 - margin.left - margin.right;
height = 300 - margin.top - margin.bottom; var height = 300 - margin.top - margin.bottom;
$("#right-upper").empty(); $("#right-upper").empty();
var svg = d3.select("#right-upper").append("svg") var svg = d3.select("#right-upper").append("svg")
@@ -90,51 +99,68 @@ function updateGraph() {
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleLinear() var x = d3.scaleLinear()
.range([0, width]); .range([0, width])
.domain([0, Math.max.apply(null, strippedData)]).nice();
var y = d3.scaleLinear() var maxY0 = Object.values(counts).sort((prev, next) => next - prev)[0];
.range([height, 0]); var y0 = d3.scaleLinear()
.range([height, 0])
.domain([0, maxY0]).nice();
x.domain([0, Math.max.apply(null, strippedData)]).nice(); var tte = (new Date(optionResults.MonteCarlo.ExpiryDate) - new Date(optionResults.MonteCarlo.ValueDate)) / (1000 * 60 * 60 * 24 * 365.25);
var maxY = Object.values(counts).sort((prev, next) => next - prev)[0]; var scale = optionResults.MonteCarlo.Spot * Math.exp(optionResults.MonteCarlo.Rfr * tte);
y.domain([0, maxY]).nice(); var shape = Math.sqrt(Math.exp(Math.pow(optionResults.MonteCarlo.Vol, 2)) * (Math.exp(Math.pow(optionResults.MonteCarlo.Vol, 2)) - 1)) * Math.sqrt(tte);
var maxY1 = logNormal(Math.exp(0 - Math.pow(shape, 2)), shape) / scale;
var y1 = d3.scaleLinear()
.range([height, 0])
.domain([0, maxY1]).nice();
var xAxis = d3.axisBottom().scale(x);
var yAxisLeft = d3.axisLeft().scale(y0);
var yAxisRight = d3.axisRight().scale(y1);
var logNormalLine = d3.line()
.x(function (d) { return x(d); })
.y(function (d) { return y1(logNormal(d / scale, shape) / scale); })
.curve(d3.curveBasis);
svg.selectAll(".bin") svg.selectAll(".bin")
.data(summaryData) .data(summaryData)
.enter().append("line") .enter().append("line")
.attr("class", "bin") .attr("class", "bin")
.attr("x1", function(d) { return x(d.key) }) .attr("x1", function (d) { return x(d.key); })
.attr("x2", function(d) { return x(d.key) }) .attr("x2", function (d) { return x(d.key); })
.attr("y1", height) .attr("y1", height)
.attr("y2", function(d) { return y(d.value ) }); .attr("y2", function (d) { return y0(d.value); });
svg.append("path")
.attr("stroke", "blue")
.attr("stroke-width", "3")
.attr("fill", "none")
.attr("d", logNormalLine(d3.range(x.domain()[0], x.domain()[1], 1)));
svg.append("g") svg.append("g")
.attr("class", "x axis") .attr("class", "x axis")
.attr("transform", "translate(0," + height + ")") .attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom() .call(xAxis);
.scale(x));
svg.append("g") svg.append("g")
.attr("class", "y axis") .attr("class", "y axis")
.call(d3.axisLeft() .call(yAxisLeft);
.scale(y));
var logNormalLine = d3.line()
.x(function(d, i) { return x(d); })
.y(function(d) { return logNormal(d, 100, 0.4); })
.curve(d3.curveBasis);
svg.append("g") svg.append("g")
.attr("d", logNormalLine(d3.range(x.domain()[0], x.domain()[1], 1))) .attr("class", "y axis")
.attr("stroke", "blue") .style("fill", "blue")
.attr("stroke-width", 2) .attr("transform", "translate(" + width + ", 0)")
.attr("fill", "none") .call(yAxisRight);
} }
function logNormal(x, mean, stddev) { function logNormal(x, shape) {
var y = (1 / (x * Math.sqrt(2 * Math.PI * Math.pow(stddev, 2)))) * Math.pow(Math.E, - (Math.pow(Math.log(x) - mean, 2) / (2 * Math.pow(stddev, 2)))); "use strict";
// console.log('logNormal', x, mean, stddev, y); var y = 1 / (shape * x * Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * Math.pow((Math.log(x) / shape), 2));
y = isFinite(y) ? y : 0; y = isFinite(y) ? y : 0;
return y; return y;
} }