frequi_origin/src/components/ftbot/BacktestResultView.vue

337 lines
11 KiB
Vue
Raw Normal View History

2020-07-26 17:35:56 +00:00
<template>
2021-07-04 17:57:19 +00:00
<div class="container-fluid px-0 backtestresult-container">
2021-06-25 18:00:40 +00:00
<div class="row d-flex justify-content-center">
2021-03-10 15:09:55 +00:00
<h3>Backtest-result for {{ backtestResult.strategy_name }}</h3>
2020-07-26 17:35:56 +00:00
</div>
2021-03-11 18:17:09 +00:00
2021-07-04 17:57:19 +00:00
<div class="row text-left ml-0">
<div class="row w-100">
<div class="col-12 col-xl-6 px-0 px-xl-0 pr-xl-1">
<b-card header="Strategy settings">
<b-table
small
borderless
:items="backtestResultSettings"
:fields="backtestsettingFields"
>
</b-table>
</b-card>
</div>
<div class="col-12 col-xl-6 px-0 px-xl-0 pt-2 pt-xl-0 pl-xl-1">
<b-card header="Metrics">
<b-table small borderless :items="backtestResultStats" :fields="backtestResultFields">
</b-table>
</b-card>
</div>
2021-01-19 21:50:51 +00:00
</div>
<b-card header="Results per Exit-reason" class="row mt-2 w-100">
2021-07-17 15:31:01 +00:00
<b-table
small
hover
stacked="sm"
:items="backtestResult.exit_reason_summary || backtestResult.sell_reason_summary"
2022-04-06 18:38:38 +00:00
:fields="perExitReason"
2021-07-17 15:31:01 +00:00
>
2020-07-26 17:36:47 +00:00
</b-table>
</b-card>
2021-07-04 17:57:19 +00:00
<b-card header="Results per pair" class="row mt-2 w-100">
2021-07-17 15:31:01 +00:00
<b-table
small
hover
stacked="sm"
:items="backtestResult.results_per_pair"
:fields="perPairFields"
>
2021-01-06 19:25:38 +00:00
</b-table>
</b-card>
2020-07-26 17:36:47 +00:00
2021-07-04 17:57:19 +00:00
<b-card header="Single trades" class="row mt-2 w-100">
<TradeList
class="row trade-history mt-2 w-100"
:trades="backtestResult.trades"
2021-08-09 17:56:11 +00:00
:show-filter="true"
:stake-currency="backtestResult.stake_currency"
2021-07-04 17:57:19 +00:00
/>
</b-card>
2020-07-26 17:35:56 +00:00
</div>
</div>
</template>
<script lang="ts">
import TradeList from '@/components/ftbot/TradeList.vue';
import { Component, Vue, Prop } from 'vue-property-decorator';
2021-01-21 06:47:51 +00:00
import { StrategyBacktestResult, Trade } from '@/types';
2020-07-26 17:35:56 +00:00
2021-03-10 15:34:09 +00:00
import ValuePair from '@/components/general/ValuePair.vue';
2020-09-12 17:21:35 +00:00
import {
timestampms,
formatPercent,
formatPrice,
humanizeDurationFromSeconds,
} from '@/shared/formatters';
2020-07-26 17:35:56 +00:00
@Component({
2021-03-10 15:34:09 +00:00
components: {
TradeList,
ValuePair,
},
2020-07-26 17:35:56 +00:00
})
export default class BacktestResultView extends Vue {
@Prop({ required: true }) readonly backtestResult!: StrategyBacktestResult;
get hasBacktestResult() {
return !!this.backtestResult;
}
2021-01-21 06:47:51 +00:00
getSortedTrades(backtestResult: StrategyBacktestResult): Trade[] {
const sortedTrades = backtestResult.trades
.slice()
.sort((a, b) => a.profit_ratio - b.profit_ratio);
return sortedTrades;
}
2021-02-28 08:53:51 +00:00
formatPriceStake(price) {
return `${formatPrice(price, this.backtestResult.stake_currency_decimals)} ${
this.backtestResult.stake_currency
}`;
}
2021-01-21 06:47:51 +00:00
get bestPair(): string {
const trades = this.getSortedTrades(this.backtestResult);
const value = trades[trades.length - 1];
return `${value.pair} ${formatPercent(value.profit_ratio, 2)}`;
}
get worstPair(): string {
const trades = this.getSortedTrades(this.backtestResult);
const value = trades[0];
return `${value.pair} ${formatPercent(value.profit_ratio, 2)}`;
}
2020-07-26 17:35:56 +00:00
get backtestResultStats() {
// Transpose Result into readable format
return [
2020-09-12 17:21:35 +00:00
{
metric: 'Total Profit',
2021-02-28 08:53:51 +00:00
value: `${formatPercent(this.backtestResult.profit_total)} | ${this.formatPriceStake(
2020-09-12 17:21:35 +00:00
this.backtestResult.profit_total_abs,
2021-02-28 08:53:51 +00:00
)}`,
2020-09-12 17:21:35 +00:00
},
2021-07-06 04:24:32 +00:00
{
metric: 'Total trades / Daily Avg Trades',
value: `${this.backtestResult.total_trades} / ${this.backtestResult.trades_per_day}`,
},
// { metric: 'First trade', value: this.backtestResult.backtest_fi },
// { metric: 'First trade Pair', value: this.backtestResult.backtest_best_day },
2021-03-08 18:39:15 +00:00
{
metric: 'Best day',
value: `${formatPercent(
this.backtestResult.backtest_best_day,
2,
)} | ${this.formatPriceStake(this.backtestResult.backtest_best_day_abs)}`,
},
{
metric: 'Worst day',
value: `${formatPercent(
this.backtestResult.backtest_worst_day,
2,
)} | ${this.formatPriceStake(this.backtestResult.backtest_worst_day_abs)}`,
},
2021-01-21 06:47:51 +00:00
2021-01-19 21:50:51 +00:00
{
metric: 'Win/Draw/Loss',
value: `${
this.backtestResult.results_per_pair[this.backtestResult.results_per_pair.length - 1].wins
} / ${
this.backtestResult.results_per_pair[this.backtestResult.results_per_pair.length - 1]
.draws
} / ${
this.backtestResult.results_per_pair[this.backtestResult.results_per_pair.length - 1]
.losses
}`,
},
2020-09-12 17:21:35 +00:00
{
metric: 'Days win/draw/loss',
value: `${this.backtestResult.winning_days} / ${this.backtestResult.draw_days} / ${this.backtestResult.losing_days}`,
},
{
metric: 'Avg. Duration winners',
value: humanizeDurationFromSeconds(this.backtestResult.winner_holding_avg),
},
{
metric: 'Avg. Duration Losers',
value: humanizeDurationFromSeconds(this.backtestResult.loser_holding_avg),
},
2021-05-23 14:25:31 +00:00
{ metric: 'Rejected buy signals', value: this.backtestResult.rejected_signals },
2021-03-11 18:17:09 +00:00
{ metric: '___', value: '___' },
2020-09-12 17:21:35 +00:00
{ metric: 'Max Drawdown', value: formatPercent(this.backtestResult.max_drawdown) },
2021-02-28 08:53:51 +00:00
{
metric: 'Max Drawdown ABS',
value: this.formatPriceStake(this.backtestResult.max_drawdown_abs),
},
2021-03-11 18:17:09 +00:00
{ metric: 'Drawdown start', value: timestampms(this.backtestResult.drawdown_start_ts) },
{ metric: 'Drawdown end', value: timestampms(this.backtestResult.drawdown_end_ts) },
{ metric: '___', value: '___' },
2021-02-28 08:53:51 +00:00
{ metric: 'Min balance', value: this.formatPriceStake(this.backtestResult.csum_min) },
{ metric: 'Max balance', value: this.formatPriceStake(this.backtestResult.csum_max) },
2020-09-12 17:21:35 +00:00
{ metric: 'Market change', value: formatPercent(this.backtestResult.market_change) },
2021-03-11 18:17:09 +00:00
{ metric: '___', value: '___' },
2021-01-16 10:05:44 +00:00
{
metric: 'Best Pair',
value: `${this.backtestResult.best_pair.key} ${formatPercent(
this.backtestResult.best_pair.profit_sum,
)}`,
},
{
metric: 'Worst Pair',
value: `${this.backtestResult.worst_pair.key} ${formatPercent(
this.backtestResult.worst_pair.profit_sum,
)}`,
},
2021-01-21 06:47:51 +00:00
{ metric: 'Best single Trade', value: this.bestPair },
{ metric: 'Worst single Trade', value: this.worstPair },
2020-07-26 17:35:56 +00:00
];
}
2021-03-11 18:17:09 +00:00
timestampms = timestampms;
formatPercent = formatPercent;
2021-03-10 15:34:09 +00:00
2021-01-19 21:50:51 +00:00
get backtestResultSettings() {
// Transpose Result into readable format
return [
{ setting: 'Backtesting from', value: timestampms(this.backtestResult.backtest_start_ts) },
{ setting: 'Backtesting to', value: timestampms(this.backtestResult.backtest_end_ts) },
2021-03-22 06:46:21 +00:00
{
setting: 'BT execution time',
value: humanizeDurationFromSeconds(
this.backtestResult.backtest_run_end_ts - this.backtestResult.backtest_run_start_ts,
),
},
2021-01-19 21:50:51 +00:00
{ setting: 'Max open trades', value: this.backtestResult.max_open_trades },
{ setting: 'Timeframe', value: this.backtestResult.timeframe },
{ setting: 'Timerange', value: this.backtestResult.timerange },
{ setting: 'Stoploss', value: formatPercent(this.backtestResult.stoploss, 2) },
{ setting: 'Trailing Stoploss', value: this.backtestResult.trailing_stop },
{
setting: 'Trail only when offset is reached',
value: this.backtestResult.trailing_only_offset_is_reached,
},
{ setting: 'Trailing Stop positive', value: this.backtestResult.trailing_stop_positive },
{
setting: 'Trailing stop positive offset',
value: this.backtestResult.trailing_stop_positive_offset,
},
{ setting: 'Custom Stoploss', value: this.backtestResult.use_custom_stoploss },
{ setting: 'ROI', value: this.backtestResult.minimal_roi },
2022-04-06 18:38:38 +00:00
{
setting: 'Use Exit Signal',
value:
this.backtestResult.use_exit_signal !== undefined
? this.backtestResult.use_exit_signal
: this.backtestResult.use_sell_signal,
2022-04-06 18:38:38 +00:00
},
{
setting: 'Exit profit only',
value:
this.backtestResult.exit_profit_only !== undefined
? this.backtestResult.exit_profit_only
: this.backtestResult.sell_profit_only,
2022-04-06 18:38:38 +00:00
},
{
setting: 'Exit profit offset',
value:
this.backtestResult.exit_profit_offset !== undefined
? this.backtestResult.exit_profit_offset
: this.backtestResult.sell_profit_offset,
2022-04-06 18:38:38 +00:00
},
2021-01-19 21:50:51 +00:00
{ setting: 'Enable protections', value: this.backtestResult.enable_protections },
2021-02-28 08:53:51 +00:00
{
setting: 'Starting balance',
value: this.formatPriceStake(this.backtestResult.starting_balance),
},
{
setting: 'Final balance',
value: this.formatPriceStake(this.backtestResult.final_balance),
},
{
setting: 'Avg. stake amount',
value: this.formatPriceStake(this.backtestResult.avg_stake_amount),
},
{
setting: 'Total trade volume',
value: this.formatPriceStake(this.backtestResult.total_volume),
},
2021-01-19 21:50:51 +00:00
];
}
2020-07-26 17:36:47 +00:00
get perPairFields() {
return [
{ key: 'key', label: 'Pair' },
{ key: 'trades', label: 'Buys' },
{ key: 'profit_mean', label: 'Avg Profit %', formatter: (value) => formatPercent(value, 2) },
{ key: 'profit_sum', label: 'Cum Profit %', formatter: (value) => formatPercent(value, 2) },
2020-09-12 17:21:35 +00:00
{
key: 'profit_total_abs',
label: `Tot Profit ${this.backtestResult.stake_currency}`,
2021-07-17 15:31:01 +00:00
formatter: (value) => formatPrice(value, this.backtestResult.stake_currency_decimals),
2020-09-12 17:21:35 +00:00
},
2020-07-26 17:36:47 +00:00
{
2020-12-05 15:22:41 +00:00
key: 'profit_total',
2020-07-26 17:36:47 +00:00
label: 'Tot Profit %',
formatter: (value) => formatPercent(value, 2),
},
{ key: 'duration_avg', label: 'Avg Duration' },
{ key: 'wins', label: 'Wins' },
{ key: 'draws', label: 'Draws' },
{ key: 'losses', label: 'Losses' },
];
}
2022-04-06 18:38:38 +00:00
get perExitReason() {
2020-07-26 17:36:47 +00:00
return [
{ key: 'exit_reason', label: 'Exit Reason' },
2020-07-26 17:36:47 +00:00
{ key: 'trades', label: 'Buys' },
{ key: 'profit_mean', label: 'Avg Profit %', formatter: (value) => formatPercent(value, 2) },
{ key: 'profit_sum', label: 'Cum Profit %', formatter: (value) => formatPercent(value, 2) },
2021-07-17 15:31:01 +00:00
{
key: 'profit_total_abs',
label: `Tot Profit ${this.backtestResult.stake_currency}`,
formatter: (value) => formatPrice(value, this.backtestResult.stake_currency_decimals),
},
2020-07-26 17:36:47 +00:00
{
2020-09-16 18:28:26 +00:00
key: 'profit_total',
2020-07-26 17:36:47 +00:00
label: 'Tot Profit %',
formatter: (value) => formatPercent(value, 2),
},
{ key: 'wins', label: 'Wins' },
{ key: 'draws', label: 'Draws' },
{ key: 'losses', label: 'Losses' },
];
}
2020-07-26 17:35:56 +00:00
backtestResultFields: Array<Record<string, string>> = [
{ key: 'metric', label: 'Metric' },
{ key: 'value', label: 'Value' },
];
2021-01-19 21:50:51 +00:00
backtestsettingFields: Array<Record<string, string>> = [
{ key: 'setting', label: 'Setting' },
{ key: 'value', label: 'Value' },
];
2020-07-26 17:35:56 +00:00
}
</script>
2021-07-04 17:57:19 +00:00
<style lang="scss" scoped>
.backtestresult-container {
@media (min-width: 1200px) {
max-width: 1200px;
}
}
</style>