Merge branch 'develop' into mac_install_talib
This commit is contained in:
commit
346e155dd9
@ -20,8 +20,8 @@ We recommend you start by taking a look at `hyperopt.py` file located in [freqtr
|
||||
|
||||
### Configure your Guards and Triggers
|
||||
There are two places you need to change to add a new buy strategy for testing:
|
||||
- Inside [populate_buy_trend()](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/optimize/hyperopt.py#L278-L294).
|
||||
- Inside [hyperopt_space()](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/optimize/hyperopt.py#L218-L229)
|
||||
- Inside [populate_buy_trend()](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/optimize/hyperopt.py#L231-L264).
|
||||
- Inside [hyperopt_space()](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/optimize/hyperopt.py#L213-L224)
|
||||
and the associated methods `indicator_space`, `roi_space`, `stoploss_space`.
|
||||
|
||||
There you have two different type of indicators: 1. `guards` and 2. `triggers`.
|
||||
|
@ -4,7 +4,7 @@ This module contains the class to persist trades into SQLite
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from decimal import Decimal, getcontext
|
||||
from decimal import Decimal
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import arrow
|
||||
@ -241,7 +241,6 @@ class Trade(_DECL_BASE):
|
||||
|
||||
logger.info('Updating trade (id=%d) ...', self.id)
|
||||
|
||||
getcontext().prec = 8 # Bittrex do not go above 8 decimal
|
||||
if order_type == 'limit' and order['side'] == 'buy':
|
||||
# Update open rate and actual amount
|
||||
self.open_rate = Decimal(order['price'])
|
||||
@ -278,7 +277,6 @@ class Trade(_DECL_BASE):
|
||||
If rate is not set self.fee will be used
|
||||
:return: Price in BTC of the open trade
|
||||
"""
|
||||
getcontext().prec = 8
|
||||
|
||||
buy_trade = (Decimal(self.amount) * Decimal(self.open_rate))
|
||||
fees = buy_trade * Decimal(fee or self.fee_open)
|
||||
@ -296,7 +294,6 @@ class Trade(_DECL_BASE):
|
||||
If rate is not set self.close_rate will be used
|
||||
:return: Price in BTC of the open trade
|
||||
"""
|
||||
getcontext().prec = 8
|
||||
|
||||
if rate is None and not self.close_rate:
|
||||
return 0.0
|
||||
@ -336,7 +333,6 @@ class Trade(_DECL_BASE):
|
||||
:param fee: fee to use on the close rate (optional).
|
||||
:return: profit in percentage as float
|
||||
"""
|
||||
getcontext().prec = 8
|
||||
|
||||
open_trade_price = self.calc_open_trade_price()
|
||||
close_trade_price = self.calc_close_trade_price(
|
||||
|
@ -84,9 +84,7 @@ class RPC(object):
|
||||
"""
|
||||
# Fetch open trade
|
||||
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
|
||||
if self._freqtrade.state != State.RUNNING:
|
||||
raise RPCException('trader is not running')
|
||||
elif not trades:
|
||||
if not trades:
|
||||
raise RPCException('no active trade')
|
||||
else:
|
||||
results = []
|
||||
@ -118,9 +116,7 @@ class RPC(object):
|
||||
|
||||
def _rpc_status_table(self) -> DataFrame:
|
||||
trades = Trade.query.filter(Trade.is_open.is_(True)).all()
|
||||
if self._freqtrade.state != State.RUNNING:
|
||||
raise RPCException('trader is not running')
|
||||
elif not trades:
|
||||
if not trades:
|
||||
raise RPCException('no active order')
|
||||
else:
|
||||
trades_list = []
|
||||
@ -385,8 +381,6 @@ class RPC(object):
|
||||
Handler for performance.
|
||||
Shows a performance statistic from finished trades
|
||||
"""
|
||||
if self._freqtrade.state != State.RUNNING:
|
||||
raise RPCException('trader is not running')
|
||||
|
||||
pair_rates = Trade.session.query(Trade.pair,
|
||||
sql.func.sum(Trade.close_profit).label('profit_sum'),
|
||||
|
@ -307,11 +307,14 @@ class Telegram(RPC):
|
||||
result = self._rpc_balance(self._config.get('fiat_display_currency', ''))
|
||||
output = ''
|
||||
for currency in result['currencies']:
|
||||
output += "*{currency}:*\n" \
|
||||
"\t`Available: {available: .8f}`\n" \
|
||||
"\t`Balance: {balance: .8f}`\n" \
|
||||
"\t`Pending: {pending: .8f}`\n" \
|
||||
"\t`Est. BTC: {est_btc: .8f}`\n".format(**currency)
|
||||
if currency['est_btc'] > 0.0001:
|
||||
output += "*{currency}:*\n" \
|
||||
"\t`Available: {available: .8f}`\n" \
|
||||
"\t`Balance: {balance: .8f}`\n" \
|
||||
"\t`Pending: {pending: .8f}`\n" \
|
||||
"\t`Est. BTC: {est_btc: .8f}`\n".format(**currency)
|
||||
else:
|
||||
output += "*{currency}:* not showing <1$ amount \n".format(**currency)
|
||||
|
||||
output += "\n*Estimated Value*:\n" \
|
||||
"\t`BTC: {total: .8f}`\n" \
|
||||
|
@ -534,7 +534,7 @@ def test_backtest(default_conf, fee, mocker) -> None:
|
||||
|
||||
expected = pd.DataFrame(
|
||||
{'pair': [pair, pair],
|
||||
'profit_percent': [0.00029975, 0.00056708],
|
||||
'profit_percent': [0.00029977, 0.00056716],
|
||||
'profit_abs': [1.49e-06, 7.6e-07],
|
||||
'open_time': [Arrow(2018, 1, 29, 18, 40, 0).datetime,
|
||||
Arrow(2018, 1, 30, 3, 30, 0).datetime],
|
||||
|
@ -40,10 +40,6 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:
|
||||
patch_get_signal(freqtradebot, (True, False))
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
freqtradebot.state = State.STOPPED
|
||||
with pytest.raises(RPCException, match=r'.*trader is not running*'):
|
||||
rpc._rpc_trade_status()
|
||||
|
||||
freqtradebot.state = State.RUNNING
|
||||
with pytest.raises(RPCException, match=r'.*no active trade*'):
|
||||
rpc._rpc_trade_status()
|
||||
@ -81,10 +77,6 @@ def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
|
||||
patch_get_signal(freqtradebot, (True, False))
|
||||
rpc = RPC(freqtradebot)
|
||||
|
||||
freqtradebot.state = State.STOPPED
|
||||
with pytest.raises(RPCException, match=r'.*trader is not running*'):
|
||||
rpc._rpc_status_table()
|
||||
|
||||
freqtradebot.state = State.RUNNING
|
||||
with pytest.raises(RPCException, match=r'.*no active order*'):
|
||||
rpc._rpc_status_table()
|
||||
|
@ -250,9 +250,10 @@ def test_status_handle(default_conf, update, ticker, fee, markets, mocker) -> No
|
||||
telegram = Telegram(freqtradebot)
|
||||
|
||||
freqtradebot.state = State.STOPPED
|
||||
# Status is also enabled when stopped
|
||||
telegram._status(bot=MagicMock(), update=update)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'trader is not running' in msg_mock.call_args_list[0][0][0]
|
||||
assert 'no active trade' in msg_mock.call_args_list[0][0][0]
|
||||
msg_mock.reset_mock()
|
||||
|
||||
freqtradebot.state = State.RUNNING
|
||||
@ -295,9 +296,10 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
|
||||
telegram = Telegram(freqtradebot)
|
||||
|
||||
freqtradebot.state = State.STOPPED
|
||||
# Status table is also enabled when stopped
|
||||
telegram._status_table(bot=MagicMock(), update=update)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'trader is not running' in msg_mock.call_args_list[0][0][0]
|
||||
assert 'no active order' in msg_mock.call_args_list[0][0][0]
|
||||
msg_mock.reset_mock()
|
||||
|
||||
freqtradebot.state = State.RUNNING
|
||||
@ -507,7 +509,12 @@ def test_telegram_balance_handle(default_conf, update, mocker) -> None:
|
||||
'total': 10.0,
|
||||
'free': 10.0,
|
||||
'used': 0.0
|
||||
}
|
||||
},
|
||||
'XRP': {
|
||||
'total': 1.0,
|
||||
'free': 1.0,
|
||||
'used': 0.0
|
||||
}
|
||||
}
|
||||
|
||||
def mock_ticker(symbol, refresh):
|
||||
@ -517,7 +524,12 @@ def test_telegram_balance_handle(default_conf, update, mocker) -> None:
|
||||
'ask': 10000.00,
|
||||
'last': 10000.00,
|
||||
}
|
||||
|
||||
elif symbol == 'XRP/BTC':
|
||||
return {
|
||||
'bid': 0.00001,
|
||||
'ask': 0.00001,
|
||||
'last': 0.00001,
|
||||
}
|
||||
return {
|
||||
'bid': 0.1,
|
||||
'ask': 0.1,
|
||||
@ -548,7 +560,8 @@ def test_telegram_balance_handle(default_conf, update, mocker) -> None:
|
||||
assert '*USDT:*' in result
|
||||
assert 'Balance:' in result
|
||||
assert 'Est. BTC:' in result
|
||||
assert 'BTC: 14.00000000' in result
|
||||
assert 'BTC: 12.00000000' in result
|
||||
assert '*XRP:* not showing <1$ amount' in result
|
||||
|
||||
|
||||
def test_balance_handle_empty_response(default_conf, update, mocker) -> None:
|
||||
@ -712,7 +725,7 @@ def test_forcesell_handle(default_conf, update, ticker, fee,
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.172e-05,
|
||||
'profit_amount': 6.126e-05,
|
||||
'profit_percent': 0.06110514,
|
||||
'profit_percent': 0.0611052,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
} == last_msg
|
||||
@ -765,7 +778,7 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee,
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.044e-05,
|
||||
'profit_amount': -5.492e-05,
|
||||
'profit_percent': -0.05478343,
|
||||
'profit_percent': -0.05478342,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
} == last_msg
|
||||
@ -810,7 +823,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.098e-05,
|
||||
'profit_amount': -5.91e-06,
|
||||
'profit_percent': -0.00589292,
|
||||
'profit_percent': -0.00589291,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
} == msg
|
||||
@ -895,26 +908,6 @@ def test_performance_handle(default_conf, update, ticker, fee,
|
||||
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:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.telegram.Telegram',
|
||||
_init=MagicMock(),
|
||||
_send_msg=msg_mock
|
||||
)
|
||||
freqtradebot = FreqtradeBot(default_conf)
|
||||
patch_get_signal(freqtradebot, (True, False))
|
||||
telegram = Telegram(freqtradebot)
|
||||
|
||||
# Trader is not running
|
||||
freqtradebot.state = State.STOPPED
|
||||
telegram._performance(bot=MagicMock(), update=update)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'not running' in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
|
||||
def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> None:
|
||||
patch_coinmarketcap(mocker)
|
||||
patch_exchange(mocker)
|
||||
|
@ -167,11 +167,6 @@ def test_gen_pair_whitelist_not_supported(mocker, default_conf, tickers) -> None
|
||||
freqtrade._gen_pair_whitelist(base_currency='BTC')
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="Test not implemented")
|
||||
def test_refresh_whitelist() -> None:
|
||||
pass
|
||||
|
||||
|
||||
def test_get_trade_stake_amount(default_conf, ticker, limit_buy_order, fee, mocker) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
@ -804,7 +799,7 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order,
|
||||
trade.update(limit_sell_order)
|
||||
|
||||
assert trade.close_rate == 0.00001173
|
||||
assert trade.close_profit == 0.06201057
|
||||
assert trade.close_profit == 0.06201058
|
||||
assert trade.calc_profit() == 0.00006217
|
||||
assert trade.close_date is not None
|
||||
|
||||
@ -1231,7 +1226,7 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, markets, moc
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.172e-05,
|
||||
'profit_amount': 6.126e-05,
|
||||
'profit_percent': 0.06110514,
|
||||
'profit_percent': 0.0611052,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
} == last_msg
|
||||
@ -1277,7 +1272,7 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, markets,
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.044e-05,
|
||||
'profit_amount': -5.492e-05,
|
||||
'profit_percent': -0.05478343,
|
||||
'profit_percent': -0.05478342,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
} == last_msg
|
||||
@ -1324,7 +1319,7 @@ def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee,
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.172e-05,
|
||||
'profit_amount': 6.126e-05,
|
||||
'profit_percent': 0.06110514,
|
||||
'profit_percent': 0.0611052,
|
||||
} == last_msg
|
||||
|
||||
|
||||
@ -1370,7 +1365,7 @@ def test_execute_sell_without_conf_sell_down(default_conf, ticker, fee,
|
||||
'open_rate': 1.099e-05,
|
||||
'current_rate': 1.044e-05,
|
||||
'profit_amount': -5.492e-05,
|
||||
'profit_percent': -0.05478343,
|
||||
'profit_percent': -0.05478342,
|
||||
} == last_msg
|
||||
|
||||
|
||||
|
@ -113,7 +113,7 @@ def test_update_with_bittrex(limit_buy_order, limit_sell_order, fee):
|
||||
trade.update(limit_sell_order)
|
||||
assert trade.open_order_id is None
|
||||
assert trade.close_rate == 0.00001173
|
||||
assert trade.close_profit == 0.06201057
|
||||
assert trade.close_profit == 0.06201058
|
||||
assert trade.close_date is not None
|
||||
|
||||
|
||||
@ -129,16 +129,16 @@ def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order, fee):
|
||||
|
||||
trade.open_order_id = 'something'
|
||||
trade.update(limit_buy_order)
|
||||
assert trade.calc_open_trade_price() == 0.001002500
|
||||
assert trade.calc_open_trade_price() == 0.0010024999999225068
|
||||
|
||||
trade.update(limit_sell_order)
|
||||
assert trade.calc_close_trade_price() == 0.0010646656
|
||||
assert trade.calc_close_trade_price() == 0.0010646656050132426
|
||||
|
||||
# Profit in BTC
|
||||
assert trade.calc_profit() == 0.00006217
|
||||
|
||||
# Profit in percent
|
||||
assert trade.calc_profit_percent() == 0.06201057
|
||||
assert trade.calc_profit_percent() == 0.06201058
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
@ -207,10 +207,10 @@ def test_calc_open_trade_price(limit_buy_order, fee):
|
||||
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||
|
||||
# Get the open rate price with the standard fee rate
|
||||
assert trade.calc_open_trade_price() == 0.001002500
|
||||
assert trade.calc_open_trade_price() == 0.0010024999999225068
|
||||
|
||||
# Get the open rate price with a custom fee rate
|
||||
assert trade.calc_open_trade_price(fee=0.003) == 0.001003000
|
||||
assert trade.calc_open_trade_price(fee=0.003) == 0.001002999999922468
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
@ -226,14 +226,14 @@ def test_calc_close_trade_price(limit_buy_order, limit_sell_order, fee):
|
||||
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||
|
||||
# Get the close rate price with a custom close rate and a regular fee rate
|
||||
assert trade.calc_close_trade_price(rate=0.00001234) == 0.0011200318
|
||||
assert trade.calc_close_trade_price(rate=0.00001234) == 0.0011200318470471794
|
||||
|
||||
# Get the close rate price with a custom close rate and a custom fee rate
|
||||
assert trade.calc_close_trade_price(rate=0.00001234, fee=0.003) == 0.0011194704
|
||||
assert trade.calc_close_trade_price(rate=0.00001234, fee=0.003) == 0.0011194704275749754
|
||||
|
||||
# Test when we apply a Sell order, and ask price with a custom fee rate
|
||||
trade.update(limit_sell_order)
|
||||
assert trade.calc_close_trade_price(fee=0.005) == 0.0010619972
|
||||
assert trade.calc_close_trade_price(fee=0.005) == 0.0010619972701635854
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
@ -281,17 +281,17 @@ def test_calc_profit_percent(limit_buy_order, limit_sell_order, fee):
|
||||
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||
|
||||
# Get percent of profit with a custom rate (Higher than open rate)
|
||||
assert trade.calc_profit_percent(rate=0.00001234) == 0.1172387
|
||||
assert trade.calc_profit_percent(rate=0.00001234) == 0.11723875
|
||||
|
||||
# Get percent of profit with a custom rate (Lower than open rate)
|
||||
assert trade.calc_profit_percent(rate=0.00000123) == -0.88863827
|
||||
assert trade.calc_profit_percent(rate=0.00000123) == -0.88863828
|
||||
|
||||
# Test when we apply a Sell order. Sell higher than open rate @ 0.00001173
|
||||
trade.update(limit_sell_order)
|
||||
assert trade.calc_profit_percent() == 0.06201057
|
||||
assert trade.calc_profit_percent() == 0.06201058
|
||||
|
||||
# Test with a custom fee rate on the close trade
|
||||
assert trade.calc_profit_percent(fee=0.003) == 0.0614782
|
||||
assert trade.calc_profit_percent(fee=0.003) == 0.06147824
|
||||
|
||||
|
||||
def test_clean_dry_run_db(default_conf, fee):
|
||||
|
@ -1,18 +1,18 @@
|
||||
ccxt==1.17.375
|
||||
ccxt==1.17.402
|
||||
SQLAlchemy==1.2.12
|
||||
python-telegram-bot==11.1.0
|
||||
arrow==0.12.1
|
||||
cachetools==2.1.0
|
||||
requests==2.19.1
|
||||
urllib3==1.23
|
||||
requests==2.20.0
|
||||
urllib3==1.24
|
||||
wrapt==1.10.11
|
||||
pandas==0.23.4
|
||||
scikit-learn==0.20.0
|
||||
scipy==1.1.0
|
||||
jsonschema==2.6.0
|
||||
numpy==1.15.2
|
||||
numpy==1.15.3
|
||||
TA-Lib==0.4.17
|
||||
pytest==3.8.2
|
||||
pytest==3.9.2
|
||||
pytest-mock==1.10.0
|
||||
pytest-asyncio==0.9.0
|
||||
pytest-cov==2.6.0
|
||||
|
Loading…
Reference in New Issue
Block a user