mirror of
https://github.com/freqtrade/frequi.git
synced 2024-11-27 13:35:17 +00:00
Update profit-chart to include all bots
This commit is contained in:
parent
1df87176bc
commit
211d7a3115
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
res.push({ date: trade.close_timestamp, profit, [trade.botId]: profit });
|
||||||
|
if (!this.botList.includes(trade.botId)) {
|
||||||
|
this.botList.push(trade.botId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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>
|
||||||
|
|
|
@ -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}`);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user