웹훅 설정과 서버에서 해줘야할 작성을 모두 마쳤습니다. 이제는 클라이언트에게 보여줘야할 코드를 작성할 차례입니다.
페이지에서 보여질 요소는 디폴트로 BTC/USDT가 있고, 각 포지션에 따른 실시간 가격과 포지션 정보, PNL, 해당 코인의 차트보기, 긴급상황을 대비한 수동청산, 승/패, 롱/숏 비율정도가 있습니다.
1. 차트
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
var ctx1 = document.getElementById('line-chart-1');
var myChart1 = new Chart(ctx1, {
type: 'line',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'],
datasets: [{
label: 'PNL',
data: [1000, 1300, 900, 1267, 1117, 1500,
1817, 1555, 1317, 1920, 2000, 2321],
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 2,
fill: false
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
chart.js를 활용해 만들었습니다. Flask에서 해당 라이브러리를 사용할 때 주의할 점으로 JS파일을 static 폴더에서 가져오면 동작하지 않는다는 것입니다. 그래서 html 파일 밑에 script 태그를 이용하여 작성했습니다.
Flask에서 render_template를 이용해 데이터를 넘겨주고 이를 JS에서 받아오려면 다음의 코드를 사용할 수 있습니다.
var 변수명 = {{변수명|tojson}};
2. 실시간 가격
def binance_socket_thread():
# url = f"wss://stream.binance.com:9443/ws/{coin}@trade" // 단일코인(현물)
# url = f"wss://stream.binance.com:9443/ws/!ticker@arr" // 모든코인(현물)
url = f"wss://fstream.binance.com/ws/!markPrice@arr" // 선물만
def on_message(ws,message):
data = json.loads(message)
socketio.emit('binance_trade', data)
def on_error(ws,error):
print(error)
while True:
try:
ws = websocket.WebSocketApp(url, on_message=on_message, on_error=on_error)
ws.run_forever()
except Exception as e:
print('error:', e)
ws.close()
time.sleep(5)
@socketio.on('connect')
def handle_connect():
# with app.app_context():
print('WebSocket Client Connected')
@socketio.on('disconnect')
def handle_disconnect():
# with app.app_context():
print('WebSocket Client Disconnected')
@socketio.on('request')
def handle_message(message):
# with app.app_context():
print('Received message:', message)
socketio.emit('response', {'data': 'Server response'})
실시간 가격을 가져오려면 웹소켓을 활용해 가져와야합니다. 그리고 간혹 웹소켓이 context 밖에서 요청한다는 경우가 있는데 그런 경우 with app.app_context() 구문 안에 웹소켓을 실행하면됩니다.
서버에서 위와 같이 넘겨주면 JS에서 넘겨준 데이터를 받아와 화면에 표시합니다.
var socket = io.connect('http://127.0.0.1:5000/');
socket.on('connect', function() {
// console.log('WebSocket Client Connected');
});
socket.on('response', function(data) {
// console.log('Received response:', data);
});
socket.on('binance_trade', function(data) {
// console.log('Binance Trade:', data);
for(var i=0; i<data.length; i++){
// 여기서 데이터 처리 또는 화면에 표시 작업 수행
var name1Value = document.getElementById("name1").textContent
var name2Value = document.getElementById("name2").textContent
var name3Value = document.getElementById("name3").textContent
var name4Value = document.getElementById("name4").textContent
var name5Value = document.getElementById("name5").textContent
if (data[i]['s'] == 'BTCUSDT') document.getElementById('price0').innerHTML = '$ ' + parseFloat(data[i]['p']).toFixed(2);
if (data[i]['s'] == name1Value) document.getElementById('price1').innerHTML = '$ ' + parseFloat(data[i]['p']).toFixed(6);
if (data[i]['s'] == name2Value) document.getElementById('price2').innerHTML = '$ ' + parseFloat(data[i]['p']).toFixed(6);
if (data[i]['s'] == name3Value) document.getElementById('price3').innerHTML = '$ ' + parseFloat(data[i]['p']).toFixed(6);
if (data[i]['s'] == name4Value) document.getElementById('price4').innerHTML = '$ ' + parseFloat(data[i]['p']).toFixed(6);
if (data[i]['s'] == name5Value) document.getElementById('price5').innerHTML = '$ ' + parseFloat(data[i]['p']).toFixed(6);
}
});
그리고 각 영역에 잡힌 포지션에 대해 정보를 띄워주기 위해서는 Ajax를 활용해 일정 시간마다 지속적으로 API를 요청할 수 있습니다.
3. 포지션별 차트
<script type="text/javascript" src="https://s3.tradingview.com/tv.js"></script>
<script type="text/javascript">
var chart_btn = document.querySelectorAll('#chart-btn');
chart_btn.forEach(function(chart_btn){
chart_btn.addEventListener('click',function(event){
var card = chart_btn.getAttribute('data-name-id');
var symbol = document.getElementById(card).textContent;
if (chart_btn.textContent == '차트보기')
{
chart_btn.textContent = '차트닫기';
new TradingView.widget(
{
// "autosize":true,
"width": '100%',
"hight": 600,
"symbol": "BINANCE:" + symbol + ".P",
"interval": "15",
"timezone": "Etc/UTC",
"theme": "dark",
"style": "1",
"locale": "kr",
"enable_publishing": false,
"allow_symbol_change": true,
"gridColor": "rgba(0, 0, 0, 0.01)",
"container_id": "tradingview_e84e6"
}
);
}
else if(chart_btn.textContent == '차트닫기')
{
chart_btn.textContent = '차트보기';
document.getElementById('tradingview_e84e6').innerHTML = '';
}
})
})
</script>
TradingView에서 제공하는 차트를 가져오는 것은 매우 쉽습니다. TradingView에서 위젯 형태로 매우 손쉽게 제공하고 있기 때문입니다.
차트보기 버튼을 누르면 해당 심볼에 맞게 트레이딩뷰 차트가 열리며 차트 닫기를 누를시 다시 닫혀지게 됩니다.
해당 프로젝트는 TradingView 얼러트 웹훅을 이용한 매매를 진행하는데, 매번 바이낸스를 들어가기도 귀찮고 실제 들어가 있는 포지션만 보면 좋겠다 싶어 짧게 구현해봤습니다. 사실 보완요소와 더불어 저만이 아닌 다른 사용자가 이용한 경우까지 포함한다면 아직 나아가야할 길이 더 많고, 리팩토링도 여러번 되야할 것입니다.
본 글은 웹프로젝트의 기록물입니다.
This article is a record of the web project.
'Side Project > Flask' 카테고리의 다른 글
[Flask] TradingView를 활용한 암호화폐 매수/매도 (2) (0) | 2023.08.28 |
---|---|
[Flask] TradingView를 활용한 암호화폐 매수/매도 (1) (0) | 2023.08.28 |