Final components to script setup

This commit is contained in:
Matthias 2023-05-09 20:06:24 +02:00
parent 85820c8684
commit ff1b217ca9
5 changed files with 426 additions and 480 deletions

View File

@ -1,8 +1,8 @@
<template> <template>
<v-chart v-if="trades" :option="chartOptions" autoresize :theme="settingsStore.chartTheme" /> <e-charts v-if="trades" :option="chartOptions" autoresize :theme="settingsStore.chartTheme" />
</template> </template>
<script lang="ts"> <script setup lang="ts">
import ECharts from 'vue-echarts'; import ECharts from 'vue-echarts';
import { EChartsOption } from 'echarts'; import { EChartsOption } from 'echarts';
@ -18,7 +18,7 @@ import {
} from 'echarts/components'; } from 'echarts/components';
import { ClosedTrade, CumProfitData, CumProfitDataPerDate } from '@/types'; import { ClosedTrade, CumProfitData, CumProfitDataPerDate } from '@/types';
import { defineComponent, computed, ComputedRef } from 'vue'; import { computed, ComputedRef } from 'vue';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { dataZoomPartial } from '@/shared/charts/chartZoom'; import { dataZoomPartial } from '@/shared/charts/chartZoom';
@ -38,157 +38,147 @@ use([
// Define Column labels here to avoid typos // Define Column labels here to avoid typos
const CHART_PROFIT = 'Profit'; const CHART_PROFIT = 'Profit';
export default defineComponent({ const props = defineProps({
name: 'CumProfitChart', trades: { required: true, type: Array as () => ClosedTrade[] },
components: { showTitle: { default: true, type: Boolean },
'v-chart': ECharts, profitColumn: { default: 'profit_abs', type: String },
}, });
props: { const settingsStore = useSettingsStore();
trades: { required: true, type: Array as () => ClosedTrade[] }, // const botList = ref<string[]>([]);
showTitle: { default: true, type: Boolean }, // const cumulativeData = ref<{ date: number; profit: any }[]>([]);
profitColumn: { default: 'profit_abs', type: String },
},
setup(props) {
const settingsStore = useSettingsStore();
// const botList = ref<string[]>([]);
// const cumulativeData = ref<{ date: number; profit: any }[]>([]);
const cumulativeData: ComputedRef<{ date: number; profit: number }[]> = computed(() => { const cumulativeData: ComputedRef<{ date: number; profit: number }[]> = computed(() => {
const res: CumProfitData[] = []; const res: CumProfitData[] = [];
const resD: CumProfitDataPerDate = {}; const resD: CumProfitDataPerDate = {};
const closedTrades = props.trades const closedTrades = props.trades
.slice() .slice()
.sort((a, b) => (a.close_timestamp > b.close_timestamp ? 1 : -1)); .sort((a, b) => (a.close_timestamp > b.close_timestamp ? 1 : -1));
let profit = 0.0; let profit = 0.0;
for (let i = 0, len = closedTrades.length; i < len; i += 1) { for (let i = 0, len = closedTrades.length; i < len; i += 1) {
const trade = closedTrades[i]; const trade = closedTrades[i];
if (trade.close_timestamp && trade[props.profitColumn]) { if (trade.close_timestamp && trade[props.profitColumn]) {
profit += trade[props.profitColumn]; profit += trade[props.profitColumn];
if (!resD[trade.close_timestamp]) { if (!resD[trade.close_timestamp]) {
// New timestamp // New timestamp
resD[trade.close_timestamp] = { profit, [trade.botId]: profit }; resD[trade.close_timestamp] = { profit, [trade.botId]: profit };
} else { } else {
// Add to existing profit // Add to existing profit
resD[trade.close_timestamp].profit += trade[props.profitColumn]; resD[trade.close_timestamp].profit += trade[props.profitColumn];
if (resD[trade.close_timestamp][trade.botId]) { if (resD[trade.close_timestamp][trade.botId]) {
resD[trade.close_timestamp][trade.botId] += trade[props.profitColumn]; resD[trade.close_timestamp][trade.botId] += trade[props.profitColumn];
} else { } else {
resD[trade.close_timestamp][trade.botId] = profit; resD[trade.close_timestamp][trade.botId] = profit;
}
}
res.push({ date: trade.close_timestamp, profit, [trade.botId]: profit });
} }
} }
// console.log(resD); res.push({ date: trade.close_timestamp, profit, [trade.botId]: profit });
}
}
// console.log(resD);
return Object.entries(resD).map(([k, v]) => { return Object.entries(resD).map(([k, v]) => {
const obj = { date: parseInt(k, 10), profit: v.profit }; const obj = { date: parseInt(k, 10), profit: v.profit };
// TODO: The below could allow "lines" per bot" // TODO: The below could allow "lines" per bot"
// this.botList.forEach((botId) => { // this.botList.forEach((botId) => {
// obj[botId] = v[botId]; // obj[botId] = v[botId];
// }); // });
return obj; return obj;
}); });
}); });
const chartOptions = computed((): EChartsOption => { const chartOptions = computed((): EChartsOption => {
const chartOptionsLoc: EChartsOption = { const chartOptionsLoc: EChartsOption = {
title: { title: {
text: 'Cumulative Profit', text: 'Cumulative Profit',
show: props.showTitle, show: props.showTitle,
},
backgroundColor: 'rgba(0, 0, 0, 0)',
dataset: {
dimensions: ['date', 'profit'],
source: cumulativeData.value,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
label: {
backgroundColor: '#6a7985',
}, },
backgroundColor: 'rgba(0, 0, 0, 0)', },
dataset: { },
dimensions: ['date', 'profit'], legend: {
source: cumulativeData.value, data: [CHART_PROFIT],
right: '5%',
},
useUTC: false,
xAxis: {
type: 'time',
},
yAxis: [
{
type: 'value',
name: CHART_PROFIT,
splitLine: {
show: false,
}, },
tooltip: { nameRotate: 90,
trigger: 'axis', nameLocation: 'middle',
axisPointer: { nameGap: 40,
type: 'line', },
label: { ],
backgroundColor: '#6a7985', grid: {
}, bottom: 80,
}, },
}, dataZoom: [
legend: { {
data: [CHART_PROFIT], type: 'inside',
right: '5%', // xAxisIndex: [0],
}, start: 0,
useUTC: false,
xAxis: {
type: 'time',
},
yAxis: [
{
type: 'value',
name: CHART_PROFIT,
splitLine: {
show: false,
},
nameRotate: 90,
nameLocation: 'middle',
nameGap: 40,
},
],
grid: {
bottom: 80,
},
dataZoom: [
{
type: 'inside',
// xAxisIndex: [0],
start: 0,
end: 100, end: 100,
}, },
{ {
// xAxisIndex: [0], // xAxisIndex: [0],
bottom: 10, bottom: 10,
start: 0, start: 0,
end: 100, end: 100,
...dataZoomPartial, ...dataZoomPartial,
}, },
], ],
series: [ series: [
{ {
type: 'line', type: 'line',
name: CHART_PROFIT, name: CHART_PROFIT,
animation: true, animation: true,
step: 'end', step: 'end',
lineStyle: { lineStyle: {
color: settingsStore.chartTheme === 'dark' ? '#c2c2c2' : 'black', color: settingsStore.chartTheme === 'dark' ? '#c2c2c2' : 'black',
}, },
itemStyle: { itemStyle: {
color: settingsStore.chartTheme === 'dark' ? '#c2c2c2' : 'black', color: settingsStore.chartTheme === 'dark' ? '#c2c2c2' : 'black',
}, },
// symbol: 'none', // symbol: 'none',
}, },
], ],
}; };
// TODO: maybe have profit lines per bot? // TODO: maybe have profit lines per bot?
// this.botList.forEach((botId: string) => { // this.botList.forEach((botId: string) => {
// console.log('bot', botId); // console.log('bot', botId);
// chartOptionsLoc.series.push({ // chartOptionsLoc.series.push({
// type: 'line', // type: 'line',
// name: botId, // name: botId,
// animation: true, // animation: true,
// step: 'end', // step: 'end',
// lineStyle: { // lineStyle: {
// color: settingsStore.chartTheme === 'dark' ? '#c2c2c2' : 'black', // color: settingsStore.chartTheme === 'dark' ? '#c2c2c2' : 'black',
// }, // },
// itemStylesettingsStore.chartTheme === 'dark' ? '#c2c2c2' : 'black', // itemStylesettingsStore.chartTheme === 'dark' ? '#c2c2c2' : 'black',
// }, // },
// // symbol: 'none', // // symbol: 'none',
// }); // });
// }); // });
return chartOptionsLoc; return chartOptionsLoc;
});
return { settingsStore, cumulativeData, chartOptions };
},
}); });
</script> </script>

View File

@ -1,5 +1,5 @@
<template> <template>
<v-chart <e-charts
v-if="dailyStats.data" v-if="dailyStats.data"
:option="dailyChartOptions" :option="dailyChartOptions"
:theme="settingsStore.chartTheme" :theme="settingsStore.chartTheme"
@ -7,8 +7,8 @@
/> />
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, computed, ComputedRef } from 'vue'; import { computed, ComputedRef } from 'vue';
import ECharts from 'vue-echarts'; import ECharts from 'vue-echarts';
// import { EChartsOption } from 'echarts'; // import { EChartsOption } from 'echarts';
@ -44,125 +44,113 @@ use([
const CHART_ABS_PROFIT = 'Absolute profit'; const CHART_ABS_PROFIT = 'Absolute profit';
const CHART_TRADE_COUNT = 'Trade Count'; const CHART_TRADE_COUNT = 'Trade Count';
export default defineComponent({ const props = defineProps({
components: { dailyStats: {
'v-chart': ECharts, type: Object as () => DailyReturnValue,
required: true,
}, },
props: { showTitle: {
dailyStats: { type: Boolean,
type: Object as () => DailyReturnValue, default: true,
required: true,
},
showTitle: {
type: Boolean,
default: true,
},
}, },
});
setup(props) { const settingsStore = useSettingsStore();
const settingsStore = useSettingsStore(); const absoluteMin = computed(() =>
const absoluteMin = computed(() => props.dailyStats.data.reduce(
props.dailyStats.data.reduce( (min, p) => (p.abs_profit < min ? p.abs_profit : min),
(min, p) => (p.abs_profit < min ? p.abs_profit : min), props.dailyStats.data[0]?.abs_profit,
props.dailyStats.data[0]?.abs_profit, ),
), );
); const absoluteMax = computed(() =>
const absoluteMax = computed(() => props.dailyStats.data.reduce(
props.dailyStats.data.reduce( (max, p) => (p.abs_profit > max ? p.abs_profit : max),
(max, p) => (p.abs_profit > max ? p.abs_profit : max), props.dailyStats.data[0]?.abs_profit,
props.dailyStats.data[0]?.abs_profit, ),
), );
); const dailyChartOptions: ComputedRef<EChartsOption> = computed(() => {
const dailyChartOptions: ComputedRef<EChartsOption> = computed(() => { return {
return { title: {
title: { text: 'Daily profit',
text: 'Daily profit', show: props.showTitle,
show: props.showTitle, },
backgroundColor: 'rgba(0, 0, 0, 0)',
dataset: {
dimensions: ['date', 'abs_profit', 'trade_count'],
source: props.dailyStats.data,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
label: {
backgroundColor: '#6a7985',
}, },
backgroundColor: 'rgba(0, 0, 0, 0)', },
dataset: { },
dimensions: ['date', 'abs_profit', 'trade_count'], legend: {
source: props.dailyStats.data, data: [CHART_ABS_PROFIT, CHART_TRADE_COUNT],
}, right: '5%',
tooltip: { },
trigger: 'axis', xAxis: [
axisPointer: { {
type: 'line', type: 'category',
label: { },
backgroundColor: '#6a7985', ],
}, visualMap: [
}, {
}, dimension: 1,
legend: { seriesIndex: 0,
data: [CHART_ABS_PROFIT, CHART_TRADE_COUNT], show: false,
right: '5%', pieces: [
},
xAxis: [
{ {
type: 'category', max: 0.0,
min: absoluteMin.value,
color: 'red',
},
{
min: 0.0,
max: absoluteMax.value,
color: 'green',
}, },
], ],
visualMap: [ },
{ ],
dimension: 1, yAxis: [
seriesIndex: 0, {
show: false, type: 'value',
pieces: [ name: CHART_ABS_PROFIT,
{ splitLine: {
max: 0.0, show: false,
min: absoluteMin.value, },
color: 'red', nameRotate: 90,
}, nameLocation: 'middle',
{ nameGap: 40,
min: 0.0, },
max: absoluteMax.value, {
color: 'green', type: 'value',
}, name: CHART_TRADE_COUNT,
], nameRotate: 90,
}, nameLocation: 'middle',
], nameGap: 30,
yAxis: [ },
{ ],
type: 'value', series: [
name: CHART_ABS_PROFIT, {
splitLine: { type: 'line',
show: false, name: CHART_ABS_PROFIT,
}, // Color is induced by visualMap
nameRotate: 90, },
nameLocation: 'middle', {
nameGap: 40, type: 'bar',
}, name: CHART_TRADE_COUNT,
{ itemStyle: {
type: 'value', color: 'rgba(150,150,150,0.3)',
name: CHART_TRADE_COUNT, },
nameRotate: 90, yAxisIndex: 1,
nameLocation: 'middle', },
nameGap: 30, ],
}, };
],
series: [
{
type: 'line',
name: CHART_ABS_PROFIT,
// Color is induced by visualMap
},
{
type: 'bar',
name: CHART_TRADE_COUNT,
itemStyle: {
color: 'rgba(150,150,150,0.3)',
},
yAxisIndex: 1,
},
],
};
});
return {
dailyChartOptions,
settingsStore,
};
},
}); });
</script> </script>

View File

@ -1,5 +1,5 @@
<template> <template>
<v-chart <e-charts
v-if="trades.length > 0" v-if="trades.length > 0"
:option="hourlyChartOptions" :option="hourlyChartOptions"
autoresize autoresize
@ -7,10 +7,10 @@
/> />
</template> </template>
<script lang="ts"> <script setup lang="ts">
import ECharts from 'vue-echarts'; import ECharts from 'vue-echarts';
import { useSettingsStore } from '@/stores/settings'; import { useSettingsStore } from '@/stores/settings';
import { defineComponent, computed } from 'vue'; import { computed } from 'vue';
import { Trade } from '@/types'; import { Trade } from '@/types';
import { timestampHour } from '@/shared/formatters'; import { timestampHour } from '@/shared/formatters';
@ -45,121 +45,112 @@ use([
const CHART_PROFIT = 'Profit %'; const CHART_PROFIT = 'Profit %';
const CHART_TRADE_COUNT = 'Trade Count'; const CHART_TRADE_COUNT = 'Trade Count';
export default defineComponent({ const props = defineProps({
name: 'HourlyChart', trades: { required: true, type: Array as () => Trade[] },
components: { showTitle: { default: true, type: Boolean },
'v-chart': ECharts, });
}, const settingsStore = useSettingsStore();
props: {
trades: { required: true, type: Array as () => Trade[] },
showTitle: { default: true, type: Boolean },
},
setup(props) {
const settingsStore = useSettingsStore();
const hourlyData = computed(() => { const hourlyData = computed(() => {
const res = new Array(24); const res = new Array(24);
for (let i = 0; i < 24; i += 1) { for (let i = 0; i < 24; i += 1) {
res[i] = { hour: i, hourDesc: `${i}h`, profit: 0.0, count: 0.0 }; res[i] = { hour: i, hourDesc: `${i}h`, profit: 0.0, count: 0.0 };
} }
for (let i = 0, len = props.trades.length; i < len; i += 1) { for (let i = 0, len = props.trades.length; i < len; i += 1) {
const trade = props.trades[i]; const trade = props.trades[i];
if (trade.close_timestamp) { if (trade.close_timestamp) {
const hour = timestampHour(trade.close_timestamp); const hour = timestampHour(trade.close_timestamp);
res[hour].profit += trade.profit_ratio; res[hour].profit += trade.profit_ratio;
res[hour].count += 1; res[hour].count += 1;
} }
} }
return res; return res;
}); });
const hourlyChartOptions = computed((): EChartsOption => { const hourlyChartOptions = computed((): EChartsOption => {
return { return {
title: { title: {
text: 'Hourly Profit', text: 'Hourly Profit',
show: props.showTitle, show: props.showTitle,
},
backgroundColor: 'rgba(0, 0, 0, 0)',
dataset: {
dimensions: ['hourDesc', 'profit', 'count'],
source: hourlyData.value,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
label: {
backgroundColor: '#6a7985',
}, },
backgroundColor: 'rgba(0, 0, 0, 0)', },
dataset: { },
dimensions: ['hourDesc', 'profit', 'count'], legend: {
source: hourlyData.value, data: [CHART_PROFIT, CHART_TRADE_COUNT],
right: '5%',
},
xAxis: {
type: 'category',
},
yAxis: [
{
type: 'value',
name: CHART_PROFIT,
splitLine: {
show: false,
}, },
tooltip: { nameRotate: 90,
trigger: 'axis', nameLocation: 'middle',
axisPointer: { nameGap: 30,
type: 'line', },
label: { {
backgroundColor: '#6a7985', type: 'value',
}, name: CHART_TRADE_COUNT,
}, nameRotate: 90,
}, nameLocation: 'middle',
legend: { nameGap: 30,
data: [CHART_PROFIT, CHART_TRADE_COUNT], },
right: '5%', ],
}, visualMap: [
xAxis: { {
type: 'category', dimension: 1,
}, seriesIndex: 0,
yAxis: [ show: false,
pieces: [
{ {
type: 'value', max: 0.0,
name: CHART_PROFIT, min: -2,
splitLine: { color: 'red',
show: false,
},
nameRotate: 90,
nameLocation: 'middle',
nameGap: 30,
}, },
{ {
type: 'value', min: 0.0,
name: CHART_TRADE_COUNT, max: 2,
nameRotate: 90, color: 'green',
nameLocation: 'middle',
nameGap: 30,
}, },
], ],
visualMap: [ },
{ ],
dimension: 1, series: [
seriesIndex: 0, {
show: false, type: 'line',
pieces: [ name: CHART_PROFIT,
{ animation: false,
max: 0.0, // symbol: 'none',
min: -2, },
color: 'red', {
}, type: 'bar',
{ name: CHART_TRADE_COUNT,
min: 0.0, animation: false,
max: 2, itemStyle: {
color: 'green', color: 'rgba(150,150,150,0.3)',
}, },
], yAxisIndex: 1,
}, },
], ],
series: [ };
{
type: 'line',
name: CHART_PROFIT,
animation: false,
// symbol: 'none',
},
{
type: 'bar',
name: CHART_TRADE_COUNT,
animation: false,
itemStyle: {
color: 'rgba(150,150,150,0.3)',
},
yAxisIndex: 1,
},
],
};
});
return { settingsStore, hourlyChartOptions };
},
}); });
</script> </script>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="d-flex flex-column h-100 position-relative"> <div class="d-flex flex-column h-100 position-relative">
<div class="flex-grow-1 order-2"> <div class="flex-grow-1 order-2">
<v-chart v-if="trades" :option="chartOptions" autoresize :theme="settingsStore.chartTheme" /> <e-charts v-if="trades" :option="chartOptions" autoresize :theme="settingsStore.chartTheme" />
</div> </div>
<b-form-group <b-form-group
class="w-25 order-1" class="w-25 order-1"
@ -22,8 +22,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, computed } from 'vue'; import { computed } from 'vue';
import ECharts from 'vue-echarts'; import ECharts from 'vue-echarts';
import { EChartsOption } from 'echarts'; import { EChartsOption } from 'echarts';
@ -57,92 +57,82 @@ use([
// Define Column labels here to avoid typos // Define Column labels here to avoid typos
const CHART_PROFIT = 'Trade count'; const CHART_PROFIT = 'Trade count';
export default defineComponent({ const props = defineProps({
name: 'ProfitDistributionChart', trades: { required: true, type: Array as () => ClosedTrade[] },
components: { showTitle: { default: true, type: Boolean },
'v-chart': ECharts, });
}, const settingsStore = useSettingsStore();
props: { // registerTransform(ecStat.transform.histogram);
trades: { required: true, type: Array as () => ClosedTrade[] }, // console.log(profits);
showTitle: { default: true, type: Boolean }, // const data = [[]];
}, const binOptions = [10, 15, 20, 25, 50];
setup(props) { const data = computed(() => {
const settingsStore = useSettingsStore(); const profits = props.trades.map((trade) => trade.profit_ratio);
// registerTransform(ecStat.transform.histogram);
// console.log(profits);
// const data = [[]];
const binOptions = [10, 15, 20, 25, 50];
const data = computed(() => {
const profits = props.trades.map((trade) => trade.profit_ratio);
return binData(profits, settingsStore.profitDistributionBins); return binData(profits, settingsStore.profitDistributionBins);
}); });
const chartOptions = computed((): EChartsOption => { const chartOptions = computed((): EChartsOption => {
const chartOptionsLoc: EChartsOption = { const chartOptionsLoc: EChartsOption = {
title: { title: {
text: 'Profit distribution', text: 'Profit distribution',
show: props.showTitle, show: props.showTitle,
},
backgroundColor: 'rgba(0, 0, 0, 0)',
dataset: {
source: data.value,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
label: {
backgroundColor: '#6a7985',
}, },
backgroundColor: 'rgba(0, 0, 0, 0)', },
dataset: { },
source: data.value, legend: {
data: [CHART_PROFIT],
right: '5%',
},
xAxis: {
type: 'category',
name: 'Profit %',
nameLocation: 'middle',
nameGap: 25,
},
yAxis: [
{
type: 'value',
name: CHART_PROFIT,
splitLine: {
show: false,
}, },
tooltip: { nameRotate: 90,
trigger: 'axis', nameLocation: 'middle',
axisPointer: { nameGap: 35,
type: 'line', position: 'left',
label: { },
backgroundColor: '#6a7985', ],
}, // grid: {
}, // bottom: 80,
}, // },
legend: {
data: [CHART_PROFIT],
right: '5%',
},
xAxis: {
type: 'category',
name: 'Profit %',
nameLocation: 'middle',
nameGap: 25,
},
yAxis: [
{
type: 'value',
name: CHART_PROFIT,
splitLine: {
show: false,
},
nameRotate: 90,
nameLocation: 'middle',
nameGap: 35,
position: 'left',
},
],
// grid: {
// bottom: 80,
// },
series: [ series: [
{ {
type: 'bar', type: 'bar',
name: CHART_PROFIT, name: CHART_PROFIT,
animation: true, animation: true,
encode: { encode: {
x: 'x0', x: 'x0',
y: 'y0', y: 'y0',
}, },
// symbol: 'none', // symbol: 'none',
}, },
], ],
}; };
return chartOptionsLoc; return chartOptionsLoc;
});
// console.log(chartOptions);
return { settingsStore, chartOptions, binOptions };
},
}); });
</script> </script>

View File

@ -21,43 +21,30 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { timestampms } from '@/shared/formatters'; import { timestampms } from '@/shared/formatters';
import { Lock } from '@/types'; import { Lock } from '@/types';
import { showAlert } from '@/stores/alerts'; import { showAlert } from '@/stores/alerts';
import { useBotStore } from '@/stores/ftbotwrapper'; import { useBotStore } from '@/stores/ftbotwrapper';
import { defineComponent } from 'vue'; import { TableField } from 'bootstrap-vue-next';
const botStore = useBotStore();
export default defineComponent({ const tableFields: TableField[] = [
name: 'PairLockList', { key: 'pair', label: 'Pair' },
setup() { { key: 'lock_end_timestamp', label: 'Until', formatter: (value) => timestampms(value as number) },
const botStore = useBotStore(); { key: 'reason', label: 'Reason' },
{ key: 'actions' },
];
const tableFields = [ const removePairLock = (item: Lock) => {
{ key: 'pair', label: 'Pair' }, console.log(item);
{ key: 'lock_end_timestamp', label: 'Until', formatter: 'timestampms' }, if (item.id !== undefined) {
{ key: 'reason', label: 'Reason' }, botStore.activeBot.deleteLock(item.id);
{ key: 'actions' }, } else {
]; showAlert('This Freqtrade version does not support deleting locks.');
}
const removePairLock = (item: Lock) => { };
console.log(item);
if (item.id !== undefined) {
botStore.activeBot.deleteLock(item.id);
} else {
showAlert('This Freqtrade version does not support deleting locks.');
}
};
return {
timestampms,
botStore,
tableFields,
removePairLock,
};
},
});
</script> </script>
<style scoped></style> <style scoped></style>