From 67686583007e0a8260d84f525e3a76eef665dcfd Mon Sep 17 00:00:00 2001 From: Pan Long Date: Mon, 25 Dec 2017 14:01:01 +0800 Subject: [PATCH] Make get_signals async. This should speed up create_trade calls by at least 10x. (#223) --- freqtrade/analyze.py | 3 +++ freqtrade/exchange/__init__.py | 4 +++- freqtrade/main.py | 15 +++++++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/freqtrade/analyze.py b/freqtrade/analyze.py index d586077db..887fc0282 100644 --- a/freqtrade/analyze.py +++ b/freqtrade/analyze.py @@ -144,6 +144,9 @@ def get_signal(pair: str, signal: SignalType) -> bool: except ValueError as ex: logger.warning('Unable to analyze ticker for pair %s: %s', pair, str(ex)) return False + except Exception: + logger.exception('Unexpected error when analyzing ticker for pair %s.', pair) + return False if dataframe.empty: return False diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 7b5c0c753..8e87cfc8b 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -3,6 +3,7 @@ import enum import logging from random import randint +from threading import RLock from typing import List, Dict, Any, Optional import arrow @@ -14,6 +15,7 @@ from freqtrade.exchange.bittrex import Bittrex from freqtrade.exchange.interface import Exchange logger = logging.getLogger(__name__) +lock = RLock() # Current selected exchange _API: Exchange = None @@ -138,7 +140,7 @@ def get_ticker(pair: str) -> dict: return _API.get_ticker(pair) -@cached(TTLCache(maxsize=100, ttl=30)) +@cached(TTLCache(maxsize=100, ttl=30), lock=lock) def get_ticker_history(pair: str, tick_interval: Optional[int] = 5) -> List[Dict]: return _API.get_ticker_history(pair, tick_interval) diff --git a/freqtrade/main.py b/freqtrade/main.py index 212e9f0e9..31a4c4c55 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 +import asyncio import copy import json import logging import sys import time import traceback +from concurrent.futures import ThreadPoolExecutor from datetime import datetime from typing import Dict, Optional, List @@ -210,8 +212,17 @@ def create_trade(stake_amount: float) -> bool: raise DependencyException('No pair in whitelist') # Pick pair based on StochRSI buy signals - for _pair in whitelist: - if get_signal(_pair, SignalType.BUY): + with ThreadPoolExecutor() as pool: + awaitable_signals = [ + asyncio.wrap_future(pool.submit(get_signal, pair, SignalType.BUY)) + for pair in whitelist + ] + + loop = asyncio.get_event_loop() + signals = loop.run_until_complete(asyncio.gather(*awaitable_signals)) + + for idx, _pair in enumerate(whitelist): + if signals[idx]: pair = _pair break else: