var tvBlackBgColor = '#f5f5f5' // 黑色背景色 var tvIntervalList = ['1', '5', '15', '30', '60', '240', 'D', 'W'] // 所有周期 var tvIntradayMultipliers = ['1', '5', '15', '30', '60', '240'] // 日内周期 var realtimeFlag = false; var kcCurrentData = {}; var lastBarTime = parseInt(Date.now() / 1000); var loadMoreFlag = false; /** * 一个对象,往上面挂[id]: callback; * id为键,对应一个请求历史数据的请求, * callback是该请求历史数据返回的回调函数, * 且回调函数会延时清理自身过期id callback * { * 1: function(){} * 2: function(){} * } */ var kcHistoryKeyId = 1 // 自增id,本地维护 var kcHistoryCallbackMap = {} var kcSocket = null // websocket 实例 var kcSubscribeId = 3601 // 自增id, 本地维护 var kcChart = null; // 获取当前交易对 如BTC/USDT function getSymbol() { return kcCurrentData.symbol || (kcCurrentData.coinSymbol + '/' + kcCurrentData.baseSymbol) } // 设置可见K线范围 function setKLineVisibleRange(lastBarTime_t, barsCount) { var count = barsCount || 300 // 显示几条k线 var interval = kcCurrentData.interval var to = parseInt(lastBarTime_t) // 历史数据的最后一条柱子的时间 var toNum = 20 // 多显示几条k线距离 var seconds = getSecondsByInterval(interval); // 秒数 var options = { from: to - (seconds * count), to: to, // 可见的结束时间,因为结束时间可能不是当前时间,为了与右边价格刻度有一点距离所以加toNum条柱子的时间 interval: seconds } return options; } // 周期转换为秒 function getSecondsByInterval(interval) { // 周期 ['1', '5', '15', '30', '60', '240', 'D', 'W'] interval = interval || kcCurrentData.interval; var map = { '1': 60, '5': 60 * 5, '15': 60 * 15, '30': 60 * 30, '60': 60 * 60, '240': 60 * 240, 'D': 60 * 60 * 24, 'W': 60 * 60 * 24 * 7 } return map[interval + ''] } function loadMoreKline(data, is_first, key){ if(key == kcHistoryKeyId) { is_first = is_first || false; if (is_first) { kcChart.clearData(); } if (data != null || data != '' || data != undefined) { var dataArr = []; var dataArr_index = 0; $.each(data, function (index, item) { try { if (typeof item == 'string') { item = JSON.parse(item); } dataArr[dataArr_index] = { timestamp: Number(item[0] * 1000), open: Number(item[1]), high: Number(item[3]), low: Number(item[4]), close: Number(item[2]), volume: Number(item[5]) }; // if(kcCurrentData.interval == 'D' || kcCurrentData.interval == 'W') dataArr[dataArr_index].timestamp += 57600000; dataArr_index++; } catch (e) { } }) // console.log(dataArr); // kcHistoryKeyId++; if (dataArr.length <= 0) { kcChart.applyMoreData(dataArr, false); } else { lastBarTime = (dataArr[0].timestamp / 1000) - getSecondsByInterval(); console.log(lastBarTime); kcChart.applyMoreData(dataArr, true); } } } } // $('.interval_btn').on('click', function(){ // console.log('11111'); // if(kcChart != null || kcChart != undefined){ // var _this = $(this); // kcCurrentData.interval = _this.attr('data-interval'); // // 请求历史数据 // kcHistoryKeyId = 1; // var rang = setKLineVisibleRange(parseInt(Date.now() / 1000)); // $.ajax({ // url: "https://dfmg.dficoins.com/api/getkkline", // type: 'get', // async: false, // data: { // symbol: getSymbol(), // interval: getSecondsByInterval(kcCurrentData.interval), // times: kcHistoryKeyId, // from: rang.from, // to: rang.to + (365 * 86400) // }, // beforeSend: function(){ // loading_index = layer.load(1, { // shade: [0.1, '#fff'] //0.1透明度的白色背景 // }); // }, // success:function (result) { //成功回调 // console.log(result); // if(result.status){ // loadMoreKline(result.data, true, result.code); // $('.interval_btn').removeClass('active'); // _this.addClass('active'); // }else{ // } // layer.close(loading_index); // }, // error: function(xhr){ // layer.close(loading_index); // } // }); // } // }) // 初始化tv function initKlineChart() { kcChart = klinecharts.init(kcCurrentData.containerId); kcChart.setTimezone(kcCurrentData.timezone); kcChart.setOffsetRightSpace(20); // 创建一个主图指标 kcChart.createTechnicalIndicator({ name: 'VOL', calcParams: [10], styles: { margin: { top: 0.2, bottom: 2 } } }) kcChart.createTechnicalIndicator({ name: 'MA', shortName: 'MA', calcParams: [10, 20, 30], dragEnabled: true, plots: [ { key: 'ma1', title: 'MA10: ', type: 'line' }, { key: 'ma2', title: 'MA20: ', type: 'line' }, { key: 'ma3', title: 'MA30: ', type: 'line' } ], // 当计算参数改变时,希望提示的和参数一样,即title的值需要改变 regeneratePlots: (params) => { return params.map((p, i) => { return { key: `ma${i + 1}`, title: `MA${p}: `, type: 'line' } }) }, // 计算结果 calcTechnicalIndicator: (kLineDataList, { params, plots }) => { // 注意:返回数据个数需要和kLineDataList的数据个数一致,如果无值,用{}代替即可。 // 计算参数最好取回调参数params,如果不是,后续计算参数发生变化的时候,这里计算不能及时响应 const closeSums = [] return kLineDataList.map((kLineData, i) => { const ma = {} const close = kLineData.close params.forEach((param, j) => { closeSums[j] = (closeSums[j] || 0) + close if (i >= param - 1) { ma[plots[j].key] = closeSums[j] / param closeSums[j] -= dataList[i - (param - 1)].close } }) // 如果有值的情况下,这里每一项的数据格式应该是 { ma1: xxx, ma2: xxx } // 每个key需要和plots中的子项key对应的值一致 return ma }) } }, true, { id: 'candle_pane', dragEnabled: true }); kcChart.setPriceVolumePrecision(kcCurrentData.coinScale, kcCurrentData.volumeScale); kcChart.loadMore(function () { setTimeout(function(){ if(loadMoreFlag) { loadMoreFlag = false; var rang = setKLineVisibleRange(lastBarTime); $.ajax({ url: "https://dfmg.dficoins.com/api/getkkline", type: 'get', async: false, data: { symbol: getSymbol(), interval: getSecondsByInterval(kcCurrentData.interval), times: kcHistoryKeyId, from: rang.from, to: rang.to }, success: function (result) { //成功回调 console.log(result); if (result.status) { loadMoreKline(result.data, false, result.code); loadMoreFlag = true; } else { } } }); } }, kcHistoryKeyId == 1 ? 500 : 10); }) kcChart.setStyleOptions({ // 蜡烛图 candle: { // 提示 tooltip: { // 'always' | 'follow_cross' | 'none' showRule: 'always', // 'standard' | 'rect' showType: 'rect', labels: [ langData[kcCurrentData.language].time, langData[kcCurrentData.language].open, langData[kcCurrentData.language].close, langData[kcCurrentData.language].high, langData[kcCurrentData.language].low, langData[kcCurrentData.language].volume ], values: null, defaultValue: '--', rect: { paddingLeft: 0, paddingRight: 0, paddingTop: 0, paddingBottom: 6, offsetLeft: 8, offsetTop: 20, offsetRight: 8, borderRadius: 4, borderSize: 1, borderColor: '#3f4254', backgroundColor: 'rgba(17, 17, 17, .3)' }, text: { size: 12, family: 'Helvetica Neue', weight: 'normal', color: '#fff', marginLeft: 8, marginTop: 6, marginRight: 8, marginBottom: 0 } } } }); var rang = setKLineVisibleRange(lastBarTime); $.ajax({ url: "https://dfmg.dficoins.com/api/getkkline", type: 'get', async: false, data: { symbol: getSymbol(), interval: getSecondsByInterval(kcCurrentData.interval), times: kcHistoryKeyId, from: rang.from, to: rang.to + (365 * 86400) }, beforeSend: function(){ loading_index = layer.load(1, { shade: [0.1, '#fff'] //0.1透明度的白色背景 }); }, success:function (result) { //成功回调 console.log(result); if(result.status){ loadMoreKline(result.data, true, result.code); loadMoreFlag = true; $('.interval_btn').removeClass('active'); $('.interval_btn[data-interval="' + result.msg + '"]').addClass('active'); }else{ layer.msg(result.msg, {icon: 2}); } layer.close(loading_index); }, error: function(xhr){ layer.close(loading_index); } }); } // 先引入这个JS文件,然后在websocket连接成功后,调用这个方法,启动TradingView /** * 启动 * @param {Object} _ws 已经连接成功的Websocket对象 * @param {Object} _config Tv配置项,计价币种和交易币种必须要传入 */ function kcStart(_config){ // 重要:k线图配置的重要数据,当前k线维护的一份数据,k线切换时,改变周期时都要变对应的值 kcCurrentData = { containerId: _config.containerId, baseSymbol: _config.baseSymbol, // 计价币种 coinSymbol: _config.coinSymbol, // 交易币种 symbol: _config.symbol || '--', coinScale: _config.coinScale || 2, // 计价币种精度 volumeScale: _config.volumeScale || 2, // 成交量精度保留 interval: _config.interval || '15', // 15分钟 bgColor: _config.bgColor || tvBlackBgColor, // 当前选择背景色 language: _config.language || 'en', timezone: _config.timezone || 'Asia/Shanghai' } initKlineChart() }