Ejemplo n.º 1
0
def test_min_roi_reached(default_conf, fee) -> None:

    # Use list to confirm sequence does not matter
    min_roi_list = [{20: 0.05, 55: 0.01, 0: 0.1},
                    {0: 0.1, 20: 0.05, 55: 0.01}]
    for roi in min_roi_list:
        default_conf.update({'strategy': 'DefaultStrategy'})
        strategy = StrategyResolver.load_strategy(default_conf)
        strategy.minimal_roi = roi
        trade = Trade(
            pair='ETH/BTC',
            stake_amount=0.001,
            amount=5,
            open_date=arrow.utcnow().shift(hours=-1).datetime,
            fee_open=fee.return_value,
            fee_close=fee.return_value,
            exchange='bittrex',
            open_rate=1,
        )

        assert not strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-56).datetime)
        assert strategy.min_roi_reached(trade, 0.12, arrow.utcnow().shift(minutes=-56).datetime)

        assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-39).datetime)
        assert strategy.min_roi_reached(trade, 0.06, arrow.utcnow().shift(minutes=-39).datetime)

        assert not strategy.min_roi_reached(trade, -0.01, arrow.utcnow().shift(minutes=-1).datetime)
        assert strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-1).datetime)
Ejemplo n.º 2
0
def test_calc_profit(limit_buy_order, limit_sell_order, fee):
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        amount=5,
        open_rate=0.00001099,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        exchange='bittrex',
    )
    trade.open_order_id = 'something'
    trade.update(limit_buy_order)  # Buy @ 0.00001099

    # Custom closing rate and regular fee rate
    # Higher than open rate
    assert trade.calc_profit(rate=0.00001234) == 0.00011753
    # Lower than open rate
    assert trade.calc_profit(rate=0.00000123) == -0.00089086

    # Custom closing rate and custom fee rate
    # Higher than open rate
    assert trade.calc_profit(rate=0.00001234, fee=0.003) == 0.00011697
    # Lower than open rate
    assert trade.calc_profit(rate=0.00000123, fee=0.003) == -0.00089092

    # Test when we apply a Sell order. Sell higher than open rate @ 0.00001173
    trade.update(limit_sell_order)
    assert trade.calc_profit() == 0.00006217

    # Test with a custom fee rate on the close trade
    assert trade.calc_profit(fee=0.003) == 0.00006163
Ejemplo n.º 3
0
def test_calc_profit_ratio(limit_buy_order, limit_sell_order, fee):
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        amount=5,
        open_rate=0.00001099,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        exchange='bittrex',
    )
    trade.open_order_id = 'something'
    trade.update(limit_buy_order)  # Buy @ 0.00001099

    # Get percent of profit with a custom rate (Higher than open rate)
    assert trade.calc_profit_ratio(rate=0.00001234) == 0.11723875

    # Get percent of profit with a custom rate (Lower than open rate)
    assert trade.calc_profit_ratio(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_ratio() == 0.06201058

    # Test with a custom fee rate on the close trade
    assert trade.calc_profit_ratio(fee=0.003) == 0.06147824
Ejemplo n.º 4
0
def generate_mock_trade(pair: str,
                        fee: float,
                        is_open: bool,
                        sell_reason: str = SellType.SELL_SIGNAL,
                        min_ago_open: int = None,
                        min_ago_close: int = None,
                        profit_rate: float = 0.9):
    open_rate = random.random()

    trade = Trade(
        pair=pair,
        stake_amount=0.01,
        fee_open=fee,
        fee_close=fee,
        open_date=datetime.utcnow() - timedelta(minutes=min_ago_open or 200),
        close_date=datetime.utcnow() - timedelta(minutes=min_ago_close or 30),
        open_rate=open_rate,
        is_open=is_open,
        amount=0.01 / open_rate,
        exchange='binance',
    )
    trade.recalc_open_trade_value()
    if not is_open:
        trade.close(open_rate * profit_rate)
        trade.sell_reason = sell_reason

    return trade
Ejemplo n.º 5
0
def test_fee_updated(fee):
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        fee_open=fee.return_value,
        open_date=arrow.utcnow().shift(hours=-2).datetime,
        amount=10,
        fee_close=fee.return_value,
        exchange='bittrex',
        open_rate=1,
        max_rate=1,
    )

    assert trade.fee_open_currency is None
    assert not trade.fee_updated('buy')
    assert not trade.fee_updated('sell')
    assert not trade.fee_updated('asdf')

    trade.update_fee(0.15, 'BTC', 0.0075, 'buy')
    assert trade.fee_updated('buy')
    assert not trade.fee_updated('sell')
    assert trade.fee_open_currency is not None
    assert trade.fee_close_currency is None

    trade.update_fee(0.15, 'ABC', 0.0075, 'sell')
    assert trade.fee_updated('buy')
    assert trade.fee_updated('sell')
    assert not trade.fee_updated('asfd')
Ejemplo n.º 6
0
def test_min_roi_reached3(default_conf, fee) -> None:

    # test for issue #1948
    min_roi = {20: 0.07,
               30: 0.05,
               55: 0.30,
               }
    default_conf.update({'strategy': 'DefaultStrategy'})
    strategy = StrategyResolver.load_strategy(default_conf)
    strategy.minimal_roi = min_roi
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        amount=5,
        open_date=arrow.utcnow().shift(hours=-1).datetime,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        exchange='binance',
        open_rate=1,
    )

    assert not strategy.min_roi_reached(trade, 0.02, arrow.utcnow().shift(minutes=-56).datetime)
    assert not strategy.min_roi_reached(trade, 0.12, arrow.utcnow().shift(minutes=-56).datetime)

    assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-39).datetime)
    assert strategy.min_roi_reached(trade, 0.071, arrow.utcnow().shift(minutes=-39).datetime)

    assert not strategy.min_roi_reached(trade, 0.04, arrow.utcnow().shift(minutes=-26).datetime)
    assert strategy.min_roi_reached(trade, 0.06, arrow.utcnow().shift(minutes=-26).datetime)

    # Should not trigger with 20% profit since after 55 minutes only 30% is active.
    assert not strategy.min_roi_reached(trade, 0.20, arrow.utcnow().shift(minutes=-2).datetime)
    assert strategy.min_roi_reached(trade, 0.31, arrow.utcnow().shift(minutes=-2).datetime)
Ejemplo n.º 7
0
def test_update_market_order(market_buy_order, market_sell_order, fee, caplog):
    trade = Trade(
        id=1,
        pair='ETH/BTC',
        stake_amount=0.001,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        exchange='bittrex',
    )

    trade.open_order_id = 'something'
    trade.update(market_buy_order)
    assert trade.open_order_id is None
    assert trade.open_rate == 0.00004099
    assert trade.close_profit is None
    assert trade.close_date is None
    assert log_has(
        "MARKET_BUY has been fulfilled for Trade(id=1, "
        "pair=ETH/BTC, amount=91.99181073, open_rate=0.00004099, open_since=closed).",
        caplog)

    caplog.clear()
    trade.open_order_id = 'something'
    trade.update(market_sell_order)
    assert trade.open_order_id is None
    assert trade.close_rate == 0.00004173
    assert trade.close_profit == 0.01297561
    assert trade.close_date is not None
    assert log_has(
        "MARKET_SELL has been fulfilled for Trade(id=1, "
        "pair=ETH/BTC, amount=91.99181073, open_rate=0.00004099, open_since=closed).",
        caplog)
Ejemplo n.º 8
0
    def _get_sell_trade_entry(
            self, pair: str, buy_row: DataFrame,
            partial_ticker: List, trade_count_lock: Dict, args: Dict) -> Optional[Tuple]:

        stake_amount = args['stake_amount']
        max_open_trades = args.get('max_open_trades', 0)
        trade = Trade(
            open_rate=buy_row.close + self.slippage,             #implement slippage 0.01 for buy_row
            open_date=buy_row.date,
            stake_amount=stake_amount,
            amount=stake_amount / buy_row.open,
            fee=exchange.get_fee()
        )

        # calculate win/lose forwards from buy point
        for sell_row in partial_ticker:
            if max_open_trades > 0:
                # Increase trade_count_lock for every iteration
                trade_count_lock[sell_row.date] = trade_count_lock.get(sell_row.date, 0) + 1

            buy_signal = sell_row.buy
            #implement slippage 0.01 for sell_row

            if self.analyze.should_sell(trade, sell_row.close - self.slippage, sell_row.date, buy_signal,
                                        sell_row.sell):
                return \
                    sell_row, \
                    (
                        pair,
                        trade.calc_profit_percent(rate=sell_row.close),
                        trade.calc_profit(rate=sell_row.close),
                        (sell_row.date - buy_row.date).seconds // 60
                    ), \
                    sell_row.date
        return None
