Implement missing methods

This commit is contained in:
Matthias 2020-12-26 20:05:27 +01:00
parent e23898d17b
commit 9350f505bc
4 changed files with 162 additions and 61 deletions

View File

@ -1,4 +1,4 @@
from typing import Dict, List, Optional, Union
from typing import Any, Dict, List, Optional, Union
from datetime import date
from pydantic import BaseModel
@ -161,3 +161,23 @@ class DeleteTrade(BaseModel):
result: str
result_msg: str
trade_id: int
class PlotConfig(BaseModel):
main_plot: Optional[Dict[str, Any]]
subplots: Optional[Dict[str, Any]]
class StrategyListResponse(BaseModel):
strategies: List[str]
class StrategyResponse(BaseModel):
strategy: str
code: str
class AvailablePairs(BaseModel):
length: int
pairs: List[str]
pair_interval: List[List[str]]

View File

@ -1,13 +1,21 @@
from typing import List, Optional
from copy import deepcopy
from freqtrade.constants import USERPATH_STRATEGIES
from typing import Dict, List, Optional, Union
from pathlib import Path
from fastapi import APIRouter, Depends
from fastapi.exceptions import HTTPException
from freqtrade import __version__
from freqtrade.data.history import get_datahandler
from freqtrade.exceptions import OperationalException
from freqtrade.rpc import RPC
from freqtrade.rpc.rpc import RPCException
from .api_models import (Balances, BlacklistPayload, BlacklistResponse, Count, Daily, DeleteTrade, ForceBuyPayload, ForceSellPayload, Locks, Logs, PerformanceEntry, Ping, Profit, ResultMsg, Stats,
StatusMsg, Version, WhitelistResponse)
from .api_models import (AvailablePairs, Balances, BlacklistPayload, BlacklistResponse, Count,
Daily, DeleteTrade, ForceBuyPayload, ForceSellPayload, Locks, Logs,
PerformanceEntry, Ping, PlotConfig, Profit, ResultMsg, Stats, StatusMsg, StrategyListResponse, StrategyResponse, Version,
WhitelistResponse)
from .deps import get_config, get_rpc
@ -154,3 +162,77 @@ def stop_buy(rpc: RPC = Depends(get_rpc)):
@router.post('/reload_config', response_model=StatusMsg, tags=['botcontrol'])
def reload_config(rpc: RPC = Depends(get_rpc)):
return rpc._rpc_reload_config()
# TODO: Missing response model
@router.get('/pair_candles', tags=['candle data'])
def pair_candles(pair: str, timeframe: str, limit: Optional[int], rpc=Depends(get_rpc)):
return rpc._rpc_analysed_dataframe(pair, timeframe, limit)
# TODO: Missing response model
@router.get('/pair_history', tags=['candle data'])
def pair_history(pair: str, timeframe: str, timerange: str, strategy: str,
config=Depends(get_config)):
config = deepcopy(config)
config.update({
'strategy': strategy,
})
return RPC._rpc_analysed_history_full(config, pair, timeframe, timerange)
@router.get('/plot_config', response_model=Union[Dict, PlotConfig], tags=['candle data'])
def plot_config(rpc=Depends(get_rpc)):
return rpc._rpc_plot_config()
@router.get('/strategies', response_model=StrategyListResponse, tags=['strategy'])
def list_strategies(config=Depends(get_config)):
directory = Path(config.get(
'strategy_path', config['user_data_dir'] / USERPATH_STRATEGIES))
from freqtrade.resolvers.strategy_resolver import StrategyResolver
strategies = StrategyResolver.search_all_objects(directory, False)
strategies = sorted(strategies, key=lambda x: x['name'])
return {'strategies': [x['name'] for x in strategies]}
@router.get('/strategy/{strategy}', response_model=StrategyResponse, tags=['strategy'])
def get_strategy(strategy: str, rpc: RPC = Depends(get_rpc), config=Depends(get_config)):
config = deepcopy(config)
from freqtrade.resolvers.strategy_resolver import StrategyResolver
try:
strategy_obj = StrategyResolver._load_strategy(strategy, config,
extra_dir=config.get('strategy_path'))
except OperationalException:
raise HTTPException(status_code=404, detail='Strategy not found')
return {
'strategy': strategy_obj.get_strategy_name(),
'code': strategy_obj.__source__,
}
@router.get('/available_pairs', response_model=AvailablePairs, tags=['candle data'])
def list_available_pairs(timeframe: Optional[str] = None, stake_currency: Optional[str] = None,
config=Depends(get_config)):
dh = get_datahandler(config['datadir'], config.get('dataformat_ohlcv', None))
pair_interval = dh.ohlcv_get_available_data(config['datadir'])
if timeframe:
pair_interval = [pair for pair in pair_interval if pair[1] == timeframe]
if stake_currency:
pair_interval = [pair for pair in pair_interval if pair[0].endswith(stake_currency)]
pair_interval = sorted(pair_interval, key=lambda x: x[0])
pairs = list({x[0] for x in pair_interval})
result = {
'length': len(pairs),
'pairs': pairs,
'pair_interval': pair_interval,
}
return result

