feat: add initial download-data api endpoints

This commit is contained in:
Matthias
2024-10-24 06:05:40 +02:00
parent f23da7ea75
commit 83122fa58b
3 changed files with 107 additions and 1 deletions
@@ -0,0 +1,99 @@
import logging
from copy import deepcopy
from fastapi import APIRouter, BackgroundTasks, Depends
from fastapi.exceptions import HTTPException
from freqtrade.configuration.timerange import TimeRange
from freqtrade.constants import Config
from freqtrade.exceptions import OperationalException
from freqtrade.persistence import FtNoDBContext
from freqtrade.rpc.api_server.api_pairlists import handleExchangePayload
from freqtrade.rpc.api_server.api_schemas import BgJobStarted, DownloadDataPayload
from freqtrade.rpc.api_server.deps import get_config, get_exchange
from freqtrade.rpc.api_server.webserver_bgwork import ApiBG
logger = logging.getLogger(__name__)
# Private API, protected by authentication and webserver_mode dependency
router = APIRouter(tags=["download-data", "webserver"])
def __run_download(job_id: str, config_loc: Config):
try:
ApiBG.jobs[job_id]["is_running"] = True
from freqtrade.data.history.history_utils import (
refresh_backtest_ohlcv_data,
)
from freqtrade.plugins.pairlist.pairlist_helpers import dynamic_expand_pairlist
with FtNoDBContext():
exchange = get_exchange(config_loc)
available_pairs = [
p
for p in exchange.get_markets(
tradable_only=True, active_only=not config_loc.get("include_inactive")
).keys()
]
expanded_pairs = dynamic_expand_pairlist(config_loc, available_pairs)
print(expanded_pairs)
timerange = TimeRange()
timerange = TimeRange.parse_timerange(config_loc.get("timerange"))
pairs_not_available = refresh_backtest_ohlcv_data(
exchange,
pairs=expanded_pairs,
timeframes=config_loc["timeframes"],
datadir=config_loc["datadir"],
timerange=timerange,
new_pairs_days=config_loc["new_pairs_days"],
erase=bool(config_loc.get("erase")),
data_format=config_loc["dataformat_ohlcv"],
trading_mode=config_loc.get("trading_mode", "spot"),
prepend=config_loc.get("prepend_data", False),
)
ApiBG.jobs[job_id]["result"] = {
"pairs_not_available": pairs_not_available,
}
ApiBG.jobs[job_id]["status"] = "success"
except (OperationalException, Exception) as e:
logger.exception(e)
ApiBG.jobs[job_id]["error"] = str(e)
ApiBG.jobs[job_id]["status"] = "failed"
finally:
ApiBG.jobs[job_id]["is_running"] = False
ApiBG.download_data_running = False
@router.post("/download_data", response_model=BgJobStarted)
def pairlists_evaluate(
payload: DownloadDataPayload, background_tasks: BackgroundTasks, config=Depends(get_config)
):
if ApiBG.download_data_running:
raise HTTPException(status_code=400, detail="Pairlist evaluation is already running.")
config_loc = deepcopy(config)
config_loc["stake_currency"] = payload.stake_currency
config_loc["pairs"] = payload.pairs
config_loc["timeframes"] = payload.timeframes
handleExchangePayload(payload, config_loc)
print(payload)
job_id = ApiBG.get_job_id()
ApiBG.jobs[job_id] = {
"category": "download_data",
"status": "pending",
"progress": None,
"is_running": False,
"result": {},
"error": None,
}
background_tasks.add_task(__run_download, job_id, config_loc)
ApiBG.download_data_running = True
return {
"status": "Data Download started in background.",
"job_id": job_id,
}
+6
View File
@@ -116,6 +116,7 @@ class ApiServer(RPCHandler):
from freqtrade.rpc.api_server.api_auth import http_basic_or_jwt_token, router_login from freqtrade.rpc.api_server.api_auth import http_basic_or_jwt_token, router_login
from freqtrade.rpc.api_server.api_background_tasks import router as api_bg_tasks from freqtrade.rpc.api_server.api_background_tasks import router as api_bg_tasks
from freqtrade.rpc.api_server.api_backtest import router as api_backtest from freqtrade.rpc.api_server.api_backtest import router as api_backtest
from freqtrade.rpc.api_server.api_download_data import router as api_download_data
from freqtrade.rpc.api_server.api_pairlists import router as api_pairlists from freqtrade.rpc.api_server.api_pairlists import router as api_pairlists
from freqtrade.rpc.api_server.api_v1 import router as api_v1 from freqtrade.rpc.api_server.api_v1 import router as api_v1
from freqtrade.rpc.api_server.api_v1 import router_public as api_v1_public from freqtrade.rpc.api_server.api_v1 import router_public as api_v1_public
@@ -146,6 +147,11 @@ class ApiServer(RPCHandler):
prefix="/api/v1", prefix="/api/v1",
dependencies=[Depends(http_basic_or_jwt_token), Depends(is_webserver_mode)], dependencies=[Depends(http_basic_or_jwt_token), Depends(is_webserver_mode)],
) )
app.include_router(
api_download_data,
prefix="/api/v1",
dependencies=[Depends(http_basic_or_jwt_token), Depends(is_webserver_mode)],
)
app.include_router(ws_router, prefix="/api/v1") app.include_router(ws_router, prefix="/api/v1")
# UI Router MUST be last! # UI Router MUST be last!
app.include_router(router_ui, prefix="") app.include_router(router_ui, prefix="")
+2 -1
View File
@@ -5,7 +5,7 @@ from freqtrade.exchange.exchange import Exchange
class JobsContainer(TypedDict): class JobsContainer(TypedDict):
category: Literal["pairlist"] category: Literal["pairlist", "download_data"]
is_running: bool is_running: bool
status: str status: str
progress: float | None progress: float | None
@@ -32,6 +32,7 @@ class ApiBG:
jobs: dict[str, JobsContainer] = {} jobs: dict[str, JobsContainer] = {}
# Pairlist evaluate things # Pairlist evaluate things
pairlist_running: bool = False pairlist_running: bool = False
download_data_running: bool = False
@staticmethod @staticmethod
def get_job_id() -> str: def get_job_id() -> str: