Update profit-chart to include all bots

This commit is contained in:
Matthias 2021-09-04 16:41:44 +02:00
parent 1df87176bc
commit 211d7a3115
5 changed files with 71 additions and 10 deletions

View File

@ -1,5 +1,5 @@
<template> <template>
<v-chart v-if="trades.length > 0" :option="chartOptions" autoresize :theme="getChartTheme" /> <v-chart v-if="trades" :option="chartOptions" autoresize :theme="getChartTheme" />
</template> </template>
<script lang="ts"> <script lang="ts">
@ -53,24 +53,54 @@ export default class CumProfitChart extends Vue {
@Getter getChartTheme!: string; @Getter getChartTheme!: string;
botList: string[] = [];
get cumulativeData() { get cumulativeData() {
this.botList = [];
const res: CumProfitData[] = []; const res: CumProfitData[] = [];
const resD = {};
const closedTrades = this.trades const closedTrades = this.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[this.profitColumn]) { if (trade.close_timestamp && trade[this.profitColumn]) {
profit += trade[this.profitColumn]; profit += trade[this.profitColumn];
res.push({ date: trade.close_timestamp, profit }); if (!resD[trade.close_timestamp]) {
// New timestamp
resD[trade.close_timestamp] = { profit, [trade.botId]: profit };
} else {
// Add to existing profit
resD[trade.close_timestamp].profit += profit;
if (resD[trade.close_timestamp][trade.botId]) {
resD[trade.close_timestamp][trade.botId] += profit;
} else {
resD[trade.close_timestamp][trade.botId] = profit;
}
}
res.push({ date: trade.close_timestamp, profit, [trade.botId]: profit });
if (!this.botList.includes(trade.botId)) {
this.botList.push(trade.botId);
}
} }
} }
return res; // console.log(resD);
return Object.entries(resD).map(([k, v]) => {
const obj = { date: parseInt(k, 10), profit: v.profit };
// TODO: The below could allow "lines" per bot"
// this.botList.forEach((botId) => {
// obj[botId] = v[botId];
// });
return obj;
});
} }
get chartOptions(): EChartsOption { get chartOptions(): EChartsOption {
return { const chartOptionsLoc: EChartsOption = {
title: { title: {
text: 'Cumulative Profit', text: 'Cumulative Profit',
show: this.showTitle, show: this.showTitle,
@ -151,6 +181,24 @@ export default class CumProfitChart extends Vue {
}, },
], ],
}; };
// TODO: maybe have profit lines per bot?
// this.botList.forEach((botId: string) => {
// console.log('bot', botId);
// chartOptionsLoc.series.push({
// type: 'line',
// name: botId,
// animation: true,
// step: 'end',
// lineStyle: {
// color: this.getChartTheme === 'dark' ? '#c2c2c2' : 'black',
// },
// itemStyle: {
// color: this.getChartTheme === 'dark' ? '#c2c2c2' : 'black',
// },
// // symbol: 'none',
// });
// });
return chartOptionsLoc;
} }
} }
</script> </script>

View File

