You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 09:15:07