Merge pull request #259 from gcarq/fix/issue-248

Fix issue #248: missing configuration when executing /forcesell
This commit is contained in:
Gérald LONLAS 2017-12-30 17:28:16 -08:00 committed by GitHub
commit 9803130848
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 131 additions and 16 deletions

View File

@ -55,7 +55,7 @@ use the `last` price and values between those interpolate between ask and last
price. Using `ask` price will guarantee quick success in bid, but bot will also price. Using `ask` price will guarantee quick success in bid, but bot will also
end up paying more then would probably have been necessary. end up paying more then would probably have been necessary.
`fiat_currency` set the fiat to use for the conversion form coin to `fiat_display_currency` set the fiat to use for the conversion form coin to
fiat in Telegram. The valid value are: "AUD", "BRL", "CAD", "CHF", fiat in Telegram. The valid value are: "AUD", "BRL", "CAD", "CHF",
"CLP", "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HUF", "IDR", "ILS", "CLP", "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HUF", "IDR", "ILS",
"INR", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD", "PHP", "PKR", "PLN", "INR", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD", "PHP", "PKR", "PLN",

View File

@ -124,26 +124,39 @@ def execute_sell(trade: Trade, limit: float) -> None:
fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2) fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2)
profit_trade = trade.calc_profit(rate=limit) profit_trade = trade.calc_profit(rate=limit)
fiat_converter = CryptoToFiatConverter() message = '*{exchange}:* Selling [{pair}]({pair_url}) with limit `{limit:.8f}`'.format(
profit_fiat = fiat_converter.convert_amount( exchange=trade.exchange,
profit_trade, pair=trade.pair.replace('_', '/'),
_CONF['stake_currency'], pair_url=exchange.get_pair_detail_url(trade.pair),
_CONF['fiat_display_currency'] limit=limit
) )
rpc.send_msg('*{exchange}:* Selling [{pair}]({pair_url}) with limit `{limit:.8f}`' # For regular case, when the configuration exists
'` (profit: ~{profit_percent:.2f}%, {profit_coin:.8f} {coin}`' if 'stake_currency' in _CONF and 'fiat_display_currency' in _CONF:
'` / {profit_fiat:.3f} {fiat})`'.format( fiat_converter = CryptoToFiatConverter()
exchange=trade.exchange, profit_fiat = fiat_converter.convert_amount(
pair=trade.pair.replace('_', '/'), profit_trade,
pair_url=exchange.get_pair_detail_url(trade.pair), _CONF['stake_currency'],
limit=limit, _CONF['fiat_display_currency']
)
message += '` (profit: ~{profit_percent:.2f}%, {profit_coin:.8f} {coin}`' \
'` / {profit_fiat:.3f} {fiat})`'.format(
profit_percent=fmt_exp_profit, profit_percent=fmt_exp_profit,
profit_coin=profit_trade, profit_coin=profit_trade,
coin=_CONF['stake_currency'], coin=_CONF['stake_currency'],
profit_fiat=profit_fiat, profit_fiat=profit_fiat,
fiat=_CONF['fiat_display_currency'], fiat=_CONF['fiat_display_currency'],
)) )
# Because telegram._forcesell does not have the configuration
# Ignore the FIAT value and does not show the stake_currency as well
else:
message += '` (profit: ~{profit_percent:.2f}%, {profit_coin:.8f})`'.format(
profit_percent=fmt_exp_profit,
profit_coin=profit_trade
)
# Send the message
rpc.send_msg(message)
Trade.session.flush() Trade.session.flush()

View File

@ -288,6 +288,7 @@ CONF_SCHEMA = {
'max_open_trades', 'max_open_trades',
'stake_currency', 'stake_currency',
'stake_amount', 'stake_amount',
'fiat_display_currency',
'dry_run', 'dry_run',
'minimal_roi', 'minimal_roi',
'bid_strategy', 'bid_strategy',

View File

@ -11,7 +11,7 @@ from freqtrade import DependencyException, OperationalException
from freqtrade.analyze import SignalType from freqtrade.analyze import SignalType
from freqtrade.exchange import Exchanges from freqtrade.exchange import Exchanges
from freqtrade.main import create_trade, handle_trade, init, \ from freqtrade.main import create_trade, handle_trade, init, \
get_target_bid, _process get_target_bid, _process, execute_sell
from freqtrade.misc import get_state, State from freqtrade.misc import get_state, State
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
@ -331,3 +331,104 @@ def test_balance_fully_last_side(mocker):
def test_balance_bigger_last_ask(mocker): def test_balance_bigger_last_ask(mocker):
mocker.patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}}) mocker.patch.dict('freqtrade.main._CONF', {'bid_strategy': {'ask_last_balance': 1.0}})
assert get_target_bid({'ask': 5, 'last': 10}) == 5 assert get_target_bid({'ask': 5, 'last': 10}) == 5
def test_execute_sell_up(default_conf, ticker, ticker_sell_up, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
mocker.patch('freqtrade.rpc.init', MagicMock())
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker)
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
ticker=MagicMock(return_value={'price_usd': 15000.0}),
_cache_symbols=MagicMock(return_value={'BTC': 1}))
init(default_conf, create_engine('sqlite://'))
# Create some test data
create_trade(0.001)
trade = Trade.query.first()
assert trade
# Increase the price and sell it
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker_sell_up)
execute_sell(trade=trade, limit=ticker_sell_up()['bid'])
assert rpc_mock.call_count == 2
assert 'Selling [BTC/ETH]' 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]
assert '0.919 USD' in rpc_mock.call_args_list[-1][0][0]
def test_execute_sell_down(default_conf, ticker, ticker_sell_down, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
mocker.patch('freqtrade.rpc.init', MagicMock())
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
mocker.patch.multiple('freqtrade.rpc.telegram',
_CONF=default_conf,
init=MagicMock(),
send_msg=MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker)
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
ticker=MagicMock(return_value={'price_usd': 15000.0}),
_cache_symbols=MagicMock(return_value={'BTC': 1}))
init(default_conf, create_engine('sqlite://'))
# Create some test data
create_trade(0.001)
trade = Trade.query.first()
assert trade
# Decrease the price and sell it
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker_sell_down)
execute_sell(trade=trade, limit=ticker_sell_down()['bid'])
assert rpc_mock.call_count == 2
assert 'Selling [BTC/ETH]' in rpc_mock.call_args_list[-1][0][0]
assert '0.00001044' in rpc_mock.call_args_list[-1][0][0]
assert 'profit: ~-5.48%, -0.00005492' in rpc_mock.call_args_list[-1][0][0]
assert '-0.824 USD' in rpc_mock.call_args_list[-1][0][0]
def test_execute_sell_without_conf(default_conf, ticker, ticker_sell_up, mocker):
mocker.patch.dict('freqtrade.main._CONF', default_conf)
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
mocker.patch('freqtrade.rpc.init', MagicMock())
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker)
init(default_conf, create_engine('sqlite://'))
# Create some test data
create_trade(0.001)
trade = Trade.query.first()
assert trade
# Increase the price and sell it
mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(),
get_ticker=ticker_sell_up)
mocker.patch('freqtrade.main._CONF', {})
execute_sell(trade=trade, limit=ticker_sell_up()['bid'])
assert rpc_mock.call_count == 2
assert 'Selling [BTC/ETH]' 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]
assert 'USD' not in rpc_mock.call_args_list[-1][0][0]