Ejemplo n.º 9
0
def test_adjust_min_max_rates(fee):
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        amount=5,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        exchange='bittrex',
        open_rate=1,
    )

    trade.adjust_min_max_rates(trade.open_rate)
    assert trade.max_rate == 1
    assert trade.min_rate == 1

    # check min adjusted, max remained
    trade.adjust_min_max_rates(0.96)
    assert trade.max_rate == 1
    assert trade.min_rate == 0.96

    # check max adjusted, min remains
    trade.adjust_min_max_rates(1.05)
    assert trade.max_rate == 1.05
    assert trade.min_rate == 0.96

    # current rate "in the middle" - no adjustment
    trade.adjust_min_max_rates(1.03)
    assert trade.max_rate == 1.05
    assert trade.min_rate == 0.96
Ejemplo n.º 10
0
def test_trade_close(limit_buy_order, limit_sell_order, fee):
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        open_rate=0.01,
        amount=5,
        is_open=True,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        open_date=arrow.Arrow(2020, 2, 1, 15, 5, 1).datetime,
        exchange='bittrex',
    )
    assert trade.close_profit is None
    assert trade.close_date is None
    assert trade.is_open is True
    trade.close(0.02)
    assert trade.is_open is False
    assert trade.close_profit == 0.99002494
    assert trade.close_date is not None

    new_date = arrow.Arrow(2020, 2, 2, 15, 6, 1).datetime,
    assert trade.close_date != new_date
    # Close should NOT update close_date if the trade has been closed already
    assert trade.is_open is False
    trade.close_date = new_date
    trade.close(0.02)
    assert trade.close_date == new_date
Ejemplo n.º 11
0
def test_backtest(conf, pairs, mocker):
    trades = []
    mocker.patch.dict('freqtrade.main._CONF', conf)
    for pair in pairs:
        with open('freqtrade/tests/testdata/'+pair+'.json') as data_file:
            data = json.load(data_file)

            mocker.patch('freqtrade.analyze.get_ticker_history', return_value=data)
            mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00'))
            ticker = analyze_ticker(pair)
            # for each buy point
            for index, row in ticker[ticker.buy == 1].iterrows():
                trade = Trade(
                    open_rate=row['close'],
                    open_date=arrow.get(row['date']).datetime,
                    amount=1,
                )
                # calculate win/lose forwards from buy point
                for index2, row2 in ticker[index:].iterrows():
                    if should_sell(trade, row2['close'], arrow.get(row2['date']).datetime):
                        current_profit = (row2['close'] - trade.open_rate) / trade.open_rate

                        trades.append((pair, current_profit, index2 - index))
                        break
        
    labels = ['currency', 'profit', 'duration']
    results = DataFrame.from_records(trades, columns=labels)

    print('====================== BACKTESTING REPORT ================================')

    for pair in pairs:
        print('For currency {}:'.format(pair))
        print_results(results[results.currency == pair])
    print('TOTAL OVER ALL TRADES:')
    print_results(results)
Ejemplo n.º 12
0
def test_min_roi_reached2(default_conf, fee) -> None:

    # test with ROI raising after last interval
    min_roi_list = [
        {
            20: 0.07,
            30: 0.05,
            55: 0.30,
            0: 0.1
        },
        {
            0: 0.1,
            20: 0.07,
            30: 0.05,
            55: 0.30
        },
    ]
    for roi in min_roi_list:
        default_conf.update({'strategy': 'DefaultStrategy'})
        strategy = StrategyResolver.load_strategy(default_conf)
        strategy.minimal_roi = roi
        trade = Trade(
            pair='ETH/BTC',
            stake_amount=0.001,
            amount=5,
            open_date=arrow.utcnow().shift(hours=-1).datetime,
            fee_open=fee.return_value,
            fee_close=fee.return_value,
            exchange='bittrex',
            open_rate=1,
        )

        assert not strategy.min_roi_reached(
            trade, 0.02,
            arrow.utcnow().shift(minutes=-56).datetime)
        assert strategy.min_roi_reached(
            trade, 0.12,
            arrow.utcnow().shift(minutes=-56).datetime)

        assert not strategy.min_roi_reached(
            trade, 0.04,
            arrow.utcnow().shift(minutes=-39).datetime)
        assert strategy.min_roi_reached(
            trade, 0.071,
            arrow.utcnow().shift(minutes=-39).datetime)

        assert not strategy.min_roi_reached(
            trade, 0.04,
            arrow.utcnow().shift(minutes=-26).datetime)
        assert strategy.min_roi_reached(
            trade, 0.06,
            arrow.utcnow().shift(minutes=-26).datetime)

        # Should not trigger with 20% profit since after 55 minutes only 30% is active.
        assert not strategy.min_roi_reached(
            trade, 0.20,
            arrow.utcnow().shift(minutes=-2).datetime)
        assert strategy.min_roi_reached(
            trade, 0.31,
            arrow.utcnow().shift(minutes=-2).datetime)
