如何从R语言backtest包的results数组中提取收益并转为DataFrame?
Nice question! I’ve messed around with the backtest package a fair bit, so let’s walk through how to pull those decile returns into a usable DataFrame step by step.
Step 1: Understand the results Array Structure
First, let’s confirm the layout of that 5-dimensional results array. If you ran your backtest like this:
bt <- backtest(your_strategy, your_data, ...)
Then bt$results is the array in question. To see exactly what each dimension represents, run:
dimnames(bt$results)
Per the package docs, the dimensions are typically (strategies, symbols, dates, statistics, portfolios). The decile returns will live in the statistics dimension, with names like "decile1.return", "decile2.return", ..., "decile10.return".
Step 2: Extract the Decile Return Subset
First, let’s isolate just the decile return entries from the array. We can use grep() to match the statistic names:
# Grab the indices for decile return statistics decile_stat_indices <- grep("decile.*return", dimnames(bt$results)[[4]]) # Extract the subset (adjust indices if you have multiple strategies/symbols/portfolios) # Here we're taking the first strategy, first symbol, first portfolio decile_subset <- bt$results[1, 1, , decile_stat_indices, 1]
Step 3: Convert to a DataFrame (Base R Approach)
Now let’s turn this 3D slice (dates x deciles) into a clean DataFrame with dates as rows and deciles as columns:
# Extract date labels and convert to Date type dates <- as.Date(dimnames(decile_subset)[[1]]) # Extract decile labels decile_names <- dimnames(decile_subset)[[2]] # Transpose the subset to get dates as rows, deciles as columns decile_data_matrix <- t(decile_subset) # Convert to DataFrame and add the date column decile_df <- as.data.frame(decile_data_matrix) decile_df$date <- dates # Reorder columns to put date first (optional but cleaner) decile_df <- decile_df[, c("date", decile_names)]
Step 4: Tidyverse Alternative (Cleaner for Complex Cases)
If you use the tidyverse ecosystem, this becomes even more straightforward, especially if you have multiple strategies/symbols/portfolios to handle:
library(tidyverse) decile_df <- as.data.table(bt$results) %>% # Filter to only decile return statistics filter(str_detect(statistic, "decile.*return")) %>% # Keep only relevant columns select(date, statistic, value) %>% # Reshape to wide format (one column per decile) pivot_wider(names_from = statistic, values_from = value) %>% # Convert date to proper Date type mutate(date = as.Date(date))
Quick Validation & Notes
- Double-check that the output matches what
summary(bt)prints by runninghead(decile_df)and comparing to the summary output. - If you have multiple strategies, symbols, or portfolios, adjust the indices in the base R approach (e.g.,
bt$results[2, , , decile_stat_indices, 1]for the second strategy) or add grouping in the tidyverse code (e.g.,group_by(strategy, symbol)before pivoting).
内容的提问来源于stack exchange,提问作者Niccola Tartaglia

