Merge pull request #762 from freqtrade/dashboard_select

Allow selection of Multiple bots for Dashboard View
This commit is contained in:
Matthias 2022-05-05 07:08:27 +02:00 committed by GitHub
commit 2705c62c20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 31 deletions

View File

@ -8,6 +8,16 @@
:items="tableItems"
:fields="tableFields"
>
<template #cell(botName)="row">
<div class="d-flex flex-row">
<b-form-checkbox
v-if="row.item.botId && botStore.botCount > 1"
v-model="botStore.botStores[row.item.botId].isSelected"
title="Show bot in Dashboard"
/>
<span>{{ row.value }}</span>
</div>
</template>
<template #cell(profitOpen)="row">
<profit-pill
v-if="row.item.profitOpen && row.item.botId != 'Summary'"
@ -47,7 +57,7 @@ import ProfitPill from '@/components/general/ProfitPill.vue';
import { formatPrice } from '@/shared/formatters';
import { defineComponent, computed } from '@vue/composition-api';
import { useBotStore } from '@/stores/ftbotwrapper';
import { ProfitInterface } from '@/types';
import { ProfitInterface, ComparisonTableItems } from '@/types';
export default defineComponent({
name: 'BotComparisonList',
@ -56,7 +66,7 @@ export default defineComponent({
const botStore = useBotStore();
const tableFields: Record<string, string | Function>[] = [
{ key: 'botId', label: 'Bot' },
{ key: 'botName', label: 'Bot' },
{ key: 'trades', label: 'Trades' },
{ key: 'profitOpen', label: 'Open Profit' },
{ key: 'profitClosed', label: 'Closed Profit' },
@ -66,9 +76,10 @@ export default defineComponent({
const tableItems = computed(() => {
console.log('tableItems called');
const val: any[] = [];
const summary = {
botId: 'Summary',
const val: ComparisonTableItems[] = [];
const summary: ComparisonTableItems = {
botId: undefined,
botName: 'Summary',
profitClosed: 0,
profitClosedRatio: 0,
profitOpen: 0,
@ -87,7 +98,8 @@ export default defineComponent({
// TODO: handle one inactive bot ...
val.push({
botId: botStore.availableBots[k].botName,
botId: k,
botName: botStore.availableBots[k].botName,
trades: `${botStore.allOpenTradeCount[k]} / ${
botStore.allBotState[k]?.max_open_trades || 'N/A'
}`,
@ -117,6 +129,7 @@ export default defineComponent({
formatPrice,
tableFields,
tableItems,
botStore,
};
},
});

View File

@ -44,7 +44,7 @@ import {
TradeResponse,
ClosedTrade,
} from '@/types';
import axios, { AxiosInstance, AxiosResponse } from 'axios';
import axios, { AxiosResponse } from 'axios';
import { defineStore } from 'pinia';
import { showAlert } from './alerts';
@ -55,6 +55,7 @@ export function createBotSubStore(botId: string, botName: string) {
const useBotStore = defineStore(botId, {
state: () => {
return {
isSelected: true,
ping: '',
botStatusAvailable: false,
isBotOnline: false,

View File

@ -14,7 +14,6 @@ import {
RenameBotPayload,
Trade,
} from '@/types';
import { AxiosInstance } from 'axios';
import { defineStore } from 'pinia';
import { createBotSubStore } from './ftbot';
const AUTH_SELECTED_BOT = 'ftSelectedBot';
@ -89,24 +88,29 @@ export const useBotStore = defineStore('wrapper', {
return result;
},
allOpenTradesAllBots: (state): Trade[] => {
allOpenTradesSelectedBots: (state): Trade[] => {
const result: Trade[] = [];
Object.entries(state.botStores).forEach(([, botStore]) => {
if (botStore.isSelected) {
result.push(...botStore.openTrades);
}
});
return result;
},
allTradesAllBots: (state): ClosedTrade[] => {
allTradesSelectedBots: (state): ClosedTrade[] => {
const result: ClosedTrade[] = [];
Object.entries(state.botStores).forEach(([, botStore]) => {
if (botStore.isSelected) {
result.push(...botStore.trades);
}
});
return result;
},
allDailyStatsAllBots: (state): DailyReturnValue => {
allDailyStatsSelectedBots: (state): DailyReturnValue => {
// Return aggregated daily stats for all bots - sorted ascending.
const resp: Record<string, DailyRecord> = {};
Object.entries(state.botStores).forEach(([, botStore]) => {
if (botStore.isSelected) {
botStore.dailyStats?.data?.forEach((d) => {
if (!resp[d.date]) {
resp[d.date] = { ...d };
@ -119,6 +123,7 @@ export const useBotStore = defineStore('wrapper', {
resp[d.date].trade_count += d.trade_count;
}
});
}
});
const dailyReturn: DailyReturnValue = {

View File

@ -0,0 +1,14 @@
export interface ComparisonTableItems {
botId: string | undefined;
botName: string;
trades?: string;
profitClosed: number;
profitClosedRatio: number;
profitOpen: number;
profitOpenRatio: number;
stakeCurrency: string;
wins: number;
losses: number;
balance?: number;
stakeCurrencyDecimals?: number;
}

View File

@ -1,7 +1,8 @@
export * from './auth';
export * from './balance';
export * from './backtest';
export * from './balance';
export * from './blacklist';
export * from './botComparison';
export * from './chart';
export * from './daily';
export * from './locks';

View File

@ -26,8 +26,8 @@
>
<DraggableContainer :header="`Daily Profit ${botStore.botCount > 1 ? 'combined' : ''}`">
<DailyChart
v-if="botStore.allDailyStatsAllBots"
:daily-stats="botStore.allDailyStatsAllBots"
v-if="botStore.allDailyStatsSelectedBots"
:daily-stats="botStore.allDailyStatsSelectedBots"
:show-title="false"
/>
</DraggableContainer>
@ -57,7 +57,11 @@
drag-allow-from=".drag-header"
>
<DraggableContainer header="Open Trades">
<trade-list :active-trades="true" :trades="botStore.allOpenTradesAllBots" multi-bot-view />
<trade-list
:active-trades="true"
:trades="botStore.allOpenTradesSelectedBots"
multi-bot-view
/>
</DraggableContainer>
</GridItem>
<GridItem
@ -71,7 +75,7 @@
drag-allow-from=".drag-header"
>
<DraggableContainer header="Cumulative Profit">
<CumProfitChart :trades="botStore.allTradesAllBots" :show-title="false" />
<CumProfitChart :trades="botStore.allTradesSelectedBots" :show-title="false" />
</DraggableContainer>
</GridItem>
<GridItem
@ -85,7 +89,7 @@
drag-allow-from=".drag-header"
>
<DraggableContainer header="Trades Log">
<TradesLogChart :trades="botStore.allTradesAllBots" :show-title="false" />
<TradesLogChart :trades="botStore.allTradesSelectedBots" :show-title="false" />
</DraggableContainer>
</GridItem>
</GridLayout>