强大的金融类图表库 TradingView 使用分享
这段时间刚好做币圈交易所,运用到了现在最火的金融类图表库 -- TradingView ,就是强大,基本上现在的火币网(https://www.huobi.com),币安网(https://www.binance.com/)等大型交易所都在使用。
简介:
带有开放API的可下载图表库。这是一个独立的解决方案,可以将其下载,托管在自己的服务器上,连接自己的数据,在自己的网站/应用程序免费使用。
适用于手机和桌面应用程序、 门户网站、博客和新闻网站。 当您想要完全控制图表并希望显示您所控制的数据时,此为最佳选择。
使用教程:
本教程使用的是nodejs 提供的接口,所有的数据都本地mock出来的,这样大家可以更加方便理解数据使用的问题。
步骤:
1.注册TradingView账号,然后申请TradingView的图表库(申请地址:https://cn.tradingview.com/how-it-works/),(注意,必须是以公司名义申请,不允许个人名义申请,如果以个人名义申请或者你所在行业经过中国区经销商了解后不需要用到tradingview将无法给你提供github的开源代码下载。源码结构如下图:)
/charting\_library
包含全部的图表库文件。/charting\_library/charting\_library.min.js
包含外部图表库widget接口。此文件不应该被修改。/charting_library/charting_library.min.d.ts
包含TypeScript定义的widget接口/charting_library/datafeed-api.d.ts
包含TypeScript定义的datafeed接口。/charting_library/datafeeds/udf/
包含UDF-compatible 的datafeed包装类(用于实现JS API通过UDF传输数据给图表库)。例子中的datafeed包装器类实现了脉冲实时仿真数据。您可以自由编辑此文件。/charting\_library/static
文件夹中存储图表库内部资源,不适用于其他目的。/index.html
为使用Charting Library widget 的html例子。/test.html
为不同的图表库自定义功能使用的示例。/mobile\*.html
也是Widget自定义的示例。
然后把整个项目clone 下来到本地。
2.安装nodejs (安装教程:https://www.cnblogs.com/zhouyu2017/p/6485265.html)
3.安装koa (Koa -- 基于 Node.js 平台的下一代 web 开发框架)
$ npm i koa
4.安装koa-generator (Koa 脚手架)
$ npm i -g koa-generator
5.使用koa-generator 快速创建项目
$ koa2 TrandingPiewProject && cd TrandingPiewProject && npm install
koa-generator创建的项目已经集成了nodemon,所以大家可以直接使用nodemon启动项目
$ nodemon run start
打开浏览器: http://localhost:3001
就可以看到nodejs项目已经启动了
6.在nodejs创建3个接口
地址1:http://localhost:3001/api/config (存放trandingview的 datafeed配置数据)
地址2:http://localhost:3001/api/symbols (trandingview的 商品解析数据)
地址3:http://localhost:3001/api/history (trandingview的 K线数据)
7.nodejs项目文件修改如下
app.js (修改部分黄色标出)
const Koa = require('koa')
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')
// 引入koa2-cors "允许跨域"
const cors = require('koa2-cors') const index = require('./routes/index')
const api = require('./routes/api') const app = new Koa()
app.use(cors())
// error handler
onerror(app) // middlewares
app.use(bodyparser({
enableTypes:['json', 'form', 'text']
}))
app.use(json())
app.use(logger())
app.use(require('koa-static')(__dirname + '/public')) app.use(views(__dirname + '/views', {
extension: 'pug'
})) // logger
app.use(async (ctx, next) => {
const start = new Date()
await next()
const ms = new Date() - start
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
}) // routes
app.use(index.routes(), index.allowedMethods())
app.use(api.routes(), api.allowedMethods()) // error-handling
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
}); module.exports = app
把原来的routes下面的users.js改成api.js,
贴上我的api.js
api.js (修改部分黄色标出)
const router = require('koa-router')() router.prefix('/api') // 产生随机数的方法
function random(lower, upper) {
return Math.floor(Math.random() * (upper - lower)) + lower;
}
// 获取两数中一数的方法
function rd(n, m) {
var c = m - n + 1;
return Math.floor(Math.random() * c + n);
} // config接口
router.get('/config', async (ctx, next) => {
ctx.body = {
"supports_search": true, //是否支持搜索
"supports_group_request": false, //是否支持搜索或品种解析
"supported_resolutions": ["30", "60", "240", "D"], //中的值D代表天day,W代表周week,M代表月;2D是两天;3W是三周;6M是6个月,表示支持显示的哪几种图日线图、2日线
"supports_marks": false,
"supports_timescale_marks": false,
}
})
// symbols接口
router.get('/symbols', async (ctx, next) => {
ctx.body = {
"name": "CDCC/ETH", //品种名称
"session": "24x7", //开盘时间
"has_intraday": true, //显示符号是否具有历史盘中数据
"timezone": "Asia/Shanghai", //时区
"data_status": "delayed_streaming",
"supported_resolutions": ["5", "10", "15", "30", "60", "120", "240", "D", "W"],
"intraday_multipliers": ["5", "60", "D"],
"minmov": 20, //用于格式化用途
"pricescale": 100000000, //数据显示的小数位数(例如:100显示0.01)
"type": "bitcoin" //类型
}
})
// history接口
router.get('/history', async (ctx, next) => {
let resolution = ctx.query.resolution // 商品名称或者代码
let from = new Date(ctx.query.from * 1000) //获取数据的开始时间戳
let to = new Date(ctx.query.to * 1000) //获取数据的结束时间戳 if (resolution == '1' || resolution == '5' || resolution == '10' || resolution == '15' || resolution == '30') {
from.setMilliseconds(0)
to.setMilliseconds(0)
from.setSeconds(0)
to.setSeconds(0)
} else if (resolution == '60') {
from.setMilliseconds(0)
to.setMilliseconds(0)
from.setSeconds(0)
to.setSeconds(0)
from.setMinutes(0)
to.setMinutes(0)
} else if (resolution == 'D') {
from.setMilliseconds(0)
to.setMilliseconds(0)
from.setSeconds(0)
to.setSeconds(0)
from.setMinutes(0)
to.setMinutes(0)
from.setHours(0)
to.setHours(0)
}
let text = from
const time = Math.floor((to.getTime() - from.getTime()) / 60 / 1000)
let num
if (resolution == 'D') {
num = time / (60 * 24)
} else {
num = time / resolution
}
let o = []
let c = []
let h = []
let l = []
let v = []
let t = []
let newnum = 3000;
for (var i = 0; i < num; i++) {
t.push(text.getTime() / 1000)
if (resolution == 'D') {
text.setMinutes(text.getMinutes() + Number(24 * 60))
} else {
text.setMinutes(text.getMinutes() + Number(resolution))
}
if (rd(1, 2) == 1) {
newnum += random(1, 10)
o.push(newnum)
let h1 = 0;
let l1 = 0;
if (rd(1, 2) == 1) {
h1 = newnum + random(1, 10)
h.push(h1)
l1 = h1 - random(1, 10)
l.push(l1)
c.push(rd(l1, h1))
} else {
h1 = newnum - random(1, 10)
h.push(h1)
l1 = h1 - random(1, 10)
l.push(l1)
c.push(rd(l1, h1))
}
} else {
newnum -= random(1, 10)
if (newnum < 0) {
newnum = 0
}
o.push(newnum)
if (rd(1, 2) == 1) {
h.push(newnum + random(1, 10))
l.push(newnum + random(1, 10))
c.push(newnum + random(1, 10))
} else {
if ((newnum - random(1, 10)) < 0) {
newnum = 0
h.push(0)
} else {
h.push(newnum - random(1, 10))
}
if ((newnum - random(1, 10)) < 0) {
newnum = 0
l.push(0)
} else {
l.push(newnum - random(1, 10))
}
if ((newnum - random(1, 10)) < 0) {
newnum = 0
c.push(0)
} else {
c.push(newnum - random(1, 10))
}
}
} v.push(random(1, 1000))
}
ctx.body = {
t: t, //表示时间,将t的数值补000后就代表毫秒数,比如js的(new Date).getTime()
o: o, //表示open开盘价
c: c, //表示close收盘价
h: h, //表示high最高价
l: l, //表示low最低价
v: v, //表示volume成交量
s: "ok" //表示状态,返回数据是否成功,ok表示成功
}
}) module.exports = router
修改完之后,其实上面创建的3个就可以访问了。mock 数据也完成了。
8.把github上clone下来的项目启动在自己本地的服务器,我个人用了代理服务器nginx,nginx 具体的安装流程请大家自己去搜索,以及为什么用nginx,这个就是因为接口跨域问题,大家自己私下了解下就可以了,我在这里就不多做解释了。
接着把克隆下来的charting_library文件移动到nginx的html文件下就可以了。
这里我贴出我的nginx.conf 文件
注意:修改下里面charting_library文件夹根目录下的 test.html 文件,把名字改成 index3.html。因为nginx跟恶心,对test这个词有bug。
#user nobody;
worker_processes 1; #error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info; #pid logs/nginx.pid; events {
worker_connections 1024;
} http {
include mime.types;
default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on;
#tcp_nopush on; #keepalive_timeout 0;
keepalive_timeout 65; #gzip on; server {
listen 8083;
server_name localhost;
location / {
root ./html/charting_library;
index index3.html index3.htm;
}
} server {
listen 8084;
server_name localhost; location / {
proxy_pass http://localhost:8083;
proxy_redirect default;
}
location /apis {
rewrite ^/apis/(.*)$ /$1 break;
proxy_pass http://localhost:3001;
} } # HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost; # ssl_certificate cert.pem;
# ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on; # location / {
# root html;
# index index.html index.htm;
# }
#} }
好了,这个时候项目就已经启动了。
9.然后修改Tradingview的配置就可以连接自己的nodesj mock出来的数据了。
tradingview 目录结构
然后只需要修改里里面的index.html(其实就是原来的test.html,只是我这里把它改成index3.html)
<!DOCTYPE html>
<html lang="en"> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>TradingView Charting Library demo -- testing mess</title>
<!-- Fix for iOS Safari zooming bug -->
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="http://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script type="text/javascript" src="charting_library/charting_library.min.js"></script>
<script type="text/javascript" src="datafeeds/udf/dist/polyfills.js"></script>
<script type="text/javascript" src="datafeeds/udf/dist/bundle.js"></script>
<script type="text/javascript">
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
} TradingView.onready(function() {
var widget = window.tvWidget = new TradingView.widget({
debug: false,
// 是否全屏
fullscreen: true,
// 初始商品
symbol: 'CDCC/ETH',
// 周期
interval: 60,
// 时区
timezone: "Asia/Shanghai",
// id属性为指定要包含widget的DOM元素id
container_id: "tv_chart_container",
// 语言
locale: "zh",
// static文件夹的路径
library_path: "charting_library/",
// JavaScript对象的实现接口 JS API 以反馈图表及数据
datafeed: new Datafeeds.UDFCompatibleDatafeed("http://localhost:3001/api"),
// 自动调节大小
autosize: true,
// 主题颜色(dark,light)
theme: 'dark',
time_frames: false,
style: "1",
overrides: {
"timeScale.rightOffset": 1,
"timeScale.barSpacing": 12.709329141645004,
"headerToolbarIndicators.backgroundColor": "#dc1a5a",
"headerToolbarIndicators.backgroundColor": "#dc1a5a",
"mainSeriesProperties.candleStyle.borderColor": "#212c3f",
"mainSeriesProperties.candleStyle.borderDownColor": "#dc1a5a",
"mainSeriesProperties.candleStyle.borderUpColor": "#0fbb89",
"mainSeriesProperties.candleStyle.downColor": "#dc1a5a",
"mainSeriesProperties.candleStyle.upColor": "#0fbb89",
"mainSeriesProperties.candleStyle.wickDownColor": "#dc1a5a",
"mainSeriesProperties.candleStyle.wickUpColor": "#0fbb89",
"mainSeriesProperties.hollowCandleStyle.borderColor": "#212c3f",
"mainSeriesProperties.hollowCandleStyle.borderDownColor": "#dc1a5a",
"mainSeriesProperties.hollowCandleStyle.borderUpColor": "#0fbb89",
"mainSeriesProperties.hollowCandleStyle.downColor": "#dc1a5a",
"mainSeriesProperties.hollowCandleStyle.upColor": "#0fbb89",
"mainSeriesProperties.showCountdown": false,
"mainSeriesProperties.style": 1,
"paneProperties.background": "#131722",
"paneProperties.crossHairProperties.color": "#999",
"paneProperties.horzGridProperties.color": "#252c40",
"paneProperties.horzGridProperties.style": 2,
"paneProperties.legendProperties.showLegend": true,
"paneProperties.vertGridProperties.color": "#131722",
"paneProperties.vertGridProperties.style": 2,
"symbolWatermarkProperties.color": "#0e192b",
"volumePaneSize": "small",
},
studies_overrides: {
"volume.volume.color.0": "#0fbb89",
"volume.volume.color.1": "#dc1a5a",
"volume.options.showStudyArguments": false,
"bollinger bands.median.color": "#33FF88",
"bollinger bands.upper.linewidth": 0
},
disabled_features: [
"header_symbol_search",
"header_saveload",
"header_screenshot",
"header_chart_type",
"header_compare",
"header_undo_redo",
"timeframes_toolbar",
"volume_force_overlay",
"header_resolutions",
"display_market_status",
"timezone_menu",
"countdown",
"symbol_info"
],
enabled_features: [
"legend_context_menu"
], // 指标模板
charts_storage_api_version: '1.1',
// 定制加载进度条
loading_screen: { backgroundColor: "#000000" },
'scalesProperties.fontSize': 14, // 设置坐标轴字体大小 }); // 参考线、 按钮、 时间切换:
var thats = widget;
var buttons = [
{ title: '5分', resolution: '5', chartType: 1 },
{ title: '10分', resolution: '10', chartType: 1 },
{ title: '15分', resolution: '15', chartType: 1 },
{ title: '30分', resolution: '30', chartType: 1 },
{ title: '1小时', resolution: '60', chartType: 1 },
{ title: '2小时', resolution: '120', chartType: 1 },
{ title: '4小时', resolution: '240', chartType: 1 },
{ title: '1天', resolution: 'D', chartType: 1 },
{ title: '1周', resolution: 'W', chartType: 1 },
]; var studies = []; function createButton(buttons) {
for (var i = 0; i < buttons.length; i++) {
thats.createButton()
.attr('title', buttons[i].title)
.attr('data-interval', buttons[i].resolution)
.addClass('btn-m')
.text(buttons[i].title)
.on('click', function(e) {
tvWidget.setSymbol("CDCC/ETH",$(this).attr('data-interval'),function(){});
})
}
} function createStudy() {
var id = widget.chart().createStudy('Moving Average', false, false, [5], null, { 'Plot.color': 'rgb(150, 95, 196)' });
studies.push(id);
id = widget.chart().createStudy('Moving Average', false, false, [10], null, { 'Plot.color': 'rgb(116,149,187)' });
studies.push(id);
id = widget.chart().createStudy('Moving Average', false, false, [20], null, { "plot.color": "rgb(58,113,74)" });
studies.push(id);
id = widget.chart().createStudy('Moving Average', false, false, [30], null, { "plot.color": "rgb(118,32,99)" });
studies.push(id);
} widget.onChartReady(function() {
//设置均线种类 均线样式
createStudy();
//生成时间按钮
createButton(buttons);
});
});
</script>
</head> <body style="margin:0;">
<div id="tv_chart_container"></div>
</body> </html>
上面是我的index3.html文件
修改完之后大家打开http://localhost:8083/ 就可以看到自己的TradingView 项目连接着自己的nodejs服务器mock出来的数据运行了,是不是很有成就感啦!!!
这个给大家介绍个好东西,图表功能展示
地址: https://tradingview.gitee.io/featuresets/
这里,我就是介绍了简单的ajax请求方法的,要WS的后面我再慢慢更新哈。
以上只是一部分,后续会继续更新完善。
期待!期待!期待!
强大的金融类图表库 TradingView 使用分享的更多相关文章
- ECharts一个强大的商业产品图表库
Architecture ECharts (Enterprise Charts 商业产品图表库) 提供商业产品常用图表库,底层基于ZRender,创建了坐标系,图例,提示,工具箱等基础组件,并在此上构 ...
- highCharts入门-强大的图表库插件
简介 Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习.个人网站和非商业 ...
- Afreechart很强大的图表库,支持股票曲线图,饼图,曲线
Afreechart是一个很强大的图表库,支持股票曲线图,饼图,曲线等.源码下载:http://www.23code.com/afreechart/
- 双11不再孤单,结识ECharts---强大的常用图表库
又是一年双十一,广大单身狗们有没有很寂寞(好把,其实我也是)!但是这次的双十一,我不再孤单,因为结识了一个js的强大的图表库---ECharts. 最近做软件工程项目的时候,由于设计图中有柱状图和饼图 ...
- 基于html5 Canvas图表库 : ECharts
ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表.创新的拖拽重计算.数据视图.值 ...
- 前端开发者常用的9个JavaScript图表库
当前,数据可视化已经成为数据科学领域非常重要的一部分.不同网络系统中产生的数据,都需要经过适当的可视化处理,以便更好的呈现给用户读取和分析. 对任何一个组织来说,如果能够充分的获取数据.可视化数据和分 ...
- Android图表库MPAndroidChart(一)——了解他的本质,方能得心应手
Android图表库MPAndroidChart(一)--了解他的本质,方能得心应手 我们项目中经常会遇到一些统计图,比如折线图,线形图等,在一些运动健康类的App中尤其的常见,这画起来要命,我以前就 ...
- 我的Android进阶之旅------>【强力推荐】Android开源图表库XCL-Charts版本发布及展示页
因为要做图表相关的应用,后来百度发现了一个很好的Android开源图表库(XCL-Charts is a free charting library for Android platform.) 下面 ...
- Android开源图表库XCL-Charts版本号公布及展示页
XCL-Charts V2.1 Android开源图表库(XCL-Charts is a free charting library for Android platform.) XCL-Charts ...
随机推荐
- THINKPHP and or 模板语句书写
select * from xx where (a = 22 or b = 333) or (c=11 and d=22) $where_1['a'] = array('eq', '222'); $w ...
- linux 安装软件三种方法
引言 在ubuntu当中,安装应用程序我所知道的有三种方法,分别是apt-get,dpkg安装deb和make install安装源码包三种.下面针对每一种方法各举例来说明. apt-get方法 使用 ...
- 原生js开发,无依赖、轻量级的现代浏览器图片懒加载插件,适合在移动端开发使用
优势 1.原生js开发,不依赖任何框架或库 2.支持将各种宽高不一致的图片,自动剪切成默认图片的宽高 比如说你的默认图片是一张正方形的图片,则各种宽度高度不一样的图片,自动剪切成正方形. 完美解决移动 ...
- [c/c++] programming之路(31)、位运算(二)
一.取反的高级用法 #include<stdio.h> #include<stdlib.h> //取反的作用:末位清零 取反适用于各种位数不同的数据 void main0(){ ...
- opencv学习之路(37)、运动物体检测(二)
一.运动物体轮廓椭圆拟合及中心 #include "opencv2/opencv.hpp" #include<iostream> using namespace std ...
- BZOJ1688|二进制枚举子集| 状态压缩DP
Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) ...
- java基础之集合框架--使用ArrayList类动态 存储数据
一.ArrayList是List接口下的一个实现类,实现了长度可变的.连续的数组:拥有数组的特性. 遵循了LIst的规则:不唯一的.有序的. 如果没有增加泛型的话,集合中可以添加任何类型的数据. 使用 ...
- web 页面间传值 js 封装方法
用法 var id = getParam("id"); function getParam(strKey) { var url=document.URL; //var url=&q ...
- 前后端分离之【接口文档管理及数据模拟工具docdoc与dochelper】
前后端分离的常见开发方式是: 后端:接收http请求->根据请求url及params处理对应业务逻辑->将处理结果序列化为json返回 前端:发起http请求并传递相关参数->获取返 ...
- openssl 生成pfx
证书可以通过几种渠道获得, 可以购买, 可以使用IIS生成, 也可以使用Openssl这样的工具生成证书. 本篇文章主要介绍openssl生成pfx文件 首选去网关下载openssl 下载地址:htt ...