• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

freqtrade / freqtrade / 9394559170

26 Apr 2024 06:36AM UTC coverage: 94.656% (-0.02%) from 94.674%
9394559170

push

github

xmatthias
Loader should be passed as kwarg for clarity

20280 of 21425 relevant lines covered (94.66%)

0.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.55
/freqtrade/rpc/api_server/api_background_tasks.py
1
import logging
1✔
2
from copy import deepcopy
1✔
3

4
from fastapi import APIRouter, BackgroundTasks, Depends
1✔
5
from fastapi.exceptions import HTTPException
1✔
6

7
from freqtrade.constants import Config
1✔
8
from freqtrade.enums import CandleType
1✔
9
from freqtrade.exceptions import OperationalException
1✔
10
from freqtrade.persistence import FtNoDBContext
1✔
11
from freqtrade.rpc.api_server.api_schemas import (BackgroundTaskStatus, BgJobStarted,
1✔
12
                                                  ExchangeModePayloadMixin, PairListsPayload,
13
                                                  PairListsResponse, WhitelistEvaluateResponse)
14
from freqtrade.rpc.api_server.deps import get_config, get_exchange
1✔
15
from freqtrade.rpc.api_server.webserver_bgwork import ApiBG
1✔
16

17

18
logger = logging.getLogger(__name__)
1✔
19

20
# Private API, protected by authentication and webserver_mode dependency
21
router = APIRouter()
1✔
22

23

24
@router.get('/background/{jobid}', response_model=BackgroundTaskStatus, tags=['webserver'])
1✔
25
def background_job(jobid: str):
1✔
26
    if not (job := ApiBG.jobs.get(jobid)):
1✔
27
        raise HTTPException(status_code=404, detail='Job not found.')
1✔
28

29
    return {
1✔
30
        'job_id': jobid,
31
        'job_category': job['category'],
32
        'status': job['status'],
33
        'running': job['is_running'],
34
        'progress': job.get('progress'),
35
        # 'job_error': job['error'],
36
    }
37

38

39
@router.get('/pairlists/available',
1✔
40
            response_model=PairListsResponse, tags=['pairlists', 'webserver'])
41
def list_pairlists(config=Depends(get_config)):
1✔
42
    from freqtrade.resolvers import PairListResolver
1✔
43
    pairlists = PairListResolver.search_all_objects(
1✔
44
        config, False)
45
    pairlists = sorted(pairlists, key=lambda x: x['name'])
1✔
46

47
    return {'pairlists': [{
1✔
48
        "name": x['name'],
49
        "is_pairlist_generator": x['class'].is_pairlist_generator,
50
        "params": x['class'].available_parameters(),
51
        "description": x['class'].description(),
52
         } for x in pairlists
53
    ]}
54

55

56
def __run_pairlist(job_id: str, config_loc: Config):
1✔
57
    try:
1✔
58

59
        ApiBG.jobs[job_id]['is_running'] = True
1✔
60
        from freqtrade.plugins.pairlistmanager import PairListManager
1✔
61
        with FtNoDBContext():
1✔
62
            exchange = get_exchange(config_loc)
1✔
63
            pairlists = PairListManager(exchange, config_loc)
1✔
64
            pairlists.refresh_pairlist()
1✔
65
            ApiBG.jobs[job_id]['result'] = {
1✔
66
                    'method': pairlists.name_list,
67
                    'length': len(pairlists.whitelist),
68
                    'whitelist': pairlists.whitelist
69
                }
70
            ApiBG.jobs[job_id]['status'] = 'success'
1✔
71
    except (OperationalException, Exception) as e:
×
72
        logger.exception(e)
×
73
        ApiBG.jobs[job_id]['error'] = str(e)
×
74
        ApiBG.jobs[job_id]['status'] = 'failed'
×
75
    finally:
76
        ApiBG.jobs[job_id]['is_running'] = False
1✔
77
        ApiBG.pairlist_running = False
1✔
78

79

80
@router.post('/pairlists/evaluate', response_model=BgJobStarted, tags=['pairlists', 'webserver'])
1✔
81
def pairlists_evaluate(payload: PairListsPayload, background_tasks: BackgroundTasks,
1✔
82
                       config=Depends(get_config)):
83
    if ApiBG.pairlist_running:
1✔
84
        raise HTTPException(status_code=400, detail='Pairlist evaluation is already running.')
1✔
85

86
    config_loc = deepcopy(config)
1✔
87
    config_loc['stake_currency'] = payload.stake_currency
1✔
88
    config_loc['pairlists'] = payload.pairlists
1✔
89
    handleExchangePayload(payload, config_loc)
1✔
90
    # TODO: overwrite blacklist? make it optional and fall back to the one in config?
91
    # Outcome depends on the UI approach.
92
    config_loc['exchange']['pair_blacklist'] = payload.blacklist
1✔
93
    # Random job id
94
    job_id = ApiBG.get_job_id()
1✔
95

96
    ApiBG.jobs[job_id] = {
1✔
97
        'category': 'pairlist',
98
        'status': 'pending',
99
        'progress': None,
100
        'is_running': False,
101
        'result': {},
102
        'error': None,
103
    }
104
    background_tasks.add_task(__run_pairlist, job_id, config_loc)
1✔
105
    ApiBG.pairlist_running = True
1✔
106

107
    return {
1✔
108
        'status': 'Pairlist evaluation started in background.',
109
        'job_id': job_id,
110
    }
111

112

113
def handleExchangePayload(payload: ExchangeModePayloadMixin, config_loc: Config):
1✔
114
    """
115
    Handle exchange and trading mode payload.
116
    Updates the configuration with the payload values.
117
    """
118
    if payload.exchange:
1✔
119
        config_loc['exchange']['name'] = payload.exchange
1✔
120
    if payload.trading_mode:
1✔
121
        config_loc['trading_mode'] = payload.trading_mode
1✔
122
        config_loc['candle_type_def'] = CandleType.get_default(
1✔
123
            config_loc.get('trading_mode', 'spot') or 'spot')
124
    if payload.margin_mode:
1✔
125
        config_loc['margin_mode'] = payload.margin_mode
1✔
126

127

128
@router.get('/pairlists/evaluate/{jobid}', response_model=WhitelistEvaluateResponse,
1✔
129
            tags=['pairlists', 'webserver'])
130
def pairlists_evaluate_get(jobid: str):
1✔
131
    if not (job := ApiBG.jobs.get(jobid)):
1✔
132
        raise HTTPException(status_code=404, detail='Job not found.')
1✔
133

134
    if job['is_running']:
1✔
135
        raise HTTPException(status_code=400, detail='Job not finished yet.')
×
136

137
    if error := job['error']:
1✔
138
        return {
×
139
            'status': 'failed',
140
            'error': error,
141
        }
142

143
    return {
1✔
144
        'status': 'success',
145
        'result': job['result'],
146
    }
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc