diff --git a/freqtrade/main.py b/freqtrade/main.py index 602ec67b2..acf72ab0c 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -67,11 +67,8 @@ def _process(dynamic_whitelist: Optional[bool] = False) -> bool: if len(trades) < _CONF['max_open_trades']: try: # Create entity and execute trade - trade = create_trade(float(_CONF['stake_amount'])) - if trade: - Trade.session.add(trade) - state_changed = True - else: + state_changed = create_trade(float(_CONF['stake_amount'])) + if not state_changed: logger.info( 'Checked all whitelisted currencies. ' 'Found no suitable entry positions for buying. Will keep looking ...' @@ -126,6 +123,7 @@ def execute_sell(trade: Trade, limit: float) -> None: limit, fmt_exp_profit )) + Trade.session.flush() def min_roi_reached(trade: Trade, current_rate: float, current_time: datetime) -> bool: @@ -172,11 +170,12 @@ def get_target_bid(ticker: Dict[str, float]) -> float: return ticker['ask'] + balance * (ticker['last'] - ticker['ask']) -def create_trade(stake_amount: float) -> Optional[Trade]: +def create_trade(stake_amount: float) -> bool: """ Checks the implemented trading indicator(s) for a randomly picked pair, if one pair triggers the buy_signal a new trade record gets created :param stake_amount: amount of btc to spend + :return: True if a trade object has been created and persisted, False otherwise """ logger.info( 'Checking buy signals to create a new trade with stake_amount: %f ...', @@ -203,7 +202,7 @@ def create_trade(stake_amount: float) -> Optional[Trade]: pair = _pair break else: - return None + return False # Calculate amount and subtract fee fee = exchange.get_fee() @@ -219,14 +218,19 @@ def create_trade(stake_amount: float) -> Optional[Trade]: buy_limit )) # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL - return Trade(pair=pair, - stake_amount=stake_amount, - amount=amount, - fee=fee * 2, - open_rate=buy_limit, - open_date=datetime.utcnow(), - exchange=exchange.get_name().upper(), - open_order_id=order_id) + trade = Trade( + pair=pair, + stake_amount=stake_amount, + amount=amount, + fee=fee * 2, + open_rate=buy_limit, + open_date=datetime.utcnow(), + exchange=exchange.get_name().upper(), + open_order_id=order_id + ) + Trade.session.add(trade) + Trade.session.flush() + return True def init(config: dict, db_url: Optional[str] = None) -> None: diff --git a/freqtrade/tests/test_main.py b/freqtrade/tests/test_main.py index 494e50e43..73fe664f0 100644 --- a/freqtrade/tests/test_main.py +++ b/freqtrade/tests/test_main.py @@ -115,9 +115,9 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker): whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist']) init(default_conf, create_engine('sqlite://')) - trade = create_trade(15.0) - Trade.session.add(trade) - Trade.session.flush() + create_trade(15.0) + + trade = Trade.query.first() assert trade is not None assert trade.stake_amount == 15.0 assert trade.is_open @@ -176,13 +176,14 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker): buy=MagicMock(return_value='mocked_limit_buy'), sell=MagicMock(return_value='mocked_limit_sell')) init(default_conf, create_engine('sqlite://')) - trade = create_trade(15.0) - trade.update(limit_buy_order) - Trade.session.add(trade) - Trade.session.flush() - trade = Trade.query.filter(Trade.is_open.is_(True)).first() + create_trade(15.0) + + trade = Trade.query.first() assert trade + trade.update(limit_buy_order) + assert trade.is_open is True + handle_trade(trade) assert trade.open_order_id == 'mocked_limit_sell' @@ -205,15 +206,14 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mo # Create trade and sell it init(default_conf, create_engine('sqlite://')) - trade = create_trade(15.0) - Trade.session.add(trade) - trade.update(limit_buy_order) - trade = Trade.query.filter(Trade.is_open.is_(True)).first() + create_trade(15.0) + + trade = Trade.query.first() assert trade + trade.update(limit_buy_order) trade.update(limit_sell_order) - trade = Trade.query.filter(Trade.is_open.is_(False)).first() - assert trade + assert trade.is_open is False with pytest.raises(ValueError, match=r'.*closed trade.*'): handle_trade(trade) diff --git a/freqtrade/tests/test_rpc_telegram.py b/freqtrade/tests/test_rpc_telegram.py index ebedc5962..d8cb43966 100644 --- a/freqtrade/tests/test_rpc_telegram.py +++ b/freqtrade/tests/test_rpc_telegram.py @@ -101,11 +101,7 @@ def test_status_handle(default_conf, update, ticker, mocker): msg_mock.reset_mock() # Create some test data - trade = create_trade(15.0) - assert trade - Trade.session.add(trade) - Trade.session.flush() - + create_trade(15.0) # Trigger status while we have a fulfilled order for the open trade _status(bot=MagicMock(), update=update) @@ -141,10 +137,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker): msg_mock.reset_mock() # Create some test data - trade = create_trade(15.0) - assert trade - Trade.session.add(trade) - Trade.session.flush() + create_trade(15.0) _status_table(bot=MagicMock(), update=update) @@ -177,8 +170,8 @@ def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell msg_mock.reset_mock() # Create some test data - trade = create_trade(15.0) - assert trade + create_trade(15.0) + trade = Trade.query.first() # Simulate fulfilled LIMIT_BUY order for trade trade.update(limit_buy_order) @@ -193,8 +186,6 @@ def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell trade.close_date = datetime.utcnow() trade.is_open = False - Trade.session.add(trade) - Trade.session.flush() _profit(bot=MagicMock(), update=update) assert msg_mock.call_count == 1 @@ -216,11 +207,10 @@ def test_forcesell_handle(default_conf, update, ticker, mocker): init(default_conf, create_engine('sqlite://')) # Create some test data - trade = create_trade(15.0) - assert trade + create_trade(15.0) - Trade.session.add(trade) - Trade.session.flush() + trade = Trade.query.first() + assert trade update.message.text = '/forcesell 1' _forcesell(bot=MagicMock(), update=update) @@ -245,8 +235,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker): # Create some test data for _ in range(4): - Trade.session.add(create_trade(15.0)) - Trade.session.flush() + create_trade(15.0) rpc_mock.reset_mock() update.message.text = '/forcesell all' @@ -309,7 +298,8 @@ def test_performance_handle( init(default_conf, create_engine('sqlite://')) # Create some test data - trade = create_trade(15.0) + create_trade(15.0) + trade = Trade.query.first() assert trade # Simulate fulfilled LIMIT_BUY order for trade @@ -320,8 +310,6 @@ def test_performance_handle( trade.close_date = datetime.utcnow() trade.is_open = False - Trade.session.add(trade) - Trade.session.flush() _performance(bot=MagicMock(), update=update) assert msg_mock.call_count == 1 @@ -351,9 +339,7 @@ def test_count_handle(default_conf, update, ticker, mocker): update_state(State.RUNNING) # Create some test data - Trade.session.add(create_trade(15.0)) - Trade.session.flush() - + create_trade(15.0) msg_mock.reset_mock() _count(bot=MagicMock(), update=update)