diff --git a/sdk/tests/tutorials/valuation/test_quotes_scaling_factor.py b/sdk/tests/tutorials/valuation/test_quotes_scaling_factor.py index 3ad344c830d9..706731372e83 100644 --- a/sdk/tests/tutorials/valuation/test_quotes_scaling_factor.py +++ b/sdk/tests/tutorials/valuation/test_quotes_scaling_factor.py @@ -24,7 +24,7 @@ def upsert_quotes(self, scale_factor) -> None: """ # Add prices as a percentage of par prices = [ - (self.instrument_ids[0], 100), + ("BBG00Y271826", 100), ] requests = [ @@ -33,7 +33,7 @@ def upsert_quotes(self, scale_factor) -> None: models.QuoteSeriesId( provider="Lusid", instrument_id=price[0], - instrument_id_type="LusidInstrumentId", + instrument_id_type="Figi", quote_type="Price", field="mid", ), @@ -72,7 +72,7 @@ def create_configuration_recipe( suppliers=models.MarketContextSuppliers(equity="Lusid"), options=models.MarketOptions( default_supplier="Lusid", - default_instrument_code_type="LusidInstrumentId", + default_instrument_code_type="Figi", default_scope=TestDataUtilities.tutorials_scope, ), ), diff --git a/sdk/tests/tutorials/valuation/test_recipe_currency_subunits.py b/sdk/tests/tutorials/valuation/test_recipe_currency_subunits.py index b67d602f5dfe..15389d5596e7 100644 --- a/sdk/tests/tutorials/valuation/test_recipe_currency_subunits.py +++ b/sdk/tests/tutorials/valuation/test_recipe_currency_subunits.py @@ -64,9 +64,9 @@ def upsert_quotes(self, quotes_date) -> models.UpsertQuotesResponse: """ prices = [ - ("BBG000BF46Y8", 10000), - ("BBG000PQKVN8", 20000), - ("BBG000FD8G46", 30000), + ("BBG00Y271826", 10000), + ("BBG005D5KGM0", 20000), + ("BBG000DPM932", 30000), ] requests = [ diff --git a/sdk/tests/tutorials/valuation/test_recipe_diff_quote_txns_ids.py b/sdk/tests/tutorials/valuation/test_recipe_differing_ids_quote_txns.py similarity index 94% rename from sdk/tests/tutorials/valuation/test_recipe_diff_quote_txns_ids.py rename to sdk/tests/tutorials/valuation/test_recipe_differing_ids_quote_txns.py index 71032db8b699..73c2c0e9750f 100644 --- a/sdk/tests/tutorials/valuation/test_recipe_diff_quote_txns_ids.py +++ b/sdk/tests/tutorials/valuation/test_recipe_differing_ids_quote_txns.py @@ -24,9 +24,9 @@ def upsert_quotes(self, instrument_id) -> models.UpsertQuotesResponse: """ prices = [ - ("GB0008847096", 100), - ("GB00B1CRLC47", 200), - ("BMG4593F1389", 300), + ("GB00BMH18Q19", 100), + ("US31959T1025", 200), + ("GB00B1QH8P22", 300), ] requests = [ @@ -139,15 +139,15 @@ def test_differing_quote_and_transaction_instrument_ids(self) -> None: # Instrument ISINs from the upserted quotes prices = [ - ("GB0008847096", 100), - ("GB00B1CRLC47", 200), - ("BMG4593F1389", 300), + ("GB00BMH18Q19", 100), + ("US31959T1025", 200), + ("GB00B1QH8P22", 300), ] # Instrument IDs as upserted originally using the InstrumentLoader() instruments = [ - ("BBG000BF46Y8", "TESCO PLC"), - ("BBG000PQKVN8", "MONDI PLC"), - ("BBG000FD8G46", "HISCOX LTD"), + ("BBG00Y271826", "BYTES TECHNOLOGY GROUP PLC"), + ("BBG005D5KGM0", "FIRST CITRUS BANCORPORATION"), + ("BBG000DPM932", "FRASERS GROUP PLC") ] # Create an upsert instrument request including the ISINs diff --git a/sdk/tests/tutorials/valuation/test_valuation.py b/sdk/tests/tutorials/valuation/test_valuation.py index 4e137b6cac42..a4436bf5507e 100644 --- a/sdk/tests/tutorials/valuation/test_valuation.py +++ b/sdk/tests/tutorials/valuation/test_valuation.py @@ -18,9 +18,9 @@ def upsert_quotes(self) -> models.UpsertQuotesResponse: """ prices = [ - (self.instrument_ids[0], 100), - (self.instrument_ids[1], 200), - (self.instrument_ids[2], 300), + ("BBG00Y271826", 100), + ("BBG005D5KGM0", 200), + ("BBG000DPM932", 300), ] requests = [ @@ -29,7 +29,7 @@ def upsert_quotes(self) -> models.UpsertQuotesResponse: models.QuoteSeriesId( provider="Lusid", instrument_id=price[0], - instrument_id_type="LusidInstrumentId", + instrument_id_type="Figi", quote_type="Price", field="mid", ), @@ -67,7 +67,7 @@ def create_configuration_recipe( suppliers=models.MarketContextSuppliers(equity="Lusid"), options=models.MarketOptions( default_supplier="Lusid", - default_instrument_code_type="LusidInstrumentId", + default_instrument_code_type="Figi", default_scope=TestDataUtilities.tutorials_scope, ), ), diff --git a/sdk/tests/utilities/base_valuation_tests_setup.py b/sdk/tests/utilities/base_valuation_tests_setup.py index c72e794ec511..15b7657b9cd2 100644 --- a/sdk/tests/utilities/base_valuation_tests_setup.py +++ b/sdk/tests/utilities/base_valuation_tests_setup.py @@ -30,13 +30,30 @@ def setUpClass(cls): cls.test_data_utilities = TestDataUtilities(cls.transaction_portfolios_api) # Setup test portfolios - cls.portfolio_scope = TestDataUtilities.tutorials_scope + # cls.portfolio_scope = TestDataUtilities.tutorials_scope + + cls.id_generator = IdGenerator(scope=TestDataUtilities.tutorials_scope) + + _, cls.portfolio_scope, cls.portfolio_code = cls.id_generator.generate_scope_and_code( + entity="portfolio", + scope=TestDataUtilities.tutorials_scope, + code_prefix="portfolio-" + ) + _, cls.xccy_portfolio_scope, cls.xccy_portfolio_code = cls.id_generator.generate_scope_and_code( + entity="portfolio", + scope=TestDataUtilities.tutorials_scope, + code_prefix="portfolio-" + ) + cls.portfolio_code = cls.test_data_utilities.create_transaction_portfolio( - TestDataUtilities.tutorials_scope + scope=TestDataUtilities.tutorials_scope, + code=cls.portfolio_code ) cls.xccy_portfolio_code = cls.test_data_utilities.create_transaction_portfolio( - TestDataUtilities.tutorials_scope + TestDataUtilities.tutorials_scope, + code=cls.xccy_portfolio_code ) + # Load transactions to test portfolio portfolio_loader = PortfolioLoader( cls.transaction_portfolios_api, cls.instruments_api @@ -58,7 +75,7 @@ def setUpClass(cls): # Set market data scope to be used with quotes and recipes cls.market_data_provider = "Lusid" - cls.market_data_scope = "Test-" + str(uuid.uuid4()) + cls.market_data_scope = TestDataUtilities.market_data_scope # Set valuation key cls.valuation_key = "Sum(Valuation/PV)" @@ -127,4 +144,6 @@ def tearDownClass(cls): # Delete portfolio once tests are concluded for code in portfolio_codes: - cls.portfolios_api.delete_portfolio(TestDataUtilities.tutorials_scope, code) \ No newline at end of file + cls.portfolios_api.delete_portfolio(TestDataUtilities.tutorials_scope, code) + + #InstrumentLoader(cls.instruments_api).delete_instruments() \ No newline at end of file diff --git a/sdk/tests/utilities/instrument_loader.py b/sdk/tests/utilities/instrument_loader.py index e848c0b0eb95..f24cc4ade1bc 100644 --- a/sdk/tests/utilities/instrument_loader.py +++ b/sdk/tests/utilities/instrument_loader.py @@ -18,7 +18,7 @@ class InstrumentLoader: def __init__(self, instruments_api: lusid.InstrumentsApi): self.instruments_api = instruments_api - def load_instruments(self): + def load_instruments(self, return_luids=True, alternate_id="Figi"): instruments_to_create = { i.Figi: models.InstrumentDefinition( name=i.Name, @@ -32,7 +32,12 @@ def load_instruments(self): assert (len(response.failed) == 0) - return sorted([i.lusid_instrument_id for i in response.values.values()]) + if return_luids: + identifiers = sorted([i.lusid_instrument_id for i in response.values.values()]) + else: + identifiers = sorted([i.identifiers[alternate_id] for i in response.values.values()]) + + return identifiers def delete_instruments(self): for i in self.__instruments: diff --git a/sdk/tests/utilities/portfolio_loader.py b/sdk/tests/utilities/portfolio_loader.py index fc2614af93ed..dec594df8ded 100644 --- a/sdk/tests/utilities/portfolio_loader.py +++ b/sdk/tests/utilities/portfolio_loader.py @@ -1,26 +1,22 @@ +import uuid + import lusid import lusid.models as models from utilities import InstrumentLoader -import uuid +from utilities import TestDataUtilities -class PortfolioLoader: +class PortfolioLoader(TestDataUtilities): def __init__(self, transaction_portfolios_api: lusid.TransactionPortfoliosApi, instruments_api: lusid.InstrumentsApi): self.transaction_portfolios_api = transaction_portfolios_api self.instruments_api = instruments_api - def build_transaction_request(self, instrument_id, id_type, units, price, currency, trade_date, transaction_type): - return models.TransactionRequest(transaction_id=str(uuid.uuid4()), - type=transaction_type, - instrument_identifiers={f"Instrument/default/{id_type}": instrument_id}, - transaction_date=trade_date, - settlement_date=trade_date, - units=units, - transaction_price=models.TransactionPrice(price=price), - total_consideration=models.CurrencyAndAmount(amount=price * units, - currency=currency), - source="Broker") + portfolio_figis = [ + "BBG00Y271826", + "BBG005D5KGM0", + "BBG000DPM932", + ] def setup_gbp_portfolio(self, portfolio_scope, portfolio_code, effective_date) -> None: """ @@ -30,32 +26,34 @@ def setup_gbp_portfolio(self, portfolio_scope, portfolio_code, effective_date) - :param datetime effective_date: The portfolio creation date :return: None """ - instrument_ids = InstrumentLoader(self.instruments_api).load_instruments() + instrument_ids = InstrumentLoader(self.instruments_api).load_instruments(return_luids=False) + for figi in self.portfolio_figis: + assert figi in instrument_ids transactions = [ self.build_transaction_request( - instrument_id=instrument_ids[0], - id_type="LusidInstrumentId", + instrument_id="BBG00Y271826", + id_type="Figi", units=100, - price=101, + price=100, currency="GBP", trade_date=effective_date, transaction_type="StockIn", ), self.build_transaction_request( - instrument_id=instrument_ids[1], - id_type="LusidInstrumentId", + instrument_id="BBG005D5KGM0", + id_type="Figi", units=100, - price=102, + price=100, currency="GBP", trade_date=effective_date, transaction_type="StockIn", ), self.build_transaction_request( - instrument_id=instrument_ids[2], - id_type="LusidInstrumentId", + instrument_id="BBG000DPM932", + id_type="Figi", units=100, - price=103, + price=100, currency="GBP", trade_date=effective_date, transaction_type="StockIn", @@ -76,12 +74,14 @@ def setup_xccy_portfolio(self, portfolio_scope, portfolio_code, effective_date) :param datetime effective_date: The portfolio creation date :return: None """ - instrument_ids = InstrumentLoader(self.instruments_api).load_instruments() + instrument_ids = InstrumentLoader(self.instruments_api).load_instruments(return_luids=False) + for figi in self.portfolio_figis: + assert figi in instrument_ids transactions = [ self.build_transaction_request( - instrument_id=instrument_ids[0], - id_type="LusidInstrumentId", + instrument_id="BBG00Y271826", + id_type="Figi", units=100, price=101, currency="EUR", @@ -89,8 +89,8 @@ def setup_xccy_portfolio(self, portfolio_scope, portfolio_code, effective_date) transaction_type="StockIn", ), self.build_transaction_request( - instrument_id=instrument_ids[1], - id_type="LusidInstrumentId", + instrument_id="BBG005D5KGM0", + id_type="Figi", units=100, price=102, currency="USD", @@ -98,8 +98,8 @@ def setup_xccy_portfolio(self, portfolio_scope, portfolio_code, effective_date) transaction_type="StockIn", ), self.build_transaction_request( - instrument_id=instrument_ids[2], - id_type="LusidInstrumentId", + instrument_id="BBG000DPM932", + id_type="Figi", units=100, price=103, currency="JPY", diff --git a/sdk/tests/utilities/test_data_utilities.py b/sdk/tests/utilities/test_data_utilities.py index 2e7e5f575f21..41607ea8892b 100644 --- a/sdk/tests/utilities/test_data_utilities.py +++ b/sdk/tests/utilities/test_data_utilities.py @@ -35,17 +35,17 @@ def api_client(cls): cls._api_client = ApiClientBuilder().build(CredentialsSource.secrets_path()) return cls._api_client - def create_transaction_portfolio(self, scope): - guid = str(uuid.uuid4()) + def create_transaction_portfolio(self, scope, code=None, currency="GBP"): + guid = code if code else str(uuid.uuid4()) # Effective date of the portfolio, this is the date the portfolio was created and became live. # All dates/times must be supplied in UTC effective_date = datetime(2018, 1, 1, tzinfo=pytz.utc) # Details of the new portfolio to be created, created here with the minimum set of mandatory fields - request = models.CreateTransactionPortfolioRequest(display_name="Portfolio-{}".format(guid), - code="Id-{}".format(guid), - base_currency="GBP", + request = models.CreateTransactionPortfolioRequest(display_name=f"Portfolio-{guid}", + code=f"Id-{guid}", + base_currency=currency, created=effective_date) # Create the portfolio in LUSID @@ -55,10 +55,10 @@ def create_transaction_portfolio(self, scope): return portfolio.id.code - def build_transaction_request(self, instrument_id, units, price, currency, trade_date, transaction_type): + def build_transaction_request(self, instrument_id, units, price, currency, trade_date, transaction_type, id_type="LusidInstrumentId"): return models.TransactionRequest(transaction_id=str(uuid.uuid4()), type=transaction_type, - instrument_identifiers={self.lusid_luid_identifier: instrument_id}, + instrument_identifiers={f"Instrument/default/{id_type}": instrument_id}, transaction_date=trade_date, settlement_date=trade_date, units=units, diff --git a/sdk/tests/utilities/test_instrument_loader.py b/sdk/tests/utilities/test_instrument_loader.py new file mode 100644 index 000000000000..de7cb7708b2a --- /dev/null +++ b/sdk/tests/utilities/test_instrument_loader.py @@ -0,0 +1,36 @@ +import unittest + +import lusid + +from utilities import InstrumentLoader +from utilities import TestDataUtilities + +class InstrumentLoaderTests(unittest.TestCase): + + @classmethod + def setUpClass(cls): + # Create a configured API client + api_client = TestDataUtilities.api_client() + cls.instruments_api = lusid.InstrumentsApi(api_client) + cls.instrument_loader = InstrumentLoader(cls.instruments_api) + + def test_load_instruments(self): + # Test luids returned in default case + luids = self.instrument_loader.load_instruments() + self.assertEqual(len(luids), 5) + + def test_load_instrument_figis(self): + + # Expected Figis - see utilities.instrument_loader + expected_figis = [ + "BBG00KTDTF73", + "BBG00Y271826", + "BBG00L7XVNP1", + "BBG005D5KGM0", + "BBG000DPM932", + ] + + # Test figis match expected identifiers + figis = self.instrument_loader.load_instruments(return_luids=False) + self.assertEqual(len(figis), len(expected_figis)) + self.assertTrue(set(figis).issuperset(set(expected_figis)))