コード例 #1
0
    def test_seed_instrument_master(self):
        response = self.instruments_api.upsert_instruments(
            instruments={
                "BBG000FD8G46":
                models.InstrumentDefinition(name="HISCOX LTD",
                                            identifiers={
                                                "Figi":
                                                models.InstrumentIdValue(
                                                    value="BBG000FD8G46"),
                                                "ClientInternal":
                                                models.InstrumentIdValue(
                                                    value="internal_id_1")
                                            }),
                "BBG000DW76R4":
                models.InstrumentDefinition(name="ITV PLC",
                                            identifiers={
                                                "Figi":
                                                models.InstrumentIdValue(
                                                    value="BBG000DW76R4"),
                                                "ClientInternal":
                                                models.InstrumentIdValue(
                                                    value="internal_id_2")
                                            }),
                "BBG000PQKVN8":
                models.InstrumentDefinition(name="MONDI PLC",
                                            identifiers={
                                                "Figi":
                                                models.InstrumentIdValue(
                                                    value="BBG000PQKVN8"),
                                                "ClientInternal":
                                                models.InstrumentIdValue(
                                                    value="internal_id_3")
                                            }),
                "BBG000BDWPY0":
                models.InstrumentDefinition(name="NEXT PLC",
                                            identifiers={
                                                "Figi":
                                                models.InstrumentIdValue(
                                                    value="BBG000BDWPY0"),
                                                "ClientInternal":
                                                models.InstrumentIdValue(
                                                    value="internal_id_4")
                                            }),
                "BBG000BF46Y8":
                models.InstrumentDefinition(name="TESCO PLC",
                                            identifiers={
                                                "Figi":
                                                models.InstrumentIdValue(
                                                    value="BBG000BF46Y8"),
                                                "ClientInternal":
                                                models.InstrumentIdValue(
                                                    value="internal_id_5")
                                            })
            })

        self.assertEqual(len(response.values), 5, response.failed)
コード例 #2
0
    def test_seed_instrument_master(self):
        response = self.instruments_api.upsert_instruments(
            request_body={
                "BBG00KTDTF73":
                models.InstrumentDefinition(
                    name="AT&T INC",
                    identifiers={
                        "Figi":
                        models.InstrumentIdValue(value="BBG00KTDTF73"),
                        "ClientInternal":
                        models.InstrumentIdValue(value="internal_id_1_example")
                    }),
                "BBG00Y271826":
                models.InstrumentDefinition(
                    name="BYTES TECHNOLOGY GROUP PLC",
                    identifiers={
                        "Figi":
                        models.InstrumentIdValue(value="BBG00Y271826"),
                        "ClientInternal":
                        models.InstrumentIdValue(value="internal_id_2_example")
                    }),
                "BBG00L7XVNP1":
                models.InstrumentDefinition(
                    name="CUSHMAN & WAKEFIELD PLC",
                    identifiers={
                        "Figi":
                        models.InstrumentIdValue(value="BBG00L7XVNP1"),
                        "ClientInternal":
                        models.InstrumentIdValue(value="internal_id_3_example")
                    }),
                "BBG005D5KGM0":
                models.InstrumentDefinition(
                    name="FIRST CITRUS BANCORPORATION",
                    identifiers={
                        "Figi":
                        models.InstrumentIdValue(value="BBG005D5KGM0"),
                        "ClientInternal":
                        models.InstrumentIdValue(value="internal_id_4_example")
                    }),
                "BBG000DPM932":
                models.InstrumentDefinition(
                    name="FRASERS GROUP PLC",
                    identifiers={
                        "Figi":
                        models.InstrumentIdValue(value="BBG000DPM932"),
                        "ClientInternal":
                        models.InstrumentIdValue(value="internal_id_5_example")
                    })
            })

        self.assertEqual(len(response.values), 5, response.failed)
