示例#1
0
def test_backtesting_three_routes():
    reset_config()
    router.set_routes([
        (exchanges.SANDBOX, 'BTCUSD', timeframes.MINUTE_5, 'Test19'),
        (exchanges.SANDBOX, 'ETHUSD', timeframes.MINUTE_5, 'Test19'),
        (exchanges.SANDBOX, 'XRPUSD', timeframes.MINUTE_15, 'Test19'),
    ])
    store.reset(True)
    candles = {}
    routes = router.routes
    for r in routes:
        key = jh.key(r.exchange, r.symbol)
        candles[key] = {
            'exchange': r.exchange,
            'symbol': r.symbol,
            'candles': fake_range_candle(5 * 3 * 20)
        }

        # assert that strategy hasn't been initiated before running backtest_mode()
        assert r.strategy is None

    # run backtest (dates are fake just to pass)
    backtest_mode.run('2019-04-01', '2019-04-02', candles)

    # there must be three positions present with the updated current_price
    assert len(store.positions.storage) == 3

    for r in routes:
        # r3's '15m' timeframe makes r1 and r2 to support
        # '15' timeframe as well. r1 and r2 also make r3
        # to support '5m' timeframe also.
        r_one_min = store.candles.get_candles(r.exchange, r.symbol, '1m')
        r_five_min = store.candles.get_candles(r.exchange, r.symbol, '5m')
        r_fifteen_min = store.candles.get_candles(r.exchange, r.symbol, '15m')

        # assert the count of present candles
        assert len(r_one_min) == (5 * 3) * 20
        assert len(r_five_min) == 20 * 3
        assert len(r_fifteen_min) == 20

        r_first_1 = r_one_min[0]
        r_last_1 = r_one_min[-1]
        r_first_5 = r_five_min[0]
        r_last_5 = r_five_min[-1]
        r_first_15 = r_fifteen_min[0]
        r_last_15 = r_fifteen_min[-1]

        # assert timestamps
        assert r_first_1[0] == r_first_5[0]
        assert r_last_1[0] == (r_last_5[0] + 60000 * 4)
        assert r_last_5[0] == (r_last_15[0] + 60000 * 10)

        # assert positions
        p = selectors.get_position(r.exchange, r.symbol)
        assert p.is_close is True
        last_candle = store.candles.get_candles(r.exchange, r.symbol, '1m')[-1]
        assert p.current_price == last_candle[2]

        # assert that the strategy has been initiated
        assert r.strategy is not None
示例#2
0
def test_get_forming_candle():
    set_up()

    candles_to_add = fake_range_candle(13)
    store.candles.batch_add_candle(candles_to_add[0:4], 'Sandbox', 'BTCUSD',
                                   '1m')
    forming_candle = store.candles.get_current_candle('Sandbox', 'BTCUSD',
                                                      '5m')
    assert forming_candle[0] == candles_to_add[0][0]
    assert forming_candle[1] == candles_to_add[0][1]
    assert forming_candle[2] == candles_to_add[3][2]

    # add the rest of 1m candles
    store.candles.batch_add_candle(candles_to_add[4:], 'Sandbox', 'BTCUSD',
                                   '1m')
    # add 5m candles
    store.candles.batch_add_candle(candles_to_add[0:5], 'Sandbox', 'BTCUSD',
                                   '5m')
    store.candles.batch_add_candle(candles_to_add[5:10], 'Sandbox', 'BTCUSD',
                                   '5m')

    forming_candle = store.candles.get_current_candle('Sandbox', 'BTCUSD',
                                                      '5m')
    assert forming_candle[0] == candles_to_add[10][0]
    assert forming_candle[1] == candles_to_add[10][1]
    assert forming_candle[2] == candles_to_add[12][2]
