class NettingTest(unittest.TestCase):

    def setUp(self):
        self.longMessage = True  # Print complete error message on failure
        self.maxDiff = None  # View the complete diff when there is a mismatch in a test
        self.interface = TransactionsInterface(environment=ENVIRONMENT)
        self.asset_manager_id = 1
        self.assets_interface = AssetsInterface(environment=ENVIRONMENT)
        self.books_interface = BooksInterface(environment=ENVIRONMENT)
        self.asset = generate_asset(asset_manager_id=self.asset_manager_id, fungible=True)
        self.asset_book = generate_book(asset_manager_id=self.asset_manager_id)
        self.counterparty_book = generate_book(asset_manager_id=self.asset_manager_id)
        self.transaction1 = generate_transaction(asset_manager_id=self.asset_manager_id, asset_id=self.asset.asset_id,
                                                 asset_book_id=self.asset_book.book_id,
                                                 counterparty_book_id=self.counterparty_book.book_id,
                                                 transaction_currency='USD',
                                                 net_affecting_charges=True,
                                                 charge_currency='USD')
        self.transaction2 = generate_transaction(asset_manager_id=self.asset_manager_id, asset_id=self.asset.asset_id,
                                                 asset_book_id=self.asset_book.book_id,
                                                 counterparty_book_id=self.counterparty_book.book_id,
                                                 transaction_currency='USD',
                                                 net_affecting_charges=True,
                                                 charge_currency='USD')
        self.setup_cache()
        self.interface.new(self.transaction1)
        self.interface.new(self.transaction2)
        self.transaction_id1 = self.transaction1.transaction_id
        self.transaction_id2 = self.transaction2.transaction_id

    def tearDown(self):
        pass

    def create_transaction_asset(self):
        self.assets_interface.upsert(self.asset)

    def setup_cache(self):
        self.create_transaction_asset()
        self.create_transaction_book(self.asset_book)
        self.create_transaction_book(self.counterparty_book)

    def create_transaction_book(self, book):
        self.books_interface.new(book)

    def test_GenerateNettingSet(self):
        net = self.interface.net_transactions(asset_manager_id=self.asset_manager_id,
                                              transaction_ids=[self.transaction_id1, self.transaction_id2])
        self.assertEqual(type(net), Transaction)
        transaction_ids = {link.linked_transaction_id for link in net.links.get('NettingSet')}
        self.assertEqual(transaction_ids, {self.transaction_id1, self.transaction_id2})

    def test_RetrieveNettingSet(self):
        net = self.interface.net_transactions(asset_manager_id=self.asset_manager_id,
                                              transaction_ids=[self.transaction_id1, self.transaction_id2])
        net_transaction_id, netting_set = self.interface.retrieve_netting_set(asset_manager_id=self.asset_manager_id,
                                                                              transaction_id=net.transaction_id)
        self.assertEqual(net_transaction_id, net.transaction_id)
        self.assertEqual(len(netting_set), 2)
        transaction_ids = {transaction.transaction_id for transaction in netting_set}
        self.assertEqual(transaction_ids, {self.transaction_id1, self.transaction_id2})
示例#2
0
def _import_transaction(asset_manager_id, rowdata):
    charge_columns = [
        c for c in rowdata.keys() if c.startswith(CHARGES_PREFIX)
    ]
    charges = {
        column.replace(CHARGES_PREFIX, ''): rowdata.pop(column)
        for column in charge_columns if rowdata.get(column)
    }
    party_columns = [c for c in rowdata.keys() if c.startswith(PARTIES_PREFIX)]
    parties = {
        column.replace(PARTIES_PREFIX, ''): rowdata.pop(column)
        for column in party_columns if rowdata.get(column)
    }
    rate_columns = [c for c in rowdata.keys() if c.startswith(RATES_PREFIX)]
    rates = {
        column.replace(RATES_PREFIX, ''): rowdata.pop(column)
        for column in rate_columns if rowdata.get(column)
    }
    rowdata = {to_snake_case(key): value for key, value in rowdata.items()}

    asset_type = rowdata.pop('asset_type')
    if not asset_type:
        return
    asset_id = rowdata['asset_id']
    settlement_date = parse(rowdata['settlement_date'])
    if asset_type in ['ForeignExchangeSpot', 'ForeignExchangeForward']:
        underlying = asset_id
        # this should be handled by our SDK ideally
        prefix, model = ('SPT', ForeignExchangeSpot) \
                         if asset_type == 'ForeignExchangeSpot' \
                         else ('FWD', ForeignExchangeForward)
        asset_id = f'{prefix}{asset_id}{settlement_date.strftime("%Y%m%d")}'
        rowdata['asset_id'] = asset_id
        params = {
            'asset_manager_id': asset_manager_id,
            'asset_id': asset_id,
            'underlying': underlying,
            'settlement_date': rowdata['settlement_date'],
            'currency': rowdata['transaction_currency']
        }
        if asset_type == 'ForeignExchangeForward':
            params['fixing_date'] = rowdata.get('fixing_date')
            params['forward_rate'] = rowdata['price']
        asset = model(**params)
        asset.references['CCY Pair'] = Reference(underlying,
                                                 reference_primary=True)
        asset_api = AssetsInterface(environment=ENVIRONMENT)
        existing_asset = asset_api.search(asset_manager_id=asset_manager_id,
                                          asset_ids=[asset_id])
        asset = asset_api.new(asset) if not existing_asset \
                                     else asset_api.amend(asset)

    transaction = Transaction(**rowdata)
    transaction_api = TransactionsInterface(environment=ENVIRONMENT)
    existing_transaction = transaction_api.search(
        asset_manager_id=asset_manager_id,
        transaction_ids=[rowdata['transaction_id']])

    for party_type, party_id in parties.items():
        transaction.parties[party_type] = TransactionParty(party_id)
    for charge_type, charge_value in charges.items():
        transaction.charges[charge_type] = Charge(
            charge_value, rowdata['transaction_currency'])
    for rate_type, rate_value in rates.items():
        transaction.rates[rate_type] = Rate(rate_value)
    if not existing_transaction:
        transaction_api.new(transaction)
    else:
        transaction_api.amend(transaction)

    return transaction
