futures.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. import { computed } from 'vue'
  2. import { timerInterceptor } from '@/utils/timer'
  3. import { queryErmcpGoods, queryQuoteDay } from '@/services/api/goods'
  4. import { createStore } from '../base'
  5. import { timerTask } from '@/utils/timer'
  6. import eventBus from '@/services/bus'
  7. import moment from 'moment'
  8. /**
  9. * 期货存储对象
  10. */
  11. export const futuresStore = createStore({
  12. state() {
  13. return {
  14. loading: false,
  15. quotes: <Proto.Quote[]>[], // 行情数据
  16. goodsList: <Model.GoodsRsp[]>[], // 商品列表
  17. quoteDayList: <Model.QuoteDayRsp[]>[], // 盘面列表
  18. }
  19. },
  20. getters: {
  21. quoteList() {
  22. return this.state.goodsList.reduce((res, cur) => {
  23. const { goodscode, goodsname, goodsgroupid, marketid, decimalplace } = cur
  24. const {
  25. last = 0,
  26. bid = 0,
  27. ask = 0,
  28. bidvolume = 0,
  29. askvolume = 0,
  30. totalvolume = 0,
  31. lastvolume = 0,
  32. holdvolume = 0,
  33. holdincrement = 0,
  34. presettle = 0,
  35. totalturnover = 0,
  36. opened = 0,
  37. highest = 0,
  38. lowest = 0,
  39. lasttime = '',
  40. } = this.actions.getQuoteDayInfoByCode(goodscode).value ?? {}
  41. const change = last === 0 ? 0 : last - presettle // 涨跌额/涨跌: 最新价 - 昨结价
  42. const item: Model.Futures = {
  43. marketid,
  44. goodsgroupid,
  45. goodscode,
  46. goodsname,
  47. decimalplace,
  48. last,
  49. lasttime,
  50. amplitude: change === 0 ? 0 : change / presettle, // 涨跌幅/幅度: (最新价 - 昨结价) / 昨结价
  51. change,
  52. bid,
  53. ask,
  54. bidvolume,
  55. askvolume,
  56. totalvolume,
  57. lastvolume,
  58. holdvolume,
  59. holdincrement,
  60. presettle,
  61. totalturnover,
  62. opened,
  63. highest,
  64. lowest,
  65. }
  66. res.push(item)
  67. return res
  68. }, [] as Model.Futures[])
  69. }
  70. },
  71. actions: {
  72. // 获取商品列表
  73. getGoodsList() {
  74. this.state.loading = true
  75. return queryErmcpGoods({
  76. success: (res) => {
  77. const codes = res.data.map((e) => e.goodscode)
  78. this.state.goodsList = res.data
  79. // 获取商品盘面信息
  80. const getQuoteDay = () => {
  81. return queryQuoteDay({
  82. data: {
  83. goodsCodes: codes.join(',')
  84. },
  85. success: (res) => {
  86. this.state.quoteDayList = res.data
  87. },
  88. complete: () => {
  89. // 每5分钟获取一次盘面
  90. timerTask.setTimeout(() => getQuoteDay(), 5 * 60 * 1000, 'quoteDay')
  91. }
  92. })
  93. }
  94. if (codes.length) {
  95. getQuoteDay()
  96. }
  97. },
  98. complete: () => {
  99. this.state.loading = false
  100. }
  101. })
  102. },
  103. // 通过 goodscode 获取盘面实时行情
  104. getQuoteDayInfoByCode(goodscode: string) {
  105. return computed(() => this.state.quoteDayList.find((e) => e.goodscode.toUpperCase() === goodscode.toUpperCase()))
  106. },
  107. // 通过 goodscode 获取商品实时报价
  108. getGoodsPriceByCode(goodscode: string) {
  109. return computed(() => {
  110. const quote = this.actions.getQuoteDayInfoByCode(goodscode)
  111. return quote.value?.last ?? 0
  112. })
  113. }
  114. }
  115. })
  116. // 接收行情推送通知
  117. export const quotePushNotify = eventBus.$on('QuotePushNotify', (res) => {
  118. const { quotes } = futuresStore.$mapState()
  119. const data = res as Proto.Quote[]
  120. data.forEach((item) => {
  121. const index = quotes.value.findIndex((e) => e.goodscode === item.goodscode)
  122. if (index > -1) {
  123. quotes.value[index] = item
  124. } else {
  125. quotes.value.push(item)
  126. }
  127. })
  128. handleQuote()
  129. })
  130. // 处理行情数据
  131. const handleQuote = timerInterceptor.setThrottle(() => {
  132. const { quotes, goodsList, quoteDayList, } = futuresStore.$mapState()
  133. quotes.value.forEach((item) => {
  134. const goods = goodsList.value.find((e) => e.goodscode.toUpperCase() === item.goodscode?.toUpperCase())
  135. const quote = quoteDayList.value.find((e) => e.goodscode.toUpperCase() === item.goodscode?.toUpperCase())
  136. const lasttime = (item.date && item.time) ? moment(item.date + item.time, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss') : ''
  137. // 处理报价小数位
  138. const last = (() => {
  139. const decimal = goods?.decimalplace ?? 0
  140. const num = Math.pow(10, decimal)
  141. if (item.last) {
  142. return item.last / num
  143. }
  144. return 0
  145. })()
  146. if (quote) {
  147. Object.entries(item).forEach(([key, value]) => {
  148. // 只更新存在的属性
  149. if (Reflect.has(quote, key)) {
  150. Object.defineProperty(quote, key, value)
  151. }
  152. })
  153. quote.last = last
  154. // 处理最高最低价
  155. if (last) {
  156. if (last > quote.highest) {
  157. quote.highest = last
  158. }
  159. if (last < quote.lowest) {
  160. quote.lowest = last
  161. }
  162. }
  163. // 处理最新时间
  164. if (lasttime) {
  165. quote.lasttime = lasttime
  166. }
  167. } else {
  168. console.warn('行情推送的商品 ' + item.goodscode + ' 缺少盘面信息')
  169. quoteDayList.value.push({
  170. ask: item.ask ?? 0,
  171. ask2: item.ask2 ?? 0,
  172. ask3: item.ask3 ?? 0,
  173. ask4: item.ask4 ?? 0,
  174. ask5: item.ask5 ?? 0,
  175. ask6: 0,
  176. ask7: 0,
  177. ask8: 0,
  178. ask9: 0,
  179. ask10: 0,
  180. askorderid: 0,
  181. askorderid2: 0,
  182. askorderid3: 0,
  183. askorderid4: 0,
  184. askorderid5: 0,
  185. askordervolume: 0,
  186. askordervolume2: 0,
  187. askordervolume3: 0,
  188. askordervolume4: 0,
  189. askordervolume5: 0,
  190. askordervolume6: 0,
  191. askordervolume7: 0,
  192. askordervolume8: 0,
  193. askordervolume9: 0,
  194. askordervolume10: 0,
  195. askqueueinfo: "",
  196. askvolume: item.askvolume ?? 0,
  197. askvolume2: item.askvolume2 ?? 0,
  198. askvolume3: item.askvolume3 ?? 0,
  199. askvolume4: item.askvolume4 ?? 0,
  200. askvolume5: item.askvolume5 ?? 0,
  201. askvolume6: 0,
  202. askvolume7: 0,
  203. askvolume8: 0,
  204. askvolume9: 0,
  205. askvolume10: 0,
  206. averageprice: 0,
  207. bid: item.bid ?? 0,
  208. bid2: item.bid2 ?? 0,
  209. bid3: item.bid3 ?? 0,
  210. bid4: item.bid4 ?? 0,
  211. bid5: item.bid5 ?? 0,
  212. bid6: 0,
  213. bid7: 0,
  214. bid8: 0,
  215. bid9: 0,
  216. bid10: 0,
  217. bidorderid: 0,
  218. bidorderid2: 0,
  219. bidorderid3: 0,
  220. bidorderid4: 0,
  221. bidorderid5: 0,
  222. bidordervolume: 0,
  223. bidordervolume2: 0,
  224. bidordervolume3: 0,
  225. bidordervolume4: 0,
  226. bidordervolume5: 0,
  227. bidordervolume6: 0,
  228. bidordervolume7: 0,
  229. bidordervolume8: 0,
  230. bidordervolume9: 0,
  231. bidordervolume10: 0,
  232. bidqueueinfo: "",
  233. bidvolume: item.bidvolume ?? 0,
  234. bidvolume2: item.bidvolume2 ?? 0,
  235. bidvolume3: item.bidvolume3 ?? 0,
  236. bidvolume4: item.bidvolume4 ?? 0,
  237. bidvolume5: item.bidvolume5 ?? 0,
  238. bidvolume6: 0,
  239. bidvolume7: 0,
  240. bidvolume8: 0,
  241. bidvolume9: 0,
  242. bidvolume10: 0,
  243. calloptionpremiums: item.calloptionpremiums ?? 0,
  244. calloptionpremiums2: item.calloptionpremiums2 ?? 0,
  245. calloptionpremiums3: item.calloptionpremiums3 ?? 0,
  246. calloptionpremiums4: item.calloptionpremiums4 ?? 0,
  247. calloptionpremiums5: item.calloptionpremiums5 ?? 0,
  248. cleartime: 0,
  249. exchangecode: item.exchangecode ?? 0,
  250. exchangedate: item.exchangedate ?? 0,
  251. goodscode: item.goodscode ?? '',
  252. grepmarketprice: 0,
  253. highest: item.highest ?? 0,
  254. holdincrement: 0,
  255. holdvolume: item.holdvolume ?? 0,
  256. iep: 0,
  257. iev: 0,
  258. inventory: item.inventory ?? 0,
  259. iscleared: 0,
  260. issettled: 0,
  261. last,
  262. lastlot: 0,
  263. lasttime,
  264. Lastturnover: 0,
  265. lastvolume: item.lastvolume ?? 0,
  266. limitdown: item.limitlow ?? 0,
  267. limitup: item.limithigh ?? 0,
  268. lowest: item.lowest ?? 0,
  269. nontotalholdervolume: 0,
  270. nontotallot: 0,
  271. nontotalturnover: 0,
  272. nontotalvolume: 0,
  273. opened: item.opened ?? 0,
  274. opentime: '',
  275. orderid: 0,
  276. preclose: item.preclose ?? 0,
  277. preholdvolume: item.preholdvolume ?? 0,
  278. presettle: item.presettle ?? 0,
  279. publictradetype: '',
  280. putoptionpremiums: item.putoptionpremiums ?? 0,
  281. putoptionpremiums2: item.putoptionpremiums2 ?? 0,
  282. putoptionpremiums3: item.putoptionpremiums3 ?? 0,
  283. putoptionpremiums4: item.putoptionpremiums4 ?? 0,
  284. putoptionpremiums5: item.putoptionpremiums5 ?? 0,
  285. settle: item.settle ?? 0,
  286. strikeprice: 0,
  287. totalaskvolume: 0,
  288. totalbidvolume: 0,
  289. totallot: 0,
  290. totalturnover: item.totalturnover ?? 0,
  291. totalvolume: item.totalvolume ?? 0,
  292. utclasttime: ''
  293. })
  294. }
  295. })
  296. }, 200)