示例#1
0
def test_imbalance(mocker):
    """ Test imbalance calculation """
    mocker.patch('rlmarket.environment.exchange_elements.pickle.load',
                 return_value=[])
    mocker.patch('builtins.open', mocker.mock_open())

    env = Exchange('', 0, indicators=[])
    ind = Imbalance(2, decay=0)
    assert ind.dimension == 1
    env.book.add_limit_order(LimitOrder(1, 1, 'B', 10000, 100))
    env.book.add_limit_order(LimitOrder(2, 2, 'S', 12000, 100))
    assert ind.update(env) == (0, )

    env.book.add_limit_order(LimitOrder(3, 3, 'S', 11000, 100))
    assert ind.update(env) == (-100 / 300, )

    env.book.match_limit_order(MarketOrder(4, 3, 'B', 50))
    assert ind.update(env) == (-50 / 250, )

    env.book.add_limit_order(LimitOrder(4, 4, 'B', 9000, 100))
    assert ind.update(env) == (50 / 350, )

    # We only use the first two levels
    env.book.add_limit_order(LimitOrder(5, 5, 'B', 8000, 100))
    assert ind.update(env) == (50 / 350, )

    ind = Imbalance(2, decay=1)
    bid_vol = 100 + 100 * np.exp(1)
    ask_vol = 100 + 50 * np.exp(1)
    assert abs(ind.update(env)[0] - (bid_vol - ask_vol) /
               (bid_vol + ask_vol)) < 1E-10
def test_pnl_calculation():
    """
    Test private method _calculate_pnl
    * Buy and sell
    * Same side no execution. Queue increases
    * Opposite side
        * shares < queued shares
        * shares == queued shares
        * shares > queued shares
            * Multiple shares
    """
    exchange = NewExchange(files=[''],
                           indicators=[Position(),
                                       Imbalance(1, decay=0)],
                           reward_lb=-1000,
                           reward_ub=1000,
                           start_time=start_time,
                           end_time=end_time,
                           latency=delta,
                           order_size=50,
                           position_limit=100)

    # Case 1 - shares < queued shares
    assert exchange._calculate_pnl(Execution(1, 100, 100)) == 0
    assert exchange._calculate_pnl(Execution(2, 120, -50)) == 1000
    assert len(exchange._open_positions) == 1
    assert exchange._open_positions[0].price == 100
    assert exchange._open_positions[0].shares == 50

    # Case 2 - shares == queued shares
    assert exchange._calculate_pnl(Execution(3, 90, -50)) == -500
    assert len(exchange._open_positions) == 0

    # Case 3 - same side
    assert exchange._calculate_pnl(Execution(4, 100, -100)) == 0
    assert exchange._calculate_pnl(Execution(5, 110, -100)) == 0
    assert exchange._calculate_pnl(Execution(6, 120, -100)) == 0
    assert len(exchange._open_positions) == 3

    # Case ? - FIFO
    assert exchange._calculate_pnl(Execution(7, 110, 50)) == -500

    # Case 4 - shares > queued shares
    assert exchange._calculate_pnl(Execution(
        8, 90, 200)) == 10 * 50 + 20 * 100 + 30 * 50
    assert len(exchange._open_positions) == 1
    assert exchange._open_positions[0].price == 120
    assert exchange._open_positions[0].shares == -50