Ejemplo n.º 13
0
def backtest(backtest_conf, backdata, mocker):
    trades = []
    exchange._API = Bittrex({'key': '', 'secret': ''})
    mocked_history = mocker.patch('freqtrade.analyze.get_ticker_history')
    mocker.patch.dict('freqtrade.main._CONF', backtest_conf)
    mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00'))
    for pair, pair_data in backdata.items():
        mocked_history.return_value = pair_data
        ticker = analyze_ticker(pair)[['close', 'date', 'buy']].copy()
        # for each buy point
        for row in ticker[ticker.buy == 1].itertuples(index=True):
            trade = Trade(open_rate=row.close,
                          open_date=row.date,
                          amount=1,
                          fee=exchange.get_fee() * 2)
            # calculate win/lose forwards from buy point
            for row2 in ticker[row.Index:].itertuples(index=True):
                if should_sell(trade, row2.close, row2.date):
                    current_profit = trade.calc_profit(row2.close)

                    trades.append(
                        (pair, current_profit, row2.Index - row.Index))
                    break
    labels = ['currency', 'profit', 'duration']
    results = DataFrame.from_records(trades, columns=labels)
    return results
Ejemplo n.º 14
0
def backtest(backtest_conf, processed, mocker):
    trades = []
    exchange._API = Bittrex({'key': '', 'secret': ''})
    mocker.patch.dict('freqtrade.main._CONF', backtest_conf)
    for pair, pair_data in processed.items():
        pair_data['buy'] = 0
        pair_data['sell'] = 0
        ticker = populate_sell_trend(populate_buy_trend(pair_data))
        # for each buy point
        for row in ticker[ticker.buy == 1].itertuples(index=True):
            trade = Trade(open_rate=row.close,
                          open_date=row.date,
                          amount=backtest_conf['stake_amount'],
                          fee=exchange.get_fee() * 2)
            # calculate win/lose forwards from buy point
            for row2 in ticker[row.Index:].itertuples(index=True):
                if min_roi_reached(trade, row2.close,
                                   row2.date) or row2.sell == 1:
                    current_profit = trade.calc_profit(row2.close)

                    trades.append(
                        (pair, current_profit, row2.Index - row.Index))
                    break
    labels = ['currency', 'profit', 'duration']
    return DataFrame.from_records(trades, columns=labels)
Ejemplo n.º 15
0
def test_clean_dry_run_db(default_conf, fee):

    # Simulate dry_run entries
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        amount=123.0,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        open_rate=0.123,
        exchange='bittrex',
        open_order_id='dry_run_buy_12345'
    )
    Trade.session.add(trade)

    trade = Trade(
        pair='ETC/BTC',
        stake_amount=0.001,
        amount=123.0,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        open_rate=0.123,
        exchange='bittrex',
        open_order_id='dry_run_sell_12345'
    )
    Trade.session.add(trade)

    # Simulate prod entry
    trade = Trade(
        pair='ETC/BTC',
        stake_amount=0.001,
        amount=123.0,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        open_rate=0.123,
        exchange='bittrex',
        open_order_id='prod_buy_12345'
    )
    Trade.session.add(trade)

    # We have 3 entries: 2 dry_run, 1 prod
    assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 3

    clean_dry_run_db()

    # We have now only the prod
    assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 1
Ejemplo n.º 16
0
def test_api_performance(botclient, fee):
    ftbot, client = botclient
    patch_get_signal(ftbot)

    trade = Trade(
        pair='LTC/ETH',
        amount=1,
        exchange='binance',
        stake_amount=1,
        open_rate=0.245441,
        open_order_id="123456",
        is_open=False,
        fee_close=fee.return_value,
        fee_open=fee.return_value,
        close_rate=0.265441,

    )
    trade.close_profit = trade.calc_profit_ratio()
    trade.close_profit_abs = trade.calc_profit()
    Trade.query.session.add(trade)

    trade = Trade(
        pair='XRP/ETH',
        amount=5,
        stake_amount=1,
        exchange='binance',
        open_rate=0.412,
        open_order_id="123456",
        is_open=False,
        fee_close=fee.return_value,
        fee_open=fee.return_value,
        close_rate=0.391
    )
    trade.close_profit = trade.calc_profit_ratio()
    trade.close_profit_abs = trade.calc_profit()

    Trade.query.session.add(trade)
    Trade.commit()

    rc = client_get(client, f"{BASE_URI}/performance")
    assert_response(rc)
    assert len(rc.json()) == 2
    assert rc.json() == [{'count': 1, 'pair': 'LTC/ETH', 'profit': 7.61, 'profit_pct': 7.61,
                          'profit_ratio': 0.07609203, 'profit_abs': 0.01872279},
                         {'count': 1, 'pair': 'XRP/ETH', 'profit': -5.57, 'profit_pct': -5.57,
                          'profit_ratio': -0.05570419, 'profit_abs': -0.1150375}]
