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",
+ " txn_id | \n",
+ " trade_date | \n",
+ " transaction_type | \n",
+ " instrument_desc | \n",
+ " client_internal | \n",
+ " instrument_currency | \n",
+ " quantity | \n",
+ " price | \n",
+ " net_money | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " txn01 | \n",
+ " 2020-01-01T00:00:00.0000000+00:00 | \n",
+ " FundsIn | \n",
+ " CASH_GBP | \n",
+ " cash | \n",
+ " GBP | \n",
+ " 1000000 | \n",
+ " 1.00 | \n",
+ " 1000000 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " txn02 | \n",
+ " 2020-01-02T00:00:00.0000000+00:00 | \n",
+ " Buy | \n",
+ " Tesco | \n",
+ " EQ_001 | \n",
+ " GBP | \n",
+ " 100000 | \n",
+ " 2.56 | \n",
+ " 256000 | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " txn03 | \n",
+ " 2020-01-03T00:00:00.0000000+00:00 | \n",
+ " Sell | \n",
+ " Tesco | \n",
+ " EQ_001 | \n",
+ " GBP | \n",
+ " 30000 | \n",
+ " 2.56 | \n",
+ " 256000 | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " txn04 | \n",
+ " 2020-01-04T00:00:00.0000000+00:00 | \n",
+ " DirectAdjustmentIncrease | \n",
+ " Tesco | \n",
+ " EQ_001 | \n",
+ " GBP | \n",
+ " 50000 | \n",
+ " 0.00 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " txn05 | \n",
+ " 2020-01-05T00:00:00.0000000+00:00 | \n",
+ " DirectAdjustmentDecrease | \n",
+ " Tesco | \n",
+ " EQ_001 | \n",
+ " GBP | \n",
+ " 40000 | \n",
+ " 0.00 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\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",
+ " names | \n",
+ " cost | \n",
+ " units | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " GBP | \n",
+ " 1000000.0 | \n",
+ " 1000000.0 | \n",
+ "
\n",
+ " \n",
+ "
\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",
+ " names | \n",
+ " cost | \n",
+ " units | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " GBP | \n",
+ " 744000.0 | \n",
+ " 744000.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " Tesco | \n",
+ " 256000.0 | \n",
+ " 100000.0 | \n",
+ "
\n",
+ " \n",
+ "
\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",
+ " names | \n",
+ " cost | \n",
+ " units | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " GBP | \n",
+ " 1000000.0 | \n",
+ " 1000000.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " Tesco | \n",
+ " 179200.0 | \n",
+ " 70000.0 | \n",
+ "
\n",
+ " \n",
+ "
\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",
+ " names | \n",
+ " cost | \n",
+ " units | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " GBP | \n",
+ " 1000000.0 | \n",
+ " 1000000.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " Tesco | \n",
+ " 179200.0 | \n",
+ " 120000.0 | \n",
+ "
\n",
+ " \n",
+ "
\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",
+ " names | \n",
+ " cost | \n",
+ " units | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " GBP | \n",
+ " 1000000.0 | \n",
+ " 1000000.0 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " Tesco | \n",
+ " 179200.0 | \n",
+ " 80000.0 | \n",
+ "
\n",
+ " \n",
+ "
\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