ws-deedfeeds.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. const wssUrl = "wss://api.hadax.com/ws"
  2. // const wssUrl = 'wss://api-aws.huobi.pro/ws'; // 实时币种价格
  3. const pako = window.pako
  4. // 'm1','h1', 'd1', 'w1', 'M1'
  5. // 1min, 5min, 15min, 30min, 60min, 4hour, 1day, 1mon, 1week, 1year
  6. // 取消订阅
  7. // { "unsub": "topic to unsub", "id": "id generate by client" }
  8. // 单位映射
  9. const unitMap = {
  10. m: 'min',
  11. h: 'hour',
  12. d: 'day',
  13. w: 'week',
  14. M: 'mon',
  15. }
  16. // 初始化图表
  17. const chart = klinecharts.init('chart_container')
  18. let chart_type=0;
  19. function loading(type){
  20. // let type= $('.loding').data('type')
  21. console.info(type)
  22. if(type==0){
  23. $('.loding').css('display','flex');
  24. $('.loding').data('type','1');
  25. }else{
  26. $('.loding').css('display','none');
  27. $('.loding').data('type','0');
  28. }
  29. }
  30. function changInterval(interval,th){
  31. loading(0)
  32. console.info(VyKline)
  33. window.deedfeeds.intervalChanged({interval:interval,setHistoryData: VyKline.initHistoryData,subscribeData: VyKline.getRealTimeData})
  34. console.info(th)
  35. $(th).addClass('active');
  36. $(th).siblings().removeClass('active')
  37. }
  38. function initOnReady1(kLineDataList){
  39. // 创建一个主图技术指标
  40. chart.createTechnicalIndicator('MA', false, { id: 'candle_pane' })
  41. // 创建一个副图技术指标VOL
  42. chart.createTechnicalIndicator('VOL')
  43. // 创建一个副图技术指标MACD
  44. // chart.createTechnicalIndicator('MACD')
  45. // 加载数据
  46. kLineDataList.reverse()
  47. // console.info(kLineDataList)
  48. var chartDataList = kLineDataList.map(function (data) {
  49. return {
  50. timestamp: data.time,
  51. open: data.open,
  52. high: data.high,
  53. low: data.low,
  54. close: data.close,
  55. volume:data.volume,
  56. }
  57. })
  58. chart.applyNewData(chartDataList)
  59. chart.setOffsetRightSpace(2)
  60. chart_type=1;
  61. // chart.subscribeAction('drawCandle',function(res){
  62. // console.info(res)
  63. // })
  64. // chart.createAnnotation({
  65. // point: { timestamp: 1626937081, price: 0.054050 },
  66. // styles: {
  67. // symbol: {
  68. // type: 'diamond',
  69. // position: 'top',
  70. // size: 8,
  71. // color: '#1e88e5',
  72. // activeSize: 10,
  73. // activeColor: '#FF9600',
  74. // offset: [0, 20]
  75. // }
  76. // },
  77. // checkPointInCustomSymbol: function ({ point, coordinate, size }) {
  78. // console.log(point, coordinate, size)
  79. // return true
  80. // },
  81. // drawCustomSymbol: function ({ ctx, point, coordinate, viewport, isActive, styles }) {
  82. // console.log(point, coordinate, viewport, isActive, styles)
  83. // },
  84. // drawExtend: function ({ ctx, point, coordinate, viewport, isActive, styles }) {
  85. // console.log(point, coordinate, viewport, isActive, styles)
  86. // },
  87. // onClick: function ({ id, points, event }) { console.log(id, points, event) },
  88. // onRightClick: function ({ id, points, event }) { console.log(id, points, event) },
  89. // onMouseEnter: function ({ id, points, event }) { console.log(id, points, event) },
  90. // onMouseLeave: function ({ id, points, event }) { console.log(id, points, event) },
  91. // })
  92. // chart.setDataSpace(15)
  93. }
  94. // 格式化时间粒度
  95. function formatPeriod(str) {
  96. const reg = /([A-z]+)([0-9]+)/
  97. const matchedArr = str.match(reg)
  98. if (matchedArr) {
  99. return matchedArr[2] + unitMap[matchedArr[1]]
  100. } else {
  101. console.error("格式化时间粒度出错!");
  102. }
  103. }
  104. // ajax
  105. // function ajaxaitc(){
  106. // const historyData = []
  107. // var ajax = new XMLHttpRequest();
  108. // //步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
  109. // ajax.open('get','/Chart/getMarketSpecialtyJsonAitc.html?market=aitc_usdt&step=900');
  110. // //步骤三:发送请求
  111. // ajax.send();
  112. // //步骤四:注册事件 onreadystatechange 状态改变就会调用
  113. // ajax.onreadystatechange = function () {
  114. // if (ajax.readyState==4 &&ajax.status==200) {
  115. // if(ajax.responseText){
  116. // //步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
  117. //       let data = JSON.parse(ajax.responseText)
  118. //     // console.log(data);//输入相应的内容
  119. // data && data.forEach(item => {
  120. // historyData.unshift({
  121. // time: item.id * 1000, // 时间
  122. // open: item.open, // 开
  123. // high: item.high, // 高
  124. // low: item.low, // 低
  125. // close: item.close, // 收
  126. // volume: item.vol // 交易量
  127. // })
  128. // })
  129. // // return historyData
  130. //    }
  131. //   // console.log(ajax.responseText)
  132. //   // return 111111111111;
  133. // callback(historyData);
  134. // }
  135. // }
  136. // }
  137. // 币种
  138. const SYMBOL =window.SYMBOL;
  139. // 固定为 300 条数据
  140. const dataNum = 900 // 数据条数
  141. const historyK = (interval) => {
  142. const reg1 = /([A-z]+)([0-9]+)/
  143. let matchedArr = interval.match(reg1)
  144. // console.log(interval,11111111111)
  145. const reg = /[0-9]+/
  146. let shijian = interval.match(reg)[0]
  147. if(matchedArr[1] == 'h'){
  148. shijian = matchedArr[2] * 60
  149. }
  150. if(matchedArr[1] == 'd'){
  151. shijian = matchedArr[2] * 60*24
  152. }
  153. if(matchedArr[1] == 'w'){
  154. shijian = matchedArr[2] * 60*24*3.5
  155. }
  156. let form1 = Math.trunc(Date.now() / 1000) - 60 * dataNum * shijian
  157. // if(`${formatPeriod(interval)}` == '4hour'){
  158. // form1 = Math.trunc(Date.now() / 1000)- (4*60*60*dataNum*1.5)
  159. // }
  160. // if(`${formatPeriod(interval)}` == '1day'){
  161. // form1 = Math.trunc(Date.now() / 1000)- (24*60*60*dataNum)
  162. // }
  163. // if(`${formatPeriod(interval)}` == '1week'){
  164. // form1 = Math.trunc(Date.now() / 1000)- (24*60*60*dataNum*7)
  165. // }
  166. // console.log(form1)
  167. let str = {
  168. req: `market.${SYMBOL}.kline.${formatPeriod(interval)}`,
  169. id: SYMBOL,
  170. from:form1, // 1min 对应一条数据 最小粒度为 1 min
  171. to: Math.trunc(Date.now() / 1000)
  172. }
  173. return str
  174. }
  175. const subK = (interval) => ({ // 订阅数据
  176. sub: `market.${SYMBOL}.kline.${formatPeriod(interval)}`,
  177. id: SYMBOL
  178. })
  179. const unsubK = (interval) => ({ // 取消订阅数据
  180. unsub: `market.${SYMBOL}.kline.${formatPeriod(interval)}`,
  181. id: SYMBOL
  182. })
  183. class Deedfeeds {
  184. getMarketSpecialtyJsonAitclast(interval){
  185. const reg1 = /([A-z]+)([0-9]+)/
  186. let matchedArr = interval.match(reg1)
  187. // console.log(1111111)
  188. let shijian = matchedArr[2]
  189. if(matchedArr[1] == 'h'){
  190. shijian = matchedArr[2] * 60
  191. }
  192. if(matchedArr[1] == 'd'){
  193. shijian = matchedArr[2] * 60*24
  194. }
  195. if(matchedArr[1] == 'w'){
  196. shijian = matchedArr[2] * 60*24*3.5
  197. }
  198. let _this= this
  199. // console.log(interval,'时间')
  200. $.ajax({
  201. //请求方式
  202. type : "GET",
  203. //请求的媒体类型
  204. contentType: "application/json;charset=UTF-8",
  205. //请求地址
  206. url : "/Home/Chart/getMarketSpecialtyJsonAitclast.html?step="+shijian*60,
  207. //请求成功
  208. success : function(result) {
  209. var historyData = []
  210. console.log(result)
  211. var item = result[0]
  212. console.log(historyData)
  213. _this.subscribeDataParam.subscribeData({
  214. time: parseInt(item.time) * 1000, // 时间
  215. open: parseFloat(item.open), // 开
  216. high: parseFloat(item.high), // 高
  217. low: parseFloat(item.low), // 低
  218. close: parseFloat(item.close), // 收
  219. volume: parseFloat(item.volume) // 交易量
  220. })
  221. chart.updateData(
  222. {
  223. // 开盘价,必要字段
  224. open: parseFloat(item.open),
  225. // 收盘价,必要字段
  226. close: parseFloat(item.close),
  227. // 最高价,必要字段
  228. high: parseFloat(item.high),
  229. // 最低价,必要字段
  230. low: parseFloat(item.low),
  231. // 成交量,非必须字段
  232. volume: parseFloat(item.volume),
  233. // 时间戳,毫秒级别,必要字段
  234. timestamp: parseInt(item.time) * 1000
  235. }
  236. );
  237. // if(matchedArr[0] == 'm1'){
  238. // localStorage.setItem('closeshijian'+SYMBOL,item.close)
  239. // }else{
  240. // localStorage.removeItem('closeshijian'+SYMBOL)
  241. // }
  242. localStorage.setItem('closeshijian'+SYMBOL,item.close)
  243. // console.log(historyData)
  244. },
  245. //请求失败,包含具体的错误信息
  246. error : function(e){
  247. console.log(e.status);
  248. console.log(e.responseText);
  249. }
  250. });
  251. }
  252. ajaxaitc(interval){
  253. let _this= this
  254. const reg1 = /([A-z]+)([0-9]+)/
  255. let matchedArr = interval.match(reg1)
  256. let shijian = matchedArr[2]
  257. if(matchedArr[1] == 'h'){
  258. shijian = matchedArr[2] * 60
  259. }
  260. if(matchedArr[1] == 'd'){
  261. shijian = matchedArr[2] * 60*24
  262. }
  263. if(matchedArr[1] == 'w'){
  264. shijian = matchedArr[2] * 60*24*3.5
  265. }
  266. // console.log(interval,'时间')
  267. $.ajax({
  268. //请求方式
  269. type : "GET",
  270. //请求的媒体类型
  271. contentType: "application/json;charset=UTF-8",
  272. //请求地址
  273. url : "/Home/Chart/getMarketSpecialtyJsonAitc.html?market=usdz_usdt&step="+shijian*60,
  274. //请求成功
  275. success : function(result) {
  276. console.info(result)
  277. var historyData = []
  278. result && result.forEach(item => {
  279. historyData.unshift({
  280. time: parseInt(item.time) * 1000, // 时间
  281. open: parseFloat(item.open), // 开
  282. high: parseFloat(item.high), // 高
  283. low: parseFloat(item.low), // 低
  284. close: parseFloat(item.close), // 收
  285. volume: parseFloat(item.volume) // 交易量
  286. })
  287. })
  288. _this.subscribeDataParam.setHistoryData(historyData)
  289. if(matchedArr[0] == 'm1'){
  290. localStorage.setItem('closeshijian'+SYMBOL,historyData[0].close)
  291. }else{
  292. localStorage.removeItem('closeshijian'+SYMBOL)
  293. }
  294. console.info(chart_type)
  295. if(chart_type==0){
  296. loading(1)
  297. chart.setPriceVolumePrecision(6,6)
  298. initOnReady1(historyData)
  299. }else{
  300. let historyData1=[]
  301. result && result.forEach(item => {
  302. historyData1.unshift({
  303. timestamp: parseInt(item.time) * 1000, // 时间
  304. open: parseFloat(item.open), // 开
  305. high: parseFloat(item.high), // 高
  306. low: parseFloat(item.low), // 低
  307. close: parseFloat(item.close), // 收
  308. volume: parseFloat(item.volume) // 交易量
  309. })
  310. })
  311. loading(1)
  312. chart.applyNewData(historyData1.reverse())
  313. }
  314. // console.log(historyData)
  315. },
  316. //请求失败,包含具体的错误信息
  317. error : function(e){
  318. console.log(e.status);
  319. console.log(e.responseText);
  320. }
  321. });
  322. }
  323. constructor() {
  324. this.ws = new WebSocket(wssUrl)
  325. this.currentInterval = null
  326. this.subscribeDataParam = {
  327. interval: null,
  328. setHistoryData: null,
  329. subscribeData: null
  330. } // 再次订阅时需要的数据
  331. }
  332. //______________________________
  333. handleData(msg) { // 处理数据
  334. if (!this.subscribeDataParam.interval) {
  335. console.error("订阅数据参数错误!");
  336. return
  337. }
  338. let data = JSON.parse(msg)
  339. // console.log("响应数据", data);
  340. // console.log(this.subscribeDataParam)
  341. if (data.ping) {
  342. //这里写平台币
  343. // console.log(JSON.stringify({ pong: data.ping }));
  344. this.ws.send(JSON.stringify({ pong: data.ping }));
  345. } else if (data.status === "ok") { // 响应数据 历史数据 | 常规回调
  346. // this.getResData(data)
  347. // console.log("响应数据", data);
  348. // 注意倒序
  349. if (data.data) {
  350. const historyData = []
  351. // console.log(data.data)
  352. data.data && data.data.forEach(item => {
  353. historyData.unshift({
  354. time: item.id * 1000, // 时间
  355. open: item.open, // 开
  356. high: item.high, // 高
  357. low: item.low, // 低
  358. close: item.close, // 收
  359. volume: item.vol // 交易量
  360. })
  361. })
  362. console.log(historyData)
  363. loading(1)
  364. if(chart_type==0){
  365. chart.setPriceVolumePrecision(2,2)
  366. initOnReady1(historyData)
  367. }else{
  368. let historyData1=[]
  369. data.data && data.data.forEach(item => {
  370. historyData1.unshift({
  371. timestamp: item.id * 1000, // 时间
  372. open: item.open, // 开
  373. high: item.high, // 高
  374. low: item.low, // 低
  375. close: item.close, // 收
  376. volume: item.vol // 交易量
  377. })
  378. })
  379. historyData1.reverse()
  380. chart.applyNewData(historyData1)
  381. }
  382. this.subscribeDataParam.setHistoryData(historyData)
  383. } else if (data.unsubbed) { // 取消订阅成功
  384. this.ws.send(JSON.stringify(historyK(this.subscribeDataParam.interval)));
  385. this.ws.send(JSON.stringify(subK(this.subscribeDataParam.interval)));
  386. }
  387. } else { // 实时数据
  388. // this.getResData(data)
  389. console.log(data);
  390. if (data.tick) {
  391. const perData = data.tick
  392. const perData1={
  393. // 开盘价,必要字段
  394. open: perData.open,
  395. // 收盘价,必要字段
  396. close: perData.close,
  397. // 最高价,必要字段
  398. high: perData.high,
  399. // 最低价,必要字段
  400. low: perData.low,
  401. // 成交量,非必须字段
  402. volume: perData.vol,
  403. // 时间戳,毫秒级别,必要字段
  404. // timestamp: perData.id * 1000
  405. timestamp:perData.id * 1000,
  406. }
  407. console.info(perData1)
  408. chart.updateData(perData1);
  409. localStorage.setItem('closeshijian'+SYMBOL,perData.close)
  410. this.subscribeDataParam.subscribeData({
  411. time: perData.id * 1000, // 时间
  412. open: perData.open, // 开
  413. high: perData.high, // 高
  414. low: perData.low, // 低
  415. close: perData.close, // 收
  416. volume: perData.vol // 交易量
  417. })
  418. }
  419. }
  420. }
  421. //————————————————————————————————————————————————————————————————
  422. setHistoryData({ interval, setHistoryData, subscribeData }) {
  423. this.currentInterval = interval
  424. this.ws.onopen = () => {
  425. if(SYMBOL == 'usdzusdt'){
  426. this.ajaxaitc(interval)
  427. let _this = this
  428. window.a = setInterval(function(){
  429. _this.getMarketSpecialtyJsonAitclast(interval)
  430. }, 2000);
  431. }else{
  432. this.ws.send(JSON.stringify(historyK(interval)));
  433. this.ws.send(JSON.stringify(subK(interval)));
  434. }
  435. }
  436. this.subscribeDataParam = {
  437. interval,
  438. setHistoryData,
  439. subscribeData
  440. }
  441. this.ws.onmessage = event => {
  442. let blob = event.data;
  443. const fileReader = new FileReader();
  444. fileReader.onload = e => {
  445. let ploydata = new Uint8Array(e.target.result);
  446. let msg = pako.inflate(ploydata, { to: 'string' });
  447. this.handleData(msg);
  448. };
  449. fileReader.readAsArrayBuffer(blob, "utf-8")
  450. }
  451. }
  452. intervalChanged({ interval, setHistoryData, subscribeData }) {
  453. this.subscribeDataParam = {
  454. interval,
  455. setHistoryData,
  456. subscribeData
  457. }
  458. console.log('重新请求')
  459. if(SYMBOL == 'usdzusdt'){
  460. // console.log(77777)
  461. clearInterval(window.a);
  462. clearInterval(window.b);
  463. let _this=this
  464. window.b= setInterval(function (){
  465. _this.getMarketSpecialtyJsonAitclast(interval)
  466. },2000)
  467. this.ajaxaitc(interval)
  468. }else{
  469. this.ws.send(JSON.stringify(unsubK(this.currentInterval)))
  470. }
  471. // console.log($('#market_new_price'),'html')
  472. this.currentInterval = interval
  473. }
  474. }
  475. window.deedfeeds = new Deedfeeds();