From 612d8d432e2f0a6d1aa31f17b1e175303cd38d31 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Wed, 17 Jun 2026 19:38:04 +0200 Subject: [PATCH] Handle private markets sell order and IPO --- pytr/event.py | 16 +- tests/ipo-spacex.json | 198 ++++++++++++++++ tests/private_markets_verkaufsorder.json | 223 ++++++++++++++++++ ...ivate_markets_verkaufsorder_erstellt.json} | 0 tests/test_events.py | 45 +++- 5 files changed, 475 insertions(+), 7 deletions(-) create mode 100644 tests/ipo-spacex.json create mode 100644 tests/private_markets_verkaufsorder.json rename tests/{private_markets_verkaufs_order_erstellt.json => private_markets_verkaufsorder_erstellt.json} (100%) diff --git a/pytr/event.py b/pytr/event.py index a923403..247a9b5 100644 --- a/pytr/event.py +++ b/pytr/event.py @@ -80,6 +80,7 @@ class PPEventType(EventType): "TAX_REFUND": PPEventType.TAX_REFUND, "ssp_tax_correction_invoice": PPEventType.TAX_REFUND, # Trade invoices + "IPO_TRADE_EXECUTED": ConditionalEventType.TRADE_INVOICE, "ORDER_EXECUTED": ConditionalEventType.TRADE_INVOICE, "SAVINGS_PLAN_EXECUTED": ConditionalEventType.TRADE_INVOICE, "SAVINGS_PLAN_INVOICE_CREATED": ConditionalEventType.TRADE_INVOICE, @@ -164,6 +165,7 @@ class PPEventType(EventType): "CREDIT_CANCELED", "CUSTOMER_CREATED", "CRYPTO_ANNUAL_STATEMENT", + "CSX_CHAT_ACTIVITY", "DEVICE_RESET", "DOCUMENTS_ACCEPTED", "DOCUMENTS_CHANGED", @@ -231,6 +233,7 @@ class PPEventType(EventType): events_known_ignored_subtitle = [ "Cash oder Aktie", "Erteilt", + "Fall abgeschlossen", "Jährliche Hauptversammlung", "Kartenprüfung", "Kauf-Abrechnung storniert", @@ -536,12 +539,13 @@ def from_dict(cls, event_dict: Dict[Any, Any]): note = cls._parse_card_note(event_dict) if event_type == ConditionalEventType.PRIVATE_MARKETS_ORDER: - if value is None: - shares = 0 - else: - shares = abs(value) / 100 - if fees is not None: - shares = shares - (abs(fees) / 100) + if shares is None: + if value is None: + shares = 0 + elif fees is not None: + shares = (abs(value) - abs(fees)) / 100 + else: + shares = abs(value) / 100 note = event_dict["subtitle"] if event_type is PPEventType.SWAP and uebersicht_dict: diff --git a/tests/ipo-spacex.json b/tests/ipo-spacex.json new file mode 100644 index 0000000..9871d1c --- /dev/null +++ b/tests/ipo-spacex.json @@ -0,0 +1,198 @@ + { + "id": "e742c3cb-c17c-4905-845c-ab42189da291", + "timestamp": "2026-06-06T04:20:02.120+0000", + "title": "SpaceX", + "icon": "logos/US84615Q1031/v2", + "avatar": { + "asset": "logos/US84615Q1031/v2", + "badge": null + }, + "badge": null, + "subtitle": "IPO", + "amount": { + "currency": "EUR", + "value": -33.33, + "fractionDigits": 2 + }, + "subAmount": null, + "status": "EXECUTED", + "action": { + "type": "timelineDetail", + "payload": "e742c3cb-c17c-4905-845c-ab42189da291" + }, + "cashAccountNumber": "123456789", + "hidden": false, + "deleted": false, + "eventType": "IPO_TRADE_EXECUTED", + "source": "timelineTransaction", + "details": { + "id": "e742c3cb-c17c-4905-845c-ab42189da291", + "sections": [ + { + "title": "Du hast 33,33 € investiert", + "data": { + "icon": { + "asset": "logos/US84615Q1031/v2", + "badge": null + }, + "timestamp": "2026-06-06T04:20:02.081244Z", + "status": "executed" + }, + "action": { + "payload": "US84615Q1031", + "type": "instrumentDetail" + }, + "type": "header" + }, + { + "title": "Deine Zuteilung für SpaceX", + "description": "Du hast SpaceX Aktien im Wert von 32,33 € erhalten. Nicht investiertes Geld wurde erstattet.", + "type": "banner" + }, + { + "title": "Übersicht", + "data": [ + { + "title": "IPO", + "detail": { + "text": "Ausgeführt", + "functionalStyle": "EXECUTED", + "type": "status" + }, + "style": "plain" + }, + { + "title": "Asset", + "detail": { + "text": "SpaceX", + "displayValue": { + "text": "SpaceX" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Transaktion", + "detail": { + "text": "0,276891 × 116,762806 €", + "action": { + "payload": { + "id": "00000000-0000-0000-0000-000000000000", + "sections": [ + { + "title": "Transaktion", + "type": "title" + }, + { + "data": [ + { + "title": "Aktienkurs", + "detail": { + "text": "116,762806 €", + "displayValue": { + "text": "116,762806 €" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Aktien", + "detail": { + "text": "0,276891", + "displayValue": { + "text": "0,276891" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Summe", + "detail": { + "text": "32,33 €", + "displayValue": { + "text": "32,33 €" + }, + "type": "text" + }, + "style": "plain" + } + ], + "type": "table" + } + ] + }, + "displayMode": "bottomSheet", + "type": "infoPage" + }, + "displayValue": { + "text": "116,762806 €", + "prefix": "0,276891 × " + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Gebühr", + "detail": { + "text": "1,00 €", + "displayValue": { + "text": "1,00 €" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Summe", + "detail": { + "text": "33,33 €", + "displayValue": { + "text": "33,33 €" + }, + "type": "text" + }, + "style": "plain" + } + ], + "type": "table" + }, + { + "title": "Dokumente", + "data": [ + { + "title": "Abrechnung", + "action": { + "payload": "", + "type": "browserModal" + }, + "id": "1ae44e9f-08ae-46a4-80da-19e6c84f6a1c", + "postboxType": "SECURITIES_SETTLEMENT" + }, + { + "title": "Kosteninformation", + "action": { + "payload": "", + "type": "browserModal" + }, + "id": "a1566adc-c184-40f3-8062-87b3cf60197d", + "postboxType": "EQUITIES_BUY_EX_ANTE" + }, + { + "title": "Prospekt", + "action": { + "payload": "https://assets.traderepublic.com/assets/files/TR_EU_Prospectus_yD8uWbXoKs2.pdf", + "type": "browserModal" + }, + "id": "4b3b1e09-fd8d-38d7-9291-00de9b6a2cd1", + "postboxType": "" + } + ], + "type": "documents" + } + ] + } + } diff --git a/tests/private_markets_verkaufsorder.json b/tests/private_markets_verkaufsorder.json new file mode 100644 index 0000000..a1a2e0a --- /dev/null +++ b/tests/private_markets_verkaufsorder.json @@ -0,0 +1,223 @@ + { + "id": "86417e07-754d-45a6-a429-72c1437bc159", + "timestamp": "2026-06-08T14:15:00.000+0000", + "title": "Private Equity", + "icon": "logos/LU3176111881/v2", + "avatar": { + "asset": "logos/LU3176111881/v2", + "badge": null + }, + "badge": null, + "subtitle": "Verkaufsorder", + "amount": { + "currency": "EUR", + "value": 103.54, + "fractionDigits": 2 + }, + "subAmount": null, + "status": "EXECUTED", + "action": { + "type": "timelineDetail", + "payload": "86417e07-754d-45a6-a429-72c1437bc159" + }, + "cashAccountNumber": "12345678", + "hidden": false, + "deleted": false, + "eventType": "PRIVATE_MARKET_FUND_TRADE_EXECUTED", + "source": "timelineTransaction", + "details": { + "id": "86417e07-754d-45a6-a429-72c1437bc159", + "sections": [ + { + "title": "Du hast 103,54 € erhalten", + "data": { + "icon": { + "asset": "logos/LU3176111881/v2", + "badge": null + }, + "timestamp": "2026-06-08T14:15:00Z", + "status": "executed" + }, + "action": { + "payload": "LU3176111881", + "type": "instrumentDetail" + }, + "type": "header" + }, + { + "title": "Übersicht", + "data": [ + { + "title": "Verkaufen", + "detail": { + "text": "Ausgeführt", + "functionalStyle": "EXECUTED", + "type": "status" + }, + "style": "plain" + }, + { + "title": "Asset", + "detail": { + "text": "Private Equity", + "displayValue": { + "text": "Private Equity" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Transaktion", + "detail": { + "text": "1,01 × 105,7252 €", + "action": { + "payload": { + "id": "00000000-0000-0000-0000-000000000000", + "sections": [ + { + "title": "Transaktion", + "type": "title" + }, + { + "data": [ + { + "title": "Aktienkurs", + "detail": { + "text": "105,7252 €", + "displayValue": { + "text": "105,7252 €" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Aktien", + "detail": { + "text": "1,01", + "displayValue": { + "text": "1,01" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Summe", + "detail": { + "text": "103,54 €", + "displayValue": { + "text": "103,54 €" + }, + "type": "text" + }, + "style": "plain" + } + ], + "type": "table" + } + ] + }, + "displayMode": "bottomSheet", + "type": "infoPage" + }, + "displayValue": { + "text": "105,7252 €", + "prefix": "1,01 × " + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Abzug für 1 %-Bonus", + "detail": { + "text": "1,00 €", + "action": { + "payload": { + "id": "00000000-0000-0000-0000-000000000000", + "sections": [ + { + "title": "Abzug für 1 %-Bonus", + "type": "title" + }, + { + "text": "Du hast einen Bonus erhalten, der abgezogen werden muss, da du vor 18 Sept. 2027 verkaufst.", + "type": "text" + } + ] + }, + "displayMode": "bottomSheet", + "type": "infoPage" + }, + "displayValue": { + "text": "1,00 €" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Steuer", + "detail": { + "text": "1,24 €", + "displayValue": { + "text": "1,24 €" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Gebühr", + "detail": { + "text": "1,00 €", + "displayValue": { + "text": "1,00 €" + }, + "type": "text" + }, + "style": "plain" + }, + { + "title": "Summe", + "detail": { + "text": "103,54 €", + "displayValue": { + "text": "103,54 €" + }, + "type": "text" + }, + "style": "plain" + } + ], + "type": "table" + }, + { + "title": "Dokumente", + "data": [ + { + "title": "Abrechnung", + "action": { + "payload": "", + "type": "browserModal" + }, + "id": "7d8b50fe-e2fe-4d8a-859a-58e0d5354e82", + "postboxType": "SECURITIES_SETTLEMENT" + }, + { + "title": "Kosteninformation", + "action": { + "payload": "", + "type": "browserModal" + }, + "id": "b5ac9e63-b975-4a94-93dc-5652c0333522", + "postboxType": "EQUITIES_SELL_EX_ANTE" + } + ], + "type": "documents" + } + ] + } + } diff --git a/tests/private_markets_verkaufs_order_erstellt.json b/tests/private_markets_verkaufsorder_erstellt.json similarity index 100% rename from tests/private_markets_verkaufs_order_erstellt.json rename to tests/private_markets_verkaufsorder_erstellt.json diff --git a/tests/test_events.py b/tests/test_events.py index 1bd47a8..0317fd2 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -756,6 +756,26 @@ def test_events(): } ], }, + { + "filename": "ipo-spacex.json", + "event_type": ConditionalEventType.TRADE_INVOICE, + "title": "SpaceX", + "isin": "US84615Q1031", + "shares": 0.276891, + "value": -33.33, + "fees": 1.0, + "transactions": [ + { + "Datum": "2026-06-06T04:20:02", + "Typ": "Kauf", + "Wert": -33.33, + "Notiz": "SpaceX", + "ISIN": "US84615Q1031", + "Stück": 0.276891, + "Gebühren": 1.0, + } + ], + }, { "filename": "junior_p2p_transfer.json", "event_type": PPEventType.REMOVAL, @@ -1275,7 +1295,30 @@ def test_events(): ], }, { - "filename": "private_markets_verkaufs_order_erstellt.json", + "filename": "private_markets_verkaufsorder_erstellt.json", + }, + { + "filename": "private_markets_verkaufsorder.json", + "event_type": ConditionalEventType.PRIVATE_MARKETS_ORDER, + "title": "Private Equity", + "isin": "LU3176111881", + "shares": 1.01, + "value": 103.54, + "fees": 1, + "taxes": 1.24, + "note": "Verkaufsorder", + "transactions": [ + { + "Datum": "2026-06-08T14:15:00", + "Typ": "Verkauf", + "Wert": 103.54, + "Notiz": "EQT", + "ISIN": "LU3176111881", + "Stück": 1.01, + "Gebühren": 1.0, + "Steuern": 1.24, + }, + ], }, { "filename": "private_markets_vorabpauschale.json",