TradingView JS API集成教程(二):第1部分

TradingView静态图表

查看本教程系列的简介(如果您还没有观看)。设置TradingView图表可能是一个复杂的过程,所以请事先查看免责声明和备注。

免责声明:TradingView图表库是Github上的免费私有项目,您必须申请访问。我认为许可协议禁止我将其分发给您,因此要完全完成本指南,您需要申请下载图表库的权限。

要在本地运行本教程的这一部分(假设您可以访问图表库)克隆下面提供的repo,然后将图表库文件夹复制到part1文件夹中的/public/目录下。运行npm install然后npm start启动开发服务器。

教程资源: https://github.com/jonchurch/tradingview-js-api-tutorial.git
部署预览: https://tv-tut-part1.glitch.me/


TradingView允许您在自己的网站上使用自己的图表库,并拥有自己的数据源。

有两种方法可以将您的数据导入TradingView,UDF API和JS API。JS API使您可以最大程度地控制数据,在我看来,它更加灵活。而且它是Javascript!

您可以随意实现数据连接,但实际的实现细节非常模糊不清。本教程的目的是向您展示使用您自己的数据源和TradingView图表创建一个基本的静态图表的工作示例。

注意:TradingView不会为您提供此数据源,并假设您已实现自己的来源。为方便起见,本教程依赖于CryptoCompare的历史价格API作为数据源。

本指南以此处提供的React Javascript TradingView示例为基础

概述

首次加载图表widget时,它将使用默认交易对的商品名称调用JS API方法resolveSymbol 。在我们的示例中Coinbase:BTC/USD是默认的交易对。您应该将symbolInfo对象通过图表库JSAPI传递给resolveSymbol函数的回调onSymbolResolvedCallback

整个集成由几部分组成:

  • 图表库Widget构造函数 - 获取widget配置对象,传入datafeed,显示默认交易对,用户选项,图表加载/保存选项
  • Datafeed - JS API和后端之间的接口
  • JS API - 图表库显示数据所需的接口
  • History Provider - 提供OHLCV的K线数据
  • Realtime Provider - 提供实时更新或增加最新的K线数据
  • Symbol Store - 提供可用的商品列表

第1部分介绍图表库Widget构造函数,Datafeed,JS API和History Provider,用于创建有硬编码交易对的静态图表。

Widget构造函数

Widget构造选项可配置TradingView图表,并影响图表首次加载时启用的功能,以及用户可以设置的选项。

在这里,我们设置选项,如用户ID,样式设置,语言,要加载的交易对,图表库的公共资源路径,以及传入我们的JS API Datafeed实现。

Widget构造选项的文档都可以在这里找到

这是我们开始的构造函数选项:

const widgetOptions = {  
   debug: false,  
   symbol: 'Coinbase:BTC/USD',  
   datafeed: Datafeed, // our datafeed object  
   interval: '15',  
   container_id: 'tv_chart_container',  
   library_path: '/charting_library/',  
   locale: getLanguageFromURL() || 'en',  
   disabled_features: ['use_localstorage_for_settings'],  
   enabled_features: [],  
   client_id: 'test',  
   user_id: 'public_user_id',  
   fullscreen: false,  
   autosize: true,  
   overrides: {  
    "paneProperties.background": "#131722",  
    "paneProperties.vertGridProperties.color": "#363c4e",  
    "paneProperties.horzGridProperties.color": "#363c4e",  
    "symbolWatermarkProperties.transparency": 90,  
    "scalesProperties.textColor" : "#AAA",  
    "mainSeriesProperties.candleStyle.wickUpColor": '#336854',  
    "mainSeriesProperties.candleStyle.wickDownColor": '#7f323f',  
   }  
  };

这会将Widget配置为向我们显示Coinbase:BTC/USD15分钟周期的K线数据,并设置一些其他自定义(禁用的功能集,要覆盖的默认设置,要使用的语言等)。

加载后,您不需要更改任何选项,Widget会公开方法可用于动态更改某些设置。(更改商品可以通过我们将在本教程的第3部分中实现的商品搜索来完成)

我通过设置功能集将图表默认为黑色模式overrides."painProperties.background": “#131722”

JS API Datafeed集成

现在我们已经配置了Widget并设置了我们喜欢的样式,让我们看看我们如何将图表数据连接到TradingView 图表库的JS API上。

JS API实际上是您提供给TradingView Widget的对象,它公开了TradingView将调用的函数,并且在大多数情况下,您需要将数据传递给这些函数中的回调函数,以使您的数据与TradingView一起使用。

例如,我们使用CryptoCompare的历史图表数据,在第2部分中,使用websocket API来获得实时价格更新。

TradingView将根据需要调用您提供的方法,以使数据填充当前图表,以及必须执行的其他生命周期方法。

下面是TradingView希望您传递给Widget的整个JS API对象。有些方法是可选的,请参阅文档以获取更多信息

