def test_calc_sell_liability(): GIVEN("a price and a size") price = 1.01 size = 100 WHEN("we calculate the sell liability") liability = calc_sell_liability(price=price, size=size) THEN("the correct value is returned") assert liability == 100 * (1.01 - 1) GIVEN("an invalid price and a size") price = 0.99 size = 1000000 WHEN("we calculate the sell liability") liability = calc_sell_liability(price=price, size=size) THEN("the correct value is returned") assert liability == 0 GIVEN("a price and an invalid size") price = 1.99 size = -1 WHEN("we calculate the sell liability") liability = calc_sell_liability(price=price, size=size) THEN("the correct value is returned") assert liability == 0 GIVEN("an invalid price and an invalid size") price = 1 size = -1 WHEN("we calculate the sell liability") liability = calc_sell_liability(price=price, size=size) THEN("the correct value is returned") assert liability == 0
def test_inverse_price(): GIVEN("a price") buy_price = 2 WHEN("we calculate the inverse") sell_price = calc_inverse_price(buy_price) THEN("the correct price is returned") assert sell_price == 2 GIVEN("another valid price") buy_price = 1.5 WHEN("we calculate the sell price") sell_price = calc_inverse_price(buy_price) THEN("the correct price is returned") assert sell_price == 1 / (1 - (1 / buy_price)) GIVEN("a string price") buy_price = "a price" WHEN("we calculate the sell price") sell_price = calc_inverse_price(buy_price) THEN("the sell price is shown to be not a number") assert is_not_a_number(sell_price) GIVEN("a negative price") buy_price = -2 WHEN("we calculate the sell price") sell_price = calc_inverse_price(buy_price) THEN("the sell price is shown to be not a number") assert is_not_a_number(sell_price) GIVEN("a price between 0 and 1") buy_price = 0.99 WHEN("we calculate the sell price") sell_price = calc_inverse_price(buy_price) THEN("the sell price is shown to be not a number") assert is_not_a_number(sell_price)
def test_exit_run_on_no_data(mock_call_exchange): GIVEN("a handler") external_api = ExternalAPIMarketHandler(environment="Dev", headers={}, market_id=45678) handler = MarketHandler( market_id=45678, external_api=external_api, market_start_time="2019-01-01T00:00:00.000Z", ) external_api.set_mediator(mediator=handler) mock_call_exchange.return_value = {} WHEN("we call run and no data is return from the api") for i in range(9): try: maybe_s = "s" if i > 0 else "" THEN(f"the handler will run {i + 1} time{maybe_s} without error") handler.run() except SystemExit: fail("Unexpected SystemExit") WHEN("we call run and no data is returned a 10th time") with raises(SystemExit) as system_exit: handler.run() THEN("the system will exit") assert system_exit.type == SystemExit assert system_exit.value.code == 0
def test_item_adapter_interface(): GIVEN("the external api market interface") with raises(TypeError): WHEN( "a class inherits the interface but does not implement the appropriate method" ) class DoesNotImplement(ItemAdapterInterface): pass THEN("an error is thrown on instantiation") DoesNotImplement() WHEN( "a class inherits the interface and implements the appropriate method") class Implements(ItemAdapterInterface): def get_adapted_data(self): pass try: THEN("the class can be instantiated without error") Implements() except TypeError: fail("Unexpected TypeError")
def test_handler(): GIVEN("a directory, an historical external api file and a handler") directory = "./data/29220705" file_name = "1.157190397.txt" file = HistoricalExternalAPIFileHander(directory=directory, file=file_name) WHEN("we get the file as a list") file_data = file.get_file_as_list() THEN("the data is a list") assert isinstance(file_data, list) THEN("the file has a record for every 5 seconds in the" + "4 minutes 27 seconds leading up to 33 seconds before the race") assert len(file_data) == round_down(((5 * 60) - 33) / 5) for record in file_data: THEN("each record in the file data has a process time") assert isinstance(record.get("process_time"), str) THEN("none of the records have marketInfo") assert record.get("marketInfo") is None WHEN("we get the market start time") market_start_time = file.get_market_start_time() THEN("the market_start_time is a string") assert isinstance(market_start_time, str) THEN("the market start time can be converted to an epoch") epoch = DateTime(market_start_time).get_epoch() assert epoch > 0
def test_market_data_external_api_interface(): GIVEN("the external api market interface") with raises(TypeError): WHEN( "a class inherits the interface but does not implement the appropriate method" ) class DoesNotImplement(MarketDataRecordInterface): pass THEN("an error is thrown on instantiation") DoesNotImplement() WHEN( "a class inherits the interface and implements the appropriate method") class Implements(MarketDataRecordInterface): def convert(self): pass try: THEN("the class can be instantiated without error") Implements() except TypeError: fail("Unexpected TypeError")
def test_regex_match(): GIVEN("a pattern and a string that match") a_str = "This is a string" pattern = r"This\sis" WHEN("we call regex_match") return_str = regex_match(pattern=pattern, str=a_str) THEN("the string is returned") assert return_str == a_str GIVEN("a pattern and a string that do not match") a_str = "This is a string" pattern = r"This\sisnt" WHEN("we call regex_match") return_str = regex_match(pattern=pattern, str=a_str) THEN("the string is returned") assert return_str is None GIVEN("a date pattern and a string that match") a_str = "1984-11-07T12:45:00Z" pattern = r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z" WHEN("we call regex_match") return_str = regex_match(pattern=pattern, str=a_str) THEN("the string is returned") assert return_str == a_str GIVEN("a different date pattern and a string that match") a_str = "1984-11-07T12:45:00.000Z" pattern = r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z" WHEN("we call regex_match") return_str = regex_match(pattern=pattern, str=a_str) THEN("the string is returned") assert return_str == a_str
def test_single_item(mock_notify): GIVEN("an orders handler and some items") mediator = MockMediator() handler = OrdersHandler(mediator=mediator, bank=5000) items = [{ "id": 16397186, "probability": 0.19889500121124917, "type": "BUY", "ex_price": 6.4, "returns_price": 6.13, }] WHEN("we call get_new_orders") handler.get_new_orders(items=items) THEN("the mediator's notify method is called with the correct paramaters") args, kwargs = mock_notify.call_args assert args == () assert kwargs.get("event") == "new orders" new_orders = kwargs.get("data") THEN("the correct order information is returned") assert new_orders == [{ "id": 16397186, "probability": 0.19889500121124917, "type": "BUY", "ex_price": 6.4, "returns_price": 6.13, "min_size": 5, "size": 250.0, "risk_percentage": 0.05, }] WHEN("we add the order to the handler (after processing)") handler.prevent_reorder(orders=new_orders) THEN("the correct information has been added to the handler") assert handler.get_orders() == new_orders WHEN("we try to add the order to the handler a second time") handler.prevent_reorder(orders=new_orders) THEN("the order has not been added again to the handler") assert handler.get_orders() == new_orders WHEN("we try to get new orders again using the same item") handler.get_new_orders(items=items) THEN("the mediator's notify method is called with the correct paramaters") args, kwargs = mock_notify.call_args assert args == () assert kwargs.get("event") == "finished processing" new_orders = kwargs.get("data") THEN("there are no new orders") assert not new_orders assert new_orders is None
def test_market_data_container_interface(): GIVEN("the external api market interface") with raises(TypeError): WHEN( "a class inherits the interface but does not implement the appropriate method" ) class DoesNotImplement(DataContainerInterface): pass THEN("an error is thrown on instantiation") DoesNotImplement() WHEN( "a class inherits the interface and implements the appropriate method") class Implements(DataContainerInterface): def new(self): pass def add_rows(self): pass def get_row_count(self): pass def get_column_count(self): pass def get_column(self): pass def get_last_column_entry(self): pass def has_column(self): pass def get_column_group_values(self): pass def get_index(self): pass def set_index(self): pass def set_column_group_name(self): pass try: THEN("the class can be instantiated without error") Implements() except TypeError: fail("Unexpected TypeError")
def test_make_copy(): GIVEN("a list with random contents") random_list = [45, 21, 333, 564, 75, 66, 459, 4, 78, 0] WHEN("we make a copy") different_l = make_copy(random_list) THEN("the lists are equal") assert lists_are_equal(random_list, different_l) WHEN("we remove the last item from the list's copy") last_item = different_l.pop() THEN("the lists are no longer equal") assert not lists_are_equal(random_list, different_l) assert last_item == random_list[-1]
def test_date_time_epoch(): GIVEN("a UTC date time string with milliseconds") utc_date_time_str = "2019-01-01T00:00:00.000Z" WHEN("we get the epoch representation") epoch = DateTime(utc_date_time_str).get_epoch() THEN("the correct epoch is returned") local_epoch = 1546261200 assert epoch == local_epoch GIVEN("a UTC date time string and another that is 60 seconds afterwards") first_date_time_str = "2019-01-01T00:00:00.000Z" second_date_time_str = "2019-01-01T00:01:00.000Z" WHEN( "we create instances of DateTime and subtract the epochs from one another" ) seconds_difference = (DateTime(first_date_time_str).get_epoch() - DateTime(second_date_time_str).get_epoch()) THEN("the difference is as expected") assert seconds_difference == -60 GIVEN("a UTC date time strings") utc_date_time_str = "2019-01-01T00:00:00.000Z" WHEN( "we create instances of DateTime and subtract the epochs from one another" ) seconds_difference = (DateTime(utc_date_time_str).get_epoch() - DateTime(utc_date_time_str).get_epoch()) THEN("there is no difference") assert seconds_difference == 0 GIVEN("two UTC date time strings 60 seconds apart") first_date_time_str = "2019-01-01T00:01:00.000Z" second_date_time_str = "2019-01-01T00:00:00.000Z" WHEN( "we create instances of DateTime and subtract the epochs from one another" ) seconds_difference = (DateTime(first_date_time_str).get_epoch() - DateTime(second_date_time_str).get_epoch()) THEN("the difference is as expected") assert seconds_difference == 60 GIVEN("two milliseconds since epoch 1 second apart") first_epoch = 1569876588922 second_epoch = 1569876587922 WHEN( "we create instances of DateTime and subtract the epochs from one another" ) seconds_difference = (DateTime(first_epoch).get_epoch() - DateTime(second_epoch).get_epoch()) THEN("the difference is as expected") assert seconds_difference == 1
def test_is_valid_price(): GIVEN("a price") price = 1.01 WHEN("we check if the price is valid") valid = is_valid_price(price) THEN("a true value is returned") assert valid is True GIVEN("an invalid price") price = 1 WHEN("we check if the price is valid") valid = is_valid_price(price) THEN("a false value is returned") assert valid is False
def test_number_dict(): GIVEN("a dictionary") data = {"a": 1, "b": 2, "c": 3} WHEN("we test if it is a number") true = is_a_number(data) THEN("it is not") assert not true GIVEN("a numeric only dictionary") data = {1: 1, 2: 2, 3: 3} WHEN("we test if it is a number") true = is_a_number(data) THEN("it is not") assert not true
def test_not_nan(): GIVEN("a value that is a number") number = 1 WHEN("we check if the value is not a number") true = is_not_a_number(number) THEN("it is not") assert not true GIVEN("a None value") none = None WHEN("we check if the value is not a number") true = is_not_a_number(none) THEN("it is not") assert not true
def test_make_directory(): GIVEN("a path") path = "./test_make_directories" WHEN("we check if the path exists") exists = path_exists(path=path) THEN("it does not") assert exists is False WHEN("we make the directory and check if it now exists") returned_path = make_directory_if_required(path=path) exists = path_exists(path=path) THEN("it does") assert exists is True assert returned_path == path remove_directory(path)
def test_add_mixed_processed_orders(): GIVEN("a handler and a set of processed orders (2 valid, 1 invalid)") mediator = MockMediator() handler = OrdersHandler(mediator=mediator, bank=100000000000) processed_orders = [ { "id": 1234, "probability": 0.2, "type": "BUY", "ex_price": 9.1, "returns_price": 8.65, "min_size": 5, "size": 50000, "risk_percentage": 0.05, }, { "id": 5678, "probability": 0.26, "type": "SELL", "ex_price": 5, "returns_price": 4.75, "min_size": 5, "size": 10000, "risk_percentage": 0.01, }, {}, ] WHEN("we add the orders to the handler") handler.prevent_reorder(orders=processed_orders) existing_orders = handler.get_orders() THEN("the correct number of orders have been added to the handler") assert len(existing_orders) == 2 THEN("the correct order data has been added to the handler") assert existing_orders == processed_orders[0:2]
def test_get_ids_for_model_data(): GIVEN("a data handler with some data and two fixed probabilities") GIVEN("a data handler and the directory and file name of a test file") directory = "./data/29184567" file_name = "1.156230797.txt" file = HistoricalExternalAPIFileHander(directory=directory, file=file_name) record = file.get_file_as_list()[0] market_start_time = file.get_market_start_time() adapter = ExternalAPIMarketRecordAdapter( market_start_time=market_start_time) mediator = MockMediator() handler = DataHandler( mediator=mediator, adapter=adapter, container=DataContainer(), ) handler.process_data(record) WHEN( "we set the probabilities of two items and get the ids required for the next model run" ) ids = handler.get_unique_ids() for runner_id in ids[0:2]: handler._set_probability(runner_id=runner_id, probability=0.1) ids.pop(0) THEN("the list omits the items which have fixed probabilities") model_ids = handler._get_ids_for_model_data() assert model_ids == ids assert len(model_ids) < len(handler.get_unique_ids())
def test_calc_order_size(): GIVEN("a handler and a list of items with risk_percentages") bank = 1000 mediator = MockMediator() handler = OrdersHandler(mediator=mediator, bank=bank) items = [ { "id": 123, "risk_percentage": -5 }, { "id": 101, "risk_percentage": 0.001 }, { "id": 456, "risk_percentage": 0.01 }, { "id": 789, "risk_percentage": 0.1 }, { "id": 202, "risk_percentage": 0.156788 }, ] WHEN("we calculate the size of the orders") for item in items: size = handler._calc_order_size(item=item) THEN("the correct sizes are returned") assert size == round(max(item.get("risk_percentage"), 0) * bank, 2)
def test_buy_metadata(required_variables): GIVEN("a dictionary with the correct information") item_data = __get_data() variables = [ "id", "removal_date", "sp_back_size", "ex_back_size", "sp_back_price", "ex_average_back_price", "ex_offered_back_price", ] required_variables.return_value = variables WHEN("we instantiate the item handler object") adapted_item_data = ItemAdapter(item_data).get_adapted_data() THEN("the object has all of the correct information") assert adapted_item_data.get("id") == __get_id(item_data) assert is_not_a_number(adapted_item_data.get("removal_date")) assert adapted_item_data.get("sp_back_size") == __calc_sp_back_size(item_data) assert adapted_item_data.get("ex_back_size") == __calc_ex_back_size(item_data) assert adapted_item_data.get("sp_back_price") == __get_sp_back_price(item_data) assert adapted_item_data.get( "ex_average_back_price" ) == __calc_ex_average_back_price(item_data) assert adapted_item_data.get( "ex_offered_back_price" ) == __get_ex_offered_back_price(item_data) assert len(adapted_item_data.keys()) == len(variables)
def test_number_number(): GIVEN("a number") number = 1 WHEN("we test if it is a number") true = is_a_number(number) THEN("it is") assert true
def test_simple_comp_data(): GIVEN("a simple set of data and a probability handler") items = ( { "id": 123, "sp_probability": 0.476190476190476 }, { "id": 456, "sp_probability": 0.476190476190476 }, ) handler = ProbabilityHandler(items=items, name="sp_probability", correct_probability=1) WHEN("we calculate the compositional probabilities") compositional_probabilities = handler.calc_compositional_probabilities() THEN("a list of dictionaries with the correct values is returned") assert compositional_probabilities == [ { "id": 123, "compositional_probability": 0.5 }, { "id": 456, "compositional_probability": 0.5 }, ]
def test_number_list(): GIVEN("a list") data = [1, 2, 3, 4] WHEN("we test if it is a number") true = is_a_number(data) THEN("it is not") assert not true
def test_get_newline(): GIVEN("a newline") newline_str = "\n" WHEN("we get a newline") newline = get_newline() THEN("they are the same") assert newline == newline_str
def test_nan(): GIVEN("a value that is not a number") nan = not_a_number() WHEN("we check if the value is not a number") true = is_not_a_number(nan) THEN("it is") assert true
def test_nan_to_num(): GIVEN("a value that is not a number") nan = not_a_number() WHEN("we convert the value to a number") number = not_a_number_to_number(nan) THEN("it is now the number 0") assert number == 0
def test_number_none(): GIVEN("a None value") none = None WHEN("we test if it is a number") true = is_a_number(none) THEN("it is not") assert not true
def test_number_nan(): GIVEN("a NaN value") nan = not_a_number() WHEN("we test if it is a number") true = is_a_number(nan) THEN("it is not") assert not true
def test_simple_comp_data(): GIVEN("a simple set of data and a data transform handler") items = ( { "id": 123, "sp_back_price": 2.1 }, { "id": 456, "sp_back_price": 2.1 }, ) handler = TransformHandler() handler._set_items(items=items) WHEN("we calculate the compositional data") compositional_data = handler._get_compositional_data( price_name="sp_back_price") THEN("a list of dictionaries with the correct values is returned") assert compositional_data == [ { "id": 123, "compositional_probability": 0.5, "compositional_price": 2 }, { "id": 456, "compositional_probability": 0.5, "compositional_price": 2 }, ]
def test_no_items(): GIVEN("a transform handler") handler = TransformHandler() WHEN("we call process with no data") transformed_data = handler.process() THEN("an empty dictionary is returned") assert not transformed_data
def test_number_str(): GIVEN("a string") a_str = "this is a string and not a number" WHEN("we test if it is a number") true = is_a_number(a_str) THEN("it is not") assert not true