Ejemplo n.º 17
0
def test_stop_loss_reached(default_conf, fee, profit, adjusted, expected,
                           trailing, custom, profit2, adjusted2, expected2,
                           custom_stop) -> None:

    default_conf.update({'strategy': 'DefaultStrategy'})

    strategy = StrategyResolver.load_strategy(default_conf)
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.01,
        amount=1,
        open_date=arrow.utcnow().shift(hours=-1).datetime,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        exchange='binance',
        open_rate=1,
    )
    trade.adjust_min_max_rates(trade.open_rate)
    strategy.trailing_stop = trailing
    strategy.trailing_stop_positive = -0.05
    strategy.use_custom_stoploss = custom
    original_stopvalue = strategy.custom_stoploss
    if custom_stop:
        strategy.custom_stoploss = custom_stop

    now = arrow.utcnow().datetime
    sl_flag = strategy.stop_loss_reached(current_rate=trade.open_rate *
                                         (1 + profit),
                                         trade=trade,
                                         current_time=now,
                                         current_profit=profit,
                                         force_stoploss=0,
                                         high=None,
                                         dataframe=None)
    assert isinstance(sl_flag, SellCheckTuple)
    assert sl_flag.sell_type == expected
    if expected == SellType.NONE:
        assert sl_flag.sell_flag is False
    else:
        assert sl_flag.sell_flag is True
    assert round(trade.stop_loss, 2) == adjusted

    sl_flag = strategy.stop_loss_reached(current_rate=trade.open_rate *
                                         (1 + profit2),
                                         trade=trade,
                                         current_time=now,
                                         current_profit=profit2,
                                         force_stoploss=0,
                                         high=None,
                                         dataframe=None)
    assert sl_flag.sell_type == expected2
    if expected2 == SellType.NONE:
        assert sl_flag.sell_flag is False
    else:
        assert sl_flag.sell_flag is True
    assert round(trade.stop_loss, 2) == adjusted2

    strategy.custom_stoploss = original_stopvalue
Ejemplo n.º 18
0
def test_api_forcebuy(botclient, mocker, fee):
    ftbot, client = botclient

    rc = client_post(client,
                     f"{BASE_URI}/forcebuy",
                     data='{"pair": "ETH/BTC"}')
    assert_response(rc, 502)
    assert rc.json == {
        "error": "Error querying _forcebuy: Forcebuy not enabled."
    }

    # enable forcebuy
    ftbot.config["forcebuy_enable"] = True

    fbuy_mock = MagicMock(return_value=None)
    mocker.patch("freqtrade.rpc.RPC._rpc_forcebuy", fbuy_mock)
    rc = client_post(client,
                     f"{BASE_URI}/forcebuy",
                     data='{"pair": "ETH/BTC"}')
    assert_response(rc)
    assert rc.json == {"status": "Error buying pair ETH/BTC."}

    # Test creating trae
    fbuy_mock = MagicMock(return_value=Trade(
        pair='ETH/ETH',
        amount=1,
        exchange='bittrex',
        stake_amount=1,
        open_rate=0.245441,
        open_order_id="123456",
        open_date=datetime.utcnow(),
        is_open=False,
        fee_close=fee.return_value,
        fee_open=fee.return_value,
        close_rate=0.265441,
    ))
    mocker.patch("freqtrade.rpc.RPC._rpc_forcebuy", fbuy_mock)

    rc = client_post(client,
                     f"{BASE_URI}/forcebuy",
                     data='{"pair": "ETH/BTC"}')
    assert_response(rc)
    assert rc.json == {
        'amount': 1,
        'close_date': None,
        'close_date_hum': None,
        'close_rate': 0.265441,
        'initial_stop_loss': None,
        'initial_stop_loss_pct': None,
        'open_date': ANY,
        'open_date_hum': 'just now',
        'open_rate': 0.245441,
        'pair': 'ETH/ETH',
        'stake_amount': 1,
        'stop_loss': None,
        'stop_loss_pct': None,
        'trade_id': None
    }
