options.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. import { reactive, watch } from 'vue'
  2. import { ECOption } from '@/components/base/echarts/core'
  3. import { ChartCycleType } from '@/constants/chart'
  4. import { useGlobalStore } from '@/stores'
  5. import { EchartsDataset, EchartsOptions, Colors } from './types'
  6. import moment from 'moment'
  7. const globalStore = useGlobalStore()
  8. const { appTheme } = globalStore.$toRefs()
  9. function getColors() {
  10. // 默认主题色配置
  11. const defaultColors: Colors = {
  12. upColor: '#ff3333',
  13. downColor: '#0aab62',
  14. xAxisLineColor: 'rgba(128,128,128,.1)',
  15. yAxisLineColor: 'rgba(128,128,128,.1)',
  16. }
  17. const colors = {
  18. default: defaultColors,
  19. dark: defaultColors,
  20. light: {
  21. ...defaultColors,
  22. xAxisLineColor: '#dae5ec',
  23. yAxisLineColor: '#dae5ec',
  24. }
  25. }
  26. return colors[appTheme.value];
  27. }
  28. export function useOptions(dataset: EchartsDataset) {
  29. // 图表配置项
  30. const options = reactive<EchartsOptions>({
  31. cycleType: ChartCycleType.Minutes,
  32. colors: getColors(),
  33. candlestick: {},
  34. macd: {},
  35. vol: {},
  36. kdj: {},
  37. cci: {},
  38. })
  39. const getDefaultOption = (): ECOption => {
  40. const { source } = dataset.candlestick;
  41. const { xAxisLineColor, yAxisLineColor } = options.colors;
  42. return {
  43. grid: {
  44. left: '25px',
  45. right: '25px',
  46. top: '20px',
  47. bottom: '15px',
  48. containLabel: true,
  49. },
  50. dataZoom: {
  51. type: 'inside',
  52. startValue: source.length - 60, // 起始显示K线条数(最新60条)
  53. end: 100,
  54. minValueSpan: 30, // 限制窗口缩放显示最少数据条数
  55. maxValueSpan: 200, // 限制窗口缩放显示最大数据条数
  56. },
  57. axisPointer: {
  58. label: {
  59. backgroundColor: 'rgba(72,72,72,.75)'
  60. }
  61. },
  62. xAxis: {
  63. type: 'category',
  64. axisLabel: {
  65. color: '#777',
  66. margin: 12,
  67. showMaxLabel:true,
  68. showMinLabel:true,
  69. formatter: (val: string) => {
  70. if (val) {
  71. switch (options.cycleType) {
  72. case ChartCycleType.Day: {
  73. return moment(val).format('YYYY-MM-DD')
  74. }
  75. default: {
  76. return moment(val).format('HH:mm')
  77. }
  78. }
  79. }
  80. return ''
  81. },
  82. // interval: (index) => {
  83. // return index % 8 === 0
  84. // }
  85. },
  86. max: (value) => {
  87. if (value.max < 30) {
  88. return 30
  89. }
  90. return value.max
  91. },
  92. axisLine: {
  93. lineStyle: {
  94. color: xAxisLineColor, // 坐标轴线线的颜色
  95. }
  96. },
  97. axisPointer: {
  98. label: {
  99. formatter: (params) => {
  100. switch (options.cycleType) {
  101. case ChartCycleType.Day: {
  102. return moment(params.value).format('YYYY-MM-DD')
  103. }
  104. default: {
  105. return moment(params.value).format('YYYY-MM-DD HH:mm:ss')
  106. }
  107. }
  108. },
  109. }
  110. },
  111. axisTick: {
  112. show: false,
  113. },
  114. // splitLine: {
  115. // show: true,
  116. // lineStyle: {
  117. // color: xAxisLineColor,
  118. // },
  119. // },
  120. },
  121. yAxis: {
  122. type: 'value',
  123. scale: true,
  124. splitLine: {
  125. lineStyle: {
  126. // 坐标分隔线颜色
  127. color: yAxisLineColor,
  128. }
  129. }
  130. }
  131. }
  132. }
  133. // K线配置项
  134. const setCandlestickOption = () => {
  135. const { dimensions, source } = dataset.candlestick;
  136. const { upColor, downColor } = options.colors;
  137. options.candlestick = {
  138. ...getDefaultOption(),
  139. dataset: {
  140. dimensions,
  141. source,
  142. },
  143. series: [
  144. {
  145. name: 'K线',
  146. type: 'candlestick',
  147. barWidth: '80%',
  148. itemStyle: {
  149. color: upColor,
  150. color0: downColor,
  151. borderColor: upColor,
  152. borderColor0: downColor,
  153. },
  154. // 最新价标线
  155. markLine: {
  156. symbol: 'none',
  157. // 标线标签样式
  158. label: {
  159. show: false,
  160. color: '#fff',
  161. backgroundColor: 'rgba(72,72,72,.75)',
  162. padding: 5,
  163. borderRadius: 3,
  164. position: 'insideStartTop',
  165. },
  166. // 标线样式
  167. lineStyle: {
  168. type: 'dashed',
  169. color: 'rgba(102,102,102,.7)'
  170. },
  171. data: [
  172. {
  173. // 收盘价
  174. yAxis: source.length ? source[source.length - 1].close : 0,
  175. },
  176. ],
  177. },
  178. },
  179. {
  180. name: 'MA5',
  181. type: 'line',
  182. sampling: 'average', //折线图在数据量远大于像素点时候的降采样策略,开启后可以有效的优化图表的绘制效率
  183. smooth: true,
  184. symbol: 'none',
  185. lineStyle: {
  186. width: 1,
  187. opacity: 0.8,
  188. },
  189. },
  190. {
  191. name: 'MA10',
  192. type: 'line',
  193. sampling: 'average',
  194. smooth: true,
  195. symbol: 'none',
  196. lineStyle: {
  197. width: 1,
  198. opacity: 0.8,
  199. },
  200. },
  201. {
  202. name: 'MA15',
  203. type: 'line',
  204. sampling: 'average',
  205. smooth: true,
  206. symbol: 'none',
  207. lineStyle: {
  208. width: 1,
  209. opacity: 0.8,
  210. },
  211. },
  212. ],
  213. }
  214. }
  215. // MACD配置项
  216. const setMacdOption = () => {
  217. const { upColor, downColor, yAxisLineColor } = options.colors;
  218. const { dimensions, source } = dataset.macd;
  219. options.macd = {
  220. ...getDefaultOption(),
  221. yAxis: {
  222. scale: true,
  223. splitNumber: 2,
  224. splitLine: {
  225. lineStyle: {
  226. // 坐标分隔线颜色
  227. color: yAxisLineColor,
  228. },
  229. },
  230. },
  231. dataset: {
  232. dimensions,
  233. source,
  234. },
  235. series: [
  236. {
  237. name: 'MACD',
  238. type: 'bar',
  239. sampling: 'average',
  240. barWidth: '60%',
  241. itemStyle: {
  242. color: ({ data }) => {
  243. const { macd } = data as { macd: number };
  244. if (macd > 0) {
  245. return upColor;
  246. } else {
  247. return downColor;
  248. }
  249. },
  250. }
  251. },
  252. {
  253. name: 'DIF',
  254. type: 'line',
  255. sampling: 'average',
  256. smooth: true,
  257. symbol: 'none',
  258. lineStyle: {
  259. width: 1,
  260. opacity: 0.8,
  261. },
  262. },
  263. {
  264. name: 'DEA',
  265. type: 'line',
  266. sampling: 'average',
  267. smooth: true,
  268. symbol: 'none',
  269. lineStyle: {
  270. width: 1,
  271. opacity: 0.8,
  272. },
  273. },
  274. ],
  275. }
  276. }
  277. // VOL配置项
  278. const setVolOption = () => {
  279. const { yAxisLineColor } = options.colors;
  280. const { dimensions, source } = dataset.vol;
  281. options.vol = {
  282. ...getDefaultOption(),
  283. yAxis: {
  284. scale: true,
  285. splitNumber: 2,
  286. splitLine: {
  287. lineStyle: {
  288. // 坐标分隔线颜色
  289. color: yAxisLineColor,
  290. },
  291. },
  292. },
  293. dataset: {
  294. dimensions,
  295. source,
  296. },
  297. series: [
  298. {
  299. name: 'VOL',
  300. type: 'bar',
  301. sampling: 'average',
  302. barWidth: '60%',
  303. },
  304. ],
  305. }
  306. }
  307. // KDJ配置项
  308. const setKdjOption = () => {
  309. const { yAxisLineColor } = options.colors;
  310. const { dimensions, source } = dataset.kdj;
  311. options.kdj = {
  312. ...getDefaultOption(),
  313. yAxis: {
  314. scale: true,
  315. splitNumber: 2,
  316. splitLine: {
  317. lineStyle: {
  318. // 坐标分隔线颜色
  319. color: yAxisLineColor,
  320. },
  321. },
  322. },
  323. dataset: {
  324. dimensions,
  325. source,
  326. },
  327. series: [
  328. {
  329. name: 'K',
  330. type: 'line',
  331. sampling: 'average',
  332. smooth: true,
  333. symbol: 'none',
  334. lineStyle: {
  335. width: 1,
  336. opacity: 0.8,
  337. },
  338. },
  339. {
  340. name: 'D',
  341. type: 'line',
  342. sampling: 'average',
  343. smooth: true,
  344. symbol: 'none',
  345. lineStyle: {
  346. width: 1,
  347. opacity: 0.8,
  348. },
  349. },
  350. {
  351. name: 'J',
  352. type: 'line',
  353. sampling: 'average',
  354. smooth: true,
  355. symbol: 'none',
  356. lineStyle: {
  357. width: 1,
  358. opacity: 0.8,
  359. },
  360. },
  361. ],
  362. }
  363. }
  364. // CCI配置项
  365. const setCciOption = () => {
  366. const { yAxisLineColor } = options.colors;
  367. const { dimensions, source } = dataset.cci;
  368. options.cci = {
  369. ...getDefaultOption(),
  370. yAxis: {
  371. scale: true,
  372. splitNumber: 2,
  373. splitLine: {
  374. lineStyle: {
  375. // 坐标分隔线颜色
  376. color: yAxisLineColor,
  377. },
  378. },
  379. },
  380. dataset: {
  381. dimensions,
  382. source,
  383. },
  384. series: [
  385. {
  386. name: 'CCI',
  387. type: 'line',
  388. sampling: 'average',
  389. smooth: true,
  390. symbol: 'none',
  391. lineStyle: {
  392. width: 1,
  393. opacity: 0.8,
  394. },
  395. },
  396. ],
  397. }
  398. }
  399. const initOptions = () => {
  400. setCandlestickOption();
  401. setMacdOption();
  402. setVolOption();
  403. setKdjOption();
  404. setCciOption();
  405. }
  406. // 动态更新数据
  407. const updateOptions = () => {
  408. const { candlestick, macd, vol, kdj, cci } = dataset;
  409. options.candlestick = {
  410. dataset: {
  411. source: candlestick.source,
  412. },
  413. series: [
  414. {
  415. name: 'K线',
  416. markLine: {
  417. data: [
  418. {
  419. yAxis: candlestick.source[candlestick.source.length - 1].close,
  420. },
  421. ],
  422. },
  423. },
  424. ],
  425. }
  426. options.macd = {
  427. dataset: {
  428. source: macd.source,
  429. },
  430. }
  431. options.vol = {
  432. dataset: {
  433. source: vol.source,
  434. },
  435. }
  436. options.kdj = {
  437. dataset: {
  438. source: kdj.source,
  439. },
  440. }
  441. options.cci = {
  442. dataset: {
  443. source: cci.source,
  444. },
  445. }
  446. }
  447. // 监听主题变化
  448. watch(appTheme, () => {
  449. options.colors = getColors();
  450. initOptions();
  451. })
  452. return {
  453. options,
  454. initOptions,
  455. updateOptions,
  456. }
  457. }