// localStorage.removeItem("tradingview.chartproperties");
// 在初始化 Highcharts 图表之前清除 TradingView 配置
localStorage.removeItem("tradingview.chartproperties");
// 然后继续初始化 Highcharts 或处理 Datafeed 类
// const datafeed = new Datafeed(vm);
// const chart = Highcharts.stockChart('container', {
// // Highcharts 配置
// });
$(function() {
// Light Theme for Highcharts
let light = {
chart: {
backgroundColor: "#ffffff",
borderColor: "#e6e6e6",
borderWidth: 1
},
title: {
style: {
color: '#333',
fontSize: '16px'
}
},
xAxis: {
gridLineColor: '#dcdee0',
labels: {
style: {
color: '#333',
fontSize: '9px'
}
},
lineColor: '#dcdee0'
},
yAxis: {
gridLineColor: '#dcdee0',
labels: {
style: {
color: '#333',
fontSize: '9px'
}
},
lineColor: '#dcdee0'
},
legend: {
itemStyle: {
color: '#333'
}
},
plotOptions: {
candlestick: {
upColor: '#2EBD85',
downColor: '#F4465D',
borderColor: '#2EBD85',
borderWidth: 1
}
}
};
// Dark Theme for Highcharts
let dark = {
chart: {
backgroundColor: "#2b2b37",
borderColor: "#49495F",
borderWidth: 1
},
title: {
style: {
color: '#fff',
fontSize: '16px'
}
},
xAxis: {
gridLineColor: '#49495F',
labels: {
style: {
color: '#fff',
fontSize: '9px'
}
},
lineColor: '#49495F'
},
yAxis: {
gridLineColor: '#49495F',
labels: {
style: {
color: '#fff',
fontSize: '9px'
}
},
lineColor: '#49495F'
},
legend: {
itemStyle: {
color: '#fff'
}
},
plotOptions: {
candlestick: {
upColor: '#2EBD85',
downColor: '#F4465D',
borderColor: '#2EBD85',
borderWidth: 1
}
}
};
// Final TV Style (light and dark theme options)
let tvStyle = {
light,
dark
};
class Datafeed {
constructor(vm) {
this.self = vm; // 传入的数据和配置
}
// onReady 方法:传递图表支持的配置
onReady(callback) {
// 返回 Highcharts 所需的配置选项
callback({
supported_resolutions: ['1', '5', '15', '30', '60', '240', '1D'],
supports_search: false,
supports_group_request: false
});
}
// resolveSymbol 方法:解析符号,返回图表所需的元数据
resolveSymbol(symbolName, onSymbolResolvedCallback, onResolveErrorCallback) {
// 解析符号(这里只是模拟数据,实际上可能需要连接到外部API来获取详细信息)
const symbolInfo = {
name: symbolName,
description: 'Some stock symbol',
type: 'stock',
timezone: 'America/New_York',
session: '24x7',
minmov: 1, // 最小变动单位
pricescale: 100, // 价格缩放
has_intraday: true, // 是否支持日内数据
has_daily: true, // 是否支持日线数据
};
// 解析完成后回调
onSymbolResolvedCallback(symbolInfo);
}
// getBars 方法:获取数据,转换为 Highcharts K线图所需的格式
getBars(symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback) {
// 模拟获取K线数据的逻辑(从数据源或服务器获取数据)
const bars = []; // 假设这是从你的数据源返回的数据
// 将数据转换为 Highcharts 所需的格式
bars.forEach(bar => {
const chartData = {
x: bar.time, // 时间戳(单位:毫秒)
open: bar.open,
high: bar.high,
low: bar.low,
close: bar.close,
volume: bar.volume
};
onHistoryCallback([chartData], { noData: false });
});
// 错误回调(如果有的话)
onErrorCallback('Some error occurred');
}
subscribeBars(symbolInfo, resolution, onRealtimeCallback) {
const updateInterval = 1000; // 更新频率,例如每秒更新一次
// 伪代码,假设这里每秒钟获取一次数据
setInterval(() => {
// 获取实时的价格数据(实际操作中需要从数据源获取)
const latestBar = getLatestBarFromDataSource(); // 假设这是从服务器获取的数据
// 转换为 Highcharts 格式
const chartData = {
x: latestBar.time,
open: latestBar.open,
high: latestBar.high,
low: latestBar.low,
close: latestBar.close,
volume: latestBar.volume
};
// 调用回调函数,推送数据到 Highcharts
onRealtimeCallback(chartData);
}, updateInterval);
}
// subscribeBars 方法:订阅数据更新
subscribeBars(symbolInfo, resolution, onRealtimeCallback, listenerGUID) {
this.self.subscribeBars(symbolInfo, resolution, (bar) => {
// 转换并推送实时更新的 K线数据
const updatedBar = {
x: bar.time * 1000, // 时间戳转换为毫秒
open: bar.open,
high: bar.high,
low: bar.low,
close: bar.close,
volume: bar.volume || 0
};
onRealtimeCallback(updatedBar);
});
}
// unsubscribeBars 方法:取消订阅数据更新
unsubscribeBars(listenerGUID) {
this.self.unsubscribeBars(listenerGUID);
}
// 默认的符号信息
defaultSymbol() {
return {
'timezone': 'Asia/Shanghai',
'minmov': 1,
'minmov2': 0,
'fractional': true,
'session': '24x7',
'has_intraday': true,
'has_no_volume': false,
'has_daily': true,
'has_weekly_and_monthly': true,
'pricescale': 10000
};
}
}
class Page {
constructor() {
this.datafeed = undefined; // 数据源
this.page = 1;
this.onRealtimeCallback = undefined;
this.TView = undefined;
this.interval = this.getQuery('interval') || '60'; // 默认 60 分钟
this.symbolName = this.getQuery('symbol'); // 从 URL 获取 symbol
this.theme = this.getQuery('theme') || 'dark'; // 默认 dark 主题
this.lang = this.getQuery('lang') || 'en'; // 默认语言
this.resolutions = this.getQuery('resolutions') || ["5", "15", "30", "60", "240", "1D", "1W",
"1M"
];
this.isLoad = false;
this.url = this.getQuery('getLinkUrl'); // 获取链接
this.TVID = "tradingview_10798345"; // TV ID
this.Ws = undefined;
this.msg = '';
this.contract = this.getQuery('contract');
this.init(); // 初始化
this.studies = []; // 配置项
this.tvBars = []; // 数据
}
// 获取路径上的参数
getQuery(name) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name); // 返回 URL 查询参数的值
}
// 初始化
init() {
this.linkSocket();
// 数据模型
this.datafeed = new Datafeed(this);
// 配置图表
this.chart = Highcharts.chart('tradingview_10798345', {
chart: {
type: 'candlestick', // 设置图表类型为 K线图
height: 500,
zoomType: 'x', // 允许水平缩放
events: {
// load: () => {
// this.chart.update({
// tooltip: {
// positioner: function (labelWidth, labelHeight, point) {
// return { x: point.plotX, y: point.plotY };
// }
// }
// });
// }
}
},
title: {
text: null // 不显示标题
},
rangeSelector: {
selected: 1 // 选择默认时间范围
},
time: {
timezone: 'Asia/Shanghai' // 设置时区
},
tooltip: {
split: true,
valueDecimals: 2, // 小数点后2位
valuePrefix: '$' // 显示货币符号
},
navigator: {
enabled: false // 禁用导航器
},
scrollbar: {
enabled: false // 禁用滚动条
},
xAxis: {
type: 'datetime', // X轴显示时间
labels: {
formatter: function () {
return Highcharts.dateFormat('%Y-%m-%d %H:%M', this.value);
}
},
title: {
text: '时间'
}
},
yAxis: {
title: {
text: '价格'
}
},
series: [{
name: 'K线',
data: this.tvBars, // 假设这是通过 Datafeed 获取的 K线数据
type: 'candlestick', // 设置为K线图
tooltip: {
valueDecimals: 2 // 设置价格的精度
}
}],
exporting: {
enabled: false // 禁用导出功能
},
credits: {
enabled: false // 禁用版权信息
},
legend: {
enabled: false // 禁用图例
}
});
// 监听图表上的事件
this.chart.series[0].points.forEach((point, i) => {
point.on('mouseOver', function () {
const time = point.x;
const price = point.open; // 取开盘价或其他价格
console.log('Time:', time, 'Price:', price);
this.showKlineQuoter(time);
});
});
}
// 创建Highcharts图表
createChart() {
console.log('222', this.tvBars);
const chartOptions = {
chart: {
renderTo: 'tradingview_10798345', // 图表容器ID
type: 'candlestick', // 设置图表类型为蜡烛图
backgroundColor: this.theme === 'light' ? '#fff' : '#2b2b37', // 根据主题选择背景颜色
height: 500, // 设置图表高度
events: {
// load: function() {
// const chart = this;
// // 使用 chart 来绑定 mousemove 事件
// chart.container.addEventListener('mousemove', function(event) {
// // 获取鼠标位置的时间戳
// const time = chart.xAxis[0].toValue(event.offsetX);
// const resolutionTime = this
// .getResolutionTime(); // 获取分辨率的时间周期
// const fTime = Math.floor(time / resolutionTime) *
// resolutionTime; // 根据分辨率计算时间
// console.log('fTime', fTime);
// chart.showKlineQuoter(fTime); // 显示对应的K线数据
// });
// }
}
},
title: {
// text: `${this.symbolName} Kline Chart`, // 标题显示symbol名称
style: {
color: this.theme === 'light' ? '#000' : '#fff' // 依据主题设置标题颜色
}
},
subtitle: {
// text: `Interval: ${this.interval}`, // 显示时间间隔
style: {
color: this.theme === 'light' ? '#000' : '#fff' // 依据主题设置副标题颜色
}
},
xAxis: {
type: 'datetime', // 设置x轴为时间格式
labels: {
style: {
color: this.theme === 'light' ? '#000' : '#fff' // 依据主题设置x轴标签颜色
}
}
},
yAxis: {
title: {
text: 'Price', // y轴标题
style: {
color: this.theme === 'light' ? '#000' : '#fff' // 依据主题设置y轴标题颜色
}
},
labels: {
style: {
color: this.theme === 'light' ? '#000' : '#fff' // 依据主题设置y轴标签颜色
}
},
},
series: [{
data: this.tvBars, // K线数据,假设数据格式已适配
// data: [
// [Date.UTC(2025, 2, 1), 100],
// [Date.UTC(2025, 2, 2), 105],
// [Date.UTC(2025, 2, 3), 110]
// ],
type: 'candlestick', // 设置图表类型为蜡烛图
upColor: '#4fff33', // 设置上涨时的颜色
color: '#f00707', // 设置下跌时的颜色
lineColor: '#f00707', // 设置线的颜色
dataGrouping: {
enabled: true, // 启用数据分组
groupPixelWidth: 10 // 每个分组的宽度
}
}],
plotOptions: {
candlestick: {
color: '#f00707', // 下跌时的颜色
upColor: '#4fff33' // 上涨时的颜色
}
},
navigation: {
buttonOptions: {
enabled: false // 禁用导航按钮
}
},
tooltip: {
pointFormatter: function() {
// 格式化鼠标悬停时显示的tooltip内容
return `Time: ${new Date(this.x).toLocaleString()}
Open: ${this.open}
High: ${this.high}
Low: ${this.low}
Close: ${this.close}
`;
}
}
};
// 渲染Highcharts图表
console.log(chartOptions);
Highcharts.stockChart(chartOptions);
}
upsertTvBars(isFirstCall, bars) {
if (isFirstCall) {
this.tvBars = []; // 初始化 tvBars 数组
}
bars.forEach((bar) => {
// 确保不会重复添加时间戳相同的条目
if (this.tvBars.length === 0 || !this.tvBars.find(o => o.time === bar.time)) {
// 将数据转换为 Highcharts K 线图需要的格式:[时间戳, 开盘价, 最高价, 最低价, 收盘价]
const highchartsBar = [
bar.time, // 时间戳
bar.open, // 开盘价
bar.high, // 最高价
bar.low, // 最低价
bar.close // 收盘价
];
this.tvBars.push(highchartsBar);
}
});
// 按照时间戳排序
this.tvBars.sort((a, b) => {
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
return 0;
});
// 更新 Highcharts 图表的数据
this.updateChart();
}
showKlineQuoter(time) {
if (this.tvBars.length === 0) return;
const {
from,
to
} = this.chart.xAxis[0].getExtremes(); // 获取 visible range
const bar = this.tvBars.find(o => o.time === time * 1000); // 查找对应的 bar
if (!bar) return;
const barTime = bar.time / 1000 + 60 * 60 * 8; // 时区调整
const fromSize = barTime - from;
const toSize = to - barTime;
// 更新 TV Quoter 面板
const tvQuoter = $('#tv-quoter');
tvQuoter.css({
visibility: 'visible',
});
// 调整 Quoter 面板的位置
if (fromSize > toSize) {
tvQuoter.css({
left: '10px',
right: 'auto'
});
} else {
tvQuoter.css({
right: '10px',
left: 'auto'
});
}
// 计算涨跌幅
let zhangdiefu = (bar.close - bar.open) / bar.open;
let zhangdiee = bar.close - bar.open;
// 更新 quoter 显示的数据
tvQuoter.find('[data-name="date"]').text(this.timestampToTime(bar.time));
tvQuoter.find('[data-name="date_lang"]').text(this.lang == 'zh-CN' ? '时间' : 'Date');
tvQuoter.find('[data-name="open"]').text(bar.open);
tvQuoter.find('[data-name="open_lang"]').text(this.lang == 'zh-CN' ? '开' : 'Open');
tvQuoter.find('[data-name="high"]').text(bar.high);
tvQuoter.find('[data-name="high_lang"]').text(this.lang == 'zh-CN' ? '高' : 'H');
tvQuoter.find('[data-name="low"]').text(bar.low);
tvQuoter.find('[data-name="low_lang"]').text(this.lang == 'zh-CN' ? '低' : 'L');
tvQuoter.find('[data-name="close"]').text(bar.close);
tvQuoter.find('[data-name="close_lang"]').text(this.lang == 'zh-CN' ? '收' : 'Close');
tvQuoter.find('[data-name="volume"]').text((+bar.volume).toFixed());
tvQuoter.find('[data-name="volume_lang"]').text(this.lang == 'zh-CN' ? '成交量' : 'Executed');
tvQuoter.find('[data-name="zhangdiefu"]').text((zhangdiefu * 100).toFixed(2) + '%');
tvQuoter.find('[data-name="zhangdiefu_lang"]').text(this.lang == 'zh-CN' ? '涨跌幅' : 'Change%');
tvQuoter.find('[data-name="zhangdiefu"]').css('color', zhangdiee > 0 ? '#53b987' : '#eb4d5c');
tvQuoter.find('[data-name="zhangdiee"]').text(zhangdiee.toFixed(4));
tvQuoter.find('[data-name="zhangdiee_lang"]').text(this.lang == 'zh-CN' ? '涨跌额' : 'Change');
tvQuoter.find('[data-name="zhangdiee"]').css('color', zhangdiee > 0 ? '#53b987' : '#eb4d5c');
// Highcharts 更新数据:例如,更新显示的特定点的 hover 信息
let chart = this.chart; // 获取 Highcharts 图表对象
// 查找与给定时间相匹配的点
const point = chart.series[0].data.find(p => p.x === bar.time);
if (point) {
// 更新图表的 tooltip 或者标记
chart.tooltip.refresh(point); // 刷新 tooltip 显示当前点的数据
}
}
timestampToTime(timestamp) {
const date = new Date(timestamp);
const yyyy = `${date.getFullYear()}`;
const yy = `${date.getFullYear()}`.substr(2);
const MM = `0${date.getMonth() + 1}`.slice(-2);
const dd = `0${date.getDate()}`.slice(-2);
const HH = `0${date.getHours()}`.slice(-2);
const mm = `0${date.getMinutes()}`.slice(-2);
// 获取Highcharts的分辨率(假设你已经设置了chart的分辨率)
const resolution = this.TView.chart().resolution();
let dateStr = '';
if (resolution === 'D' || resolution === 'W' || resolution === 'M') {
// 日期格式为 yyyy-MM-dd
dateStr = `${yyyy}-${MM}-${dd}`;
} else {
// 日期格式为 yy-MM-dd HH:mm
dateStr = `${yy}-${MM}-${dd} ${HH}:${mm}`;
}
return dateStr;
}
getResolutionTime() {
const chart = this.TView.chart();
const resolution = chart.resolution(); // 获取图表的分辨率(例如:'1', '5', 'D', 'W'等)
switch (resolution) {
case '1':
return 60; // 1分钟
case '5':
return 5 * 60; // 5分钟
case '10':
return 10 * 60; // 10分钟
case '15':
return 15 * 60; // 15分钟
case '30':
return 30 * 60; // 30分钟
case '60':
return 60 * 60; // 1小时
case '120':
return 120 * 60; // 2小时
case '240':
return 4 * 60 * 60; // 4小时
case 'D':
return 24 * 60 * 60; // 1天
case 'W':
return 7 * 24 * 60 * 60; // 1周
case 'M':
return 4 * 7 * 24 * 60 * 60; // 1月(假设每月4周)
default:
return 1; // 如果分辨率没有匹配项,默认返回1秒
}
}
createStudy() {
let chart = this.TView.chart(); // 获取图表实例
let theme = this.theme; // 获取主题
// 假设你的数据是存储在 `data` 中,这里会为每条移动平均线创建一个新的 `series`
const data = this.data; // 图表的数据
// 计算不同周期的移动平均线
const movingAverage = (data, period) => {
let maData = [];
for (let i = period - 1; i < data.length; i++) {
let sum = 0;
for (let j = i - period + 1; j <= i; j++) {
sum += data[j][1]; // 假设 `data[j][1]` 是价格
}
maData.push([data[i][0], sum / period]); // 将时间戳和均值添加到结果
}
return maData;
};
// 定义三个不同周期的移动平均线
let ma5 = movingAverage(data, 5);
let ma10 = movingAverage(data, 10);
let ma20 = movingAverage(data, 20);
// 创建图表
chart.update({
series: [{
name: 'MA 5',
data: ma5,
type: 'line',
color: theme === "light" ? "#efc149" : 'rgb(238, 218, 154)',
lineWidth: 3
},
{
name: 'MA 10',
data: ma10,
type: 'line',
color: theme === "light" ? "#7fcec0" : 'rgb(123, 201, 187)',
lineWidth: 3
},
{
name: 'MA 20',
data: ma20,
type: 'line',
color: "rgb(194, 148, 247)",
lineWidth: 3
}
]
});
}
// 连接socket并更新Highcharts图表数据
linkSocket() {
// 连接socket
this.Ws = new Ws(this.getQuery('ws'))
this.Ws.on('message', (evt) => {
console.log('111111112');
console.log('Received message:', evt); // 查看 evt 的结构
// 检测ping消息并回应pong
if (evt.cmd === 'ping' || evt.type === 'ping') {
this.Ws.send({
cmd: 'pong'
});
}
console.log('Received message:', evt); // 打印事件内容
// 处理特定的消息
if (evt.sub == this.msg) {
// 假设evt.data是图表数据的更新,按需求处理
const updatedData = this.getMap(evt.data);
console.log('updatedData', updatedData);
// 更新Highcharts图表数据
// this.updateChartData(updatedData);
console.log('123123',updatedData);
this.onRealtimeCallback(this.getMap(updatedData))
}
});
}
// 更新Highcharts图表数据
updateChartData(newData) {
// 假设newData是数组形式的数据,[时间戳, 值]
const series = this.chart.series[0]; // 获取第一个数据系列
// 向图表中添加新的数据点
series.addPoint(newData, true, true); // 参数: 新数据, 是否重新计算坐标轴, 是否移除旧数据点
// 或者更新整个数据系列
// series.setData(newData);
}
// 图表语言映射
chartLang() {
switch (this.lang) {
case "zh-CN":
return 'zh';
case "zh-TW":
return 'zh_TW';
case "tr":
return 'tr';
case "jp":
return 'ja';
case "kor":
return 'ko';
case "de":
return 'de_DE';
case "fra":
return 'fr';
case "it":
return 'it';
case "pt":
return 'pt';
case "spa":
return 'es';
default:
return 'en';
}
}
getMap(data) {
return [
data.id * 1000,
data.close * 1,
data.open * 1,
data.high * 1,
data.low * 1,
data.vol * 1,
];
}
// 获取数据
getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate, onDataCallback, onErrorCallback,
isFirstCall) {
console.log('这里获取数据');
let page = this.page > 3 ? 3 : this.page;
let data = {
symbol: symbolInfo.name,
period: this.resolution(resolution),
form: rangeStartDate,
to: rangeEndDate,
size: page * 200,
zip: 2
};
this.page++;
this.isLoad = true;
this.unSub(); // 取消订阅
// 使用 AJAX 请求获取数据
$.get(this.url, data).then(res => {
// 解压并转换数据为 Highcharts 可用格式
let arr = this.unzip(res.data.data).map(item => {
return this.getMap(item); // 假设 getMap(item) 返回 Highcharts 可识别的格式
});
// 更新数据到 Highcharts 图表
this.upsertTvBars(isFirstCall, arr); // 这里假设你已经在 Highcharts 中设置了图表
onDataCallback(arr); // 调用回调,传递数据
// 更新消息和订阅机制
this.msg = this.createMsg();
this.sub(); // 重新订阅
}).catch(err => {
// 错误回调,返回空数据
onDataCallback([]);
});
}
// 解压并适配 Highcharts 数据格式
unzip(b64Data) {
// 解码 Base64 字符串
let u8 = atob(b64Data);
// 使用 pako 解压
let jiya = pako.inflate(u8);
// 将 Uint8Array 转换为字符串
let str = this.Uint8ArrayToString(jiya);
// 解析为 JSON 格式
let jsonData = JSON.parse(str);
// 假设解压后的数据是一个数组,并且每个数据项包含时间戳和价格值
// 比如 jsonData = [{time: 1625479000000, value: 123}, ...]
// 将数据转换为 Highcharts 可识别的格式 [[timestamp, value], ...]
let highchartsData = jsonData.map(item => {
return [item.time, item.value]; // 假设数据项有 'time' 和 'value' 字段
});
return highchartsData;
}
// 将 Uint8Array 转换为字符串的函数
Uint8ArrayToString(fileData) {
var dataString = "";
for (var i = 0; i < fileData.length; i++) {
dataString += String.fromCharCode(fileData[i]);
}
return dataString;
}
// 将解压后的 JSON 数据适配为 Highcharts 数据格式
unzipAndAdaptToHighcharts(b64Data) {
// 1. 解码 Base64 字符串
let u8 = atob(b64Data);
// 2. 使用 pako 解压 Base64 字符串
let jiya = pako.inflate(u8);
// 3. 将解压后的 Uint8Array 转换为字符串
let str = this.Uint8ArrayToString(jiya);
// 4. 解析 JSON 数据
let jsonData = JSON.parse(str);
// 5. 假设解压后的数据格式为 [{time: timestamp, value: dataValue}, ...]
// 6. 转换为 Highcharts 支持的数据格式 [[timestamp, value], ...]
let highchartsData = jsonData.map(item => {
return [item.time, item.value]; // 假设每个数据项有 'time' 和 'value' 字段
});
return highchartsData;
}
// 获取传给后台的精度
resolution(resolution) {
let T = "";
if (isNaN(resolution * 1)) {
T = resolution
.replace("D", "day")
.replace("W", "week")
.replace("M", "mon");
} else {
if (resolution > 60) {
T = Math.floor(resolution / 60) + "hour";
} else {
T = resolution + "min";
}
}
return T;
}
// 获取推送回调,适配为 Highcharts 数据更新机制
subscribeBars(symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) {
this.onRealtimeCallback = onRealtimeCallback;
if (!this.symbolName) {
setTimeout(() => {
// 在Highcharts中实现数据更新机制,这里模拟重新加载数据
onResetCacheNeededCallback();
}, 100);
}
// 假设我们通过某种方式获取到新的数据,比如通过API或WebSocket
// 这个地方模拟新的数据推送
const newData = [
// 这里的数据是模拟的,格式为 [timestamp, value]
[Date.now(), Math.random() * 100], // 时间戳和随机值
];
// 更新 Highcharts 图表的数据
if (this.chart) {
// 假设 chart 是 Highcharts 的实例
this.chart.series[0].addPoint(newData[0], true, true); // 添加新数据点
}
// 使用 onRealtimeCallback 更新图表数据
if (onRealtimeCallback) {
onRealtimeCallback(newData);
}
}
// 生成符号的名称,处理为小写
getSymbol(name) {
return name.split("/").join("").toLowerCase();
}
// 生成订阅消息的内容
createMsg() {
if (this.contract) {
return `swapKline_${this.symbolName}_${this.resolution(this.interval)}`;
} else {
return `Kline_${this.getSymbol(this.symbolName)}_${this.resolution(this.interval)}`;
}
}
// 解析时间粒度
resolution(resolution) {
let T = "";
if (isNaN(resolution * 1)) {
T = resolution.replace("D", "day").replace("W", "week").replace("M", "mon");
} else {
if (resolution > 60) {
T = Math.floor(resolution / 60) + "hour";
} else {
T = resolution + "min";
}
}
return T;
}
// 订阅消息,推送给 WebSocket
sub() {
console.log('订阅消息:', this.msg);
this.Ws.send({
cmd: "sub",
msg: this.msg
});
}
// 取消订阅
unSub() {
if (!this.msg) return;
this.Ws.send({
cmd: "unsub",
msg: this.msg
});
}
}
new Page()
})