mirror of
https://github.com/freqtrade/frequi.git
synced 2024-09-21 10:01:09 +00:00
composition: plotconfig
This commit is contained in:
parent
2a49381c6c
commit
5298127402
|
@ -120,234 +120,242 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue, Prop, Emit, Watch } from 'vue-property-decorator';
|
|
||||||
import { namespace } from 'vuex-class';
|
|
||||||
import { PlotConfig, EMPTY_PLOTCONFIG, IndicatorConfig } from '@/types';
|
import { PlotConfig, EMPTY_PLOTCONFIG, IndicatorConfig } from '@/types';
|
||||||
import { getCustomPlotConfig } from '@/shared/storage';
|
import { getCustomPlotConfig } from '@/shared/storage';
|
||||||
import PlotIndicator from '@/components/charts/PlotIndicator.vue';
|
import PlotIndicator from '@/components/charts/PlotIndicator.vue';
|
||||||
import { BotStoreGetters } from '@/store/modules/ftbot';
|
|
||||||
import StoreModules from '@/store/storeSubModules';
|
import StoreModules from '@/store/storeSubModules';
|
||||||
import { showAlert } from '@/stores/alerts';
|
import { showAlert } from '@/stores/alerts';
|
||||||
|
|
||||||
const ftbot = namespace(StoreModules.ftbot);
|
import { defineComponent, computed, ref, watch, onMounted } from '@vue/composition-api';
|
||||||
|
import { useNamespacedActions, useNamespacedGetters } from 'vuex-composition-helpers';
|
||||||
|
|
||||||
@Component({
|
export default defineComponent({
|
||||||
|
name: 'PlotConfigurator',
|
||||||
components: { PlotIndicator },
|
components: { PlotIndicator },
|
||||||
})
|
props: {
|
||||||
export default class PlotConfigurator extends Vue {
|
value: { type: Object as () => PlotConfig, required: true },
|
||||||
@Prop({ required: true }) value!: PlotConfig;
|
columns: { required: true, type: Array as () => string[] },
|
||||||
|
asModal: { required: false, default: true, type: Boolean },
|
||||||
|
},
|
||||||
|
emits: ['input'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const { getStrategyPlotConfig, saveCustomPlotConfig, updatePlotConfigName } =
|
||||||
|
useNamespacedActions(StoreModules.ftbot, [
|
||||||
|
'getStrategyPlotConfig',
|
||||||
|
'saveCustomPlotConfig',
|
||||||
|
'updatePlotConfigName',
|
||||||
|
]);
|
||||||
|
const { strategyPlotConfig, plotConfigName } = useNamespacedGetters(StoreModules.ftbot, [
|
||||||
|
'strategyPlotConfig',
|
||||||
|
'plotConfigName',
|
||||||
|
]);
|
||||||
|
const plotConfig = ref<PlotConfig>(EMPTY_PLOTCONFIG);
|
||||||
|
|
||||||
@Prop({ required: true }) columns!: Array<string>;
|
const plotOptions = [
|
||||||
|
{ text: 'Main Plot', value: 'main_plot' },
|
||||||
|
{ text: 'Subplots', value: 'subplots' },
|
||||||
|
];
|
||||||
|
const plotConfigNameLoc = ref('default');
|
||||||
|
const newSubplotName = ref('');
|
||||||
|
const selAvailableIndicator = ref('');
|
||||||
|
const selIndicatorName = ref('');
|
||||||
|
const addNewIndicator = ref(false);
|
||||||
|
const showConfig = ref(false);
|
||||||
|
const selSubPlot = ref('main_plot');
|
||||||
|
const tempPlotConfig = ref<PlotConfig>();
|
||||||
|
const tempPlotConfigValid = ref(true);
|
||||||
|
|
||||||
@Prop({ required: false, default: true }) asModal!: boolean;
|
const isMainPlot = computed(() => {
|
||||||
|
return selSubPlot.value === 'main_plot';
|
||||||
|
});
|
||||||
|
|
||||||
@Emit('input')
|
const currentPlotConfig = computed(() => {
|
||||||
emitPlotConfig() {
|
if (isMainPlot.value) {
|
||||||
return this.plotConfig;
|
return plotConfig.value.main_plot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ftbot.Action getStrategyPlotConfig;
|
return plotConfig.value.subplots[selSubPlot.value];
|
||||||
|
});
|
||||||
|
const subplots = computed((): string[] => {
|
||||||
|
// Subplot keys (for selection window)
|
||||||
|
return ['main_plot', ...Object.keys(plotConfig.value.subplots)];
|
||||||
|
});
|
||||||
|
const usedColumns = computed((): string[] => {
|
||||||
|
if (isMainPlot.value) {
|
||||||
|
return Object.keys(plotConfig.value.main_plot);
|
||||||
|
}
|
||||||
|
if (selSubPlot.value in plotConfig.value.subplots) {
|
||||||
|
return Object.keys(plotConfig.value.subplots[selSubPlot.value]);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
|
||||||
@ftbot.Getter [BotStoreGetters.strategyPlotConfig];
|
const addIndicator = (newIndicator: Record<string, IndicatorConfig>) => {
|
||||||
|
console.log(plotConfig.value);
|
||||||
|
|
||||||
get selIndicator(): Record<string, IndicatorConfig> {
|
// const { plotConfig.value } = this;
|
||||||
if (this.addNewIndicator) {
|
const name = Object.keys(newIndicator)[0];
|
||||||
return {};
|
const indicator = newIndicator[name];
|
||||||
}
|
if (isMainPlot.value) {
|
||||||
if (this.selIndicatorName) {
|
console.log(`Adding ${name} to MainPlot`);
|
||||||
return {
|
plotConfig.value.main_plot[name] = { ...indicator };
|
||||||
[this.selIndicatorName]: this.currentPlotConfig[this.selIndicatorName],
|
} else {
|
||||||
};
|
console.log(`Adding ${name} to ${selSubPlot.value}`);
|
||||||
}
|
plotConfig.value.subplots[selSubPlot.value][name] = { ...indicator };
|
||||||
return {};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
set selIndicator(newValue: Record<string, IndicatorConfig>) {
|
plotConfig.value = { ...plotConfig.value };
|
||||||
// console.log('newValue', newValue);
|
// Reset random color
|
||||||
const name = Object.keys(newValue)[0];
|
addNewIndicator.value = false;
|
||||||
// this.currentPlotConfig[this.selIndicatorName] = { ...newValue[name] };
|
emit('input', plotConfig.value);
|
||||||
// this.emitPlotConfig();
|
|
||||||
if (name && newValue) {
|
|
||||||
this.addIndicator(newValue);
|
|
||||||
} else {
|
|
||||||
this.addNewIndicator = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plotConfig: PlotConfig = EMPTY_PLOTCONFIG;
|
|
||||||
|
|
||||||
plotOptions = [
|
|
||||||
{ text: 'Main Plot', value: 'main_plot' },
|
|
||||||
{ text: 'Subplots', value: 'subplots' },
|
|
||||||
];
|
|
||||||
|
|
||||||
plotConfigNameLoc = 'default';
|
|
||||||
|
|
||||||
newSubplotName = '';
|
|
||||||
|
|
||||||
selAvailableIndicator = '';
|
|
||||||
|
|
||||||
selIndicatorName = '';
|
|
||||||
|
|
||||||
addNewIndicator = false;
|
|
||||||
|
|
||||||
showConfig = false;
|
|
||||||
|
|
||||||
selSubPlot = 'main_plot';
|
|
||||||
|
|
||||||
tempPlotConfig?: PlotConfig = undefined;
|
|
||||||
|
|
||||||
tempPlotConfigValid = true;
|
|
||||||
|
|
||||||
@ftbot.Action saveCustomPlotConfig;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
@ftbot.Action updatePlotConfigName!: (plotConfigName: string) => void;
|
|
||||||
|
|
||||||
@ftbot.Getter [BotStoreGetters.plotConfigName]!: string;
|
|
||||||
|
|
||||||
get plotConfigJson() {
|
|
||||||
return JSON.stringify(this.plotConfig, null, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get subplots(): string[] {
|
|
||||||
// Subplot keys (for selection window)
|
|
||||||
return ['main_plot', ...Object.keys(this.plotConfig.subplots)];
|
|
||||||
}
|
|
||||||
|
|
||||||
get usedColumns(): string[] {
|
|
||||||
if (this.isMainPlot) {
|
|
||||||
return Object.keys(this.plotConfig.main_plot);
|
|
||||||
}
|
|
||||||
if (this.selSubPlot in this.plotConfig.subplots) {
|
|
||||||
return Object.keys(this.plotConfig.subplots[this.selSubPlot]);
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
get isMainPlot() {
|
|
||||||
return this.selSubPlot === 'main_plot';
|
|
||||||
}
|
|
||||||
|
|
||||||
get currentPlotConfig() {
|
|
||||||
if (this.isMainPlot) {
|
|
||||||
return this.plotConfig.main_plot;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.plotConfig.subplots[this.selSubPlot];
|
|
||||||
}
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
console.log('Config Mounted', this.value);
|
|
||||||
this.plotConfig = this.value;
|
|
||||||
this.plotConfigNameLoc = this.plotConfigName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Watch('value')
|
|
||||||
watchValue() {
|
|
||||||
this.plotConfig = this.value;
|
|
||||||
this.plotConfigNameLoc = this.plotConfigName;
|
|
||||||
}
|
|
||||||
|
|
||||||
addIndicator(newIndicator: Record<string, IndicatorConfig>) {
|
|
||||||
console.log(this.plotConfig);
|
|
||||||
|
|
||||||
const { plotConfig } = this;
|
|
||||||
const name = Object.keys(newIndicator)[0];
|
|
||||||
const indicator = newIndicator[name];
|
|
||||||
if (this.isMainPlot) {
|
|
||||||
console.log(`Adding ${name} to MainPlot`);
|
|
||||||
plotConfig.main_plot[name] = { ...indicator };
|
|
||||||
} else {
|
|
||||||
console.log(`Adding ${name} to ${this.selSubPlot}`);
|
|
||||||
plotConfig.subplots[this.selSubPlot][name] = { ...indicator };
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plotConfig = { ...plotConfig };
|
|
||||||
// Reset random color
|
|
||||||
this.addNewIndicator = false;
|
|
||||||
this.emitPlotConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
removeIndicator() {
|
|
||||||
console.log(this.plotConfig);
|
|
||||||
const { plotConfig } = this;
|
|
||||||
if (this.isMainPlot) {
|
|
||||||
console.log(`Removing ${this.selIndicatorName} from MainPlot`);
|
|
||||||
delete plotConfig.main_plot[this.selIndicatorName];
|
|
||||||
} else {
|
|
||||||
console.log(`Removing ${this.selIndicatorName} from ${this.selSubPlot}`);
|
|
||||||
delete plotConfig.subplots[this.selSubPlot][this.selIndicatorName];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.plotConfig = { ...plotConfig };
|
|
||||||
console.log(this.plotConfig);
|
|
||||||
this.selIndicatorName = '';
|
|
||||||
this.emitPlotConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
addSubplot() {
|
|
||||||
this.plotConfig.subplots = {
|
|
||||||
...this.plotConfig.subplots,
|
|
||||||
[this.newSubplotName]: {},
|
|
||||||
};
|
};
|
||||||
this.selSubPlot = this.newSubplotName;
|
|
||||||
this.newSubplotName = '';
|
|
||||||
|
|
||||||
console.log(this.plotConfig);
|
const selIndicator = computed({
|
||||||
this.emitPlotConfig();
|
get() {
|
||||||
}
|
if (addNewIndicator.value) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (selIndicatorName.value) {
|
||||||
|
return {
|
||||||
|
[selIndicatorName.value]: currentPlotConfig.value[selIndicatorName.value],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
set(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) {
|
||||||
|
addIndicator(newValue);
|
||||||
|
} else {
|
||||||
|
addNewIndicator.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
delSubplot() {
|
const plotConfigJson = computed({
|
||||||
delete this.plotConfig.subplots[this.selSubPlot];
|
get() {
|
||||||
this.plotConfig.subplots = { ...this.plotConfig.subplots };
|
return JSON.stringify(plotConfig.value, null, 2);
|
||||||
this.selSubPlot = '';
|
},
|
||||||
}
|
set(newValue: string) {
|
||||||
|
try {
|
||||||
|
tempPlotConfig.value = JSON.parse(newValue);
|
||||||
|
// TODO: Should Validate schema validity (should be PlotConfig type...)
|
||||||
|
tempPlotConfigValid.value = true;
|
||||||
|
} catch (err) {
|
||||||
|
tempPlotConfigValid.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
savePlotConfig() {
|
const removeIndicator = () => {
|
||||||
this.saveCustomPlotConfig({ [this.plotConfigNameLoc]: this.plotConfig });
|
console.log(plotConfig.value);
|
||||||
}
|
// const { plotConfig } = this;
|
||||||
|
if (isMainPlot.value) {
|
||||||
|
console.log(`Removing ${selIndicatorName.value} from MainPlot`);
|
||||||
|
delete plotConfig.value.main_plot[selIndicatorName.value];
|
||||||
|
} else {
|
||||||
|
console.log(`Removing ${selIndicatorName.value} from ${selSubPlot.value}`);
|
||||||
|
delete plotConfig.value.subplots[selSubPlot.value][selIndicatorName.value];
|
||||||
|
}
|
||||||
|
|
||||||
loadPlotConfig() {
|
plotConfig.value = { ...plotConfig.value };
|
||||||
this.plotConfig = getCustomPlotConfig(this.plotConfigNameLoc);
|
console.log(plotConfig.value);
|
||||||
console.log(this.plotConfig);
|
selIndicatorName.value = '';
|
||||||
console.log('loading config');
|
emit('input', plotConfig.value);
|
||||||
this.emitPlotConfig();
|
};
|
||||||
}
|
const addSubplot = () => {
|
||||||
|
plotConfig.value.subplots = {
|
||||||
|
...plotConfig.value.subplots,
|
||||||
|
[newSubplotName.value]: {},
|
||||||
|
};
|
||||||
|
selSubPlot.value = newSubplotName.value;
|
||||||
|
newSubplotName.value = '';
|
||||||
|
|
||||||
loadConfigFromString() {
|
console.log(plotConfig.value);
|
||||||
// this.plotConfig = JSON.parse();
|
emit('input', plotConfig.value);
|
||||||
if (this.tempPlotConfig !== undefined && this.tempPlotConfigValid) {
|
};
|
||||||
this.plotConfig = this.tempPlotConfig;
|
|
||||||
this.emitPlotConfig();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resetConfig() {
|
const delSubplot = () => {
|
||||||
this.plotConfig = { ...EMPTY_PLOTCONFIG };
|
delete plotConfig.value.subplots[selSubPlot.value];
|
||||||
}
|
plotConfig.value.subplots = { ...plotConfig.value.subplots };
|
||||||
|
selSubPlot.value = '';
|
||||||
|
};
|
||||||
|
const loadPlotConfig = () => {
|
||||||
|
plotConfig.value = getCustomPlotConfig(plotConfigNameLoc.value);
|
||||||
|
console.log(plotConfig.value);
|
||||||
|
console.log('loading config');
|
||||||
|
emit('input', plotConfig.value);
|
||||||
|
};
|
||||||
|
|
||||||
async loadPlotConfigFromStrategy() {
|
const loadConfigFromString = () => {
|
||||||
try {
|
// this.plotConfig = JSON.parse();
|
||||||
await this.getStrategyPlotConfig();
|
if (tempPlotConfig.value !== undefined && tempPlotConfigValid.value) {
|
||||||
this.plotConfig = this.strategyPlotConfig;
|
plotConfig.value = tempPlotConfig.value;
|
||||||
this.emitPlotConfig();
|
emit('input', plotConfig.value);
|
||||||
} catch (data) {
|
}
|
||||||
//
|
};
|
||||||
showAlert('Failed to load Plot configuration from Strategy.');
|
const resetConfig = () => {
|
||||||
}
|
plotConfig.value = { ...EMPTY_PLOTCONFIG };
|
||||||
}
|
};
|
||||||
}
|
const loadPlotConfigFromStrategy = async () => {
|
||||||
|
try {
|
||||||
|
await getStrategyPlotConfig();
|
||||||
|
plotConfig.value = strategyPlotConfig.value;
|
||||||
|
emit('input', plotConfig.value);
|
||||||
|
} catch (data) {
|
||||||
|
//
|
||||||
|
showAlert('Failed to load Plot configuration from Strategy.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const savePlotConfig = () => {
|
||||||
|
saveCustomPlotConfig({ [plotConfigNameLoc.value]: plotConfig.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(props.value, () => {
|
||||||
|
console.log('config value');
|
||||||
|
plotConfig.value = props.value;
|
||||||
|
plotConfigNameLoc.value = plotConfigName.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log('Config Mounted', props.value);
|
||||||
|
plotConfig.value = props.value;
|
||||||
|
plotConfigNameLoc.value = plotConfigName.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
saveCustomPlotConfig,
|
||||||
|
getStrategyPlotConfig,
|
||||||
|
updatePlotConfigName,
|
||||||
|
strategyPlotConfig,
|
||||||
|
plotConfigName,
|
||||||
|
addIndicator,
|
||||||
|
removeIndicator,
|
||||||
|
addSubplot,
|
||||||
|
delSubplot,
|
||||||
|
loadPlotConfig,
|
||||||
|
loadConfigFromString,
|
||||||
|
resetConfig,
|
||||||
|
loadPlotConfigFromStrategy,
|
||||||
|
savePlotConfig,
|
||||||
|
showConfig,
|
||||||
|
addNewIndicator,
|
||||||
|
selIndicatorName,
|
||||||
|
usedColumns,
|
||||||
|
selSubPlot,
|
||||||
|
newSubplotName,
|
||||||
|
subplots,
|
||||||
|
plotConfigNameLoc,
|
||||||
|
selIndicator,
|
||||||
|
plotConfigJson,
|
||||||
|
tempPlotConfigValid,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -358,6 +366,7 @@ export default class PlotConfigurator extends Vue {
|
||||||
.form-group {
|
.form-group {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user