初识tradingview
前言
tradingview
,以下简称tv
。
公司最近决定使用tv
作为交易图表,过去我们使用过echarts
、higtcharts
作为交易的图表,过去工作中没有接触过货币交易的领域,所以从来没有听说过tv
,但是现在需要使用了,便开始tv
的学习。
tradingview
是一个怎样的图表库?
这是一个专业的图表库,很多行业的大厂都使用了这个图标库,专门做K线图,虽然ECharts等也支持基本的k线图,但长期发展肯定还是使用专业的图表更利于后期的拓展。
tv官网上有三种版本:
- 轻量图表可以直接前往
github
下载。 - 技术分析图表需向官方提交一些必要的信息,然后可以获取到访问权限。
- 图表&交易平台版本我没有试过,估计需要购买才可以使用。
从名字上也可以看出来它们是越来越强大的,因为目前我只使用了k线
,感觉到第二种与第三种的区别在于第三种有交易终端可以使用,是tv
自带的一套交易。
虽然tv
非常强大,但是文档的质量非常一般,看上去方方面面都覆盖到了,但字里行间充斥着大量晦涩难懂的概念,对参数的注解也是残缺不齐,很多操作上的细节都没有提到,阅读体验非常糟糕,加上百度上关于这方面的实例非常少,没有对应的社区,各种群里也都是些新手,大佬们平时很少发话。
我看了文档后,还是一脸懵逼,完全不知道是怎么回事,到github
上寻找别人的实例,加群看别人的demo
,捣鼓了一番,终于把基础的图表功能弄出来了。
基础概念
一般情况下,图表库包含:图例(Legend)
、价格刻度(PriceSeries)
、时间刻度(TmeScale)
、头部工具(Header Tools)
、绘图工具(Drawing Tools)
、版权(Credits)
等。
tv
中有很多专业词汇,这里简单说明一下。
k线
大佬们肯定熟悉不过了,但是对于从来没有接触过这行的人来说,还是有些陌生,以1分钟
的k线
来说,其实每秒钟传过来的数据里时间都是一样的,直到下一分钟,有开
,收
,高
,低
以及交易量
这几个,具体的展示tv
都帮我们做了,我们只需要安装它规定的格式给它就好,每一条数据的格式如下:
{
time: xxx,
open: xxx,
high: xxx,
low: xxx,
close: xxx,
volume: xxx,
}
Symbol
Symbol
直译过来叫象征、符号
,这里引申为商品
。K线
表现的是价格的变化趋势,至于是什么东西的价格,可以是股票,可以是货币,也可以是任何一样商品,TradingView
为了通用,提供了这么一个抽象的概念。
一个Symbol
就是一个JS对象
,描述了商品的一些属性(名称、价格小数位、支持的时间分辨率、交易开放时间等,具体请参考官方文档),图表库会根据Symbol
的定义,来决定改获取怎样的数据。
商品名称的固定格式为EXCHANGE:SYMBOL
,SYMBOL
代表商品,例如一支股票、一个交易对;EXCHANGE
是交易所的名称,同一商品在不同交易所可能会有不同的价格,因此需要进行区分。
Resolution
Resolution
直译过来叫分辨率
,这里指K线
图中相邻两条柱子之间的时间间隔
Study
Study
直译过来叫学习、研究
,这里解释为指标
,例如成交量、均线,以及其他各种分析指标。
Chart
图表本体,特指K线图
及相关的各项指标,不包含工具栏。一个图表实例可以包含多个指标
Widget
小部件,和Android
上的Widget
类似。Widget
可以看做是一个容器,主要是一些工具栏,以及留给绘制真正图表的一块区域,不含图表本体。一个Widget
可以包含多个图表实例
FeatureSet
功能集,Widget
配置选项中的一部分,用于定制图表库的一些功能(包括显示与否、样式)。
Overrides
覆盖,Widget
配置选项中的一部分,用于定制图表库的样式(主要是图表各部分的颜色)。整个图表库由外层DOM
结构和内部多个canvas
组成,因此样式相关的设置也分为两部分,这里是用于canvas
部分的设置,另外还有一个custom_css_url
属性用于指定一个css
文件,其中可以覆盖DOM
部分的样式。
DataFeed
数据源,也就是接下来要讲的东西。它是TradingView
获取、处理数据的方法集合,也是TradingView
数据接入的核心所在,需要用户自己实现。它可以是一个Class
的实例,也可以就是一个简单的对象。
开始使用
有2种方式传给tv
数据,一个是udf
,一个是jsApi
,这个一般看过一遍文档的都能了解到,没看过文档的可以先去了解下:传送门。
udf
是tv
已经帮你封装好的一种方式,如果需要修改可以去udf文件夹下的文件,是ts写的,因为我也没用过,就不过多说了。- jsApi主要使用的是
onReady
、resolveSymbol
、getBars
、subscribeBars
、unsubscribeBars
这5个方法。
因为我也是从零开始的tv,深知新手在刚开始tv时的困境,我尽量说说我的思路,然后下面会将每一个函数主要是做什么事情,如果看不懂,可以先看了下面的,再回头看下这个思路。
- 首先,使用
new TradingView.widget(xx)
创建tv
,其中xx
为一个对象,里面包含了tv
的很多属性。 - 其中,有一个
datafeed
属性,我们需要创建一个class
或者简单对象传给它。 - 新建一个
class
,或者简单对象,里面放入几个方法,就是jsapi
里面的方法,这些方法不需要我们手动去调用,tv
自己会在它的创建过程中去调用它(这点是比较迷惑初学者的,以为要调用,其实只需要写了这样的一个方法就行了。)。- 添加一个
onReady
方法,在里面异步返回图表的一些配置。 - 添加一个
resolveSymbol
方法,异步返回商品的一些配置。 - 添加一个
getBars
方法,这个方法主要是用来传递历史数据的,将历史数据丢给它的第5个回调参数onHistoryCallback
。 - 添加一个
subscribeBars
方法,将实时数据丢给它的第3个回调参数onRealtimeCallback
。 - 添加一个
unsubscribeBars
方法,主要是取消订阅,应该是使用tv
自带的币种切换用来取消币种的订阅,因为我们设计图切换产品是在图表外面,所以我实际只是用这个方法停止websocket
连接。
- 添加一个
getBars
这个接口专门用于获取历史数据,即当前时刻之前的数据。TradingView
会根据 Resolution
从当前时刻开始往前划定一个时间范围,尝试获取这个时间范围内,指定Symbol
指定Resolution
的数据。出于性能考虑,TradingView
只获取可见范围内的数据,超出可见范围的数据会随着图表的拖拽、缩放而分段延迟加载。这个接口中的from
,to
就是这次需要的历史数据时间范围,可以自行根据时间去请求后台的数据,一般一分钟的第一次的请求是一天,即1440
条数据,如果数据不足tv
会一直去调用这个getbars
直到图表铺满,你也可以传入noData
停止请求。
getBars (symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) {
function _send (data) {
// 按时间筛选
const dataInRange = data.length ? data.filter(n => n.time >= from && n.time <= to) : []
// 没有数据就返回 noData
const meta = {
noData: !dataInRange.length
}
// 有数据,则整理成图表库要求的格式
const bar = [...dataInRange]
// 触发回调
onHistoryCallback(bar, meta)
}
}
subscribeBars
这个函数对每个Symbol + Resolution
的组合都会调用一次,所以我们可以维护一个数组对象,用于保存每一个订阅者的信息和回调函数,当推送数据到达时,遍历订阅列表,找到符合条件的订阅者,调用其回调函数传递数据。如果你没有多个订阅的话,其实可以不用理会,直接有数据就处理好,丢给它的第三个参数onRealtimeCallback
。
事实上,这个函数只是增加一个订阅者,你可以在任意你实时获取到数据的地方将数据丢入回调函数onRealtimeCallback
里。
subscribeBars (symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) {
// 限制单例
window.kChartSubscriberList = window.kChartSubscriberList || []
// 避免重复订阅
const found = window.kChartSubscriberList.some(n => n.uid === subscriberUID)
if (found) return
// 添加订阅
window.kChartSubscriberList.push({
symbol: symbolInfo,
resolution: resolution,
uid: subscriberUID,
callback: onRealtimeCallback
})
}
unsubscribeBars
这个就好理解了,当触发这个方法的时候,说明这个不订阅了,所以应该将它从我们维护的数组对象里面删除。
unsubscribeBars (subscriberUID) {
window.kChartSubscriberList = window.kChartSubscriberList || []
const idx = window.kChartSubscriberList.findIndex(n => n.uid === subscriberUID)
if (idx < 0) return
window.kChartSubscriberList.splice(idx, 1)
}
附录
后记
我接触tv
时间也不是很长,很多都只是自己的一些理解,不一定正确,大家互相交流。
有不理解的也可以在下面评论,我会尽能力解答的。
我没有直接大段代码的丢上来,把一些概念放上去,希望授人以渔。
如果有需要demo
的,大家可以加一些群,里面有很多大佬分享的demo
。