前言
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
。