2020-08-08 13:37:18 +00:00
|
|
|
<template>
|
2021-06-22 19:04:33 +00:00
|
|
|
<div class="d-flex h-100">
|
|
|
|
<div class="flex-fill container-fluid flex-column align-items-stretch d-flex h-100">
|
|
|
|
<b-modal
|
2021-06-23 18:33:56 +00:00
|
|
|
v-if="plotConfigModal"
|
2021-06-22 19:04:33 +00:00
|
|
|
id="plotConfiguratorModal"
|
|
|
|
title="Plot Configurator"
|
|
|
|
ok-only
|
|
|
|
hide-backdrop
|
|
|
|
button-size="sm"
|
|
|
|
>
|
|
|
|
<PlotConfigurator v-model="plotConfig" :columns="datasetColumns" />
|
|
|
|
</b-modal>
|
|
|
|
|
|
|
|
<div class="row mr-0">
|
|
|
|
<div class="col-mb-2 ml-2">
|
|
|
|
<b-select v-model="pair" :options="availablePairs" size="sm" @change="refresh">
|
|
|
|
</b-select>
|
|
|
|
</div>
|
|
|
|
<div class="col-mb-2 ml-2 mr-2">
|
|
|
|
<b-button :disabled="!!!pair" size="sm" @click="refresh">↻</b-button>
|
|
|
|
</div>
|
|
|
|
<div v-if="hasDataset" class="col-mb-2 ml-2 mr-2">
|
|
|
|
<small>Buysignals: {{ dataset.buy_signals }}</small>
|
|
|
|
<small class="ml-2">SellSignals: {{ dataset.sell_signals }}</small>
|
|
|
|
</div>
|
|
|
|
<div class="col-mb-2 ml-auto mr-2">
|
|
|
|
<b-select
|
|
|
|
v-model="plotConfigName"
|
|
|
|
:options="availablePlotConfigNames"
|
|
|
|
size="sm"
|
|
|
|
@change="plotConfigChanged"
|
|
|
|
>
|
|
|
|
</b-select>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="col-mb-2 mr-1">
|
|
|
|
<b-button size="sm" title="Plot configurator" @click="showConfigurator">⚙</b-button>
|
|
|
|
</div>
|
2020-09-27 07:24:12 +00:00
|
|
|
</div>
|
2021-06-22 19:04:33 +00:00
|
|
|
<div class="row mr-1 ml-1 h-100">
|
|
|
|
<CandleChart
|
|
|
|
v-if="hasDataset"
|
|
|
|
:dataset="dataset"
|
|
|
|
:trades="trades"
|
|
|
|
:plot-config="plotConfig"
|
2021-07-01 05:15:11 +00:00
|
|
|
:use-u-t-c="timezone === 'UTC'"
|
2021-06-22 19:04:33 +00:00
|
|
|
:theme="getChartTheme"
|
2020-08-08 13:57:36 +00:00
|
|
|
>
|
2021-06-22 19:04:33 +00:00
|
|
|
</CandleChart>
|
|
|
|
<label v-else style="margin: auto auto; font-size: 1.5rem">No data available</label>
|
2020-08-08 13:37:18 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
2021-06-22 19:04:33 +00:00
|
|
|
<transition name="fade" mode="in-out">
|
2021-06-23 18:33:56 +00:00
|
|
|
<div v-if="!plotConfigModal" v-show="showPlotConfig" class="w-25 config-sidebar">
|
2021-06-23 04:45:18 +00:00
|
|
|
<PlotConfigurator v-model="plotConfig" :columns="datasetColumns" :as-modal="false" />
|
2021-06-22 19:04:33 +00:00
|
|
|
</div>
|
|
|
|
</transition>
|
2020-08-08 13:37:18 +00:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2020-09-14 17:56:43 +00:00
|
|
|
import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
|
2020-12-28 19:52:18 +00:00
|
|
|
import { Getter, namespace } from 'vuex-class';
|
2020-09-14 17:56:43 +00:00
|
|
|
import {
|
|
|
|
Trade,
|
|
|
|
PairHistory,
|
|
|
|
EMPTY_PLOTCONFIG,
|
|
|
|
PlotConfig,
|
|
|
|
PairCandlePayload,
|
|
|
|
PairHistoryPayload,
|
|
|
|
} from '@/types';
|
2020-08-08 13:38:47 +00:00
|
|
|
import CandleChart from '@/components/charts/CandleChart.vue';
|
|
|
|
import PlotConfigurator from '@/components/charts/PlotConfigurator.vue';
|
2020-08-08 13:57:36 +00:00
|
|
|
import { getCustomPlotConfig, getPlotConfigName } from '@/shared/storage';
|
2020-10-31 07:47:07 +00:00
|
|
|
import { BotStoreGetters } from '@/store/modules/ftbot';
|
2021-07-01 05:15:11 +00:00
|
|
|
import { SettingsGetters } from '@/store/modules/settings';
|
2020-08-08 13:57:36 +00:00
|
|
|
|
|
|
|
const ftbot = namespace('ftbot');
|
2021-07-01 05:15:11 +00:00
|
|
|
const uiSettingsNs = namespace('uiSettings');
|
2020-08-08 13:37:18 +00:00
|
|
|
|
|
|
|
@Component({ components: { CandleChart, PlotConfigurator } })
|
|
|
|
export default class CandleChartContainer extends Vue {
|
2020-09-14 17:56:43 +00:00
|
|
|
@Prop({ required: true }) readonly availablePairs!: string[];
|
|
|
|
|
2020-08-08 13:37:18 +00:00
|
|
|
@Prop({ required: true }) readonly timeframe!: string;
|
|
|
|
|
2020-12-05 16:44:18 +00:00
|
|
|
@Prop({ required: false, default: () => [] }) readonly trades!: Array<Trade>;
|
2020-08-08 13:37:18 +00:00
|
|
|
|
2020-09-14 17:56:43 +00:00
|
|
|
@Prop({ required: false, default: false }) historicView!: boolean;
|
|
|
|
|
2021-06-22 19:04:33 +00:00
|
|
|
@Prop({ required: false, default: true }) plotConfigModal!: boolean;
|
|
|
|
|
2020-09-14 17:56:43 +00:00
|
|
|
/** Only required if historicView is true */
|
|
|
|
@Prop({ required: false, default: false }) timerange!: string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Only required if historicView is true
|
|
|
|
*/
|
|
|
|
@Prop({ required: false, default: false }) strategy!: string;
|
|
|
|
|
|
|
|
pair = '';
|
2020-08-08 13:37:18 +00:00
|
|
|
|
|
|
|
plotConfig: PlotConfig = { ...EMPTY_PLOTCONFIG };
|
|
|
|
|
2020-08-08 13:57:36 +00:00
|
|
|
plotConfigName = '';
|
|
|
|
|
2021-06-25 16:46:30 +00:00
|
|
|
showPlotConfig = this.plotConfigModal;
|
2021-06-22 19:04:33 +00:00
|
|
|
|
2020-12-28 19:52:18 +00:00
|
|
|
@Getter getChartTheme!: string;
|
|
|
|
|
2020-08-08 13:57:36 +00:00
|
|
|
@ftbot.State availablePlotConfigNames!: Array<string>;
|
|
|
|
|
2020-08-24 18:20:54 +00:00
|
|
|
@ftbot.Action setPlotConfigName;
|
|
|
|
|
2020-09-14 17:56:43 +00:00
|
|
|
@ftbot.State candleData!: PairHistory;
|
|
|
|
|
|
|
|
@ftbot.State history!: PairHistory;
|
|
|
|
|
2020-10-31 07:47:07 +00:00
|
|
|
@ftbot.Getter [BotStoreGetters.selectedPair]!: string;
|
|
|
|
|
2020-09-14 17:56:43 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
@ftbot.Action public getPairCandles!: (payload: PairCandlePayload) => void;
|
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
@ftbot.Action public getPairHistory!: (payload: PairHistoryPayload) => void;
|
|
|
|
|
2021-07-01 05:15:11 +00:00
|
|
|
@uiSettingsNs.Getter [SettingsGetters.timezone]: string;
|
|
|
|
|
2020-09-27 07:24:12 +00:00
|
|
|
get dataset(): PairHistory {
|
2020-09-14 17:56:43 +00:00
|
|
|
if (this.historicView) {
|
|
|
|
return this.history[`${this.pair}__${this.timeframe}`];
|
|
|
|
}
|
|
|
|
return this.candleData[`${this.pair}__${this.timeframe}`];
|
|
|
|
}
|
|
|
|
|
2020-08-08 13:37:18 +00:00
|
|
|
get datasetColumns() {
|
|
|
|
return this.dataset ? this.dataset.columns : [];
|
|
|
|
}
|
|
|
|
|
2020-09-27 07:37:07 +00:00
|
|
|
get hasDataset(): boolean {
|
|
|
|
return !!this.dataset;
|
|
|
|
}
|
|
|
|
|
2020-08-08 13:37:18 +00:00
|
|
|
mounted() {
|
2021-06-23 16:55:17 +00:00
|
|
|
if (this.selectedPair) {
|
|
|
|
this.pair = this.selectedPair;
|
|
|
|
} else if (this.availablePairs.length > 0) {
|
|
|
|
[this.pair] = this.availablePairs;
|
|
|
|
}
|
2020-08-08 13:57:36 +00:00
|
|
|
this.plotConfigName = getPlotConfigName();
|
|
|
|
this.plotConfig = getCustomPlotConfig(this.plotConfigName);
|
|
|
|
}
|
|
|
|
|
|
|
|
plotConfigChanged() {
|
2020-08-24 18:20:54 +00:00
|
|
|
console.log('plotConfigChanged');
|
2020-08-08 13:57:36 +00:00
|
|
|
this.plotConfig = getCustomPlotConfig(this.plotConfigName);
|
2020-08-24 18:20:54 +00:00
|
|
|
this.setPlotConfigName(this.plotConfigName);
|
2020-08-08 13:37:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
showConfigurator() {
|
2021-06-22 19:04:33 +00:00
|
|
|
if (this.plotConfigModal) {
|
|
|
|
this.$bvModal.show('plotConfiguratorModal');
|
|
|
|
} else {
|
|
|
|
this.showPlotConfig = !this.showPlotConfig;
|
|
|
|
}
|
2020-08-08 13:37:18 +00:00
|
|
|
}
|
2020-09-14 17:56:43 +00:00
|
|
|
|
|
|
|
refresh() {
|
|
|
|
if (this.pair && this.timeframe) {
|
|
|
|
if (this.historicView) {
|
|
|
|
this.getPairHistory({
|
|
|
|
pair: this.pair,
|
|
|
|
timeframe: this.timeframe,
|
|
|
|
timerange: this.timerange,
|
|
|
|
strategy: this.strategy,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.getPairCandles({ pair: this.pair, timeframe: this.timeframe, limit: 500 });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Watch('availablePairs')
|
|
|
|
watchAvailablePairs() {
|
2020-11-10 19:23:43 +00:00
|
|
|
if (!this.availablePairs.find((pair) => pair === this.pair)) {
|
|
|
|
[this.pair] = this.availablePairs;
|
|
|
|
this.refresh();
|
|
|
|
}
|
2020-09-14 17:56:43 +00:00
|
|
|
}
|
2020-10-31 07:47:07 +00:00
|
|
|
|
|
|
|
@Watch(BotStoreGetters.selectedPair)
|
|
|
|
watchSelectedPair() {
|
|
|
|
this.pair = this.selectedPair;
|
|
|
|
this.refresh();
|
|
|
|
}
|
2020-08-08 13:37:18 +00:00
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
2021-06-22 19:04:33 +00:00
|
|
|
<style scoped lang="scss">
|
|
|
|
.fade-enter-active,
|
|
|
|
.fade-leave-active {
|
|
|
|
transition: all 0.2s;
|
|
|
|
}
|
|
|
|
|
|
|
|
.fade-enter,
|
|
|
|
.fade-leave-to {
|
|
|
|
opacity: 0;
|
|
|
|
transform: translateX(30px);
|
|
|
|
}
|
|
|
|
</style>
|