TradingView + WebSocket K-line real-time push off pit Guide

This article is reproduced in: Ape 2048 Website ➝ https://www.mk2048.com/blog/blog.php?id=hik0hihjaa

[Starting on my personal blog ]

0. turned out to be more a reminder

Two days ago the company leaders actually mentioned my blog that I recently lazy, do not update ......

Take advantage of the holiday, and quickly update a ...... and so on, when it becomes a job?

1. TradingView is Gesha

Today we say a special feature - TradingView , which is a professional charting library devoted exclusively to the K line graph, line graph and K is stocks, funds and other exchange essential thing. The project itself is free, but not open source, hosted on the official Github's private library, developers only need to submit the necessary information to the official, you can get access to. Main warehouse contains the library files compressed, and simple data access cases; Wiki provides development documents, while also providing other warehouses in some cases to get started.

Several commonly used front-end chart library, like ECharts, DataV actually draw support basic K-line diagram (some called a candle, a different name for it), with bar charts and line charts, but also to draw volume, MA and other indicators. TradingView As a professional industry products, in addition to these charts mentioned earlier, also provides a number of specialized measurement tools for professional investors and analysts use these all have to go with if implemented by the developer, will need spend a lot of energy, this package packaged program, it is undoubtedly the most attractive place.

Recently the company a project in progress is the exchange of a digital asset, competing products research when he found that almost without exception colleagues have opted for this chart library, even the fire coins, FCoin industry benchmark level of large factory have opted for this chart library, visible among its authority in the industry, as well as a near monopoly. Precisely because of this, we have also begun to study it.

2. Professional === trouble

Professional go professional, but this is something for the specific needs of a particular industry development, there are a lot of professional concepts, terminology, practices, we did not know, she was now learning. Although the official form provided in Github Wiki in the document, but the quality of the document is very general, it seems to cover every aspect, but between the lines filled with a lot of obscure concept, annotate parameters is incomplete missing, many operations details are not mentioned, the reading experience is very bad. Although the project's official website offers Chinese options, charting library itself also supports multiple languages, but the document is only in English (although me personally, the language does not in itself constitute pressure; but if you need, here there is a sort of Chinese people version, also includes video tutorials based on UDF program, authors from TradingView project team, is a veteran developer. in order to facilitate the explanation, some figures here will use them, thanks to authors ).

Compared ECharts, DataV that everything is ready, just fill in the data, with the parameters of "commercial grade" chart library, difficult to get started TradingView to be a lot higher, it requires developers to develop in accordance with its rules, to achieve their own set of data sources API, although the official API for each role, the parameters are given instructions, but some of the key points and did not explain clearly, many developers (including me, some colleagues and I have come across) or not after reading the document good understanding "this tm in the end how to use." Writing this blog, I am hoping to make some contribution to solve this problem, so that newcomers can be easier.

3. In order to save time

I will note that this blog does not taught you step by step to build out the entire thing. I assume you at least the official document is to read it again, and have a preliminary attempts, have problems, turn to search engines, and then came here.

This blog is more like a FAQ, based on my own experiences stepped pit, put some of the more difficult to understand things, according to my personal understanding to share with you.

So if you can count on this blog so you do not go to the official documentation will be able to fully grasp TradingView, easily the K line drawn, then I'm sorry, let you down.

4. Let me talk about the concept

TradingView there are some of the more specialized concept, not very easy to understand, but very important, here briefly explain.

4.1. Symbol

Symbol literal translation is "a symbol, a symbol", where the idea was "commodity." K-line performance is the trend of prices, as the price of something, you can stock, can be monetary, it can be like any commodity, TradingView for GM, provides such an abstract concept. A Symbol is a JS object that describes some of the attributes (name, price decimal places, time resolution support, transaction opening hours. Please refer to the official documentation) of goods, charting library based on the definition of Symbol, decided to change to get What kind of data.

Fixed format is the trade name "EXCHANGE: SYMBOL", SYMBOL behalf of goods, such as a stock, a transaction; EXCHANGE is the name of the exchange, the same product may have different prices at different exchanges, it is necessary to distinguish.

4.2. Resolution

Resolution literal translation is called "resolution" here refers to the time interval between two adjacent columns K line graph, I have not studied the terminology is not is use of the word, but personally feel this is a way of saying, you use different words can express the idea, but TradingView chose this word.