示例#3
0
def test_get_candles_including_forming():
    set_up()

    candles_to_add = fake_range_candle(14)
    store.candles.batch_add_candle(candles_to_add, 'Sandbox', 'BTCUSD', '1m')
    store.candles.add_candle(
        generate_candle_from_one_minutes('5m', candles_to_add[0:5], False),
        'Sandbox', 'BTCUSD', '5m')
    store.candles.add_candle(
        generate_candle_from_one_minutes('5m', candles_to_add[5:10], False),
        'Sandbox', 'BTCUSD', '5m')

    assert len(store.candles.get_candles('Sandbox', 'BTCUSD', '5m')) == 3
    assert len(store.candles.get_candles('Sandbox', 'BTCUSD', '1m')) == 14

    candles = store.candles.get_candles('Sandbox', 'BTCUSD', '5m')
    assert candles[0][0] == candles_to_add[0][0]
    assert candles[-1][2] == candles_to_add[13][2]
    assert candles[-1][0] == candles_to_add[10][0]

    # add third one while still a forming candle. Now since
    # we already have forming, get_candles() must not
    # append another forming candle to the end.
    store.candles.add_candle(
        generate_candle_from_one_minutes('5m', candles_to_add[10:14], True),
        'Sandbox', 'BTCUSD', '5m')

    assert len(store.candles.get_candles('Sandbox', 'BTCUSD', '5m')) == 3
    assert candles[-1][2] == candles_to_add[13][2]
    assert candles[-1][0] == candles_to_add[10][0]
示例#4
0
def test_strategy_properties():
    set_up([
        (exchanges.SANDBOX, 'ETHUSDT', timeframes.MINUTE_5, 'Test19'),
        (exchanges.SANDBOX, 'BTCUSDT', timeframes.MINUTE_5, 'Test19'),
    ])

    candles = {}
    routes = router.routes
    for r in routes:
        key = jh.key(r.exchange, r.symbol)
        candles[key] = {
            'exchange': r.exchange,
            'symbol': r.symbol,
            'candles': fake_range_candle((5 * 3) * 20)
        }

    # run backtest (dates are fake just to pass)
    backtest_mode.run('2019-04-01', '2019-04-02', candles)

    for r in routes:
        s: Strategy = r.strategy

        assert s.name == r.strategy_name
        assert s.symbol == r.symbol
        assert s.exchange == r.exchange
        assert s.timeframe == r.timeframe
        assert s.trade is None
        assert s._is_executing is False
        assert s._is_initiated is True
        np.testing.assert_equal(s.current_candle, store.candles.get_current_candle(r.exchange, r.symbol, r.timeframe))
        np.testing.assert_equal(s.candles, store.candles.get_candles(r.exchange, r.symbol, r.timeframe))
        assert s.position == selectors.get_position(r.exchange, r.symbol)
        assert s.orders == store.orders.get_orders(r.exchange, r.symbol)
示例#5
0
def test_backtesting_one_route():
    reset_config()
    router.set_routes([
        (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5, 'Test19')
    ])
    config['env']['exchanges'][exchanges.SANDBOX]['type'] = 'margin'
    store.reset(True)

    candles = {}
    key = jh.key(exchanges.SANDBOX, 'BTC-USDT')
    candles[key] = {
        'exchange': exchanges.SANDBOX,
        'symbol': 'BTC-USDT',
        'candles': fake_range_candle(5 * 20)
    }
    routes = router.routes

    # assert that strategy hasn't been initiated before running backtest_mode()
    assert routes[0].strategy is None

    # run backtest (dates are fake just to pass)
    backtest_mode.run('2019-04-01', '2019-04-02', candles)

    one_min = store.candles.get_candles(exchanges.SANDBOX, 'BTC-USDT', '1m')
    five_min = store.candles.get_candles(exchanges.SANDBOX, 'BTC-USDT', '5m')

    # assert the count of present candles
    assert len(five_min) == 20
    assert len(one_min) == 20 * 5

    first_1 = one_min[0]
    last_1 = one_min[-1]
    first_5 = five_min[0]
    last_5 = five_min[-1]

    # assert time in store
    assert store.app.time == last_1[0] + 60000

    # assert timestamps
    assert first_1[0] == first_5[0]
    assert last_1[0] == (last_5[0] + 60000 * 4)

    # there must be only one positions present
    assert len(store.positions.storage) == 1
    p = selectors.get_position(exchanges.SANDBOX, 'BTC-USDT')
    assert p.is_close
    assert p.current_price == last_1[2]
    assert p.current_price == last_5[2]

    # assert routes
    assert len(routes) == 1
    assert routes[0].exchange == exchanges.SANDBOX
    assert routes[0].symbol == 'BTC-USDT'
    assert routes[0].timeframe == '5m'
    assert routes[0].strategy_name == 'Test19'
    # assert that the strategy has been initiated
    assert routes[0].strategy is not None
