2020-07-01 05:16:05 +00:00
|
|
|
<template>
|
2020-07-01 18:22:29 +00:00
|
|
|
<div v-if="columns">
|
2021-06-23 04:56:38 +00:00
|
|
|
<b-form-group label="Plot config name" label-for="idPlotConfigName">
|
2021-08-28 09:39:03 +00:00
|
|
|
<b-form-input id="idPlotConfigName" v-model="plotConfigNameLoc" size="sm"> </b-form-input>
|
2021-06-23 04:56:38 +00:00
|
|
|
</b-form-group>
|
|
|
|
<div class="col-mb-3">
|
2020-08-01 18:43:14 +00:00
|
|
|
<hr />
|
|
|
|
|
2021-06-23 04:56:38 +00:00
|
|
|
<b-form-group label="Target" label-for="FieldSel">
|
2021-06-23 18:33:56 +00:00
|
|
|
<b-form-select id="FieldSel" v-model="selSubPlot" :options="subplots" :select-size="3">
|
2020-07-01 18:22:29 +00:00
|
|
|
</b-form-select>
|
|
|
|
</b-form-group>
|
|
|
|
</div>
|
2021-06-23 04:56:38 +00:00
|
|
|
<b-form-group label="Add new plot" label-for="newSubPlot">
|
2020-08-01 18:43:14 +00:00
|
|
|
<b-input-group size="sm">
|
2021-06-23 04:56:38 +00:00
|
|
|
<b-form-input id="newSubPlot" v-model="newSubplotName" class="addPlot"></b-form-input>
|
2020-07-01 18:39:03 +00:00
|
|
|
<b-input-group-append>
|
|
|
|
<b-button @click="addSubplot">+</b-button>
|
2021-06-23 04:56:38 +00:00
|
|
|
<b-button v-if="selSubPlot && selSubPlot != 'main_plot'" @click="delSubplot">-</b-button>
|
2020-07-01 18:39:03 +00:00
|
|
|
</b-input-group-append>
|
|
|
|
</b-input-group>
|
2020-07-01 18:22:29 +00:00
|
|
|
</b-form-group>
|
2020-07-01 18:39:03 +00:00
|
|
|
<hr />
|
2021-06-24 05:18:06 +00:00
|
|
|
<div>
|
|
|
|
<b-form-group label="Used indicators" label-for="selectedIndicators">
|
2020-08-09 08:50:02 +00:00
|
|
|
<b-form-select
|
|
|
|
id="selectedIndicators"
|
2021-06-23 18:33:56 +00:00
|
|
|
v-model="selIndicatorName"
|
2020-08-09 08:50:02 +00:00
|
|
|
:options="usedColumns"
|
|
|
|
:select-size="4"
|
|
|
|
>
|
|
|
|
</b-form-select>
|
|
|
|
</b-form-group>
|
|
|
|
</div>
|
2021-06-23 18:33:56 +00:00
|
|
|
<div>
|
|
|
|
<b-button
|
|
|
|
variant="primary"
|
|
|
|
title="Add indicator to plot"
|
2021-06-23 04:45:18 +00:00
|
|
|
size="sm"
|
2021-06-23 18:33:56 +00:00
|
|
|
@click="addNewIndicator = !addNewIndicator"
|
2021-06-23 04:45:18 +00:00
|
|
|
>
|
2021-06-23 18:33:56 +00:00
|
|
|
Add new indicator
|
|
|
|
</b-button>
|
|
|
|
<b-button
|
|
|
|
variant="primary"
|
|
|
|
title="Remove indicator to plot"
|
|
|
|
size="sm"
|
|
|
|
:disabled="!selIndicatorName"
|
|
|
|
class="ml-1"
|
|
|
|
@click="removeIndicator"
|
|
|
|
>
|
|
|
|
Remove indicator
|
|
|
|
</b-button>
|
|
|
|
</div>
|
2020-07-01 18:22:29 +00:00
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
<PlotIndicator
|
|
|
|
v-model="selIndicator"
|
|
|
|
class="mt-1"
|
|
|
|
:columns="columns"
|
|
|
|
:add-new="addNewIndicator"
|
|
|
|
/>
|
2020-07-01 18:39:03 +00:00
|
|
|
<hr />
|
2021-06-23 04:56:38 +00:00
|
|
|
|
2021-06-24 05:18:06 +00:00
|
|
|
<div>
|
2021-06-22 19:08:03 +00:00
|
|
|
<b-button class="ml-1" variant="primary" size="sm" @click="loadPlotConfig">Load</b-button>
|
2020-08-08 13:57:36 +00:00
|
|
|
<b-button class="ml-1" variant="primary" size="sm" @click="loadPlotConfigFromStrategy">
|
2021-06-23 18:51:27 +00:00
|
|
|
From strategy
|
2020-07-28 18:39:58 +00:00
|
|
|
</b-button>
|
|
|
|
|
2020-07-11 15:50:59 +00:00
|
|
|
<b-button
|
2020-08-01 18:43:14 +00:00
|
|
|
class="ml-1"
|
2020-07-11 15:50:59 +00:00
|
|
|
variant="primary"
|
|
|
|
size="sm"
|
|
|
|
data-toggle="tooltip"
|
|
|
|
title="Save configuration"
|
2020-08-08 13:57:36 +00:00
|
|
|
@click="savePlotConfig"
|
2020-07-11 15:50:59 +00:00
|
|
|
>Save</b-button
|
|
|
|
>
|
|
|
|
<b-button
|
2020-08-08 13:57:36 +00:00
|
|
|
class="ml-1"
|
2020-07-11 15:50:59 +00:00
|
|
|
variant="primary"
|
|
|
|
size="sm"
|
2021-06-24 05:26:49 +00:00
|
|
|
title="Load configuration from text box below"
|
|
|
|
@click="resetConfig"
|
|
|
|
>Reset</b-button
|
2020-07-11 15:50:59 +00:00
|
|
|
>
|
2021-06-22 19:08:03 +00:00
|
|
|
<b-button
|
2021-06-24 05:26:49 +00:00
|
|
|
id="showButton"
|
2021-06-22 19:08:03 +00:00
|
|
|
class="ml-1"
|
|
|
|
variant="primary"
|
|
|
|
size="sm"
|
2021-06-24 05:26:49 +00:00
|
|
|
title="Show configuration for easy transfer to a strategy"
|
|
|
|
@click="showConfig = !showConfig"
|
|
|
|
>Show</b-button
|
2021-06-22 19:08:03 +00:00
|
|
|
>
|
2021-06-24 05:26:49 +00:00
|
|
|
|
2020-07-11 15:50:59 +00:00
|
|
|
<b-button
|
2020-08-08 13:57:36 +00:00
|
|
|
v-if="showConfig"
|
2020-08-01 18:43:14 +00:00
|
|
|
class="ml-1"
|
2020-07-11 15:50:59 +00:00
|
|
|
variant="primary"
|
|
|
|
size="sm"
|
|
|
|
title="Load configuration from text box below"
|
2020-08-08 13:57:36 +00:00
|
|
|
@click="loadConfigFromString"
|
2020-07-11 15:50:59 +00:00
|
|
|
>Load from String</b-button
|
|
|
|
>
|
2020-07-01 05:16:05 +00:00
|
|
|
</div>
|
2021-06-22 19:08:03 +00:00
|
|
|
<div v-if="showConfig" class="col-mb-5 ml-1 mt-2">
|
2020-07-11 15:41:33 +00:00
|
|
|
<b-textarea
|
|
|
|
id="TextArea"
|
|
|
|
v-model="plotConfigJson"
|
2020-08-08 13:57:36 +00:00
|
|
|
class="textArea"
|
2020-07-11 15:41:33 +00:00
|
|
|
size="sm"
|
|
|
|
:state="tempPlotConfigValid"
|
|
|
|
>
|
|
|
|
</b-textarea>
|
2020-07-01 18:22:29 +00:00
|
|
|
</div>
|
2020-07-01 05:16:05 +00:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2021-06-23 18:33:56 +00:00
|
|
|
import { Component, Vue, Prop, Emit, Watch } from 'vue-property-decorator';
|
2020-07-01 05:16:05 +00:00
|
|
|
import { namespace } from 'vuex-class';
|
2021-06-23 18:33:56 +00:00
|
|
|
import { PlotConfig, EMPTY_PLOTCONFIG, IndicatorConfig } from '@/types';
|
2020-08-08 13:57:36 +00:00
|
|
|
import { getCustomPlotConfig } from '@/shared/storage';
|
2021-06-23 18:33:56 +00:00
|
|
|
import PlotIndicator from '@/components/charts/PlotIndicator.vue';
|
2021-08-26 18:35:33 +00:00
|
|
|
import { BotStoreGetters } from '@/store/modules/ftbot';
|
2021-09-18 09:05:02 +00:00
|
|
|
import { AlertActions } from '@/store/modules/alerts';
|
2020-07-01 05:16:05 +00:00
|
|
|
|
|
|
|
const ftbot = namespace('ftbot');
|
|
|
|
|
2021-09-18 09:05:02 +00:00
|
|
|
const alerts = namespace('alerts');
|
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
@Component({
|
|
|
|
components: { PlotIndicator },
|
|
|
|
})
|
2020-07-01 05:16:05 +00:00
|
|
|
export default class PlotConfigurator extends Vue {
|
|
|
|
@Prop({ required: true }) value!: PlotConfig;
|
|
|
|
|
|
|
|
@Prop({ required: true }) columns!: Array<string>;
|
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
@Prop({ required: false, default: true }) asModal!: boolean;
|
2021-06-23 04:45:18 +00:00
|
|
|
|
2020-07-01 05:16:05 +00:00
|
|
|
@Emit('input')
|
|
|
|
emitPlotConfig() {
|
|
|
|
return this.plotConfig;
|
|
|
|
}
|
|
|
|
|
2020-08-07 04:57:05 +00:00
|
|
|
@ftbot.Action getStrategyPlotConfig;
|
2020-07-28 18:39:58 +00:00
|
|
|
|
2021-08-26 18:35:33 +00:00
|
|
|
@ftbot.Getter [BotStoreGetters.strategyPlotConfig];
|
2020-07-28 18:39:58 +00:00
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
get selIndicator(): Record<string, IndicatorConfig> {
|
|
|
|
if (this.addNewIndicator) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
if (this.selIndicatorName) {
|
|
|
|
return {
|
|
|
|
[this.selIndicatorName]: this.currentPlotConfig[this.selIndicatorName],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
set selIndicator(newValue: Record<string, IndicatorConfig>) {
|
|
|
|
console.log('newValue', newValue);
|
|
|
|
const name = Object.keys(newValue)[0];
|
|
|
|
// this.currentPlotConfig[this.selIndicatorName] = { ...newValue[name] };
|
|
|
|
// this.emitPlotConfig();
|
|
|
|
if (name && newValue) {
|
|
|
|
this.addIndicator(newValue);
|
|
|
|
} else {
|
|
|
|
this.addNewIndicator = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-01 05:16:05 +00:00
|
|
|
plotConfig: PlotConfig = EMPTY_PLOTCONFIG;
|
|
|
|
|
2020-08-01 18:43:14 +00:00
|
|
|
plotOptions = [
|
|
|
|
{ text: 'Main Plot', value: 'main_plot' },
|
|
|
|
{ text: 'Subplots', value: 'subplots' },
|
|
|
|
];
|
|
|
|
|
2021-08-28 09:39:03 +00:00
|
|
|
plotConfigNameLoc = 'default';
|
2020-08-24 18:05:07 +00:00
|
|
|
|
2020-07-01 05:16:05 +00:00
|
|
|
newSubplotName = '';
|
|
|
|
|
2020-08-01 18:43:14 +00:00
|
|
|
selAvailableIndicator = '';
|
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
selIndicatorName = '';
|
2020-07-01 18:59:45 +00:00
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
addNewIndicator = false;
|
2020-07-01 18:59:45 +00:00
|
|
|
|
2020-07-01 05:16:05 +00:00
|
|
|
showConfig = false;
|
|
|
|
|
2021-06-23 04:56:38 +00:00
|
|
|
selSubPlot = 'main_plot';
|
2020-07-01 05:16:05 +00:00
|
|
|
|
2020-07-11 15:41:33 +00:00
|
|
|
tempPlotConfig?: PlotConfig = undefined;
|
|
|
|
|
|
|
|
tempPlotConfigValid = true;
|
|
|
|
|
2020-08-24 18:05:07 +00:00
|
|
|
@ftbot.Mutation saveCustomPlotConfig;
|
|
|
|
|
2020-09-12 07:04:55 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
2020-08-24 18:05:07 +00:00
|
|
|
@ftbot.Mutation updatePlotConfigName!: (plotConfigName: string) => void;
|
2020-07-01 05:16:05 +00:00
|
|
|
|
2021-08-28 09:39:03 +00:00
|
|
|
@ftbot.Getter [BotStoreGetters.plotConfigName]!: string;
|
2020-08-08 13:25:58 +00:00
|
|
|
|
2021-09-18 09:05:02 +00:00
|
|
|
@alerts.Action [AlertActions.addAlert];
|
|
|
|
|
2020-07-01 05:16:05 +00:00
|
|
|
get plotConfigJson() {
|
|
|
|
return JSON.stringify(this.plotConfig, null, 2);
|
|
|
|
}
|
|
|
|
|
2020-07-11 15:41:33 +00:00
|
|
|
set plotConfigJson(newValue: string) {
|
|
|
|
try {
|
|
|
|
this.tempPlotConfig = JSON.parse(newValue);
|
|
|
|
// TODO: Should Validate schema validity (should be PlotConfig type...)
|
|
|
|
this.tempPlotConfigValid = true;
|
|
|
|
} catch (err) {
|
|
|
|
this.tempPlotConfigValid = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 04:45:18 +00:00
|
|
|
get subplots(): string[] {
|
2020-07-01 05:16:05 +00:00
|
|
|
// Subplot keys (for selection window)
|
2021-06-23 04:45:18 +00:00
|
|
|
return ['main_plot', ...Object.keys(this.plotConfig.subplots)];
|
2020-07-01 05:16:05 +00:00
|
|
|
}
|
|
|
|
|
2021-06-23 04:45:18 +00:00
|
|
|
get usedColumns(): string[] {
|
2020-08-01 18:43:14 +00:00
|
|
|
if (this.isMainPlot) {
|
|
|
|
return Object.keys(this.plotConfig.main_plot);
|
|
|
|
}
|
2021-06-23 04:56:38 +00:00
|
|
|
if (this.selSubPlot in this.plotConfig.subplots) {
|
|
|
|
return Object.keys(this.plotConfig.subplots[this.selSubPlot]);
|
2020-08-01 18:43:14 +00:00
|
|
|
}
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
get isMainPlot() {
|
2021-06-23 04:56:38 +00:00
|
|
|
return this.selSubPlot === 'main_plot';
|
2020-08-01 18:43:14 +00:00
|
|
|
}
|
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
get currentPlotConfig() {
|
|
|
|
if (this.isMainPlot) {
|
|
|
|
return this.plotConfig.main_plot;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.plotConfig.subplots[this.selSubPlot];
|
|
|
|
}
|
|
|
|
|
2020-07-01 05:16:05 +00:00
|
|
|
mounted() {
|
2021-06-23 18:33:56 +00:00
|
|
|
console.log('Config Mounted', this.value);
|
2020-07-01 05:16:05 +00:00
|
|
|
this.plotConfig = this.value;
|
2021-08-28 09:39:03 +00:00
|
|
|
this.plotConfigNameLoc = this.plotConfigName;
|
2020-07-01 05:16:05 +00:00
|
|
|
}
|
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
@Watch('value')
|
|
|
|
watchValue() {
|
|
|
|
this.plotConfig = this.value;
|
2021-08-28 09:39:03 +00:00
|
|
|
this.plotConfigNameLoc = this.plotConfigName;
|
2020-07-01 18:22:29 +00:00
|
|
|
}
|
|
|
|
|
2021-06-23 18:33:56 +00:00
|
|
|
addIndicator(newIndicator: Record<string, IndicatorConfig>) {
|
2020-07-01 05:16:05 +00:00
|
|
|
console.log(this.plotConfig);
|
|
|
|
|
|
|
|
const { plotConfig } = this;
|
2021-06-23 18:33:56 +00:00
|
|
|
const name = Object.keys(newIndicator)[0];
|
|
|
|
const indicator = newIndicator[name];
|
2020-08-01 18:43:14 +00:00
|
|
|
if (this.isMainPlot) {
|
2021-06-23 18:33:56 +00:00
|
|
|
console.log(`Adding ${name} to MainPlot`);
|
|
|
|
plotConfig.main_plot[name] = { ...indicator };
|
2020-07-01 05:16:05 +00:00
|
|
|
} else {
|
2021-06-23 18:33:56 +00:00
|
|
|
console.log(`Adding ${name} to ${this.selSubPlot}`);
|
|
|
|
plotConfig.subplots[this.selSubPlot][name] = { ...indicator };
|
2020-07-01 05:16:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.plotConfig = { ...plotConfig };
|
|
|
|
// Reset random color
|
2021-06-23 18:33:56 +00:00
|
|
|
this.addNewIndicator = false;
|
2020-08-01 18:43:14 +00:00
|
|
|
this.emitPlotConfig();
|
|
|
|
}
|
|
|
|
|
|
|
|
removeIndicator() {
|
2020-07-01 05:16:05 +00:00
|
|
|
console.log(this.plotConfig);
|
2020-08-01 18:43:14 +00:00
|
|
|
const { plotConfig } = this;
|
|
|
|
if (this.isMainPlot) {
|
2021-06-23 18:33:56 +00:00
|
|
|
console.log(`Removing ${this.selIndicatorName} from MainPlot`);
|
|
|
|
delete plotConfig.main_plot[this.selIndicatorName];
|
2020-08-01 18:43:14 +00:00
|
|
|
} else {
|
2021-06-23 18:33:56 +00:00
|
|
|
console.log(`Removing ${this.selIndicatorName} from ${this.selSubPlot}`);
|
|
|
|
delete plotConfig.subplots[this.selSubPlot][this.selIndicatorName];
|
2020-08-01 18:43:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.plotConfig = { ...plotConfig };
|
|
|
|
console.log(this.plotConfig);
|
2021-06-23 18:33:56 +00:00
|
|
|
this.selIndicatorName = '';
|
2020-07-01 05:16:05 +00:00
|
|
|
this.emitPlotConfig();
|
|
|
|
}
|
|
|
|
|
|
|
|
addSubplot() {
|
|
|
|
this.plotConfig.subplots = {
|
|
|
|
...this.plotConfig.subplots,
|
|
|
|
[this.newSubplotName]: {},
|
|
|
|
};
|
2020-08-01 18:43:14 +00:00
|
|
|
this.selSubPlot = this.newSubplotName;
|
2020-07-01 05:16:05 +00:00
|
|
|
this.newSubplotName = '';
|
2021-06-23 04:56:38 +00:00
|
|
|
|
2020-07-01 05:16:05 +00:00
|
|
|
console.log(this.plotConfig);
|
|
|
|
this.emitPlotConfig();
|
|
|
|
}
|
|
|
|
|
2020-07-01 18:22:29 +00:00
|
|
|
delSubplot() {
|
2020-08-01 18:43:14 +00:00
|
|
|
delete this.plotConfig.subplots[this.selSubPlot];
|
2020-07-01 18:22:29 +00:00
|
|
|
this.plotConfig.subplots = { ...this.plotConfig.subplots };
|
2021-06-23 18:51:27 +00:00
|
|
|
this.selSubPlot = '';
|
2020-07-01 18:22:29 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 05:16:05 +00:00
|
|
|
savePlotConfig() {
|
2020-08-24 18:05:07 +00:00
|
|
|
this.saveCustomPlotConfig({ [this.plotConfigName]: this.plotConfig });
|
2020-07-01 05:16:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
loadPlotConfig() {
|
2021-08-28 09:39:03 +00:00
|
|
|
this.plotConfig = getCustomPlotConfig(this.plotConfigNameLoc);
|
2020-07-01 05:16:05 +00:00
|
|
|
console.log(this.plotConfig);
|
|
|
|
console.log('loading config');
|
|
|
|
this.emitPlotConfig();
|
|
|
|
}
|
2020-07-11 15:41:33 +00:00
|
|
|
|
|
|
|
loadConfigFromString() {
|
|
|
|
// this.plotConfig = JSON.parse();
|
|
|
|
if (this.tempPlotConfig !== undefined && this.tempPlotConfigValid) {
|
|
|
|
this.plotConfig = this.tempPlotConfig;
|
|
|
|
this.emitPlotConfig();
|
|
|
|
}
|
|
|
|
}
|
2020-07-28 18:39:58 +00:00
|
|
|
|
2021-06-22 19:08:03 +00:00
|
|
|
resetConfig() {
|
|
|
|
this.plotConfig = { ...EMPTY_PLOTCONFIG };
|
|
|
|
}
|
|
|
|
|
2020-07-28 18:39:58 +00:00
|
|
|
async loadPlotConfigFromStrategy() {
|
2021-09-18 09:05:02 +00:00
|
|
|
try {
|
|
|
|
await this.getStrategyPlotConfig();
|
|
|
|
this.plotConfig = this.strategyPlotConfig;
|
|
|
|
this.emitPlotConfig();
|
|
|
|
} catch (data) {
|
|
|
|
//
|
|
|
|
this.addAlert({ message: 'Failed to load Plot configuration from Strategy.' });
|
|
|
|
}
|
2020-07-28 18:39:58 +00:00
|
|
|
}
|
2020-07-01 05:16:05 +00:00
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
2020-07-01 18:22:29 +00:00
|
|
|
<style scoped>
|
|
|
|
.textArea {
|
|
|
|
min-height: 250px;
|
|
|
|
}
|
2021-06-23 18:33:56 +00:00
|
|
|
|
2020-08-01 18:43:14 +00:00
|
|
|
.form-group {
|
|
|
|
margin-bottom: 0.5rem;
|
|
|
|
}
|
|
|
|
hr {
|
|
|
|
margin-bottom: 0.5rem;
|
|
|
|
margin-top: 0.5rem;
|
|
|
|
}
|
2020-07-01 05:16:05 +00:00
|
|
|
</style>
|