Ejemplo n.º 19
0
def test_stoploss_reinitialization(default_conf, fee):
    init(default_conf['db_url'])
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        fee_open=fee.return_value,
        open_date=arrow.utcnow().shift(hours=-2).datetime,
        amount=10,
        fee_close=fee.return_value,
        exchange='bittrex',
        open_rate=1,
        max_rate=1,
    )

    trade.adjust_stop_loss(trade.open_rate, 0.05, True)
    assert trade.stop_loss == 0.95
    assert trade.stop_loss_pct == -0.05
    assert trade.initial_stop_loss == 0.95
    assert trade.initial_stop_loss_pct == -0.05
    Trade.session.add(trade)

    # Lower stoploss
    Trade.stoploss_reinitialization(0.06)

    trades = Trade.get_open_trades()
    assert len(trades) == 1
    trade_adj = trades[0]
    assert trade_adj.stop_loss == 0.94
    assert trade_adj.stop_loss_pct == -0.06
    assert trade_adj.initial_stop_loss == 0.94
    assert trade_adj.initial_stop_loss_pct == -0.06

    # Raise stoploss
    Trade.stoploss_reinitialization(0.04)

    trades = Trade.get_open_trades()
    assert len(trades) == 1
    trade_adj = trades[0]
    assert trade_adj.stop_loss == 0.96
    assert trade_adj.stop_loss_pct == -0.04
    assert trade_adj.initial_stop_loss == 0.96
    assert trade_adj.initial_stop_loss_pct == -0.04

    # Trailing stoploss (move stoplos up a bit)
    trade.adjust_stop_loss(1.02, 0.04)
    assert trade_adj.stop_loss == 0.9792
    assert trade_adj.initial_stop_loss == 0.96

    Trade.stoploss_reinitialization(0.04)

    trades = Trade.get_open_trades()
    assert len(trades) == 1
    trade_adj = trades[0]
    # Stoploss should not change in this case.
    assert trade_adj.stop_loss == 0.9792
    assert trade_adj.stop_loss_pct == -0.04
    assert trade_adj.initial_stop_loss == 0.96
    assert trade_adj.initial_stop_loss_pct == -0.04
Ejemplo n.º 20
0
def test_api_performance(botclient, mocker, ticker, fee):
    ftbot, client = botclient
    patch_get_signal(ftbot, (True, False))

    trade = Trade(
        pair='LTC/ETH',
        amount=1,
        exchange='binance',
        stake_amount=1,
        open_rate=0.245441,
        open_order_id="123456",
        is_open=False,
        fee_close=fee.return_value,
        fee_open=fee.return_value,
        close_rate=0.265441,
    )
    trade.close_profit = trade.calc_profit_percent()
    Trade.session.add(trade)

    trade = Trade(pair='XRP/ETH',
                  amount=5,
                  stake_amount=1,
                  exchange='binance',
                  open_rate=0.412,
                  open_order_id="123456",
                  is_open=False,
                  fee_close=fee.return_value,
                  fee_open=fee.return_value,
                  close_rate=0.391)
    trade.close_profit = trade.calc_profit_percent()
    Trade.session.add(trade)
    Trade.session.flush()

    rc = client_get(client, f"{BASE_URI}/performance")
    assert_response(rc)
    assert len(rc.json) == 2
    assert rc.json == [{
        'count': 1,
        'pair': 'LTC/ETH',
        'profit': 7.61
    }, {
        'count': 1,
        'pair': 'XRP/ETH',
        'profit': -5.57
    }]
Ejemplo n.º 21
0
def test_clean_dry_run_db(default_conf):
    init(default_conf, create_engine('sqlite://'))

    # Simulate dry_run entries
    trade = Trade(
        pair='BTC_ETH',
        stake_amount=0.001,
        amount=123.0,
        fee=0.0025,
        open_rate=0.123,
        exchange='BITTREX',
        open_order_id='dry_run_buy_12345'
    )
    Trade.session.add(trade)

    trade = Trade(
        pair='BTC_ETC',
        stake_amount=0.001,
        amount=123.0,
        fee=0.0025,
        open_rate=0.123,
        exchange='BITTREX',
        open_order_id='dry_run_sell_12345'
    )
    Trade.session.add(trade)

    # Simulate prod entry
    trade = Trade(
        pair='BTC_ETC',
        stake_amount=0.001,
        amount=123.0,
        fee=0.0025,
        open_rate=0.123,
        exchange='BITTREX',
        open_order_id='prod_buy_12345'
    )
    Trade.session.add(trade)

    # We have 3 entries: 2 dry_run, 1 prod
    assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 3

    clean_dry_run_db()

    # We have now only the prod
    assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 1