コード例 #3
0
    def test_lookup_instrument_by_unique_id(self):

        figi = "BBG000FD8G46"

        # set up the instrument
        response = self.instruments_api.upsert_instruments(requests={
            figi: models.InstrumentDefinition(
                name="HISCOX LTD",
                identifiers={
                    "Figi": models.InstrumentIdValue(value=figi),
                    "ClientInternal": models.InstrumentIdValue(value="internal_id_1")
                }
            )
        })
        self.assertEqual(len(response.values), 1, response.failed)

        # look up an instrument that already exists in the instrument master by a
        # unique id, in this case an OpenFigi, and also return a list of aliases
        looked_up_instruments = self.instruments_api.get_instruments(identifier_type="Figi",
                                                                     identifiers=[figi],
                                                                     instrument_property_keys=[
                                                                         "Instrument/default/ClientInternal"
                                                                     ])

        self.assertTrue(figi in looked_up_instruments.values, msg=f"cannot find {figi}")

        instrument = looked_up_instruments.values[figi]
        self.assertTrue(instrument.name, "HISCOX LTD")

        property = next(filter(lambda i: i.key == "Instrument/default/ClientInternal", instrument.properties), None)
        self.assertTrue(property.value, "internal_id_1")
コード例 #4
0
def batch_upsert(instrument_universe, api_factory):
    # Initialise our batch upsert request
    batch_upsert_request = {}
    # Iterate over our instrument universe
    for row, instrument in instrument_universe.iterrows():

        # Set our identifier columns
        identifier_columns = [('isin', 'Isin'), ('figi', 'Figi'),
                              ('ticker', 'Ticker'), ('sedol', 'Sedol'),
                              ('client_internal', 'ClientInternal')]

        # Create our identifiers
        identifiers = {}
        for identifier in identifier_columns:
            identifiers[identifier[1]] = models.InstrumentIdValue(
                value=instrument[identifier[0]])

        # Add the instrument to our batch request using the FIGI as the main unique identifier
        batch_upsert_request[
            instrument['instrument_name']] = models.InstrumentDefinition(
                name=instrument['instrument_name'], identifiers=identifiers)

    # Call LUSID to upsert our batch
    instrument_response = api_factory.build(
        lusid.api.InstrumentsApi).upsert_instruments(
            request_body=batch_upsert_request)

    # Pretty print the response from LUSID
    prettyprint.instrument_response(instrument_response, identifier='Figi')
    return batch_upsert_request
コード例 #5
0
    def test_create_custom_instrument(self):

        # create a definition for the instrument
        swap_definition = models.InstrumentDefinition(
            name="10mm 5Y Fixed",

            # The set of identifiers used for identifying the instrument
            # e.g. for uploading transactions
            identifiers={
                "ClientInternal": models.InstrumentIdValue(value="SW-1")
            },

            # The details for valuing the instrument
            definition=models.InstrumentEconomicDefinition(

                # Identifies which valuation engine to use
                instrument_format="CustomFormat",
                content="<customFormat>upload in custom xml or JSON format</customFormat>"))

        # create the swap
        swap_response = self.instruments_api.upsert_instruments(requests={
            "request": swap_definition
        })

        self.assertEqual(len(swap_response.failed), 0, swap_response.failed.values())
コード例 #6
0
def setup_instruments(api_factory, instrument_name, instrument_client_internal, properties: list):

    # Create an instrument
    test_instrument_req1 = models.InstrumentDefinition(
        name=instrument_name,
        identifiers={"ClientInternal": models.InstrumentIdValue(value=instrument_client_internal)},
        properties=properties
    )
    api_factory.build(lusid.api.InstrumentsApi).upsert_instruments(
        request_body={"request1": test_instrument_req1}
    )
コード例 #7
0
    def test_load_otc_instrument_transaction(self):
        # create the portfolio
        portfolio_code = self.test_data_utilities.create_transaction_portfolio(
            TestDataUtilities.tutorials_scope)

        trade_date = datetime(2018, 1, 1, tzinfo=pytz.utc)

        swap_definition = models.InstrumentDefinition(
            name="10mm 5Y Fixed",
            identifiers={
                "ClientInternal": models.InstrumentIdValue(value="SW-1")
            },
            definition=models.InstrumentEconomicDefinition(
                instrument_format="CustomFormat",
                content=
                "<customFormat>upload in custom xml or JSON format</customFormat>"
            ))

        # create the swap
        swap_response = self.instruments_api.upsert_instruments(
            requests={"request": swap_definition})

        # get the LUID for the created instrument
        swap_id = list(swap_response.values.values())[0].lusid_instrument_id

        #   details of the transaction to be added
        transaction = models.TransactionRequest(
            transaction_id=str(uuid.uuid4()),
            type="Buy",
            instrument_identifiers={
                TestDataUtilities.lusid_luid_identifier: swap_id
            },
            transaction_date=trade_date,
            settlement_date=trade_date,
            units=1,
            transaction_price=models.TransactionPrice(0.0),
            total_consideration=models.CurrencyAndAmount(0.0, "GBP"),
            source="Client")

        # add the transaction
        self.transaction_portfolios_api.upsert_transactions(
            scope=TestDataUtilities.tutorials_scope,
            code=portfolio_code,
            transactions=[transaction])

        # get the transaction
        transactions = self.transaction_portfolios_api.get_transactions(
            scope=TestDataUtilities.tutorials_scope, code=portfolio_code)

        self.assertEqual(len(transactions.values), 1)
        self.assertEqual(transactions.values[0].transaction_id,
                         transaction.transaction_id)
コード例 #8
0
    def test_create_zero_coupon_bond(self):

        zero_coupon_bond = models.Bond(start_date=datetime(2020,
                                                           2,
                                                           7,
                                                           00,
                                                           tzinfo=pytz.utc),
                                       maturity_date=datetime(2020,
                                                              9,
                                                              18,
                                                              00,
                                                              tzinfo=pytz.utc),
                                       dom_ccy="GBP",
                                       principal=100000,
                                       coupon_rate=0,
                                       flow_conventions=models.FlowConventions(
                                           scope=None,
                                           code=None,
                                           currency="GBP",
                                           payment_frequency="0Invalid",
                                           roll_convention="None",
                                           day_count_convention="Invalid",
                                           payment_calendars=[],
                                           reset_calendars=[],
                                           settle_days=2,
                                           reset_days=2),
                                       identifiers={},
                                       instrument_type="Bond")

        request_id = "upsert_request_001"
        zero_coupon_bond_identifier = "ZeroCouponBondInstrument"
        upsert_zero_coupon_bond = self.instruments_api.upsert_instruments(
            request_body={
                request_id:
                models.InstrumentDefinition(
                    name="Zero Coupon Bond Example",
                    identifiers={
                        "ClientInternal":
                        models.InstrumentIdValue(zero_coupon_bond_identifier)
                    },
                    definition=zero_coupon_bond)
            })
        # Assert instrument was created
        self.assertIsNotNone(
            upsert_zero_coupon_bond.values[request_id].instrument_definition)
        self.assertIsNotNone(
            upsert_zero_coupon_bond.values[request_id].lusid_instrument_id)

        # Remove the test instrument
        self.instruments_api.delete_instrument("ClientInternal",
                                               zero_coupon_bond_identifier)
コード例 #9
0
    def load_instruments(self):
        instruments_to_create = {
            i.Figi: models.InstrumentDefinition(
                name=i.Name,
                identifiers={
                    "Figi": models.InstrumentIdValue(value=i.Figi)
                }
            ) for i in self._instruments
        }

        response = self.instruments_api.upsert_instruments(request_body=instruments_to_create)

        assert (len(response.failed) == 0)

        return sorted([i.lusid_instrument_id for i in response.values.values()])
コード例 #10
0
 def upsert_otc_to_lusid(self, instrument, name, lusid_id):
     response = self.instruments_api.upsert_instruments(
         request_body={
             lusid_id:
             models.InstrumentDefinition(
                 name=name,
                 identifiers={
                     "ClientInternal": models.InstrumentIdValue(
                         value=lusid_id)
                 },
                 definition=instrument,
             )
         })
     # Check for failures with response
     self.assertEqual(len(response.values), 1, response.failed)
