Implement missing methods
This commit is contained in:
parent
e23898d17b
commit
9350f505bc
@ -1,4 +1,4 @@
|
|||||||
from typing import Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
@ -161,3 +161,23 @@ class DeleteTrade(BaseModel):
|
|||||||
result: str
|
result: str
|
||||||
result_msg: str
|
result_msg: str
|
||||||
trade_id: int
|
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]]
|
||||||
|
@ -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 import APIRouter, Depends
|
||||||
|
from fastapi.exceptions import HTTPException
|
||||||
|
|
||||||
from freqtrade import __version__
|
from freqtrade import __version__
|
||||||
|
from freqtrade.data.history import get_datahandler
|
||||||
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.rpc import RPC
|
from freqtrade.rpc import RPC
|
||||||
from freqtrade.rpc.rpc import RPCException
|
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,
|
from .api_models import (AvailablePairs, Balances, BlacklistPayload, BlacklistResponse, Count,
|
||||||
StatusMsg, Version, WhitelistResponse)
|
Daily, DeleteTrade, ForceBuyPayload, ForceSellPayload, Locks, Logs,
|
||||||
|
PerformanceEntry, Ping, PlotConfig, Profit, ResultMsg, Stats, StatusMsg, StrategyListResponse, StrategyResponse, Version,
|
||||||
|
WhitelistResponse)
|
||||||
from .deps import get_config, get_rpc
|
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'])
|
@router.post('/reload_config', response_model=StatusMsg, tags=['botcontrol'])
|
||||||
def reload_config(rpc: RPC = Depends(get_rpc)):
|
def reload_config(rpc: RPC = Depends(get_rpc)):
|
||||||
return rpc._rpc_reload_config()
|
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
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
from starlette.responses import JSONResponse
|
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from fastapi import Depends, FastAPI
|
from fastapi import Depends, FastAPI
|
||||||
from fastapi.exceptions import HTTPException
|
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from starlette.responses import JSONResponse
|
||||||
|
|
||||||
from freqtrade.rpc.rpc import RPC, RPCException, RPCHandler
|
from freqtrade.rpc.rpc import RPC, RPCException, RPCHandler
|
||||||
|
|
||||||
|
@ -894,22 +894,22 @@ def test_api_pair_candles(botclient, ohlcv_history):
|
|||||||
# No pair
|
# No pair
|
||||||
rc = client_get(client,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_candles?limit={amount}&timeframe={timeframe}")
|
f"{BASE_URI}/pair_candles?limit={amount}&timeframe={timeframe}")
|
||||||
assert_response(rc, 400)
|
assert_response(rc, 422)
|
||||||
|
|
||||||
# No timeframe
|
# No timeframe
|
||||||
rc = client_get(client,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_candles?pair=XRP%2FBTC")
|
f"{BASE_URI}/pair_candles?pair=XRP%2FBTC")
|
||||||
assert_response(rc, 400)
|
assert_response(rc, 422)
|
||||||
|
|
||||||
rc = client_get(client,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_candles?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 'data_start_ts' in rc.json
|
assert 'data_start_ts' in rc.json()
|
||||||
assert 'data_start' in rc.json
|
assert 'data_start' in rc.json()
|
||||||
assert 'data_stop' in rc.json
|
assert 'data_stop' in rc.json()
|
||||||
assert 'data_stop_ts' in rc.json
|
assert 'data_stop_ts' in rc.json()
|
||||||
assert len(rc.json['data']) == 0
|
assert len(rc.json()['data']) == 0
|
||||||
ohlcv_history['sma'] = ohlcv_history['close'].rolling(2).mean()
|
ohlcv_history['sma'] = ohlcv_history['close'].rolling(2).mean()
|
||||||
ohlcv_history['buy'] = 0
|
ohlcv_history['buy'] = 0
|
||||||
ohlcv_history.loc[1, 'buy'] = 1
|
ohlcv_history.loc[1, 'buy'] = 1
|
||||||
@ -920,28 +920,28 @@ def test_api_pair_candles(botclient, ohlcv_history):
|
|||||||
rc = client_get(client,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_candles?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 'strategy' in rc.json
|
assert 'strategy' in rc.json()
|
||||||
assert rc.json['strategy'] == 'DefaultStrategy'
|
assert rc.json()['strategy'] == 'DefaultStrategy'
|
||||||
assert 'columns' in rc.json
|
assert 'columns' in rc.json()
|
||||||
assert 'data_start_ts' in rc.json
|
assert 'data_start_ts' in rc.json()
|
||||||
assert 'data_start' in rc.json
|
assert 'data_start' in rc.json()
|
||||||
assert 'data_stop' in rc.json
|
assert 'data_stop' in rc.json()
|
||||||
assert 'data_stop_ts' 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'] == '2017-11-26 08:50:00+00:00'
|
||||||
assert rc.json['data_start_ts'] == 1511686200000
|
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'] == '2017-11-26 09:00:00+00:00'
|
||||||
assert rc.json['data_stop_ts'] == 1511686800000
|
assert rc.json()['data_stop_ts'] == 1511686800000
|
||||||
assert isinstance(rc.json['columns'], list)
|
assert isinstance(rc.json()['columns'], list)
|
||||||
assert rc.json['columns'] == ['date', 'open', 'high',
|
assert rc.json()['columns'] == ['date', 'open', 'high',
|
||||||
'low', 'close', 'volume', 'sma', 'buy', 'sell',
|
'low', 'close', 'volume', 'sma', 'buy', 'sell',
|
||||||
'__date_ts', '_buy_signal_open', '_sell_signal_open']
|
'__date_ts', '_buy_signal_open', '_sell_signal_open']
|
||||||
assert 'pair' in rc.json
|
assert 'pair' in rc.json()
|
||||||
assert rc.json['pair'] == 'XRP/BTC'
|
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
|
||||||
|
|
||||||
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,
|
[['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],
|
None, 0, 0, 1511686200000, None, None],
|
||||||
['2017-11-26 08:55:00', 8.88e-05, 8.942e-05, 8.88e-05,
|
['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,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_history?timeframe={timeframe}"
|
f"{BASE_URI}/pair_history?timeframe={timeframe}"
|
||||||
"&timerange=20180111-20180112&strategy=DefaultStrategy")
|
"&timerange=20180111-20180112&strategy=DefaultStrategy")
|
||||||
assert_response(rc, 400)
|
assert_response(rc, 422)
|
||||||
|
|
||||||
# No Timeframe
|
# No Timeframe
|
||||||
rc = client_get(client,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC"
|
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC"
|
||||||
"&timerange=20180111-20180112&strategy=DefaultStrategy")
|
"&timerange=20180111-20180112&strategy=DefaultStrategy")
|
||||||
assert_response(rc, 400)
|
assert_response(rc, 422)
|
||||||
|
|
||||||
# No timerange
|
# No timerange
|
||||||
rc = client_get(client,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
||||||
"&strategy=DefaultStrategy")
|
"&strategy=DefaultStrategy")
|
||||||
assert_response(rc, 400)
|
assert_response(rc, 422)
|
||||||
|
|
||||||
# No strategy
|
# No strategy
|
||||||
rc = client_get(client,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
||||||
"&timerange=20180111-20180112")
|
"&timerange=20180111-20180112")
|
||||||
assert_response(rc, 400)
|
assert_response(rc, 422)
|
||||||
|
|
||||||
# Working
|
# Working
|
||||||
rc = client_get(client,
|
rc = client_get(client,
|
||||||
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
|
||||||
"&timerange=20180111-20180112&strategy=DefaultStrategy")
|
"&timerange=20180111-20180112&strategy=DefaultStrategy")
|
||||||
assert_response(rc, 200)
|
assert_response(rc, 200)
|
||||||
assert rc.json['length'] == 289
|
assert rc.json()['length'] == 289
|
||||||
assert len(rc.json['data']) == rc.json['length']
|
assert len(rc.json()['data']) == rc.json()['length']
|
||||||
assert 'columns' in rc.json
|
assert 'columns' in rc.json()
|
||||||
assert 'data' in rc.json
|
assert 'data' in rc.json()
|
||||||
assert rc.json['pair'] == 'UNITTEST/BTC'
|
assert rc.json()['pair'] == 'UNITTEST/BTC'
|
||||||
assert rc.json['strategy'] == 'DefaultStrategy'
|
assert rc.json()['strategy'] == 'DefaultStrategy'
|
||||||
assert rc.json['data_start'] == '2018-01-11 00:00:00+00:00'
|
assert rc.json()['data_start'] == '2018-01-11 00:00:00+00:00'
|
||||||
assert rc.json['data_start_ts'] == 1515628800000
|
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'] == '2018-01-12 00:00:00+00:00'
|
||||||
assert rc.json['data_stop_ts'] == 1515715200000
|
assert rc.json()['data_stop_ts'] == 1515715200000
|
||||||
|
|
||||||
|
|
||||||
def test_api_plot_config(botclient):
|
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")
|
rc = client_get(client, f"{BASE_URI}/plot_config")
|
||||||
assert_response(rc)
|
assert_response(rc)
|
||||||
assert rc.json == {}
|
assert rc.json() == {}
|
||||||
|
|
||||||
ftbot.strategy.plot_config = {'main_plot': {'sma': {}},
|
ftbot.strategy.plot_config = {'main_plot': {'sma': {}},
|
||||||
'subplots': {'RSI': {'rsi': {'color': 'red'}}}}
|
'subplots': {'RSI': {'rsi': {'color': 'red'}}}}
|
||||||
rc = client_get(client, f"{BASE_URI}/plot_config")
|
rc = client_get(client, f"{BASE_URI}/plot_config")
|
||||||
assert_response(rc)
|
assert_response(rc)
|
||||||
assert rc.json == ftbot.strategy.plot_config
|
assert rc.json() == ftbot.strategy.plot_config
|
||||||
assert isinstance(rc.json['main_plot'], dict)
|
assert isinstance(rc.json()['main_plot'], dict)
|
||||||
|
|
||||||
|
|
||||||
def test_api_strategies(botclient):
|
def test_api_strategies(botclient):
|
||||||
@ -1018,7 +1018,7 @@ def test_api_strategies(botclient):
|
|||||||
rc = client_get(client, f"{BASE_URI}/strategies")
|
rc = client_get(client, f"{BASE_URI}/strategies")
|
||||||
|
|
||||||
assert_response(rc)
|
assert_response(rc)
|
||||||
assert rc.json == {'strategies': ['DefaultStrategy', 'TestStrategyLegacy']}
|
assert rc.json() == {'strategies': ['DefaultStrategy', 'TestStrategyLegacy']}
|
||||||
|
|
||||||
|
|
||||||
def test_api_strategy(botclient):
|
def test_api_strategy(botclient):
|
||||||
@ -1027,10 +1027,10 @@ def test_api_strategy(botclient):
|
|||||||
rc = client_get(client, f"{BASE_URI}/strategy/DefaultStrategy")
|
rc = client_get(client, f"{BASE_URI}/strategy/DefaultStrategy")
|
||||||
|
|
||||||
assert_response(rc)
|
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()
|
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")
|
rc = client_get(client, f"{BASE_URI}/strategy/NoStrat")
|
||||||
assert_response(rc, 404)
|
assert_response(rc, 404)
|
||||||
@ -1042,21 +1042,21 @@ def test_list_available_pairs(botclient):
|
|||||||
rc = client_get(client, f"{BASE_URI}/available_pairs")
|
rc = client_get(client, f"{BASE_URI}/available_pairs")
|
||||||
|
|
||||||
assert_response(rc)
|
assert_response(rc)
|
||||||
assert rc.json['length'] == 12
|
assert rc.json()['length'] == 12
|
||||||
assert isinstance(rc.json['pairs'], list)
|
assert isinstance(rc.json()['pairs'], list)
|
||||||
|
|
||||||
rc = client_get(client, f"{BASE_URI}/available_pairs?timeframe=5m")
|
rc = client_get(client, f"{BASE_URI}/available_pairs?timeframe=5m")
|
||||||
assert_response(rc)
|
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")
|
rc = client_get(client, f"{BASE_URI}/available_pairs?stake_currency=ETH")
|
||||||
assert_response(rc)
|
assert_response(rc)
|
||||||
assert rc.json['length'] == 1
|
assert rc.json()['length'] == 1
|
||||||
assert rc.json['pairs'] == ['XRP/ETH']
|
assert rc.json()['pairs'] == ['XRP/ETH']
|
||||||
assert len(rc.json['pair_interval']) == 2
|
assert len(rc.json()['pair_interval']) == 2
|
||||||
|
|
||||||
rc = client_get(client, f"{BASE_URI}/available_pairs?stake_currency=ETH&timeframe=5m")
|
rc = client_get(client, f"{BASE_URI}/available_pairs?stake_currency=ETH&timeframe=5m")
|
||||||
assert_response(rc)
|
assert_response(rc)
|
||||||
assert rc.json['length'] == 1
|
assert rc.json()['length'] == 1
|
||||||
assert rc.json['pairs'] == ['XRP/ETH']
|
assert rc.json()['pairs'] == ['XRP/ETH']
|
||||||
assert len(rc.json['pair_interval']) == 1
|
assert len(rc.json()['pair_interval']) == 1
|
||||||
|
Loading…
Reference in New Issue
Block a user