Skip to content

Instantly share code, notes, and snippets.

@thapld
Created April 18, 2023 03:52
Show Gist options
  • Save thapld/25005e4900f7794001300e73d870ac58 to your computer and use it in GitHub Desktop.
Save thapld/25005e4900f7794001300e73d870ac58 to your computer and use it in GitHub Desktop.
<template>
<div>
<div id="tvjs-header">
<h1>
<label>Crypto Trading</label>
</h1>
<div class="app-tags">
<button name="btnBuy" class="btn-buy" @click="onBuy()">Buy</button>
<button name="btnSell" class="btn-sell" @click="onSell()">Sell</button>
</div>
<span class="night-mode">
<input type="checkbox" v-model="night">
<label class="night-mode-label">NM</label>
</span>
</div>
<div id="app-container" :style="{top: top+'px'}">
<trading-vue :data="chart" :width="this.width" :height="this.height"
:timezone="7"
:legend-buttons="['display', 'settings', 'up', 'down', 'add', 'remove']"
:chart-config="{MIN_ZOOM:1, DEFAULT_LEN:70}"
:color-back="colors.colorBack"
:color-grid="colors.colorGrid"
:color-text="colors.colorText"
title-txt="BTCUSD"
:extensions="extensions"
ref="tvjs"
:overlays="ovs"
:x-settings="xsett">
</trading-vue>
</div>
</div>
</template>
<script>
import TradingVue from 'trading-vue-js'
import {DataCube} from 'trading-vue-js'
import Stream from './DataHelper/stream.js'
import Overlays from 'tvjs-overlays'
import Extensions from 'tvjs-xp'
import SetupIndicator from "@/overlays/SetupIndicator";
const URL = `https://api.binance.com/api/v3/klines?symbol=`
const WSS = `wss://stream.binance.com:9443/ws/btcusdt@ticker`
//wss://stream.binance.com:9443/ws/btcusdt@kline_1s
const WSS_LOCAL = `ws://127.0.0.1:8585/bo?x-access-key=6867485266f5404dad1138378275693e`
export default {
name: 'app',
description: 'Real-time BTC-USD',
components: {
TradingVue
},
mounted() {
window.addEventListener('resize', this.onResize)
this.onResize()
// Load the last data chunk & init DataCube:
let now = (new Date()).getTime()
this.load_chunk([now - 4 * 3600 * 1000, now]).then(data => {
this.chart = new DataCube({
ohlcv: data['chart.data'],
onchart: [
{
type: 'EMA',name: 'EMA 12', data: [],
settings: {length: 12}
},
{
type: 'EMA',name: 'EMA 26', data: [],
settings: {length: 26}
},
],
offchart: [
{
"name": "RSI, 20",
"type": "RSI",
"data": [],
"settings": {
"upper": 70,
"lower": 30,
"backColor": "#9b9ba316",
"bandColor": "#666"
}
},
],
}, { aggregation: 100 })
this.chart.onrange(this.load_chunk)
this.$refs.tvjs.resetChart()
this.stream = new Stream(WSS_LOCAL)
this.stream.ontrades = this.on_trades
window.dc = this.chart // Debug
window.tv = this.$refs.tvjs // Debug
})
},
methods: {
onBuy() {
this.chart.add('onchart',{
"name": "Data sections",
"type": "Splitters",
"data": [
[
1681742700000,
"BUY",
1,
"#FF6000"
]
],
"settings": {
"legend": false,
"lineColor": "#FF6000"
}
})
this.chart.add('onchart', {
name: 'Bet',
type: 'Setups',
data: [[1681742700000, 1, 29370.76, 1681743000000]],
settings: {
radius: 10,
color: '#F9D949',
legend: false
}
},)
this.chart.add('onchart',{
"name": "Data sections",
"type": "Splitters",
"data": [
[
1681743000000,
"Kết thúc",
1,
"#FF6000"
]
],
"settings": {
"legend": false,
"lineColor": "#FF6000"
}
})
},
onSell() {
},
onResize() {
this.width = window.innerWidth
this.height = window.innerHeight - this.top
},
// New data handler. Should return Promise, or
// use callback: load_chunk(range, tf, callback)
async load_chunk(range) {
let [t1, t2] = range
let x = 'BTCUSDT'
let q = `${x}&interval=1m&startTime=${t1}&endTime=${t2}`
let r = await fetch(URL + q).then(r => r.json())
return this.format(this.parse_binance(r))
},
// Parse a specific exchange format
parse_binance(data) {
if (!Array.isArray(data)) return []
return data.map(x => {
for (let i = 0; i < x.length; i++) {
x[i] = parseFloat(x[i])
}
return x.slice(0,6)
})
},
format(data) {
// Each query sets data to a corresponding overlay
return {
'chart.data': data
// other onchart/offchart overlays can be added here,
// but we are using Script Engine to calculate some:
// see EMAx6 & BuySellBalance
}
},
on_trades(trade) {
this.chart.update({
t: trade.msg.at/1000000, // Exchange time (optional)
price: parseFloat(trade.msg.close), // Trade price
volume: parseFloat(trade.msg.volume), // Trade amount
// ... other onchart/offchart updates
})
}
},
computed: {
colors() {
return this.night ? {} : {
colorBack: '#fff',
colorGrid: '#eee',
colorText: '#333'
}
},
},
beforeDestroy() {
window.removeEventListener('resize', this.onResize)
if (this.stream) this.stream.off()
},
data() {
return {
chart: {},
width: window.innerWidth,
height: window.innerHeight,
extensions: Object.values(Extensions),
night: true,
top: 50,
xsett: {
'grid-resize': { min_height: 30 }
},
ovs: [...Object.values(Overlays), SetupIndicator]
}
}
}
</script>
<style>
html,
body {
background-color: #000;
margin: 0;
padding: 0;
overflow: hidden;
font: 11px -apple-system,BlinkMacSystemFont,
Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,
Fira Sans,Droid Sans,Helvetica Neue,
sans-serif
}
#tvjs-header {
position: absolute;
height: 49px;
color: #ddd;
width: 100%;
background-color: #121826;
border-bottom: 1px solid black;
}
#tvjs-header img{
width: 40px;
height: 40px;
margin: 5px;
}
#tvjs-header label{
vertical-align: top;
line-height: 2.3em;
margin-left: 2px;
font-weight: 500;
}
#app-container {
position: absolute;
width: 100%;
}
#tvjs-header h1 {
color: #9b9ca0;
margin: 0px 0 0 3px;
}
#tvjs-header p {
position: absolute;
width: 100%;
top: 1px;
text-align: center;
font-family: -apple-system,BlinkMacSystemFont,
Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,
Fira Sans,Droid Sans,Helvetica Neue,
sans-serif;
font-weight: 200;
}
#extensions-lbl {
position: absolute;
top: 17px;
color: #5e6061;
right: 290px;
font-weight: 600;
}
.night-mode {
position: absolute;
top: 15px;
right: 20px;
}
.night-mode-label {
line-height: 1.6em !important;
}
.app-tags {
position: absolute;
top: 10px;
right: 100px;
}
.btn-buy{
background-color: #28a742;
padding: 5px 10px 5px 10px;
color: white;
margin-right: 10px;
}
.btn-sell{
background-color: #d80e0e;
padding: 5px 10px 5px 10px;
color: white;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment