<!DOCTYPE html>
<html>
<head>
<!-- Load plotly.js into the DOM -->
<script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>
</head>
<body>
<div class="contents">
<div id="myDiv" class="box1">
<!-- Plotly chart will be drawn inside this DIV -->
</div>
<!-- フォームの追加 -->
<div class="box2">
<div class="box2-1">
<!-- 全体数値の表 -->
<table class="table-container" border="1">
<tr>
<th>データ</th>
<th>数値</th>
</tr>
<tr>
<td>個数</td>
<td><span id="pieces"></span></td>
</tr>
<tr>
<td>平均</td>
<td><span id="average"></span></td>
</tr>
<tr>
<td>分散</td>
<td><span id="variance"></span></td>
</tr>
<tr>
<td>標準偏差σ</td>
<td><span id="sd"></span></td>
</tr>
<tr>
<td>中央値</td>
<td><span id="median"></span></td>
</tr>
<tr>
<td>最大値</td>
<td><span id="maxNd"></span></td>
</tr>
<tr>
<td>最小値</td>
<td><span id="minNd"></span></td>
</tr>
</table>
</div>
<div class="box2-2">
<form onsubmit="redrawChart(event)">
<div class="box2-2-1">
<div>
<label for="currentValue">初期投資額(10~10000万円)</label>
<input
type="number"
id="currentValue"
value="100"
step="1"
min="10"
max="100000"
required="required"
/>
</div>
<div>
<label for="averageReturnRate">期待リターン(年率0~100%)</label>
<input
type="number"
id="averageReturnRate"
value="10"
step="0.1"
min="0"
max="100"
required="required"
/>
</div>
<div>
<label for="riskRate">想定リスク(σ,年率0~100%)</label>
<input
type="number"
id="riskRate"
value="10"
step="0.1"
min="0"
max="100"
required="required"
/>
</div>
<div>
<label for="years">運用期間(1~20年)</label>
<input
type="number"
id="years"
value="5"
step="1"
min="1"
max="20"
required="required"
/>
</div>
</div>
<!-- 再描画ボタンの追加 -->
<div class="rebutton">
<button onclick="redrawChart()">再描画</button>
</div>
</form>
</div>
<!-- 横並びfloteクリア -->
<div class="clear"></div>
<!-- 既存の表を描画するための要素 -->
<div id="tableDiv" class="box2-3"></div>
</div>
</div>
<script>
var averageReturnRate;
var riskRate;
var currentValue;
var years;
var nd = [];
window.onload = function () {
// フォームの初期値を設定
document.getElementById("averageReturnRate").value = "10";
document.getElementById("riskRate").value = "10";
document.getElementById("currentValue").value = "100";
document.getElementById("years").value = "10";
// 初回描画
redrawChart(event);
};
function redrawChart(event) {
// Prevent the default form submission behavior
event.preventDefault();
// データをクリア
nd = [];
// フォームの値を取得
averageReturnRate = parseFloat(
document.getElementById("averageReturnRate").value
);
riskRate = parseFloat(document.getElementById("riskRate").value);
currentValue = parseFloat(
document.getElementById("currentValue").value
);
years = parseFloat(document.getElementById("years").value);
// getRandomValue()を呼び出して100,000回発生させる
getRandomValue(averageReturnRate, riskRate, currentValue, years);
// データの個数を表示
document.getElementById("pieces").textContent = nd.length;
// データの合計を求める
const sum = nd.reduce((a, b) => a + b, 0);
// データの平均を求める
const average = sum / nd.length;
document.getElementById("average").textContent = average.toFixed(2);
// データの分散を求める
const sumSquaredDiff = nd.reduce((a, b) => a + (b - average) ** 2, 0);
const variance = sumSquaredDiff / nd.length;
document.getElementById("variance").textContent = variance.toFixed(2);
// データの標準偏差を求める
const standardDeviation = Math.sqrt(variance);
document.getElementById("sd").textContent =
standardDeviation.toFixed(2);
// データの中央値を求める
const sortedData = [...nd].sort((a, b) => a - b);
const middle = Math.floor(sortedData.length / 2);
const median =
sortedData.length % 2 === 0
? (sortedData[middle - 1] + sortedData[middle]) / 2
: sortedData[middle];
document.getElementById("median").textContent = median.toFixed(2);
// データの最大値と最小値を求める
maxNd = Math.max(...nd);
minNd = Math.min(...nd);
document.getElementById("maxNd").textContent = maxNd.toFixed(0);
document.getElementById("minNd").textContent = minNd.toFixed(0);
var nd1 = [];
var nd2 = [];
var nd3 = [];
var nd4 = [];
var nd5 = [];
var nd6 = [];
var nd7 = [];
var nd8 = [];
function getRandomValue(
averageReturnRate,
riskRate,
currentValue,
years
) {
var x, y, z, re, s;
for (let i = 0; i < 100000; i++) {
re = 1; // 内側のループ前に re を初期化
for (let j = 0; j < years; j++) {
x = Math.random();
y = Math.random();
z = Math.sqrt(-2 * Math.log(x)) * Math.cos(2 * Math.PI * y);
re *= 1 + averageReturnRate * 0.01 + riskRate * 0.01 * z;
}
s = currentValue * re;
nd.push(s);
}
return nd; // 関数の戻り値として nd を返す
}
// ヒストグラムの各バーに対する色を決定する関数
function getColor(value) {
const deviation = (value - average) / standardDeviation;
if (deviation <= -3) {
return "purple"; // -3標準偏差超
} else if (deviation < -2) {
return "orange"; // -3標準偏差以内
} else if (deviation < -1) {
return "cyan"; // -2標準偏差以内
} else if (deviation < 0) {
return "brown"; // -1標準偏差以内
} else if (deviation < 1) {
return "red"; // 1標準偏差以内
} else if (deviation < 2) {
return "green"; // 2標準偏差以内
} else if (deviation < 3) {
return "blue"; // 3標準偏差以内
} else {
return "yellow"; // 3標準偏差超
}
}
// データを各範囲に分ける
nd.forEach((value) => {
const color = getColor(value);
if (color === "purple") {
nd1.push(value);
} else if (color === "orange") {
nd2.push(value);
} else if (color === "cyan") {
nd3.push(value);
} else if (color === "brown") {
nd4.push(value);
} else if (color === "red") {
nd5.push(value);
} else if (color === "green") {
nd6.push(value);
} else if (color === "blue") {
nd7.push(value);
} else {
nd8.push(value);
}
});
var trace1 = {
x: nd1,
type: "histogram",
marker: {
color: "purple",
},
xbins: {
end: maxNd,
size: 10 ** (String((maxNd / 1000).toFixed(0)).length - 1),
start: minNd,
},
bingroup: "group1", // 各トレースを同じグループに追加
};
var trace2 = {
x: nd2,
type: "histogram",
marker: {
color: "orange",
},
xbins: {
end: maxNd,
size: 10 ** (String((maxNd / 1000).toFixed(0)).length - 1),
start: minNd,
},
bingroup: "group2", // 各トレースを同じグループに追加
};
var trace3 = {
x: nd3,
type: "histogram",
marker: {
color: "cyan",
},
xbins: {
end: maxNd,
size: 10 ** (String((maxNd / 1000).toFixed(0)).length - 1),
start: minNd,
},
bingroup: "group3", // 各トレースを同じグループに追加
};
var trace4 = {
x: nd4,
type: "histogram",
marker: {
color: "brown",
},
xbins: {
end: maxNd,
size: 10 ** (String((maxNd / 1000).toFixed(0)).length - 1),
start: minNd,
},
bingroup: "group4", // 各トレースを同じグループに追加
};
var trace5 = {
x: nd5,
type: "histogram",
marker: {
color: "red",
},
xbins: {
end: maxNd,
size: 10 ** (String((maxNd / 1000).toFixed(0)).length - 1),
start: minNd,
},
bingroup: "group5", // 各トレースを同じグループに追加
};
var trace6 = {
x: nd6,
type: "histogram",
marker: {
color: "green",
},
xbins: {
end: maxNd,
size: 10 ** (String((maxNd / 1000).toFixed(0)).length - 1),
start: minNd,
},
bingroup: "group6", // 各トレースを同じグループに追加
};
var trace7 = {
x: nd7,
type: "histogram",
marker: {
color: "blue",
},
xbins: {
end: maxNd,
size: 10 ** (String((maxNd / 1000).toFixed(0)).length - 1),
start: minNd,
},
bingroup: "group7", // 各トレースを同じグループに追加
};
var trace8 = {
x: nd8,
type: "histogram",
marker: {
color: "yellow",
},
xbins: {
end: maxNd,
size: 10 ** (String((maxNd / 1000).toFixed(0)).length - 1),
start: minNd,
},
bingroup: "group8", // 各トレースを同じグループに追加
};
var data = [
trace1,
trace2,
trace3,
trace4,
trace5,
trace6,
trace7,
trace8,
];
var layout = {
title: "Future Asset Distribution",
xaxis: { title: "Value" },
yaxis: { title: "Count" },
width: 1000,
height: 700,
margin: {
r: 0,
b: 50,
l: 100,
t: 0,
pad: 0,
},
};
// 表を描画するためのデータ
var tableData = [
["標準偏差", "範囲", "個数", "確率", "累積分布"],
[
" ~ -3σ",
"~" + (average - 3 * standardDeviation).toFixed(1),
nd1.length,
(nd1.length / nd.length).toFixed(1),
(nd1.length / nd.length).toFixed(4),
],
[
"-3σ ~ -2σ",
(average - 3 * standardDeviation).toFixed(1) +
"~" +
(average - 2 * standardDeviation).toFixed(1),
nd2.length,
(nd2.length / nd.length).toFixed(4),
((nd1.length + nd2.length) / nd.length).toFixed(4),
],
[
"-2σ ~ -1σ",
(average - 2 * standardDeviation).toFixed(1) +
"~" +
(average - 1 * standardDeviation).toFixed(1),
nd3.length,
(nd3.length / nd.length).toFixed(4),
((nd1.length + nd2.length + nd3.length) / nd.length).toFixed(4),
],
[
"-1σ ~ 平均",
(average - 1 * standardDeviation).toFixed(1) +
"~" +
average.toFixed(1),
nd4.length,
(nd4.length / nd.length).toFixed(4),
(
(nd1.length + nd2.length + nd3.length + nd4.length) /
nd.length
).toFixed(4),
],
[
"平均 ~ 1σ",
average.toFixed(1) +
"~" +
(parseFloat(average) + parseFloat(standardDeviation)).toFixed(1),
nd5.length,
(nd5.length / nd.length).toFixed(4),
(
(nd1.length + nd2.length + nd3.length + nd4.length + nd5.length) /
nd.length
).toFixed(4),
],
[
"1σ ~ 2σ",
(parseFloat(average) + parseFloat(standardDeviation)).toFixed(1) +
"~" +
(parseFloat(average) + 2 * parseFloat(standardDeviation)).toFixed(
1
),
nd6.length,
(nd6.length / nd.length).toFixed(4),
(
(nd1.length +
nd2.length +
nd3.length +
nd4.length +
nd5.length +
nd6.length) /
nd.length
).toFixed(4),
],
[
"2σ ~ 3σ",
(parseFloat(average) + 2 * parseFloat(standardDeviation)).toFixed(
1
) +
"~" +
(parseFloat(average) + 3 * parseFloat(standardDeviation)).toFixed(
1
),
nd7.length,
(nd7.length / nd.length).toFixed(4),
(
(nd1.length +
nd2.length +
nd3.length +
nd4.length +
nd5.length +
nd6.length +
nd7.length) /
nd.length
).toFixed(4),
],
[
"3σ ~ ",
(parseFloat(average) + 3 * parseFloat(standardDeviation)).toFixed(
1
) + "~",
nd8.length,
(nd8.length / nd.length).toFixed(4),
(
(nd1.length +
nd2.length +
nd3.length +
nd4.length +
nd5.length +
nd6.length +
nd7.length +
nd8.length) /
nd.length
).toFixed(4),
],
];
// tableDiv 内の内容をクリア
document.getElementById("tableDiv").innerHTML = "";
// 表を描画
var tableDiv = document.getElementById("tableDiv");
var table = document.createElement("table");
var thead = document.createElement("thead");
var tbody = document.createElement("tbody");
table.appendChild(thead);
table.appendChild(tbody);
tableDiv.appendChild(table);
// theadを追加
var headRow = thead.insertRow();
tableData[0].forEach(function (item) {
var th = document.createElement("th");
th.appendChild(document.createTextNode(item));
// セルのスタイルを追加
th.style.border = "1px solid #000";
th.style.padding = "10px";
th.style.backgroundColor = "#f0f0f0";
headRow.appendChild(th);
});
// tbodyを追加
tableData.slice(1).forEach(function (row) {
var tr = document.createElement("tr");
row.forEach(function (item) {
var td = document.createElement("td");
td.appendChild(document.createTextNode(item));
// セルのスタイルを追加
td.style.border = "1px solid #000";
td.style.padding = "10px";
td.style.backgroundColor = "#ffffff"; // 他のセルの背景色
tr.appendChild(td);
});
tbody.appendChild(tr);
});
// 1列目のセルに色を付ける
var targetCell = document.querySelector(
"#tableDiv tbody tr:nth-child(1) td:first-child"
);
targetCell.style.backgroundColor = "purple";
targetCell.style.color = "white";
var targetCell = document.querySelector(
"#tableDiv tbody tr:nth-child(2) td:first-child"
);
targetCell.style.backgroundColor = "orange";
targetCell.style.color = "white";
var targetCell = document.querySelector(
"#tableDiv tbody tr:nth-child(3) td:first-child"
);
targetCell.style.backgroundColor = "cyan";
targetCell.style.color = "white";
var targetCell = document.querySelector(
"#tableDiv tbody tr:nth-child(4) td:first-child"
);
targetCell.style.backgroundColor = "brown";
targetCell.style.color = "white";
var targetCell = document.querySelector(
"#tableDiv tbody tr:nth-child(5) td:first-child"
);
targetCell.style.backgroundColor = "red";
targetCell.style.color = "white";
var targetCell = document.querySelector(
"#tableDiv tbody tr:nth-child(6) td:first-child"
);
targetCell.style.backgroundColor = "green";
targetCell.style.color = "white";
var targetCell = document.querySelector(
"#tableDiv tbody tr:nth-child(7) td:first-child"
);
targetCell.style.backgroundColor = "blue";
targetCell.style.color = "white";
var targetCell = document.querySelector(
"#tableDiv tbody tr:nth-child(8) td:first-child"
);
targetCell.style.backgroundColor = "yellow";
targetCell.style.color = "white";
Plotly.newPlot("myDiv", data, layout);
}
</script>
</body>
</html>
コメント