K线和深度图的实现

K线和深度图在股票及数字货币交易中到处可见,然而这个K线和深度图的实现,如果没有真实写过一次,对里面的一些坑还是有可能避免不了。最近由于我们的产品中开发了一个云算力合约的交易K线,所以我也实现了一个简单的K线图和深度图。

K线长下面这样:
image

要实现一个K线,首先要知道K线是什么,K线由于长得就像一根根蜡烛,所以又被称为蜡烛图,是用来反映价格走势的一种图表。K线可以按照不同的周期进行划分,例如15分钟、1小时、1天等等,它的每一根“蜡烛”反映的是那个周期内的开盘价、收盘价、最高价和最低价,而底部还会有一个成交量。

image

K线的开盘价,就是“蜡烛”矩形的底边或者顶边,收盘价就是另外一边,绘制时,先绘制开盘价,如果收盘价高于开盘价,那么就绘制在开盘价上方,整个矩形的颜色是绿色(假设绿涨红跌),反之,则这个周期内是跌的,则会绘制成红色。

每根蜡烛,还会有一根细线贯穿,这根就叫“引线”,引线顶端代表该周期的最高价,底端代表着最低价,这根引线反应了这个周期内的价格震动幅度。

一根根蜡烛排列起来,就能看到价格的走势,一眼就可以看出是涨是跌,同时也能看住单个周期内的涨跌情况。一般除了蜡烛之外,还有一些其它指标,如MACD,KDJ等。这里讨论比较常见的MACD,也即平滑异同移动均线,它是采用每个周期的收盘价,做一个平均值,有MA7、MA30等不同周期长度的平均值,一般绘制K线的组件已经提供了该功能,只要填入数据,它将自动计算该周期及前六个周期的收盘价平均值,如果不满七个周期,那么则不计算。

K线图的实现

K线图要实现快速的加载,必须要添加缓存,否则每次都是用成交单据实时计算,则非常耗时。对于我们上面提到的单根蜡烛的数据,我们要将它按不同的周期存起来。以15分钟的为例,每根K线,是一个数据项。

1
2
3
4
[
  [time1, open1, high1, low1, close1],
  [time2, open2, high2, low2, close2]
]

拉取K线数据时优先从缓存中取,如果缓存中取不到,那么则从DB中根据过往的成交记录生成,然后存储到缓存中,以备下次使用,一般来说,首次加载是比较耗时的,因为这个时候所有K线数据都还没有。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
points = []
r = redis_store.hmget(market_type + '_hash_trade_kline_' + period_type, keys)
for index, value in enumerate(r):
   t = int(keys[index])
   is_cache = ((index + 1) != len(r))
   if not value:
       v = get_kline_point(market_type, period_type, t, t + interval)
       if v[5] == 0:
           if not last_v:
               continue
           last_close = last_v[4]
           v[1] = last_close # open
           v[2] = last_close # high
           v[3] = last_close # low
           v[4] = last_close # close
       if is_cache: // 防至缓存
           redis_store.hset(market_type + '_hash_trade_kline_' + period_type, t, json.dumps(v))
   else:
       v = json.loads(value) // 直接读取缓存
   points.append(v)
   last_v = v
return points

值得一提的是,如果当前周期没有成交,那怎么办?如果没有成交,那么开盘价、收盘价、最高价、最低价要以昨日的收盘价为准,这样才能保证K线是平滑变化的,而不会因为这个周期没有成交量,而导致K线断开,或者突然跌到0。

K线的绘制

K线是在前端进行绘制的,通过highlight或者Trading View等一些专业的K线绘制工具,就能将K线数据绘制出来了,一般只要配置组件的参数,将请求得到的数据放入即可,另外,MA7、MA30等一些指标,组件也可以自动根据历史数据计算出来。

MA7,即过往七个周期的收盘价格的移动平均值,依此类推,MA30,就是30个周期的收盘价格的移动平均值。所谓移动,就是说随着周期往前移动,进入一个最新数据,就会剔除一个最老数据,类似一个队列一样。MA值能够反映价格的变化趋势,是人们判断价格走势的常用工具。虽然无需我们自己计算,但我们不妨看看它们的计算公式:

image

深度图

对于用户的挂单,我们往往要展示一个深度图。深度图展示的是买卖单的价格及数量情况,通过对比买盘和买盘,我们就知道是买盘强劲还是买盘强劲,以及交易的活跃程度。

image

如上图的深度图,展示了各个价格的买卖量,然后根据买卖数量,来绘制红色区块和绿色区块的长度。这个长度是由两个因素决定的,一个是该档价格的累计委托量,这个累计委托量的意思就是,这个量是所有上的数量一直加下来累加的,而不仅仅是这档价格的量,它将作为分子,另外一个是所有委买或者委卖的量里面的最大值。比如,价格为0.0043这档,买入合计529.44,而总体的买入合计为1739,总体卖出为7867。则这一个块的绿色部分长度就是 529.44 / 7867 * 方块最大长度。我们可以看到上图右侧的卖出合计比较大,所以它的红色色块会长一点。

结语

很多经验,自己不试一次,还真就不知道K线是这样绘制出来的,而这也仅仅只是金融图表的最简单的一种,金融领域还有很多指标可以用来反映价格和市场的变化,如果能够掌握它们,用来帮助自己或者用户来把握趋势,都是意义的事情。