资源加载中... loading...

商品期货量能足迹图footprint chart分析与实现

Author: 扫地僧, Created: 2020-03-20 17:18:29, Updated: 2023-12-06 09:36:26

img

一、摘要

量能足迹图是一种高级图表分析工具,英文名称为“Footprint Charts”。它显示的是单个 K 线中每一个价格的交易活动,除了提供价格信息外,还提供交易量、主动买入、主动卖出等信息。它是一种多维的技术图表,揭示了以成交量为依据每个价格真实的分布比例,解释了成交量、价格和时间之间的复杂关系,可以为交易者提供更多的参考依据。

二、什么是量能足迹图

简单的说,量能足迹通过对买卖双方在各种价格水平下发生的情况进行微观分析,从而提供了市场透明度。在量能足迹图图中看到了什么:

  • K 线价格
  • 主动买入交易量(ASK)
  • 主动卖出交易量(BID)
  • 买卖均衡比例

img

如上图所示,这是在优宽量化交易平台(youquant.com)实现的量能足迹图演示版,基于真实的 Tick 行情来计算,详细的数据都附加在 K 线上,当鼠标悬停在 K 线上时,即可呈现量能足迹数据。蓝色方块中的数据就是其计算结果,总共分为两列,左边一列是当前 K 线所有的价格点位,依次由大到小向上排列。右边一列就是每个价格水平的交易量,细分为买入交易量和卖出交易量,并用“x”分隔。在“x”的左边是主动买入的成交量,在“x”的右边就是主动卖出的成交量。

三、量能足迹图的作用

细想一下是什么导致了价格上涨?答案很简单…买卖双方。如果买家多于卖家,价格将会上涨;如果卖家多于买家,价格将会下跌。假如当前卖家数量约等于买价数量,那么市场将会出现震荡走势,即市场处于平衡状态。一旦大买家或卖家出现,就会打破这种平衡,那么在能量足迹图就会呈现出极端的主动买入卖出比例。

能量足迹是根据 Tick 数据动态显示,因此特别适用于日内短线交易。交易者可以准确看到每个价格上的主动买卖交易量,以解释价格波动的原因或规律,并定制自己的交易策略。比如:如果左边的买量比右边的卖量大得多,就意味着市场参与者在积极买入,未来价格可能会上涨;反之如果右边的卖量比左边的买量大得多,就意味着市场参与者在积极卖出,未来价格可能会下跌。

四、量能足迹图原理

量能足迹图的计算原理来自于成交量和盘口数据,根据盘口价格变动实时计算当前成交量,如果盘口价格上涨,那么就把成交量记为主动买入;如果盘口价格下跌,那么就把成交量记为主动卖出。在优宽量化的能量足迹图中,会实时计算Tick数据,精确计算到每个Tick的成交量。

五、量能足迹图代码实现

/*backtest
start: 2020-03-10 00:00:00
end: 2020-03-10 23:59:00
period: 1h
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
mode: 1
*/

