Spaces:
Running
Running
Codex commited on
Commit ยท
ddd40be
1
Parent(s): e3ed8af
Use overall K in strength map
Browse files
app.js
CHANGED
|
@@ -39,6 +39,13 @@ const state = {
|
|
| 39 |
const $ = (id) => document.getElementById(id);
|
| 40 |
const isExaone = (model) => model === "exaone-forecast" || model.startsWith("exaone-");
|
| 41 |
const displayName = (model) => isExaone(model) ? "EXAONE Forecast Finance" : model;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
const finite = (v) => Number.isFinite(v);
|
| 43 |
const fmt = (v, digits = 2) => finite(v) ? v.toFixed(digits) : '<span class="skip">โ</span>';
|
| 44 |
const fmtValue = (v) => {
|
|
@@ -277,7 +284,7 @@ function detailsByScope() {
|
|
| 277 |
for (const row of state.records) {
|
| 278 |
const group = `${row.scope || "Other"} ยท ${row.category || "Other"}`;
|
| 279 |
if (!grouped.has(group)) grouped.set(group, new Map());
|
| 280 |
-
if (!grouped.get(group).has(row.detail_category)) grouped.get(group).set(row.detail_category, row.detail_category);
|
| 281 |
}
|
| 282 |
return [...grouped.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
| 283 |
}
|
|
@@ -622,7 +629,7 @@ function fillHowtoUnits() {
|
|
| 622 |
const tier = $("howto-tier").value || "tier1";
|
| 623 |
const current = $("howto-detail").value;
|
| 624 |
const details = [...new Set(state.records.filter((r) => r.model === model && r.tier === tier).map((r) => r.detail_category))].sort();
|
| 625 |
-
$("howto-detail").innerHTML = details.map((detail) => `<option value="${detail}">${detail}</option>`).join("");
|
| 626 |
if (details.includes(current)) $("howto-detail").value = current;
|
| 627 |
fillHowtoFrequencies();
|
| 628 |
}
|
|
@@ -768,7 +775,7 @@ function showMetricScoreDetail(model, tier, metricGroup) {
|
|
| 768 |
&& candidate.series_id === row.series_id
|
| 769 |
&& candidate.metric === row.metric;
|
| 770 |
}).length;
|
| 771 |
-
html += `<tr><td title="${row.category || ""}">${row.detail_category}</td><td title="${row.frequency}">${freqCode(row.frequency)}</td><td title="${row.metric}">${parts.name} <span class="dir-arrow ${direction > 0 ? "up" : "down"}">${direction > 0 ? "โ" : "โ"}</span></td><td>${parts.type}</td><td>${parts.target}</td><td class="num">${fmtValue(row.value)}</td><td class="num">${rankText(row.rank, total)}</td></tr>`;
|
| 772 |
}
|
| 773 |
html += `</tbody></table><p class="note">ํ์ฌ ์ผ์ชฝ Metric ยท Detail Category ยท Frequency ํํฐ ์กฐ๊ฑด ์์์ ์ด ํ๊ท ์
์ ๊ตฌ์ฑํ ์ค์ metric ๊ฐ๊ณผ rank์
๋๋ค.</p>`;
|
| 774 |
openDrawer(`${displayName(model)} ยท ${metricGroupLabel(metricGroup)}`, html);
|
|
@@ -799,10 +806,16 @@ function renderStrength() {
|
|
| 799 |
$("strength-body").innerHTML = '<p class="loading-note">์ ํ๋ ํํฐ ์กฐ๊ฑด์ ํด๋นํ๋ cell์ด ์์ต๋๋ค.</p>';
|
| 800 |
return;
|
| 801 |
}
|
| 802 |
-
const
|
| 803 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 804 |
const matrix = unitK(null, scopedRecords);
|
| 805 |
-
const overall =
|
|
|
|
|
|
|
| 806 |
const colRanks = new Map();
|
| 807 |
for (const [unit] of units) {
|
| 808 |
const vals = state.models.map((model) => ({ model, value: matrix.get(model).get(unit) }));
|
|
@@ -817,9 +830,9 @@ function renderStrength() {
|
|
| 817 |
for (const [, label] of units) html += `<th class="sp"><span>${label}</span></th>`;
|
| 818 |
html += `</tr></thead><tbody>`;
|
| 819 |
for (const model of overall) {
|
| 820 |
-
const
|
| 821 |
-
const
|
| 822 |
-
html += `<tr class="${isExaone(model) ? "exaone-row" : ""}"><td class="mh">${displayName(model)}</td><td class="ov" style="background:${color(
|
| 823 |
for (const [unit] of units) {
|
| 824 |
const k = matrix.get(model).get(unit);
|
| 825 |
const rank = colRanks.get(unit).get(model);
|
|
@@ -867,7 +880,7 @@ function renderGuide() {
|
|
| 867 |
function showModelDetail(model) {
|
| 868 |
if (!state.recordsReady) return;
|
| 869 |
const stats = tierStats().find((r) => r.model === model);
|
| 870 |
-
const units = [...new Map(includedRecords().filter((r) => r.model === model).map((r) => [r.unit, r.unit_label || r.unit])).entries()].sort((a, b) => a[1].localeCompare(b[1]));
|
| 871 |
const categoryByUnit = new Map(includedRecords().filter((r) => r.model === model).map((r) => [r.unit, r.category || ""]));
|
| 872 |
const matrixByTier = Object.fromEntries(Object.keys(TIER_LABEL).map((tier) => [tier, unitK(tier).get(model)]));
|
| 873 |
let html = `<p class="detail-k">Rank sum = <b>${fmt(stats.overall, finite(stats.overall) && stats.overall % 1 ? 1 : 0)}</b></p><table><thead><tr><th>Category</th><th>Detail Category</th><th class="num">Point</th><th class="num">Ranking</th><th class="num">Decision</th></tr></thead><tbody>`;
|
|
@@ -888,7 +901,7 @@ function showModelDetail(model) {
|
|
| 888 |
function showTierDetail(model, tier) {
|
| 889 |
if (!state.recordsReady) return;
|
| 890 |
const matrix = unitK(tier).get(model);
|
| 891 |
-
const units = [...new Map(includedRecords().filter((r) => r.model === model && r.tier === tier).map((r) => [r.unit, r.unit_label || r.unit])).entries()].sort((a, b) => a[1].localeCompare(b[1]));
|
| 892 |
const categoryByUnit = new Map(includedRecords().filter((r) => r.model === model && r.tier === tier).map((r) => [r.unit, r.category || ""]));
|
| 893 |
let html = `<p class="detail-k">${TIER_SHORT[tier]} K = <b>${fmt(tierStats().find((r) => r.model === model)[`${ASPECT[tier]}_k`])}</b></p><table><thead><tr><th>Category</th><th>Detail Category</th><th class="num">K</th></tr></thead><tbody>`;
|
| 894 |
for (const [unit, label] of units) {
|
|
@@ -917,7 +930,7 @@ function showMetricDetail(model, tier, unit) {
|
|
| 917 |
|| horizonOrder(aTarget) - horizonOrder(bTarget)
|
| 918 |
|| a.metric.localeCompare(b.metric);
|
| 919 |
});
|
| 920 |
-
const label = rows[0]?.unit_label || unit;
|
| 921 |
const k = geometricMean(rows.map((r) => r.rank));
|
| 922 |
let html = `<p class="detail-k">${TIER_SHORT[tier]} ยท ${label} K = <b>${fmt(k)}</b> ยท ${rows.length.toLocaleString()} cells</p>`;
|
| 923 |
html += `<div class="period-card"><h3>Description for Date Codes</h3><div class="period-help"><span><b>D</b> Day</span><span><b>W</b> Week</span><span><b>M</b> Month</span><span><b>Q</b> Quarter</span><span><b>H</b> Half-year</span><span><b>Y</b> Year</span><span><b>B</b> Business</span><span><b>BD</b> Business-day</span></div></div>`;
|
|
|
|
| 39 |
const $ = (id) => document.getElementById(id);
|
| 40 |
const isExaone = (model) => model === "exaone-forecast" || model.startsWith("exaone-");
|
| 41 |
const displayName = (model) => isExaone(model) ? "EXAONE Forecast Finance" : model;
|
| 42 |
+
const displayDetailLabel = (label) => {
|
| 43 |
+
const map = {
|
| 44 |
+
"Crypto Pair Close (Top 100)": "Crypto Pair Close",
|
| 45 |
+
"OHLCV Close": "Close"
|
| 46 |
+
};
|
| 47 |
+
return map[label] || label;
|
| 48 |
+
};
|
| 49 |
const finite = (v) => Number.isFinite(v);
|
| 50 |
const fmt = (v, digits = 2) => finite(v) ? v.toFixed(digits) : '<span class="skip">โ</span>';
|
| 51 |
const fmtValue = (v) => {
|
|
|
|
| 284 |
for (const row of state.records) {
|
| 285 |
const group = `${row.scope || "Other"} ยท ${row.category || "Other"}`;
|
| 286 |
if (!grouped.has(group)) grouped.set(group, new Map());
|
| 287 |
+
if (!grouped.get(group).has(row.detail_category)) grouped.get(group).set(row.detail_category, displayDetailLabel(row.detail_category));
|
| 288 |
}
|
| 289 |
return [...grouped.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
| 290 |
}
|
|
|
|
| 629 |
const tier = $("howto-tier").value || "tier1";
|
| 630 |
const current = $("howto-detail").value;
|
| 631 |
const details = [...new Set(state.records.filter((r) => r.model === model && r.tier === tier).map((r) => r.detail_category))].sort();
|
| 632 |
+
$("howto-detail").innerHTML = details.map((detail) => `<option value="${detail}">${displayDetailLabel(detail)}</option>`).join("");
|
| 633 |
if (details.includes(current)) $("howto-detail").value = current;
|
| 634 |
fillHowtoFrequencies();
|
| 635 |
}
|
|
|
|
| 775 |
&& candidate.series_id === row.series_id
|
| 776 |
&& candidate.metric === row.metric;
|
| 777 |
}).length;
|
| 778 |
+
html += `<tr><td title="${row.category || ""}">${displayDetailLabel(row.detail_category)}</td><td title="${row.frequency}">${freqCode(row.frequency)}</td><td title="${row.metric}">${parts.name} <span class="dir-arrow ${direction > 0 ? "up" : "down"}">${direction > 0 ? "โ" : "โ"}</span></td><td>${parts.type}</td><td>${parts.target}</td><td class="num">${fmtValue(row.value)}</td><td class="num">${rankText(row.rank, total)}</td></tr>`;
|
| 779 |
}
|
| 780 |
html += `</tbody></table><p class="note">ํ์ฌ ์ผ์ชฝ Metric ยท Detail Category ยท Frequency ํํฐ ์กฐ๊ฑด ์์์ ์ด ํ๊ท ์
์ ๊ตฌ์ฑํ ์ค์ metric ๊ฐ๊ณผ rank์
๋๋ค.</p>`;
|
| 781 |
openDrawer(`${displayName(model)} ยท ${metricGroupLabel(metricGroup)}`, html);
|
|
|
|
| 806 |
$("strength-body").innerHTML = '<p class="loading-note">์ ํ๋ ํํฐ ์กฐ๊ฑด์ ํด๋นํ๋ cell์ด ์์ต๋๋ค.</p>';
|
| 807 |
return;
|
| 808 |
}
|
| 809 |
+
const overallScores = new Map(state.models.map((model) => [
|
| 810 |
+
model,
|
| 811 |
+
geometricMean(scopedRecords.filter((row) => row.model === model).map((row) => row.rank))
|
| 812 |
+
]));
|
| 813 |
+
const overallRanks = new Map(rankRows([...overallScores.entries()].map(([model, value]) => ({ model, value })), "value", -1).map((row) => [row.model, row.rank]));
|
| 814 |
+
const units = [...new Map(scopedRecords.map((r) => [r.unit, displayDetailLabel(r.unit_label || r.unit)])).entries()].sort((a, b) => a[1].localeCompare(b[1]));
|
| 815 |
const matrix = unitK(null, scopedRecords);
|
| 816 |
+
const overall = state.models
|
| 817 |
+
.filter((model) => finite(overallScores.get(model)))
|
| 818 |
+
.sort((a, b) => compareNullable(overallScores.get(a), overallScores.get(b)) || a.localeCompare(b));
|
| 819 |
const colRanks = new Map();
|
| 820 |
for (const [unit] of units) {
|
| 821 |
const vals = state.models.map((model) => ({ model, value: matrix.get(model).get(unit) }));
|
|
|
|
| 830 |
for (const [, label] of units) html += `<th class="sp"><span>${label}</span></th>`;
|
| 831 |
html += `</tr></thead><tbody>`;
|
| 832 |
for (const model of overall) {
|
| 833 |
+
const ov = overallScores.get(model);
|
| 834 |
+
const ovRank = overallRanks.get(model);
|
| 835 |
+
html += `<tr class="${isExaone(model) ? "exaone-row" : ""}"><td class="mh">${displayName(model)}</td><td class="ov" style="background:${color(ovRank, overall.length)}" title="Overall K geomean">${fmt(ov)}</td>`;
|
| 836 |
for (const [unit] of units) {
|
| 837 |
const k = matrix.get(model).get(unit);
|
| 838 |
const rank = colRanks.get(unit).get(model);
|
|
|
|
| 880 |
function showModelDetail(model) {
|
| 881 |
if (!state.recordsReady) return;
|
| 882 |
const stats = tierStats().find((r) => r.model === model);
|
| 883 |
+
const units = [...new Map(includedRecords().filter((r) => r.model === model).map((r) => [r.unit, displayDetailLabel(r.unit_label || r.unit)])).entries()].sort((a, b) => a[1].localeCompare(b[1]));
|
| 884 |
const categoryByUnit = new Map(includedRecords().filter((r) => r.model === model).map((r) => [r.unit, r.category || ""]));
|
| 885 |
const matrixByTier = Object.fromEntries(Object.keys(TIER_LABEL).map((tier) => [tier, unitK(tier).get(model)]));
|
| 886 |
let html = `<p class="detail-k">Rank sum = <b>${fmt(stats.overall, finite(stats.overall) && stats.overall % 1 ? 1 : 0)}</b></p><table><thead><tr><th>Category</th><th>Detail Category</th><th class="num">Point</th><th class="num">Ranking</th><th class="num">Decision</th></tr></thead><tbody>`;
|
|
|
|
| 901 |
function showTierDetail(model, tier) {
|
| 902 |
if (!state.recordsReady) return;
|
| 903 |
const matrix = unitK(tier).get(model);
|
| 904 |
+
const units = [...new Map(includedRecords().filter((r) => r.model === model && r.tier === tier).map((r) => [r.unit, displayDetailLabel(r.unit_label || r.unit)])).entries()].sort((a, b) => a[1].localeCompare(b[1]));
|
| 905 |
const categoryByUnit = new Map(includedRecords().filter((r) => r.model === model && r.tier === tier).map((r) => [r.unit, r.category || ""]));
|
| 906 |
let html = `<p class="detail-k">${TIER_SHORT[tier]} K = <b>${fmt(tierStats().find((r) => r.model === model)[`${ASPECT[tier]}_k`])}</b></p><table><thead><tr><th>Category</th><th>Detail Category</th><th class="num">K</th></tr></thead><tbody>`;
|
| 907 |
for (const [unit, label] of units) {
|
|
|
|
| 930 |
|| horizonOrder(aTarget) - horizonOrder(bTarget)
|
| 931 |
|| a.metric.localeCompare(b.metric);
|
| 932 |
});
|
| 933 |
+
const label = displayDetailLabel(rows[0]?.unit_label || unit);
|
| 934 |
const k = geometricMean(rows.map((r) => r.rank));
|
| 935 |
let html = `<p class="detail-k">${TIER_SHORT[tier]} ยท ${label} K = <b>${fmt(k)}</b> ยท ${rows.length.toLocaleString()} cells</p>`;
|
| 936 |
html += `<div class="period-card"><h3>Description for Date Codes</h3><div class="period-help"><span><b>D</b> Day</span><span><b>W</b> Week</span><span><b>M</b> Month</span><span><b>Q</b> Quarter</span><span><b>H</b> Half-year</span><span><b>Y</b> Year</span><span><b>B</b> Business</span><span><b>BD</b> Business-day</span></div></div>`;
|