@ -1,4 +1,4 @@
import { BotDescriptor, BotDescriptors } from '@/types'; import { BotDescriptor, BotDescriptors, Trade } from '@/types';
import { AxiosInstance } from 'axios'; import { AxiosInstance } from 'axios';
import { BotStoreActions, BotStoreGetters, createBotSubStore } from './ftbot'; import { BotStoreActions, BotStoreGetters, createBotSubStore } from './ftbot';
@ -18,6 +18,7 @@ export enum MultiBotStoreGetters {
selectedBotObj = 'selectedBotObj', selectedBotObj = 'selectedBotObj',
allAvailableBots = 'allAvailableBots', allAvailableBots = 'allAvailableBots',
allAvailableBotsList = 'allAvailableBotsList', allAvailableBotsList = 'allAvailableBotsList',
allTradesAllBots = 'allTradesAllBots',
// Automatically created entries // Automatically created entries
allIsBotOnline = 'allIsBotOnline', allIsBotOnline = 'allIsBotOnline',
allAutoRefresh = 'allAutoRefresh', allAutoRefresh = 'allAutoRefresh',
@ -76,6 +77,15 @@ export default function createBotStore(store) {
[MultiBotStoreGetters.allAvailableBotsList](state: FTMultiBotState): string[] { [MultiBotStoreGetters.allAvailableBotsList](state: FTMultiBotState): string[] {
return Object.keys(state.availableBots); return Object.keys(state.availableBots);
}, },
[MultiBotStoreGetters.allTradesAllBots](state: FTMultiBotState, getters): Trade[] {
let resp: Trade[] = [];
getters.allAvailableBotsList.forEach((botId) => {
const trades = getters[`${botId}/${BotStoreGetters.trades}`].map((t) => ({ ...t, botId }));
resp = resp.concat(trades);
});
return resp;
},
}; };
// Autocreate getters from botStores // Autocreate getters from botStores
Object.keys(BotStoreGetters).forEach((e) => { Object.keys(BotStoreGetters).forEach((e) => {
@ -160,7 +170,6 @@ export default function createBotStore(store) {
commit('selectBot', botId); commit('selectBot', botId);
}, },
allRefreshFrequent({ dispatch, getters }, slow: boolean) { allRefreshFrequent({ dispatch, getters }, slow: boolean) {
console.log('dispatching all frequent refreshes');
getters.allAvailableBotsList.forEach((e) => { getters.allAvailableBotsList.forEach((e) => {
if (getters[`${e}/${BotStoreGetters.refreshNow}`]) { if (getters[`${e}/${BotStoreGetters.refreshNow}`]) {
// console.log('refreshing', e); // console.log('refreshing', e);
@ -169,7 +178,6 @@ export default function createBotStore(store) {
}); });
}, },
allRefreshSlow({ dispatch, getters }) { allRefreshSlow({ dispatch, getters }) {
console.log('dispatching all slow refreshes');
getters.allAvailableBotsList.forEach((e) => { getters.allAvailableBotsList.forEach((e) => {
if (getters[`${e}/${BotStoreGetters.refreshNow}`]) { if (getters[`${e}/${BotStoreGetters.refreshNow}`]) {
dispatch(`${e}/${BotStoreActions.refreshSlow}`); dispatch(`${e}/${BotStoreActions.refreshSlow}`);

View File

@ -325,7 +325,7 @@ export function createBotSubStore(botId: string) {
state.tradeCount = tradesCount; state.tradeCount = tradesCount;
}, },
updateOpenTrades(state: FtbotStateType, trades) { updateOpenTrades(state: FtbotStateType, trades) {
console.log(`Update open trade length ${trades.length}`); // console.log(`Update open trade length ${trades.length}`);
state.openTrades = trades; state.openTrades = trades;
}, },
updateLocks(state: FtbotStateType, locks: LockResponse) { updateLocks(state: FtbotStateType, locks: LockResponse) {

View File

@ -1,4 +1,9 @@
export interface Trade { export interface Trade {
/**
* BotId - only available on "all" methods.
* corresponds to the UI (ftbot.1) - does NOT relate to the backend
*/
botId: string;
trade_id: number; trade_id: number;
pair: string; pair: string;
is_open: boolean; is_open: boolean;

View File

@ -101,7 +101,7 @@
drag-allow-from=".drag-header" drag-allow-from=".drag-header"
> >
<DraggableContainer header="Cumulative Profit"> <DraggableContainer header="Cumulative Profit">
<CumProfitChart :trades="closedTrades" :show-title="false" /> <CumProfitChart :trades="allTradesAllBots" :show-title="false" />
</DraggableContainer> </DraggableContainer>
</GridItem> </GridItem>
<GridItem <GridItem
@ -169,7 +169,7 @@ const layoutNs = namespace('layout');
export default class Dashboard extends Vue { export default class Dashboard extends Vue {
@ftbot.Getter closedTrades!: Trade[]; @ftbot.Getter closedTrades!: Trade[];
@ftbot.Getter [MultiBotStoreGetters.allClosedTrades]!: Record<string, ClosedTrade>; @ftbot.Getter [MultiBotStoreGetters.allTradesAllBots]!: ClosedTrade[];
@ftbot.Getter [BotStoreGetters.dailyStats]!: DailyReturnValue; @ftbot.Getter [BotStoreGetters.dailyStats]!: DailyReturnValue;