4.3. Study

Study literal translation is "learning, research", here interpreted as "targets", such as volume, moving averages, and various other analytical indicators. Developers can add their own through the API TradingView provided.

4.4. Chart

Chart body, especially the K-line diagram and related indicators, does not include the toolbar. A graph showing an example may comprise a plurality of indicators

4.5. Widget

Widget, and a concept of Widget Android. Chart component itself can be seen as a container, mainly because some toolbar, and draw an area reserved for real chart, the chart does not contain a body. It may comprise a plurality of widget instance graph showing an example

4.6. FeatureSet

Feature sets, Widget part of the configuration options for some functions to customize the chart library (including the display or not, style).

4.7. Overrides

Cover, Widget part of the configuration options for customizing the chart style library (mainly the color of each part of the graph). DOM entire chart library consists of an outer layer and an inner structure composed of a plurality of canvas, the style-related settings are also divided into two parts, where part of the canvas is provided for, in addition to a custom_css_urlproperty is used to specify a file css, which may be covered DOM style section. Specific can be combined with official documents, as well as Chrome DevTool to locate.

4.8. DataFeed

Data source, that is, talk about the next thing. It is TradingView acquisition, processing data collection, but also access data at the heart of TradingView, require the user to achieve. It may be an instance of a Class may be that a simple object.

5. How to access its own data

Create a database instance chart is not difficult to read the document and to use case should be able to understand, the difficulty lies in how the data to fill in. I believe the vast majority of TradingView headache friends are stuck in here, as long as the data is turned on, and the rest are minor problems.

TradingView the best generic that it did and performance data separation, charting library itself provides only part of the performance, no matter what kind of data you have, as long as organized into a specified format to fill in, on the line. To put it plainly, a need for developers to implement their own adapter.

TradingView provides two ways to get data, HTTP scheme (UDF, Universal Data Feed, presentation case is to use the main repository of this kind) based WebSocket-based programs (JS API).

udf_or_jsapi

No matter which program uses it in terms of the data it can be divided into two parts: To date historical data, and the data after the new generation.

5.1. UDF program

perform
UDF is TradingView own custom set of protocols. Essentially actually called JS API. Protocol is based on HTTP + polling request to query historical data under the specified conditions through HTTP, and then continuously polls to check for new data.

This program is very simple, the front part has been defined, just follow the demo code access interface case provided on it (the demo code is written TypeScript, there is a little extra cognitive costs, but not a big problem) the main work is the back end, it is necessary to provide the appropriate query interface in accordance with the requirements, the core of which is to obtain a specified commodity, specify the resolution, data range of the specified time, the specific format can refer to the official documentation. Here we have not carried out.

Polling - we know that is a very valid but not recommended practice (unless the environment does not support WebSocket, it would only use it), because very often fail to get the new data, very wasteful performance. Our hope is that whenever new data arrives, we can take the initiative to inform, which also leads to the following scheme.

5.2. JS API

JSAPI
This is the core TradingView data access, you can access any type of data through this API developer, of course, the most common or WebSocket. UDF said before the program actually calls these API.

Official documentation of each API are described, which are essential onReady(), , resolveSymbol(), getBars(), subscribeBars(), unsubscribeBars()and the rest according to their own needs to achieve, where we just say the most basic use. The first two no difficulty, we focused look at the back of a few. (Here we have an example in the form of DataFeed class method to achieve, you can simply create JS object that contains these functions)

5.2.1. getBars ()

This interface is designed to obtain historical data, that is data before the current time. According to Resolution TradingView will begin to move forward from the current time designate a time, trying to get in this time range, specify the Symbol Resolution specified data. For performance reasons, TradingView acquiring data only in the visible range, beyond the visible range of the data as will drag the chart, scaling segment lazy loading.

This part of the code to achieve more, we step by step, to be implemented inside a function to send data:

getBars (symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) {
  function _send (data) {
    // 按时间筛选
    const dataInRange = data.length
      ? data.filter(n => n.time >= ensureMilliseconds(from) && n.time <= ensureMilliseconds(to))
      : []

    // 没有数据就返回 noData
    const meta = {
      noData: !dataInRange.length
    }

    // 有数据,则整理成图表库要求的格式
    const bar = [...dataInRange]

    // 触发回调
    onHistoryCallback(bar, meta)
  }
}

