def test_reset_sets_amount_to_start_amount(rates): rates.add_record(entry("BTC_ETH", 2), entry("ETH_BTC", 0.5)) \ .add_record(entry("BTC_ETH", 3), entry("ETH_BTC", 0.33)).finish() env = make_env(rates, start_amount=2) env.step("ETH") env.reset() assert env.amount == 2
def test_calculate_correct_statistics_of_multiple_entries(rates): rates.add_record(entry("BTC_ETH", "10"), entry("LIC_GAME", "2")) \ .add_record(entry("BTC_ETH", "6"), entry("LIC_GAME", "1")).finish() assert str(analyze(rates)) == " EXCHANGE | MEAN | SD | MEDIAN | MIN | MAX | DIF \n" \ "-------------------------------------------------------------------------\n" \ " BTC_ETH | 8.0| 2.0| 10.0| 6.0| 10.0| -4.0\n" \ " LIC_GAME | 1.5| 0.5| 2.0| 1.0| 2.0| -1.0\n"
def test_long_and_short(rates): rates.add_record(entry("BTC_ETH", "1")).add_record(entry("BTC_ETH", "2")).add_record( entry("BTC_ETH", "3")).finish() vis, plotter = make_visualizer(rates) vis.record_exchange(0, "ETH") vis.record_exchange(2, "BTC") vis.render("BTC_ETH") assert plotter.plots[0] == (( 0, Decimal('1'), 'o', ), { 'markerfacecolor': 'r', 'markeredgecolor': 'k', 'markersize': 10 }) assert plotter.plots[1] == (( 2, Decimal('3'), '^', ), { 'markerfacecolor': 'g', 'markeredgecolor': 'k', 'markersize': 10 }) assert plotter.plots[2] == (([Decimal('1'), Decimal('2'), Decimal('3')], ), { 'color': 'blue', 'label': 'Rate' })
def test_current_balance(rates): rates.add_record(entry("BTC_ETH", "2")).add_record(entry("BTC_ETH", "3")).finish() env = make_env(rates, start_coin="BTC", start_amount=2) env.step(None) assert env.balance_in("BTC") == 2 assert env.balance_in("ETH") == 6
def test_data_too_small_for_window(rates): rates.add_record(entry("BTC_ETH", 1)).add_record(entry("BTC_ETH", 2)).finish() with pytest.raises(WindowError) as e: make_env(rates, window=3) assert str( e.value) == "There is not enough data to fill the window of size 3"
def test_agent_step_received_all_but_last_reward(env, agent_spy): env.add_record(entry("BTC_ETH", 1), None) \ .add_record(entry("BTC_ETH", 2), 3) \ .add_record(entry("BTC_ETH", 3), -10) \ .add_record(entry("BTC_ETH", 4), 9).finish() make_session(env, agent_spy).run() assert agent_spy.received_rewards == [3, -10]
def test_calculates_rate_if_calculator_is_provided(rates): rates.add_record(entry("BTC_ETH", 1.1)) \ .add_record(entry("BTC_ETH", 1.2)).finish() env = make_env(rates, reward_calculator=lambda e: 2.0) _, r, _, _ = env.step(None) assert r == 2.0
def test_multiple_exchange_rates(rates): rates.add_record(entry("BTC_ETH", "1.267"), entry("LIC_GAME", "10.9")).finish() assert str(analyze(rates)) == " EXCHANGE | MEAN | SD | MEDIAN | MIN | MAX | DIF \n" \ "-------------------------------------------------------------------------\n" \ " BTC_ETH | 1.267| 0.0| 1.267| 1.267| 1.267| 0.0\n" \ " LIC_GAME | 10.9| 0.0| 10.9| 10.9| 10.9| 0.0\n"
def test_calculate_correct_statistics(rates): rates.add_record(entry("BTC_ETH", "10")) \ .add_record(entry("BTC_ETH", "5")) \ .add_record(entry("BTC_ETH", "12")).finish() assert str(analyze(rates)) == " EXCHANGE | MEAN | SD | MEDIAN | MIN | MAX | DIF \n" \ "-------------------------------------------------------------------------\n" \ " BTC_ETH | 9.0|2.94392028| 10.0| 5.0| 12.0| 2.0\n"
def test_exchanging_to_itself(rates): rates.add_record(entry("BTC_ETH", "12", "0.002")) \ .add_record(entry("BTC_ETH", "14")).finish() env = make_env(rates, "BTC", 2) env.step("BTC") assert env.amount == 2 assert env.token == "BTC"
def test_exchanging(rates): rates.add_record(entry("BTC_ETH", "12", "0.002"), entry("ETH_BTC", "0.12")) \ .add_record(entry("BTC_ETH", "14"), entry("ETH_BTC", "0.14")).finish() env = make_env(rates, "BTC", 2) env.step("ETH") assert env.amount == 23.998 assert env.token == "ETH"
def test_visualize_meta_data(rates): rates.add_record(entry("BTC_ETH", "1")).add_record(entry("BTC_ETH", "2")).finish() vis, plotter = make_visualizer(rates) vis.render("BTC_ETH") assert plotter.title_str == "BTC_ETH" assert plotter.x_axis == "Time" assert plotter.y_axis == "Rate"
def test_calculating_loss(env, agent): env.add_record(entry("BTC_ETH", 1)) \ .add_record(entry("BTC_ETH", 2, miner_fee=0)) \ .add_record(entry("ETH_BTC", "0.5")).finish() agent.set_actions(None, "ETH") sess = make_session(env, agent) sess.run() assert sess.difference() == Decimal(0)
def test_balance_after_exchange(rates): rates.add_record(entry("BTC_ETH", "2", miner_fee="0.1")).add_record(entry("ETH_BTC", "1")).finish() env = make_env(rates, start_coin="BTC", start_amount=2) env.step("ETH") assert env.balance_in("BTC") == 3.9 assert env.balance_in("ETH") == 3.9
def test_step_yields_next_state(rates): rates.add_record(entry("BTC_ETH", 1.1)) \ .add_record(entry("BTC_ETH", 1.2)).finish() env = make_env(rates) s, _, _, _ = env.step(None) assert s["token"] == "BTC" assert s["balance"] == 1 assert s["rates"][0]["BTC_ETH"] == entry("BTC_ETH", 1.2)
def test_action_not_in_mapping_counts_as_none(rates): rates.add_record(entry("BTC_ETH", "2", "0"), entry("ETH_BTC", "0.5", "0")) \ .add_record(entry("BTC_ETH", "1", "0"), entry("ETH_BTC", "1", "0")).finish() s, _, _, _ = make_env(rates, start_coin="BTC", index_to_coin={ 1: "BTC", 2: "ETH" }).step(0) assert s[1] == 0.0
def test_normalized_balance(rates): rates.add_record(entry("BTC_ETH", "2", "0"), entry("ETH_BTC", "0.5", "0")) \ .add_record(entry("BTC_ETH", "1", "0"), entry("ETH_BTC", "1", "0")).finish() s, _, _, _ = make_env(rates, start_coin="BTC", index_to_coin={ 0: "BTC", 1: "ETH" }).step(1) assert s[1] == 1.0
def test_visualize_rates(rates): rates.add_record(entry("BTC_ETH", "1")).add_record(entry("BTC_ETH", "2")).finish() vis, plotter = make_visualizer(rates) vis.render("BTC_ETH") assert plotter.is_shown is True assert plotter.plots[0] == (([Decimal('1'), Decimal('2')], ), { 'color': 'blue', 'label': 'Rate' })
def test_transform_rates_if_specified(rates): rates.add_record(entry("BTC_ETH", 1.1)) \ .add_record(entry("BTC_ETH", 1.2)).finish() env = make_env(rates, transform=lambda s: float(s["rates"][0]["BTC_ETH"].rate)) s = env.reset() assert s == 1.1 s, _, _, _ = env.step(None) assert s == 1.2
def test_environment_with_window(rates): rates.add_record(entry("BTC_ETH", 1.1)) \ .add_record(entry("BTC_ETH", 1.2)) \ .add_record(entry("BTC_ETH", 1.3)).finish() s = make_env(rates, window=2).reset() assert s["rates"] == [{ "BTC_ETH": entry("BTC_ETH", 1.1) }, { "BTC_ETH": entry("BTC_ETH", 1.2) }]
def test_reset_returns_environment_to_start(rates): rates.add_record(entry("BTC_ETH", 1.1)) \ .add_record(entry("BTC_ETH", 1.2)).finish() env = make_env(rates) env.step(None) env.reset() s, _, _, _ = env.step(None) assert s["token"] == "BTC" assert s["balance"] == 1 assert s["rates"][0]["BTC_ETH"] == entry("BTC_ETH", 1.2)
def test_calculated_differences_are_normalized(q_function, policy_spy): env = CryptoEnvironmentStub(action_to_token={ 1: "BTC", 2: "ETH" }, active_token="BTC") env.add_record(entry("BTC_ETH", "10")). \ add_record(entry("BTC_ETH", "8.1")).finish() policy = make_policy(env, policy_spy, 1.0, threshold=0.2) policy.select(A_STATE, q_function) assert policy_spy.received_select_args == (A_STATE, q_function)
def test_agent_received_initial_state_as_start(env, agent_spy): env.add_record(entry("BTC_ETH", 1)).add_record(entry("BTC_ETH", 2)).finish() make_session(env, agent_spy).run() assert agent_spy.received_start_state == { "token": "BTC", "balance": Decimal("2"), "rates": [{ "BTC_ETH": entry("BTC_ETH", 1) }] }
def test_coin_not_part_of_render_exchange(rates): rates.add_record(entry("BTC_ETH", "1")).add_record(entry("BTC_ETH", "2")).add_record( entry("BTC_ETH", "3")).finish() vis, plotter = make_visualizer(rates) vis.record_exchange(1, "RPL") vis.render("BTC_ETH") assert plotter.plots[0] == (([Decimal('1'), Decimal('2'), Decimal('3')], ), { 'color': 'blue', 'label': 'Rate' })
def test_rigging_leaves_rates_unaffected(q_function): env = CryptoEnvironmentStub(action_to_token={ 1: "BTC", 2: "ETH" }, active_token="BTC") env.add_record(entry("BTC_ETH", "2")). \ add_record(entry("BTC_ETH", "4")). \ add_record(entry("BTC_ETH", "1")). \ add_record(entry("BTC_ETH", "3")).finish() policy = make_policy(env, policy_spy, 1.0) policy.select(A_STATE, q_function) assert next(env.rates_stream)["BTC_ETH"] == entry("BTC_ETH", "2")
def test_rigging_happens_by_specified_change(q_function): random.seed(7) env = CryptoEnvironmentStub(action_to_token={ 1: "BTC", 2: "ETH" }, active_token="BTC") env.add_record(entry("BTC_ETH", "2")). \ add_record(entry("BTC_ETH", "4")). \ add_record(entry("BTC_ETH", "1")). \ add_record(entry("BTC_ETH", "2")).finish() policy = make_policy(env, PolicyDummy(), 0.5) assert policy.select(A_STATE, q_function) == 0
def test_window_moves_when_stepping(rates): rates.add_record(entry("BTC_ETH", 1.1)) \ .add_record(entry("BTC_ETH", 1.2)) \ .add_record(entry("BTC_ETH", 1.3)).finish() e = make_env(rates, window=2) e.reset() s, _, done, _ = e.step(None) assert done assert s["rates"] == [{ "BTC_ETH": entry("BTC_ETH", 1.2) }, { "BTC_ETH": entry("BTC_ETH", 1.3) }]
def test_rigging_starts_at_current_rate_position(q_function): env = CryptoEnvironmentStub(action_to_token={ 1: "BTC", 2: "ETH" }, active_token="BTC") env.add_record(entry("BTC_ETH", "1")). \ add_record(entry("BTC_ETH", "4")). \ add_record(entry("BTC_ETH", "1")). \ add_record(entry("BTC_ETH", "2")).finish() env.step(0) policy = make_policy(env, policy_spy, 1.0) assert policy.select(A_STATE, q_function) == 2 assert policy.select(A_STATE, q_function) == 1
def test_rigging_looks_ahead_for_profitable_exchange_and_selects_actions_accordingly( q_function): env = CryptoEnvironmentStub(action_to_token={ 1: "BTC", 2: "ETH" }, active_token="BTC") env.add_record(entry("BTC_ETH", "2")). \ add_record(entry("BTC_ETH", "4")). \ add_record(entry("BTC_ETH", "1")). \ add_record(entry("BTC_ETH", "2")).finish() policy = make_policy(env, PolicyDummy(), 1.0) assert policy.select(A_STATE, q_function) == 0 assert policy.select(A_STATE, q_function) == 2 assert policy.select(A_STATE, q_function) == 1
def test_reward_calculator_is_called_with_the_current_state(rates): rates.add_record(entry("BTC_ETH", 1.1)) \ .add_record(entry("BTC_ETH", 1.2)).finish() class RCalc: def __init__(self): self.received_state = None def __call__(self, state): self.received_state = state return 0 calc = RCalc() env = make_env(rates, reward_calculator=calc) s, _, _, _ = env.step(None) assert calc.received_state == s