示例#3
0
class AllocationTest(unittest.TestCase):

    def setUp(self):
        self.longMessage = True  # Print complete error message on failure
        self.maxDiff = None  # View the complete diff when there is a mismatch in a test
        self.transactions_interface = TransactionsInterface()
        self.asset_manager_id = 1
        self.asset = generate_asset(asset_manager_id=self.asset_manager_id)
        self.asset_book = generate_book(asset_manager_id=self.asset_manager_id)
        self.counterparty_book = generate_book(asset_manager_id=self.asset_manager_id)
        self.transaction = generate_transaction(asset_manager_id=self.asset_manager_id, asset_id=self.asset.asset_id,
                                                asset_book_id=self.asset_book.book_id,
                                                counterparty_book_id=self.counterparty_book.book_id)
        self.transaction_id = self.transaction.transaction_id
        self.setup_cache()

    def tearDown(self):
        pass

    def create_transaction_asset(self):
        transaction_asset_fields = ['asset_manager_id', 'asset_id', 'asset_status', 'asset_class', 'asset_type',
                                    'fungible']
        asset_json = self.asset.to_json()
        transaction_asset_json = {attr: asset_json.get(attr) for attr in transaction_asset_fields}
        self.transactions_interface.upsert_transaction_asset(transaction_asset_json=transaction_asset_json)

    def setup_cache(self):
        self.create_transaction_asset()
        self.create_transaction_book(self.asset_book)
        self.create_transaction_book(self.counterparty_book)

    def create_transaction_book(self, book):
        transaction_book_fields = ['asset_manager_id', 'book_id', 'party_id', 'book_status']
        book_json = book.to_json()
        transaction_book_json = {attr: book_json.get(attr) for attr in transaction_book_fields}
        self.transactions_interface.upsert_transaction_book(transaction_book_json=transaction_book_json)

    def test_Allocations(self):
        transaction = generate_transaction(asset_manager_id=self.asset_manager_id, asset_id=self.asset.asset_id,
                                           asset_book_id=self.asset_book.book_id,
                                           counterparty_book_id=self.counterparty_book.book_id,
                                           quantity=Decimal('100'))
        transaction.charges['TEST'] = Charge(charge_value=Decimal('10'), currency='SGD')
        self.transactions_interface.new(transaction)
        allocation_dicts = [{'book_id': 'ABC', 'quantity': Decimal('40')},
                            {'book_id': 'XYZ', 'quantity': Decimal('60')}]
        abc_book = generate_book(asset_manager_id=self.asset_manager_id, book_id='ABC')
        xyz_book = generate_book(asset_manager_id=self.asset_manager_id, book_id='XYZ')
        self.create_transaction_book(abc_book)
        self.create_transaction_book(xyz_book)
        allocations = self.transactions_interface.allocate_transaction(asset_manager_id=self.asset_manager_id,
                                                                       transaction_id=transaction.transaction_id,
                                                                       allocation_type='asset_manager',
                                                                       allocation_dicts=allocation_dicts)
        self.assertEqual(len(allocations), 2)
        book_ids = sorted([allocation.asset_book_id for allocation in allocations])
        self.assertEqual(book_ids, ['ABC', 'XYZ'])
        quantities = sorted([allocation.quantity for allocation in allocations])
        self.assertEqual(quantities, [Decimal('40'), Decimal('60')])
        charges = sorted([allocation.charges.get('TEST').charge_value for allocation in allocations])
        self.assertEqual(charges, [Decimal('4'), Decimal('6')])

    def test_AllocationWithExplictID(self):
        transaction = generate_transaction(asset_manager_id=self.asset_manager_id, asset_id=self.asset.asset_id,
                                           asset_book_id=self.asset_book.book_id,
                                           counterparty_book_id=self.counterparty_book.book_id,
                                           quantity=Decimal('100'))
        self.transactions_interface.new(transaction)
        partial_tran_id = transaction.transaction_id[:10]
        allocation_dicts = [{'book_id': 'ABC', 'quantity': Decimal('60'), 'transaction_id': partial_tran_id + '_ABC'},
                            {'book_id': 'XYZ', 'quantity': Decimal('40'), 'transaction_id': partial_tran_id + '_XYZ'}]
        abc_book = generate_book(asset_manager_id=self.asset_manager_id, book_id='ABC')
        xyz_book = generate_book(asset_manager_id=self.asset_manager_id, book_id='XYZ')
        self.create_transaction_book(abc_book)
        self.create_transaction_book(xyz_book)
        allocations = self.transactions_interface.allocate_transaction(asset_manager_id=self.asset_manager_id,
                                                                       transaction_id=transaction.transaction_id,
                                                                       allocation_type='counterparty',
                                                                       allocation_dicts=allocation_dicts)
        self.assertEqual(len(allocations), 2)
        book_ids = sorted([allocation.counterparty_book_id for allocation in allocations])
        self.assertEqual(book_ids, ['ABC', 'XYZ'])
        quantities = sorted([allocation.quantity for allocation in allocations])
        self.assertEqual(quantities, [Decimal('40'), Decimal('60')])
        transaction_ids = sorted([allocation.transaction_id for allocation in allocations])
        self.assertEqual(transaction_ids, [partial_tran_id + '_ABC', partial_tran_id + '_XYZ'])

    def test_RetrieveTransactionAllocations(self):
        pass