如何为自定义Datafeed的TradingView Widget设置指定日期范围
自定义TradingView图表的起止日期范围
问题原因
你已经尝试用chart.setVisibleRange()设置固定范围,但可能没生效——因为getBars返回了全量数据,TradingView会自动适配数据的完整时间范围,覆盖你设置的初始值;另外,图表初始化后的自动数据请求也可能重置范围。
两步修改实现固定范围
1. 强制锁定图表显示范围
在onChartReady里设置范围后,禁用自动缩放,防止用户或系统自动调整:
widget.onChartReady(function () { var chart = widget.chart(); // 自定义起止日期:注意月份是0基,时间戳转成TradingView要求的秒级 const customFrom = Date.UTC(2018, 7, 1) / 1000; // 2018年8月1日 const customTo = Date.UTC(2020, 1, 1) / 1000; // 2020年2月1日 // 设置显示范围 chart.setVisibleRange({ from: customFrom, to: customTo }); // 禁用自动缩放,锁定范围(可选,防止用户误操作调整) chart.applyOverrides({ "scales.autoscale": false }); });
2. 在Datafeed中过滤数据到指定范围
修改getBars函数,只返回自定义日期范围内的数据,从根源上限制图表的可用数据范围:
getBars: async (symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) => { // 定义你的固定起止日期(秒级时间戳) const customFrom = Date.UTC(2018, 7, 1) / 1000; const customTo = Date.UTC(2020, 1, 1) / 1000; try { // 用symbolInfo.ticker代替全局symbolName,避免变量污染 const data = await GetSnapshotData(symbolInfo.ticker); if (!data || data.length === 0) { onHistoryCallback([], { noData: true }); return; } let bars = []; data.forEach(bar => { const dateString = bar.Date; const year = parseInt(dateString.substr(0, 4)); const month = parseInt(dateString.substr(4, 2)) - 1; const day = parseInt(dateString.substr(6, 2)); const barDate = new Date(year, month, day); // 转成秒级时间戳,和自定义范围对比 const barTimestampSec = barDate.getTime() / 1000; // 只保留自定义范围内的K线 if (barTimestampSec >= customFrom && barTimestampSec < customTo) { let price = bar.Price; const rndVal = 0.85; const basePrice = price; const openNoise = (0.1 - Math.random() * 0.2) + rndVal; const closeNoise = (0.1 - Math.random() * 0.2) + rndVal; const openP = basePrice * openNoise; const closeP = basePrice * closeNoise; const highP = Math.max(basePrice * (0.45 + Math.random() * 0.1), openP, closeP); const lowP = Math.min(basePrice * (1 - Math.random() * 0.1), openP, closeP); bars.push({ time: barDate.getTime(), // TradingView要求K线时间是毫秒级 low: lowP, high: highP, open: openP, close: closeP, volume: bar.Volume }); } }); if (periodParams.firstDataRequest && bars.length > 0) { lastBarsCache.set(symbolInfo.full_name, { ...bars[bars.length - 1] }); } // 如果过滤后无数据,标记noData onHistoryCallback(bars, { noData: bars.length === 0 }); console.log(`[getBars]: 返回${bars.length}条K线`); } catch (error) { console.error('[getBars]: 请求出错', error); onErrorCallback(error); } },
关键注意点
- 时间戳单位:TradingView的
from/to参数是秒级,但K线的time字段需要是毫秒级,转换时别搞混 - 变量正确性:别用全局
symbolName,改用symbolInfo.ticker保证符号匹配 - 无数据处理:过滤后如果没有数据,一定要设置
noData: true,否则图表会显示异常
内容的提问来源于stack exchange,提问作者Sivakumar
相关产品推荐
相关产品推荐

