Anonymous
Как воспроизвести этот точный пользовательский интерфейс панели оценки DCF в ECharts (составленные зоны + наложенные мет
Сообщение
Anonymous » 23 фев 2026, 12:20
Я строю диаграмму оценки в стиле DCF с помощью
ECharts 5 и хочу, чтобы диаграмма точно соответствовала прикрепленному снимку экрана с точки зрения
внешнего вида .
Я нашел SVG в статье на Уолл-стрит и пытаюсь воссоздать ту же диаграмму с помощью библиотеки диаграмм. Я уже достиг примерно 70% желаемого результата. Нет ограничений на то, какую библиотеку использовать — мы можем использовать ECharts, amCharts или любую другую библиотеку диаграмм.
Желаемый результат
Что у меня есть
В настоящее время у меня есть следующее код:
Код: Выделить всё
document.addEventListener("DOMContentLoaded", function () {
// 🔹 Data
const currentPrice = 293.19;
const fairValue = 818.37;
const maxValue = fairValue * 1.4;
// 🔹 % Calculation
const percentUndervalued =
((fairValue - currentPrice) / fairValue * 100).toFixed(1);
document.getElementById("percentText").innerText =
percentUndervalued + "% Undervalued";
const chart = echarts.init(document.getElementById('chart'));
// 🔹 Zone Sizes
const greenZone = fairValue;
const yellowZone = fairValue * 0.25;
const redZone = maxValue - greenZone - yellowZone;
const option = {
animation:false,
backgroundColor:'transparent',
grid:{ left:0, right:0, top:60, bottom:120 },
xAxis:{
type:'value',
min:0,
max:maxValue,
show:false
},
yAxis:{
type:'category',
data:[''],
show:false
},
series:[
{
type:'bar',
stack:'zones',
data:[greenZone],
barWidth:350,
itemStyle:{ color:'#178f55' }
},
{
type:'bar',
stack:'zones',
data:[yellowZone],
barWidth:350,
itemStyle:{ color:'#d49326' }
},
{
type:'bar',
stack:'zones',
data:[redZone],
barWidth:350,
itemStyle:{
color:{
type:'pattern',
image:createHatchPattern('#b71c1c','#7f0000'),
repeat:'repeat'
}
}
}
],
graphic:[
// 🔹 Thin green top line
{
type:'rect',
left:0,
top:55,
shape:{
width:(greenZone/maxValue*100)+'%',
height:4
},
style:{ fill:'#19e27c' }
},
// 🔹 Current price dashed line
{
type:'line',
shape:{
x1:currentPrice/maxValue*chart.getWidth(),
y1:80,
x2:currentPrice/maxValue*chart.getWidth(),
y2:300
},
style:{
stroke:'#ffffff',
lineWidth:2,
lineDash:[6,6]
}
},
// 🔹 Arrow
{
type:'polygon',
shape:{
points:[
[currentPrice/maxValue*chart.getWidth()-6,75],
[currentPrice/maxValue*chart.getWidth()+6,75],
[currentPrice/maxValue*chart.getWidth(),60]
]
},
style:{ fill:'#ffffff' }
},
// 🔹 Current price box
{
type:'group',
left:(currentPrice/maxValue*100)+'%',
top:'70%',
children:[
{
type:'rect',
shape:{ width:130, height:80 },
style:{
fill:'#ffffff',
shadowBlur:15,
shadowColor:'rgba(0,0,0,0.6)',
radius:6
}
},
{
type:'text',
left:15,
top:18,
style:{
text:'Current Price',
fill:'#000',
fontSize:13
}
},
{
type:'text',
left:15,
top:45,
style:{
text:'US$'+currentPrice.toFixed(2),
fill:'#000',
fontSize:20,
fontWeight:'bold'
}
}
]
},
// 🔹 Fair value box
{
type:'group',
left:(fairValue/maxValue*100)+'%',
top:'65%',
children:[
{
type:'rect',
shape:{ width:200, height:90 },
style:{
fill:'rgba(10,40,20,0.9)',
shadowBlur:20,
shadowColor:'rgba(0,0,0,0.7)',
radius:8
}
},
{
type:'text',
left:18,
top:30,
style:{
text:'Cash Flow Value',
fill:'#d1d5db',
fontSize:14
}
},
{
type:'text',
left:18,
top:52,
style:{
text:'US$'+fairValue.toFixed(2),
fill:'#ffffff',
fontSize:28,
fontWeight:'bold'
}
}
]
}
]
};
chart.setOption(option);
window.addEventListener('resize', () => {
chart.resize();
});
// 🔹 Hatch pattern generator
function createHatchPattern(color1,color2){
const size=12;
const canvas=document.createElement('canvas');
canvas.width=size;
canvas.height=size;
const ctx=canvas.getContext('2d');
ctx.fillStyle=color1;
ctx.fillRect(0,0,size,size);
ctx.strokeStyle=color2;
ctx.lineWidth=2;
ctx.beginPath();
ctx.moveTo(0,size);
ctx.lineTo(size,0);
ctx.stroke();
return canvas;
}
});
Код: Выделить всё
body {
margin:0;
padding:40px;
background:#0f1b2d;
font-family: "Segoe UI", sans-serif;
color:white;
}
.container {
max-width:900px;
margin:auto;
}
h1 {
font-size:22px;
font-weight:600;
}
.subtitle {
color:#9ca3af;
margin-top:8px;
line-height:1.4;
}
.percent {
margin-top:30px;
font-size:40px;
font-weight:800;
color:#19e27c;
}
#chart {
width:100%;
height:420px;
margin-top:40px;
}
.bottom-labels {
display:flex;
justify-content:space-between;
margin-top:20px;
font-weight:600;
}
.bottom-labels span {
transform:rotate(-30deg);
display:inline-block;
}
.green-label { color:#19e27c; }
.yellow-label { color:#facc15; }
.red-label { color:#ef4444; }
Код: Выделить всё
DCF Valuation Chart
1.1 Share Price vs Future Cash Flow Value
What is the Fair Price when looking at future cash flows?
For this estimate we use a Discounted Cash Flow model.
20% Undervalued
About Right
20% Overvalued
Подробнее здесь:
https://stackoverflow.com/questions/798 ... -zones-ove
1771838456
Anonymous
Я строю диаграмму оценки в стиле DCF с помощью [b]ECharts 5[/b] и хочу, чтобы диаграмма точно соответствовала прикрепленному снимку экрана с точки зрения [b]внешнего вида[/b]. Я нашел SVG в статье на Уолл-стрит и пытаюсь воссоздать ту же диаграмму с помощью библиотеки диаграмм. Я уже достиг примерно 70% желаемого результата. Нет ограничений на то, какую библиотеку использовать — мы можем использовать ECharts, amCharts или любую другую библиотеку диаграмм. Желаемый результат [img]https://i.sstatic.net/DddllUo4.png[/img] Что у меня есть В настоящее время у меня есть следующее код: [code]document.addEventListener("DOMContentLoaded", function () { // 🔹 Data const currentPrice = 293.19; const fairValue = 818.37; const maxValue = fairValue * 1.4; // 🔹 % Calculation const percentUndervalued = ((fairValue - currentPrice) / fairValue * 100).toFixed(1); document.getElementById("percentText").innerText = percentUndervalued + "% Undervalued"; const chart = echarts.init(document.getElementById('chart')); // 🔹 Zone Sizes const greenZone = fairValue; const yellowZone = fairValue * 0.25; const redZone = maxValue - greenZone - yellowZone; const option = { animation:false, backgroundColor:'transparent', grid:{ left:0, right:0, top:60, bottom:120 }, xAxis:{ type:'value', min:0, max:maxValue, show:false }, yAxis:{ type:'category', data:[''], show:false }, series:[ { type:'bar', stack:'zones', data:[greenZone], barWidth:350, itemStyle:{ color:'#178f55' } }, { type:'bar', stack:'zones', data:[yellowZone], barWidth:350, itemStyle:{ color:'#d49326' } }, { type:'bar', stack:'zones', data:[redZone], barWidth:350, itemStyle:{ color:{ type:'pattern', image:createHatchPattern('#b71c1c','#7f0000'), repeat:'repeat' } } } ], graphic:[ // 🔹 Thin green top line { type:'rect', left:0, top:55, shape:{ width:(greenZone/maxValue*100)+'%', height:4 }, style:{ fill:'#19e27c' } }, // 🔹 Current price dashed line { type:'line', shape:{ x1:currentPrice/maxValue*chart.getWidth(), y1:80, x2:currentPrice/maxValue*chart.getWidth(), y2:300 }, style:{ stroke:'#ffffff', lineWidth:2, lineDash:[6,6] } }, // 🔹 Arrow { type:'polygon', shape:{ points:[ [currentPrice/maxValue*chart.getWidth()-6,75], [currentPrice/maxValue*chart.getWidth()+6,75], [currentPrice/maxValue*chart.getWidth(),60] ] }, style:{ fill:'#ffffff' } }, // 🔹 Current price box { type:'group', left:(currentPrice/maxValue*100)+'%', top:'70%', children:[ { type:'rect', shape:{ width:130, height:80 }, style:{ fill:'#ffffff', shadowBlur:15, shadowColor:'rgba(0,0,0,0.6)', radius:6 } }, { type:'text', left:15, top:18, style:{ text:'Current Price', fill:'#000', fontSize:13 } }, { type:'text', left:15, top:45, style:{ text:'US$'+currentPrice.toFixed(2), fill:'#000', fontSize:20, fontWeight:'bold' } } ] }, // 🔹 Fair value box { type:'group', left:(fairValue/maxValue*100)+'%', top:'65%', children:[ { type:'rect', shape:{ width:200, height:90 }, style:{ fill:'rgba(10,40,20,0.9)', shadowBlur:20, shadowColor:'rgba(0,0,0,0.7)', radius:8 } }, { type:'text', left:18, top:30, style:{ text:'Cash Flow Value', fill:'#d1d5db', fontSize:14 } }, { type:'text', left:18, top:52, style:{ text:'US$'+fairValue.toFixed(2), fill:'#ffffff', fontSize:28, fontWeight:'bold' } } ] } ] }; chart.setOption(option); window.addEventListener('resize', () => { chart.resize(); }); // 🔹 Hatch pattern generator function createHatchPattern(color1,color2){ const size=12; const canvas=document.createElement('canvas'); canvas.width=size; canvas.height=size; const ctx=canvas.getContext('2d'); ctx.fillStyle=color1; ctx.fillRect(0,0,size,size); ctx.strokeStyle=color2; ctx.lineWidth=2; ctx.beginPath(); ctx.moveTo(0,size); ctx.lineTo(size,0); ctx.stroke(); return canvas; } });[/code] [code]body { margin:0; padding:40px; background:#0f1b2d; font-family: "Segoe UI", sans-serif; color:white; } .container { max-width:900px; margin:auto; } h1 { font-size:22px; font-weight:600; } .subtitle { color:#9ca3af; margin-top:8px; line-height:1.4; } .percent { margin-top:30px; font-size:40px; font-weight:800; color:#19e27c; } #chart { width:100%; height:420px; margin-top:40px; } .bottom-labels { display:flex; justify-content:space-between; margin-top:20px; font-weight:600; } .bottom-labels span { transform:rotate(-30deg); display:inline-block; } .green-label { color:#19e27c; } .yellow-label { color:#facc15; } .red-label { color:#ef4444; }[/code] [code] DCF Valuation Chart 1.1 Share Price vs Future Cash Flow Value What is the Fair Price when looking at future cash flows? For this estimate we use a Discounted Cash Flow model. 20% Undervalued About Right 20% Overvalued [/code] Подробнее здесь: [url]https://stackoverflow.com/questions/79894469/how-to-replicate-this-exact-dcf-valuation-bar-ui-in-echarts-stacked-zones-ove[/url]