View File

@ -1,11 +1,10 @@
import logging
from typing import Any, Dict, Optional
from starlette.responses import JSONResponse
import uvicorn
from fastapi import Depends, FastAPI
from fastapi.exceptions import HTTPException
from fastapi.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse
from freqtrade.rpc.rpc import RPC, RPCException, RPCHandler

View File

@ -894,22 +894,22 @@ def test_api_pair_candles(botclient, ohlcv_history):
# No pair
rc = client_get(client,
f"{BASE_URI}/pair_candles?limit={amount}&timeframe={timeframe}")
assert_response(rc, 400)
assert_response(rc, 422)
# No timeframe
rc = client_get(client,
f"{BASE_URI}/pair_candles?pair=XRP%2FBTC")
assert_response(rc, 400)
assert_response(rc, 422)
rc = client_get(client,
f"{BASE_URI}/pair_candles?limit={amount}&pair=XRP%2FBTC&timeframe={timeframe}")
assert_response(rc)
assert 'columns' in rc.json
assert 'data_start_ts' in rc.json
assert 'data_start' in rc.json
assert 'data_stop' in rc.json
assert 'data_stop_ts' in rc.json
assert len(rc.json['data']) == 0
assert 'columns' in rc.json()
assert 'data_start_ts' in rc.json()
assert 'data_start' in rc.json()
assert 'data_stop' in rc.json()
assert 'data_stop_ts' in rc.json()
assert len(rc.json()['data']) == 0
ohlcv_history['sma'] = ohlcv_history['close'].rolling(2).mean()
ohlcv_history['buy'] = 0
ohlcv_history.loc[1, 'buy'] = 1
@ -920,28 +920,28 @@ def test_api_pair_candles(botclient, ohlcv_history):
rc = client_get(client,
f"{BASE_URI}/pair_candles?limit={amount}&pair=XRP%2FBTC&timeframe={timeframe}")
assert_response(rc)
assert 'strategy' in rc.json
assert rc.json['strategy'] == 'DefaultStrategy'
assert 'columns' in rc.json
assert 'data_start_ts' in rc.json
assert 'data_start' in rc.json
assert 'data_stop' in rc.json
assert 'data_stop_ts' in rc.json
assert rc.json['data_start'] == '2017-11-26 08:50:00+00:00'
assert rc.json['data_start_ts'] == 1511686200000
assert rc.json['data_stop'] == '2017-11-26 09:00:00+00:00'
assert rc.json['data_stop_ts'] == 1511686800000
assert isinstance(rc.json['columns'], list)
assert rc.json['columns'] == ['date', 'open', 'high',
assert 'strategy' in rc.json()
assert rc.json()['strategy'] == 'DefaultStrategy'
assert 'columns' in rc.json()
assert 'data_start_ts' in rc.json()
assert 'data_start' in rc.json()
assert 'data_stop' in rc.json()
assert 'data_stop_ts' in rc.json()
assert rc.json()['data_start'] == '2017-11-26 08:50:00+00:00'
assert rc.json()['data_start_ts'] == 1511686200000
assert rc.json()['data_stop'] == '2017-11-26 09:00:00+00:00'
assert rc.json()['data_stop_ts'] == 1511686800000
assert isinstance(rc.json()['columns'], list)
assert rc.json()['columns'] == ['date', 'open', 'high',
'low', 'close', 'volume', 'sma', 'buy', 'sell',
'__date_ts', '_buy_signal_open', '_sell_signal_open']
assert 'pair' in rc.json
assert rc.json['pair'] == 'XRP/BTC'
assert 'pair' in rc.json()
assert rc.json()['pair'] == 'XRP/BTC'
assert 'data' in rc.json
assert len(rc.json['data']) == amount
assert 'data' in rc.json()
assert len(rc.json()['data']) == amount
assert (rc.json['data'] ==
assert (rc.json()['data'] ==
[['2017-11-26 08:50:00', 8.794e-05, 8.948e-05, 8.794e-05, 8.88e-05, 0.0877869,
None, 0, 0, 1511686200000, None, None],
['2017-11-26 08:55:00', 8.88e-05, 8.942e-05, 8.88e-05,
@ -960,41 +960,41 @@ def test_api_pair_history(botclient, ohlcv_history):
rc = client_get(client,
f"{BASE_URI}/pair_history?timeframe={timeframe}"
"&timerange=20180111-20180112&strategy=DefaultStrategy")
assert_response(rc, 400)
assert_response(rc, 422)
# No Timeframe
rc = client_get(client,
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC"
"&timerange=20180111-20180112&strategy=DefaultStrategy")
assert_response(rc, 400)
assert_response(rc, 422)
# No timerange
rc = client_get(client,
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
"&strategy=DefaultStrategy")
assert_response(rc, 400)
assert_response(rc, 422)
# No strategy
rc = client_get(client,
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
"&timerange=20180111-20180112")
assert_response(rc, 400)
assert_response(rc, 422)
# Working
rc = client_get(client,
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
"&timerange=20180111-20180112&strategy=DefaultStrategy")
assert_response(rc, 200)
assert rc.json['length'] == 289
assert len(rc.json['data']) == rc.json['length']
assert 'columns' in rc.json
assert 'data' in rc.json
assert rc.json['pair'] == 'UNITTEST/BTC'
assert rc.json['strategy'] == 'DefaultStrategy'
assert rc.json['data_start'] == '2018-01-11 00:00:00+00:00'
assert rc.json['data_start_ts'] == 1515628800000
assert rc.json['data_stop'] == '2018-01-12 00:00:00+00:00'
assert rc.json['data_stop_ts'] == 1515715200000
assert rc.json()['length'] == 289
assert len(rc.json()['data']) == rc.json()['length']
assert 'columns' in rc.json()
assert 'data' in rc.json()
assert rc.json()['pair'] == 'UNITTEST/BTC'
assert rc.json()['strategy'] == 'DefaultStrategy'
assert rc.json()['data_start'] == '2018-01-11 00:00:00+00:00'
assert rc.json()['data_start_ts'] == 1515628800000
assert rc.json()['data_stop'] == '2018-01-12 00:00:00+00:00'
assert rc.json()['data_stop_ts'] == 1515715200000
def test_api_plot_config(botclient):
@ -1002,14 +1002,14 @@ def test_api_plot_config(botclient):
rc = client_get(client, f"{BASE_URI}/plot_config")
assert_response(rc)
assert rc.json == {}
assert rc.json() == {}
ftbot.strategy.plot_config = {'main_plot': {'sma': {}},
'subplots': {'RSI': {'rsi': {'color': 'red'}}}}
rc = client_get(client, f"{BASE_URI}/plot_config")
assert_response(rc)
assert rc.json == ftbot.strategy.plot_config
assert isinstance(rc.json['main_plot'], dict)
assert rc.json() == ftbot.strategy.plot_config
assert isinstance(rc.json()['main_plot'], dict)
def test_api_strategies(botclient):
@ -1018,7 +1018,7 @@ def test_api_strategies(botclient):
rc = client_get(client, f"{BASE_URI}/strategies")
assert_response(rc)
assert rc.json == {'strategies': ['DefaultStrategy', 'TestStrategyLegacy']}
assert rc.json() == {'strategies': ['DefaultStrategy', 'TestStrategyLegacy']}
def test_api_strategy(botclient):
@ -1027,10 +1027,10 @@ def test_api_strategy(botclient):
rc = client_get(client, f"{BASE_URI}/strategy/DefaultStrategy")
assert_response(rc)
assert rc.json['strategy'] == 'DefaultStrategy'
assert rc.json()['strategy'] == 'DefaultStrategy'
data = (Path(__file__).parents[1] / "strategy/strats/default_strategy.py").read_text()
assert rc.json['code'] == data
assert rc.json()['code'] == data
rc = client_get(client, f"{BASE_URI}/strategy/NoStrat")
assert_response(rc, 404)
@ -1042,21 +1042,21 @@ def test_list_available_pairs(botclient):
rc = client_get(client, f"{BASE_URI}/available_pairs")
assert_response(rc)
assert rc.json['length'] == 12
assert isinstance(rc.json['pairs'], list)
assert rc.json()['length'] == 12
assert isinstance(rc.json()['pairs'], list)
rc = client_get(client, f"{BASE_URI}/available_pairs?timeframe=5m")
assert_response(rc)
assert rc.json['length'] == 12
assert rc.json()['length'] == 12
rc = client_get(client, f"{BASE_URI}/available_pairs?stake_currency=ETH")
assert_response(rc)
assert rc.json['length'] == 1
assert rc.json['pairs'] == ['XRP/ETH']
assert len(rc.json['pair_interval']) == 2
assert rc.json()['length'] == 1
assert rc.json()['pairs'] == ['XRP/ETH']
assert len(rc.json()['pair_interval']) == 2
rc = client_get(client, f"{BASE_URI}/available_pairs?stake_currency=ETH&timeframe=5m")
assert_response(rc)
assert rc.json['length'] == 1
assert rc.json['pairs'] == ['XRP/ETH']
assert len(rc.json['pair_interval']) == 1
assert rc.json()['length'] == 1
assert rc.json()['pairs'] == ['XRP/ETH']
assert len(rc.json()['pair_interval']) == 1