Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- Ec2 GitHub CodeDeploy
- 집앞 낚시
- aws ec2 서브도메인 설정
- 순천 횟집
- ssl 사용
- 까먹는 개발자
- 고흥 회센터
- nginx 설정방법
- Gmail business card
- zerossl
- ssl 인증서 검증
- CodeDeploy 연동하기
- 트레이딩뷰
- ec2 배포환경 구축
- Gamil 명함 설정
- 쉽게 https
- 포트별 서비스
- tradingview
- ec2 자동배포
- Gmail 설정
- CodeDeploy 적용
- https 붙이기
- ec2 redirect
- AWS EC2
- EC2 원격접속
- express 배포
- ec2 인바운드 편집
- nginx 서브도메인
- 최고의 오션뷰
- GitHub CodeDeploy
Archives
- Today
- Total
힐링 휴식 그리고 개발
트레이딩 뷰 차트 소켓데이터 적용하기 - 까먹는 개발자 본문
트레이딩 뷰 차트 - Technical Analysis Charts for Reactjs (2 / 2)
TradingView Chart를 연동 create-react-app에 연동 시킨 후, 데이터 베이스와 소켓 데이터를 바인딩 시키기 위한 예제입니다.
준비사항
https://github.com/ookm1020/basic-tradingview.git
지난 1편에서 소켓 모듈을 설치했기 때문에 따로 업급은 하지 않겠습니다. 각 함수들에 것은 Jon Church님의 글에 자세하게 설명이 되어 있으니 참고하시면 됩니다.
시작하기 전에-
소켓 데이터 연결을 하기에 앞서, 업비트의 오픈API를 통해서 현재 체결되는 데이터를 소켓을 통해 받아오는 서버를 켜놓고 이 예제를 진행했습니다.
WebSocket을 이용한 업비트 시세 수신을 이용하여 가상 소켓 서버를 만드신 후, 진행하시면 원활하게 테스트가 가능합니다.
데이터 포맷
업비트에서 수신되는 실시간 매칭 데이터는 다음과 같습니다.
data: {
acc_ask_volume: 614.8915618
acc_bid_volume: 419.11867853
acc_trade_price: 18943312506.64586
acc_trade_price_24h: 83406758933.7941
acc_trade_volume: 1034.01024033
acc_trade_volume_24h: 4599.40064738
ask_bid: "ASK"
change: "FALL"
change_price: 3000
change_rate: 0.0001641587
code: "KRW-BTC"
delisting_date: null
high_price: 18420000
highest_52_week_date: "2020-11-16"
highest_52_week_price: 18450000
is_trading_suspended: false
low_price: 18207000
lowest_52_week_date: "2020-03-13"
lowest_52_week_price: 5489000
market_state: "ACTIVE"
market_state_for_ios: null
market_warning: "NONE"
opening_price: 18275000
prev_closing_price: 18275000
signed_change_price: -3000
signed_change_rate: -0.0001641587
stream_type: "REALTIME"
timestamp: 1605590707860
trade_date: "20201117"
trade_price: 18272000
trade_status: null
trade_time: "052507"
trade_timestamp: 1605590707000
trade_volume: 0.000132
type: "ticker"
}
트레이딩 뷰 차트에 데이터 연결
실시간 소켓 데이터는 stream.js에서 관리합니다.
폴더 구조는 다음과 같습니다.