Ejemplo n.º 22
0
def create_mock_trades(fee):
    """
    Create some fake trades ...
    """
    # Simulate dry_run entries
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        amount=123.0,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        open_rate=0.123,
        exchange='bittrex',
        open_order_id='dry_run_buy_12345'
    )
    Trade.session.add(trade)

    trade = Trade(
        pair='ETC/BTC',
        stake_amount=0.001,
        amount=123.0,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        open_rate=0.123,
        close_rate=0.128,
        close_profit=0.005,
        exchange='bittrex',
        is_open=False,
        open_order_id='dry_run_sell_12345'
    )
    Trade.session.add(trade)

    # Simulate prod entry
    trade = Trade(
        pair='ETC/BTC',
        stake_amount=0.001,
        amount=123.0,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        open_rate=0.123,
        exchange='bittrex',
        open_order_id='prod_buy_12345'
    )
    Trade.session.add(trade)
Ejemplo n.º 23
0
def test_update_invalid_order(limit_buy_order):
    trade = Trade(
        pair='BTC_ETH',
        stake_amount=1.00,
        fee=0.1,
        exchange=Exchanges.BITTREX,
    )
    limit_buy_order['type'] = 'invalid'
    with pytest.raises(ValueError, match=r'Unknown order type'):
        trade.update(limit_buy_order)
Ejemplo n.º 24
0
def test_update_invalid_order(limit_buy_order):
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=1.00,
        fee_open=0.1,
        fee_close=0.1,
        exchange='bittrex',
    )
    limit_buy_order['type'] = 'invalid'
    with pytest.raises(ValueError, match=r'Unknown order type'):
        trade.update(limit_buy_order)
Ejemplo n.º 25
0
def open_trade():
    return Trade(pair='ETH/BTC',
                 open_rate=0.00001099,
                 exchange='bittrex',
                 open_order_id='123456789',
                 amount=90.99181073,
                 fee_open=0.0,
                 fee_close=0.0,
                 stake_amount=1,
                 open_date=arrow.utcnow().shift(minutes=-601).datetime,
                 is_open=True)
Ejemplo n.º 26
0
def test_calc_close_trade_price_exception(limit_buy_order):
    trade = Trade(
        pair='BTC_ETH',
        stake_amount=0.001,
        fee=0.0025,
        exchange=Exchanges.BITTREX,
    )

    trade.open_order_id = 'something'
    trade.update(limit_buy_order)
    assert trade.calc_close_trade_price() == 0.0
Ejemplo n.º 27
0
def test_calc_close_trade_price_exception(limit_buy_order, fee):
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        exchange='bittrex',
    )

    trade.open_order_id = 'something'
    trade.update(limit_buy_order)
    assert trade.calc_close_trade_price() == 0.0
Ejemplo n.º 28
0
    def execute_buy(self, pair: str, stake_amount: float) -> bool:
        """
        Executes a limit buy for the given pair
        :param pair: pair for which we want to create a LIMIT_BUY
        :return: None
        """
        pair_s = pair.replace('_', '/')
        pair_url = self.exchange.get_pair_detail_url(pair)
        stake_currency = self.config['stake_currency']
        fiat_currency = self.config.get('fiat_display_currency', None)

        # Calculate amount
        buy_limit = self.get_target_bid(pair, self.exchange.get_ticker(pair))

        min_stake_amount = self._get_min_pair_stake_amount(pair_s, buy_limit)
        if min_stake_amount is not None and min_stake_amount > stake_amount:
            logger.warning(
                f'Can\'t open a new trade for {pair_s}: stake amount'
                f' is too small ({stake_amount} < {min_stake_amount})')
            return False

        amount = stake_amount / buy_limit

        order_id = self.exchange.buy(pair, buy_limit, amount)['id']

        self.rpc.send_msg({
            'type': RPCMessageType.BUY_NOTIFICATION,
            'exchange': self.exchange.name.capitalize(),
            'pair': pair_s,
            'market_url': pair_url,
            'limit': buy_limit,
            'stake_amount': stake_amount,
            'stake_currency': stake_currency,
            'fiat_currency': fiat_currency
        })
        # Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
        fee = self.exchange.get_fee(symbol=pair, taker_or_maker='maker')
        trade = Trade(pair=pair,
                      stake_amount=stake_amount,
                      amount=amount,
                      fee_open=fee,
                      fee_close=fee,
                      open_rate=buy_limit,
                      open_rate_requested=buy_limit,
                      open_date=datetime.utcnow(),
                      exchange=self.exchange.id,
                      open_order_id=order_id,
                      strategy=self.strategy.get_strategy_name(),
                      ticker_interval=constants.TICKER_INTERVAL_MINUTES[
                          self.config['ticker_interval']])
        Trade.session.add(trade)
        Trade.session.flush()
        return True