示例#6
0
def test_generate_candle_from_one_minutes():
    candles = fake_range_candle(5)

    five_minutes_candle = generate_candle_from_one_minutes('5m', candles)

    assert five_minutes_candle[0] == candles[0][0]
    assert five_minutes_candle[1] == candles[0][1]
    assert five_minutes_candle[2] == candles[-1][2]
    assert five_minutes_candle[3] == candles[:, 3].max()
    assert five_minutes_candle[4] == candles[:, 4].min()
    assert five_minutes_candle[5] == candles[:, 5].sum()
示例#7
0
def test_batch_add_candles():
    set_up()

    assert len(store.candles.get_candles('Sandbox', 'BTCUSD', '1m')) == 0

    # create 100 candles
    candles_to_add = fake_range_candle(100)
    assert len(candles_to_add) == 100

    store.candles.batch_add_candle(candles_to_add, 'Sandbox', 'BTCUSD', '1m')
    np.testing.assert_equal(store.candles.get_candles('Sandbox', 'BTCUSD', '1m'), candles_to_add)
示例#8
0
def test_should_buy_and_execute_buy():
    set_up([
        (exchanges.SANDBOX, 'ETHUSD', timeframes.MINUTE_5, 'Test01'),
    ])

    candles = {}
    routes = router.routes
    for r in routes:
        key = jh.key(r.exchange, r.symbol)
        candles[key] = {
            'exchange': r.exchange,
            'symbol': r.symbol,
            'candles': fake_range_candle((5 * 3) * 20)
        }

    # run backtest (dates are fake just to pass)
    backtest_mode.run('2019-04-01', '2019-04-02', candles)

    ss1 = store

    for r in routes:
        s: Strategy = r.strategy
        p = s.position

        assert p.is_close is True
        assert len(s.orders) == 3
        o: Order = s.orders[0]
        short_candles = store.candles.get_candles(r.exchange, r.symbol, '1m')
        assert o.price == short_candles[4][2]
        assert o.price == s.candles[0][2]
        assert o.created_at == short_candles[4][0] + 60_000
        assert o.is_executed is True
        assert s.orders[1].role == order_roles.CLOSE_POSITION
        assert s.orders[2].role == order_roles.CLOSE_POSITION
        assert s.orders[0].role == order_roles.OPEN_POSITION
        assert s.trade is None
        trade: CompletedTrade = store.completed_trades.trades[0]
        assert trade.type == 'long'
        # must include executed orders, in this case it's entry and take_profit
        assert len(trade.orders) == 2
        assert trade.orders[0].side == 'buy'
        assert trade.orders[0].type == 'MARKET'
        assert trade.orders[1].side == 'sell'
        assert trade.orders[1].type == 'LIMIT'
        assert len(store.completed_trades.trades) == 1
示例#9
0
def test_can_perform_backtest_with_multiple_routes():
    set_up([
        (exchanges.SANDBOX, 'ETH-USDT', timeframes.MINUTE_5, 'Test01'),
        (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5, 'Test02'),
    ])

    candles = {}
    routes = router.routes
    for r in routes:
        key = jh.key(r.exchange, r.symbol)
        candles[key] = {
            'exchange': r.exchange,
            'symbol': r.symbol,
            'candles': fake_range_candle((5 * 3) * 20)
        }

    # run backtest (dates are fake just to pass)
    backtest_mode.run('2019-04-01', '2019-04-02', candles)

    for r in routes:
        s: Strategy = r.strategy
        p = s.position

        assert p.is_close is True
        assert len(s.orders) == 3
        o: Order = s.orders[0]
        short_candles = store.candles.get_candles(r.exchange, r.symbol, '1m')
        assert o.price == short_candles[4][2]
        assert o.price == s.candles[0][2]
        assert o.created_at == short_candles[4][0] + 60_000
        assert o.is_executed is True
        assert s.orders[0].role == order_roles.OPEN_POSITION
        assert s.orders[0].type == order_types.MARKET
        assert s.orders[2].role == order_roles.CLOSE_POSITION
        assert s.orders[2].type == order_types.STOP
        assert s.orders[1].role == order_roles.CLOSE_POSITION
        assert s.orders[1].type == order_types.LIMIT
        assert s.trade is None
        assert len(store.completed_trades.trades) == 2
        # assert one is long and the other is a short trade
        assert (store.completed_trades.trades[0].type == 'long'
                and store.completed_trades.trades[1].type == 'short') or (
                    store.completed_trades.trades[0].type == 'short'
                    and store.completed_trades.trades[1].type == 'long')