실질적으로 stream.js에 작성되어 있는 updateBar 함수가 차트의 캔들을 업데이트를 해주는데 해당 함수를 따로 건드리지 않고 필요한 정보만 주입하는 방식으로 진행합니다. 수정 부분 - updateBar func, socket module
- 기존 require방식이 마음에 들지 않아 import방식으로 변경한 부분입니다.
// api/stream.js
import historyProvider from './historyProvider.js'
// we use Socket.io client to connect to cryptocompare's socket.io stream
// 업비트에서 수신할 가상의 소켓서버와의 연결을 위해 주석처리합니다.
//var io = require('socket.io-client')
//var socket_url = 'wss://streamer.cryptocompare.com'
//var socket = io(socket_url)
import socketClient from "socket.io-client";
// 로컬에 3001로 켜져 있는 가상의 소켓서버로 소켓을 연결합니다. 예제에서는 BTC코인의 시세만 반영하기 때문에 data=KRW-BTC로 지정했습니다.
const socket = socketClient(`http://localhost:3001?data=KRW-BTC`);
.
.
.
- socket.on의 코드를 가상의 소켓서버와 채널을 맞추고 data를 업비트의 데이터 포맷에 맞게 변경합니다.
// 기존 코드
socket.on('m', (e) => {
// here we get all events the CryptoCompare connection has subscribed to
// we need to send this new data to our subscribed charts
const _data= e.split('~')
if (_data[0] === "3") {
// console.log('Websocket Snapshot load event complete')
return
}
const data = {
sub_type: parseInt(_data[0],10),
exchange: _data[1],
to_sym: _data[2],
from_sym: _data[3],
trade_id: _data[5],
ts: parseInt(_data[6],10),
volume: parseFloat(_data[7]),
price: parseFloat(_data[8])
};
// 변경 코드
socket.on('/ticker', (e) => {
console.log("match data: ", e);
const data = {
sub_type: parseInt(0, 10),
exchange: "BITHUMB",
to_sym: e.code.split("-")[1], // "BTC"
from_sym: e.code.split("-")[0], // "KRW"
// trade_id: _data[5],
trade_id: "",
ts: e.timestamp / 1000, // timestamp
volume: e.trade_volume, // 거래량
price: e.trade_price // 가격
};
- 차트에서 원하는 형식에 맞게 소켓으로 수신된 데이터로 바꿔줍니다. (간단 구현을 위해 close와 volume만 바꿨습니다.)
function updateBar(data, sub) {
var lastBar = sub.lastBar
let resolution = sub.resolution
if (resolution.includes('D')) {
// 1 day in minutes === 1440
resolution = 1440
} else if (resolution.includes('W')) {
// 1 week in minutes === 10080
resolution = 10080
}
var coeff = resolution * 60
// console.log({coeff})
var rounded = Math.floor(data.ts / coeff) * coeff
var lastBarSec = lastBar.time / 1000
var _lastBar
if (rounded > lastBarSec) {
// create a new candle, use last close as open **PERSONAL CHOICE**
// 기존 코드
_lastBar = {
time: rounded * 1000,
open: lastBar.close,
high: lastBar.close,
low: lastBar.close,
close: data.price,
volume: data.volume
}
// 변경 코드
_lastBar = {
time: rounded * 1000,
open: lastBar.close,
high: lastBar.close,
low: lastBar.close,
close: data.price,
volume: data.volume
}
} else {
// update lastBar candle!
if (data.price < lastBar.low) {
lastBar.low = data.price
} else if (data.price > lastBar.high) {
lastBar.high = data.price
}
lastBar.volume += data.volume
lastBar.close = data.price
_lastBar = lastBar
}
return _lastBar
}
/ticker 채널에서 받아오는 데이터는 위에서 언급한 데이터 포맷입니다. 또한 거래소 이름을 BITUMB로 한 이유는 현재 트레이딩 뷰 측에서 승인이 되지 않은 거래소를 사용할 수 없기 때문에 임시로 지정했습니다.
따라서 다음과 같이 index.jsx의 symbol도 변경합니다.
import * as React from "react";
import "./index.css";
import Datafeed from "./api/";
function getLanguageFromURL() {
const regex = new RegExp("[\\?&]lang=([^&#]*)");
const results = regex.exec(window.location.search);
return results === null ? null : decodeURIComponent(results[1].replace(/\+/g, " "));
}
export class TVChartContainer extends React.PureComponent {
static defaultProps = {
symbol: "BITHUMB:BTC/KRW",
interval: "1",
containerId: "tv_chart_container",
libraryPath: "/charting_library/",
chartsStorageUrl: "https://saveload.tradingview.com",
chartsStorageApiVersion: "1.1",
clientId: "tradingview.com",
userId: "public_user_id",
fullscreen: false,
autosize: true,
studiesOverrides: {},
};
componentDidMount() {
const widgetOptions = {
debug: false,
symbol: this.props.symbol,
datafeed: Datafeed,
interval: this.props.interval,
container_id: this.props.containerId,
library_path: this.props.libraryPath,
locale: getLanguageFromURL() || "en",
disabled_features: ["use_localstorage_for_settings"],
enabled_features: ["study_templates"],
charts_storage_url: this.props.chartsStorageUrl,
charts_storage_api_version: this.props.chartsStorageApiVersion,
client_id: this.props.clientId,
user_id: this.props.userId,
fullscreen: this.props.fullscreen,
autosize: this.props.autosize,
studies_overrides: this.props.studiesOverrides,
overrides: {
"mainSeriesProperties.showCountdown": true,
"paneProperties.background": "#fff",
"paneProperties.vertGridProperties.color": "#E6EFF4",
"paneProperties.horzGridProperties.color": "#E6EFF4",
"symbolWatermarkProperties.transparency": 90,
"scalesProperties.textColor": "#AAA",
"mainSeriesProperties.candleStyle.wickUpColor": "#336854",
"mainSeriesProperties.candleStyle.wickDownColor": "#7f323f"
}
};
Datafeed.onReady(() => {
const widget = (window.tvWidget = new window.TradingView.widget(widgetOptions));
widget.onChartReady(() => {
console.log("Chart has loaded!");
});
});
}
render() {
return <div id={this.props.containerId} className={"TVChartContainer"} />;
}
}
※ 2 편은 업비트의 시세 수신 API를 이용해서 간단하게 최신시세를 반영하는 예제입니다. 승인 관련 문제때문에 BITUMB의 거래소 이름으로 진행했으며, 정상적으로 트레이딩뷰 측의 신청서를 통해서 인증을 받으신 분들은 자체 거래소 이름을 작성하시면 됩니다.
※ 요즘 정신이 없네요. 많은 분들이 2편을 요청하셔서 간략하게 나마 작성해봤습니다. 너무 간략하기는 하지만, 질문 사항 있으신 분들은 댓글 또는 방명록에 작성해주시면 최대한 답변해드리겠습니다 :)
예정 사항으로는 차트의 색상 변경 및 업비트 시세 수신 가상 소켓 서버 구현 등을 생각하고 있습니다. 여유가 생기는 대로 작성해보도록 하겠습니다..🙇♂️
감사합니다.
이 글을 작성하기 위해 Jon Church님의 글 을 참고하였습니다.
'개발관련 > 차트' 카테고리의 다른 글
트레이딩 뷰 차트 적용하기 - 까먹는 개발자 (40) | 2019.07.10 |
---|
Comments