2020-06-17 18:38:25 +00:00
|
|
|
<template>
|
2020-08-08 13:37:18 +00:00
|
|
|
<div class="row flex-grow-1 chart-wrapper">
|
|
|
|
<v-chart v-if="hasData" theme="dark" autoresize :options="chartOptions" />
|
2020-06-17 18:38:25 +00:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
2020-06-23 19:48:37 +00:00
|
|
|
<script lang="ts">
|
2020-06-25 04:55:41 +00:00
|
|
|
import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
|
2020-06-17 18:38:25 +00:00
|
|
|
import ECharts from 'vue-echarts';
|
2020-06-25 04:51:47 +00:00
|
|
|
import * as echarts from 'echarts';
|
2020-08-08 13:57:36 +00:00
|
|
|
import { Trade, PairHistory, PlotConfig } from '@/types';
|
2020-07-24 05:57:14 +00:00
|
|
|
import randomColor from '@/shared/randomColor';
|
|
|
|
import { roundTimeframe } from '@/shared/timemath';
|
2020-07-13 19:38:18 +00:00
|
|
|
|
2020-06-17 18:38:25 +00:00
|
|
|
import 'echarts';
|
|
|
|
|
2020-06-24 05:01:03 +00:00
|
|
|
// Chart default options
|
2020-09-14 17:55:21 +00:00
|
|
|
const MARGINLEFT = '4%';
|
|
|
|
const MARGINRIGHT = '1%';
|
2020-09-12 07:30:40 +00:00
|
|
|
// const upColor = '#00da3c';
|
|
|
|
// const downColor = '#ec0000';
|
|
|
|
// const upBorderColor = '#008F28';
|
|
|
|
// const downBorderColor = '#8A0000';
|
|
|
|
|
|
|
|
// Binance colors
|
|
|
|
const upColor = '#2ed191';
|
|
|
|
const upBorderColor = '#19d189';
|
|
|
|
const downColor = '#f84960';
|
|
|
|
const downBorderColor = '#e33249';
|
2020-06-20 06:35:22 +00:00
|
|
|
|
2020-06-23 19:48:37 +00:00
|
|
|
@Component({
|
2020-08-08 13:37:18 +00:00
|
|
|
components: { 'v-chart': ECharts },
|
2020-06-23 19:48:37 +00:00
|
|
|
})
|
|
|
|
export default class CandleChart extends Vue {
|
2020-07-13 18:52:29 +00:00
|
|
|
@Prop({ required: false, default: [] }) readonly trades!: Array<Trade>;
|
|
|
|
|
2020-06-25 04:51:47 +00:00
|
|
|
@Prop({ required: true }) readonly dataset!: PairHistory;
|
2020-06-20 06:35:22 +00:00
|
|
|
|
2020-08-08 13:37:18 +00:00
|
|
|
@Prop({ default: true }) readonly useUTC!: boolean;
|
2020-06-20 06:35:22 +00:00
|
|
|
|
2020-08-08 13:37:18 +00:00
|
|
|
@Prop({ required: true }) plotConfig!: PlotConfig;
|
2020-07-28 18:39:42 +00:00
|
|
|
|
2020-06-24 05:10:40 +00:00
|
|
|
// Only recalculate buy / sell data if necessary
|
|
|
|
signalsCalculated = false;
|
|
|
|
|
|
|
|
buyData = [] as Array<number>[];
|
|
|
|
|
|
|
|
sellData = [] as Array<number>[];
|
|
|
|
|
2020-06-25 04:55:41 +00:00
|
|
|
@Watch('timeframe')
|
|
|
|
timeframeChanged() {
|
|
|
|
this.signalsCalculated = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Watch('dataset')
|
|
|
|
datasetChanged() {
|
|
|
|
this.signalsCalculated = false;
|
|
|
|
}
|
|
|
|
|
2020-07-31 05:30:49 +00:00
|
|
|
get strategy() {
|
|
|
|
return this.dataset ? this.dataset.strategy : '';
|
|
|
|
}
|
|
|
|
|
|
|
|
get pair() {
|
|
|
|
return this.dataset ? this.dataset.pair : '';
|
|
|
|
}
|
|
|
|
|
2020-09-14 06:02:37 +00:00
|
|
|
get timeframe() {
|
|
|
|
return this.dataset ? this.dataset.timeframe : '';
|
|
|
|
}
|
|
|
|
|
2020-09-14 17:28:27 +00:00
|
|
|
get timeframems() {
|
|
|
|
return this.dataset ? this.dataset.timeframe_ms : 0;
|
|
|
|
}
|
|
|
|
|
2020-07-28 18:34:32 +00:00
|
|
|
get datasetColumns() {
|
|
|
|
return this.dataset ? this.dataset.columns : [];
|
|
|
|
}
|
|
|
|
|
2020-06-23 19:48:37 +00:00
|
|
|
get hasData() {
|
|
|
|
return this.dataset !== null && typeof this.dataset === 'object';
|
|
|
|
}
|
|
|
|
|
2020-07-13 18:52:29 +00:00
|
|
|
get filteredTrades() {
|
|
|
|
return this.trades.filter((item: Trade) => item.pair === this.pair);
|
|
|
|
}
|
|
|
|
|
2020-06-23 19:48:37 +00:00
|
|
|
get chartOptions() {
|
|
|
|
if (!this.hasData) {
|
|
|
|
return {};
|
|
|
|
}
|
2020-06-24 05:01:03 +00:00
|
|
|
|
2020-09-27 07:37:07 +00:00
|
|
|
// console.log(`Available Columns: ${this.dataset.columns}`);
|
2020-06-23 19:48:37 +00:00
|
|
|
// Find default columns (sequence might be different, depending on the strategy)
|
2020-07-27 05:20:35 +00:00
|
|
|
const colDate = this.dataset.columns.findIndex((el) => el === '__date_ts');
|
2020-06-23 19:48:37 +00:00
|
|
|
const colOpen = this.dataset.columns.findIndex((el) => el === 'open');
|
|
|
|
const colHigh = this.dataset.columns.findIndex((el) => el === 'high');
|
|
|
|
const colLow = this.dataset.columns.findIndex((el) => el === 'low');
|
|
|
|
const colClose = this.dataset.columns.findIndex((el) => el === 'close');
|
|
|
|
const colVolume = this.dataset.columns.findIndex((el) => el === 'volume');
|
2020-07-02 17:58:06 +00:00
|
|
|
const colBuyData = this.dataset.columns.findIndex((el) => el === '_buy_signal_open');
|
|
|
|
const colSellData = this.dataset.columns.findIndex((el) => el === '_sell_signal_open');
|
2020-07-11 13:34:14 +00:00
|
|
|
|
2020-08-09 12:34:50 +00:00
|
|
|
const subplotCount =
|
|
|
|
'subplots' in this.plotConfig ? Object.keys(this.plotConfig.subplots).length : 0;
|
|
|
|
|
2020-11-10 16:52:17 +00:00
|
|
|
// console.log(`subplotcount: ${subplotCount}`);
|
2020-08-09 12:34:50 +00:00
|
|
|
|
2020-07-11 13:34:14 +00:00
|
|
|
// Always show ~250 candles max as starting point
|
|
|
|
const startingZoom = (1 - 250 / this.dataset.length) * 100;
|
2020-06-24 05:10:40 +00:00
|
|
|
|
2020-06-25 04:51:47 +00:00
|
|
|
const options: echarts.EChartOption = {
|
2020-06-23 19:48:37 +00:00
|
|
|
title: {
|
2020-07-31 05:30:49 +00:00
|
|
|
text: `${this.strategy} - ${this.pair} - ${this.timeframe}`,
|
2020-06-23 19:48:37 +00:00
|
|
|
show: true,
|
|
|
|
},
|
2020-09-30 13:20:58 +00:00
|
|
|
backgroundColor: '#1b1b1b',
|
2020-07-28 18:39:42 +00:00
|
|
|
useUTC: this.useUTC,
|
2020-06-23 19:48:37 +00:00
|
|
|
dataset: {
|
|
|
|
source: this.dataset.data,
|
|
|
|
},
|
|
|
|
animation: false,
|
|
|
|
legend: {
|
2020-06-25 04:51:47 +00:00
|
|
|
data: ['Candles', 'Volume', 'Buy', 'Sell'],
|
2020-09-16 17:37:28 +00:00
|
|
|
right: '1%',
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
tooltip: {
|
2020-10-02 05:02:30 +00:00
|
|
|
show: true,
|
2020-06-23 19:48:37 +00:00
|
|
|
trigger: 'axis',
|
|
|
|
axisPointer: {
|
|
|
|
type: 'cross',
|
|
|
|
lineStyle: {
|
|
|
|
color: '#cccccc',
|
|
|
|
width: 1,
|
|
|
|
opacity: 1,
|
|
|
|
},
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
axisPointer: {
|
2020-06-25 04:51:47 +00:00
|
|
|
link: [{ xAxisIndex: 'all' }],
|
2020-06-23 19:48:37 +00:00
|
|
|
label: {
|
|
|
|
backgroundColor: '#777',
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
xAxis: [
|
|
|
|
{
|
2020-07-13 18:52:29 +00:00
|
|
|
type: 'time',
|
2020-06-23 19:48:37 +00:00
|
|
|
scale: true,
|
|
|
|
boundaryGap: false,
|
|
|
|
axisLine: { onZero: false },
|
2020-09-16 17:37:28 +00:00
|
|
|
axisTick: { show: true },
|
|
|
|
axisLabel: { show: true },
|
|
|
|
position: 'top',
|
2020-06-23 19:48:37 +00:00
|
|
|
splitLine: { show: false },
|
|
|
|
splitNumber: 20,
|
|
|
|
min: 'dataMin',
|
|
|
|
max: 'dataMax',
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
{
|
2020-07-13 18:52:29 +00:00
|
|
|
type: 'time',
|
2020-06-23 19:48:37 +00:00
|
|
|
gridIndex: 1,
|
|
|
|
scale: true,
|
|
|
|
boundaryGap: false,
|
|
|
|
axisLine: { onZero: false },
|
|
|
|
axisTick: { show: false },
|
|
|
|
axisLabel: { show: false },
|
2020-09-16 17:37:28 +00:00
|
|
|
splitLine: { show: false },
|
2020-06-23 19:48:37 +00:00
|
|
|
splitNumber: 20,
|
|
|
|
min: 'dataMin',
|
|
|
|
max: 'dataMax',
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
],
|
|
|
|
yAxis: [
|
|
|
|
{
|
|
|
|
scale: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
scale: true,
|
|
|
|
gridIndex: 1,
|
|
|
|
splitNumber: 2,
|
|
|
|
axisLabel: { show: false },
|
|
|
|
axisLine: { show: false },
|
|
|
|
axisTick: { show: false },
|
|
|
|
splitLine: { show: false },
|
|
|
|
},
|
|
|
|
],
|
|
|
|
grid: [
|
|
|
|
{
|
|
|
|
left: MARGINLEFT,
|
|
|
|
right: MARGINRIGHT,
|
2020-09-30 05:48:36 +00:00
|
|
|
// Grid Layout from bottom to top
|
2020-09-16 17:37:28 +00:00
|
|
|
bottom: `${subplotCount * 10 + 10}%`,
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
// Volume
|
|
|
|
left: MARGINLEFT,
|
|
|
|
right: MARGINRIGHT,
|
2020-09-30 05:48:36 +00:00
|
|
|
// Grid Layout from bottom to top
|
2020-09-30 13:20:58 +00:00
|
|
|
bottom: `${subplotCount * 10 + 5}%`,
|
2020-07-11 13:34:14 +00:00
|
|
|
height: '10%',
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
],
|
|
|
|
dataZoom: [
|
|
|
|
{
|
|
|
|
type: 'inside',
|
2020-06-25 04:51:47 +00:00
|
|
|
xAxisIndex: [0, 1],
|
2020-07-11 13:34:14 +00:00
|
|
|
start: startingZoom,
|
2020-06-23 19:48:37 +00:00
|
|
|
end: 100,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
show: true,
|
2020-06-25 04:51:47 +00:00
|
|
|
xAxisIndex: [0, 1],
|
2020-06-23 19:48:37 +00:00
|
|
|
type: 'slider',
|
|
|
|
bottom: 10,
|
2020-07-11 13:34:14 +00:00
|
|
|
start: startingZoom,
|
2020-06-23 19:48:37 +00:00
|
|
|
end: 100,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
// visualMap: {
|
|
|
|
// // TODO: this would allow to colorize volume bars (if we'd want this)
|
|
|
|
// // Needs green / red indicator column in data.
|
|
|
|
// show: true,
|
|
|
|
// seriesIndex: 1,
|
|
|
|
// dimension: 5,
|
|
|
|
// pieces: [
|
|
|
|
// {
|
|
|
|
// max: 500000.0,
|
|
|
|
// color: downColor,
|
|
|
|
// },
|
|
|
|
// {
|
|
|
|
// min: 500000.0,
|
|
|
|
// color: upColor,
|
|
|
|
// },
|
|
|
|
// ],
|
|
|
|
// },
|
|
|
|
series: [
|
|
|
|
{
|
|
|
|
name: 'Candles',
|
|
|
|
type: 'candlestick',
|
2020-09-12 07:13:56 +00:00
|
|
|
barWidth: '80%',
|
2020-06-23 19:48:37 +00:00
|
|
|
itemStyle: {
|
|
|
|
color: upColor,
|
|
|
|
color0: downColor,
|
|
|
|
borderColor: upBorderColor,
|
|
|
|
borderColor0: downBorderColor,
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
encode: {
|
2020-07-27 05:20:35 +00:00
|
|
|
x: colDate,
|
2020-06-23 19:48:37 +00:00
|
|
|
// open, close, low, high
|
|
|
|
y: [colOpen, colClose, colLow, colHigh],
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Volume',
|
|
|
|
type: 'bar',
|
|
|
|
xAxisIndex: 1,
|
|
|
|
yAxisIndex: 1,
|
|
|
|
itemStyle: {
|
|
|
|
color: '#777777',
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
large: true,
|
|
|
|
encode: {
|
2020-07-27 05:20:35 +00:00
|
|
|
x: colDate,
|
2020-06-23 19:48:37 +00:00
|
|
|
y: colVolume,
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Buy',
|
|
|
|
type: 'scatter',
|
|
|
|
symbol: 'triangle',
|
2020-09-27 07:23:35 +00:00
|
|
|
symbolSize: 10,
|
2020-06-23 19:48:37 +00:00
|
|
|
xAxisIndex: 0,
|
|
|
|
yAxisIndex: 0,
|
|
|
|
itemStyle: {
|
2020-09-27 07:23:35 +00:00
|
|
|
color: '#00ff26',
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
encode: {
|
2020-07-27 05:20:35 +00:00
|
|
|
x: colDate,
|
2020-07-02 17:58:06 +00:00
|
|
|
y: colBuyData,
|
2020-06-19 18:37:14 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'Sell',
|
|
|
|
type: 'scatter',
|
|
|
|
symbol: 'diamond',
|
2020-06-29 05:19:17 +00:00
|
|
|
symbolSize: 8,
|
2020-06-23 19:48:37 +00:00
|
|
|
xAxisIndex: 0,
|
|
|
|
yAxisIndex: 0,
|
|
|
|
itemStyle: {
|
|
|
|
color: '#FF0000',
|
2020-06-19 18:37:14 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
encode: {
|
2020-07-27 05:20:35 +00:00
|
|
|
x: colDate,
|
2020-07-02 17:58:06 +00:00
|
|
|
y: colSellData,
|
2020-06-17 18:38:25 +00:00
|
|
|
},
|
2020-06-23 19:48:37 +00:00
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
2020-06-25 04:51:47 +00:00
|
|
|
|
2020-07-02 17:58:06 +00:00
|
|
|
// this.createSignalData(colDate, colOpen, colBuy, colSell);
|
2020-06-25 04:51:47 +00:00
|
|
|
|
|
|
|
// This will be merged into final plot config
|
|
|
|
// const subPlots = {
|
|
|
|
// legend: [] as string[],
|
|
|
|
// grid: [] as object[],
|
|
|
|
// yaxis: [] as object[],
|
|
|
|
// xaxis: [] as object[],
|
|
|
|
// xaxisIndex: [] as number[],
|
|
|
|
// series: [] as object[],
|
|
|
|
// };
|
|
|
|
|
|
|
|
if ('main_plot' in this.plotConfig) {
|
|
|
|
Object.entries(this.plotConfig.main_plot).forEach(([key, value]) => {
|
|
|
|
const col = this.dataset.columns.findIndex((el) => el === key);
|
2020-11-17 07:15:38 +00:00
|
|
|
if (col > 1) {
|
|
|
|
if (options.legend && options.legend.data) {
|
|
|
|
options.legend.data.push(key);
|
|
|
|
}
|
|
|
|
const sp: echarts.EChartOption.Series = {
|
|
|
|
name: key,
|
|
|
|
type: value.type || 'line',
|
|
|
|
xAxisIndex: 0,
|
|
|
|
yAxisIndex: 0,
|
|
|
|
itemStyle: {
|
|
|
|
color: value.color,
|
|
|
|
},
|
|
|
|
encode: {
|
|
|
|
x: colDate,
|
|
|
|
y: col,
|
|
|
|
},
|
|
|
|
showSymbol: false,
|
|
|
|
};
|
|
|
|
if (options.series) {
|
|
|
|
options.series.push(sp);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.log(`element ${key} for main plot not found in columns.`);
|
2020-06-25 04:51:47 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-08-30 18:19:50 +00:00
|
|
|
// START Subplots
|
2020-06-25 04:51:47 +00:00
|
|
|
if ('subplots' in this.plotConfig) {
|
|
|
|
let plotIndex = 2;
|
|
|
|
Object.entries(this.plotConfig.subplots).forEach(([key, value]) => {
|
|
|
|
// define yaxis
|
|
|
|
if (options.yAxis && Array.isArray(options.yAxis)) {
|
|
|
|
options.yAxis.push({
|
|
|
|
scale: true,
|
|
|
|
gridIndex: plotIndex,
|
|
|
|
name: key,
|
|
|
|
nameLocation: 'middle',
|
|
|
|
nameGap: 60,
|
|
|
|
axisLabel: { show: true },
|
|
|
|
axisLine: { show: false },
|
|
|
|
axisTick: { show: false },
|
|
|
|
splitLine: { show: false },
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (options.xAxis && Array.isArray(options.xAxis)) {
|
|
|
|
options.xAxis.push({
|
2020-07-14 05:21:13 +00:00
|
|
|
type: 'time',
|
2020-06-25 04:51:47 +00:00
|
|
|
scale: true,
|
|
|
|
gridIndex: plotIndex,
|
|
|
|
boundaryGap: false,
|
|
|
|
axisLine: { onZero: false },
|
|
|
|
axisTick: { show: false },
|
|
|
|
axisLabel: { show: false },
|
2020-09-16 17:37:28 +00:00
|
|
|
splitLine: { show: false },
|
2020-06-25 04:51:47 +00:00
|
|
|
splitNumber: 20,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (options.dataZoom) {
|
|
|
|
options.dataZoom.forEach((el) =>
|
|
|
|
el.xAxisIndex && Array.isArray(el.xAxisIndex) ? el.xAxisIndex.push(plotIndex) : null,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (options.grid && Array.isArray(options.grid)) {
|
|
|
|
options.grid.push({
|
|
|
|
left: MARGINLEFT,
|
|
|
|
right: MARGINRIGHT,
|
2020-09-30 13:20:58 +00:00
|
|
|
bottom: `${plotIndex * 8}%`,
|
|
|
|
height: '8%',
|
2020-06-25 04:51:47 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
Object.entries(value).forEach(([sk, sv]) => {
|
|
|
|
if (options.legend && options.legend.data && Array.isArray(options.legend.data)) {
|
|
|
|
options.legend.data.push(sk);
|
|
|
|
}
|
|
|
|
// entries per subplot
|
|
|
|
const col = this.dataset.columns.findIndex((el) => el === sk);
|
2020-07-14 05:21:13 +00:00
|
|
|
if (col > 0) {
|
2020-07-13 18:52:29 +00:00
|
|
|
const sp: echarts.EChartOption.Series = {
|
2020-06-25 04:51:47 +00:00
|
|
|
name: sk,
|
2020-07-01 18:59:45 +00:00
|
|
|
type: sv.type || 'line',
|
2020-06-25 04:51:47 +00:00
|
|
|
xAxisIndex: plotIndex,
|
|
|
|
yAxisIndex: plotIndex,
|
|
|
|
itemStyle: {
|
|
|
|
color: sv.color || randomColor(),
|
|
|
|
},
|
|
|
|
encode: {
|
|
|
|
x: colDate,
|
|
|
|
y: col,
|
|
|
|
},
|
|
|
|
showSymbol: false,
|
|
|
|
};
|
|
|
|
if (options.series && Array.isArray(options.series)) {
|
|
|
|
options.series.push(sp);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.log(`element ${sk} was not found in the columns.`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
plotIndex += 1;
|
|
|
|
});
|
|
|
|
}
|
2020-08-30 18:19:50 +00:00
|
|
|
// END Subplots
|
2020-09-16 17:37:28 +00:00
|
|
|
// Last subplot should show xAxis labels
|
|
|
|
// if (options.xAxis && Array.isArray(options.xAxis)) {
|
|
|
|
// options.xAxis[options.xAxis.length - 1].axisLabel.show = true;
|
|
|
|
// options.xAxis[options.xAxis.length - 1].axisTick.show = true;
|
|
|
|
// }
|
|
|
|
if (options.grid && Array.isArray(options.grid)) {
|
2020-09-30 05:48:36 +00:00
|
|
|
// Last subplot is bottom
|
|
|
|
options.grid[options.grid.length - 1].bottom = '50px';
|
2020-09-16 17:37:28 +00:00
|
|
|
delete options.grid[options.grid.length - 1].top;
|
|
|
|
}
|
2020-06-25 04:51:47 +00:00
|
|
|
|
2020-07-13 18:52:29 +00:00
|
|
|
if (this.filteredTrades.length > 0) {
|
|
|
|
// Show trades
|
|
|
|
const trades: Array<string | number>[] = [];
|
|
|
|
const tradesClose: Array<string | number>[] = [];
|
|
|
|
for (let i = 0, len = this.filteredTrades.length; i < len; i += 1) {
|
|
|
|
const trade: Trade = this.filteredTrades[i];
|
|
|
|
if (
|
|
|
|
trade.open_timestamp >= this.dataset.data_start_ts &&
|
|
|
|
trade.open_timestamp <= this.dataset.data_stop_ts
|
|
|
|
) {
|
2020-09-12 07:26:26 +00:00
|
|
|
trades.push([roundTimeframe(this.timeframems, trade.open_timestamp), trade.open_rate]);
|
2020-07-13 18:52:29 +00:00
|
|
|
}
|
|
|
|
if (
|
|
|
|
trade.close_timestamp !== undefined &&
|
|
|
|
trade.close_timestamp < this.dataset.data_stop_ts &&
|
|
|
|
trade.close_timestamp > this.dataset.data_start_ts
|
|
|
|
) {
|
|
|
|
if (trade.close_date !== undefined && trade.close_rate !== undefined) {
|
2020-07-13 19:38:18 +00:00
|
|
|
tradesClose.push([
|
2020-09-12 07:26:26 +00:00
|
|
|
roundTimeframe(this.timeframems, trade.close_timestamp),
|
2020-07-13 19:38:18 +00:00
|
|
|
trade.close_rate,
|
|
|
|
]);
|
2020-07-13 18:52:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-14 05:21:13 +00:00
|
|
|
// console.log(`Trades: ${trades.length}`);
|
|
|
|
// console.log(trades);
|
|
|
|
// console.log(`ClosesTrades: ${tradesClose.length}`);
|
|
|
|
// console.log(tradesClose);
|
2020-07-13 18:52:29 +00:00
|
|
|
|
|
|
|
const name = 'Trades';
|
|
|
|
const nameClose = 'Trades Close';
|
|
|
|
if (options.legend && options.legend.data) {
|
|
|
|
options.legend.data.push(name);
|
|
|
|
}
|
|
|
|
const sp: echarts.EChartOption.SeriesScatter = {
|
|
|
|
name,
|
|
|
|
type: 'scatter',
|
|
|
|
xAxisIndex: 0,
|
|
|
|
yAxisIndex: 0,
|
|
|
|
itemStyle: {
|
|
|
|
color: 'cyan',
|
|
|
|
},
|
|
|
|
data: trades,
|
|
|
|
};
|
|
|
|
if (options.series) {
|
|
|
|
options.series.push(sp);
|
|
|
|
}
|
|
|
|
if (options.legend && options.legend.data) {
|
|
|
|
options.legend.data.push(nameClose);
|
|
|
|
}
|
|
|
|
const closeSeries: echarts.EChartOption.SeriesScatter = {
|
|
|
|
name: nameClose,
|
|
|
|
type: 'scatter',
|
|
|
|
xAxisIndex: 0,
|
|
|
|
yAxisIndex: 0,
|
|
|
|
itemStyle: {
|
|
|
|
color: 'pink',
|
|
|
|
},
|
|
|
|
data: tradesClose,
|
|
|
|
};
|
|
|
|
if (options.series) {
|
|
|
|
options.series.push(closeSeries);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-01 18:59:45 +00:00
|
|
|
// console.log(options);
|
2020-06-25 04:51:47 +00:00
|
|
|
// TODO: Rebuilding this causes a full redraw for every new step
|
|
|
|
return options;
|
2020-06-23 19:48:37 +00:00
|
|
|
}
|
2020-06-24 05:10:40 +00:00
|
|
|
|
2020-07-02 17:58:06 +00:00
|
|
|
// createSignalData(colDate: number, colOpen: number, colBuy: number, colSell: number): void {
|
|
|
|
// Calculate Buy and sell Series
|
|
|
|
// if (!this.signalsCalculated) {
|
|
|
|
// // Generate Buy and sell array (using open rate to display marker)
|
|
|
|
// for (let i = 0, len = this.dataset.data.length; i < len; i += 1) {
|
|
|
|
// if (this.dataset.data[i][colBuy] === 1) {
|
|
|
|
// this.buyData.push([this.dataset.data[i][colDate], this.dataset.data[i][colOpen]]);
|
|
|
|
// }
|
|
|
|
// if (this.dataset.data[i][colSell] === 1) {
|
|
|
|
// this.sellData.push([this.dataset.data[i][colDate], this.dataset.data[i][colOpen]]);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// this.signalsCalculated = true;
|
|
|
|
// }
|
|
|
|
// }
|
2020-06-23 19:48:37 +00:00
|
|
|
}
|
2020-06-17 18:38:25 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
2020-06-19 18:37:14 +00:00
|
|
|
.chart-wrapper {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
}
|
2020-06-17 18:38:25 +00:00
|
|
|
.echarts {
|
|
|
|
width: 100%;
|
2020-09-14 18:24:24 +00:00
|
|
|
min-height: 200px;
|
2020-06-17 18:38:25 +00:00
|
|
|
/* TODO: height calculation is not working correctly - uses min-height for now */
|
|
|
|
/* height: 600px; */
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
</style>
|