示例#10
0
def test_multiple_routes_can_communicate_with_each_other():
    set_up([
        (exchanges.SANDBOX, 'ETH-USDT', timeframes.MINUTE_5, 'Test03'),
        (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5, 'Test03'),
    ])

    candles = {}
    routes = router.routes
    for r in routes:
        key = jh.key(r.exchange, r.symbol)
        candles[key] = {
            'exchange': r.exchange,
            'symbol': r.symbol,
            'candles': fake_range_candle((5 * 3) * 20)
        }

    # run backtest (dates are fake just to pass)
    backtest_mode.run('2019-04-01', '2019-04-02', candles)

    assert len(store.completed_trades.trades) == 1

    for r in routes:
        s: Strategy = r.strategy
        p = s.position

        assert p.is_close is True
        o: Order = s.orders[0]
        short_candles = store.candles.get_candles(r.exchange, r.symbol, '1m')
        assert o.created_at == short_candles[4][0] + 60_000
        if r.strategy.trades_count == 1:
            assert len(s.orders) == 3
            assert o.is_executed is True
            assert s.orders[0].role == order_roles.OPEN_POSITION
            assert s.orders[0].type == order_types.LIMIT
            assert s.orders[2].role == order_roles.CLOSE_POSITION
            assert s.orders[2].type == order_types.STOP
            assert s.orders[1].role == order_roles.CLOSE_POSITION
            assert s.orders[1].type == order_types.LIMIT
        elif r.strategy.trades_count == 0:
            assert len(s.orders) == 1
            # assert that the order got canceled
            assert o.is_canceled is True
            assert s.orders[0].role == order_roles.OPEN_POSITION
            assert s.orders[0].type == order_types.LIMIT
示例#11
0
def test_get_past_candle():
    set_up()

    candles_to_add = fake_range_candle(14)
    store.candles.batch_add_candle(candles_to_add, 'Sandbox', 'BTCUSD', '1m')
    store.candles.add_candle(
        generate_candle_from_one_minutes('5m', candles_to_add[0:5]), 'Sandbox',
        'BTCUSD', '5m')
    store.candles.add_candle(
        generate_candle_from_one_minutes('5m', candles_to_add[5:10]),
        'Sandbox', 'BTCUSD', '5m')
    assert len(store.candles.get_candles('Sandbox', 'BTCUSD', '1m')) == 14

    # get_past_candle() should act as if there are 3 candles (last one being the forming)
    np.testing.assert_equal(
        store.candles.get_past_candle('Sandbox', 'BTCUSD', '5m', 1),
        store.candles.storage[jh.key('Sandbox', 'BTCUSD', '5m')][1])

    np.testing.assert_equal(
        store.candles.get_past_candle('Sandbox', 'BTCUSD', '5m', 0),
        generate_candle_from_one_minutes('5m', candles_to_add[10:], True))
示例#12
0
def test_should_sell_and_execute_sell():
    set_up([
        (exchanges.SANDBOX, 'ETH-USDT', timeframes.MINUTE_5, 'Test02'),
    ])

    candles = {}
    routes = router.routes
    for r in routes:
        key = jh.key(r.exchange, r.symbol)
        candles[key] = {
            'exchange': r.exchange,
            'symbol': r.symbol,
            'candles': fake_range_candle((5 * 3) * 20)
        }

    # run backtest (dates are fake just to pass)
    backtest_mode.run('2019-04-01', '2019-04-02', candles)

    for r in routes:
        s: Strategy = r.strategy
        p = s.position

        assert p.is_close is True
        assert len(s.orders) == 3
        o: Order = s.orders[0]
        short_candles = store.candles.get_candles(r.exchange, r.symbol, '1m')
        assert o.price == short_candles[4][2]
        assert o.price == s.candles[0][2]
        assert o.created_at == short_candles[4][0] + 60_000
        assert o.is_executed is True
        assert s.orders[1].role == order_roles.CLOSE_POSITION
        assert s.orders[2].role == order_roles.CLOSE_POSITION
        assert s.orders[0].role == order_roles.OPEN_POSITION
        assert s.trade is None
        assert len(store.completed_trades.trades) == 1
        assert store.completed_trades.trades[0].type == 'short'