コード例 #11
0
def upsert_instruments(client, data_frame, instrument_identifier_mapping,
                       instrument_mapping_required,
                       instrument_mapping_optional):
    """
    This function upserts instruments

    :param client:
    :param data_frame:
    :param instrument_identifier_mapping:
    :param instrument_mapping_required:
    :param instrument_mapping_optional:
    :return:
    """

    # Initialise our batch upsert request
    batch_upsert_request = {}

    # Iterate over our instrument universe
    for row, instrument in data_frame.iterrows():

        # Create our identifiers
        identifiers = {}

        for identifier_lusid, identifier_column in instrument_identifier_mapping[
                'identifier_mapping'].items():

            if not pd.isna(instrument[identifier_column]):

                identifiers[identifier_lusid] = models.InstrumentIdValue(
                    value=instrument[identifier_column])

        # Add the instrument to our batch request using the FIGI as the main unique identifier
        single_instrument = models.InstrumentDefinition(
            name=instrument[instrument_mapping_required['name']],
            identifiers=identifiers)

        batch_upsert_request[instrument[
            instrument_mapping_required['name']]] = single_instrument

    # Call LUSID to upsert our batch
    instrument_response = client.instruments.upsert_instruments(
        requests=batch_upsert_request)

    # Pretty print the response from LUSID
    return instrument_response
コード例 #12
0
    def expected_response(self):
        instrument_definition = models.Bond(
            start_date=datetime(2002, 2, 28, tzinfo=pytz.utc),
            maturity_date=datetime(2032, 3, 1, tzinfo=pytz.utc),
            dom_ccy="USD",
            coupon_rate=0.07,
            principal=500000000,
            flow_conventions=models.FlowConventions(
                # coupon payment currency
                currency="USD",
                # semi-annual coupon payments
                payment_frequency="6M",
                # using an Actual/365 day count convention (other options : Act360, ActAct, ...
                day_count_convention="Thirty360",
                # modified following rolling convention (other options : ModifiedPrevious, NoAdjustment, EndOfMonth,...)
                roll_convention="MF",
                # no holiday calendar supplied
                payment_calendars=["US"],
                reset_calendars=["US"],
                settle_days=2,
                reset_days=2,
            ),
            identifiers={"clientInternal": "imd_34534538"},
            instrument_type="Bond",
        )

        instrument_request = {
            "ClientInternal: imd_34534538":
            models.InstrumentDefinition(
                # instrument display name
                name="DISNEY_7_2032",
                # unique instrument identifier
                identifiers={
                    "ClientInternal": models.InstrumentIdValue("imd_34534538"),
                    "Isin": models.InstrumentIdValue("US25468PBW59"),
                },
                # instrument definition
                definition=instrument_definition,
            )
        }

        return self.instruments_api.upsert_instruments(instrument_request)
コード例 #13
0
    def test_create_term_deposit(self):

        term_deposit = models.TermDeposit(
            start_date=datetime(2020, 2, 5, 00, tzinfo=pytz.utc),
            maturity_date=datetime(2020, 2, 8, 00, tzinfo=pytz.utc),
            contract_size=1000000,
            flow_convention=models.FlowConventions(
                scope=None,
                code=None,
                currency="GBP",
                payment_frequency="6M",
                roll_convention="MF",
                day_count_convention="Act365",
                payment_calendars=[],
                reset_calendars=[],
                settle_days=1,
                reset_days=0),
            rate=0.03,
            instrument_type="TermDeposit")

        request_id = "upsert_request_001"
        term_deposit_identifier = "TermDepositInstrument"
        upsert_term_deposit = self.instruments_api.upsert_instruments(
            request_body={
                request_id:
                models.InstrumentDefinition(name="Term Deposit Example",
                                            identifiers={
                                                "ClientInternal":
                                                models.InstrumentIdValue(
                                                    term_deposit_identifier)
                                            },
                                            definition=term_deposit)
            })
        # Assert instrument was created
        self.assertIsNotNone(
            upsert_term_deposit.values[request_id].instrument_definition)
        self.assertIsNotNone(
            upsert_term_deposit.values[request_id].lusid_instrument_id)

        # Remove the test instrument
        self.instruments_api.delete_instrument("ClientInternal",
                                               term_deposit_identifier)
コード例 #14
0
portfolio_request = models.CreateTransactionPortfolioRequest(
    display_name=f"Portfolio-{guid}",
    code=f"Id-{guid}",
    base_currency="GBP",
    created=portfolio_creation_date)

portfolio = tx_portfolios_api.create_portfolio(
    scope, create_transaction_portfolio_request=portfolio_request)
portfolio_code = portfolio.id.code
print("portfolio:", portfolio_code)

