Skip to content

Commit

Permalink
Implement caching in the correct place
Browse files Browse the repository at this point in the history
  • Loading branch information
xmatthias committed Feb 22, 2020
1 parent f5b4a6d commit 97e6e5e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 9 deletions.
32 changes: 26 additions & 6 deletions freqtrade/freqtradebot.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from typing import Any, Dict, List, Optional, Tuple

import arrow
from cachetools import TTLCache
from requests.exceptions import RequestException

from freqtrade import __version__, constants, persistence
Expand Down Expand Up @@ -54,6 +55,9 @@ def __init__(self, config: Dict[str, Any]) -> None:

self._heartbeat_msg = 0

self._sell_rate_cache = TTLCache(maxsize=100, ttl=5)
self._buy_rate_cache = TTLCache(maxsize=100, ttl=5)

self.heartbeat_interval = self.config.get('internals', {}).get('heartbeat_interval', 60)

self.strategy: IStrategy = StrategyResolver.load_strategy(self.config)
Expand Down Expand Up @@ -234,11 +238,19 @@ def enter_positions(self) -> int:

return trades_created

def get_buy_rate(self, pair: str, refresh: bool, tick: Dict = None) -> float:
def get_buy_rate(self, pair: str, refresh: bool) -> float:
"""
Calculates bid target between current ask price and last price
:param pair: Pair to get rate for
:param refresh: allow cached data
:return: float: Price
"""
if not refresh:
rate = self._sell_rate_cache.get(pair)
# Check if cache has been invalidated
if rate:
return rate

config_bid_strategy = self.config.get('bid_strategy', {})
if 'use_order_book' in config_bid_strategy and\
config_bid_strategy.get('use_order_book', False):
Expand All @@ -251,18 +263,17 @@ def get_buy_rate(self, pair: str, refresh: bool, tick: Dict = None) -> float:
logger.info('...top %s order book buy rate %0.8f', order_book_top, order_book_rate)
used_rate = order_book_rate
else:
if not tick:
logger.info('Using Last Ask / Last Price')
ticker = self.exchange.fetch_ticker(pair)
else:
ticker = tick
logger.info('Using Last Ask / Last Price')
ticker = self.exchange.fetch_ticker(pair)
if ticker['ask'] < ticker['last']:
ticker_rate = ticker['ask']
else:
balance = self.config['bid_strategy']['ask_last_balance']
ticker_rate = ticker['ask'] + balance * (ticker['last'] - ticker['ask'])
used_rate = ticker_rate

self._buy_rate_cache[pair] = used_rate

return used_rate

def get_trade_stake_amount(self, pair: str) -> float:
Expand Down Expand Up @@ -621,8 +632,16 @@ def get_sell_rate(self, pair: str, refresh: bool) -> float:
The orderbook portion is only used for rpc messaging, which would otherwise fail
for BitMex (has no bid/ask in fetch_ticker)
or remain static in any other case since it's not updating.
:param pair: Pair to get rate for
:param refresh: allow cached data
:return: Bid rate
"""
if not refresh:
rate = self._sell_rate_cache.get(pair)
# Check if cache has been invalidated
if rate:
return rate

config_ask_strategy = self.config.get('ask_strategy', {})
if config_ask_strategy.get('use_order_book', False):
logger.debug('Using order book to get sell rate')
Expand All @@ -632,6 +651,7 @@ def get_sell_rate(self, pair: str, refresh: bool) -> float:

else:
rate = self.exchange.fetch_ticker(pair)['bid']
self._sell_rate_cache[pair] = rate
return rate

def handle_trade(self, trade: Trade) -> bool:
Expand Down
6 changes: 3 additions & 3 deletions tests/rpc/test_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'open_order': '(limit buy rem=0.00000000)'
} == results[0]

mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_sell_rate',
MagicMock(side_effect=DependencyException(f"Pair 'ETH/BTC' not available")))
results = rpc._rpc_trade_status()
assert isnan(results[0]['current_profit'])
Expand Down Expand Up @@ -132,7 +132,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
assert 'ETH/BTC' in result[0][1]
assert '-0.59% (-0.09)' == result[0][3]

mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_sell_rate',
MagicMock(side_effect=DependencyException(f"Pair 'ETH/BTC' not available")))
result, headers = rpc._rpc_status_table(default_conf['stake_currency'], 'USD')
assert 'instantly' == result[0][2]
Expand Down Expand Up @@ -256,7 +256,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
assert prec_satoshi(stats['best_rate'], 6.2)

# Test non-available pair
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_sell_rate',
MagicMock(side_effect=DependencyException(f"Pair 'ETH/BTC' not available")))
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
assert stats['trade_count'] == 2
Expand Down

0 comments on commit 97e6e5e

Please sign in to comment.