var NewFuturesTradeFilter = function (period) {
    var self = {} // 创建一个对象
    self.c = Chart({ // 创建Chart图表
        tooltip: {
            xDateFormat: '%Y-%m-%d %H:%M:%S, %A',
            pointFormat: '{point.tips}'
        },
        series: [{
            name: exchange.GetName(),
            type: 'candlestick',
            data: []
        }]
    })
    self.c.reset() // 清空图表数据
    self.pre = null // 用于记录上一个数据
    self.records = []
    self.feed = function (ticker) {
        if (!self.pre) { // 如果上一个数据不为真
            self.pre = ticker // 赋值为最新数据
        }
        var action = '' // 标记为空字符串
        Log('ticker', ticker)
        Log('pre', self.pre)
        if (ticker.Last >= self.pre.Sell) { // 如果最新数据的最后价格大于等于上一个数据的卖价
            action = 'buy' // 标记为buy
        } else if (ticker.Last <= self.pre.Buy) { // 如果最新数据的最后价格小于等于上一个数据的买价
            action = 'sell' // 标记为sell
        } else {
            if (ticker.Last >= ticker.Sell) { // 如果最新数据的最后价格大于等于最新数据的卖价
                action = 'buy' // 标记为buy
            } else if (ticker.Last <= ticker.Buy) { // 如果最新数据的最后价格小于等于最新数据的买价
                action = 'sell' // 标记为sell
            } else {
                action = 'both' // 标记为both
            }
        }
        // reset volume
        if (ticker.Volume < self.pre.Volume) { // 如果最新数据的成交量小于上一个数据的成交量
            self.pre.Volume = 0 // 把上一个数据的成交量赋值为0
        }
        var amount = ticker.Volume - self.pre.Volume // 最新数据的成交量减去上一个数据的成交量
        if (action != '' && amount > 0) { // 如果标记不为空字符串,并且action大于0
            var epoch = parseInt(ticker.Time / period) * period // 计算K线时间戳并取整
            var bar = null
            var pos = undefined
            if (
                self.records.length == 0 || // 如果K线长度为0或者最后一根K线时间戳小于epoch
                self.records[self.records.length - 1].time < epoch
            ) {
                bar = {
                    time: epoch,
                    data: {},
                    open: ticker.Last,
                    high: ticker.Last,
                    low: ticker.Last,
                    close: ticker.Last
                } // 把最新的数据赋值给bar
                self.records.push(bar) // 把bar添加到records数组中
            } else { // 重新给bar赋值
                bar = self.records[self.records.length - 1] // 上一个数据最后一根K线
                bar.high = Math.max(bar.high, ticker.Last) // 上一个数据最后一根K线的最高价与最新数据最后价格的最大值
                bar.low = Math.min(bar.low, ticker.Last) // 上一个数据最后一根K线的最低价与最新数据最后价格的最小值
                bar.close = ticker.Last // 最新数据的最后价格
                pos = -1
            }
            if (typeof bar.data[ticker.Last] === 'undefined') { // 如果数据为空
                bar.data[ticker.Last] = { // 重新赋值
                    buy: 0,
                    sell: 0
                }
            }
            if (action == 'both') { // 如果标记等于both
                bar.data[ticker.Last]['buy'] += amount // buy累加
                bar.data[ticker.Last]['sell'] += amount // sell累加
            } else {
                bar.data[ticker.Last][action] += amount // 标记累加
            }
            var tips = ''
            Object.keys(bar.data) // 将对象里的键放到一个数组中
                .sort() // 排序
                .reverse() // 颠倒数组中的顺序
                .forEach(function (p) { // 遍历数组
                    tips += '<br>' + p + ' ' + bar.data[p].sell + 'x' + bar.data[p].buy
                })
            self.c.add( // 添加数据
                0, {
                    x: bar.time,
                    open: bar.open,
                    high: bar.high,
                    low: bar.low,
                    close: bar.close,
                    tips: tips
                },
                pos
            )
        }
        self.pre = ticker // 重新赋值
    }
    return self // 返回对象
}


// 程序入口
function main() {
    Log(_C(exchange.SetContractType, 'MA888')) // 订阅数据
    var filt = NewFuturesTradeFilter(60000) // 创建一个对象
    while (true) { // 进入循环模式
        var ticker = exchange.GetTicker() // 获取交易所Tick数据
        if (ticker) { // 如果成功获取到Tick数据
            filt.feed(ticker) // 开始处理数据
        }
    }
}

六、量能足迹图代码下载

量能足迹图footprint chart策略代码已经发布到优宽量化平台的策略广场,普通用户无需设置即可使用。 https://www.youquant.com/strategy/189965

七、总结

在实际使用中,能量足迹图也可以从成交量的角度分析资金流向,无论是分析大级别趋势方向还是分析日内短期方向,都起着至关重要的作用。但需要注意的是,这里所谓的资金流向并不是指资金的进场和离场,而是反应市场多空的买卖意愿和主力与散户的博弈行为。


相关内容

更多内容

zhaosunday 有点意思