# Add instruments
# FIGIs are from https://www.openfigi.com/search#!?page=1
figis_to_create = {
    figi: models.InstrumentDefinition(
        name=name, identifiers={"Figi": models.InstrumentIdValue(value=figi)})
    for figi, name in [("BBG000C6K6G9",
                        "VODAFONE GROUP PLC"), ("BBG000C04D57",
                                                "BARCLAYS PLC")]
}

instruments_api.upsert_instruments(request_body=figis_to_create)

instruments = {
    value.name: value.lusid_instrument_id
    for _, value in instruments_api.get_instruments(
        identifier_type="Figi", request_body=list(
            figis_to_create.keys())).values.items()
}
inverted_instruments = {v: k for k, v in instruments.items()}
コード例 #15
0
    code=f"Id-{guid}",
    base_currency="GBP",
    created=datetime.datetime(2021, 3, 20, tzinfo=pytz.utc)
)

portfolio = tx_portfolios_api.create_portfolio(scope, create_transaction_portfolio_request=portfolio_request)
portfolio_code = portfolio.id.code
print("Porfolio Code:", portfolio_code)

# Upsert instruments
instruments_api = api_factory.build(lusid.api.InstrumentsApi)

# FIGI is from https://www.openfigi.com/id/BBG000C6K6G9
figis_to_create = {
    "BBG000C6K6G9": models.InstrumentDefinition(name="VODAFONE GROUP PLC",
        identifiers={"Figi": models.InstrumentIdValue(value="BBG000C6K6G9")}
    )
}

instruments_api.upsert_instruments(request_body=figis_to_create)

# Get instruments
instruments_response = instruments_api.get_instruments(
    identifier_type="Figi", request_body=list(figis_to_create.keys()))
name_to_luid = {
    value.name: value.lusid_instrument_id
    for _, value in instruments_response.values.items()
}
luid_to_name = {v: k for k, v in name_to_luid.items()}

