Add expiremental feature to sell only if we make a profit
This commit is contained in:
parent
9803130848
commit
714d77dbd8
@ -32,7 +32,8 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"experimental": {
|
"experimental": {
|
||||||
"use_sell_signal": false
|
"use_sell_signal": false,
|
||||||
|
"sell_profit_only": false
|
||||||
},
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -191,13 +191,19 @@ def handle_trade(trade: Trade) -> bool:
|
|||||||
logger.debug('Handling %s ...', trade)
|
logger.debug('Handling %s ...', trade)
|
||||||
current_rate = exchange.get_ticker(trade.pair)['bid']
|
current_rate = exchange.get_ticker(trade.pair)['bid']
|
||||||
|
|
||||||
|
# Experimental: Check if the trade is profitable before selling it (avoid selling at loss)
|
||||||
|
if _CONF.get('experimental', {}).get('sell_profit_only'):
|
||||||
|
logger.debug('Checking if trade is profitable ...')
|
||||||
|
if trade.calc_profit(rate=current_rate) <= 0:
|
||||||
|
return False
|
||||||
|
|
||||||
# Check if minimal roi has been reached
|
# Check if minimal roi has been reached
|
||||||
if min_roi_reached(trade, current_rate, datetime.utcnow()):
|
if min_roi_reached(trade, current_rate, datetime.utcnow()):
|
||||||
logger.debug('Executing sell due to ROI ...')
|
logger.debug('Executing sell due to ROI ...')
|
||||||
execute_sell(trade, current_rate)
|
execute_sell(trade, current_rate)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Check if sell signal has been enabled and triggered
|
# Experimental: Check if sell signal has been enabled and triggered
|
||||||
if _CONF.get('experimental', {}).get('use_sell_signal'):
|
if _CONF.get('experimental', {}).get('use_sell_signal'):
|
||||||
logger.debug('Checking sell_signal ...')
|
logger.debug('Checking sell_signal ...')
|
||||||
if get_signal(trade.pair, SignalType.SELL):
|
if get_signal(trade.pair, SignalType.SELL):
|
||||||
|
@ -234,7 +234,8 @@ CONF_SCHEMA = {
|
|||||||
'experimental': {
|
'experimental': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
'use_sell_signal': {'type': 'boolean'}
|
'use_sell_signal': {'type': 'boolean'},
|
||||||
|
'sell_profit_only': {'type': 'boolean'}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'telegram': {
|
'telegram': {
|
||||||
|
@ -432,3 +432,99 @@ def test_execute_sell_without_conf(default_conf, ticker, ticker_sell_up, mocker)
|
|||||||
assert '0.00001172' 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 '(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]
|
assert 'USD' not in rpc_mock.call_args_list[-1][0][0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, mocker):
|
||||||
|
default_conf['experimental'] = {}
|
||||||
|
default_conf['experimental']['sell_profit_only'] = True
|
||||||
|
|
||||||
|
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||||
|
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||||
|
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
validate_pairs=MagicMock(),
|
||||||
|
get_ticker=MagicMock(return_value={
|
||||||
|
'bid': 0.00002172,
|
||||||
|
'ask': 0.00002173,
|
||||||
|
'last': 0.00002172
|
||||||
|
}),
|
||||||
|
buy=MagicMock(return_value='mocked_limit_buy'))
|
||||||
|
|
||||||
|
init(default_conf, create_engine('sqlite://'))
|
||||||
|
create_trade(0.001)
|
||||||
|
|
||||||
|
trade = Trade.query.first()
|
||||||
|
trade.update(limit_buy_order)
|
||||||
|
assert handle_trade(trade) is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker):
|
||||||
|
default_conf['experimental'] = {}
|
||||||
|
default_conf['experimental']['sell_profit_only'] = False
|
||||||
|
|
||||||
|
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||||
|
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||||
|
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
validate_pairs=MagicMock(),
|
||||||
|
get_ticker=MagicMock(return_value={
|
||||||
|
'bid': 0.00002172,
|
||||||
|
'ask': 0.00002173,
|
||||||
|
'last': 0.00002172
|
||||||
|
}),
|
||||||
|
buy=MagicMock(return_value='mocked_limit_buy'))
|
||||||
|
|
||||||
|
init(default_conf, create_engine('sqlite://'))
|
||||||
|
create_trade(0.001)
|
||||||
|
|
||||||
|
trade = Trade.query.first()
|
||||||
|
trade.update(limit_buy_order)
|
||||||
|
assert handle_trade(trade) is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker):
|
||||||
|
default_conf['experimental'] = {}
|
||||||
|
default_conf['experimental']['sell_profit_only'] = True
|
||||||
|
|
||||||
|
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||||
|
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||||
|
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
validate_pairs=MagicMock(),
|
||||||
|
get_ticker=MagicMock(return_value={
|
||||||
|
'bid': 0.00000172,
|
||||||
|
'ask': 0.00000173,
|
||||||
|
'last': 0.00000172
|
||||||
|
}),
|
||||||
|
buy=MagicMock(return_value='mocked_limit_buy'))
|
||||||
|
|
||||||
|
init(default_conf, create_engine('sqlite://'))
|
||||||
|
create_trade(0.001)
|
||||||
|
|
||||||
|
trade = Trade.query.first()
|
||||||
|
trade.update(limit_buy_order)
|
||||||
|
assert handle_trade(trade) is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker):
|
||||||
|
default_conf['experimental'] = {}
|
||||||
|
default_conf['experimental']['sell_profit_only'] = False
|
||||||
|
|
||||||
|
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||||
|
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||||
|
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
validate_pairs=MagicMock(),
|
||||||
|
get_ticker=MagicMock(return_value={
|
||||||
|
'bid': 0.00000172,
|
||||||
|
'ask': 0.00000173,
|
||||||
|
'last': 0.00000172
|
||||||
|
}),
|
||||||
|
buy=MagicMock(return_value='mocked_limit_buy'))
|
||||||
|
|
||||||
|
init(default_conf, create_engine('sqlite://'))
|
||||||
|
create_trade(0.001)
|
||||||
|
|
||||||
|
trade = Trade.query.first()
|
||||||
|
trade.update(limit_buy_order)
|
||||||
|
assert handle_trade(trade) is True
|
||||||
|
Loading…
Reference in New Issue
Block a user