Add plotconfig selector

This commit is contained in:
Matthias 2020-08-08 15:57:36 +02:00
parent 25cce25fc1
commit 1886e3328f
6 changed files with 77 additions and 51 deletions

View File

@ -8,7 +8,7 @@
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'; import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
import ECharts from 'vue-echarts'; import ECharts from 'vue-echarts';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import { Trade, PairHistory, PlotConfig } from '@/store/types'; import { Trade, PairHistory, PlotConfig } from '@/types';
import randomColor from '@/shared/randomColor'; import randomColor from '@/shared/randomColor';
import { roundTimeframe } from '@/shared/timemath'; import { roundTimeframe } from '@/shared/timemath';
import { timestampms } from '@/shared/formatters'; import { timestampms } from '@/shared/formatters';

View File

@ -7,16 +7,22 @@
hide-backdrop hide-backdrop
button-size="sm" button-size="sm"
> >
<PlotConfigurator :columns="datasetColumns" v-model="plotConfig" /> <PlotConfigurator v-model="plotConfig" :columns="datasetColumns" />
</b-modal> </b-modal>
<div class="row ml-auto"> <div class="row ml-auto">
<div class="col-mb-2 mr-2">
<b-select
v-model="plotConfigName"
:options="availablePlotConfigNames"
@change="plotConfigChanged"
>
</b-select>
</div>
<div class="col-mb-2 mr-2"> <div class="col-mb-2 mr-2">
<b-checkbox v-model="useUTC" title="Use UTC for graph">useUtc</b-checkbox> <b-checkbox v-model="useUTC" title="Use UTC for graph">useUtc</b-checkbox>
</div> </div>
<div class="col-mb-2 mr-3"> <div class="col-mb-2 mr-3">
<b-button @click="showConfigurator" size="sm" title="Plot configurator"> <b-button size="sm" title="Plot configurator" @click="showConfigurator"> &#9881; </b-button>
&#9881;
</b-button>
</div> </div>
</div> </div>
<CandleChart <CandleChart
@ -24,7 +30,7 @@
:timeframems="timeframems" :timeframems="timeframems"
:dataset="dataset" :dataset="dataset"
:trades="trades" :trades="trades"
:plotConfig="plotConfig" :plot-config="plotConfig"
> >
</CandleChart> </CandleChart>
</div> </div>
@ -32,10 +38,13 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator'; import { Component, Vue, Prop } from 'vue-property-decorator';
import { Trade, PairHistory, EMPTY_PLOTCONFIG, PlotConfig } from '@/store/types'; import { namespace } from 'vuex-class';
import { Trade, PairHistory, EMPTY_PLOTCONFIG, PlotConfig } from '@/types';
import CandleChart from '@/components/charts/CandleChart.vue'; import CandleChart from '@/components/charts/CandleChart.vue';
import PlotConfigurator from '@/components/charts/PlotConfigurator.vue'; import PlotConfigurator from '@/components/charts/PlotConfigurator.vue';
import { loadCustomPlotConfig, loadPlotConfigName } from '../../shared/storage'; import { getCustomPlotConfig, getPlotConfigName } from '@/shared/storage';
const ftbot = namespace('ftbot');
@Component({ components: { CandleChart, PlotConfigurator } }) @Component({ components: { CandleChart, PlotConfigurator } })
export default class CandleChartContainer extends Vue { export default class CandleChartContainer extends Vue {
@ -51,12 +60,21 @@ export default class CandleChartContainer extends Vue {
plotConfig: PlotConfig = { ...EMPTY_PLOTCONFIG }; plotConfig: PlotConfig = { ...EMPTY_PLOTCONFIG };
plotConfigName = '';
@ftbot.State availablePlotConfigNames!: Array<string>;
get datasetColumns() { get datasetColumns() {
return this.dataset ? this.dataset.columns : []; return this.dataset ? this.dataset.columns : [];
} }
mounted() { mounted() {
this.plotConfig = loadCustomPlotConfig(loadPlotConfigName()); this.plotConfigName = getPlotConfigName();
this.plotConfig = getCustomPlotConfig(this.plotConfigName);
}
plotConfigChanged() {
this.plotConfig = getCustomPlotConfig(this.plotConfigName);
} }
showConfigurator() { showConfigurator() {

View File

@ -2,28 +2,28 @@
<div v-if="columns"> <div v-if="columns">
<div class="col-mb-3 ml-2"> <div class="col-mb-3 ml-2">
<b-form-radio-group <b-form-radio-group
class="w-100"
v-model="plotOption" v-model="plotOption"
class="w-100"
:options="plotOptions" :options="plotOptions"
buttons buttons
button-variant="outline-primary" button-variant="outline-primary"
> >
</b-form-radio-group> </b-form-radio-group>
</div> </div>
<div class="col-mb-3" v-if="plotOption == 'subplots'"> <div v-if="plotOption == 'subplots'" class="col-mb-3">
<hr /> <hr />
<b-form-group label="Subplot" label-for="FieldSel"> <b-form-group label="Subplot" label-for="FieldSel">
<b-form-select id="FieldSel" :options="subplots" v-model="selSubPlot" :select-size="4"> <b-form-select id="FieldSel" v-model="selSubPlot" :options="subplots" :select-size="4">
</b-form-select> </b-form-select>
</b-form-group> </b-form-group>
</div> </div>
<b-form-group v-if="plotOption == 'subplots'" label="New subplot" label-for="newSubplot"> <b-form-group v-if="plotOption == 'subplots'" label="New subplot" label-for="newSubplot">
<b-input-group size="sm"> <b-input-group size="sm">
<b-form-input class="addPlot" id="newSubplot" v-model="newSubplotName"></b-form-input> <b-form-input id="newSubplot" v-model="newSubplotName" class="addPlot"></b-form-input>
<b-input-group-append> <b-input-group-append>
<b-button @click="addSubplot">+</b-button> <b-button @click="addSubplot">+</b-button>
<b-button @click="delSubplot" v-if="selSubPlot">-</b-button> <b-button v-if="selSubPlot" @click="delSubplot">-</b-button>
</b-input-group-append> </b-input-group-append>
</b-input-group> </b-input-group>
</b-form-group> </b-form-group>
@ -31,8 +31,8 @@
<b-form-group label="Used indicators" label-for="selectedIndicators"> <b-form-group label="Used indicators" label-for="selectedIndicators">
<b-form-select <b-form-select
id="selectedIndicators" id="selectedIndicators"
:options="usedColumns"
v-model="selIndicator" v-model="selIndicator"
:options="usedColumns"
:select-size="4" :select-size="4"
> >
</b-form-select> </b-form-select>
@ -40,15 +40,15 @@
<b-form-group label="Add indicator" label-for="indicatorSelector"> <b-form-group label="Add indicator" label-for="indicatorSelector">
<b-form-select <b-form-select
id="indicatorSelector" id="indicatorSelector"
:options="columns"
v-model="selAvailableIndicator" v-model="selAvailableIndicator"
:options="columns"
:select-size="4" :select-size="4"
> >
</b-form-select> </b-form-select>
</b-form-group> </b-form-group>
<b-form-group label="Choose type" label-for="plotTypeSelector"> <b-form-group label="Choose type" label-for="plotTypeSelector">
<b-form-select id="plotTypeSelector" :options="availableGraphTypes" v-model="graphType"> <b-form-select id="plotTypeSelector" v-model="graphType" :options="availableGraphTypes">
</b-form-select> </b-form-select>
</b-form-group> </b-form-group>
<hr /> <hr />
@ -56,78 +56,78 @@
<b-form-group label="Color" label-for="colsel" size="sm"> <b-form-group label="Color" label-for="colsel" size="sm">
<b-input-group> <b-input-group>
<b-input-group-prepend> <b-input-group-prepend>
<div v-bind:style="{ 'background-color': selColor }" class="colorbox mr-2"></div> <div :style="{ 'background-color': selColor }" class="colorbox mr-2"></div>
</b-input-group-prepend> </b-input-group-prepend>
<b-form-input id="colsel" v-model="selColor" size="sm"> </b-form-input> <b-form-input id="colsel" v-model="selColor" size="sm"> </b-form-input>
<b-input-group-append> <b-input-group-append>
<b-button variant="primary" @click="newColor" size="sm">&#x21bb;</b-button> <b-button variant="primary" size="sm" @click="newColor">&#x21bb;</b-button>
</b-input-group-append> </b-input-group-append>
</b-input-group> </b-input-group>
</b-form-group> </b-form-group>
<hr /> <hr />
<b-form-group label="Plot config name" label-for="idPlotConfigName"> <b-form-group label="Plot config name" label-for="idPlotConfigName">
<b-form-input id="idPlotConfigName" :options="availableGraphTypes" v-model="plotConfigName"> <b-form-input id="idPlotConfigName" v-model="plotConfigName" :options="availableGraphTypes">
</b-form-input> </b-form-input>
</b-form-group> </b-form-group>
<div class="row"> <div class="row">
<b-button <b-button
class="ml-1" class="ml-1"
variant="primary" variant="primary"
@click="addIndicator"
title="Add indicator to plot" title="Add indicator to plot"
size="sm" size="sm"
:disabled="!selAvailableIndicator" :disabled="!selAvailableIndicator"
@click="addIndicator"
> >
Add Add
</b-button> </b-button>
<b-button <b-button
class="ml-1" class="ml-1"
variant="primary" variant="primary"
@click="removeIndicator"
title="Remove indicator to plot" title="Remove indicator to plot"
size="sm" size="sm"
:disabled="!selIndicator" :disabled="!selIndicator"
@click="removeIndicator"
> >
Remove Remove
</b-button> </b-button>
<b-button class="ml-1" variant="primary" @click="loadPlotConfig" size="sm">Load</b-button> <b-button class="ml-1" variant="primary" size="sm" @click="loadPlotConfig">Load</b-button>
<b-button class="ml-1" variant="primary" @click="loadPlotConfigFromStrategy" size="sm"> <b-button class="ml-1" variant="primary" size="sm" @click="loadPlotConfigFromStrategy">
Load from strategy Load from strategy
</b-button> </b-button>
<b-button <b-button
class="ml-1" class="ml-1"
variant="primary" variant="primary"
@click="savePlotConfig"
size="sm" size="sm"
data-toggle="tooltip" data-toggle="tooltip"
title="Save configuration" title="Save configuration"
@click="savePlotConfig"
>Save</b-button >Save</b-button
> >
<b-button <b-button
class="ml-1"
id="showButton" id="showButton"
class="ml-1"
variant="primary" variant="primary"
@click="showConfig = !showConfig"
size="sm" size="sm"
title="Show configuration for easy transfer to a strategy" title="Show configuration for easy transfer to a strategy"
@click="showConfig = !showConfig"
>Show</b-button >Show</b-button
> >
<b-button <b-button
v-if="showConfig"
class="ml-1" class="ml-1"
variant="primary" variant="primary"
@click="loadConfigFromString"
size="sm" size="sm"
v-if="showConfig"
title="Load configuration from text box below" title="Load configuration from text box below"
@click="loadConfigFromString"
>Load from String</b-button >Load from String</b-button
> >
</div> </div>
<div class="col-mb-5 ml-2 mt-2" v-if="showConfig"> <div v-if="showConfig" class="col-mb-5 ml-2 mt-2">
<b-textarea <b-textarea
id="TextArea" id="TextArea"
class="textArea"
v-model="plotConfigJson" v-model="plotConfigJson"
class="textArea"
size="sm" size="sm"
:state="tempPlotConfigValid" :state="tempPlotConfigValid"
> >
@ -139,9 +139,9 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop, Emit } from 'vue-property-decorator'; import { Component, Vue, Prop, Emit } from 'vue-property-decorator';
import { namespace } from 'vuex-class'; import { namespace } from 'vuex-class';
import { PlotConfig, EMPTY_PLOTCONFIG } from '@/store/types'; import { PlotConfig, EMPTY_PLOTCONFIG } from '@/types';
import randomColor from '@/shared/randomColor'; import randomColor from '@/shared/randomColor';
import { loadCustomPlotConfig } from '@/shared/storage'; import { getCustomPlotConfig } from '@/shared/storage';
const ftbot = namespace('ftbot'); const ftbot = namespace('ftbot');
@ -302,7 +302,7 @@ export default class PlotConfigurator extends Vue {
} }
loadPlotConfig() { loadPlotConfig() {
this.plotConfig = loadCustomPlotConfig(this.plotConfigName); this.plotConfig = getCustomPlotConfig(this.plotConfigName);
console.log(this.plotConfig); console.log(this.plotConfig);
console.log('loading config'); console.log('loading config');
this.emitPlotConfig(); this.emitPlotConfig();

View File

@ -3,7 +3,7 @@ import { PlotConfig, EMPTY_PLOTCONFIG, PlotConfigStorage } from '@/types';
const PLOT_CONFIG = 'ft_custom_plot_config'; const PLOT_CONFIG = 'ft_custom_plot_config';
const PLOT_CONFIG_NAME = 'ft_selected_plot_config'; const PLOT_CONFIG_NAME = 'ft_selected_plot_config';
export function loadPlotConfigName(): string { export function getPlotConfigName(): string {
return localStorage.getItem(PLOT_CONFIG_NAME) || 'default'; return localStorage.getItem(PLOT_CONFIG_NAME) || 'default';
} }
@ -11,17 +11,21 @@ export function storePlotConfigName(plotConfigName: string): void {
localStorage.setItem(PLOT_CONFIG_NAME, plotConfigName); localStorage.setItem(PLOT_CONFIG_NAME, plotConfigName);
} }
export function loadAllCustomPlotConfig(): PlotConfig { export function getAllCustomPlotConfig(): PlotConfig {
return JSON.parse(localStorage.getItem(PLOT_CONFIG) || '{}'); return JSON.parse(localStorage.getItem(PLOT_CONFIG) || '{}');
} }
export function loadCustomPlotConfig(configName: string): PlotConfig { export function getAllPlotConfigNames(): Array<string> {
const configs = loadAllCustomPlotConfig(); return Object.keys(getAllCustomPlotConfig());
}
export function getCustomPlotConfig(configName: string): PlotConfig {
const configs = getAllCustomPlotConfig();
return configName in configs ? configs[configName] : { ...EMPTY_PLOTCONFIG }; return configName in configs ? configs[configName] : { ...EMPTY_PLOTCONFIG };
} }
export function storeCustomPlotConfig(plotConfig: PlotConfigStorage) { export function storeCustomPlotConfig(plotConfig: PlotConfigStorage) {
const existingConfig = loadAllCustomPlotConfig(); const existingConfig = getAllCustomPlotConfig();
// Merge existing with new config // Merge existing with new config
const finalPlotConfig = { ...existingConfig, ...plotConfig }; const finalPlotConfig = { ...existingConfig, ...plotConfig };

View File

@ -15,7 +15,12 @@ import {
PlotConfigStorage, PlotConfigStorage,
} from '@/types'; } from '@/types';
import { storeCustomPlotConfig, loadPlotConfigName, storePlotConfigName } from '@/shared/storage'; import {
storeCustomPlotConfig,
getPlotConfigName,
getAllPlotConfigNames,
storePlotConfigName,
} from '@/shared/storage';
import { showAlert } from './alerts'; import { showAlert } from './alerts';
export enum BotStoreGetters { export enum BotStoreGetters {
@ -47,7 +52,8 @@ export default {
history: {}, history: {},
strategyPlotConfig: {}, strategyPlotConfig: {},
customPlotConfig: { ...EMPTY_PLOTCONFIG }, customPlotConfig: { ...EMPTY_PLOTCONFIG },
plotConfigName: loadPlotConfigName(), plotConfigName: getPlotConfigName(),
availablePlotConfigNames: getAllPlotConfigNames(),
strategyList: [], strategyList: [],
pairlist: [], pairlist: [],
}, },
@ -128,12 +134,14 @@ export default {
state.strategyPlotConfig = plotConfig; state.strategyPlotConfig = plotConfig;
}, },
updatePlotConfigName(state, plotConfigName: string) { updatePlotConfigName(state, plotConfigName: string) {
// Set default plot config name
state.plotConfigName = plotConfigName; state.plotConfigName = plotConfigName;
storePlotConfigName(plotConfigName); storePlotConfigName(plotConfigName);
}, },
saveCustomPlotConfig(state, plotConfig: PlotConfigStorage) { saveCustomPlotConfig(state, plotConfig: PlotConfigStorage) {
state.customPlotConfig = plotConfig; state.customPlotConfig = plotConfig;
storeCustomPlotConfig(plotConfig); storeCustomPlotConfig(plotConfig);
state.availablePlotConfigNames = getAllPlotConfigNames();
}, },
}, },
actions: { actions: {

View File

@ -8,17 +8,13 @@
<b-button @click="refresh">&#x21bb;</b-button> <b-button @click="refresh">&#x21bb;</b-button>
</div> </div>
<div class="col-mb-2"> <div class="col-mb-2">
<b-form-select <b-select v-model="pair" :options="historicView ? pairlist : whitelist" @change="refresh">
:options="historicView ? pairlist : whitelist" </b-select>
v-model="pair"
@change="refresh"
>
</b-form-select>
</div> </div>
</div> </div>
<div class="mt-2 row" v-if="historicView"> <div v-if="historicView" class="mt-2 row">
<TimeRangeSelect class="col-md-4 mr-2" v-model="timerange"></TimeRangeSelect> <TimeRangeSelect v-model="timerange" class="col-md-4 mr-2"></TimeRangeSelect>
<StrategyList class="col-md-2" v-model="strategy"></StrategyList> <StrategyList v-model="strategy" class="col-md-2"></StrategyList>
</div> </div>
<div class="row"> <div class="row">
@ -40,7 +36,7 @@ import { namespace } from 'vuex-class';
import CandleChartContainer from '@/components/charts/CandleChartContainer.vue'; import CandleChartContainer from '@/components/charts/CandleChartContainer.vue';
import TimeRangeSelect from '@/components/ftbot/TimeRangeSelect.vue'; import TimeRangeSelect from '@/components/ftbot/TimeRangeSelect.vue';
import StrategyList from '@/components/ftbot/StrategyList.vue'; import StrategyList from '@/components/ftbot/StrategyList.vue';
import { AvailablePairPayload, PairCandlePayload, PairHistoryPayload } from '@/store/types'; import { AvailablePairPayload, PairCandlePayload, PairHistoryPayload } from '@/types';
const ftbot = namespace('ftbot'); const ftbot = namespace('ftbot');