Update templates/index.html
Browse files- templates/index.html +130 -19
templates/index.html
CHANGED
|
@@ -143,6 +143,7 @@
|
|
| 143 |
.research-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 10px; }
|
| 144 |
.research-ticker { font-size: 1.8em; font-weight: 800; background: linear-gradient(135deg, #00d9ff, #00ff88); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
| 145 |
.rating-badge { padding: 10px 20px; border-radius: 25px; font-size: 1em; font-weight: 700; }
|
|
|
|
| 146 |
.rating-buy { background: #2ed573; color: #1a1a2e; }
|
| 147 |
.rating-hold { background: #ffa502; color: #1a1a2e; }
|
| 148 |
.rating-sell { background: #ff4757; color: white; }
|
|
@@ -423,21 +424,28 @@
|
|
| 423 |
<div class="metrics-grid">
|
| 424 |
<div class="metric-card">
|
| 425 |
<div class="metric-label">νμ¬κ°</div>
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
<div class="metric-
|
| 438 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
</div>
|
| 440 |
-
</div>
|
| 441 |
<div class="soma-agent soma-supervisor">
|
| 442 |
<div class="soma-header">
|
| 443 |
<div class="soma-icon" style="background: #9b59b6;">π</div>
|
|
@@ -668,8 +676,51 @@
|
|
| 668 |
<div class="metric-card"><div class="metric-label">νμ¬κ°</div><div class="metric-value" id="result-current-price">-</div></div>
|
| 669 |
<div class="metric-card"><div class="metric-label">λͺ©νκ°</div><div class="metric-value" style="color: #00ff88;" id="result-target-price">-</div></div>
|
| 670 |
<div class="metric-card"><div class="metric-label">ν¬μμ견</div><div class="metric-value" style="color: #00d9ff;" id="result-rating">-</div></div>
|
| 671 |
-
<div class="metric-card"><div class="metric-label">μμΉμ¬λ ₯</div><div class="metric-value" style="color: #2ed573;" id="result-upside">-</div></div>
|
| 672 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 673 |
<div class="deep-section" style="background: rgba(0,217,255,0.1); border: 1px solid rgba(0,217,255,0.3);"><h3>π ν΅μ¬ μμ½</h3><div class="content" id="result-executive-summary"></div></div>
|
| 674 |
<div class="deep-section"><h3>π’ νμ¬ κ°μ</h3><div class="content" id="result-company-overview"></div></div>
|
| 675 |
<div class="deep-section"><h3>π° μ¬λ¬΄ λΆμ</h3><div class="content" id="result-financial-analysis"></div></div>
|
|
@@ -1399,6 +1450,46 @@
|
|
| 1399 |
return text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>').replace(/\n/g, '<br>');
|
| 1400 |
}
|
| 1401 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1402 |
function initAnalysisCharts(report) {
|
| 1403 |
[metricsChartInstance, priceChartInstance, riskChartInstance, growthChartInstance].forEach(c => c && c.destroy());
|
| 1404 |
const cp = report.current_price || 100, tp = report.target_price || 112;
|
|
@@ -1504,7 +1595,9 @@
|
|
| 1504 |
document.getElementById('result-current-price').textContent = report.current_price ? `$${report.current_price.toLocaleString()}` : '-';
|
| 1505 |
document.getElementById('result-target-price').textContent = report.target_price ? `$${report.target_price.toLocaleString()}` : '-';
|
| 1506 |
document.getElementById('result-rating').textContent = report.rating || 'Buy';
|
| 1507 |
-
|
|
|
|
|
|
|
| 1508 |
|
| 1509 |
setTimeout(() => initAnalysisCharts(report), 100);
|
| 1510 |
|
|
@@ -1602,10 +1695,28 @@
|
|
| 1602 |
<div class="metric-label">ν¬μμ견</div>
|
| 1603 |
<div class="metric-value">${document.getElementById('result-rating')?.textContent || '-'}</div>
|
| 1604 |
</div>
|
| 1605 |
-
|
| 1606 |
-
|
| 1607 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1608 |
</div>
|
|
|
|
| 1609 |
</div>
|
| 1610 |
|
| 1611 |
<div class="section">
|
|
|
|
| 143 |
.research-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 10px; }
|
| 144 |
.research-ticker { font-size: 1.8em; font-weight: 800; background: linear-gradient(135deg, #00d9ff, #00ff88); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
| 145 |
.rating-badge { padding: 10px 20px; border-radius: 25px; font-size: 1em; font-weight: 700; }
|
| 146 |
+
.rating-strong-buy { background: linear-gradient(135deg, #00ff88, #00d9ff); color: #1a1a2e; }
|
| 147 |
.rating-buy { background: #2ed573; color: #1a1a2e; }
|
| 148 |
.rating-hold { background: #ffa502; color: #1a1a2e; }
|
| 149 |
.rating-sell { background: #ff4757; color: white; }
|
|
|
|
| 424 |
<div class="metrics-grid">
|
| 425 |
<div class="metric-card">
|
| 426 |
<div class="metric-label">νμ¬κ°</div>
|
| 427 |
+
<div class="metric-value">${{ "{:,.2f}".format(report.current_price) }}</div>
|
| 428 |
+
</div>
|
| 429 |
+
<div class="metric-card">
|
| 430 |
+
<div class="metric-label">λͺ©νκ°</div>
|
| 431 |
+
<div class="metric-value" style="color: #00ff88;">${{ "{:,.2f}".format(report.target_price) }}</div>
|
| 432 |
+
</div>
|
| 433 |
+
<div class="metric-card">
|
| 434 |
+
<div class="metric-label">π νλ½ λ¦¬μ€ν¬</div>
|
| 435 |
+
<div class="metric-value" style="color: #ff4757;">{{ report.get('expected_downside', -10) }}%</div>
|
| 436 |
+
<div style="font-size: 0.7em; color: #888;">{{ report.get('down_probability', 45) }}% νλ₯ </div>
|
| 437 |
+
</div>
|
| 438 |
+
<div class="metric-card" style="background: rgba(0,217,255,0.15); border: 1px solid rgba(0,217,255,0.3);">
|
| 439 |
+
<div class="metric-label">π― κΈ°λ μμ΅</div>
|
| 440 |
+
<div class="metric-value" style="color: #00d9ff;">{% set pred = report.get('base_prediction', report.get('upside', 8)) %}{% if pred >= 0 %}+{% endif %}{{ pred }}%</div>
|
| 441 |
+
<div style="font-size: 0.7em; color: #888;">R/R {{ report.get('risk_reward', 1.5) }}:1</div>
|
| 442 |
+
</div>
|
| 443 |
+
<div class="metric-card">
|
| 444 |
+
<div class="metric-label">π μμΉ μ μ¬λ ₯</div>
|
| 445 |
+
<div class="metric-value" style="color: #00ff88;">+{{ report.get('expected_upside', 15) }}%</div>
|
| 446 |
+
<div style="font-size: 0.7em; color: #888;">{{ report.get('up_probability', 55) }}% νλ₯ </div>
|
| 447 |
+
</div>
|
| 448 |
</div>
|
|
|
|
| 449 |
<div class="soma-agent soma-supervisor">
|
| 450 |
<div class="soma-header">
|
| 451 |
<div class="soma-icon" style="background: #9b59b6;">π</div>
|
|
|
|
| 676 |
<div class="metric-card"><div class="metric-label">νμ¬κ°</div><div class="metric-value" id="result-current-price">-</div></div>
|
| 677 |
<div class="metric-card"><div class="metric-label">λͺ©νκ°</div><div class="metric-value" style="color: #00ff88;" id="result-target-price">-</div></div>
|
| 678 |
<div class="metric-card"><div class="metric-label">ν¬μμ견</div><div class="metric-value" style="color: #00d9ff;" id="result-rating">-</div></div>
|
|
|
|
| 679 |
</div>
|
| 680 |
+
|
| 681 |
+
<!-- νλ ₯μ± μμΈ‘ μκ°μ UI -->
|
| 682 |
+
<div class="elasticity-container" style="margin-bottom: 25px; padding: 20px; background: rgba(0,0,0,0.3); border-radius: 15px; border: 1px solid rgba(255,255,255,0.1);">
|
| 683 |
+
<h4 style="color: #00d9ff; margin-bottom: 15px; text-align: center;">π νλ ₯μ± μμΈ‘</h4>
|
| 684 |
+
|
| 685 |
+
<!-- μκ°μ λ° -->
|
| 686 |
+
<div class="elasticity-bar-container" style="position: relative; height: 50px; margin: 20px 0;">
|
| 687 |
+
<div class="elasticity-scale" style="display: flex; justify-content: space-between; font-size: 11px; color: #888; margin-bottom: 5px;">
|
| 688 |
+
<span id="elasticity-min">-30%</span>
|
| 689 |
+
<span>0%</span>
|
| 690 |
+
<span id="elasticity-max">+40%</span>
|
| 691 |
+
</div>
|
| 692 |
+
<div class="elasticity-track" style="position: relative; height: 20px; background: linear-gradient(to right, #ff4757 0%, #ff4757 40%, #888 40%, #888 45%, #00ff88 45%, #00ff88 100%); border-radius: 10px; overflow: hidden;">
|
| 693 |
+
<!-- μμΈ‘ λ²μ νμ -->
|
| 694 |
+
<div id="elasticity-range" style="position: absolute; height: 100%; background: rgba(0,217,255,0.4); border: 2px solid #00d9ff; border-radius: 8px;"></div>
|
| 695 |
+
<!-- κΈ°λ³Έ μμΈ‘μΉ λ§μ»€ -->
|
| 696 |
+
<div id="elasticity-marker" style="position: absolute; top: -8px; width: 4px; height: 36px; background: #fff; border-radius: 2px; box-shadow: 0 0 10px rgba(255,255,255,0.8);"></div>
|
| 697 |
+
</div>
|
| 698 |
+
</div>
|
| 699 |
+
|
| 700 |
+
<!-- μμΉ νμ - νλ₯ κ°μ‘° -->
|
| 701 |
+
<div style="display: flex; justify-content: space-between; gap: 15px; margin-top: 20px;">
|
| 702 |
+
<div style="flex: 1; text-align: center; padding: 15px; background: rgba(255,71,87,0.15); border-radius: 10px; border: 1px solid rgba(255,71,87,0.3);">
|
| 703 |
+
<div style="font-size: 12px; color: #ff6b7a; margin-bottom: 5px;">π νλ½ λ¦¬μ€ν¬</div>
|
| 704 |
+
<div id="result-downside" style="font-size: 22px; font-weight: bold; color: #ff4757;">-</div>
|
| 705 |
+
<div style="font-size: 11px; color: #888; margin-top: 3px;"><span id="result-down-prob">-</span> νλ₯ </div>
|
| 706 |
+
</div>
|
| 707 |
+
<div style="flex: 1; text-align: center; padding: 15px; background: rgba(0,217,255,0.15); border-radius: 10px; border: 1px solid rgba(0,217,255,0.3);">
|
| 708 |
+
<div style="font-size: 12px; color: #00d9ff; margin-bottom: 5px;">π― κΈ°λ μμ΅</div>
|
| 709 |
+
<div id="result-prediction" style="font-size: 24px; font-weight: bold; color: #00d9ff;">-</div>
|
| 710 |
+
<div style="font-size: 11px; color: #888; margin-top: 3px;">R/R <span id="result-rr">-</span></div>
|
| 711 |
+
</div>
|
| 712 |
+
<div style="flex: 1; text-align: center; padding: 15px; background: rgba(0,255,136,0.15); border-radius: 10px; border: 1px solid rgba(0,255,136,0.3);">
|
| 713 |
+
<div style="font-size: 12px; color: #00ff88; margin-bottom: 5px;">π μμΉ μ μ¬λ ₯</div>
|
| 714 |
+
<div id="result-upside" style="font-size: 22px; font-weight: bold; color: #00ff88;">-</div>
|
| 715 |
+
<div style="font-size: 11px; color: #888; margin-top: 3px;"><span id="result-up-prob">-</span> νλ₯ </div>
|
| 716 |
+
</div>
|
| 717 |
+
</div>
|
| 718 |
+
|
| 719 |
+
<div style="text-align: center; margin-top: 12px; font-size: 11px; color: #666;">
|
| 720 |
+
β» AI κΈ°λ° λΆμμ΄λ©° μ€μ ν¬μ μμ΅μ 보μ₯νμ§ μμ΅λλ€
|
| 721 |
+
</div>
|
| 722 |
+
</div>
|
| 723 |
+
|
| 724 |
<div class="deep-section" style="background: rgba(0,217,255,0.1); border: 1px solid rgba(0,217,255,0.3);"><h3>π ν΅μ¬ μμ½</h3><div class="content" id="result-executive-summary"></div></div>
|
| 725 |
<div class="deep-section"><h3>π’ νμ¬ κ°μ</h3><div class="content" id="result-company-overview"></div></div>
|
| 726 |
<div class="deep-section"><h3>π° μ¬λ¬΄ λΆμ</h3><div class="content" id="result-financial-analysis"></div></div>
|
|
|
|
| 1450 |
return text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>').replace(/\n/g, '<br>');
|
| 1451 |
}
|
| 1452 |
|
| 1453 |
+
function updateElasticityUI(report) {
|
| 1454 |
+
// νλ ₯μ± λ°μ΄ν° μΆμΆ (κΈ°λ³Έκ° μ€μ )
|
| 1455 |
+
const upside = report.expected_upside || 15;
|
| 1456 |
+
const downside = report.expected_downside || -10;
|
| 1457 |
+
const prediction = report.base_prediction || report.upside || 8;
|
| 1458 |
+
const upProb = report.up_probability || 55;
|
| 1459 |
+
const downProb = report.down_probability || 45;
|
| 1460 |
+
const riskReward = report.risk_reward || 1.5;
|
| 1461 |
+
|
| 1462 |
+
// μμΉ νμ
|
| 1463 |
+
document.getElementById('result-upside').textContent = `+${upside}%`;
|
| 1464 |
+
document.getElementById('result-downside').textContent = `${downside}%`;
|
| 1465 |
+
document.getElementById('result-prediction').textContent = prediction >= 0 ? `+${prediction}%` : `${prediction}%`;
|
| 1466 |
+
document.getElementById('result-prediction').style.color = prediction >= 0 ? '#00d9ff' : '#ff4757';
|
| 1467 |
+
document.getElementById('result-up-prob').textContent = `${upProb}%`;
|
| 1468 |
+
document.getElementById('result-down-prob').textContent = `${downProb}%`;
|
| 1469 |
+
document.getElementById('result-rr').textContent = `${riskReward}:1`;
|
| 1470 |
+
|
| 1471 |
+
// μκ°μ λ° μ
λ°μ΄νΈ
|
| 1472 |
+
const minVal = Math.min(downside, -30);
|
| 1473 |
+
const maxVal = Math.max(upside, 40);
|
| 1474 |
+
const range = maxVal - minVal;
|
| 1475 |
+
|
| 1476 |
+
// μ€μΌμΌ λΌλ²¨ μ
λ°μ΄νΈ
|
| 1477 |
+
document.getElementById('elasticity-min').textContent = `${Math.round(minVal)}%`;
|
| 1478 |
+
document.getElementById('elasticity-max').textContent = `+${Math.round(maxVal)}%`;
|
| 1479 |
+
|
| 1480 |
+
// λ²μ λ° μμΉ κ³μ° (downside ~ upside)
|
| 1481 |
+
const rangeLeft = ((downside - minVal) / range) * 100;
|
| 1482 |
+
const rangeRight = ((upside - minVal) / range) * 100;
|
| 1483 |
+
const rangeEl = document.getElementById('elasticity-range');
|
| 1484 |
+
rangeEl.style.left = `${rangeLeft}%`;
|
| 1485 |
+
rangeEl.style.width = `${rangeRight - rangeLeft}%`;
|
| 1486 |
+
|
| 1487 |
+
// κΈ°λ³Έ μμΈ‘ λ§μ»€ μμΉ
|
| 1488 |
+
const markerPos = ((prediction - minVal) / range) * 100;
|
| 1489 |
+
const markerEl = document.getElementById('elasticity-marker');
|
| 1490 |
+
markerEl.style.left = `calc(${markerPos}% - 2px)`;
|
| 1491 |
+
}
|
| 1492 |
+
|
| 1493 |
function initAnalysisCharts(report) {
|
| 1494 |
[metricsChartInstance, priceChartInstance, riskChartInstance, growthChartInstance].forEach(c => c && c.destroy());
|
| 1495 |
const cp = report.current_price || 100, tp = report.target_price || 112;
|
|
|
|
| 1595 |
document.getElementById('result-current-price').textContent = report.current_price ? `$${report.current_price.toLocaleString()}` : '-';
|
| 1596 |
document.getElementById('result-target-price').textContent = report.target_price ? `$${report.target_price.toLocaleString()}` : '-';
|
| 1597 |
document.getElementById('result-rating').textContent = report.rating || 'Buy';
|
| 1598 |
+
|
| 1599 |
+
// νλ ₯μ± μμΈ‘ UI μ
λ°μ΄νΈ
|
| 1600 |
+
updateElasticityUI(report);
|
| 1601 |
|
| 1602 |
setTimeout(() => initAnalysisCharts(report), 100);
|
| 1603 |
|
|
|
|
| 1695 |
<div class="metric-label">ν¬μμ견</div>
|
| 1696 |
<div class="metric-value">${document.getElementById('result-rating')?.textContent || '-'}</div>
|
| 1697 |
</div>
|
| 1698 |
+
</div>
|
| 1699 |
+
|
| 1700 |
+
<div class="section" style="background: #f0f8ff; border-left-color: #0099cc;">
|
| 1701 |
+
<div class="section-title">π μμ΅λ₯ μ λ§</div>
|
| 1702 |
+
<div style="display: flex; justify-content: space-around; text-align: center; margin: 15px 0;">
|
| 1703 |
+
<div>
|
| 1704 |
+
<div style="color: #cc0000; font-size: 12px;">π νλ½ λ¦¬μ€ν¬</div>
|
| 1705 |
+
<div style="font-size: 20px; font-weight: bold; color: #cc0000;">${document.getElementById('result-downside')?.textContent || '-'}</div>
|
| 1706 |
+
<div style="font-size: 11px; color: #666;">${document.getElementById('result-down-prob')?.textContent || '-'} νλ₯ </div>
|
| 1707 |
+
</div>
|
| 1708 |
+
<div>
|
| 1709 |
+
<div style="color: #0066cc; font-size: 12px;">π― κΈ°λ μμ΅</div>
|
| 1710 |
+
<div style="font-size: 24px; font-weight: bold; color: #0066cc;">${document.getElementById('result-prediction')?.textContent || '-'}</div>
|
| 1711 |
+
<div style="font-size: 11px; color: #666;">R/R ${document.getElementById('result-rr')?.textContent || '-'}</div>
|
| 1712 |
+
</div>
|
| 1713 |
+
<div>
|
| 1714 |
+
<div style="color: #009966; font-size: 12px;">π μμΉ μ μ¬λ ₯</div>
|
| 1715 |
+
<div style="font-size: 20px; font-weight: bold; color: #009966;">${document.getElementById('result-upside')?.textContent || '-'}</div>
|
| 1716 |
+
<div style="font-size: 11px; color: #666;">${document.getElementById('result-up-prob')?.textContent || '-'} νλ₯ </div>
|
| 1717 |
+
</div>
|
| 1718 |
</div>
|
| 1719 |
+
<div style="text-align: center; font-size: 10px; color: #999;">β» AI κΈ°λ° λΆμμ΄λ©° μ€μ ν¬μ μμ΅μ 보μ₯νμ§ οΏ½οΏ½μ΅λλ€</div>
|
| 1720 |
</div>
|
| 1721 |
|
| 1722 |
<div class="section">
|