def test_block_exchange(mocker):
    """
    * Test if the correct reward and metric are outputted
    * Test liquidation
    """
    mocker.patch('rlmarket.environment.exchange_elements.pickle.load',
                 return_value=deepcopy(tape))
    mocker.patch('builtins.open', mocker.mock_open())

    exchange = NewExchange(files=[''],
                           indicators=[Position(),
                                       Imbalance(1, decay=0)],
                           reward_lb=-2000,
                           reward_ub=2000,
                           start_time=start_time,
                           end_time=end_time,
                           latency=delta,
                           order_size=50,
                           position_limit=100)

    assert exchange.state_dimension == 2

    state = exchange.reset()
    assert exchange.book.quote == (10000, 12000)
    assert state == (0, 50 / 250)

    state, reward, pnl1, done = exchange.step(3)  # Buy 50 @ 10000
    assert state == (50, -75 / 125)
    assert reward == 0
    assert pnl1 == 0
    assert not done

    state, reward, pnl2, done = exchange.step(3)  # Sell 50 @ 12000
    assert state == (0, -75 / 125)
    assert reward == 10
    assert pnl2 == 10
    assert not done

    state, reward, pnl3, done = exchange.step(3)  # Buy 50 @ 9000
    assert state == (50, -50 / 150)
    assert reward == 0
    assert pnl3 == 0
    assert not done

    state, reward, pnl4, done = exchange.step(
        3)  # Buy 50 @ 8000 and liquidate 20 @ 6000
    assert state == (80, -50 / 150)
    assert reward == -20  # Two times of reward lower bound because of liquidation
    assert pnl4 == -6
    assert not done

    state, reward, pnl5, done = exchange.step(3)  # Sell 50 @ 13000
    assert state == (30, 25 / 75)
    assert reward == 10  # Reach upper bound
    assert pnl5 == 30 * 0.4 + 20 * 0.5
    assert not done

    state, reward, pnl6, done = exchange.step(3)  # Sell 50 @ 14000
    assert state == (-20, 0)
    assert reward == 10  # Reach upper bound
    assert pnl6 == 30 * 0.6
    assert not done

    # Total
    total_pnl = pnl1 + pnl2 + pnl3 + pnl4 + pnl5 + pnl6
    assert total_pnl == -50 * 1 + 50 * 1.2 - 50 * 0.9 - 50 * 0.8 + 20 * 0.6 + 50 * 1.3 + 30 * 1.4

    # Finishing
    assert not exchange.book.empty
    exchange.clean_up()
    assert exchange.book.empty

    # Test restart. Should output the same stats
    mocker.patch('rlmarket.environment.exchange_elements.pickle.load',
                 return_value=deepcopy(tape))
    state = exchange.reset()
    assert exchange.book.quote == (10000, 12000)
    assert state == (0, 50 / 250)

    _, _, metric, _ = exchange.step(3)
    assert metric == 0
    _, _, metric, _ = exchange.step(3)
    assert metric == 10
    _, _, metric, _ = exchange.step(3)
    assert metric == 0
    _, _, metric, _ = exchange.step(3)
    assert metric == -6
    _, _, metric, _ = exchange.step(3)
    assert metric == 22
    _, _, metric, _ = exchange.step(3)
    assert metric == 18
示例#4
0
    environment.clean_up()
    print(f'Pnl: {total_pnl} / Reward: {total_reward}')


if __name__ == '__main__':
    # Parameters
    order_size = 50
    position_limit = 1000
    liquidation_ratio = 0.2
    reward_lb = -0.004
    reward_ub = 0.002

    indicators = [
        MidPriceDeltaSign(3),
        Imbalance(),
        NormalizedPosition(position_limit)
    ]

    env = RelativeExchange(files=[
        'AAPL_20170201', 'AAPL_20170202', 'AAPL_20170203', 'AAPL_20170206'
    ],
                           indicators=indicators,
                           reward_lb=reward_lb,
                           reward_ub=reward_ub,
                           start_time=34230000000000,
                           end_time=57540000000000,
                           order_size=order_size,
                           position_limit=position_limit,
                           liquidation_ratio=liquidation_ratio)
