Add pair_history endpoint

This commit is contained in:
Matthias 2020-07-02 07:10:56 +02:00
parent 677078350f
commit f5dc10e4ae
3 changed files with 65 additions and 14 deletions

View File

@ -212,6 +212,8 @@ class ApiServer(RPC):
view_func=self._trades, methods=['GET'])
self.app.add_url_rule(f'{BASE_URI}/trades/<int:tradeid>', 'trades_delete',
view_func=self._trades_delete, methods=['DELETE'])
self.app.add_url_rule(f'{BASE_URI}/pair_candles', 'pair_candles',
view_func=self._analysed_candles, methods=['GET'])
self.app.add_url_rule(f'{BASE_URI}/pair_history', 'pair_history',
view_func=self._analysed_history, methods=['GET'])
self.app.add_url_rule(f'{BASE_URI}/plot_config', 'plot_config',
@ -507,9 +509,10 @@ class ApiServer(RPC):
@require_login
@rpc_catch_errors
def _analysed_history(self):
def _analysed_candles(self):
"""
Handler for /pair_history.
Returns the dataframe the bot is using during live/dry operations.
Takes the following get arguments:
get:
parameters:
@ -521,9 +524,31 @@ class ApiServer(RPC):
timeframe = request.args.get("timeframe")
limit = request.args.get("limit", type=int)
results = self._rpc_analysed_history(pair, timeframe, limit)
results = self._analysed_dataframe(pair, timeframe, limit)
return self.rest_dump(results)
@require_login
@rpc_catch_errors
def _analysed_history(self):
"""
Handler for /pair_history.
Returns the dataframe of a given timerange
Takes the following get arguments:
get:
parameters:
- pair: Pair
- timeframe: Timeframe to get data for (should be aligned to strategy.timeframe)
- timerange: timerange in the format YYYYMMDD-YYYYMMDD (YYYYMMDD- or (-YYYYMMDD))
are als possible. If omitted uses all available data.
"""
pair = request.args.get("pair")
timeframe = request.args.get("timeframe")
timerange = request.args.get("timerange")
results = self._rpc_analysed_history_full(pair, timeframe, timerange)
return self.rest_dump(results)
@require_login
@rpc_catch_errors
def _plot_config(self):

View File

@ -9,9 +9,11 @@ from math import isnan
from typing import Any, Dict, List, Optional, Tuple, Union
import arrow
from numpy import NAN, mean, int64
from numpy import NAN, int64, mean
from freqtrade.configuration.timerange import TimeRange
from freqtrade.constants import CANCEL_REASON
from freqtrade.data.history import load_data
from freqtrade.exceptions import ExchangeError, PricingError
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_msecs
from freqtrade.loggers import bufferHandler
@ -654,19 +656,41 @@ class RPC:
raise RPCException('Edge is not enabled.')
return self._freqtrade.edge.accepted_pairs()
def _rpc_analysed_history(self, pair, timeframe, limit) -> Dict[str, Any]:
def _convert_dataframe_to_dict(self, pair, dataframe, last_analyzed):
dataframe = dataframe.replace({NAN: None})
dataframe['date'] = dataframe['date'].astype(int64) // 1000 // 1000
return {
'pair': pair,
'columns': list(dataframe.columns),
'data': dataframe.values.tolist(),
'length': len(dataframe),
'last_analyzed': last_analyzed,
}
def _analysed_dataframe(self, pair: str, timeframe: str, limit: int) -> Dict[str, Any]:
_data, last_analyzed = self._freqtrade.dataprovider.get_analyzed_dataframe(pair, timeframe)
if limit:
_data = _data.iloc[-limit:]
_data = _data.replace({NAN: None})
_data['date'] = _data['date'].astype(int64) // 1000 // 1000
return {
'columns': list(_data.columns),
'data': _data.values.tolist(),
'length': len(_data),
'last_analyzed': last_analyzed,
}
return self._convert_dataframe_to_dict(pair, _data, last_analyzed)
def _rpc_analysed_history_full(self, pair: str, timeframe: str,
timerange: str) -> Dict[str, Any]:
timerange = TimeRange.parse_timerange(None if self.config.get(
'timerange') is None else str(self.config.get('timerange')))
_data = load_data(
datadir=self._freqtrade.config.get("datadir"),
pairs=[pair],
timeframe=self._freqtrade.config.get('timeframe', '5m'),
timerange=timerange,
data_format=self._freqtrade.config.get('dataformat_ohlcv', 'json'),
)
from freqtrade.resolvers.strategy_resolver import StrategyResolver
strategy = StrategyResolver.load_strategy(self._freqtrade.config)
df_analyzed = strategy.analyze_ticker(_data, {'pair': pair})
return self._convert_dataframe_to_dict(pair, df_analyzed, arrow.Arrow.utcnow().datetime)
def _rpc_plot_config(self) -> Dict[str, Any]:

View File

@ -813,7 +813,7 @@ def test_api_forcesell(botclient, mocker, ticker, fee, markets):
assert rc.json == {'result': 'Created sell order for trade 1.'}
def test_api_pair_history(botclient, ohlcv_history):
def test_api_pair_candles(botclient, ohlcv_history):
ftbot, client = botclient
timeframe = '5m'
amount = 2
@ -821,11 +821,13 @@ def test_api_pair_history(botclient, ohlcv_history):
ftbot.dataprovider._set_cached_df("XRP/BTC", timeframe, ohlcv_history)
rc = client_get(client,
f"{BASE_URI}/pair_history?limit={amount}&pair=XRP%2FBTC&timeframe={timeframe}")
f"{BASE_URI}/pair_candles?limit={amount}&pair=XRP%2FBTC&timeframe={timeframe}")
assert_response(rc)
assert 'columns' in rc.json
assert isinstance(rc.json['columns'], list)
assert rc.json['columns'] == ['date', 'open', 'high', 'low', 'close', 'volume', 'sma']
assert 'pair' in rc.json
assert rc.json['pair'] == 'XRP/BTC'
assert 'data' in rc.json
assert len(rc.json['data']) == amount