Add pair_history endpoint
This commit is contained in:
parent
677078350f
commit
f5dc10e4ae
@ -212,6 +212,8 @@ class ApiServer(RPC):
|
|||||||
view_func=self._trades, methods=['GET'])
|
view_func=self._trades, methods=['GET'])
|
||||||
self.app.add_url_rule(f'{BASE_URI}/trades/<int:tradeid>', 'trades_delete',
|
self.app.add_url_rule(f'{BASE_URI}/trades/<int:tradeid>', 'trades_delete',
|
||||||
view_func=self._trades_delete, methods=['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',
|
self.app.add_url_rule(f'{BASE_URI}/pair_history', 'pair_history',
|
||||||
view_func=self._analysed_history, methods=['GET'])
|
view_func=self._analysed_history, methods=['GET'])
|
||||||
self.app.add_url_rule(f'{BASE_URI}/plot_config', 'plot_config',
|
self.app.add_url_rule(f'{BASE_URI}/plot_config', 'plot_config',
|
||||||
@ -507,9 +509,10 @@ class ApiServer(RPC):
|
|||||||
|
|
||||||
@require_login
|
@require_login
|
||||||
@rpc_catch_errors
|
@rpc_catch_errors
|
||||||
def _analysed_history(self):
|
def _analysed_candles(self):
|
||||||
"""
|
"""
|
||||||
Handler for /pair_history.
|
Handler for /pair_history.
|
||||||
|
Returns the dataframe the bot is using during live/dry operations.
|
||||||
Takes the following get arguments:
|
Takes the following get arguments:
|
||||||
get:
|
get:
|
||||||
parameters:
|
parameters:
|
||||||
@ -521,9 +524,31 @@ class ApiServer(RPC):
|
|||||||
timeframe = request.args.get("timeframe")
|
timeframe = request.args.get("timeframe")
|
||||||
limit = request.args.get("limit", type=int)
|
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)
|
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
|
@require_login
|
||||||
@rpc_catch_errors
|
@rpc_catch_errors
|
||||||
def _plot_config(self):
|
def _plot_config(self):
|
||||||
|
@ -9,9 +9,11 @@ from math import isnan
|
|||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||||
|
|
||||||
import arrow
|
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.constants import CANCEL_REASON
|
||||||
|
from freqtrade.data.history import load_data
|
||||||
from freqtrade.exceptions import ExchangeError, PricingError
|
from freqtrade.exceptions import ExchangeError, PricingError
|
||||||
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_msecs
|
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_msecs
|
||||||
from freqtrade.loggers import bufferHandler
|
from freqtrade.loggers import bufferHandler
|
||||||
@ -654,19 +656,41 @@ class RPC:
|
|||||||
raise RPCException('Edge is not enabled.')
|
raise RPCException('Edge is not enabled.')
|
||||||
return self._freqtrade.edge.accepted_pairs()
|
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)
|
_data, last_analyzed = self._freqtrade.dataprovider.get_analyzed_dataframe(pair, timeframe)
|
||||||
if limit:
|
if limit:
|
||||||
_data = _data.iloc[-limit:]
|
_data = _data.iloc[-limit:]
|
||||||
_data = _data.replace({NAN: None})
|
return self._convert_dataframe_to_dict(pair, _data, last_analyzed)
|
||||||
_data['date'] = _data['date'].astype(int64) // 1000 // 1000
|
|
||||||
return {
|
def _rpc_analysed_history_full(self, pair: str, timeframe: str,
|
||||||
'columns': list(_data.columns),
|
timerange: str) -> Dict[str, Any]:
|
||||||
'data': _data.values.tolist(),
|
timerange = TimeRange.parse_timerange(None if self.config.get(
|
||||||
'length': len(_data),
|
'timerange') is None else str(self.config.get('timerange')))
|
||||||
'last_analyzed': last_analyzed,
|
|
||||||
}
|
_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]:
|
def _rpc_plot_config(self) -> Dict[str, Any]:
|
||||||
|
|
||||||
|
@ -813,7 +813,7 @@ def test_api_forcesell(botclient, mocker, ticker, fee, markets):
|
|||||||
assert rc.json == {'result': 'Created sell order for trade 1.'}
|
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
|
ftbot, client = botclient
|
||||||
timeframe = '5m'
|
timeframe = '5m'
|
||||||
amount = 2
|
amount = 2
|
||||||
@ -821,11 +821,13 @@ def test_api_pair_history(botclient, ohlcv_history):
|
|||||||
ftbot.dataprovider._set_cached_df("XRP/BTC", timeframe, ohlcv_history)
|
ftbot.dataprovider._set_cached_df("XRP/BTC", timeframe, ohlcv_history)
|
||||||
|
|
||||||
rc = client_get(client,
|
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_response(rc)
|
||||||
assert 'columns' in rc.json
|
assert 'columns' in rc.json
|
||||||
assert isinstance(rc.json['columns'], list)
|
assert isinstance(rc.json['columns'], list)
|
||||||
assert rc.json['columns'] == ['date', 'open', 'high', 'low', 'close', 'volume', 'sma']
|
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 'data' in rc.json
|
||||||
assert len(rc.json['data']) == amount
|
assert len(rc.json['data']) == amount
|
||||||
|
Loading…
Reference in New Issue
Block a user