示例#5
0
def test_block_exchange(mocker):
    """
    * Test if the correct reward and metric are outputted
    * Test liquidation
    """
    mocker.patch('rlmarket.environment.exchange_elements.pickle.load',
                 return_value=deepcopy(tape))
    mocker.patch('builtins.open', mocker.mock_open())

    exchange = BlockExchange(files=[''],
                             indicators=[Position(),
                                         Imbalance(1, decay=0)],
                             start_time=start_time,
                             end_time=end_time,
                             latency=delta,
                             order_size=50,
                             position_limit=100,
                             block_size=2)

    assert exchange.state_dimension == 2

    state = exchange.reset()
    assert exchange.book.quote == (10000, 12000)
    assert state == (0, 50 / 250)

    # ====== Block 1 ======
    state, reward, metric, done = exchange.step(0)  # Buy 50 @ 10000
    assert state == (50, -75 / 125)
    assert reward is None
    assert metric is None
    assert not done

    state, reward, metric, done = exchange.step(0)  # Sell 50 @ 12000
    assert state == (0, -75 / 125)
    assert reward is None
    assert metric is None
    assert not done

    state, reward, metric1, done = exchange.step(0)  # Buy 50 @ 9000
    assert state == (50, -50 / 150)
    assert reward == 0.25 + (2.5 + 5)  # last spread profit is not count
    assert metric1 == 2.5 + (2.5 + 5 + 7.5)
    assert not done

    # ====== Block 2 ======
    state, reward, metric, done = exchange.step(0)  # Buy 50 @ 8000
    assert state == (80, -50 / 150)
    assert reward is None
    assert metric is None
    assert not done

    state, reward, metric, done = exchange.step(0)  # Sell 50 @ 13000
    assert state == (30, 25 / 75)
    assert reward is None
    assert metric is None
    assert not done

    state, reward, metric2, done = exchange.step(0)  # Sell 50 @ 14000
    assert state == (-20, 0)
    assert reward == (-50 * 1.05 - 50 * 1 + 20 * 0.95 + 50 * 1 +
                      30 * 1.1) + (10 - 7 + 15)
    assert metric2 == (-50 * 1.05 - 50 * 1 + 20 * 0.95 + 50 * 1 +
                       30 * 1.1) + (10 - 7 + 15 + 15)
    assert not done

    # Total
    assert metric1 + metric2 == -50 * 1 + 50 * 1.2 - 50 * 0.9 - 50 * 0.8 + 20 * 0.6 + 50 * 1.3 + 50 * 1.4 - 20 * 1.1

    # Finishing
    assert not exchange.book.empty
    exchange.clean_up()
    assert exchange.book.empty

    # Test restart. Should output the same stats
    mocker.patch('rlmarket.environment.exchange_elements.pickle.load',
                 return_value=deepcopy(tape))
    state = exchange.reset()
    assert exchange.book.quote == (10000, 12000)
    assert state == (0, 50 / 250)

    _, _, metric, _ = exchange.step(0)
    assert metric is None
    _, _, metric, _ = exchange.step(0)
    assert metric is None
    _, _, metric1, _ = exchange.step(0)
    assert metric1 == 2.5 + (2.5 + 5 + 7.5)
示例#6
0
def test_exchange(mocker):
    mocker.patch('rlmarket.environment.exchange_elements.pickle.load',
                 return_value=deepcopy(tape))
    mocker.patch('builtins.open', mocker.mock_open())

    position_limit = 100

    exchange = AbsoluteExchange(
        files=[''],
        indicators=[Position(), Imbalance(1, decay=0)],
        reward_lb=-0.2,
        reward_ub=0.3,  # Bounds in percentage
        start_time=start_time,
        end_time=end_time,
        latency=delta,
        order_size=50,
        position_limit=position_limit)

    assert exchange.observation_space.shape == (2, )

    state = exchange.reset()
    assert exchange.book.quote == (10000, 12000)
    assert_almost_equal(state, (0, 50 / 250))

    total_pnl = 0

    state, reward, done, info = exchange.step(3)  # Buy 50 @ 10000
    assert_almost_equal(state, (50, -75 / 125))
    assert reward == 0
    assert info['pnl'] == 0
    assert not done
    total_pnl += info['pnl']

    state, reward, done, info = exchange.step(3)  # Sell 50 @ 12000
    assert_almost_equal(state, (0, -75 / 125))
    assert reward == 10
    assert info['pnl'] == 10
    assert not done
    total_pnl += info['pnl']

    state, reward, done, info = exchange.step(3)  # Buy 50 @ 9000
    assert_almost_equal(state, (50, -50 / 150))
    assert reward == 0
    assert info['pnl'] == 0
    assert not done
    total_pnl += info['pnl']

    state, reward, done, info = exchange.step(
        3)  # Buy 50 @ 8000 and liquidate 20 @ 6000
    assert_almost_equal(state, (80, -50 / 150))
    assert reward == -4  # Two times of reward lower bound because of liquidation
    assert info['pnl'] == -6
    assert not done
    total_pnl += info['pnl']

    state, reward, done, info = exchange.step(3)  # Sell 50 @ 13000
    assert_almost_equal(state, (30, 25 / 75))
    assert reward == 15  # Reach upper bound
    assert info['pnl'] == 30 * 0.4 + 20 * 0.5
    assert not done
    total_pnl += info['pnl']

    state, reward, done, info = exchange.step(3)  # Sell 50 @ 14000
    assert_almost_equal(state, (-20, 0))
    assert reward == 9  # Close out 30 shares at a profit of 0.36 -> 0.3 * 30 = 9
    assert info['pnl'] == 30 * 0.6
    assert not done
    total_pnl += info['pnl']

    # Total
    assert total_pnl == -50 * 1 + 50 * 1.2 - 50 * 0.9 - 50 * 0.8 + 20 * 0.6 + 50 * 1.3 + 30 * 1.4

    # Finishing
    assert not exchange.book.empty
    exchange.clean_up()
    assert exchange.book.empty

    # Test restart. Should output the same stats
    mocker.patch('rlmarket.environment.exchange_elements.pickle.load',
                 return_value=deepcopy(tape))
    state = exchange.reset()
    assert exchange.book.quote == (10000, 12000)
    assert_almost_equal(state, (0, 50 / 250))

    _, _, _, info = exchange.step(3)
    assert info['pnl'] == 0
    _, _, _, info = exchange.step(3)
    assert info['pnl'] == 10
    _, _, _, info = exchange.step(3)
    assert info['pnl'] == 0
    _, _, _, info = exchange.step(3)
    assert info['pnl'] == -6
    _, _, _, info = exchange.step(3)
    assert info['pnl'] == 22
    _, _, _, info = exchange.step(3)
    assert info['pnl'] == 18
