Angular에서 Trading View Chart Library 다루기
Trading View Chart Library
Github Chart library
[github] (https://github.com/tradingview/charting_library) 사용설명
차트 라이브러리의 소스는 위의 github에서 가져올 수 있지만 접근 제한이 걸려 있다.
이것을 사용하기 위해서는 github 접근 허가를 받아야 한다.
트레이딩 뷰 차트 라이브러리 신청하기
혹은 https://www.tradingview.com/free-charting-libraries/ 에서 "Advanced Charts" 에서 "Learn more" 클릭후 "Get the libray" 클릭
Angular 에서 시작하기
import {
widget,
IChartingLibraryWidget,
ChartingLibraryWidgetOptions,
LanguageCode,
ThemeName,
Timezone,
IBasicDataFeed,
ResolutionString,
ResolutionBackValues,
HistoryDepth
} from './charting_library.min';
..........
export class TvChartContainerComponent {
constructor() {
const widgetOptions = {} // 아래 별도의 widgetOption 설명
this._tvWidget = new widget(widgetOptions);
this._tvWidget.onChartReady(() => {})
}
}
widgetOptions
symbol
예 : Coinbase:BTC/USD
datafeed
예 : new (window as any).Datafeeds.UDFCompatibleDatafeed(this._datafeedUrl),
interval
resolution 이나 interval은 바의 시간이다.
default resolution 을 세팅 할 수 있다.
new TradingView.widget({
interval: '1D',
});
container_id: this._containerId,
library_path: this._libraryPath,
locale
예 : 'ko',
load_last_chart: false,
disabled_features: [
// 'left_toolbar', 'edit_buttons_in_legend', 'hide_last_na_study_output', 'symbol_info', 'dont_show_boolean_study_arguments', 'legend_context_menu', 'display_market_status', 'use_localstorage_for_settings', // local에 저장되어있는 세팅 // 'header_widget', // 상단 툴바 'timeframes_toolbar', // 하단 툴바 'widget_logo' ],
charts_storage_url: this._chartsStorageUrl, // 추가
client_id: this._clientId,
user_id: this._userId,
fullscreen: this._fullscreen,
autosize: this._autosize,
hide_top_toolbar: false,
style: 1,
timezone: this.timezone,
theme (ThemeName):
'Dark';
overrides:
{
'mainSeriesProperties.showCountdown': false, // 추가
'paneProperties.background': this.themeColorObj.bg, //백그라운드 배경색
'paneProperties.vertGridProperties.color': this.themeColorObj.vertiLine,
'paneProperties.horzGridProperties.color': this.themeColorObj.horiLine,
'symbolWatermarkProperties.transparency': 90,
'paneProperties.topMargin': 15,
'paneProperties.bottomMargin': 15,
'scalesProperties.textColor': this.themeColorObj.txt, // 전체 글자컬러 색
'mainSeriesProperties.candleStyle.upColor': '#d3225d',
'mainSeriesProperties.candleStyle.downColor': '#4094e8',
'mainSeriesProperties.candleStyle.drawWick': true,
'mainSeriesProperties.candleStyle.drawBorder': true,
'mainSeriesProperties.candleStyle.borderUpColor': '#d3225d',
'mainSeriesProperties.candleStyle.borderDownColor': '#4094e8',
'mainSeriesProperties.candleStyle.wickUpColor': '#d3225d',
'mainSeriesProperties.candleStyle.wickDownColor': '#4094e8',
'mainSeriesProperties.candleStyle.barColorsOnPrevClose': false,
}
Method
onChartReady
tv chart가 준비된 상태인지 확인
this._tvWidget.onChartReady(() => {})
activeChart
활성화된 차트에 대해서 다양한 프로그램을 처리한다.
setVisibleRange
차트에서 볼 수 있는 시간 구간을 프로그래밍적으로 설정
tvWidget.activeChart().setVisibleRange(range: {from: number, to: number})
- from: Unix timestamp (초 단위) - 범위 시작 시간
- to: Unix timestamp (초 단위) - 범위 종료 시간
this._tvWidget.activeChart().setVisibleRange({from,to}, {
percentRightMargin: 1,
applyDefaultRightMargin: false
}).then(() => {});
setVisibleBars
시간뿐 아니라 바 인덱스 기반으로 설정 가능
getVisibleRange
현재 보이는 범위 확인
chart
setChartType
this._tvWidget.chart().setChartType(1); // candles
this._tvWidget.chart().setChartType(2); // lines
createMultipointShape
다음과 같은 복수 지점을 기반으로 하는 도형(Shape)을 생성할 때 사용
- 추세선 (Trend Line)
- 평행 채널 (Parallel Channel)
- 삼각형 (Triangle)
- 피보나치 도구 등
createMultipointShape(points: Array<ChartPoint>, options: MultipointShapeOptions)
const shape = chart.createMultipointShape(
[
{ time: 1718250000, price: 42000 }, // 첫 번째 지점
{ time: 1718253600, price: 43000 } // 두 번째 지점
],
{
shape: 'trend_line', // 도형 종류
disableSelection: false,
disableSave: false,
disableUndo: false,
zOrder: 'top',
overrides: {
linecolor: '#ff0000',
linewidth: 2
}
}
);
this._tvWidget.chart().createMultipointShape([{
time: this.gameResult.time,
price: this.gameResult.price,
}], {
shape: 'arrow_up',
lock: true,
text: this.gameResult.min + '',
disableSelection: true,
disableSave: true,
disableUndo: true,
overrides: [{
backgroundColor: '#F55F72',
color: '#F55F72',
linecolor: '#F55F72',
fontsize: 12,
}]
});
지원하는 shape 종류는 아래등이 있으나 tv의 라이브러리 버전에 따라 다르므로 공식문서등을 참조 바랍니다.
- trend_line: 일반 추세선
- parallel_channelㅍ평행 채널
- fib_retracement: 피보나치 되돌림 도구
- triangle: 삼각형
- path: 자유 형식 경로 (custom path)
createOrderLine
주문 라인을 그려줄때 사용한다. (현재 나의 주문 금액이랑 주문량등등)
this.orderLine = this._tvWidget.chart().createOrderLine({
price: 1500, // 표시할 가격
lineColor: '#0ac7cb', // 선 색상
lineWidth: 2, // 선 두께
lineStyle: 0, // 0: 실선, 1: 점선, 2: 파선 등
lineLength: 3, // 선 길이 (기본: 2~3)
text: 'Take Profit', // 라벨 텍스트 (선택사항)
quantity: 1, // 주문 수량 (선택사항)
quantityFont: { // 수량 표시 폰트 (선택사항)
size: 12,
family: 'Arial',
color: '#000'
}
});
특정 price에서 라인만 그려줄 경우는 위와 같이 하면 이상하게 나온다.
특히 가격라인이 정확하게 그려지지 않는 경우도 있다.
버전에 따른 차이인지는 모르겠지만 본인은 아래와 같이 처리하였다.
this.orderLine = this._tvWidget.chart().createOrderLine({})
.setText('')
.setQuantity('')
.setLineColor('#db713b')
.setPrice(1500);
삭제할 경우는 아래와 같이 처리한다.
// await this.orderLine.setPrice(null);
await this.orderLine.remove();
this.orderLine = null;
data 처리하기
data는 크게 두가지 방식일 것이다. 초기데이타 및 실시간 업데이트 데이타 일 것이다.
여기서는 api를 이용하여 json 파일을 받아서 초기 세팅용으로 처리하는 데이타와 이후 nodejs io를 이용하여 실시간으로 받는 데이타를 예로 설명드립니다.
- history.service.ts
초기 데이타를 api를 통해 가져옮
import { HttpClient } from '@angular/common/http';
export class HistoryService {
constructor(private http: HttpClient) { }
private handleError(error: Response): any {}
public async getHistoryData(): Promise<any> {
const baseUrl = [Your API URL];
return new Promise((resolve) => {
this.http.get(this.baseUrl).subscribe({
next: (data) => {resolve(data)},
error: (err) => this.handleError(err)
});
});
}
}
- socket.service.ts
socket에 접속하여 실시간 데이타 수신
import { Injectable, OnDestroy } from '@angular/core';
import { SocketMultiService } from 'ng-node-socket';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
..........
export class SocketService {
private socket: any;
private _subscriptions = [];
private ngUnsubscribe = new Subject();
constructor(
private sockets: SocketMultiService,
) {}
public subscribeBars(updateCb: any): void {
this.sockets.On('fx', 'game_tick')
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe({
next: (data: any) => {
const lastBarData = {
time: data[0].date * 1000,
low: data[0].low,
high: data[0].high,
open: data[0].open,
close: data[0].close
};
updateCb(lastBarData);
},
});
}
public unsubscribeBars(uid: string): void {
const subIndex = this._subscriptions.findIndex((e: any) => e.uid === uid);
if (subIndex === -1) {
return;
}
const sub: any = this._subscriptions[subIndex];
this.socket.emit('SubRemove', {
subs: [sub.channelString]
});
this._subscriptions.splice(subIndex, 1);
}
}
- tv-chart.ts
import { HistoryService } from './history.service';
import { SocketService } from './socket.service';
export class TvChartContainerComponent {
constructor(
private tradeHistory: TradeHistoryService,
private socketService: SocketService,
) {
}
private loadTradingViewData(): void {
const widgetOptions: any = {
..........
datafeed: this.Datafeed,
}
this._tvWidget = new widget(widgetOptions);
this.Datafeed = {
..........
getBars: (symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) => {
// sending 2000 default limit
this.tradeHistory.getHistoryData().then((res) => {
if (res.error) {
onHistoryCallback([], {
noData: true
});
}
if (res.data.length) {
const bars = res.data.map((el: any) => {
return {
time: el.date * 1000, // 미리 세컨드로 변경
low: el.low,
high: el.high,
open: el.open,
close: el.close,
volume: 0
};
});
if (firstDataRequest) {
const lastBar = bars[bars.length - 1];
history[symbolInfo.name] = {
lastBar
};
}
if (bars.length) {
onHistoryCallback(bars, {
noData: false
});
} else {
onHistoryCallback([], {
noData: true
});
}
} else {
onHistoryCallback([], {
noData: true
});
}
});
},
subscribeBars: (symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback) => {
this.socketService.subscribeBars(onRealtimeCallback);
},
unsubscribeBars: (subscriberUID) => {
this.socketService.unsubscribeBars(subscriberUID);
},
..........
};
}
}
Table of contents 목차
- Trading View Chart Library
- Github Chart library
- Angular 에서 시작하기
- widgetOptions
- symbol
- datafeed
- interval
- container_id: this._containerId,
- library_path: this._libraryPath,
- locale
- load_last_chart: false,
- disabled_features: [
- charts_storage_url: this._chartsStorageUrl, // 추가
- client_id: this._clientId,
- user_id: this._userId,
- fullscreen: this._fullscreen,
- autosize: this._autosize,
- hide_top_toolbar: false,
- style: 1,
- timezone: this.timezone,
- theme (ThemeName):
- overrides:
- Method
- data 처리하기