iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
1
AI & Data

D3.js資料視覺化的浪漫突進系列 第 23

Day23 D3js Candlestick Chart來張K線圖吧!

  • 分享至 

  • xImage
  •  

D3js Candlestick Chart來張K線圖吧!

用途

市面上有更多關於股票的K線圖,但有時候特殊情況下仍然需要自己高度客製化,就需要自己來動手嚕一張了。

基本分析

圖上元件

根據圖上需要的部分,分成以下幾個部分。

  • Axis比例尺
  • 箱型圖(線, 方形)
  • 對應的紅綠顏色

資料識別

根據基本K線圖需要的資料,為以下幾種資料源。

  • 時間
  • 開盤價
  • 收盤價
  • 最高價
  • 最低價

箱型為開盤價格以及收盤價格,如果收盤比開盤開,代表紅色(漲),反之則為綠(跌)。

簡易範例

準備基本部分範例:


const datas = d3.csvParse(dataCSV);
const width = 1200;
const height = 800;
const padding = 50;
const innerWidth = width - padding * 2;
const innerHeight = height - padding * 2;

// g
const svg = d3.select('svg').attr('width', width).attr('height', height);
const rootLayer = svg.append('g').attr('transform', `translate(${padding}, ${padding})`);
const axisLayer = rootLayer.append('g');
const xAxisLayer = axisLayer.append('g').attr('transform', `translate(${0}, ${innerHeight})`);
const yAxisLayer = axisLayer.append('g');
const lineLayer = rootLayer.append('g');
const rectLayer = rootLayer.append('g');
// ["Date", "Open", "High", "Low", "Close", "Adj Close", "Volume"]

// inital
let xExtent;
let yExtent;

let xScale;
let yScale;

let xAxis;
let yAxis;

let lines;
let rects;

dataCSV為股價的資料,將會轉為datas轉成json

剩下為準備塗層,以及宣告基本變數。

計算以及渲染範例


// 抓出X最大日期及最小日期以及Y軸最大值及最小值。
const calcExtent = () => {
  xExtent = [d3.min(datas, data => new Date(data.Date)), d3.max(datas, data => new Date(data.Date))];
  yExtent = [d3.min(datas, data => data.Low), d3.max(datas, data => data.High)];
}

// 計算`Scale`算出比例,透過`nice`可以讓我們的`yScale`上下預留一點空。
const calcScale = () => {
  xScale = d3.scaleTime().domain(xExtent).range([0, innerWidth]);
  yScale = d3.scaleLinear().domain(yExtent).range([innerHeight, 0]).nice();
}

// 繪製Axis比例尺。
const paintAxis = () => {
  xAxis = d3.axisBottom().scale(xScale);
  yAxis = d3.axisLeft().scale(yScale);
  
  yAxisLayer.call(yAxis);
  xAxisLayer.call(xAxis);
}

// 繪製K線圖的線
const paintLines = () => {
  lines = lineLayer
            .selectAll('line')
            .data(datas, data => data.Date)
            .enter()
            .append('line')
            .attr('class', 'line')
            .attr('x1', (d, i) => xScale(new Date(d.Date)))
            .attr('x2', (d, i) => xScale(new Date(d.Date)))
            .attr('y1', d => yScale(d.High))
            .attr('y2', d => yScale(d.Low))
            // 這邊要判斷開盤以及收盤漲跌
            .attr("stroke", d => (d.Open === d.Close) ? "white" : (d.Open > d.Close) ? "green" : "red");
}

// 繪製K線圖的方形
const paintRects = () => {
  rects = rectLayer
            .selectAll('rect')
            .data(datas, data => data.Date)
            .enter()
            .append('rect')
            .attr('class', 'rect')
            .attr('x', d => xScale(new Date(d.Date)) - 2)
            // 這邊要注意是取得開盤收盤之間最大值,因為目前上方y值為大,所以是取Open, Close之間最大值,來當作方塊的y。
            .attr('y', d => yScale(Math.max(d.Open, d.Close)))
            .attr('width', 5)
            .attr('height', d => Math.abs(yScale(d.Open) - yScale(d.Close)))
            .attr('fill', d => (d.Open > d.Close) ? 'green': 'red')
}
calcExtent();
calcScale();
paintAxis();
paintLines();
paintRects();

結論

輕鬆可以嚕出一個K線圖,還可以搭配d3.tip或是d3.zoom做到更多功能的K線圖。但還是傾向套用現成圖表比較安全。

Codepen範例

參考

Zoomable candlestick chart


上一篇
Day22 D3js d3與canvas
下一篇
Day24 D3js Gantt Chart 來張甘特圖吧!
系列文
D3.js資料視覺化的浪漫突進30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言