Add Post endpoint for to filter dataframe by columns

This commit is contained in:
Matthias
2024-04-28 10:30:27 +02:00
parent cabdfabf03
commit 54d467d2bf
3 changed files with 46 additions and 17 deletions

View File

@@ -489,12 +489,20 @@ class AvailablePairs(BaseModel):
pair_interval: List[List[str]]
class PairHistoryRequest(BaseModel):
pair: str
timeframe: str
limit: Optional[int] = None
columns: Optional[List[str]] = None
class PairHistory(BaseModel):
strategy: str
pair: str
timeframe: str
timeframe_ms: int
columns: List[str]
selected_columns: List[str] = []
data: SerializeAsAny[List[Any]]
length: int
buy_signals: int

View File

@@ -17,10 +17,11 @@ from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, Blac
ForceEnterResponse, ForceExitPayload,
FreqAIModelListResponse, Health, Locks,
LocksPayload, Logs, MixTag, OpenTradeSchema,
PairHistory, PerformanceEntry, Ping, PlotConfig,
Profit, ResultMsg, ShowConfig, Stats, StatusMsg,
StrategyListResponse, StrategyResponse, SysInfo,
Version, WhitelistResponse)
PairHistory, PairHistoryRequest, PerformanceEntry,
Ping, PlotConfig, Profit, ResultMsg, ShowConfig,
Stats, StatusMsg, StrategyListResponse,
StrategyResponse, SysInfo, Version,
WhitelistResponse)
from freqtrade.rpc.api_server.deps import get_config, get_exchange, get_rpc, get_rpc_optional
from freqtrade.rpc.rpc import RPCException
@@ -53,7 +54,8 @@ logger = logging.getLogger(__name__)
# 2.32: new /backtest/history/ patch endpoint
# 2.33: Additional weekly/monthly metrics
# 2.34: new entries/exits/mix_tags endpoints
API_VERSION = 2.34
# 2.35: pair_candles and pair_history endpoints as Post variant
API_VERSION = 2.35
# Public API, requires no auth.
router_public = APIRouter()
@@ -291,7 +293,14 @@ def reload_config(rpc: RPC = Depends(get_rpc)):
@router.get('/pair_candles', response_model=PairHistory, tags=['candle data'])
def pair_candles(
pair: str, timeframe: str, limit: Optional[int] = None, rpc: RPC = Depends(get_rpc)):
return rpc._rpc_analysed_dataframe(pair, timeframe, limit)
return rpc._rpc_analysed_dataframe(pair, timeframe, limit, None)
@router.post('/pair_candles', response_model=PairHistory, tags=['candle data'])
def pair_candles_filtered(payload: PairHistoryRequest, rpc: RPC = Depends(get_rpc)):
# Advanced pair_candles endpoint with column filtering
return rpc._rpc_analysed_dataframe(
payload.pair, payload.timeframe, payload.limit, payload.columns)
@router.get('/pair_history', response_model=PairHistory, tags=['candle data'])
@@ -307,7 +316,7 @@ def pair_history(pair: str, timeframe: str, timerange: str, strategy: str,
'freqaimodel': freqaimodel if freqaimodel else config.get('freqaimodel'),
})
try:
return RPC._rpc_analysed_history_full(config, pair, timeframe, exchange)
return RPC._rpc_analysed_history_full(config, pair, timeframe, exchange, None)
except Exception as e:
raise HTTPException(status_code=502, detail=str(e))

View File

@@ -16,7 +16,7 @@ from sqlalchemy import func, select
from freqtrade import __version__
from freqtrade.configuration.timerange import TimeRange
from freqtrade.constants import CANCEL_REASON, Config
from freqtrade.constants import CANCEL_REASON, DEFAULT_DATAFRAME_COLUMNS, Config
from freqtrade.data.history import load_data
from freqtrade.data.metrics import calculate_expectancy, calculate_max_drawdown
from freqtrade.enums import (CandleType, ExitCheckTuple, ExitType, MarketDirection, SignalDirection,
@@ -1190,9 +1190,11 @@ class RPC:
return self._freqtrade.edge.accepted_pairs()
@staticmethod
def _convert_dataframe_to_dict(strategy: str, pair: str, timeframe: str, dataframe: DataFrame,
last_analyzed: datetime) -> Dict[str, Any]:
def _convert_dataframe_to_dict(
strategy: str, pair: str, timeframe: str, dataframe: DataFrame,
last_analyzed: datetime, selected_cols: Optional[List[str]]) -> Dict[str, Any]:
has_content = len(dataframe) != 0
dataframe_columns = list(dataframe.columns)
signals = {
'enter_long': 0,
'exit_long': 0,
@@ -1200,6 +1202,11 @@ class RPC:
'exit_short': 0,
}
if has_content:
if selected_cols:
# Ensure OHLCV columns are always present
cols_set = set(DEFAULT_DATAFRAME_COLUMNS + selected_cols)
df_cols = [col for col in dataframe_columns if col in cols_set]
dataframe = dataframe.loc[:, df_cols]
dataframe.loc[:, '__date_ts'] = dataframe.loc[:, 'date'].astype(int64) // 1000 // 1000
# Move signal close to separate column when signal for easy plotting
@@ -1224,7 +1231,8 @@ class RPC:
'timeframe': timeframe,
'timeframe_ms': timeframe_to_msecs(timeframe),
'strategy': strategy,
'columns': list(dataframe.columns),
'columns': dataframe_columns,
'selected_columns': list(dataframe.columns),
'data': dataframe.values.tolist(),
'length': len(dataframe),
'buy_signals': signals['enter_long'], # Deprecated
@@ -1249,13 +1257,16 @@ class RPC:
})
return res
def _rpc_analysed_dataframe(self, pair: str, timeframe: str,
limit: Optional[int]) -> Dict[str, Any]:
def _rpc_analysed_dataframe(
self, pair: str, timeframe: str, limit: Optional[int],
selected_cols: Optional[List[str]]) -> Dict[str, Any]:
""" Analyzed dataframe in Dict form """
_data, last_analyzed = self.__rpc_analysed_dataframe_raw(pair, timeframe, limit)
return RPC._convert_dataframe_to_dict(self._freqtrade.config['strategy'],
pair, timeframe, _data, last_analyzed)
return RPC._convert_dataframe_to_dict(
self._freqtrade.config['strategy'], pair, timeframe, _data, last_analyzed,
selected_cols
)
def __rpc_analysed_dataframe_raw(
self,
@@ -1322,7 +1333,7 @@ class RPC:
@staticmethod
def _rpc_analysed_history_full(config: Config, pair: str, timeframe: str,
exchange) -> Dict[str, Any]:
exchange, selected_cols: Optional[List[str]]) -> Dict[str, Any]:
timerange_parsed = TimeRange.parse_timerange(config.get('timerange'))
from freqtrade.data.converter import trim_dataframe
@@ -1352,7 +1363,8 @@ class RPC:
df_analyzed = trim_dataframe(df_analyzed, timerange_parsed, startup_candles=startup_candles)
return RPC._convert_dataframe_to_dict(strategy.get_strategy_name(), pair, timeframe,
df_analyzed.copy(), dt_now())
df_analyzed.copy(), dt_now(),
selected_cols)
def _rpc_plot_config(self) -> Dict[str, Any]:
if (self._freqtrade.strategy.plot_config and