Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
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
Exemplo n.º 3
0
    def test_aggregation(self, _, in_line_recipe, recipe_scope,
                         recipe_code) -> None:
        """
        General valuation/aggregation test
        """
        # create recipe (provides model parameters, locations to use in resolving market data etc.
        # and push it into LUSID. Only needs to happen once each time when updated, or first time run to create.
        recipe = self.create_configuration_recipe(recipe_scope, recipe_code)
        self.upsert_recipe_request(recipe)

        # Set valuation result key
        valuation_key = "Sum(Holding/default/PV)"

        # create valuation 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"],
            valuation_schedule=models.ValuationSchedule(
                effective_at=self.effective_date),
            portfolio_entity_ids=[
                models.PortfolioEntityId(
                    scope=TestDataUtilities.tutorials_scope,
                    code=self.portfolio_code)
            ])

        # Complete aggregation
        aggregation = self.aggregation_api.get_valuation(
            valuation_request=valuation_request)

        # Asserts
        self.assertEqual(len(aggregation.data), 3)
        self.assertEqual(aggregation.data[0][valuation_key], 10000)
        self.assertEqual(aggregation.data[1][valuation_key], 20000)
        self.assertEqual(aggregation.data[2][valuation_key], 30000)
Exemplo n.º 4
0
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)
Exemplo n.º 6
0
    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)