TradingView 支持自定义指标,不过是把你要定义的指标写成一个 JS 源文件(customIndex.js),放在图表库 static 文件夹下。自定义指标 JS 源代码模板如下:
1 __customIndicators = [ 2 { 3 name: 'ShuBenRSI', 4 metainfo: { 5 '_metainfoVersion': 40, 6 'id': 'ShuBenRSI@tv-basicstudies-1', 7 'scriptIdPart': '', 8 'name': 'ShuBenRSI', 9 'description': 'ShuBenRSI', 10 'shortDescription': 'ShuBenRSI', 11 'is_hidden_study': true, 12 'is_price_study': true, 13 'isCustomIndicator': true, 14 'plots': [{'id': 'plot_0', 'type': 'line'}], 15 'defaults': { 16 'styles': { 17 'plot_0': { 18 'linestyle': 0, 19 'visible': true, 20 'linewidth': 1, 21 'plottype': 2, // 绘制类型为线形图: 2 22 'trackPrice': true, 23 'transparency': 40, 24 'color': '#880000' 25 } 26 }, 27 'precision': 1, // 精度 eg:608.4 28 'inputs': {} 29 }, 30 'styles': { 31 'plot_0': { 32 'title': 'ShuBenRSI', 33 'histogrambase': 0, 34 } 35 }, 36 'inputs': [], 37 }, 38 constructor: function () { 39 this.init = function (context, inputCallback) { 40 this._context = context; 41 this._input = inputCallback; 42 //var symbol = 'p1905'; 43 var symbol = PineJS.Std.ticker(this._context); // 获取所选商品代码 44 this._context.new_sym(symbol, PineJS.Std.period(this._context), PineJS.Std.period(this._context)); 45 }; 46 this.main = function (context, inputCallback) { 47 this._context = context; 48 this._input = inputCallback; 49 this._context.select_sym(1); 50 if(this._context['symbol']['time'] != NaN){ 51 var c = PineJS.Std.close(this._context)-50; 52 var o = PineJS.Std.open(this._context)-50; 53 var l = PineJS.Std.low(this._context)-50; 54 var h = PineJS.Std.high(this._context)-50; 55 console.log('execute custom index!'); 56 console.log('symbol: ', this._context['symbol']['time']); 57 return [o, c]; 58 } 59 60 } 61 } 62 } 63 ];
其中 main 方法会根据数据量(getBar 中的后台获取的数据)的多少自动进行循环遍历,在此可以对数据进行修改,以创建自己的数据曲线(个人理解)
即 new TradingView.widget() 中使用 indicators_file_name: 'customIndex.js'
onChartReady() 中将定义指标添加到页面显示中 widget.chart().createStudy('ShuBenRSI', false, false); // 自定义 RSI 曲线
自定义的曲线数据源来自 getBar 方法中回调函数中的 bar 数据,可以在自定义模板中修改此数据。
1 __customIndicators = [ 2 { 3 name: 'ShuBenRSI', 4 metainfo: { 5 '_metainfoVersion': 40, 6 'id': 'ShuBenRSI@tv-basicstudies-1', 7 'scriptIdPart': '', 8 'name': 'ShuBenRSI', 9 //当调用createStudy方法时,它也被用作“name”参数 10 'description': 'ShuBenRSI', 11 // 该描述将显示在图表上 12 'shortDescription': 'ShuBenRSI', 13 'is_hidden_study': true, 14 // 指标曲线是否在主数据列窗口中显示 15 'is_price_study': true, 16 'isCustomIndicator': true, 17 'plots': [{'id': 'plot_0', 'type': 'line'}], 18 'defaults': { 19 'styles': { 20 'plot_0': { 21 'linestyle': 0, 22 'visible': true, 23 'linewidth': 1, 24 'plottype': 2, // 绘制类型为线形图: 2 25 'trackPrice': true, 26 'transparency': 40, 27 'color': '#880000' 28 } 29 }, 30 'precision': 3, // 精度 eg:608.4 31 'inputs': {} 32 }, 33 'styles': { 34 'plot_0': { 35 'title': 'ShuBenRSI', 36 'histogrambase': 0, 37 } 38 }, 39 'inputs': [], 40 }, 41 constructor: function () { 42 this.init = function (context, inputCallback) { 43 var host = window.location; 44 var host1 = host.href.split('static'); 45 var fakeDataRSI = []; 46 $.ajaxSetup({ async: false }); 47 $.post(host1[0] + 'cta_posPL_syetem/getChartData',{method:'getDataRSI'}, function (result) { 48 if(result.result_code == 'success'){ 49 fakeDataRSI = result.data; 50 } 51 52 }); 53 this.fakeData = fakeDataRSI; 54 this.count = 0; 55 this.time = 0; 56 this.rsi = 0; 57 this.infoList = []; 58 //console.log('init context: ', context); 59 //console.log(this.count); 60 this._context = context; 61 this._input = inputCallback; 62 //var symbol = 'p1905'; 63 var symbol = PineJS.Std.ticker(this._context); // 获取所选商品代码 64 this._context.new_sym(symbol, PineJS.Std.period(this._context), PineJS.Std.period(this._context)); 65 }; 66 this.main = function (context, inputCallback) { 67 //this.count += 1; 68 //console.log('count: ',this.count); 69 //if(this.count<5)console.log('main fakeData: ', this.fakeData[this.count]); 70 this._context = context; 71 this._input = inputCallback; 72 this._context.select_sym(1); 73 /* 74 // RSI 计算 75 if(this.count > 1 && this.time != this._context['symbol']['time']){ 76 //console.log(PineJS.Std.close(this._context)); 77 this.infoList.push(PineJS.Std.close(this._context)); 78 var upSum = 0;var downSum = 0; 79 if(this.count > 15){ 80 for(var i = 1; i <= 14; i++){ 81 var change = this.infoList[i] - this.infoList[i - 1]; 82 change > 0 ? upSum += change : downSum -= change; 83 } 84 var rs = Math.round(upSum / 14 *1000) / downSum; 85 this.rsi = Math.round(rs / (1 + rs) * 100 * 1000) / 1000; 86 //console.log('current: ', this._context['symbol']['time'], 'pretime: ',this.time); 87 //console.log('infoList: ',this.infoList); 88 this.infoList.splice(0, 1); 89 this.time = this._context['symbol']['time']; 90 //console.log('index close: --- >', PineJS.Std.close(this._context)); 91 return [this.rsi]; 92 } 93 } 94 return [this.rsi]; 95 */ 96 var c = this.fakeData[this.count++]['close']; 97 //console.log('rsi: ',this.rsi); 98 99 return [c]; 100 /* 101 var c = PineJS.Std.close(this._context)-50; 102 var o = PineJS.Std.open(this._context)-50; 103 var l = PineJS.Std.low(this._context)-50; 104 var h = PineJS.Std.high(this._context)-50; 105 //console.log('execute custom index!'); 106 console.log('symbol: ', this._context['symbol']['time']); 107 //return [o, c]; 108 */ 109 } 110 } 111 } 112 ];
如果你想要自定义的曲线数据并不是 K 线数据,你可以在自定义模板中,向后台请求 用后台返回的数据。eg:
1 __customIndicators = [ 2 { 3 name: 'ShuBenRSI', 4 metainfo: { 5 '_metainfoVersion': 40, 6 'id': 'ShuBenRSI@tv-basicstudies-1', 7 'scriptIdPart': '', 8 'name': 'ShuBenRSI', 9 //当调用createStudy方法时,它也被用作“name”参数 10 'description': 'ShuBenRSI', 11 // 该描述将显示在图表上 12 'shortDescription': 'ShuBenRSI', 13 'is_hidden_study': true, 14 'is_price_study': false, 15 'isCustomIndicator': true, 16 'plots': [{'id': 'plot_0', 'type': 'line'}], 17 'defaults': { 18 'styles': { 19 'plot_0': { 20 'linestyle': 0, 21 'visible': true, 22 'linewidth': 1, 23 'plottype': 2, // 绘制类型为线形图: 2 24 'trackPrice': true, 25 'transparency': 40, 26 'color': '#880000' 27 } 28 }, 29 'precision': 3, // 精度 eg:608.4 30 'inputs': {} 31 }, 32 'styles': { 33 'plot_0': { 34 'title': 'ShuBenRSI', 35 'histogrambase': 0, 36 } 37 }, 38 'inputs': [], 39 }, 40 constructor: function () { 41 this.init = function (context, inputCallback) { 42 var host = window.location.href.split('static')[0]; 43 var fakeDataRSI = []; 44 $.ajaxSetup({ async: false }); 45 $.post(host + 'cta_posPL_syetem/getChartData',{method:'getDataRSI'}, function (result) { 46 if(result.result_code == 'success'){ 47 fakeDataRSI = result.data; 48 } 49 }); 50 this.fakeData = fakeDataRSI; 51 this.count = 0; 52 this.time = 0; 53 this.rsi = 0; 54 this.infoList = []; 55 this._context = context; 56 this._input = inputCallback; 57 var symbol = PineJS.Std.ticker(this._context); // 获取所选商品代码 58 this._context.new_sym(symbol, PineJS.Std.period(this._context), PineJS.Std.period(this._context)); 59 }; 60 this.main = function (context, inputCallback) { 61 this._context = context; 62 this._input = inputCallback; 63 this._context.select_sym(1); 64 var c = this.fakeData[this.count++]['close']; 65 return [c]; 66 } 67 } 68 } 69 ];