|
1 | | -import { useCallback, useState } from 'react'; |
2 | 1 | import type { CandlestickData } from '../../types/tradeview.type'; |
3 | 2 | import ValueSeries, { type ValueSeriesProps } from './ValueSeries'; |
4 | 3 |
|
@@ -49,65 +48,64 @@ const DUMMY_DATA: CandlestickData[] = (() => { |
49 | 48 | return data; |
50 | 49 | })(); |
51 | 50 |
|
52 | | -export default function ValueSeriesWithData(props: ValueSeriesProps) { |
53 | | - const [data, setData] = useState<CandlestickData[]>(DUMMY_DATA); |
54 | | - |
55 | | - const fetchPastTimeData = useCallback(async () => { |
56 | | - setData((prevData) => { |
57 | | - if (prevData.length === 0) return prevData; |
58 | | - |
59 | | - // 기존 데이터의 가장 오래된 타임스탬프와 가격을 기준으로 함 |
60 | | - const oldestData = prevData[0]; |
61 | | - const oldestTimestamp = oldestData.Timestamp; |
62 | | - const basePrice = oldestData.Open; |
63 | | - const baseVolume = 1000; |
64 | | - |
65 | | - const pastData: CandlestickData[] = []; |
66 | | - |
67 | | - // 100개의 1분봉 데이터를 가장 오래된 데이터보다 이전 시간으로 생성 |
68 | | - for (let i = 10; i >= 1; i--) { |
69 | | - const date = new Date(oldestTimestamp); |
70 | | - date.setMinutes(date.getMinutes() - i); |
71 | | - |
72 | | - // 이전 봉의 종가를 기준으로 랜덤 변동 (-1% ~ +1%) |
73 | | - const changePercent = (Math.random() * 2 - 1) / 100; |
74 | | - const prevClose = pastData.length |
75 | | - ? pastData[pastData.length - 1].Close |
76 | | - : basePrice; |
77 | | - |
78 | | - const open = prevClose; |
79 | | - const close = open * (1 + changePercent); |
80 | | - |
81 | | - // 고가는 시가와 종가 중 큰 값보다 0-1% 높게 |
82 | | - const highBaseValue = Math.max(open, close); |
83 | | - const high = highBaseValue * (1 + Math.random() * 0.01); |
84 | | - |
85 | | - // 저가는 시가와 종가 중 작은 값보다 0-1% 낮게 |
86 | | - const lowBaseValue = Math.min(open, close); |
87 | | - const low = lowBaseValue * (1 - Math.random() * 0.01); |
88 | | - |
89 | | - // 거래량 (기준 거래량의 30-200%) |
90 | | - const volume = baseVolume * (0.3 + Math.random() * 1.7); |
91 | | - |
92 | | - pastData.push({ |
93 | | - Timestamp: date.getTime(), |
94 | | - Open: Number(open.toFixed(2)), |
95 | | - Close: Number(close.toFixed(2)), |
96 | | - High: Number(high.toFixed(2)), |
97 | | - Low: Number(low.toFixed(2)), |
98 | | - Volume: Math.round(volume), |
99 | | - }); |
100 | | - } |
101 | | - |
102 | | - // 새로운 과거 데이터를 기존 데이터 앞에 추가 |
103 | | - return [...pastData, ...prevData]; |
104 | | - }); |
105 | | - }, []); |
| 51 | +const fetchPastTimeData = (prevData: CandlestickData) => { |
| 52 | + const pastData: CandlestickData[] = []; |
| 53 | + |
| 54 | + // 시작점은 주어진 데이터 |
| 55 | + let currentClose = prevData.Close; |
| 56 | + const baseVolume = prevData.Volume; |
| 57 | + const baseTimestamp = prevData.Timestamp; |
| 58 | + |
| 59 | + // 10개의 과거 데이터를 생성 (시간 역순으로) |
| 60 | + for (let i = 10; i >= 1; i--) { |
| 61 | + // 1분씩 과거로 이동 (새로운 Date 객체 생성) |
| 62 | + const pastTimestamp = baseTimestamp - i * 60 * 1000; // i분 전 |
| 63 | + |
| 64 | + // 이전 봉의 종가를 기준으로 시가 생성 (작은 갭 허용) |
| 65 | + const gapPercent = (Math.random() * 0.4 - 0.2) / 100; // -0.2% ~ +0.2% |
| 66 | + const open = currentClose * (1 + gapPercent); |
| 67 | + |
| 68 | + // 종가 생성 (-2% ~ +2% 변동) |
| 69 | + const changePercent = (Math.random() * 4 - 2) / 100; |
| 70 | + const close = open * (1 + changePercent); |
| 71 | + |
| 72 | + // 고가와 저가 생성 |
| 73 | + const maxPrice = Math.max(open, close); |
| 74 | + const minPrice = Math.min(open, close); |
| 75 | + |
| 76 | + // 고가: 시가/종가 중 높은 값보다 0~2% 높게 |
| 77 | + const high = maxPrice * (1 + Math.random() * 0.02); |
| 78 | + |
| 79 | + // 저가: 시가/종가 중 낮은 값보다 0~2% 낮게 |
| 80 | + const low = minPrice * (1 - Math.random() * 0.02); |
| 81 | + |
| 82 | + // 거래량 (기준의 50~150%) |
| 83 | + const volume = baseVolume * (0.5 + Math.random()); |
106 | 84 |
|
| 85 | + const candlestick: CandlestickData = { |
| 86 | + Timestamp: pastTimestamp, |
| 87 | + Open: Number(open.toFixed(2)), |
| 88 | + Close: Number(close.toFixed(2)), |
| 89 | + High: Number(high.toFixed(2)), |
| 90 | + Low: Number(low.toFixed(2)), |
| 91 | + Volume: Math.round(volume), |
| 92 | + }; |
| 93 | + |
| 94 | + pastData.push(candlestick); |
| 95 | + |
| 96 | + // 다음 반복을 위해 현재 종가를 다음 봉의 기준으로 설정 |
| 97 | + currentClose = close; |
| 98 | + } |
| 99 | + |
| 100 | + // 시간순으로 정렬 (과거 -> 현재) |
| 101 | + return pastData.sort((a, b) => a.Timestamp - b.Timestamp); |
| 102 | +}; |
| 103 | + |
| 104 | +export default function ValueSeriesWithData(props: ValueSeriesProps) { |
107 | 105 | return ( |
108 | 106 | <ValueSeries |
109 | 107 | {...props} |
110 | | - pastTimeData={data} |
| 108 | + pastTimeData={DUMMY_DATA} |
111 | 109 | fetchPastTimeData={fetchPastTimeData} |
112 | 110 | /> |
113 | 111 | ); |
|
0 commit comments