# Upsert transactions
コード例 #16
0
    def test_name_change_corporate_action(self):
        """The code below shows how to process a corporate action name change in LUSID:
             Create two instruments, the original and the updated instrument.
             Create a portfolio and add a transaction to it for the original instrument.
             Create a corporate action source, and a corporate action comprising a transition.
             Upsert the corporate action, then check that the holding instrument was changed.
         """
        # Define details for the corporate action.
        instrument_name = "instrument-name"
        instrument_original_figi = "FR0123456789"
        instrument_updated_figi = "FR5555555555"

        effective_at_date = datetime(2021, 1, 1, tzinfo=pytz.utc)

        # Create two instruments: an "original" instrument which
        # will be renamed and the instrument it will be renamed to.
        self.instruments_api.upsert_instruments(
            request_body={
                instrument_original_figi:
                models.InstrumentDefinition(
                    name=instrument_name,
                    identifiers={
                        "Figi":
                        models.InstrumentIdValue(
                            value=instrument_original_figi)
                    },
                ),
                instrument_updated_figi:
                models.InstrumentDefinition(
                    name=instrument_name,
                    identifiers={
                        "Figi":
                        models.InstrumentIdValue(value=instrument_updated_figi)
                    },
                ),
            })
        _, scope, portfolio_code = self.id_generator.generate_scope_and_code(
            "portfolio",
            scope=TestDataUtilities.tutorials_scope,
            code_prefix="corporate-actions-portfolio-")

        try:
            # Create a transaction portfolio to hold the original instrument.
            self.transaction_portfolios_api.create_portfolio(
                scope=scope,
                create_transaction_portfolio_request=models.
                CreateTransactionPortfolioRequest(
                    code=portfolio_code,
                    display_name=portfolio_code,
                    base_currency="GBP",
                    created=effective_at_date,
                ),
            )
        except lusid.ApiException as e:
            if json.loads(e.body)["name"] == "PortfolioWithIdAlreadyExists":
                pass  # ignore if the portfolio exists

        # Add a transaction for the original instrument.
        self.transaction_portfolios_api.upsert_transactions(
            scope=TestDataUtilities.tutorials_scope,
            code=portfolio_code,
            transaction_request=[
                models.TransactionRequest(
                    transaction_id=str(uuid.uuid4()),
                    type="Buy",
                    instrument_identifiers={
                        TestDataUtilities.lusid_figi_identifier:
                        instrument_original_figi
                    },
                    transaction_date=effective_at_date,
                    settlement_date=effective_at_date,
                    transaction_price=models.TransactionPrice(0.0),
                    units=60000,
                    total_consideration=models.CurrencyAndAmount(0, "GBP"),
                    source="Client",
                )
            ],
        )

        corporate_action_source_code = "name-change-corporate-actions-source"
        corporate_action_code = "name-change-corporate-action"

        self.id_generator.add_scope_and_code("ca_source",
                                             TestDataUtilities.tutorials_scope,
                                             corporate_action_source_code)

        # Create a corporate actions source.
        corporate_action_source = models.CreateCorporateActionSourceRequest(
            scope=TestDataUtilities.tutorials_scope,
            code=corporate_action_source_code,
            display_name=corporate_action_source_code,
            description="Name change corporate actions source",
        )

        try:
            self.corporate_actions_sources_api.create_corporate_action_source(
                create_corporate_action_source_request=corporate_action_source)
        except lusid.ApiException as e:
            if json.loads(e.body)["name"] == "EntityWithIdAlreadyExists":
                pass  # ignore if the property definition exists

        # Apply the corporate actions source to the transaction portfolio.
        self.transaction_portfolios_api.upsert_portfolio_details(
            scope=TestDataUtilities.tutorials_scope,
            code=portfolio_code,
            effective_at=effective_at_date,
            create_portfolio_details=models.CreatePortfolioDetails(
                corporate_action_source_id=models.ResourceId(
                    scope=TestDataUtilities.tutorials_scope,
                    code=corporate_action_source_code,
                )),
        )

        # Create a transition which applies to the original instrument above
        transition_in = models.CorporateActionTransitionComponentRequest(
            instrument_identifiers={
                TestDataUtilities.lusid_figi_identifier:
                instrument_original_figi
            },
            cost_factor=1,
            units_factor=1,
        )

        # and has the effect of changing its FIGI to the updated FIGI
        rename_figi_transition = models.CorporateActionTransitionComponentRequest(
            instrument_identifiers={
                TestDataUtilities.lusid_figi_identifier:
                instrument_updated_figi
            },
            cost_factor=1,
            units_factor=1,
        )

        #   while zeroing the original instrument's position.
        zero_previous_position_transition = (
            models.CorporateActionTransitionComponentRequest(
                instrument_identifiers={
                    TestDataUtilities.lusid_figi_identifier:
                    instrument_original_figi
                },
                cost_factor=0,
                units_factor=0,
            ))

        # The effect of the corporate action is the transition which
        # combines the input transition and the output transitions.
        transition = models.CorporateActionTransitionRequest(
            input_transition=transition_in,
            output_transitions=[
                rename_figi_transition,
                zero_previous_position_transition,
            ],
        )

        self.id_generator.add_scope_and_code("corp_action",
                                             TestDataUtilities.tutorials_scope,
                                             corporate_action_source_code,
                                             [corporate_action_code])

        # Create a request to upsert a corporate action with the transition above.
        corporate_action_request = models.UpsertCorporateActionRequest(
            corporate_action_code=corporate_action_code,
            announcement_date=effective_at_date + timedelta(days=1),
            ex_date=effective_at_date + timedelta(days=1),
            record_date=effective_at_date + timedelta(days=1),
            payment_date=effective_at_date + timedelta(days=1),
            transitions=[transition],
        )

        # Make the request through the CorporateActionSourcesApi.
        self.corporate_actions_sources_api.batch_upsert_corporate_actions(
            scope=TestDataUtilities.tutorials_scope,
            code=corporate_action_source_code,
            upsert_corporate_action_request=[corporate_action_request],
        )

        # Fetch holdings in portfolio once corporate action is applied.
        holdings = self.transaction_portfolios_api.get_holdings(
            scope=TestDataUtilities.tutorials_scope,
            code=portfolio_code,
            property_keys=["Instrument/default/Figi"],
        )

        # The holding for the original instrument is now against the new instrument's FIGI.
        self.assertEqual(
            holdings.values[0].properties[
                TestDataUtilities.lusid_figi_identifier].value.label_value,
            instrument_updated_figi,
        )