From cf93067936b1ee5b91781383a361686247fd17b7 Mon Sep 17 00:00:00 2001 From: Dan Barclay Date: Thu, 30 Mar 2023 15:32:42 +0100 Subject: [PATCH] SE-3083: Add notebook for Direct Adjustments --- .../Direct Adjustments.ipynb | 1083 +++++++++++++++++ .../transaction-types/data/transactions.csv | 6 + 2 files changed, 1089 insertions(+) create mode 100644 examples/use-cases/transaction-types/Direct Adjustments.ipynb create mode 100644 examples/use-cases/transaction-types/data/transactions.csv diff --git a/examples/use-cases/transaction-types/Direct Adjustments.ipynb b/examples/use-cases/transaction-types/Direct Adjustments.ipynb new file mode 100644 index 00000000..1811a818 --- /dev/null +++ b/examples/use-cases/transaction-types/Direct Adjustments.ipynb @@ -0,0 +1,1083 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "
\n", + " \n", + " \n", + "\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from lusidtools.jupyter_tools import toggle_code\n", + "\n", + "\"\"\"Direct Adjustments\n", + "\n", + "Attributes\n", + "----------\n", + "DirectAdjustment\n", + "Transactions\n", + "Portfolio\n", + "Instruments\n", + "\"\"\"\n", + "\n", + "toggle_code(\"Toggle Docstring\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Direct Adjustments\n", + "\n", + "This notebook demonstrates how to create transactions that update the units of an holding without having any impact on the cost.\n", + "\n", + "In this notebook, we will:\n", + "1. **[Setup LUSID](#1.-Setup-LUSID)**\n", + "2. **[Load Data](#2.-Load-Data)**\n", + "3. **[Create Portfolio](#3.-Create-Portfolio)**\n", + "4. **[Load Instrument](#4.-Load-Instrument)**\n", + "5. **[Load Transactions](#5.-Load-Transactions)**\n", + "6. **[Configure Transaction Types](#6.-Configure-Transaction-Types)**\n", + "7. **[Get Holdings](#7.-Get-Holdings)**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Setup LUSID\n", + "Initialise our LUSID environment." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "pycharm": { + "is_executing": true + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LUSID Environment Initialised\n", + "LUSID SDK Version: 0.6.11054.0\n" + ] + } + ], + "source": [ + "import json\n", + "import lusid\n", + "import pandas as pd\n", + "from lusid import models\n", + "from lusid.utilities import ApiClientFactory\n", + "from lusidjam import RefreshingToken\n", + "\n", + "# Initiate an API Factory which is the client side object for interacting with LUSID APIs\n", + "api_factory = lusid.utilities.ApiClientFactory(\n", + " token=RefreshingToken(),\n", + " app_name=\"LusidJupyterNotebook\",\n", + ")\n", + "\n", + "print(\"LUSID Environment Initialised\")\n", + "print(\n", + " \"LUSID SDK Version: \",\n", + " api_factory.build(lusid.api.ApplicationMetadataApi)\n", + " .get_lusid_versions()\n", + " .build_version,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Build the APIs\n", + "transaction_portfolios_api = api_factory.build(lusid.api.TransactionPortfoliosApi)\n", + "portfolios_api = api_factory.build(lusid.api.PortfoliosApi)\n", + "instruments_api = api_factory.build(lusid.api.InstrumentsApi)\n", + "transaction_configuration_api = api_factory.build(lusid.api.TransactionConfigurationApi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Load Data\n", + "\n", + "Pull data from our local csv data file. Note the `DirectAdjustmentIncrease` and `DirectAdjustmentDecrease` transaction type, once we create them, it is these that will allow an increase/decrease in units to occur without impacting the cost of the transaction.\n", + "\n", + "For these transactions, the price will need to be set to 0." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
txn_idtrade_datetransaction_typeinstrument_descclient_internalinstrument_currencyquantitypricenet_money
0txn012020-01-01T00:00:00.0000000+00:00FundsInCASH_GBPcashGBP10000001.001000000
1txn022020-01-02T00:00:00.0000000+00:00BuyTescoEQ_001GBP1000002.56256000
2txn032020-01-03T00:00:00.0000000+00:00SellTescoEQ_001GBP300002.56256000
3txn042020-01-04T00:00:00.0000000+00:00DirectAdjustmentIncreaseTescoEQ_001GBP500000.000
4txn052020-01-05T00:00:00.0000000+00:00DirectAdjustmentDecreaseTescoEQ_001GBP400000.000
\n", + "
" + ], + "text/plain": [ + " txn_id trade_date transaction_type \\\n", + "0 txn01 2020-01-01T00:00:00.0000000+00:00 FundsIn \n", + "1 txn02 2020-01-02T00:00:00.0000000+00:00 Buy \n", + "2 txn03 2020-01-03T00:00:00.0000000+00:00 Sell \n", + "3 txn04 2020-01-04T00:00:00.0000000+00:00 DirectAdjustmentIncrease \n", + "4 txn05 2020-01-05T00:00:00.0000000+00:00 DirectAdjustmentDecrease \n", + "\n", + " instrument_desc client_internal instrument_currency quantity price \\\n", + "0 CASH_GBP cash GBP 1000000 1.00 \n", + "1 Tesco EQ_001 GBP 100000 2.56 \n", + "2 Tesco EQ_001 GBP 30000 2.56 \n", + "3 Tesco EQ_001 GBP 50000 0.00 \n", + "4 Tesco EQ_001 GBP 40000 0.00 \n", + "\n", + " net_money \n", + "0 1000000 \n", + "1 256000 \n", + "2 256000 \n", + "3 0 \n", + "4 0 " + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "txns = pd.read_csv(\"./data/transactions.csv\")\n", + "txns" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Create Portfolio\n", + "\n", + "Create a portfolio to upload our transactions into." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "pycharm": { + "is_executing": true + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Portfolio 'UK_EQUITY' created\n" + ] + } + ], + "source": [ + "# Scope & code\n", + "scope = \"DirectAdjustmentsExample\"\n", + "portfolio_code = \"UK_EQUITY\"\n", + "\n", + "# Create portfolio with properties\n", + "subholding_key = {}\n", + "created_date = \"2010-01-01T00:00:00.000000+00:00\"\n", + "\n", + "# create request body\n", + "portfolio_request = models.CreateTransactionPortfolioRequest(\n", + " display_name=\"UK-EQUITY\",\n", + " code=portfolio_code,\n", + " base_currency=\"GBP\",\n", + " created=created_date\n", + ")\n", + "\n", + "# Upload new portfolio to LUSID\n", + "try:\n", + " response = transaction_portfolios_api.create_portfolio(\n", + " scope=scope, create_transaction_portfolio_request=portfolio_request\n", + " )\n", + "\n", + " print(f\"Portfolio '{response.id.code}' created\")\n", + " \n", + "except lusid.ApiException as e:\n", + " if json.loads(e.body)[\"code\"] == 112: # PortfolioWithIdAlreadyExists\n", + " print(json.loads(e.body)[\"title\"])\n", + " else:\n", + " raise e" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Load Instrument\n", + "\n", + "Create instrument for `Tesco`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 instrument created\n" + ] + } + ], + "source": [ + "# Remove duplicate values\n", + "instrument_unique = txns.drop_duplicates(subset=\"client_internal\")\n", + "\n", + "# Remove cash rows\n", + "instruments = instrument_unique[instrument_unique[\"client_internal\"] != \"cash\"]\n", + "\n", + "request_body = {\n", + " instr[\"instrument_desc\"]: models.InstrumentDefinition(\n", + " name=instr[\"instrument_desc\"],\n", + " identifiers={ \"ClientInternal\": models.InstrumentIdValue(value=instr[\"client_internal\"]) },\n", + " )\n", + " for row, instr in instruments.iterrows()\n", + "}\n", + "\n", + "# Upsert new instruments to LUSID\n", + "instrument_response = instruments_api.upsert_instruments(\n", + " request_body=request_body\n", + ")\n", + "\n", + "# Check response was successful\n", + "if len(instrument_response.failed) > 0:\n", + " raise AssertionError(\"Instruments upsert failed. Inspect response for more detail\")\n", + "else:\n", + " val_len = len(instrument_response.values)\n", + " print(f\"{val_len} {'instrument' if val_len == 1 else 'instruments'} created\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Load Transactions\n", + "\n", + "Load in our transactions from the data file." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5 transactions upserted\n" + ] + } + ], + "source": [ + "# Upsert transactions\n", + "transactions_request = []\n", + "txn_response = []\n", + "txn_type_source = \"testsource\"\n", + "for row, txn in txns.iterrows():\n", + "\n", + " if txn[\"client_internal\"] == \"cash\":\n", + " instrument_identifier = {\"Instrument/default/Currency\": \"GBP\"}\n", + " else:\n", + " instrument_identifier = {\n", + " \"Instrument/default/ClientInternal\": txn[\"client_internal\"]\n", + " }\n", + "\n", + " # Build request body\n", + " transactions_request.append(\n", + " models.TransactionRequest(\n", + " transaction_id=txn[\"txn_id\"],\n", + " type=txn[\"transaction_type\"],\n", + " instrument_identifiers=instrument_identifier,\n", + " transaction_date=txn[\"trade_date\"],\n", + " settlement_date=txn[\"trade_date\"],\n", + " units=txn[\"quantity\"],\n", + " transaction_price=models.TransactionPrice(price=txn[\"price\"], type=\"Price\"),\n", + " total_consideration=models.CurrencyAndAmount(\n", + " amount=txn[\"net_money\"], currency=txn[\"instrument_currency\"]\n", + " ),\n", + " source=txn_type_source\n", + " )\n", + " )\n", + "\n", + " # Make upsert transactions call to LUSID\n", + " txn_response.append(\n", + " transaction_portfolios_api.upsert_transactions(\n", + " scope=scope, code=portfolio_code, transaction_request=transactions_request\n", + " )\n", + " )\n", + "\n", + "print(f\"{len(txn_response)} {'transaction' if len(txn_response) == 1 else 'transactions'} upserted\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6. Configure Transaction Types\n", + "\n", + "In this section we configure some new transaction types.\n", + "\n", + "`DirectAdjustmentDecrease` to **decrease** units without an impact on cost.\n", + "\n", + "`DirectAdjustmentIncrease` to **increase** units without an impact on cost.\n", + "\n", + "First, let's create the sides." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "'Tutorial-Side1' has been created in LUSID\n" + ] + } + ], + "source": [ + "# Define our side\n", + "response = transaction_configuration_api.set_side_definition(\n", + " \"Tutorial-Side1\", \n", + " side_definition_request=models.SideDefinitionRequest(\n", + " security=\"Txn:LusidInstrumentId\",\n", + " currency=\"Txn:TradeCurrency\",\n", + " rate=\"Txn:TradeToPortfolioRate\",\n", + " units=\"Txn:Units\",\n", + " amount=\"Txn:TradeAmount\"\n", + " )\n", + ")\n", + "\n", + "print(f\"'{response.side}' has been created in LUSID\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This outcome we are trying to achieve is contingent on the `movement_options` field within our new transaction type being set to `DirectAdjustment`. Without this, we will not be able to adjust our unit values without any impact on the cost." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction type 'DirectAdjustmentDecrease' created\n", + "Transaction type 'DirectAdjustmentIncrease' created\n" + ] + } + ], + "source": [ + "types = [\n", + " (\n", + " \"DirectAdjustmentDecrease\",\n", + " models.TransactionTypeRequest(\n", + " aliases=[\n", + " models.TransactionTypeAlias(\n", + " type=\"DirectAdjustmentDecrease\",\n", + " description=\"A negative direct adjustment type\",\n", + " transaction_class=\"Custom\",\n", + " transaction_roles=\"ShortShorter\",\n", + " )\n", + " ],\n", + " movements=[\n", + " models.TransactionTypeMovement(\n", + " movement_types=\"StockMovement\",\n", + " side=\"Tutorial-Side1\",\n", + " direction=-1,\n", + " properties={},\n", + " mappings=[],\n", + " movement_options=[\"DirectAdjustment\"] # Value required\n", + " )\n", + " ]\n", + " )\n", + " ),\n", + " (\n", + " \"DirectAdjustmentIncrease\",\n", + " models.TransactionTypeRequest(\n", + " aliases=[\n", + " models.TransactionTypeAlias(\n", + " type=\"DirectAdjustmentIncrease\",\n", + " description=\"A positive direct adjustment type\",\n", + " transaction_class=\"Custom\",\n", + " transaction_roles=\"LongLonger\",\n", + " )\n", + " ],\n", + " movements=[\n", + " models.TransactionTypeMovement(\n", + " movement_types=\"StockMovement\",\n", + " side=\"Tutorial-Side1\",\n", + " direction=1,\n", + " properties={},\n", + " mappings=[],\n", + " movement_options=[\"DirectAdjustment\"] # Value required\n", + " )\n", + " ]\n", + " )\n", + " )\n", + "]\n", + "\n", + "try:\n", + " for type in types:\n", + " response = transaction_configuration_api.set_transaction_type(\n", + " source=txn_type_source,\n", + " type=type[0],\n", + " transaction_type_request=type[1]\n", + " )\n", + " print(f\"Transaction type '{response.aliases[0].type}' created\")\n", + "\n", + "except lusid.ApiException as e:\n", + " print(json.loads(e.body))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7. Get Holdings\n", + "\n", + "To verify the `DirectAdjustment` transaction types have had the desired effect, let's fetch the holdings from points in time before and after the transactions have settled." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "# Prints the name and a quick summary from a get_holdings() response\n", + "def display_holdings_summary(response):\n", + " # Inspect holdings response for today\n", + " hld = [i for i in response.values]\n", + "\n", + " names = []\n", + " amount = []\n", + " units = []\n", + "\n", + " for item in hld:\n", + " names.append(item.properties[\"Instrument/default/Name\"].value.label_value)\n", + " amount.append(item.cost.amount)\n", + " units.append(item.units)\n", + "\n", + " data = {\"names\": names, \"cost\": amount, \"units\": units}\n", + "\n", + " summary = pd.DataFrame(data=data)\n", + " return summary" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Holdings: 1st January 2020 (FundsIn)\n", + "\n", + "The holdings of our portfolio at the settle date of our `FundsIn` transaction.\n", + "\n", + "At this date, cash is added into our portfolio. We don't own any `Tesco` stock yet." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namescostunits
0GBP1000000.01000000.0
\n", + "
" + ], + "text/plain": [ + " names cost units\n", + "0 GBP 1000000.0 1000000.0" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "holdings_response_1st_jan = transaction_portfolios_api.get_holdings(\n", + " scope=scope,\n", + " code=portfolio_code,\n", + " effective_at=\"2020-01-01T00:00:01.0000000+00:00\",\n", + " property_keys=[\"Instrument/default/Name\"],\n", + ")\n", + "\n", + "display_holdings_summary(holdings_response_1st_jan)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Holdings: 2nd January 2020 (Buy)\n", + "\n", + "The holdings of our portfolio at the settle date of our `Buy` transaction.\n", + "\n", + "Note the **increase** in units and **increase** in cost for `Tesco`." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namescostunits
0GBP744000.0744000.0
1Tesco256000.0100000.0
\n", + "
" + ], + "text/plain": [ + " names cost units\n", + "0 GBP 744000.0 744000.0\n", + "1 Tesco 256000.0 100000.0" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "holdings_response_2nd_jan = transaction_portfolios_api.get_holdings(\n", + " scope=scope,\n", + " code=portfolio_code,\n", + " effective_at=\"2020-01-02T00:00:01.0000000+00:00\",\n", + " property_keys=[\"Instrument/default/Name\"],\n", + ")\n", + "\n", + "display_holdings_summary(holdings_response_2nd_jan)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Holdings: 3rd January 2020 (Sell)\n", + "\n", + "The holdings of our portfolio at the settle date of our `Sell` transaction.\n", + "\n", + "Note the **decrease** in units and **decrease** in cost for `Tesco`." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namescostunits
0GBP1000000.01000000.0
1Tesco179200.070000.0
\n", + "
" + ], + "text/plain": [ + " names cost units\n", + "0 GBP 1000000.0 1000000.0\n", + "1 Tesco 179200.0 70000.0" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "holdings_response_3rd_jan = transaction_portfolios_api.get_holdings(\n", + " scope=scope,\n", + " code=portfolio_code,\n", + " effective_at=\"2020-01-03T00:00:01.0000000+00:00\",\n", + " property_keys=[\"Instrument/default/Name\"],\n", + ")\n", + "\n", + "display_holdings_summary(holdings_response_3rd_jan)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Holdings: 4th January 2020 (DirectAdjustmentIncrease)\n", + "\n", + "The holdings of our portfolio after the `DirectAdjustmentIncrease` transaction has settled.\n", + "\n", + "Note the **increase** in units but **no change** in cost for `Tesco`." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namescostunits
0GBP1000000.01000000.0
1Tesco179200.0120000.0
\n", + "
" + ], + "text/plain": [ + " names cost units\n", + "0 GBP 1000000.0 1000000.0\n", + "1 Tesco 179200.0 120000.0" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "holdings_response_4th_jan = transaction_portfolios_api.get_holdings(\n", + " scope=scope,\n", + " code=portfolio_code,\n", + " property_keys=[\"Instrument/default/Name\"],\n", + " effective_at=\"2020-01-04T00:00:01.0000000+00:00\",\n", + ")\n", + "\n", + "display_holdings_summary(holdings_response_4th_jan)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get Holdings: 5th January 2020 (DirectAdjustmentDecrease)\n", + "\n", + "The holdings of our portfolio after the `DirectAdjustmentDecrease` transaction has settled.\n", + "\n", + "Note the **decrease** in units but **no change** in cost for `Tesco`." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namescostunits
0GBP1000000.01000000.0
1Tesco179200.080000.0
\n", + "
" + ], + "text/plain": [ + " names cost units\n", + "0 GBP 1000000.0 1000000.0\n", + "1 Tesco 179200.0 80000.0" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "holdings_response_5th_jan = transaction_portfolios_api.get_holdings(\n", + " scope=scope,\n", + " code=portfolio_code,\n", + " property_keys=[\"Instrument/default/Name\"],\n", + " effective_at=\"2020-01-05T00:00:01.0000000+00:00\",\n", + ")\n", + "\n", + "display_holdings_summary(holdings_response_5th_jan)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + }, + "vscode": { + "interpreter": { + "hash": "b0fa6594d8f4cbf19f97940f81e996739fb7646882a419484c72d19e05852a7e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/use-cases/transaction-types/data/transactions.csv b/examples/use-cases/transaction-types/data/transactions.csv new file mode 100644 index 00000000..120894d9 --- /dev/null +++ b/examples/use-cases/transaction-types/data/transactions.csv @@ -0,0 +1,6 @@ +txn_id,trade_date,transaction_type,instrument_desc,client_internal,instrument_currency,quantity,price,net_money +txn01,2020-01-01T00:00:00.0000000+00:00,FundsIn,CASH_GBP,cash,GBP,1000000,1,1000000 +txn02,2020-01-02T00:00:00.0000000+00:00,Buy,Tesco,EQ_001,GBP,100000,2.56,256000 +txn03,2020-01-03T00:00:00.0000000+00:00,Sell,Tesco,EQ_001,GBP,30000,2.56,256000 +txn04,2020-01-04T00:00:00.0000000+00:00,DirectAdjustmentIncrease,Tesco,EQ_001,GBP,50000,0,0 +txn05,2020-01-05T00:00:00.0000000+00:00,DirectAdjustmentDecrease,Tesco,EQ_001,GBP,40000,0,0 \ No newline at end of file