1document.addEventListener('DOMContentLoaded', function() { 2 3 // PHPã§ä¿åãã2ã¤ã®JSONãã¡ã¤ã«ã¸ã®ãã¹ï¼â»ç°å¢ã«åããã¦å¤æ´ãã¦ãã ããï¼ 4 const jgbLongJsonPath = '/fmp/json/jgb_treasury_long.json'; // ææ«éå¼ãçï¼é·ææ¯è¼ã»ãã¬ã³ãç¨ï¼ 5 const jgbShortJsonPath = '/fmp/json/jgb_treasury.json'; // æ¯æ¥çï¼çææ¯è¼ç¨ï¼ 6 7 // 2ã¤ã®JSONãåæã«èªã¿è¾¼ã 8 Promise.all([ 9 fetch(jgbLongJsonPath).then(res => { 10 if (!res.ok) throw new Error('æ¥æ¬å½åµ é·æJSONã¨ã©ã¼'); 11 return res.json(); 12 }), 13 fetch(jgbShortJsonPath).then(res => { 14 if (!res.ok) throw new Error('æ¥æ¬å½åµ çæJSONã¨ã©ã¼'); 15 return res.json(); 16 }) 17 ]) 18 .then(([longData, shortData]) => { 19 if(!longData || longData.length === 0 || !shortData || shortData.length === 0) return; 20 21 // ======================================================== 22 // ã¤ã¼ã«ãã«ã¼ãå ±éè¨å® 23 // ======================================================== 24 const keys = ['year1', 'year2', 'year3', 'year5', 'year7', 'year10', 'year20', 'year30', 'year40']; 25 const curveLabels = ['1å¹´', '2å¹´', '3å¹´', '5å¹´', '7å¹´', '10å¹´', '20å¹´', '30å¹´', '40å¹´']; 26 const extractValues = (rowData) => keys.map(key => rowData[key]); 27 28 // nullï¼ç©ºç½ãã¼ã¿ï¼ãé¤å¤ãã¦æå°å¤ãè¨ç®ããå®å ¨ãªé¢æ° 29 const getSafeMin = (arr) => Math.min(...arr.filter(v => v !== null)); 30 31 // ======================================================== 32 // 1-Aï¼æ¥æ¬å½åµã¤ã¼ã«ãã«ã¼ãï¼çæï¼ç¾å¨ã»5å¶æ¥æ¥åã»1ã¶æåï¼ 33 // ======================================================== 34 const latestShort = shortData[0]; 35 const fiveDaysAgo = shortData.length > 5 ? shortData[5] : shortData[shortData.length - 1]; 36 const oneMonthAgo = shortData.length > 20 ? shortData[20] : shortData[shortData.length - 1]; 37 38 const shortCurveValues = [...extractValues(latestShort), ...extractValues(fiveDaysAgo), ...extractValues(oneMonthAgo)]; 39 const shortCurveMin = getSafeMin(shortCurveValues); 40 41 const ctxShortCurve = document.getElementById('jgbYieldCurveShortChart').getContext('2d'); 42 new Chart(ctxShortCurve, { 43 type: 'line', 44 data: { 45 labels: curveLabels, 46 datasets: [ 47 { 48 label: `ç¾å¨ (${latestShort.date})`, dateLabel: latestShort.date, data: extractValues(latestShort), 49 borderColor: 'rgba(255,87,34,.6)', backgroundColor: '#FF5722', borderWidth: 3, pointRadius: 3, pointHoverRadius: 6, tension: 0.4 50 }, 51 { 52 label: `5å¶æ¥æ¥å`, dateLabel: fiveDaysAgo.date, data: extractValues(fiveDaysAgo), 53 borderColor: '#42a5f5', backgroundColor: '#fff', borderWidth: 2, borderDash: [5, 5], pointRadius: 0, pointHoverRadius: 4, tension: 0.4 54 }, 55 { 56 label: `ç´1ã¶æå`, dateLabel: oneMonthAgo.date, data: extractValues(oneMonthAgo), 57 borderColor: '#999', backgroundColor: '#fff', borderWidth: 2, borderDash: [2, 2], pointRadius: 0, pointHoverRadius: 4, tension: 0.4 58 } 59 ] 60 }, 61 options: { 62 maintainAspectRatio: false, responsive: true, 63 plugins: { 64 legend: { position: 'top', labels: { usePointStyle: true, padding: 20 } }, 65 title: { display: false, text: 'ãçææ¯è¼ãã¤ã¼ã«ãã«ã¼ãã®å¤å', font: { size: 14 } }, 66 tooltip: { 67 mode: 'index', intersect: false, 68 callbacks: { 69 label: function(context) { 70 const labelName = context.dataset.label; 71 const dateStr = context.dataset.dateLabel; 72 const value = context.parsed.y.toFixed(3); 73 74 // ãç¾å¨ (2026-02-27)ãã®ããã«æ¢ã«ã«ãã³ãå«ã¾ãã¦ããå ´åã¯æ¥ä»ãäºéã«
74è¶³ããªã 75 if (labelName.includes('(')) { 76 return `${labelName} : ${value}%`; 77 } else { 78 return `${labelName} (${dateStr}) : ${value}%`; 79 } 80 } 81 } 82 } 83 }, 84 scales: { 85 y: { suggestedMin: shortCurveMin - 0.1, title: { display: false }, ticks: { callback: function(value) { return value.toFixed(1) + '%'; } } }, 86 x: { grid: { display: false }, title: { display: true, text: 'åéæé' } } 87 }, 88 interaction: { mode: 'nearest', axis: 'x', intersect: false } 89 } 90 }); 91 92 // ======================================================== 93 // 1-Bï¼æ¥æ¬å½åµã¤ã¼ã«ãã«ã¼ãï¼é·æï¼ç¾å¨ã»3ã¶æåã»1å¹´åï¼ 94 // ======================================================== 95 const latestLong = longData[0]; 96 const threeMonthsAgo = longData.length > 3 ? longData[3] : longData[longData.length - 1]; 97 const oneYearAgo = longData.length > 12 ? longData[12] : longData[longData.length - 1]; 98 99 const longCurveValues = [...extractValues(latestLong), ...extractValues(threeMonthsAgo), ...extractValues(oneYearAgo)]; 100 const longCurveMin = getSafeMin(longCurveValues); 101 102 const ctxLongCurve = document.getElementById('jgbYieldCurveLongChart').getContext('2d'); 103 new Chart(ctxLongCurve, { 104 type: 'line', 105 data: { 106 labels: curveLabels, 107 datasets: [ 108 { 109 label: `ç¾å¨ (${latestLong.date})`, dateLabel: latestLong.date, data: extractValues(latestLong), 110 borderColor: 'rgba(255,87,34,.6)', backgroundColor: '#FF5722', borderWidth: 3, pointRadius: 3, pointHoverRadius: 6, tension: 0.4 111 }, 112 { 113 label: `3ã¶æå`, dateLabel: threeMonthsAgo.date, data: extractValues(threeMonthsAgo), 114 borderColor: '#42a5f5', backgroundColor: '#fff', borderWidth: 2, borderDash: [5, 5], pointRadius: 0, pointHoverRadius: 4, tension: 0.4 115 }, 116 { 117 label: `1å¹´å`, dateLabel: oneYearAgo.date, data: extractValues(oneYearAgo), 118 borderColor: '#999', backgroundColor: '#fff', borderWidth: 2, borderDash: [2, 2], pointRadius: 0, pointHoverRadius: 4, tension: 0.4 119 } 120 ] 121 }, 122 options: { 123 maintainAspectRatio: false, responsive: true, 124 plugins: { 125 legend: { position: 'top', labels: { usePointStyle: true, padding: 20 } }, 126 title: { display: false, text: 'ãé·ææ¯è¼ãã¤ã¼ã«ãã«ã¼ãã®å¤å', font: { size: 14 } }, 127 tooltip: { 128 mode: 'index', intersect: false, 129 callbacks: { 130 label: function(context) { 131 const labelName = context.dataset.label; 132 const dateStr = context.dataset.dateLabel; 133 const value = context.parsed.y.toFixed(3); 134 135 // ãç¾å¨ (2026-02-27)ãã®ããã«æ¢ã«ã«ãã³ãå«ã¾ãã¦ããå ´åã¯æ¥ä»ãäºéã«è¶³ããªã 136 if (labelName.includes('(')) { 137 return `${labelName} : ${value}%`; 138 } else { 139 return `${labelName} (${dateStr}) : ${value}%`; 140 } 141 } 142 } 143 } 144 }, 145 scales: { 146 y: { suggestedMin: longCurveMin - 0.1, title: { display: false }, ticks: { callback: function(value) { return value.toFixed(1) + '%'; } } }, 147 x: { grid: { display: false }, title: { display: true, text: 'åéæé' } } 148 }, 149 interaction: { mode: 'nearest', axis: 'x', intersect: false } 150 } 151 }); 152 153 // ======================================================== 154 // 2ï¼æ¥æ¬å½åµ é·æãã¬ã³ããã£ã¼ã 155 // ======================================================== 156 const monthlyData = [...longData].reverse(); // éå»ããç¾å¨ã¸æé ã«ãã 157 const trendLabels = monthlyData.map(item => item.date.replace('-', '/').substring(0, 7)); 158 159 const datasetConfig = [
160 { key: 'year1', label: '1å¹´åµ', color: '#FF9800' }, 161 { key: 'year2', label: '2å¹´åµ', color: '#F44336' }, 162 { key: 'year5', label: '5å¹´åµ', color: '#9C27B0' }, 163 { key: 'year10', label: '10å¹´åµ', color: '#2196F3' }, 164 { key: 'year30', label: '30å¹´åµ', color: '#4CAF50' } 165 ]; 166 167 const trendDatasets = datasetConfig.map(config => { 168 return { 169 label: config.label, 170 data: monthlyData.map(item => item[config.key]), 171 borderColor: config.color, 172 backgroundColor: config.color, 173 borderWidth: 1.5, 174 pointRadius: 0, 175 pointHoverRadius: 4, 176 tension: 0.1 177 }; 178 }); 179 180 let allTrendValues = []; 181 trendDatasets.forEach(dataset => allTrendValues.push(...dataset.data)); 182 const trendMin = getSafeMin(allTrendValues); 183 184 const ctxTrend = document.getElementById('jgbYieldTrendChart').getContext('2d'); 185 new Chart(ctxTrend, { 186 type: 'line', 187 data: { labels: trendLabels, datasets: trendDatasets }, 188 options: { 189 maintainAspectRatio: false, responsive: true, 190 plugins: { 191 legend: { position: 'top', labels: { usePointStyle: true, padding: 15 } }, 192 tooltip: { 193 mode: 'index', intersect: false, 194 callbacks: { 195 title: function(context) { return context[0].label; }, 196 label: function(context) { return `${context.dataset.label} : ${context.parsed.y.toFixed(3)}%`; } 197 } 198 } 199 }, 200 scales: { 201 x: { 202 grid: { display: false }, 203 ticks: { maxTicksLimit: 15, color: '#222', 204 callback: function(value) { 205 const fullLabel = this.getLabelForValue(value); 206 return fullLabel ? fullLabel.substring(0, 4) : ''; 207 } 208 } 209 }, 210 y: { 211 suggestedMin: trendMin - 0.2, title: { display: false }, 212 ticks: { color: '#222', callback: function(value) { return value.toFixed(1) + '%'; } } 213 } 214 }, 215 interaction: { mode: 'nearest', axis: 'x', intersect: false } 216 } 217 }); 218 219 // ======================================================== 220 // 3ï¼æ¥æ¬å½åµ 10å¹´-2å¹´ ã¹ãã¬ããï¼éå©å·®ï¼ãã£ã¼ã 221 // ======================================================== 222 const startDateJGB = '1990-01-01'; 223 const spreadTargetData = monthlyData.filter(item => item.date >= startDateJGB); 224 const spreadLabels = spreadTargetData.map(item => item.date.replace('-', '/').substring(0, 7)); 225 226 const spreadData = spreadTargetData.map(item => { 227 if (item.year10 !== null && item.year2 !== null) { 228 return item.year10 - item.year2; 229 } 230 return null; 231 }); 232 233 const ctxSpread = document.getElementById('jgbSpreadChart').getContext('2d'); 234 new Chart(ctxSpread, { 235 type: 'line', 236 data: { 237 labels: spreadLabels, 238 datasets: [{ 239 label: '10å¹´åµ - 2å¹´åµ éå©å·®ï¼ã¹ãã¬ããï¼', 240 data: spreadData, 241 borderColor: '#42a5f5', backgroundColor: 'rgba(66,165,245,.1)', 242 borderWidth: 2, fill: true, pointRadius: 0, pointHoverRadius: 4, tension: 0.1 243 }] 244 }, 245 options: { 246 maintainAspectRatio: false, responsive: true, 247 plugins: { 248 legend: { position: 'top', labels: { usePointStyle: true, padding: 15 } }, 249 tooltip: { 250 mode: 'index', intersect: false, 251 callbacks: { 252 title: function(context) { return context[0].label; }, 253 label: function(context) { return `${context.dataset.label} : ${context.parsed.y.toFixed(3)}%`; } 254 } 255 } 256 }, 257 scales: { 258 x: { 259 grid: { display: false }, 260 ticks: { maxTicksLimit: 15, color: '#222', 261 callback: function(value) { 262 const fullLabel = this.getLabelForValue(value); 263 return fullLabel ? fullLabel.substring(0, 4) : ''; 264 } 265 } 266 }, 267 y: { 268 title: { display: false }, 269 grid: { 270 color: function(context) { return context.tick.value === 0 ? 'rgba(255, 0, 0, 0.5)' : 'rgba(0, 0, 0, 0.05)'; }, 271 lineWidth: function(context) { return context.tick.value === 0 ? 2 : 1; } 272 }, 273 ticks: { color: '#222', callback: function(value) { return value.toFixed(1) + '%'; } } 274 } 275 }, 276 interaction: { mode: 'nearest', axis: 'x', intersect: false } 277 } 278 }); 279 280 }) 281 .catch(error => console.error('æ¥æ¬å½åµã¨ã©ã¼:', error)); 282});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.