Merge pull request #576 from xmatthias/obj-ccxt-ticker
objectify ccxt fix backtesting and some tests
This commit is contained in:
commit
aba09b8107
@ -13,19 +13,19 @@
|
||||
"key": "your_exchange_key",
|
||||
"secret": "your_exchange_secret",
|
||||
"pair_whitelist": [
|
||||
"BTC_ETH",
|
||||
"BTC_LTC",
|
||||
"BTC_ETC",
|
||||
"BTC_DASH",
|
||||
"BTC_ZEC",
|
||||
"BTC_XLM",
|
||||
"BTC_NXT",
|
||||
"BTC_POWR",
|
||||
"BTC_ADA",
|
||||
"BTC_XMR"
|
||||
"ETH/BTC",
|
||||
"LTC/BTC",
|
||||
"ETC/BTC",
|
||||
"DASH/BTC",
|
||||
"ZEC/BTC",
|
||||
"XLM/BTC",
|
||||
"NXT/BTC",
|
||||
"POWR/BTC",
|
||||
"ADA/BTC",
|
||||
"XMR/BTC"
|
||||
],
|
||||
"pair_blacklist": [
|
||||
"BTC_DOGE"
|
||||
"DOGE/BTC"
|
||||
]
|
||||
},
|
||||
"experimental": {
|
||||
|
@ -21,19 +21,19 @@
|
||||
"key": "your_exchange_key",
|
||||
"secret": "your_exchange_secret",
|
||||
"pair_whitelist": [
|
||||
"BTC_ETH",
|
||||
"BTC_LTC",
|
||||
"BTC_ETC",
|
||||
"BTC_DASH",
|
||||
"BTC_ZEC",
|
||||
"BTC_XLM",
|
||||
"BTC_NXT",
|
||||
"BTC_POWR",
|
||||
"BTC_ADA",
|
||||
"BTC_XMR"
|
||||
"ETH/BTC",
|
||||
"LTC/BTC",
|
||||
"ETC/BTC",
|
||||
"DASH/BTC",
|
||||
"ZEC/BTC",
|
||||
"XLM/BTC",
|
||||
"NXT/BTC",
|
||||
"POWR/BTC",
|
||||
"ADA/BTC",
|
||||
"XMR/BTC"
|
||||
],
|
||||
"pair_blacklist": [
|
||||
"BTC_DOGE"
|
||||
"DOGE/BTC"
|
||||
]
|
||||
},
|
||||
"experimental": {
|
||||
|
@ -14,3 +14,11 @@ class OperationalException(BaseException):
|
||||
Requires manual intervention.
|
||||
This happens when an exchange returns an unexpected error during runtime.
|
||||
"""
|
||||
|
||||
|
||||
class NetworkException(BaseException):
|
||||
"""
|
||||
Network related error.
|
||||
This could happen when an exchange is congested, unavailable, or the user
|
||||
has networking problems. Usually resolves itself after a time.
|
||||
"""
|
||||
|
@ -51,6 +51,7 @@ class Analyze(object):
|
||||
unit='ms',
|
||||
utc=True,
|
||||
infer_datetime_format=True)
|
||||
|
||||
frame.sort_values('date', inplace=True)
|
||||
return frame
|
||||
|
||||
|
@ -6,11 +6,12 @@ import ccxt
|
||||
from random import randint
|
||||
from typing import List, Dict, Any, Optional
|
||||
from cachetools import cached, TTLCache
|
||||
from datetime import datetime
|
||||
|
||||
import arrow
|
||||
import requests
|
||||
|
||||
from freqtrade import OperationalException
|
||||
from freqtrade import OperationalException, NetworkException
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -180,14 +181,25 @@ def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict:
|
||||
|
||||
# @cached(TTLCache(maxsize=100, ttl=30))
|
||||
@retrier
|
||||
def get_ticker_history(pair: str, tick_interval) -> List[Dict]:
|
||||
def get_ticker_history(pair: str, tick_interval) -> List[List]:
|
||||
# TODO: tickers need to be in format 1m,5m
|
||||
# fetch_ohlcv returns an [[datetime,o,h,l,c,v]]
|
||||
if not _API.markets:
|
||||
_API.load_markets()
|
||||
ohlcv = _API.fetch_ohlcv(pair, str(tick_interval)+'m')
|
||||
if 'fetchOHLCV' not in _API.has or not _API.has['fetchOHLCV']:
|
||||
logger.warning('Exhange %s does not support fetching historical candlestick data.',
|
||||
_API.name)
|
||||
return []
|
||||
|
||||
return ohlcv
|
||||
try:
|
||||
ohlcv = _API.fetch_ohlcv(pair, timeframe=str(tick_interval)+"m")
|
||||
|
||||
return ohlcv
|
||||
except IndexError as e:
|
||||
logger.warning('Empty ticker history. Msg %s', str(e))
|
||||
except ccxt.NetworkError as e:
|
||||
logger.warning('Could not load ticker history due to networking error. Message: %s', str(e))
|
||||
except ccxt.BaseError as e:
|
||||
logger.warning('Could not fetch ticker data. Msg: %s', str(e))
|
||||
return []
|
||||
|
||||
|
||||
def cancel_order(order_id: str) -> None:
|
||||
@ -235,7 +247,7 @@ def get_fee_taker() -> float:
|
||||
|
||||
|
||||
def get_fee() -> float:
|
||||
return _API.fees['trading']
|
||||
return get_fee_taker()
|
||||
|
||||
|
||||
def get_wallet_health() -> List[Dict]:
|
||||
|
@ -72,3 +72,11 @@ def file_dump_json(filename, data) -> None:
|
||||
"""
|
||||
with open(filename, 'w') as fp:
|
||||
json.dump(data, fp, default=str)
|
||||
|
||||
|
||||
def format_ms_time(date: str) -> str:
|
||||
"""
|
||||
convert MS date to readable format.
|
||||
: epoch-string in ms
|
||||
"""
|
||||
return datetime.fromtimestamp(date/1000.0).strftime('%Y-%m-%dT%H:%M:%S')
|
||||
|
@ -35,7 +35,7 @@ def load_tickerdata_file(
|
||||
"""
|
||||
path = make_testdata_path(datadir)
|
||||
file = os.path.join(path, '{pair}-{ticker_interval}.json'.format(
|
||||
pair=pair,
|
||||
pair=pair.replace('/', '_'),
|
||||
ticker_interval=ticker_interval,
|
||||
))
|
||||
gzipfile = file + '.gz'
|
||||
@ -126,7 +126,7 @@ def download_backtesting_testdata(datadir: str, pair: str, interval: int = 5) ->
|
||||
interval
|
||||
)
|
||||
|
||||
filepair = pair.replace("-", "_")
|
||||
filepair = pair.replace("/", "_")
|
||||
filename = os.path.join(path, '{pair}-{interval}.json'.format(
|
||||
pair=filepair,
|
||||
interval=interval,
|
||||
@ -135,8 +135,8 @@ def download_backtesting_testdata(datadir: str, pair: str, interval: int = 5) ->
|
||||
if os.path.isfile(filename):
|
||||
with open(filename, "rt") as file:
|
||||
data = json.load(file)
|
||||
logger.debug("Current Start: %s", data[1]['T'])
|
||||
logger.debug("Current End: %s", data[-1:][0]['T'])
|
||||
logger.debug("Current Start: %s", misc.format_ms_time(data[1][0]))
|
||||
logger.debug("Current End: %s", misc.format_ms_time(data[-1:][0][0]))
|
||||
else:
|
||||
data = []
|
||||
logger.debug("Current Start: None")
|
||||
@ -146,9 +146,9 @@ def download_backtesting_testdata(datadir: str, pair: str, interval: int = 5) ->
|
||||
for row in new_data:
|
||||
if row not in data:
|
||||
data.append(row)
|
||||
logger.debug("New Start: %s", data[1]['T'])
|
||||
logger.debug("New End: %s", data[-1:][0]['T'])
|
||||
data = sorted(data, key=lambda data: data['T'])
|
||||
logger.debug("New Start: %s", misc.format_ms_time(data[0][0]))
|
||||
logger.debug("New End: %s", misc.format_ms_time(data[-1:][0][0]))
|
||||
data = sorted(data, key=lambda data: data[0])
|
||||
|
||||
misc.file_dump_json(filename, data)
|
||||
|
||||
|
@ -53,7 +53,10 @@ class Backtesting(object):
|
||||
self.tickerdata_to_dataframe = self.analyze.tickerdata_to_dataframe
|
||||
self.populate_buy_trend = self.analyze.populate_buy_trend
|
||||
self.populate_sell_trend = self.analyze.populate_sell_trend
|
||||
exchange.init({'key': '', 'secret': ''})
|
||||
# Reest keys for backtesting
|
||||
self.config['exchange']['key'] = ''
|
||||
self.config['exchange']['secret'] = ''
|
||||
exchange.init(self.config)
|
||||
|
||||
@staticmethod
|
||||
def get_timeframe(data: Dict[str, DataFrame]) -> Tuple[arrow.Arrow, arrow.Arrow]:
|
||||
|
@ -73,11 +73,11 @@ def default_conf():
|
||||
"key": "key",
|
||||
"secret": "secret",
|
||||
"pair_whitelist": [
|
||||
"BTC_ETH",
|
||||
"BTC_TKN",
|
||||
"BTC_TRST",
|
||||
"BTC_SWT",
|
||||
"BTC_BCC"
|
||||
"ETH/BTC",
|
||||
"TKN/BTC",
|
||||
"TRST/BTC",
|
||||
"SWT/BTC",
|
||||
"BCC/BTC"
|
||||
]
|
||||
},
|
||||
"telegram": {
|
||||
@ -128,32 +128,31 @@ def ticker_sell_down():
|
||||
|
||||
@pytest.fixture
|
||||
def health():
|
||||
return MagicMock(return_value=[{
|
||||
'Currency': 'BTC',
|
||||
'IsActive': True,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
}, {
|
||||
'Currency': 'ETH',
|
||||
'IsActive': True,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
}, {
|
||||
'Currency': 'TRST',
|
||||
'IsActive': True,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
}, {
|
||||
'Currency': 'SWT',
|
||||
'IsActive': True,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
}, {
|
||||
'Currency': 'BCC',
|
||||
'IsActive': False,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
}])
|
||||
return MagicMock(return_value={
|
||||
"ETH/BTC": {
|
||||
'base': 'ETH',
|
||||
'active': True,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
},
|
||||
"TRST/BTC": {
|
||||
'base': 'TRST',
|
||||
'active': True,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
},
|
||||
"SWT/BTC": {
|
||||
'base': 'SWT',
|
||||
'active': True,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
},
|
||||
"BCC/BTC": {
|
||||
'base': 'BCC',
|
||||
'active': False,
|
||||
'LastChecked': '2017-11-13T20:15:00.00',
|
||||
'Notice': None
|
||||
}})
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -175,7 +174,7 @@ def limit_buy_order_old():
|
||||
return {
|
||||
'id': 'mocked_limit_buy_old',
|
||||
'type': 'LIMIT_BUY',
|
||||
'pair': 'BTC_ETH',
|
||||
'pair': 'ETH/BTC',
|
||||
'opened': str(arrow.utcnow().shift(minutes=-601).datetime),
|
||||
'rate': 0.00001099,
|
||||
'amount': 90.99181073,
|
||||
@ -188,7 +187,7 @@ def limit_sell_order_old():
|
||||
return {
|
||||
'id': 'mocked_limit_sell_old',
|
||||
'type': 'LIMIT_SELL',
|
||||
'pair': 'BTC_ETH',
|
||||
'pair': 'ETH/BTC',
|
||||
'opened': str(arrow.utcnow().shift(minutes=-601).datetime),
|
||||
'rate': 0.00001099,
|
||||
'amount': 90.99181073,
|
||||
@ -201,7 +200,7 @@ def limit_buy_order_old_partial():
|
||||
return {
|
||||
'id': 'mocked_limit_buy_old_partial',
|
||||
'type': 'LIMIT_BUY',
|
||||
'pair': 'BTC_ETH',
|
||||
'pair': 'ETH/BTC',
|
||||
'opened': str(arrow.utcnow().shift(minutes=-601).datetime),
|
||||
'rate': 0.00001099,
|
||||
'amount': 90.99181073,
|
||||
@ -307,125 +306,149 @@ def get_market_summaries_data():
|
||||
8 entries. 4 BTC, 4 USTD
|
||||
:return: JSON market summaries
|
||||
"""
|
||||
return [
|
||||
{
|
||||
'Ask': 1.316e-05,
|
||||
'BaseVolume': 5.72599471,
|
||||
'Bid': 1.3e-05,
|
||||
'Created': '2014-04-14T00:00:00',
|
||||
'High': 1.414e-05,
|
||||
'Last': 1.298e-05,
|
||||
'Low': 1.282e-05,
|
||||
'MarketName': 'BTC-XWC',
|
||||
'OpenBuyOrders': 2000,
|
||||
'OpenSellOrders': 1484,
|
||||
'PrevDay': 1.376e-05,
|
||||
'TimeStamp': '2018-02-05T01:32:40.493',
|
||||
'Volume': 424041.21418375
|
||||
return {
|
||||
'XWC/BTC': {
|
||||
'symbol': 'XWC/BTC',
|
||||
'info': {
|
||||
'Ask': 1.316e-05,
|
||||
'BaseVolume': 5.72599471,
|
||||
'Bid': 1.3e-05,
|
||||
'Created': '2014-04-14T00:00:00',
|
||||
'High': 1.414e-05,
|
||||
'Last': 1.298e-05,
|
||||
'Low': 1.282e-05,
|
||||
'MarketName': 'BTC-XWC',
|
||||
'OpenBuyOrders': 2000,
|
||||
'OpenSellOrders': 1484,
|
||||
'PrevDay': 1.376e-05,
|
||||
'TimeStamp': '2018-02-05T01:32:40.493',
|
||||
'Volume': 424041.21418375
|
||||
}
|
||||
},
|
||||
{
|
||||
'Ask': 0.00627051,
|
||||
'BaseVolume': 93.23302388,
|
||||
'Bid': 0.00618192,
|
||||
'Created': '2016-10-20T04:48:30.387',
|
||||
'High': 0.00669897,
|
||||
'Last': 0.00618192,
|
||||
'Low': 0.006,
|
||||
'MarketName': 'BTC-XZC',
|
||||
'OpenBuyOrders': 343,
|
||||
'OpenSellOrders': 2037,
|
||||
'PrevDay': 0.00668229,
|
||||
'TimeStamp': '2018-02-05T01:32:43.383',
|
||||
'Volume': 14863.60730702
|
||||
'XZC/BTC': {
|
||||
'symbol': 'XZC/BTC',
|
||||
'info': {
|
||||
'Ask': 0.00627051,
|
||||
'BaseVolume': 93.23302388,
|
||||
'Bid': 0.00618192,
|
||||
'Created': '2016-10-20T04:48:30.387',
|
||||
'High': 0.00669897,
|
||||
'Last': 0.00618192,
|
||||
'Low': 0.006,
|
||||
'MarketName': 'BTC-XZC',
|
||||
'OpenBuyOrders': 343,
|
||||
'OpenSellOrders': 2037,
|
||||
'PrevDay': 0.00668229,
|
||||
'TimeStamp': '2018-02-05T01:32:43.383',
|
||||
'Volume': 14863.60730702
|
||||
}
|
||||
},
|
||||
{
|
||||
'Ask': 0.01137247,
|
||||
'BaseVolume': 383.55922657,
|
||||
'Bid': 0.01136006,
|
||||
'Created': '2016-11-15T20:29:59.73',
|
||||
'High': 0.012,
|
||||
'Last': 0.01137247,
|
||||
'Low': 0.01119883,
|
||||
'MarketName': 'BTC-ZCL',
|
||||
'OpenBuyOrders': 1332,
|
||||
'OpenSellOrders': 5317,
|
||||
'PrevDay': 0.01179603,
|
||||
'TimeStamp': '2018-02-05T01:32:42.773',
|
||||
'Volume': 33308.07358285
|
||||
'ZCL/BTC': {
|
||||
'symbol': 'ZCL/BTC',
|
||||
'info': {
|
||||
'Ask': 0.01137247,
|
||||
'BaseVolume': 383.55922657,
|
||||
'Bid': 0.01136006,
|
||||
'Created': '2016-11-15T20:29:59.73',
|
||||
'High': 0.012,
|
||||
'Last': 0.01137247,
|
||||
'Low': 0.01119883,
|
||||
'MarketName': 'BTC-ZCL',
|
||||
'OpenBuyOrders': 1332,
|
||||
'OpenSellOrders': 5317,
|
||||
'PrevDay': 0.01179603,
|
||||
'TimeStamp': '2018-02-05T01:32:42.773',
|
||||
'Volume': 33308.07358285
|
||||
}
|
||||
},
|
||||
{
|
||||
'Ask': 0.04155821,
|
||||
'BaseVolume': 274.75369074,
|
||||
'Bid': 0.04130002,
|
||||
'Created': '2016-10-28T17:13:10.833',
|
||||
'High': 0.04354429,
|
||||
'Last': 0.041585,
|
||||
'Low': 0.0413,
|
||||
'MarketName': 'BTC-ZEC',
|
||||
'OpenBuyOrders': 863,
|
||||
'OpenSellOrders': 5579,
|
||||
'PrevDay': 0.0429,
|
||||
'TimeStamp': '2018-02-05T01:32:43.21',
|
||||
'Volume': 6479.84033259
|
||||
'ZEC/BTC': {
|
||||
'symbol': 'ZEC/BTC',
|
||||
'info': {
|
||||
'Ask': 0.04155821,
|
||||
'BaseVolume': 274.75369074,
|
||||
'Bid': 0.04130002,
|
||||
'Created': '2016-10-28T17:13:10.833',
|
||||
'High': 0.04354429,
|
||||
'Last': 0.041585,
|
||||
'Low': 0.0413,
|
||||
'MarketName': 'BTC-ZEC',
|
||||
'OpenBuyOrders': 863,
|
||||
'OpenSellOrders': 5579,
|
||||
'PrevDay': 0.0429,
|
||||
'TimeStamp': '2018-02-05T01:32:43.21',
|
||||
'Volume': 6479.84033259
|
||||
}
|
||||
},
|
||||
{
|
||||
'Ask': 210.99999999,
|
||||
'BaseVolume': 615132.70989532,
|
||||
'Bid': 210.05503736,
|
||||
'Created': '2017-07-21T01:08:49.397',
|
||||
'High': 257.396,
|
||||
'Last': 211.0,
|
||||
'Low': 209.05333589,
|
||||
'MarketName': 'USDT-XMR',
|
||||
'OpenBuyOrders': 180,
|
||||
'OpenSellOrders': 1203,
|
||||
'PrevDay': 247.93528899,
|
||||
'TimeStamp': '2018-02-05T01:32:43.117',
|
||||
'Volume': 2688.17410793
|
||||
'XMR/USDT': {
|
||||
'symbol': 'XMR/USDT',
|
||||
'info': {
|
||||
'Ask': 210.99999999,
|
||||
'BaseVolume': 615132.70989532,
|
||||
'Bid': 210.05503736,
|
||||
'Created': '2017-07-21T01:08:49.397',
|
||||
'High': 257.396,
|
||||
'Last': 211.0,
|
||||
'Low': 209.05333589,
|
||||
'MarketName': 'USDT-XMR',
|
||||
'OpenBuyOrders': 180,
|
||||
'OpenSellOrders': 1203,
|
||||
'PrevDay': 247.93528899,
|
||||
'TimeStamp': '2018-02-05T01:32:43.117',
|
||||
'Volume': 2688.17410793
|
||||
}
|
||||
},
|
||||
{
|
||||
'Ask': 0.79589979,
|
||||
'BaseVolume': 9349557.01853031,
|
||||
'Bid': 0.789226,
|
||||
'Created': '2017-07-14T17:10:10.737',
|
||||
'High': 0.977,
|
||||
'Last': 0.79589979,
|
||||
'Low': 0.781,
|
||||
'MarketName': 'USDT-XRP',
|
||||
'OpenBuyOrders': 1075,
|
||||
'OpenSellOrders': 6508,
|
||||
'PrevDay': 0.93300218,
|
||||
'TimeStamp': '2018-02-05T01:32:42.383',
|
||||
'Volume': 10801663.00788851
|
||||
'XRP/USDT': {
|
||||
'symbol': 'XRP/USDT',
|
||||
'info': {
|
||||
'Ask': 0.79589979,
|
||||
'BaseVolume': 9349557.01853031,
|
||||
'Bid': 0.789226,
|
||||
'Created': '2017-07-14T17:10:10.737',
|
||||
'High': 0.977,
|
||||
'Last': 0.79589979,
|
||||
'Low': 0.781,
|
||||
'MarketName': 'USDT-XRP',
|
||||
'OpenBuyOrders': 1075,
|
||||
'OpenSellOrders': 6508,
|
||||
'PrevDay': 0.93300218,
|
||||
'TimeStamp': '2018-02-05T01:32:42.383',
|
||||
'Volume': 10801663.00788851
|
||||
}
|
||||
},
|
||||
{
|
||||
'Ask': 0.05154982,
|
||||
'BaseVolume': 2311087.71232136,
|
||||
'Bid': 0.05040107,
|
||||
'Created': '2017-12-29T19:29:18.357',
|
||||
'High': 0.06668561,
|
||||
'Last': 0.0508,
|
||||
'Low': 0.05006731,
|
||||
'MarketName': 'USDT-XVG',
|
||||
'OpenBuyOrders': 655,
|
||||
'OpenSellOrders': 5544,
|
||||
'PrevDay': 0.0627,
|
||||
'TimeStamp': '2018-02-05T01:32:41.507',
|
||||
'Volume': 40031424.2152716
|
||||
'XVG/USDT': {
|
||||
'symbol': 'XVG/USDT',
|
||||
'info': {
|
||||
'Ask': 0.05154982,
|
||||
'BaseVolume': 2311087.71232136,
|
||||
'Bid': 0.05040107,
|
||||
'Created': '2017-12-29T19:29:18.357',
|
||||
'High': 0.06668561,
|
||||
'Last': 0.0508,
|
||||
'Low': 0.05006731,
|
||||
'MarketName': 'USDT-XVG',
|
||||
'OpenBuyOrders': 655,
|
||||
'OpenSellOrders': 5544,
|
||||
'PrevDay': 0.0627,
|
||||
'TimeStamp': '2018-02-05T01:32:41.507',
|
||||
'Volume': 40031424.2152716
|
||||
}
|
||||
},
|
||||
{
|
||||
'Ask': 332.65500022,
|
||||
'BaseVolume': 562911.87455665,
|
||||
'Bid': 330.00000001,
|
||||
'Created': '2017-07-14T17:10:10.673',
|
||||
'High': 401.59999999,
|
||||
'Last': 332.65500019,
|
||||
'Low': 330.0,
|
||||
'MarketName': 'USDT-ZEC',
|
||||
'OpenBuyOrders': 161,
|
||||
'OpenSellOrders': 1731,
|
||||
'PrevDay': 391.42,
|
||||
'TimeStamp': '2018-02-05T01:32:42.947',
|
||||
'Volume': 1571.09647946
|
||||
'ZEC/USDT': {
|
||||
'symbol': 'ZEC/USDT',
|
||||
'info': {
|
||||
'Ask': 332.65500022,
|
||||
'BaseVolume': 562911.87455665,
|
||||
'Bid': 330.00000001,
|
||||
'Created': '2017-07-14T17:10:10.673',
|
||||
'High': 401.59999999,
|
||||
'Last': 332.65500019,
|
||||
'Low': 330.0,
|
||||
'MarketName': 'USDT-ZEC',
|
||||
'OpenBuyOrders': 161,
|
||||
'OpenSellOrders': 1731,
|
||||
'PrevDay': 391.42,
|
||||
'TimeStamp': '2018-02-05T01:32:42.947',
|
||||
'Volume': 1571.09647946
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ def test_rpc_trade_status(default_conf, ticker, mocker) -> None:
|
||||
result_message = [
|
||||
'*Trade ID:* `1`\n'
|
||||
'*Current Pair:* '
|
||||
'[BTC_ETH](https://www.bittrex.com/Market/Index?MarketName=BTC-ETH)\n'
|
||||
'[ETH/BTC](https://bittrex.com/Market/Index?MarketName=BTC-ETH)\n'
|
||||
'*Open Since:* `just now`\n'
|
||||
'*Amount:* `90.99181074`\n'
|
||||
'*Open Rate:* `0.00001099`\n'
|
||||
@ -70,7 +70,7 @@ def test_rpc_trade_status(default_conf, ticker, mocker) -> None:
|
||||
'*Open Order:* `(LIMIT_BUY rem=0.00000000)`'
|
||||
]
|
||||
assert result == result_message
|
||||
assert trade.find('[BTC_ETH]') >= 0
|
||||
assert trade.find('[ETH/BTC]') >= 0
|
||||
|
||||
|
||||
def test_rpc_status_table(default_conf, ticker, mocker) -> None:
|
||||
@ -102,7 +102,7 @@ def test_rpc_status_table(default_conf, ticker, mocker) -> None:
|
||||
freqtradebot.create_trade()
|
||||
(error, result) = rpc.rpc_status_table()
|
||||
assert 'just now' in result['Since'].all()
|
||||
assert 'BTC_ETH' in result['Pair'].all()
|
||||
assert 'ETH/BTC' in result['Pair'].all()
|
||||
assert '-0.59%' in result['Profit'].all()
|
||||
|
||||
|
||||
@ -214,7 +214,7 @@ def test_rpc_trade_statistics(
|
||||
assert stats['first_trade_date'] == 'just now'
|
||||
assert stats['latest_trade_date'] == 'just now'
|
||||
assert stats['avg_duration'] == '0:00:00'
|
||||
assert stats['best_pair'] == 'BTC_ETH'
|
||||
assert stats['best_pair'] == 'ETH/BTC'
|
||||
assert prec_satoshi(stats['best_rate'], 6.2)
|
||||
|
||||
|
||||
@ -274,7 +274,7 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, ticker_sell_u
|
||||
assert stats['first_trade_date'] == 'just now'
|
||||
assert stats['latest_trade_date'] == 'just now'
|
||||
assert stats['avg_duration'] == '0:00:00'
|
||||
assert stats['best_pair'] == 'BTC_ETH'
|
||||
assert stats['best_pair'] == 'ETH/BTC'
|
||||
assert prec_satoshi(stats['best_rate'], 6.2)
|
||||
|
||||
|
||||
@ -509,7 +509,7 @@ def test_performance_handle(default_conf, ticker, limit_buy_order,
|
||||
(error, res) = rpc.rpc_performance()
|
||||
assert not error
|
||||
assert len(res) == 1
|
||||
assert res[0]['pair'] == 'BTC_ETH'
|
||||
assert res[0]['pair'] == 'ETH/BTC'
|
||||
assert res[0]['count'] == 1
|
||||
assert prec_satoshi(res[0]['profit'], 6.2)
|
||||
|
||||
|
@ -248,7 +248,8 @@ def test_status(default_conf, update, mocker, ticker) -> None:
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.freqtradebot.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker
|
||||
get_ticker=ticker,
|
||||
get_pair_detail_url=MagicMock()
|
||||
)
|
||||
msg_mock = MagicMock()
|
||||
status_table = MagicMock()
|
||||
@ -319,7 +320,7 @@ def test_status_handle(default_conf, update, ticker, mocker) -> None:
|
||||
telegram._status(bot=MagicMock(), update=update)
|
||||
|
||||
assert msg_mock.call_count == 1
|
||||
assert '[BTC_ETH]' in msg_mock.call_args_list[0][0][0]
|
||||
assert '[ETH/BTC]' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_status_table_handle(default_conf, update, ticker, mocker) -> None:
|
||||
@ -369,7 +370,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker) -> None:
|
||||
fields = re.sub('[ ]+', ' ', line[2].strip()).split(' ')
|
||||
|
||||
assert int(fields[0]) == 1
|
||||
assert fields[1] == 'BTC_ETH'
|
||||
assert fields[1] == 'ETH/BTC'
|
||||
assert msg_mock.call_count == 1
|
||||
|
||||
|
||||
@ -387,7 +388,8 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order,
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.freqtradebot.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker
|
||||
get_ticker=ticker,
|
||||
get_pair_detail_url=MagicMock()
|
||||
)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
@ -541,7 +543,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up,
|
||||
assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
assert '*Best Performing:* `BTC_ETH: 6.20%`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*Best Performing:* `ETH/BTC: 6.20%`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
||||
def test_telegram_balance_handle(default_conf, update, mocker) -> None:
|
||||
@ -779,7 +781,7 @@ def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker)
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[BTC_ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001172' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'profit: 6.11%, 0.00006126' in rpc_mock.call_args_list[-1][0][0]
|
||||
@ -822,7 +824,7 @@ def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, m
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[BTC_ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001044' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'loss: -5.48%, -0.00005492' in rpc_mock.call_args_list[-1][0][0]
|
||||
@ -838,6 +840,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker) -> None:
|
||||
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=15000.0)
|
||||
rpc_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
|
||||
mocker.patch('freqtrade.exchange.get_pair_detail_url', MagicMock())
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.freqtradebot.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
@ -942,7 +945,7 @@ def test_performance_handle(default_conf, update, ticker, limit_buy_order,
|
||||
telegram._performance(bot=MagicMock(), update=update)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'Performance' in msg_mock.call_args_list[0][0][0]
|
||||
assert '<code>BTC_ETH\t6.20% (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||
assert '<code>ETH/BTC\t6.20% (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_performance_handle_invalid(default_conf, update, mocker) -> None:
|
||||
|
@ -12,77 +12,87 @@ def whitelist_conf():
|
||||
|
||||
config['stake_currency'] = 'BTC'
|
||||
config['exchange']['pair_whitelist'] = [
|
||||
'BTC_ETH',
|
||||
'BTC_TKN',
|
||||
'BTC_TRST',
|
||||
'BTC_SWT',
|
||||
'BTC_BCC'
|
||||
'ETH/BTC',
|
||||
'TKN/BTC',
|
||||
'TRST/BTC',
|
||||
'SWT/BTC',
|
||||
'BCC/BTC'
|
||||
]
|
||||
|
||||
config['exchange']['pair_blacklist'] = [
|
||||
'BTC_BLK'
|
||||
'BLK/BTC'
|
||||
]
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def get_market_summaries():
|
||||
return [{
|
||||
'MarketName': 'BTC-TKN',
|
||||
'High': 0.00000919,
|
||||
'Low': 0.00000820,
|
||||
'Volume': 74339.61396015,
|
||||
'Last': 0.00000820,
|
||||
'BaseVolume': 1664,
|
||||
'TimeStamp': '2014-07-09T07:19:30.15',
|
||||
'Bid': 0.00000820,
|
||||
'Ask': 0.00000831,
|
||||
'OpenBuyOrders': 15,
|
||||
'OpenSellOrders': 15,
|
||||
'PrevDay': 0.00000821,
|
||||
'Created': '2014-03-20T06:00:00',
|
||||
'DisplayMarketName': ''
|
||||
}, {
|
||||
'MarketName': 'BTC-ETH',
|
||||
'High': 0.00000072,
|
||||
'Low': 0.00000001,
|
||||
'Volume': 166340678.42280999,
|
||||
'Last': 0.00000005,
|
||||
'BaseVolume': 42,
|
||||
'TimeStamp': '2014-07-09T07:21:40.51',
|
||||
'Bid': 0.00000004,
|
||||
'Ask': 0.00000005,
|
||||
'OpenBuyOrders': 18,
|
||||
'OpenSellOrders': 18,
|
||||
'PrevDay': 0.00000002,
|
||||
'Created': '2014-05-30T07:57:49.637',
|
||||
'DisplayMarketName': ''
|
||||
}, {
|
||||
'MarketName': 'BTC-BLK',
|
||||
'High': 0.00000072,
|
||||
'Low': 0.00000001,
|
||||
'Volume': 166340678.42280999,
|
||||
'Last': 0.00000005,
|
||||
'BaseVolume': 3,
|
||||
'TimeStamp': '2014-07-09T07:21:40.51',
|
||||
'Bid': 0.00000004,
|
||||
'Ask': 0.00000005,
|
||||
'OpenBuyOrders': 18,
|
||||
'OpenSellOrders': 18,
|
||||
'PrevDay': 0.00000002,
|
||||
'Created': '2014-05-30T07:57:49.637',
|
||||
'DisplayMarketName': ''
|
||||
}]
|
||||
return {
|
||||
'TKN/BTC': {
|
||||
'symbol': 'TKN/BTC',
|
||||
'info': {
|
||||
'High': 0.00000919,
|
||||
'Low': 0.00000820,
|
||||
'Volume': 74339.61396015,
|
||||
'Last': 0.00000820,
|
||||
'BaseVolume': 1664,
|
||||
'TimeStamp': '2014-07-09T07:19:30.15',
|
||||
'Bid': 0.00000820,
|
||||
'Ask': 0.00000831,
|
||||
'OpenBuyOrders': 15,
|
||||
'OpenSellOrders': 15,
|
||||
'PrevDay': 0.00000821,
|
||||
'Created': '2014-03-20T06:00:00',
|
||||
'DisplayMarketName': ''
|
||||
}
|
||||
},
|
||||
'ETH/BTC': {
|
||||
'symbol': 'ETH/BTC',
|
||||
'info': {
|
||||
'High': 0.00000072,
|
||||
'Low': 0.00000001,
|
||||
'Volume': 166340678.42280999,
|
||||
'Last': 0.00000005,
|
||||
'BaseVolume': 42,
|
||||
'TimeStamp': '2014-07-09T07:21:40.51',
|
||||
'Bid': 0.00000004,
|
||||
'Ask': 0.00000005,
|
||||
'OpenBuyOrders': 18,
|
||||
'OpenSellOrders': 18,
|
||||
'PrevDay': 0.00000002,
|
||||
'Created': '2014-05-30T07:57:49.637',
|
||||
'DisplayMarketName': ''
|
||||
}
|
||||
},
|
||||
'BLK/BTC': {
|
||||
'symbol': 'BLK/BTC',
|
||||
'info': {
|
||||
'High': 0.00000072,
|
||||
'Low': 0.00000001,
|
||||
'Volume': 166340678.42280999,
|
||||
'Last': 0.00000005,
|
||||
'BaseVolume': 3,
|
||||
'TimeStamp': '2014-07-09T07:21:40.51',
|
||||
'Bid': 0.00000004,
|
||||
'Ask': 0.00000005,
|
||||
'OpenBuyOrders': 18,
|
||||
'OpenSellOrders': 18,
|
||||
'PrevDay': 0.00000002,
|
||||
'Created': '2014-05-30T07:57:49.637',
|
||||
'DisplayMarketName': ''
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
def get_health():
|
||||
return [{'Currency': 'ETH', 'IsActive': True},
|
||||
{'Currency': 'TKN', 'IsActive': True},
|
||||
{'Currency': 'BLK', 'IsActive': True}]
|
||||
return {
|
||||
'ETH/BTC': {'base': 'ETH', 'active': True},
|
||||
'TKN/BTC': {'base': 'TKN', 'active': True},
|
||||
'BLK/BTC': {'base': 'BLK', 'active': True}}
|
||||
|
||||
|
||||
def get_health_empty():
|
||||
return []
|
||||
return {}
|
||||
|
||||
|
||||
def test_refresh_market_pair_not_in_whitelist(mocker):
|
||||
@ -92,10 +102,10 @@ def test_refresh_market_pair_not_in_whitelist(mocker):
|
||||
|
||||
mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health)
|
||||
refreshedwhitelist = freqtradebot._refresh_whitelist(
|
||||
conf['exchange']['pair_whitelist'] + ['BTC_XXX']
|
||||
conf['exchange']['pair_whitelist'] + ['XXX/BTC']
|
||||
)
|
||||
# List ordered by BaseVolume
|
||||
whitelist = ['BTC_ETH', 'BTC_TKN']
|
||||
whitelist = ['ETH/BTC', 'TKN/BTC']
|
||||
# Ensure all except those in whitelist are removed
|
||||
assert whitelist == refreshedwhitelist
|
||||
|
||||
@ -108,7 +118,7 @@ def test_refresh_whitelist(mocker):
|
||||
refreshedwhitelist = freqtradebot._refresh_whitelist(conf['exchange']['pair_whitelist'])
|
||||
|
||||
# List ordered by BaseVolume
|
||||
whitelist = ['BTC_ETH', 'BTC_TKN']
|
||||
whitelist = ['ETH/BTC', 'TKN/BTC']
|
||||
# Ensure all except those in whitelist are removed
|
||||
assert whitelist == refreshedwhitelist
|
||||
|
||||
@ -123,7 +133,7 @@ def test_refresh_whitelist_dynamic(mocker):
|
||||
)
|
||||
|
||||
# argument: use the whitelist dynamically by exchange-volume
|
||||
whitelist = ['BTC_TKN', 'BTC_ETH']
|
||||
whitelist = ['TKN/BTC', 'ETH/BTC']
|
||||
|
||||
refreshedwhitelist = freqtradebot._refresh_whitelist(
|
||||
freqtradebot._gen_pair_whitelist(conf['stake_currency'])
|
||||
|
@ -17,7 +17,6 @@ import requests
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
from freqtrade import DependencyException, OperationalException
|
||||
from freqtrade.exchange import Exchanges
|
||||
from freqtrade.freqtradebot import FreqtradeBot
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.state import State
|
||||
@ -216,15 +215,15 @@ def test_gen_pair_whitelist(mocker, default_conf, get_market_summaries_data) ->
|
||||
|
||||
# Test to retrieved BTC sorted on BaseVolume
|
||||
whitelist = freqtrade._gen_pair_whitelist(base_currency='BTC')
|
||||
assert whitelist == ['BTC_ZCL', 'BTC_ZEC', 'BTC_XZC', 'BTC_XWC']
|
||||
assert whitelist == ['ZCL/BTC', 'ZEC/BTC', 'XZC/BTC', 'XWC/BTC']
|
||||
|
||||
# Test to retrieved BTC sorted on OpenBuyOrders
|
||||
whitelist = freqtrade._gen_pair_whitelist(base_currency='BTC', key='OpenBuyOrders')
|
||||
assert whitelist == ['BTC_XWC', 'BTC_ZCL', 'BTC_ZEC', 'BTC_XZC']
|
||||
assert whitelist == ['XWC/BTC', 'ZCL/BTC', 'ZEC/BTC', 'XZC/BTC']
|
||||
|
||||
# Test with USDT sorted on BaseVolume
|
||||
whitelist = freqtrade._gen_pair_whitelist(base_currency='USDT')
|
||||
assert whitelist == ['USDT_XRP', 'USDT_XVG', 'USDT_XMR', 'USDT_ZEC']
|
||||
assert whitelist == ['XRP/USDT', 'XVG/USDT', 'XMR/USDT', 'ZEC/USDT']
|
||||
|
||||
# Test with ETH (our fixture does not have ETH, but Bittrex returns them)
|
||||
whitelist = freqtrade._gen_pair_whitelist(base_currency='ETH')
|
||||
@ -263,7 +262,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker) -> None:
|
||||
assert trade.stake_amount == 0.001
|
||||
assert trade.is_open
|
||||
assert trade.open_date is not None
|
||||
assert trade.exchange == Exchanges.BITTREX.name
|
||||
assert trade.exchange == 'BITTREX'
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
trade.update(limit_buy_order)
|
||||
@ -333,8 +332,8 @@ def test_create_trade_no_pairs(default_conf, ticker, mocker) -> None:
|
||||
)
|
||||
|
||||
conf = deepcopy(default_conf)
|
||||
conf['exchange']['pair_whitelist'] = ["BTC_ETH"]
|
||||
conf['exchange']['pair_blacklist'] = ["BTC_ETH"]
|
||||
conf['exchange']['pair_whitelist'] = ["ETH/BTC"]
|
||||
conf['exchange']['pair_blacklist'] = ["ETH/BTC"]
|
||||
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
|
||||
|
||||
freqtrade.create_trade()
|
||||
@ -358,8 +357,8 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker) ->
|
||||
)
|
||||
|
||||
conf = deepcopy(default_conf)
|
||||
conf['exchange']['pair_whitelist'] = ["BTC_ETH"]
|
||||
conf['exchange']['pair_blacklist'] = ["BTC_ETH"]
|
||||
conf['exchange']['pair_whitelist'] = ["ETH/BTC"]
|
||||
conf['exchange']['pair_blacklist'] = ["ETH/BTC"]
|
||||
freqtrade = FreqtradeBot(conf, create_engine('sqlite://'))
|
||||
|
||||
freqtrade.create_trade()
|
||||
@ -425,7 +424,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order,
|
||||
assert trade.stake_amount == default_conf['stake_amount']
|
||||
assert trade.is_open
|
||||
assert trade.open_date is not None
|
||||
assert trade.exchange == Exchanges.BITTREX.name
|
||||
assert trade.exchange == "BITTREX"
|
||||
assert trade.open_rate == 0.00001099
|
||||
assert trade.amount == 90.99181073703367
|
||||
|
||||
@ -793,7 +792,7 @@ def test_check_handle_timedout_buy(default_conf, ticker, limit_buy_order_old, mo
|
||||
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
|
||||
|
||||
trade_buy = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
open_rate=0.00001099,
|
||||
exchange='BITTREX',
|
||||
open_order_id='123456789',
|
||||
@ -832,7 +831,7 @@ def test_check_handle_timedout_sell(default_conf, ticker, limit_sell_order_old,
|
||||
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
|
||||
|
||||
trade_sell = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
open_rate=0.00001099,
|
||||
exchange='BITTREX',
|
||||
open_order_id='123456789',
|
||||
@ -871,7 +870,7 @@ def test_check_handle_timedout_partial(default_conf, ticker, limit_buy_order_old
|
||||
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
|
||||
|
||||
trade_buy = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
open_rate=0.00001099,
|
||||
exchange='BITTREX',
|
||||
open_order_id='123456789',
|
||||
@ -918,7 +917,7 @@ def test_check_handle_timedout_exception(default_conf, ticker, mocker, caplog) -
|
||||
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
|
||||
|
||||
trade_buy = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
open_rate=0.00001099,
|
||||
exchange='BITTREX',
|
||||
open_order_id='123456789',
|
||||
@ -931,7 +930,7 @@ def test_check_handle_timedout_exception(default_conf, ticker, mocker, caplog) -
|
||||
|
||||
Trade.session.add(trade_buy)
|
||||
regexp = re.compile(
|
||||
'Cannot query order for Trade(id=1, pair=BTC_ETH, amount=90.99181073, '
|
||||
'Cannot query order for Trade(id=1, pair=ETH/BTC, amount=90.99181073, '
|
||||
'open_rate=0.00001099, open_since=10 hours ago) due to Traceback (most '
|
||||
'recent call last):\n.*'
|
||||
)
|
||||
@ -1024,7 +1023,7 @@ def test_execute_sell_up(default_conf, ticker, ticker_sell_up, mocker) -> None:
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[BTC_ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'Profit' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001172' in rpc_mock.call_args_list[-1][0][0]
|
||||
@ -1064,7 +1063,7 @@ def test_execute_sell_down(default_conf, ticker, ticker_sell_down, mocker) -> No
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[BTC_ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001044' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'loss: -5.48%, -0.00005492' in rpc_mock.call_args_list[-1][0][0]
|
||||
@ -1103,7 +1102,7 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, ticker_sell_up,
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[BTC_ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'Amount' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001172' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '(profit: 6.11%, 0.00006126)' in rpc_mock.call_args_list[-1][0][0]
|
||||
@ -1143,7 +1142,7 @@ def test_execute_sell_without_conf_sell_down(default_conf, ticker,
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
assert 'Selling' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[BTC_ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '[ETH/BTC]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001044' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'loss: -5.48%, -0.00005492' in rpc_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
@ -4,7 +4,7 @@ import os
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
from freqtrade.exchange import Exchanges
|
||||
from freqtrade import exchange
|
||||
from freqtrade.persistence import Trade, init, clean_dry_run_db
|
||||
|
||||
|
||||
@ -122,7 +122,7 @@ def test_update_with_bittrex(limit_buy_order, limit_sell_order):
|
||||
pair='BTC_ETH',
|
||||
stake_amount=0.001,
|
||||
fee=0.0025,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
assert trade.open_order_id is None
|
||||
assert trade.open_rate is None
|
||||
@ -146,10 +146,10 @@ def test_update_with_bittrex(limit_buy_order, limit_sell_order):
|
||||
|
||||
def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order):
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
fee=0.0025,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
|
||||
trade.open_order_id = 'something'
|
||||
@ -168,10 +168,10 @@ def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order):
|
||||
|
||||
def test_calc_close_trade_price_exception(limit_buy_order):
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
fee=0.0025,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
|
||||
trade.open_order_id = 'something'
|
||||
@ -181,10 +181,10 @@ def test_calc_close_trade_price_exception(limit_buy_order):
|
||||
|
||||
def test_update_open_order(limit_buy_order):
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=1.00,
|
||||
fee=0.1,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
|
||||
assert trade.open_order_id is None
|
||||
@ -203,10 +203,10 @@ def test_update_open_order(limit_buy_order):
|
||||
|
||||
def test_update_invalid_order(limit_buy_order):
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=1.00,
|
||||
fee=0.1,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
limit_buy_order['type'] = 'invalid'
|
||||
with pytest.raises(ValueError, match=r'Unknown order type'):
|
||||
@ -215,10 +215,10 @@ def test_update_invalid_order(limit_buy_order):
|
||||
|
||||
def test_calc_open_trade_price(limit_buy_order):
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
fee=0.0025,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
trade.open_order_id = 'open_trade'
|
||||
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||
@ -232,10 +232,10 @@ def test_calc_open_trade_price(limit_buy_order):
|
||||
|
||||
def test_calc_close_trade_price(limit_buy_order, limit_sell_order):
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
fee=0.0025,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
trade.open_order_id = 'close_trade'
|
||||
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||
@ -253,10 +253,10 @@ def test_calc_close_trade_price(limit_buy_order, limit_sell_order):
|
||||
|
||||
def test_calc_profit(limit_buy_order, limit_sell_order):
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
fee=0.0025,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
trade.open_order_id = 'profit_percent'
|
||||
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||
@ -283,10 +283,10 @@ def test_calc_profit(limit_buy_order, limit_sell_order):
|
||||
|
||||
def test_calc_profit_percent(limit_buy_order, limit_sell_order):
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
fee=0.0025,
|
||||
exchange=Exchanges.BITTREX,
|
||||
exchange='bittrex',
|
||||
)
|
||||
trade.open_order_id = 'profit_percent'
|
||||
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||
@ -310,35 +310,35 @@ def test_clean_dry_run_db(default_conf):
|
||||
|
||||
# Simulate dry_run entries
|
||||
trade = Trade(
|
||||
pair='BTC_ETH',
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
amount=123.0,
|
||||
fee=0.0025,
|
||||
open_rate=0.123,
|
||||
exchange='BITTREX',
|
||||
exchange='bittrex',
|
||||
open_order_id='dry_run_buy_12345'
|
||||
)
|
||||
Trade.session.add(trade)
|
||||
|
||||
trade = Trade(
|
||||
pair='BTC_ETC',
|
||||
pair='ETC/BTC',
|
||||
stake_amount=0.001,
|
||||
amount=123.0,
|
||||
fee=0.0025,
|
||||
open_rate=0.123,
|
||||
exchange='BITTREX',
|
||||
exchange='bittrex',
|
||||
open_order_id='dry_run_sell_12345'
|
||||
)
|
||||
Trade.session.add(trade)
|
||||
|
||||
# Simulate prod entry
|
||||
trade = Trade(
|
||||
pair='BTC_ETC',
|
||||
pair='ETC/BTC',
|
||||
stake_amount=0.001,
|
||||
amount=123.0,
|
||||
fee=0.0025,
|
||||
open_rate=0.123,
|
||||
exchange='BITTREX',
|
||||
exchange='bittrex',
|
||||
open_order_id='prod_buy_12345'
|
||||
)
|
||||
Trade.session.add(trade)
|
||||
|
Loading…
Reference in New Issue
Block a user