import { ref, computed } from 'vue' //import { timerInterceptor } from '@/utils/timer' import { ChartCycleType } from '@/constants/chart' import { queryHistoryDatas } from '@/services/api/quote' import { useFuturesStore } from '@/stores' import { useDataset } from './dataset' import { useOptions } from './options' import moment from 'moment' export function useCandlestickChart(goodscode: string) { const { quoteWatch } = useFuturesStore() const { dataset, handleData, clearData, calcIndicator } = useDataset(); const { options, initOptions, updateOptions } = useOptions(dataset); const loading = ref(false); const isEmpty = ref(true); const dataIndex = ref(-1); // 当前数据索引值 // 当前选中的数据项 const selectedItem = computed(() => { let result: { [key: string]: number | string } = { open: '--', close: '--', highest: '--', lowest: '--', ma5: '--', ma10: '--', ma15: '--', macd: '--', dif: '--', dea: '--', vol: '--', k: '--', d: '--', j: '--', cci: '--' } if (dataIndex.value > -1 && dataset.candlestick.source.length > dataIndex.value) { const { open, close, highest, lowest, ma5, ma10, ma15 } = dataset.candlestick.source[dataIndex.value]; const { macd, dif, dea } = dataset.macd.source[dataIndex.value]; const { vol } = dataset.vol.source[dataIndex.value]; const { k, d, j } = dataset.kdj.source[dataIndex.value]; const { cci } = dataset.cci.source[dataIndex.value]; result = { open, close, highest, lowest, ma5, ma10, ma15, macd, dif, dea, vol, k, d, j, cci } } return result; }) /** * 初始化数据 * @param cycletype 周期类型 */ const initData = (cycletype: ChartCycleType) => { if (goodscode) { clearData(); dataIndex.value = -1; options.cycleType = cycletype; loading.value = true; isEmpty.value = true; // 获取历史行情 queryHistoryDatas({ data: { cycleType: cycletype, goodsCode: goodscode, count: 1440, } }).then((res) => { // 日期升序排序 const data = res.data.sort((a, b) => moment(a.ts).valueOf() - moment(b.ts).valueOf()); if (data.length) { dataIndex.value = data.length - 1; isEmpty.value = false; handleData(data); } }).finally(() => { loading.value = false; }) } } /** * 获取周期毫秒数 * @returns */ const getCycleMilliseconds = () => { const milliseconds = 60 * 1000; // 一分钟毫秒数 switch (options.cycleType) { case ChartCycleType.Minutes5: { return milliseconds * 5; } case ChartCycleType.Minutes30: { return milliseconds * 30; } case ChartCycleType.Minutes60: { return milliseconds * 60; } case ChartCycleType.Hours2: { return milliseconds * 2 * 60; } case ChartCycleType.Hours4: { return milliseconds * 4 * 60; } case ChartCycleType.Day: { return milliseconds * 24 * 60; } default: { return milliseconds; } } } /** * 格式化日期 * @param value * @returns */ const formatDate = (value: string) => { switch (options.cycleType) { case ChartCycleType.Day: { return moment(value).format('YYYY-MM-DD') } case ChartCycleType.Hours2: case ChartCycleType.Hours4: { return moment(value).format('YYYY-MM-DD HH:00:00') } default: { return moment(value).format('YYYY-MM-DD HH:mm:00') } } } /** * 更新图表数据 */ const updateChart = (quote: Partial) => { const { last, lasttime } = quote if (last && lasttime) { const { candlestick, macd, vol, kdj, cci } = dataset const lastIndex = candlestick.source.length - 1 // 历史数据最后索引位置 const cycleMilliseconds = getCycleMilliseconds() const oldTime = lastIndex === -1 ? moment(lasttime) : moment(candlestick.source[lastIndex].date) // 历史行情最后时间 const diffTime = moment(lasttime).valueOf() - oldTime.valueOf() // 计算时间差 // if (diffTime > cycleMilliseconds * 2) { // // 时间间隔超过两个周期,重新请求历史数据,待优化 // timerInterceptor.debounce(() => { // queryHistoryDatas({ // data: { // cycleType: options.cycleType, // goodsCode: goodscode, // count: 1440, // } // }).then((res) => { // // 日期升序排序 // const data = res.data.sort((a, b) => moment(a.ts).valueOf() - moment(b.ts).valueOf()); // if (data.length) { // dataIndex.value = data.length - 1 // clearData() // handleData(data, updateOptions) // } // }) // }, 1000, 'updateChart') // } else { // 判断时间差是否大于周期时间 if (lastIndex === -1 || diffTime > cycleMilliseconds) { const newtime = formatDate(lasttime) // 新增K线数据 candlestick.source.push({ date: newtime, open: last, close: last, lowest: last, highest: last, ma5: '-', ma10: '-', ma15: '-', }) // 新增MACD数据 macd.source.push({ date: newtime, ema12: 0, ema26: 0, dif: 0, dea: 0, macd: 0, }) // 新增VOL数据 vol.source.push({ date: newtime, vol: 0, }) // 新增KDJ数据 kdj.source.push({ date: newtime, k: '-', d: '-', j: '-', }) // 新增CCI数据 cci.source.push({ date: newtime, cci: '-', }) } else { // 更新列表中最后一条记录的数据 const record = candlestick.source[lastIndex] if (record.lowest > last) { record.lowest = last // 更新最低价 } if (record.highest < last) { record.highest = last // 更新最高价 } record.close = last // 更新收盘价 } // 计算各项指标 calcIndicator(lastIndex === -1 ? 0 : lastIndex) updateOptions() // } } } // 监听行情推送 quoteWatch(goodscode, (val) => { if (!loading.value && !isEmpty.value) { updateChart(val) } }) return { loading, isEmpty, dataIndex, options, selectedItem, initData, initOptions, } }