From e628db236b4c72b5760cb98ecfcee2905084fee8 Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 19 Sep 2017 19:36:40 -0400 Subject: [PATCH] Lognormal curve not prints properly --- templates/assets/main.js | 128 +++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 51 deletions(-) diff --git a/templates/assets/main.js b/templates/assets/main.js index ed66c5b..f5ce530 100644 --- a/templates/assets/main.js +++ b/templates/assets/main.js @@ -1,25 +1,31 @@ -"use strict"; - 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(); sendRequest(); - }) + }); }); function serializeForm(id) { + "use strict"; // 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() { + "use strict"; // var inputData = serializeForm("#option-terms"); + // Get the right data-types inputData.ExpiryDate = new Date(inputData.ExpiryDate).toJSON(); inputData.OptType = parseInt(inputData.OptType); @@ -33,54 +39,57 @@ function sendRequest() { // Send request var startTime; $.ajax({ - type: "POST", - url: "http://localhost:8080", - data: JSON.stringify(inputData), - beforeSend: function(request, settings) { - startTime = new Date().getTime(); + type: "POST", + url: "http://localhost:8080", + data: JSON.stringify(inputData), + beforeSend: function () { + startTime = Date.now(); }, - success: function(e) { + success: function (e) { optionResults = e; updateTable(); updateGraph(); - let requestTime = new Date().getTime() - startTime; + var requestTime = Date.now() - startTime; console.log("Request time(s):", requestTime / 1000); - }, + } }); } function updateTable() { + "use strict"; // TODO - $("#results-table > tbody > tr").each(function(idx, el) { + $("#results-table > tbody > tr").each(function (idx, el) { $($(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 = - optionResults["MonteCarlo"][$($(el).children()[0]).text()].toFixed(4); + optionResults.MonteCarlo[$($(el).children()[0]).text()].toFixed(4); }); } function updateGraph() { + "use strict"; // TODO - var strippedData = optionResults.MonteCarlo.Levels.map(function(i) { + var strippedData = optionResults.MonteCarlo.Levels.map(function (i) { return Number(i.toFixed(0)); }); + strippedData = strippedData.slice(0, MAX_PLOT_ELEMENTS); // Count the elements var counts = {}; - var minY = 0; + var num; for (var i=0; i next - prev)[0]; + var y0 = d3.scaleLinear() + .range([height, 0]) + .domain([0, maxY0]).nice(); - x.domain([0, Math.max.apply(null, strippedData)]).nice(); - var maxY = Object.values(counts).sort((prev, next) => next - prev)[0]; - y.domain([0, maxY]).nice(); + var tte = (new Date(optionResults.MonteCarlo.ExpiryDate) - new Date(optionResults.MonteCarlo.ValueDate)) / (1000 * 60 * 60 * 24 * 365.25); + var scale = optionResults.MonteCarlo.Spot * Math.exp(optionResults.MonteCarlo.Rfr * tte); + 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") .data(summaryData) .enter().append("line") .attr("class", "bin") - .attr("x1", function(d) { return x(d.key) }) - .attr("x2", function(d) { return x(d.key) }) + .attr("x1", function (d) { return x(d.key); }) + .attr("x2", function (d) { return x(d.key); }) .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") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") - .call(d3.axisBottom() - .scale(x)); + .call(xAxis); svg.append("g") .attr("class", "y axis") - .call(d3.axisLeft() - .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); + .call(yAxisLeft); svg.append("g") - .attr("d", logNormalLine(d3.range(x.domain()[0], x.domain()[1], 1))) - .attr("stroke", "blue") - .attr("stroke-width", 2) - .attr("fill", "none") - + .attr("class", "y axis") + .style("fill", "blue") + .attr("transform", "translate(" + width + ", 0)") + .call(yAxisRight); } -function logNormal(x, mean, stddev) { - 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)))); - // console.log('logNormal', x, mean, stddev, y); +function logNormal(x, shape) { + "use strict"; + 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; return y; }