diff --git a/src/components/BotEntry.vue b/src/components/BotEntry.vue new file mode 100644 index 00000000..54cf7228 --- /dev/null +++ b/src/components/BotEntry.vue @@ -0,0 +1,82 @@ + + + {{ bot.botName || bot.botId }} + + + {{ + allIsBotOnline[bot.botId] ? '🟢' : '🔴' + }} + + R + + + + + + + + + + + + + + diff --git a/src/components/BotList.vue b/src/components/BotList.vue new file mode 100644 index 00000000..77188a99 --- /dev/null +++ b/src/components/BotList.vue @@ -0,0 +1,46 @@ + + + Available bots + + + + + + + + + + + + diff --git a/src/components/Login.vue b/src/components/Login.vue index 96e68ce6..cf566dfa 100644 --- a/src/components/Login.vue +++ b/src/components/Login.vue @@ -1,6 +1,14 @@ + + + @@ -60,18 +69,29 @@ diff --git a/src/components/charts/HourlyChart.vue b/src/components/charts/HourlyChart.vue index 753bf25c..a1663909 100644 --- a/src/components/charts/HourlyChart.vue +++ b/src/components/charts/HourlyChart.vue @@ -52,6 +52,7 @@ const CHART_TRADE_COUNT = 'Trade Count'; }, }) export default class HourlyChart extends Vue { + // TODO: This chart is not used at the moment! @Prop({ required: true }) trades!: Trade[]; @Prop({ default: true, type: Boolean }) showTitle!: boolean; diff --git a/src/components/charts/PlotConfigurator.vue b/src/components/charts/PlotConfigurator.vue index b6a655ac..088845ac 100644 --- a/src/components/charts/PlotConfigurator.vue +++ b/src/components/charts/PlotConfigurator.vue @@ -124,9 +124,12 @@ import { PlotConfig, EMPTY_PLOTCONFIG, IndicatorConfig } from '@/types'; import { getCustomPlotConfig } from '@/shared/storage'; import PlotIndicator from '@/components/charts/PlotIndicator.vue'; import { BotStoreGetters } from '@/store/modules/ftbot'; +import { AlertActions } from '@/store/modules/alerts'; const ftbot = namespace('ftbot'); +const alerts = namespace('alerts'); + @Component({ components: { PlotIndicator }, }) @@ -202,6 +205,8 @@ export default class PlotConfigurator extends Vue { @ftbot.Getter [BotStoreGetters.plotConfigName]!: string; + @alerts.Action [AlertActions.addAlert]; + get plotConfigJson() { return JSON.stringify(this.plotConfig, null, 2); } @@ -334,9 +339,14 @@ export default class PlotConfigurator extends Vue { } async loadPlotConfigFromStrategy() { - await this.getStrategyPlotConfig(); - this.plotConfig = this.strategyPlotConfig; - this.emitPlotConfig(); + try { + await this.getStrategyPlotConfig(); + this.plotConfig = this.strategyPlotConfig; + this.emitPlotConfig(); + } catch (data) { + // + this.addAlert({ message: 'Failed to load Plot configuration from Strategy.' }); + } } } diff --git a/src/components/charts/TradesLog.vue b/src/components/charts/TradesLog.vue index 3bd9fcb5..d9d52f4a 100644 --- a/src/components/charts/TradesLog.vue +++ b/src/components/charts/TradesLog.vue @@ -62,7 +62,7 @@ export default class TradesLogChart extends Vue { .sort((a, b) => (a.close_timestamp > b.close_timestamp ? 1 : -1)); for (let i = 0, len = sortedTrades.length; i < len; i += 1) { const trade = sortedTrades[i]; - const entry = [i, (trade.profit_ratio * 100).toFixed(2), trade.pair]; + const entry = [i, (trade.profit_ratio * 100).toFixed(2), trade.pair, trade.botName]; res.push(entry); } @@ -86,7 +86,7 @@ export default class TradesLogChart extends Vue { tooltip: { trigger: 'axis', formatter: (params) => { - return `Profit %${params[0].data[1]} % ${params[0].data[2]}`; + return `Profit %${params[0].data[1]} % ${params[0].data[2]} | ${params[0].data[3]}`; }, axisPointer: { type: 'line', diff --git a/src/components/ftbot/BotComarisonList.vue b/src/components/ftbot/BotComarisonList.vue new file mode 100644 index 00000000..3cbafd9a --- /dev/null +++ b/src/components/ftbot/BotComarisonList.vue @@ -0,0 +1,119 @@ + + + + + + + + + + + {{ formatPrice(row.item.balance, row.item.stakeCurrencyDecimals) }} + + {{ row.item.stakeCurrency }} + + + + + {{ row.item.wins }} / + {{ row.item.losses }} + + + + + + + + diff --git a/src/components/ftbot/BotControls.vue b/src/components/ftbot/BotControls.vue index 690016ae..31ce6057 100644 --- a/src/components/ftbot/BotControls.vue +++ b/src/components/ftbot/BotControls.vue @@ -1,58 +1,56 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/ftbot/DailyStats.vue b/src/components/ftbot/DailyStats.vue index f2b2aa74..51f16a45 100644 --- a/src/components/ftbot/DailyStats.vue +++ b/src/components/ftbot/DailyStats.vue @@ -15,9 +15,10 @@ diff --git a/src/components/ftbot/TradeList.vue b/src/components/ftbot/TradeList.vue index 09a6e5a6..859c919e 100644 --- a/src/components/ftbot/TradeList.vue +++ b/src/components/ftbot/TradeList.vue @@ -11,7 +11,7 @@ :empty-text="emptyText" :per-page="perPage" :current-page="currentPage" - primary-key="trade_id" + primary-key="botTradeId" selectable select-mode="single" :filter="filterText" @@ -33,7 +33,6 @@ - {{ `${row.item.pair}${ @@ -43,10 +42,7 @@ - {{ formatPercent(row.item.profit_ratio, 2) }} - - {{ `(${formatPriceWithDecimals(row.item.profit_abs)})` }} - + @@ -87,11 +83,12 @@ import ForceSellIcon from 'vue-material-design-icons/CloseBoxMultiple.vue'; import DateTimeTZ from '@/components/general/DateTimeTZ.vue'; import { BotStoreGetters } from '@/store/modules/ftbot'; import ProfitSymbol from './ProfitSymbol.vue'; +import TradeProfit from './TradeProfit.vue'; const ftbot = namespace('ftbot'); @Component({ - components: { ProfitSymbol, DeleteIcon, ForceSellIcon, DateTimeTZ }, + components: { ProfitSymbol, DeleteIcon, ForceSellIcon, DateTimeTZ, TradeProfit }, }) export default class TradeList extends Vue { $refs!: { @@ -112,6 +109,8 @@ export default class TradeList extends Vue { @Prop({ default: false }) showFilter!: boolean; + @Prop({ default: false, type: Boolean }) multiBotView!: boolean; + @Prop({ default: 'No Trades to show.' }) emptyText!: string; @ftbot.Getter [BotStoreGetters.detailTradeId]?: number; @@ -157,6 +156,7 @@ export default class TradeList extends Vue { ]; tableFields: Record[] = [ + this.multiBotView ? { key: 'botName', label: 'Bot' } : {}, { key: 'trade_id', label: 'ID' }, { key: 'pair', label: 'Pair' }, { key: 'amount', label: 'Amount' }, diff --git a/src/components/ftbot/TradeProfit.vue b/src/components/ftbot/TradeProfit.vue new file mode 100644 index 00000000..c0e3e43f --- /dev/null +++ b/src/components/ftbot/TradeProfit.vue @@ -0,0 +1,34 @@ + + + + + + + diff --git a/src/components/general/ProfitPill.vue b/src/components/general/ProfitPill.vue new file mode 100644 index 00000000..83cfa91f --- /dev/null +++ b/src/components/general/ProfitPill.vue @@ -0,0 +1,52 @@ + + + {{ profitRatio ? formatPercent(profitRatio, 2) : '' }} + + {{ profitRatio ? '(' : '' }}{{ `${formatPrice(profitAbs, 3)}` + }}{{ profitRatio ? ')' : ` ${stakeCurrency}` }} + + + + + + + diff --git a/src/components/layout/NavBar.vue b/src/components/layout/NavBar.vue index b83e16da..446b0c02 100644 --- a/src/components/layout/NavBar.vue +++ b/src/components/layout/NavBar.vue @@ -6,49 +6,101 @@ Freqtrade UI + + - + - Trade - Dashboard - Graph - Logs - Graph + Logs + Backtest + - - + + + + + + + + + + + + - {{ botName }} + {{ botName || 'No bot selected' }} {{ isBotOnline ? 'Online' : 'Offline' }} - - - V: {{ getUiVersion }} + + + FT + V: {{ getUiVersion }} Settings Lock layout Reset Layout - Sign Out + + + + V: {{ getUiVersion }} + + + {{ botName || 'No bot selected' }} + + + {{ isBotOnline ? 'Online' : 'Offline' }} + + + + Settings + + Lock layout + + + Reset Layout + Sign Out + @@ -63,27 +115,29 @@ diff --git a/src/views/LoginModal.vue b/src/views/LoginModal.vue index 7dc5e717..3361efca 100644 --- a/src/views/LoginModal.vue +++ b/src/views/LoginModal.vue @@ -1,14 +1,14 @@ - Login - - + {{ loginText }} + + diff --git a/src/views/Trading.vue b/src/views/Trading.vue index 72b15097..a9d483b5 100644 --- a/src/views/Trading.vue +++ b/src/views/Trading.vue @@ -9,19 +9,6 @@ :is-draggable="!getLayoutLocked" @layout-updated="layoutUpdatedEvent" > - - - - - - - + - + + + + @@ -106,18 +96,6 @@ - - - - -