We refer to this as a function of getBars()internal functions, wherein from, to, onHistoryCallbackare the parameters provided by the API, datawe acquired the data, (bar, meta)a fixed form TradingView requirements.

This function is responsible for calling the callback function, we acquired the data to the chart. Next, we get the data (demo code, some of the secret, compatible code has been omitted, leaving only the most basic, publicly logic):

getBars (symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) {

  function _send (data) {
    // ...
  }

  // 出于数据共享的需要
  // 我们把获取到的数据放到 Redux 里
  // 先尝试从 Redux 获取现有数据
  const existingData = store.getState().kChartData || []

  // 如果已有数据,直接读取
  if (existingData.length) {
    _send(existingData)
    return
  }

  // 没数据则通过 WebSocket 加载
  // 我们的设计是历史数据和实时更新都走 WebSocket
  // 首次推送历史数据,后续推送更新
  // 所以同一交易对、分辨率,只会发起一个 WebSocket 请求

  // 先判断功能支持度
  // 这里我们用 WebWorker 把 WebSocket 的逻辑独立到主线程之外
  // 以达到性能优化的目的,这个后面再详述。
  if (!window.Worker) return

  // 限制 Worker 单例
  const hasWSInstance = !!window.kChartWorker
  window.kChartWorker = window.kChartWorker || new window.Worker('./worker-kchart.js')

  // WebWorker 数据推送回调
  window.kChartWorker.onmessage = e => {
    const { data = {} } = e

    // 当有数据推送时
    if (data.kChartData) {
      // 获取已有数据
      const kChartData = [...store.getState().kChartData]
      // 因为数据更新都在末端,所以倒序以加速搜索
      const kChartDataReversed = [...kChartData].reverse()

      // 将更新合并到已有数据
      for (const item of [...data.kChartData]) {
        const idx = kChartDataReversed.findIndex(n => n.time === item.time)
        idx < 0
          ? kChartData.push(item)
          : kChartData[kChartData.length - 1 - idx] = { ...kChartData[idx], ...item }
      }

      // 把新数据记录到 Redux
      const promise = new Promise((resolve, reject) => {
        store.dispatch(setKChartData(kChartData))
        resolve({
          total: kChartData,
          updates: [...data.kChartData]
        })
      })

      promise.then(res => {
        // dataInited 是我们自定义的一个变量
        // 用来区分首次推送和后续推送
        if (this.dataInited) {
          // 如非首次推送
          // 对全局 K 线订阅列表中的每个订阅者(后面详述)
          window.kChartSubscriberList = window.kChartSubscriberList || []
          for (const sub of window.kChartSubscriberList) {
            // 按交易对、分辨率筛选
            if (sub.symbol.id !== this.symbol.id) return
            if (sub.resolution !== resolution) return

            // 通过回调函数推送数据
            if (typeof sub.callback !== 'function') return
            // 图表库一次只能增加一条数据,或更新离现在时间最近的一条历史数据
            // 而我们的推送数据是个数组,可能会包含不止一条数据
            // 所以这里要逐个推送
            for (const update of res.updates) {
              sub.callback(update)
            }
          }
        } else {
          // 首次推送
          _send(res.total)
          this.dataInited = true
        }
      })
    }
  }

  // 准备 WebWorker 消息
  // 只有当没有现成数据的时候
  // 才会执行到这里
  // 所以只有在初始化、切换交易对/分辨率的时候
  // 才会发起 WebSocket 请求
  const msg = {
    action: hasWSInstance ? 'restart' : 'init',
    symbol: symbolInfo,
    resolution: resolution,
    url: WEBSOCKET_URL
  }

  // 发送 WebWorker 消息
  window.kChartWorker.postMessage(msg)
}

Here, we have successfully acquired historical data, and send real-time updates to push the various subscribers (although theoretically possible always only one subscriber, but from the perspective of system design, we designed a).

getBars()Fortunately, in fact, as long as clear mechanisms of its work, in fact, nothing particularly difficult, more optimized data structure design and performance. I believe a lot of people understand is the following function.

5.2.2. subscribeBars()

