- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- API
- 채팅
- 비전공자
- 차트구현
- typeorm
- 주식
- 에러
- 차트만들기
- apollo
- react
- nextjs
- 차트
- Coin
- javascript
- chart
- nestjs
- 3주차
- 항해99
- 코인
- Firebase
- rtk
- 리액트
- Redux
- 주식차트
- websocket
- 코인차트
- Flutter
- error
- graphql
- typescript
Act99 기술블로그
[React] 직접 주가 캔들 차트 만들기5 (이동평균선 추가) (SVG 연습용) 본문
저번 글에서 봤듯이 차트를 확대할 때, 과거 데이터를 가져오는 문제가 있었다.
https://bugerstory.tistory.com/35
이 문제를 수정하기 위해 slice를 사용했다.
const [dataLength, setDataLength] = useState(24);
const stockData = data?.gsStock.map((item) => item);
const stockDummyArray: any[] = [];
stockData?.forEach((item) => stockDummyArray.push(item));
const stockArray: any[] = [];
console.log(dataLength);
stockData
?.slice(dataLength, stockDummyArray.length)
.forEach((item) => stockArray.push(item));
console.log(stockArray[0]);
const dataWheelHandler = () => {
window.onwheel = function (e) {
e.deltaY > 0
? setDataLength(dataLength < 18 ? dataLength + 0 : dataLength - 8)
: setDataLength(
dataLength > stockDummyArray?.length - 18
? dataLength + 0
: dataLength + 8
);
};
};
stockData?.slice(dataLength, stockDummyArray.length) 를 통해
dataLength 부터 전체 데이터까지의 데이터를 가져왔다.
다음은 캔들차트 수정이다.
고가, 저가 축의 x좌표를 변경시켜주었다.
<line
x1={x + (barPlothWidth - sidePadding) / 2}
x2={x + (barPlothWidth - sidePadding) / 2}
y1={yAxisLength - scaleY(low)}
y2={yAxisLength - scaleY(high)}
stroke={open > close ? "red" : "green"}
/>
<rect
{...{ fill }}
x={x}
width={barPlothWidth - sidePadding}
y={yAxisLength - scaleY(max)}
// 시가 종가 최대 최소값의 차
height={scaleY(max) - scaleY(min)}
></rect>
시가 종가 차트의 너비의 평균값을 x좌표로 잡아주었다.
그 결과
잘 작동했다.
다음으로는 거래량 차트이다.
거래량 차트는 매도가 많을 때, 빨간색, 매수가 많을 때 초록색으로 구현해야 한다.
하지만 내가 가져온 데이터는 매도, 매수량이 없다. (아쉽게도 ㅠㅠ)
따라서 데이터의 한계로 주가가 오를 때 매수가 많으며 주가가 떨어질 때 매도수량이 많은 것으로 측정했다.
**보통 주가는 고가와 종가 차이가 클때 매도수량이 높지만(경험상) 이 역시 정확하지 않기 때문에
주가가 오를 때 매수수량이 많고 주가가 떨어질 때 매도수량이 많은 것으로 측정했다.**
const fill = close > open ? "#4AFA9A" : "#E33F64";
return (
<g key={index}>
<rect
{...{ fill }}
x={x}
y={y}
width={barPlotWidth - sidePadding}
height={height}
></rect>
</g>
여기서 한 가지 문제점을 더 발견했는데,
날짜 데이터가 정확하게 따라오지 않는다는 것이었다.
이 문제는 모든 차트들을 구현한 후, 손을 볼 예정이다.
다음은 이동평균선을 만들어 줄 것이다.
먼저 이동평균선 데이터를 가져와준다.
const stockClo5 = stockArray.map((item) => item.clo5);
const clo5Array: number[] = [];
stockClo5?.forEach((clo5) => clo5Array.push(clo5));
const stockClo20 = stockArray.map((item) => item.clo20);
const clo20Array: number[] = [];
stockClo20?.forEach((clo20) => clo20Array.push(clo20));
const stockClo60 = stockArray.map((item) => item.clo60);
const clo60Array: number[] = [];
stockClo60?.forEach((clo60) => clo60Array.push(clo60));
다음 CandleChart 의 dataArray 에 추가시켜준다.
const clo5Array: [number, number][] = [];
const clo20Array: [number, number][] = [];
const clo60Array: [number, number][] = [];
const dataArray: [
string,
number,
number,
number,
number,
number[],
number[],
number[]
][] = [];
for (let i = 0; i < date.length; i++) {
clo5Array.push([clo5[i], clo5[i + 1] == undefined ? clo5[i] : clo5[i + 1]]);
clo20Array.push([
clo20[i],
clo20[i + 1] == undefined ? clo20[i] : clo20[i + 1],
]);
clo60Array.push([
clo60[i],
clo60[i + 1] == undefined ? clo60[i] : clo60[i + 1],
]);
dataArray.push([
date[i],
open[i],
close[i],
high[i],
low[i],
clo5Array[i],
clo20Array[i],
clo60Array[i],
]);
}
undefined 이 필요한 이유는 마지막 i+1 번째는 무조건 undefined이 나오기 때문이다. (데이터가 없기 때문)
그리고 svg에 그려준다.
여기서 중요한건, 이동평균선은 전날과 현재 데이터가 일치할 수 없기 때문에 이를 이용해서 전에 undefined일 때 전날과 현재데이터를 같게 하라는 코드를 빼주어야 한다.
코드는 이렇다.
{clo5[0] > dataYMin && clo5[0] != clo5[1] ? (
<line
stroke="green"
x1={x + (barPlothWidth - sidePadding) / 2}
x2={xX + (barPlothWidth - sidePadding) / 2}
y1={yAxisLength - scaleY(clo5[0])}
y2={yAxisLength - scaleY(clo5[1])}
/>
) : null}
{clo20[0] > dataYMin && clo20[0] != clo20[1] ? (
<line
stroke="red"
x1={x + (barPlothWidth - sidePadding) / 2}
x2={xX + (barPlothWidth - sidePadding) / 2}
y1={yAxisLength - scaleY(clo20[0])}
y2={yAxisLength - scaleY(clo20[1])}
/>
) : null}
{clo60[0] > dataYMin && clo60[0] != clo60[1] ? (
<line
stroke="gold"
x1={x + (barPlothWidth - sidePadding) / 2}
x2={xX + (barPlothWidth - sidePadding) / 2}
y1={yAxisLength - scaleY(clo60[0])}
y2={yAxisLength - scaleY(clo60[1])}
/>
) : null}
결과는..
이동평균선이 잘 만들어진 것을 확인할 수 있다.
앞으로 할 일은 볼린저 밴더 형성, 틱 정보 얻기이다.
https://github.com/act99/stock-frontend
'개발팁저장소 > react' 카테고리의 다른 글
[React] 직접 주가 캔들 차트 만들기 - 코드정리1 (SVG 연습용), (차트라이브러리 x) (0) | 2021.12.02 |
---|---|
[React] 직접 주가 캔들 차트 만들기6 - 볼린저 밴드 만들기 (SVG 연습용), (차트라이브러리 x) (0) | 2021.12.01 |
[React] 직접 주가 캔들 차트 & 거래량 바 차트 만들기4 - onWheel 을 통해 데이터값을 추가시키거나 감소시키기 (라이브러리 x) (SVG 연습용) (0) | 2021.12.01 |
[React] 직접 주가 캔들 차트 & 거래량 바 차트 만들기3 (라이브러리 x) (SVG 연습용) (0) | 2021.11.30 |
[React] 직접 주가 캔들 차트 & 거래량 바 차트 만들기2 (라이브러리 x) (SVG 연습용) (1) | 2021.11.29 |