def test_run_valuation(self): # define location of data in excel spreadsheet sht = self.get_sheet('Run valuation') # define locations/names of cells containing fields scope_location = "F17" PortfolioCode = "F19" ValuationDate = "F21" # effective valuation date InlineRecipe = "J35" effective_at = get_date(ValuationDate, sht) scope = sht.range(scope_location).value code = sht.range(PortfolioCode).value inline_recipe = json.loads(sht.range(InlineRecipe).value) recipe_keys = inline_recipe.keys() self.assertTrue(scope, msg="Error loading scope from location: " + scope_location) self.assertTrue(code, msg="Error loading scope from location: " + PortfolioCode) print(f"Scope: {scope}") print(f"Code: {code}") print(f"Effective Date: {effective_at}") # get valuation data inline_recipe = models.ConfigurationRecipe( code='quotes_recipe', market=models.MarketContext( market_rules=[], suppliers=models.MarketContextSuppliers( equity='DataScope' ), options=models.MarketOptions( default_supplier='DataScope', default_instrument_code_type='LusidInstrumentId', default_scope=scope) ) ) aggregation_request = models.AggregationRequest( inline_recipe=inline_recipe, metrics=[ models.AggregateSpec("Instrument/default/Name", "Value"), models.AggregateSpec("Holding/default/PV", "Proportion"), models.AggregateSpec("Holding/default/PV", "Sum") ], group_by=["Instrument/default/Name"], effective_at=effective_at ) print(f"agg req:") pprint.pprint(aggregation_request) response = self.aggregation_api.get_aggregation(scope=scope, code=code, request=aggregation_request) for item in response.data: print("\t{}\t{}\t{}".format(item["Instrument/default/Name"], item["Proportion(Holding/default/PV)"], item["Sum(Holding/default/PV)"])) print("-------------------------------------------------") pprint.pprint(aggregation_request)
def create_aggregation_request(analyst_scope_code, today, quotes_date): # Create our aggregation request inline_recipe = models.ConfigurationRecipe( scope="User", code='quotes_recipe', market=models.MarketContext( market_rules=[ models.MarketDataKeyRule( key='Equity.LusidInstrumentId.*', supplier='DataScope', data_scope=analyst_scope_code, quote_type='Price', field='Mid', quote_interval=quotes_date.strftime("%Y-%m-%d")) ], suppliers=models.MarketContextSuppliers(commodity='DataScope', credit='DataScope', equity='DataScope', fx='DataScope', rates='DataScope'), options=models.MarketOptions( default_supplier='DataScope', default_instrument_code_type='LusidInstrumentId', default_scope=analyst_scope_code)), ) aggregation_request = models.AggregationRequest( inline_recipe=inline_recipe, effective_at=today, metrics=[ models.AggregateSpec(key='Instrument/default/LusidInstrumentId', op='Value'), models.AggregateSpec(key='Holding/default/Units', op='Sum'), models.AggregateSpec(key='Holding/default/Cost', op='Sum'), models.AggregateSpec(key='Holding/default/PV', op='Sum'), models.AggregateSpec(key='Holding/default/Price', op='Sum') ], group_by=['Instrument/default/LusidInstrumentId']) return aggregation_request
def create_configuration_recipe( self, recipe_scope, recipe_code) -> lusid.models.ConfigurationRecipe: """ Creates a configuration recipe that can be used inline or upserted :param str recipe_scope: The scope for the configuration recipe :param str recipe_code: The code of the the configuration recipe :return: ConfigurationRecipe """ return models.ConfigurationRecipe( scope=recipe_scope, code=recipe_code, market=models.MarketContext( market_rules=[], suppliers=models.MarketContextSuppliers(equity="Lusid"), options=models.MarketOptions( default_supplier="Lusid", default_instrument_code_type="LusidInstrumentId", default_scope=TestDataUtilities.tutorials_scope, ), ), )
def valuation(api_factory, marketdata_scope, portfolio_group, time): time_parts = [time[:10], time[11:]] if time_parts[1] == "LSE_market_close": time_parts[1] = "16:30:00.000000+00:00" elif time_parts[1] == "NYSE_market_close": time_parts[1] = "21:00:00.000000+00:00" time = "T".join(time_parts) # Create a recipe to perform a valuation configuration_recipe = models.ConfigurationRecipe( scope="User", code="quotes_recipe", market=models.MarketContext( market_rules=[ models.MarketDataKeyRule( key="Equity.Figi.*", supplier="DataScope", data_scope=marketdata_scope, quote_type="Price", field="Mid", ), models.MarketDataKeyRule( key="Equity.Isin.*", supplier="DataScope", data_scope=marketdata_scope, quote_type="Price", field="Mid", ), models.MarketDataKeyRule( key="Equity.LusidInstrumentId.*", supplier="DataScope", data_scope=marketdata_scope, quote_type="Price", field="Mid", ), models.MarketDataKeyRule( key="Fx.CurrencyPair.*", supplier="DataScope", data_scope=marketdata_scope, quote_type="Rate", field="Mid", ), ], suppliers=models.MarketContextSuppliers( commodity="DataScope", credit="DataScope", equity="DataScope", fx="DataScope", rates="DataScope", ), options=models.MarketOptions( default_supplier="DataScope", default_instrument_code_type="Figi", default_scope=marketdata_scope, ), ), ) upsert_configuration_recipe_response = api_factory.build( lusid.api.ConfigurationRecipeApi).upsert_configuration_recipe( upsert_recipe_request=models.UpsertRecipeRequest( configuration_recipe=configuration_recipe)) # Create the valuation request valuation_request = models.ValuationRequest( recipe_id=models.ResourceId(scope="User", code="quotes_recipe"), metrics=[ models.AggregateSpec(key="Instrument/default/LusidInstrumentId", op="Value"), models.AggregateSpec(key="Instrument/default/Name", op="Value"), models.AggregateSpec(key="Holding/default/Units", op="Sum"), models.AggregateSpec(key="Holding/default/Cost", op="Sum"), models.AggregateSpec(key="Holding/default/PV", op="Sum"), models.AggregateSpec(key="Holding/default/PV", op="Proportion"), ], group_by=["Instrument/default/LusidInstrumentId"], portfolio_entity_ids=[ models.PortfolioEntityId( scope=portfolio_group.scope, code=portfolio_group.code, portfolio_entity_type="GroupPortfolio", ) ], valuation_schedule=models.ValuationSchedule(effective_at=time), ) # Perform a valuation response = api_factory.build(lusid.api.AggregationApi).get_valuation( valuation_request=valuation_request) dataframe = prettyprint.aggregation_responses_generic_df([response]) dataframe = dataframe.append(dataframe.sum(numeric_only=True), ignore_index=True) return dataframe
def test_portfolio_aggregation(self): effective_date = datetime(2019, 4, 15, tzinfo=pytz.utc) portfolio_code = self.test_data_utilities.create_transaction_portfolio( TestDataUtilities.tutorials_scope) transactions = [ self.test_data_utilities.build_transaction_request( instrument_id=self.instrument_ids[0], units=100, price=101, currency="GBP", trade_date=effective_date, transaction_type="StockIn"), self.test_data_utilities.build_transaction_request( instrument_id=self.instrument_ids[1], units=100, price=102, currency="GBP", trade_date=effective_date, transaction_type="StockIn"), self.test_data_utilities.build_transaction_request( instrument_id=self.instrument_ids[2], units=100, price=103, currency="GBP", trade_date=effective_date, transaction_type="StockIn") ] self.transaction_portfolios_api.upsert_transactions( scope=TestDataUtilities.tutorials_scope, code=portfolio_code, transactions=transactions) prices = [ models.InstrumentAnalytic(self.instrument_ids[0], 100), models.InstrumentAnalytic(self.instrument_ids[1], 200), models.InstrumentAnalytic(self.instrument_ids[2], 300) ] requests = [] for i in range(3): requests.append( models.UpsertQuoteRequest( quote_id=models.QuoteId(models.QuoteSeriesId( provider="DataScope", instrument_id=self.instrument_ids[i], instrument_id_type="LusidInstrumentId", quote_type="Price", field="mid"), effective_at=effective_date), metric_value=models.MetricValue(value=prices[i].value, unit="GBP"))) self.quotes_api.upsert_quotes( TestDataUtilities.tutorials_scope, quotes={ "quote" + str(request_number): requests[request_number] for request_number in range(len(requests)) }) inline_recipe = models.ConfigurationRecipe( code='quotes_recipe', market=models.MarketContext( market_rules=[], suppliers=models.MarketContextSuppliers(equity='DataScope'), options=models.MarketOptions( default_supplier='DataScope', default_instrument_code_type='LusidInstrumentId', default_scope=TestDataUtilities.tutorials_scope))) aggregation_request = models.AggregationRequest( inline_recipe=inline_recipe, metrics=[ models.AggregateSpec("Instrument/default/Name", "Value"), models.AggregateSpec("Holding/default/PV", "Proportion"), models.AggregateSpec("Holding/default/PV", "Sum") ], group_by=["Instrument/default/Name"], effective_at=effective_date) # do the aggregation aggregation = self.aggregation_api.get_aggregation_by_portfolio( scope=TestDataUtilities.tutorials_scope, code=portfolio_code, request=aggregation_request) for item in aggregation.data: print("\t{}\t{}\t{}".format(item["Instrument/default/Name"], item["Proportion(Holding/default/PV)"], item["Sum(Holding/default/PV)"])) # Asserts self.assertEqual(len(aggregation.data), 3) self.assertEqual(aggregation.data[0]["Sum(Holding/default/PV)"], 10000) self.assertEqual(aggregation.data[1]["Sum(Holding/default/PV)"], 20000) self.assertEqual(aggregation.data[2]["Sum(Holding/default/PV)"], 30000)
def test_portfolio_aggregation(self): effective_date = datetime(2019, 4, 15, tzinfo=pytz.utc) portfolio_code = self.test_data_utilities.create_transaction_portfolio(TestDataUtilities.tutorials_scope) self.id_generator.add_scope_and_code("portfolio", TestDataUtilities.tutorials_scope, portfolio_code) transactions = [ self.test_data_utilities.build_transaction_request(instrument_id=self.instrument_ids[0], units=100, price=101, currency="GBP", trade_date=effective_date, transaction_type="StockIn"), self.test_data_utilities.build_transaction_request(instrument_id=self.instrument_ids[1], units=100, price=102, currency="GBP", trade_date=effective_date, transaction_type="StockIn"), self.test_data_utilities.build_transaction_request(instrument_id=self.instrument_ids[2], units=100, price=103, currency="GBP", trade_date=effective_date, transaction_type="StockIn") ] self.transaction_portfolios_api.upsert_transactions(scope=TestDataUtilities.tutorials_scope, code=portfolio_code, transaction_request=transactions) prices = [ (self.instrument_ids[0], 100), (self.instrument_ids[1], 200), (self.instrument_ids[2], 300) ] requests = [ models.UpsertQuoteRequest( quote_id=models.QuoteId( models.QuoteSeriesId( provider="DataScope", instrument_id=price[0], instrument_id_type="LusidInstrumentId", quote_type="Price", field="mid" ), effective_at=effective_date ), metric_value=models.MetricValue( value=price[1], unit="GBP" ) ) for price in prices ] self.quotes_api.upsert_quotes(TestDataUtilities.tutorials_scope, request_body={"quote" + str(request_number): requests[request_number] for request_number in range(len(requests))}) recipe_scope = 'cs-tutorials' recipe_code = 'quotes_recipe' self.id_generator.add_scope_and_code("recipe", recipe_scope, recipe_code) demo_recipe = models.ConfigurationRecipe( scope=recipe_scope, code=recipe_code, market=models.MarketContext( market_rules=[], suppliers=models.MarketContextSuppliers( equity='DataScope' ), options=models.MarketOptions( default_supplier='DataScope', default_instrument_code_type='LusidInstrumentId', default_scope=TestDataUtilities.tutorials_scope) ) ) upsert_recipe_request = models.UpsertRecipeRequest(demo_recipe) self.recipes_api.upsert_configuration_recipe(upsert_recipe_request) valuation_request = models.ValuationRequest( recipe_id=models.ResourceId(scope=recipe_scope,code=recipe_code), metrics=[ models.AggregateSpec("Instrument/default/Name", "Value"), models.AggregateSpec("Holding/default/PV", "Proportion"), models.AggregateSpec("Holding/default/PV", "Sum") ], group_by=["Instrument/default/Name"], portfolio_entity_ids = [ models.PortfolioEntityId(scope = TestDataUtilities.tutorials_scope, code = portfolio_code) ], valuation_schedule=models.ValuationSchedule(effective_at=effective_date) ) # do the aggregation aggregation = self.aggregation_api.get_valuation(valuation_request=valuation_request) for item in aggregation.data: print("\t{}\t{}\t{}".format(item["Instrument/default/Name"], item["Proportion(Holding/default/PV)"], item["Sum(Holding/default/PV)"])) # Asserts self.assertEqual(len(aggregation.data),3) self.assertEqual(aggregation.data[0]["Sum(Holding/default/PV)"], 10000) self.assertEqual(aggregation.data[1]["Sum(Holding/default/PV)"], 20000) self.assertEqual(aggregation.data[2]["Sum(Holding/default/PV)"], 30000)