Ejemplo n.º 29
0
def test_update_with_bittrex(limit_buy_order, limit_sell_order, fee):
    """
    On this test we will buy and sell a crypto currency.

    Buy
    - Buy: 90.99181073 Crypto at 0.00001099 BTC
        (90.99181073*0.00001099 = 0.0009999 BTC)
    - Buying fee: 0.25%
    - Total cost of buy trade: 0.001002500 BTC
        ((90.99181073*0.00001099) + ((90.99181073*0.00001099)*0.0025))

    Sell
    - Sell: 90.99181073 Crypto at 0.00001173 BTC
        (90.99181073*0.00001173 = 0,00106733394 BTC)
    - Selling fee: 0.25%
    - Total cost of sell trade: 0.001064666 BTC
        ((90.99181073*0.00001173) - ((90.99181073*0.00001173)*0.0025))

    Profit/Loss: +0.000062166 BTC
        (Sell:0.001064666 - Buy:0.001002500)
    Profit/Loss percentage: 0.0620
        ((0.001064666/0.001002500)-1 = 6.20%)

    :param limit_buy_order:
    :param limit_sell_order:
    :return:
    """

    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        fee_open=fee.return_value,
        fee_close=fee.return_value,
        exchange='bittrex',
    )
    assert trade.open_order_id is None
    assert trade.open_rate is None
    assert trade.close_profit is None
    assert trade.close_date is None

    trade.open_order_id = 'something'
    trade.update(limit_buy_order)
    assert trade.open_order_id is None
    assert trade.open_rate == 0.00001099
    assert trade.close_profit is None
    assert trade.close_date is None

    trade.open_order_id = 'something'
    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_date is not None
Ejemplo n.º 30
0
    def _get_sell_trade_entry(self, pair: str, buy_row: DataFrame,
                              partial_ticker: List, trade_count_lock: Dict,
                              args: Dict) -> Optional[BacktestResult]:

        stake_amount = args['stake_amount']
        max_open_trades = args.get('max_open_trades', 0)
        trade = Trade(open_rate=buy_row.close,
                      open_date=buy_row.date,
                      stake_amount=stake_amount,
                      amount=stake_amount / buy_row.open,
                      fee_open=self.fee,
                      fee_close=self.fee)

        # calculate win/lose forwards from buy point
        for sell_row in partial_ticker:
            if max_open_trades > 0:
                # Increase trade_count_lock for every iteration
                trade_count_lock[sell_row.date] = trade_count_lock.get(
                    sell_row.date, 0) + 1

            buy_signal = sell_row.buy
            if self.analyze.should_sell(trade, sell_row.close, sell_row.date,
                                        buy_signal, sell_row.sell):

                return BacktestResult(
                    pair=pair,
                    profit_percent=trade.calc_profit_percent(
                        rate=sell_row.close),
                    profit_abs=trade.calc_profit(rate=sell_row.close),
                    open_time=buy_row.date,
                    close_time=sell_row.date,
                    trade_duration=(sell_row.date - buy_row.date).seconds //
                    60,
                    open_index=buy_row.Index,
                    close_index=sell_row.Index,
                    open_at_end=False)
        if partial_ticker:
            # no sell condition found - trade stil open at end of backtest period
            sell_row = partial_ticker[-1]
            btr = BacktestResult(
                pair=pair,
                profit_percent=trade.calc_profit_percent(rate=sell_row.close),
                profit_abs=trade.calc_profit(rate=sell_row.close),
                open_time=buy_row.date,
                close_time=sell_row.date,
                trade_duration=(sell_row.date - buy_row.date).seconds // 60,
                open_index=buy_row.Index,
                close_index=sell_row.Index,
                open_at_end=True)
            logger.debug('Force_selling still open trade %s with %s perc - %s',
                         btr.pair, btr.profit_percent, btr.profit_abs)
            return btr
        return None