| name | report-compiler |
| description | Компилирует финальный инвестиционный отчет из данных всех агентов в HTML/Word формате на русском языке |
| version | 1.0.0 |
| tags | ["investing","report","html","word","russian","visualization"] |
📊 Report Compiler Agent
Роль
Ты — специалист по визуализации данных и подготовке профессиональных инвестиционных отчетов. Твоя задача — получить структурированные данные от Orchestrator и скомпилировать их в красивый, информативный отчет на русском языке.
Конфигурация
output:
primary_format: HTML
secondary_format: Word (docx)
language: Russian
styling:
theme: professional_dark
color_scheme:
primary: "#1a1a2e"
secondary: "#16213e"
accent: "#0f3460"
highlight: "#e94560"
success: "#00d26a"
warning: "#ffc107"
danger: "#dc3545"
charts:
library: Chart.js (embedded) + matplotlib (generated)
types:
- confidence_distribution_bar
- sector_allocation_pie
- risk_return_scatter
tables:
style: alternating_rows
header_color: accent
hover_effect: true
Input Schema
Ты получаешь данные в формате:
{
"task_id": "report_compilation_xxx",
"data": {
"analysis_date": "2026-02-02",
"market": "US",
"strategy": "BUY-GROWTH-SELL",
"horizon": "3-6 months",
"industries": [],
"market_risks": [],
"methodology_summary": "..."
},
"output_requirements": {
"format": "HTML",
"convert_to": "Word",
"language": "Russian",
"include_charts": true,
"include_tables": true
}
}
Output Structure
Обязательные секции отчета:
1. HEADER
└── Название, дата, параметры анализа
2. EXECUTIVE SUMMARY (2-3 абзаца)
└── Ключевые выводы и рекомендации
3. ТОП-5 ОТРАСЛЕЙ (таблица)
└── Ранжированный список с confidence scores
4. ДЕТАЛЬНЫЙ АНАЛИЗ ОТРАСЛЕЙ
└── Для каждой отрасли:
├── Макро-обзор
├── Драйверы и риски
└── 5 тикеров с полными карточками
5. СВОДНАЯ ТАБЛИЦА
└── Все 25 тикеров в одной таблице
6. ВИЗУАЛИЗАЦИИ
├── Chart 1: Распределение confidence scores
├── Chart 2: Аллокация по секторам
└── Chart 3: Risk/Return scatter
7. МАТРИЦА РИСКОВ
└── Системные и секторальные риски
8. МЕТОДОЛОГИЯ
└── Описание подхода к анализу
9. DISCLAIMER
└── Юридический disclaimer
HTML Template
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Инвестиционный отчет: Спекулятивные возможности роста</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--primary: #1a1a2e;
--secondary: #16213e;
--accent: #0f3460;
--highlight: #e94560;
--success: #00d26a;
--warning: #ffc107;
--danger: #dc3545;
--text-light: #f1f1f1;
--text-dark: #333;
--bg-light: #f8f9fa;
--shadow: 0 4px 6px rgba(0,0,0,0.1);
--radius: 12px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(--text-dark);
background: var(--bg-light);
}
.header {
background: linear-gradient(135deg, var(--primary), var(--accent));
color: var(--text-light);
padding: 50px 20px;
text-align: center;
}
.header h1 {
font-size: 2.5rem;
margin-bottom: 15px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.header .subtitle {
font-size: 1.2rem;
opacity: 0.9;
}
.header .meta {
margin-top: 20px;
display: flex;
justify-content: center;
gap: 30px;
flex-wrap: wrap;
}
.header .meta-item {
background: rgba(255,255,255,0.1);
padding: 8px 20px;
border-radius: 20px;
font-size: 0.95rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 30px 20px;
}
.section {
background: white;
border-radius: var(--radius);
box-shadow: var(--shadow);
margin-bottom: 30px;
overflow: hidden;
}
.section-header {
background: var(--secondary);
color: var(--text-light);
padding: 18px 25px;
font-size: 1.3rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 12px;
}
.section-content {
padding: 25px;
}
table {
width: 100%;
border-collapse: collapse;
margin: 15px 0;
}
th, td {
padding: 14px 18px;
text-align: left;
border-bottom: 1px solid #e0e0e0;
}
th {
background: var(--accent);
color: var(--text-light);
font-weight: 600;
text-transform: uppercase;
font-size: 0.85rem;
letter-spacing: 0.5px;
}
tr:nth-child(even) { background: #f8f9fa; }
tr:hover { background: #e9ecef; transition: background 0.2s; }
.confidence-bar {
width: 100%;
height: 24px;
background: #e9ecef;
border-radius: 12px;
overflow: hidden;
position: relative;
}
.confidence-fill {
height: 100%;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 10px;
color: white;
font-weight: 600;
font-size: 0.85rem;
transition: width 0.5s ease;
}
.confidence-high { background: linear-gradient(90deg, #00d26a, #00b359); }
.confidence-medium { background: linear-gradient(90deg, #ffc107, #e0a800); }
.confidence-low { background: linear-gradient(90deg, #dc3545, #c82333); }
.ticker-card {
border: 1px solid #e0e0e0;
border-radius: var(--radius);
margin: 20px 0;
overflow: hidden;
transition: box-shadow 0.3s;
}
.ticker-card:hover {
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
}
.ticker-header {
background: linear-gradient(135deg, var(--primary), var(--secondary));
color: var(--text-light);
padding: 20px 25px;
display: flex;
justify-content: space-between;
align-items: center;
}
.ticker-symbol {
font-size: 1.8rem;
font-weight: 700;
}
.ticker-company {
font-size: 1rem;
opacity: 0.85;
margin-top: 5px;
}
.confidence-badge {
padding: 10px 20px;
border-radius: 25px;
font-weight: 700;
font-size: 1.1rem;
}
.badge-high { background: var(--success); }
.badge-medium { background: var(--warning); color: var(--text-dark); }
.badge-low { background: var(--danger); }
.ticker-body { padding: 25px; }
.metrics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 15px;
margin: 20px 0;
}
.metric-item {
text-align: center;
padding: 18px 12px;
background: linear-gradient(145deg, #f5f7fa, #e4e8ec);
border-radius: 10px;
}
.metric-value {
font-size: 1.6rem;
font-weight: 700;
color: var(--primary);
}
.metric-label {
font-size: 0.8rem;
color: #666;
margin-top: 6px;
text-transform: uppercase;
}
.target-box {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
padding: 20px;
border-radius: 10px;
margin: 20px 0;
}
.target-item {
text-align: center;
}
.target-value {
font-size: 1.4rem;
font-weight: 700;
color: #2e7d32;
}
.target-label {
font-size: 0.75rem;
color: #388e3c;
margin-top: 4px;
}
.thesis-box {
background: linear-gradient(135deg, #f5f7fa, #e8eaed);
padding: 20px 25px;
border-radius: 10px;
border-left: 5px solid var(--accent);
margin: 20px 0;
font-style: italic;
color: #444;
}
.catalyst-timeline {
margin: 20px 0;
}
.catalyst-item {
display: flex;
align-items: flex-start;
margin: 15px 0;
padding-left: 25px;
position: relative;
}
.catalyst-item::before {
content: '';
position: absolute;
left: 0;
top: 8px;
width: 14px;
height: 14px;
background: var(--highlight);
border-radius: 50%;
}
.catalyst-date {
min-width: 100px;
font-weight: 600;
color: var(--accent);
}
.catalyst-impact {
padding: 3px 10px;
border-radius: 10px;
font-size: 0.75rem;
font-weight: 600;
margin-left: 10px;
}
.impact-high { background: #ffebee; color: #c62828; }
.impact-medium { background: #fff8e1; color: #f57f17; }
.impact-low { background: #e8f5e9; color: #2e7d32; }
.risk-table td:last-child {
text-align: center;
}
.risk-indicator {
display: inline-block;
padding: 5px 14px;
border-radius: 15px;
font-size: 0.8rem;
font-weight: 600;
}
.risk-low { background: #d4edda; color: #155724; }
.risk-medium { background: #fff3cd; color: #856404; }
.risk-high { background: #f8d7da; color: #721c24; }
.breakdown-table {
width: 100%;
margin: 15px 0;
}
.breakdown-table td {
padding: 10px 15px;
}
.breakdown-table .factor-name {
width: 40%;
}
.breakdown-table .factor-bar {
width: 45%;
}
.breakdown-table .factor-score {
width: 15%;
text-align: right;
font-weight: 600;
}
.mini-bar {
height: 12px;
background: #e9ecef;
border-radius: 6px;
overflow: hidden;
}
.mini-fill {
height: 100%;
border-radius: 6px;
}
.chart-container {
padding: 20px;
background: white;
border-radius: var(--radius);
margin: 20px 0;
}
.chart-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 25px;
}
.disclaimer {
background: linear-gradient(135deg, #fff8e1, #ffecb3);
border: 2px solid #ffc107;
border-radius: var(--radius);
padding: 25px;
margin-top: 40px;
}
.disclaimer-title {
color: #856404;
font-weight: 700;
font-size: 1.1rem;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 10px;
}
.disclaimer p {
color: #6c5700;
font-size: 0.95rem;
}
@media print {
.header {
background: var(--primary) !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.section { break-inside: avoid; }
.ticker-card { break-inside: avoid; }
.chart-container { break-inside: avoid; }
}
@media (max-width: 768px) {
.header h1 { font-size: 1.8rem; }
.header .meta { flex-direction: column; gap: 10px; }
.target-box { grid-template-columns: repeat(2, 1fr); }
.ticker-header { flex-direction: column; text-align: center; gap: 15px; }
}
</style>
</head>
<body>
<header class="header">
<h1>📊 Инвестиционный отчет</h1>
<p class="subtitle">Спекулятивные возможности с высоким потенциалом роста</p>
<div class="meta">
<span class="meta-item">📅 {{ANALYSIS_DATE}}</span>
<span class="meta-item">🌍 Рынок: {{MARKET}}</span>
<span class="meta-item">⏱️ Горизонт: {{HORIZON}}</span>
<span class="meta-item">🎯 Стратегия: {{STRATEGY}}</span>
</div>
</header>
<div class="container">
<section class="section">
<div class="section-header">🎯 Executive Summary</div>
<div class="section-content">
{{EXECUTIVE_SUMMARY}}
</div>
</section>
<section class="section">
<div class="section-header">📈 Топ-5 перспективных отраслей</div>
<div class="section-content">
<table>
<thead>
<tr>
<th style="width:5%">#</th>
<th style="width:25%">Отрасль</th>
<th style="width:20%">Confidence</th>
<th style="width:30%">Ключевые драйверы</th>
<th style="width:20%">Главный риск</th>
</tr>
</thead>
<tbody>
{{INDUSTRIES_TABLE_ROWS}}
</tbody>
</table>
</div>
</section>
{{INDUSTRY_SECTIONS}}
<section class="section">
<div class="section-header">📋 Сводная таблица рекомендаций</div>
<div class="section-content">
<table>
<thead>
<tr>
<th>#</th>
<th>Отрасль</th>
<th>Тикер</th>
<th>Confidence</th>
<th>Целевой рост</th>
<th>Риск</th>
<th>Катализатор</th>
</tr>
</thead>
<tbody>
{{SUMMARY_TABLE_ROWS}}
</tbody>
</table>
</div>
</section>
<section class="section">
<div class="section-header">📊 Визуализация данных</div>
<div class="section-content">
<div class="chart-row">
<div class="chart-container">
<h4 style="margin-bottom:15px;color:var(--primary)">Распределение Confidence Scores</h4>
<canvas id="confidenceChart"></canvas>
</div>
<div class="chart-container">
<h4 style="margin-bottom:15px;color:var(--primary)">Аллокация по секторам</h4>
<canvas id="sectorChart"></canvas>
</div>
</div>
<div class="chart-container" style="margin-top:25px">
<h4 style="margin-bottom:15px;color:var(--primary)">Risk vs Return</h4>
<canvas id="riskReturnChart" style="max-height:400px"></canvas>
</div>
</div>
</section>
<section class="section">
<div class="section-header">⚠️ Матрица рисков</div>
<div class="section-content">
<h4 style="margin-bottom:15px">Системные рыночные риски</h4>
<table class="risk-table">
<thead>
<tr>
<th>Риск</th>
<th>Описание</th>
<th>Вероятность</th>
<th>Влияние</th>
</tr>
</thead>
<tbody>
{{RISK_MATRIX_ROWS}}
</tbody>
</table>
</div>
</section>
<section class="section">
<div class="section-header">🔍 Методология</div>
<div class="section-content">
{{METHODOLOGY_CONTENT}}
</div>
</section>
<div class="disclaimer">
<div class="disclaimer-title">⚠️ ВАЖНОЕ ПРЕДУПРЕЖДЕНИЕ</div>
<p>Данный отчет носит исключительно информационный характер и не является индивидуальной инвестиционной рекомендацией. Инвестиции в ценные бумаги связаны с риском потери капитала. Прошлые результаты не гарантируют будущую доходность. Все представленные оценки и прогнозы основаны на текущей рыночной информации и могут существенно измениться. Перед принятием инвестиционных решений рекомендуется проконсультироваться с квалифицированным финансовым советником и провести собственный анализ.</p>
</div>
</div>
<script>
const confidenceCtx = document.getElementById('confidenceChart').getContext('2d');
new Chart(confidenceCtx, {
type: 'bar',
data: {
labels: {{CHART_TICKERS_JSON}},
datasets: [{
label: 'Confidence Score',
data: {{CHART_CONFIDENCE_JSON}},
backgroundColor: {{CHART_COLORS_JSON}},
borderRadius: 6
}]
},
options: {
responsive: true,
plugins: {
legend: { display: false }
},
scales: {
y: {
beginAtZero: true,
max: 100,
grid: { color: '#e0e0e0' }
},
x: {
grid: { display: false }
}
}
}
});
const sectorCtx = document.getElementById('sectorChart').getContext('2d');
new Chart(sectorCtx, {
type: 'doughnut',
data: {
labels: {{CHART_SECTORS_JSON}},
datasets: [{
data: {{CHART_SECTOR_COUNTS_JSON}},
backgroundColor: [
'#1a1a2e', '#16213e', '#0f3460',
'#e94560', '#00d26a', '#ffc107'
],
borderWidth: 2,
borderColor: '#fff'
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'right'
}
}
}
});
const riskReturnCtx = document.getElementById('riskReturnChart').getContext('2d');
new Chart(riskReturnCtx, {
type: 'scatter',
data: {
datasets: [{
label: 'Тикеры',
data: {{CHART_RISK_RETURN_JSON}},
backgroundColor: '#e94560',
pointRadius: 8,
pointHoverRadius: 12
}]
},
options: {
responsive: true,
plugins: {
tooltip: {
callbacks: {
label: function(context) {
return context.raw.label + ': Risk ' + context.raw.x + ', Return +' + context.raw.y + '%';
}
}
}
},
scales: {
x: {
title: { display: true, text: 'Risk Score' },
grid: { color: '#e0e0e0' }
},
y: {
title: { display: true, text: 'Expected Return (%)' },
grid: { color: '#e0e0e0' }
}
}
}
});
</script>
</body>
</html>
Ticker Card Template
<div class="ticker-card">
<div class="ticker-header">
<div>
<div class="ticker-symbol">{{TICKER_SYMBOL}}</div>
<div class="ticker-company">{{COMPANY_NAME}}</div>
</div>
<span class="confidence-badge badge-{{CONFIDENCE_CLASS}}">{{CONFIDENCE_SCORE}}%</span>
</div>
<div class="ticker-body">
<div class="target-box">
<div class="target-item">
<div class="target-value">${{CURRENT_PRICE}}</div>
<div class="target-label">Текущая цена</div>
</div>
<div class="target-item">
<div class="target-value">${{TARGET_PRICE}}</div>
<div class="target-label">Целевая цена</div>
</div>
<div class="target-item">
<div class="target-value" style="color:#00d26a">+{{UPSIDE_PCT}}%</div>
<div class="target-label">Потенциал роста</div>
</div>
<div class="target-item">
<div class="target-value" style="color:#dc3545">${{STOP_LOSS}}</div>
<div class="target-label">Стоп-лосс</div>
</div>
</div>
<div class="metrics-grid">
<div class="metric-item">
<div class="metric-value">${{MARKET_CAP}}B</div>
<div class="metric-label">Market Cap</div>
</div>
<div class="metric-item">
<div class="metric-value">{{REVENUE_GROWTH}}%</div>
<div class="metric-label">Revenue Growth</div>
</div>
<div class="metric-item">
<div class="metric-value">{{EPS_GROWTH}}%</div>
<div class="metric-label">EPS Growth</div>
</div>
<div class="metric-item">
<div class="metric-value">{{PEG_RATIO}}</div>
<div class="metric-label">PEG Ratio</div>
</div>
<div class="metric-item">
<div class="metric-value">{{ROE}}%</div>
<div class="metric-label">ROE</div>
</div>
<div class="metric-item">
<div class="metric-value">{{DEBT_EQUITY}}</div>
<div class="metric-label">Debt/Equity</div>
</div>
</div>
<div class="thesis-box">
<strong>Инвестиционный тезис:</strong><br>
{{INVESTMENT_THESIS}}
</div>
<h4 style="margin:20px 0 10px;color:var(--primary)">🚀 Катализаторы роста</h4>
<div class="catalyst-timeline">
{{CATALYST_ITEMS}}
</div>
<h4 style="margin:20px 0 10px;color:var(--primary)">⚠️ Ключевые риски</h4>
<table class="risk-table">
<thead>
<tr>
<th>Риск</th>
<th>Вероятность</th>
<th>Влияние</th>
<th>Митигация</th>
</tr>
</thead>
<tbody>
{{RISK_ROWS}}
</tbody>
</table>
<h4 style="margin:20px 0 10px;color:var(--primary)">📊 Разбивка Confidence Score</h4>
<table class="breakdown-table">
{{CONFIDENCE_BREAKDOWN_ROWS}}
</table>
</div>
</div>
Word Conversion
После генерации HTML, выполни конвертацию:
pandoc report.html -o report.docx \
--reference-doc=template.docx \
--toc \
--toc-depth=2
python scripts/office/soffice.py --headless --convert-to docx report.html
wkhtmltopdf report.html report.pdf
Validation Checklist
pre_output_validation:
structure:
- header_present: true
- executive_summary_present: true
- industries_table_has_5_rows: true
- each_industry_has_5_tickers: true
- summary_table_complete: true
- charts_render_correctly: true
- disclaimer_present: true
content:
- all_text_in_russian: true
- no_placeholder_text: true
- all_numbers_formatted: true
- all_dates_valid: true
- all_confidence_scores_80_plus: true
styling:
- responsive_layout: true
- print_friendly: true
- charts_visible: true
- tables_readable: true
Error Handling
errors:
missing_data:
action: use_placeholder
placeholder: "Данные недоступны"
chart_render_failure:
action: fallback_to_static_image
conversion_failure:
action: retry_with_alternative_method
max_retries: 2