feat: add backtest/.../wallets endpoint
This commit is contained in:
@@ -312,6 +312,20 @@ def get_backtest_market_change(filename: Path, include_ts: bool = True) -> pd.Da
|
|||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
|
def get_backtest_wallet_change(filename: Path, strategy_name: str) -> pd.DataFrame:
|
||||||
|
"""
|
||||||
|
Read backtest wallet change file.
|
||||||
|
:param filename: Path to the backtest result zip file
|
||||||
|
:param strategy_name: Name of the strategy to load
|
||||||
|
:return: DataFrame with wallet change data
|
||||||
|
"""
|
||||||
|
data = load_file_from_zip(filename, f"{filename.stem}_{strategy_name}_wallet.feather")
|
||||||
|
df = pd.read_feather(BytesIO(data))
|
||||||
|
|
||||||
|
df.loc[:, "__date_ts"] = df.loc[:, "date"].astype(np.int64) // 1000 // 1000
|
||||||
|
return df
|
||||||
|
|
||||||
|
|
||||||
def find_existing_backtest_stats(
|
def find_existing_backtest_stats(
|
||||||
dirname: Path | str, run_ids: dict[str, str], min_backtest_date: datetime | None = None
|
dirname: Path | str, run_ids: dict[str, str], min_backtest_date: datetime | None = None
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from freqtrade.data.btanalysis import (
|
|||||||
get_backtest_market_change,
|
get_backtest_market_change,
|
||||||
get_backtest_result,
|
get_backtest_result,
|
||||||
get_backtest_resultlist,
|
get_backtest_resultlist,
|
||||||
|
get_backtest_wallet_change,
|
||||||
load_and_merge_backtest_result,
|
load_and_merge_backtest_result,
|
||||||
update_backtest_metadata,
|
update_backtest_metadata,
|
||||||
)
|
)
|
||||||
@@ -29,6 +30,7 @@ from freqtrade.rpc.api_server.api_schemas import (
|
|||||||
BacktestMetadataUpdate,
|
BacktestMetadataUpdate,
|
||||||
BacktestRequest,
|
BacktestRequest,
|
||||||
BacktestResponse,
|
BacktestResponse,
|
||||||
|
BacktestWalletsSummary,
|
||||||
)
|
)
|
||||||
from freqtrade.rpc.api_server.deps import get_config, verify_strategy
|
from freqtrade.rpc.api_server.deps import get_config, verify_strategy
|
||||||
from freqtrade.rpc.api_server.webserver_bgwork import ApiBG
|
from freqtrade.rpc.api_server.webserver_bgwork import ApiBG
|
||||||
@@ -354,3 +356,29 @@ def api_get_backtest_market_change(file: str, config=Depends(get_config)):
|
|||||||
"data": df.values.tolist(),
|
"data": df.values.tolist(),
|
||||||
"length": len(df),
|
"length": len(df),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
"/backtest/history/{file}/{strategy}/wallet",
|
||||||
|
response_model=BacktestWalletsSummary,
|
||||||
|
tags=["webserver", "backtest"],
|
||||||
|
)
|
||||||
|
def api_get_backtest_wallet(file: str, strategy: str, config=Depends(get_config)):
|
||||||
|
bt_results_base: Path = config["user_data_dir"] / "backtest_results"
|
||||||
|
file_abs = (bt_results_base / file).with_suffix(".zip")
|
||||||
|
# Ensure file is in backtest_results directory
|
||||||
|
if not is_file_in_dir(file_abs, bt_results_base):
|
||||||
|
raise HTTPException(status_code=404, detail="File not found.")
|
||||||
|
|
||||||
|
results = get_backtest_wallet_change(file_abs, strategy)
|
||||||
|
if results is None:
|
||||||
|
raise HTTPException(status_code=404, detail="File not found.")
|
||||||
|
# Consolidate the wallet to the base currency
|
||||||
|
results.loc[:, "total"] = results["price"] * results["balance"]
|
||||||
|
results = results.groupby(["date", "__date_ts"]).agg({"total": "sum"}).reset_index()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"columns": results.columns.tolist(),
|
||||||
|
"data": results.values.tolist(),
|
||||||
|
"length": len(results),
|
||||||
|
}
|
||||||
|
|||||||
@@ -679,6 +679,12 @@ class BacktestMarketChange(BaseModel):
|
|||||||
data: list[list[Any]]
|
data: list[list[Any]]
|
||||||
|
|
||||||
|
|
||||||
|
class BacktestWalletsSummary(BaseModel):
|
||||||
|
columns: list[str]
|
||||||
|
length: int
|
||||||
|
data: list[list[Any]]
|
||||||
|
|
||||||
|
|
||||||
class MarketRequest(ExchangeModePayloadMixin, BaseModel):
|
class MarketRequest(ExchangeModePayloadMixin, BaseModel):
|
||||||
base: str | None = None
|
base: str | None = None
|
||||||
quote: str | None = None
|
quote: str | None = None
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ logger = logging.getLogger(__name__)
|
|||||||
# 2.45: Add price to forceexit endpoint
|
# 2.45: Add price to forceexit endpoint
|
||||||
# 2.46: Add prepend_data to download-data endpoint
|
# 2.46: Add prepend_data to download-data endpoint
|
||||||
# 2.47: Add Strategy parameters
|
# 2.47: Add Strategy parameters
|
||||||
API_VERSION = 2.47
|
# 2.48: add /backtest/history/wallets endpoint
|
||||||
|
API_VERSION = 2.48
|
||||||
|
|
||||||
# Public API, requires no auth.
|
# Public API, requires no auth.
|
||||||
router_public = APIRouter()
|
router_public = APIRouter()
|
||||||
|
|||||||
Reference in New Issue
Block a user