2020-07-26 17:35:56 +00:00
|
|
|
<template>
|
2023-08-16 09:55:32 +00:00
|
|
|
<div class="px-0 mw-100">
|
|
|
|
<div class="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
|
|
|
|
2023-08-16 09:55:32 +00:00
|
|
|
<div class="d-flex flex-column text-start ms-0 me-2 gap-2">
|
2023-08-16 09:57:12 +00:00
|
|
|
<div class="d-flex flex-column flex-xl-row">
|
|
|
|
<div class="px-0 px-xl-0 pe-xl-1 flex-fill">
|
2021-07-04 17:57:19 +00:00
|
|
|
<b-card header="Strategy settings">
|
|
|
|
<b-table
|
|
|
|
small
|
|
|
|
borderless
|
|
|
|
:items="backtestResultSettings"
|
|
|
|
:fields="backtestsettingFields"
|
|
|
|
>
|
|
|
|
</b-table>
|
|
|
|
</b-card>
|
|
|
|
</div>
|
2023-08-16 09:57:12 +00:00
|
|
|
<div class="px-0 px-xl-0 pt-2 pt-xl-0 ps-xl-1 flex-fill">
|
2021-07-04 17:57:19 +00:00
|
|
|
<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>
|
2023-08-16 09:55:32 +00:00
|
|
|
<b-card header="Results per Exit-reason">
|
2021-07-17 15:31:01 +00:00
|
|
|
<b-table
|
|
|
|
small
|
|
|
|
hover
|
|
|
|
stacked="sm"
|
2023-07-11 20:02:02 +00:00
|
|
|
:items="
|
|
|
|
(backtestResult.exit_reason_summary ||
|
|
|
|
backtestResult.sell_reason_summary) as unknown as TableItem[]
|
|
|
|
"
|
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>
|
2023-08-16 09:55:32 +00:00
|
|
|
<b-card header="Results per pair">
|
2021-07-17 15:31:01 +00:00
|
|
|
<b-table
|
|
|
|
small
|
|
|
|
hover
|
|
|
|
stacked="sm"
|
2023-04-06 05:16:57 +00:00
|
|
|
:items="backtestResult.results_per_pair as unknown as TableItem[]"
|
2021-07-17 15:31:01 +00:00
|
|
|
:fields="perPairFields"
|
|
|
|
>
|
2021-01-06 19:25:38 +00:00
|
|
|
</b-table>
|
|
|
|
</b-card>
|
2023-08-16 09:55:32 +00:00
|
|
|
<b-card v-if="backtestResult.periodic_breakdown" header="Periodic breakdown">
|
2023-07-11 20:02:02 +00:00
|
|
|
<BacktestResultPeriodBreakdown :periodic-breakdown="backtestResult.periodic_breakdown">
|
|
|
|
</BacktestResultPeriodBreakdown>
|
2023-04-24 09:19:14 +00:00
|
|
|
</b-card>
|
2020-07-26 17:36:47 +00:00
|
|
|
|
2023-08-16 09:55:32 +00:00
|
|
|
<b-card header="Single trades">
|
2021-07-04 17:57:19 +00:00
|
|
|
<TradeList
|
|
|
|
:trades="backtestResult.trades"
|
2021-08-09 17:56:11 +00:00
|
|
|
:show-filter="true"
|
2021-07-17 15:14:20 +00:00
|
|
|
: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>
|
|
|
|
|
2022-12-10 13:17:13 +00:00
|
|
|
<script setup lang="ts">
|
2020-07-26 17:35:56 +00:00
|
|
|
import TradeList from '@/components/ftbot/TradeList.vue';
|
2021-01-21 06:47:51 +00:00
|
|
|
import { StrategyBacktestResult, Trade } from '@/types';
|
2023-04-24 09:25:30 +00:00
|
|
|
import BacktestResultPeriodBreakdown from './BacktestResultPeriodBreakdown.vue';
|
2023-10-24 17:21:56 +00:00
|
|
|
import { formatObjectForTable } from '@/shared/objectToTableItems';
|
2020-07-26 17:35:56 +00:00
|
|
|
|
2023-04-24 09:25:30 +00:00
|
|
|
import { computed } from 'vue';
|
2020-09-12 17:21:35 +00:00
|
|
|
import {
|
|
|
|
timestampms,
|
|
|
|
formatPercent,
|
|
|
|
formatPrice,
|
|
|
|
humanizeDurationFromSeconds,
|
|
|
|
} from '@/shared/formatters';
|
2023-10-24 17:45:37 +00:00
|
|
|
import { generateBacktestMetricRows } from '@/shared/backtestMetrics';
|
2023-04-06 05:16:57 +00:00
|
|
|
import { TableField, TableItem } from 'bootstrap-vue-next';
|
2020-07-26 17:35:56 +00:00
|
|
|
|
2022-12-10 13:17:13 +00:00
|
|
|
const props = defineProps({
|
|
|
|
backtestResult: { required: true, type: Object as () => StrategyBacktestResult },
|
|
|
|
});
|
2021-01-21 06:47:51 +00:00
|
|
|
|
2022-12-10 13:17:13 +00:00
|
|
|
const formatPriceStake = (price) => {
|
|
|
|
return `${formatPrice(price, props.backtestResult.stake_currency_decimals)} ${
|
|
|
|
props.backtestResult.stake_currency
|
|
|
|
}`;
|
|
|
|
};
|
2023-07-20 18:47:30 +00:00
|
|
|
|
2022-12-10 13:17:13 +00:00
|
|
|
const backtestResultStats = computed(() => {
|
2023-10-24 17:45:37 +00:00
|
|
|
const tmp = generateBacktestMetricRows(props.backtestResult);
|
2023-10-24 17:32:40 +00:00
|
|
|
return formatObjectForTable({ value: tmp }, 'metric');
|
2022-12-10 13:17:13 +00:00
|
|
|
});
|
2021-01-19 21:50:51 +00:00
|
|
|
|
2022-12-10 13:17:13 +00:00
|
|
|
const backtestResultSettings = computed(() => {
|
|
|
|
// Transpose Result into readable format
|
2023-10-24 17:21:56 +00:00
|
|
|
const tmp = [
|
|
|
|
{ 'Backtesting from': timestampms(props.backtestResult.backtest_start_ts) },
|
|
|
|
{ 'Backtesting to': timestampms(props.backtestResult.backtest_end_ts) },
|
2022-12-10 13:17:13 +00:00
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'BT execution time': humanizeDurationFromSeconds(
|
2022-12-10 13:17:13 +00:00
|
|
|
props.backtestResult.backtest_run_end_ts - props.backtestResult.backtest_run_start_ts,
|
|
|
|
),
|
|
|
|
},
|
2023-10-24 17:21:56 +00:00
|
|
|
{ 'Max open trades': props.backtestResult.max_open_trades },
|
|
|
|
{ Timeframe: props.backtestResult.timeframe },
|
|
|
|
{ 'Timeframe Detail': props.backtestResult.timeframe_detail || 'N/A' },
|
|
|
|
{ Timerange: props.backtestResult.timerange },
|
|
|
|
{ Stoploss: formatPercent(props.backtestResult.stoploss, 2) },
|
|
|
|
{ 'Trailing Stoploss': props.backtestResult.trailing_stop },
|
2022-12-10 13:17:13 +00:00
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Trail only when offset is reached': props.backtestResult.trailing_only_offset_is_reached,
|
2022-12-10 13:17:13 +00:00
|
|
|
},
|
2023-10-24 17:21:56 +00:00
|
|
|
{ 'Trailing Stop positive': props.backtestResult.trailing_stop_positive },
|
2022-12-10 13:17:13 +00:00
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Trailing stop positive offset': props.backtestResult.trailing_stop_positive_offset,
|
2022-12-10 13:17:13 +00:00
|
|
|
},
|
2023-10-24 17:21:56 +00:00
|
|
|
{ 'Custom Stoploss': props.backtestResult.use_custom_stoploss },
|
|
|
|
{ ROI: props.backtestResult.minimal_roi },
|
2022-12-10 13:17:13 +00:00
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Use Exit Signal':
|
2022-12-10 13:17:13 +00:00
|
|
|
props.backtestResult.use_exit_signal !== undefined
|
|
|
|
? props.backtestResult.use_exit_signal
|
|
|
|
: props.backtestResult.use_sell_signal,
|
|
|
|
},
|
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Exit profit only':
|
2022-12-10 13:17:13 +00:00
|
|
|
props.backtestResult.exit_profit_only !== undefined
|
|
|
|
? props.backtestResult.exit_profit_only
|
|
|
|
: props.backtestResult.sell_profit_only,
|
|
|
|
},
|
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Exit profit offset':
|
2022-12-10 13:17:13 +00:00
|
|
|
props.backtestResult.exit_profit_offset !== undefined
|
|
|
|
? props.backtestResult.exit_profit_offset
|
|
|
|
: props.backtestResult.sell_profit_offset,
|
|
|
|
},
|
2023-10-24 17:21:56 +00:00
|
|
|
{ 'Enable protections': props.backtestResult.enable_protections },
|
2022-12-10 13:17:13 +00:00
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Starting balance': formatPriceStake(props.backtestResult.starting_balance),
|
2022-12-10 13:17:13 +00:00
|
|
|
},
|
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Final balance': formatPriceStake(props.backtestResult.final_balance),
|
2022-12-10 13:17:13 +00:00
|
|
|
},
|
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Avg. stake amount': formatPriceStake(props.backtestResult.avg_stake_amount),
|
2022-12-10 13:17:13 +00:00
|
|
|
},
|
|
|
|
{
|
2023-10-24 17:21:56 +00:00
|
|
|
'Total trade volume': formatPriceStake(props.backtestResult.total_volume),
|
2022-12-10 13:17:13 +00:00
|
|
|
},
|
|
|
|
];
|
2023-10-24 17:21:56 +00:00
|
|
|
|
|
|
|
return formatObjectForTable({ value: tmp }, 'setting');
|
2022-12-10 13:17:13 +00:00
|
|
|
});
|
|
|
|
const perPairFields = computed(() => {
|
|
|
|
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) },
|
|
|
|
{
|
|
|
|
key: 'profit_total_abs',
|
|
|
|
label: `Tot Profit ${props.backtestResult.stake_currency}`,
|
|
|
|
formatter: (value) => formatPrice(value, props.backtestResult.stake_currency_decimals),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'profit_total',
|
|
|
|
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' },
|
|
|
|
];
|
|
|
|
});
|
2020-07-26 17:36:47 +00:00
|
|
|
|
2022-12-10 13:17:13 +00:00
|
|
|
const perExitReason = computed(() => {
|
|
|
|
return [
|
|
|
|
{ key: 'exit_reason', label: 'Exit Reason' },
|
|
|
|
{ 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) },
|
|
|
|
{
|
|
|
|
key: 'profit_total_abs',
|
|
|
|
label: `Tot Profit ${props.backtestResult.stake_currency}`,
|
2021-01-19 21:50:51 +00:00
|
|
|
|
2022-12-10 13:17:13 +00:00
|
|
|
formatter: (value) => formatPrice(value, props.backtestResult.stake_currency_decimals),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
key: 'profit_total',
|
|
|
|
label: 'Tot Profit %',
|
|
|
|
formatter: (value) => formatPercent(value, 2),
|
|
|
|
},
|
|
|
|
{ key: 'wins', label: 'Wins' },
|
|
|
|
{ key: 'draws', label: 'Draws' },
|
|
|
|
{ key: 'losses', label: 'Losses' },
|
|
|
|
];
|
2022-04-21 04:37:57 +00:00
|
|
|
});
|
2023-04-05 19:08:53 +00:00
|
|
|
const backtestResultFields: TableField[] = [
|
2022-12-10 13:17:13 +00:00
|
|
|
{ key: 'metric', label: 'Metric' },
|
|
|
|
{ key: 'value', label: 'Value' },
|
|
|
|
];
|
|
|
|
|
2023-04-05 19:08:53 +00:00
|
|
|
const backtestsettingFields: TableField[] = [
|
2022-12-10 13:17:13 +00:00
|
|
|
{ key: 'setting', label: 'Setting' },
|
|
|
|
{ key: 'value', label: 'Value' },
|
|
|
|
];
|
2020-07-26 17:35:56 +00:00
|
|
|
</script>
|
|
|
|
|
2023-08-16 09:55:32 +00:00
|
|
|
<style lang="scss" scoped></style>
|