Documentation says this function is used to subscribe to K-line data, coupled with " getBars()the onHistoryCallbackcallback only one call," two words to mislead a lot of people, that getBars()will only be called once, get complete historical data is over, get real-time push needed subscribeBars()to achieve in. In fact, this just adds a subscriber, add the callback function to update the data saved to the outer layer, the callback function is actually in front of getBars()the finished inside. This function is only equivalent to ranked teams, all of the data acquisition and distribution are getBars()carried out inside.

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
  })
}

This function + Resolution of the combination will be called once for each Symbol, pass and identification information corresponding to the callback function to subscribe to the list, when push data arrives, will traverse the subscription list to find qualified subscribers, calls its callback function passed data. It is actually a basic "observer mode."

5.2.3. unsubscribeBars()

Learn finish subscribeBars(), that in fact unsubscribeBars()there is very clear, simple passing:

unsubscribeBars (subscriberUID) {
  window.kChartSubscriberList = window.kChartSubscriberList || []

  const idx = window.kChartSubscriberList.findIndex(n => n.uid === subscriberUID)
  if (idx < 0) return

  window.kChartSubscriberList.splice(idx, 1)
}

6. How to switch transaction / resolution

After creating the widget instance, you can get chart instance by a specific method, and then update the Symbol and Resolution by a particular method, updated several functions previously mentioned operation will re-trigger a new parameter. From this perspective, these functions a bit like life-cycle function, describes the data acquisition, the timing of the operation subscribe to updates an occurrence, there are developers decide when to do something.

this.widget = new window.TradingView.widget(widgetOptions)
this.widget.onChartReady(() => {
  this.chart = this.widget.chart()

  // 设置图表类型(比如分时图和常规的蜡烛图的类型就不一样)
  this.chart.setChartType(chartType)

  // 切换 Symbol
  this.chart.setSymbol(symbol, callback)

  // 切换 Resolution
  this.chart.setResolution(resolution, callback)
})

The other pit 7. TradingView

  • JS API function of automatically invoked at the right time, passing arguments, regardless of the function of the outer layer to get the call manually.
  • JS API in onReady()and resolveSymbol()these two functions, they must asynchronously call a callback function, do not ask why, people requirements.
  • Symbol and Resolution Switching functions have a callback, the value of new and existing current value if the same setting, the callback is not triggered.

8. K-line performance optimization

In the process of using WebSocket, we used the WebWorker performance optimization. When trading frequency reaches a certain level, WebSocket will frequently push data to the client, if this part of the logic directly into React assembly, a new data go setState(), then the page will be immediately sticks badly (painful lesson). Principle is very simple, very short time intervals setState()are cached, merged into one to update, to reduce unnecessary computation and rendering, if the data continue to come in frequent irrigation, she saved a lot of it will not commit to update the components can not always go to the next round render; plus each time new data come in increments need to be consolidated, high-frequency computing load will occupy the main thread of the old data and resources, resulting in no sufficient computing resources page rendering, the page also stuck.

Understand this, then the program will come out, is to take these compute-intensive tasks, went out to the concurrent threads, that is WebWorker, to perform from the main thread. But just not enough to pay out the calculation, although the calculation of the main thread load down, but the update is still very frequent. Scientific data show that the human visual residence time of around 0.1 seconds, that is to say, even if the numbers on the page really make a change in one second a dozen times or more, the human eye no time to look at, from the use of point of view, one second a change 4-5 times is the limit, even if completely updated every 0.5 seconds does not affect, so we need not push the WebSocket data in accordance with the frequency to update the page, we can establish a buffer zone, the cache to a small array of data in WebSocket push over, at fixed time intervals to check whether there is an array of content, there are updates to notify the main thread, not on what they should not do, so find between performance and effectiveness a balance.

Some people will be concerned about compatibility issues WebWorker, after all, the general rarely use this page H5, not cooked. WebWorker browser incompatibilities and WebSocket roughly the same, at least in the range we are concerned, is the same, are IE 10 and above, Ivy browsers already support Needless to say, so unless you have an antique must be compatible needs, rest assured that with the good.

9. Summary

Exchange of this project, should be relatively large in recent years, it took over the project, involving a lot of things, many of which did not come into contact with before are buying and learning. Encountered a lot of pits, also have no small growth. Follow-up I will share some other pit encountered.


More professional front-end knowledge, make the [2048] ape www.mk2048.com

Guess you like

Origin www.cnblogs.com/dssx/p/11774671.html