示例#7
0
def test_basic_exchange(mocker):
    """
    * Test order placement with latency
        * Test that once an order is executed, another will be cancelled
    * Test liquidation
    """
    mocker.patch('rlmarket.environment.exchange_elements.pickle.load',
                 return_value=tape)
    mocker.patch('builtins.open', mocker.mock_open())

    exchange = Exchange(files=[''],
                        indicators=[Position(),
                                    Imbalance(1, decay=0)],
                        start_time=start_time,
                        end_time=end_time,
                        latency=delta,
                        order_size=50,
                        position_limit=100)

    state = exchange.reset()
    assert exchange.state_dimension == 2
    assert exchange.book.quote == (10000, 12000)
    assert state == (0, 50 / 250)

    # Test order placement
    state, reward, metric, done = exchange.step(
        0)  # Placed order at 10000 and 12000
    assert state == (50, -75 / 125
                     )  # Real level is already move to the 9000 level
    assert reward == 0
    assert metric == 0
    assert not done

    assert exchange.book.bid_book.user_order_info is None
    assert exchange.book.ask_book.user_order_info is None  # Order is cancelled

    # Test order placement - complete an update full cycle to output rewards
    state, reward, metric, done = exchange.step(
        0)  # Placing order at 9000 and 12000
    assert exchange.book.quote == (9000, 13000)
    assert state == (0, -75 / 125
                     )  # Real level is already move to the 9000 level
    assert reward == 2.5 + 2.5 * 0.1  # Last reward
    assert metric == 2.5 + 2.5
    assert not done

    # Last cycle finishes. Clean start
    assert exchange.book.bid_book.user_order_info is None
    assert exchange.book.ask_book.user_order_info is None

    # Test liquidation
    state, reward, metric, done = exchange.step(
        0)  # Placing order at 9000 and 13000
    assert exchange.book.quote == (8000, 13000)
    assert state == (50, -50 / 150)  # Real level is at 9000 and 12000
    assert reward == 5  # No position pnl because position was 0
    assert metric == 5
    assert not done

    state, reward, metric, done = exchange.step(
        0)  # Placing order at 8000 and 13000
    assert exchange.book.quote == (6000, 14000)  # Order 7 is cancelled
    print(exchange.book.get_depth(5))
    assert state == (
        80, 0)  # Liquidation. Also, Order 5 of 50 shares vs Order 8 of 50
    assert reward == 7.5 - 5
    assert metric == 7.5 - 5
    assert not done

    # Market is cleared
    state, reward, metric, done = exchange.step(0)
    assert state == (30, 0)
    assert reward == 7.5 - 8 + 13 * 0.1
    assert metric == 7.5 - 8 + 13
    assert not done
    assert not exchange.book.empty

    # Final cleanup
    exchange.clean_up()
    assert exchange.book.empty