{  
/* 实时图表的必须方法 */  
onReady: cb => {},

// 只在检索功能开启时才需要searchSymbols方法
searchSymbols:(userInput, exchange, symbolType, onResultReadyCallback) => {},

resolveSymbol: (symbolName, onSymbolResolvedCallback, onResolveErrorCallback) => {},

getBars: (symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) => {},

subscribeBars: (symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback) => {},

unsubscribeBars: subscriberUID => {},

/* 可选方法 */

getServerTime: cb => {},

calculateHistoryDepth: (resolution, resolutionBack, intervalBack) => {},

getMarks: (symbolInfo, startDate, endDate, onDataCallback, resolution) => {},

getTimeScaleMarks: (symbolInfo, startDate, endDate, onDataCallback, resolution) => {}  
}

首次加载图表时,JS API流程如下所示:

1. onReady被调用,传递datafeed配置选项cb

2. resolveSymbol被调用,传递symbolInfo对象onSymbolResolvedCallback

3. getBars被调用,传递K线对象数组(时间为以毫秒为单位的UTC时间戳)个体onHistoryCallback

让我们看看我们的每个实现

onReady

const config = {  
  supported_resolutions: ["1", "3", "5", "15", "30", "60", "120",   "240", "D"]  
}

onReady: cb => {  
  console.log('=====onReady running')   
  setTimeout(() => cb(config), 0)  
}

onReady在图表Widget初始化之后立即调用,我们必须将datafeed配置选项传递给该onReady 方法的 cb回调函数。图表库希望它以异步方式执行,并建议在延迟为0秒的setTimeout中包装以强制执行此行为。

现在我们只指定了一个可能的选项supported_resolutions它告诉图表库我们的数据源支持哪些K线周期。这些将显示给用户,并且可以在稍后的每个交易对的resolveSymbol 方法中被覆盖。我们提供的列表转换为:

1分钟, 3分钟, 15分钟, 30分钟, 1小时, 2小时, 4小时, 1天

在本教程的后面,我们将为Datafeed配置添加选项,因为我们实现了搜索和实时数据图表。

resolveSymbol

配置数据源后,图表库将通过Widget初始化对象中的symbol属性调用resolveSymbol 。我们只给出一个字符串值,并且必须返回表示相应商品的symbolInfo对象

resolveSymbol: (symbolName, onSymbolResolvedCallback, onResolveErrorCallback) => {  
  var split_data = symbolName.split(/[:/]/)  
    
  var symbol_stub = {  
   name: symbolName,  
   description: '',  
   type: 'crypto',  
   session: '24x7',  
   timezone: 'America/New_York',  
   ticker: symbolName,  
   minmov: 1,  
   pricescale: 100000000,  
   has_intraday: true,  
   intraday_multipliers: ['1', '60'],  
   supported_resolution:  ["1", "3", "5", "15", "30", "60", "120",   "240", "D"],  
   volume_precision: 8,  
   data_status: 'streaming',  
  }

  if (split_data[2].match(/USD|EUR|JPY|AUD|GBP|KRW|CNY/)) {  
   symbol_stub.pricescale = 100  
  }  
    
  setTimeout(function() {  
   **onSymbolResolvedCallback(symbol_stub)**  
  }, 0)  
}

您可以在此配置单个商品,设置要显示的小数位数,每个刻度移动多少(对于数字货币它几乎总是1),以及非常重要的,容易搞错的intraday_multipliers !因为数字货币是不间断交易的,所以我们将交易时间设置为24x7 。时区应该是这个商品的交易所时区。

symbolInfo的所有文档都在这里,请务必熟悉它。

intraday_multipliershas_intraday控制显示低于1天的K线周期。现在我在这里犯了很多错误:TradingView可以为你建立一些K线。
例如,让我们假设我们的历史数据API只能以1分钟的时间周期给我们数据,这意味着如果我们请求过去24小时的数据,我们将获得1440个K线数据,即24小时内的分钟数。

但是如果我们想要显示15分钟的K线呢?
您可以告诉TradingView我们的intraday_multiplier‘1’并且只传递1分钟K线。图表库将为您构建15分钟的K线,并将其显示在图表上。

我们正在为小时K线做同样的事情,告诉TradingView我们可以提供60分钟的K线,它应该从我们的60分钟K线建立我们的2小时和4小时的K线。

Ticker也非常重要。如果设置,那么图表库将在内部使用Ticker来作为唯一ID(ticker值将被发送到resolveSymbol而不是name字段)。name字段将显示给用户。我将nameticker都设置了相同的值以使我的工作更轻松,因为我使用的name包括识别商品所需的所有信息:交易所,交易对(例如Coinbase:BTC/USD)

Pricescale有点有趣,因为不同的交易对可以有不同的小数精度。例如,BTC/USD将其测量为小数点后两位,pricescale = 100但是对于TRX/BTC(写入时为0.00000771 BTC),我们将其测量为satoshi的8位小数。因此对于TRX/BTC pricescale = 100000000但对于TRX/USD(写作时为0.059432 USD),我们将其设置为6位小数pricescale = 1000000

了解symbolInfo如何影响您的图表非常重要,因此请查看文档

getBars

现在开始进入有趣的部分!
从我们的API源获取图表数据并将其交给TradingView。

getBars: function(symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) {  
  
  historyProvider.getBars(symbolInfo, resolution, from, to, firstDataRequest)  
  .then(bars => {  
   if (bars.length) {  
    onHistoryCallback(bars, {noData: false})
   } else {  
    onHistoryCallback(bars, {noData: true})  
   }  
  }).catch(err => {  
   console.log({err})  
   onErrorCallback(err)  
  })  
}

...

/* historyProvider.js */  
var rp = require('request-promise').defaults({json: true})

    getBars: function(symbolInfo, resolution, from, to, first, limit) {  
  var split_symbol = symbolInfo.name.split(/[:/]/) 
     
  const url = resolution === 'D' ? '/data/histoday' : resolution >= 60 ? '/data/histohour' : '/data/histominute'

   const qs = {  
     e: split_symbol[0], // Coinbase  
     fsym: split_symbol[1], // BTC  
     tsym: split_symbol[2], // USD  
     toTs:  to ? to : '',  
     limit: 2000,   
    }

return rp({  
                url: `${api_root}${url}`,  
                qs,  
            })  
            .then(data => {  
    if (data.Response && data.Response === 'Error') {  
     console.log('CryptoCompare API error:',data.Message)  
     return []  
    }  
    if (data.Data.length) {  
     var bars = data.Data.map(el => {  
      return {  
       time: el.time * 1000, //TradingView requires bar time in ms  
       low: el.low,  
       high: el.high,  
       open: el.open,  
       close: el.close,  
       volume: el.volumefrom   
      }  
     })  
     return bars  
    } else {  
     return []  
    }  
   })  
}

好吧,让我们打破所有代码吧!

Tradingview调用getBars并传递symbolInfo对象,此symbolInfo对象是我们传递给resolveSymbol回调传递的,周期(我们需要1分钟K线?60分钟K线?1天?),to和from时间戳,以及是否第一次请求这个商品数据的布尔类型标记。

从那里开始,我们调用的historyProvider.getBars是我们编写的代码,用于从Cryptocompare的历史价格API中检索历史性的ohlcv数据。我们必须将一个K线数据数组传递给getBar的 onHistoryCallback ,该数组在1分钟K线数据中看起来像这样:

[  
...{  
time: 1528322340000, //bar time must be in milliseconds  
open: 7678.85,  
high: 7702.55,  
low: 7656.98,  
close: 7658.25,  
volume: 0.9834  
},  
...  
]

因此,我们的historyProvider文件负责实际向CryptoCompare发出请求以获取适当的数据。要使用CrytoCompare发出请求,我们需要知道商品,商品和我们想要数据的指定交易所。

因为我们选择将所有相关信息放入商品名称(Coinbase:BTC/USD),所以我们能够从****字符串中****提取这些参数symbolInfo.name

TradingView还传递resolution给getBars,它将告知我们从CryptoCompare请求的API端点,分钟,小时或日历史数据端点。

由于CryptoCompare API的限制(我们一次只能获得2000条记录),我们可能会传递一套不完整的TradingView请求的数据。别担心!将再次调用getBars,使用new和from 时间戳,直到获得填充图表可见部分所需的所有数据。


万岁静态图表!

我希望这对你有帮助。这个过程一开始让我不知所措,这就是我试图与你分享我的学习的原因,这是一个令人困惑的过程。

你可能会想“好的,但静态图表对我帮助不大”。在本教程系列的第2部分中,我们实现了对图表的实时更新。首先要掌握这里概述的概念,熟悉TradingView的文档非常重要。

以下是第1部分的部署预览https://tv-tut-part1.glitch.me/

我相信很多人仍然感到困惑,或者发现我可能犯过的错误。您可以在此处发表评论,或通过以下电子邮件与我联系👇👇


关于译者

我是一名现就职于日本最大数字货币交易所bitbank的全栈开发人员,住在东京。如果您需要加快将TradingView放入到您的网站或交易网页,我可以付费帮忙。

您可以联系我:zlq4863947@gmail.com

您也可以加入tradingview开发交流qq群:313839516

关于本篇译文

英文原文地址: TradingView Charting Library JS API Setup for Crypto: Part 1

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,693评论 2 59
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,516评论 25 707
  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,898评论 2 89
  • 2018年关键词-自律&学习 转眼宝宝已经2岁了,在宝宝出生之前就说要记录她成长的点点滴滴,由于懒惰,没有坚持下来...
    梁曦曦阅读 261评论 0 3
  • 每天六点半的五十八 她下班回家 不知什么时候爱上她 他想陪着她 傍晚街头路灯与霓虹 他想牵着她 他疯狂找着话题想出...
    MNISCY阅读 191评论 0 0