Skip to content

Vorabpauschale gets parsed as Dividend #163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
egorlukomsky opened this issue Jan 25, 2025 · 1 comment
Open

Vorabpauschale gets parsed as Dividend #163

egorlukomsky opened this issue Jan 25, 2025 · 1 comment
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@egorlukomsky
Copy link

I just got the recent Vorabpauschale transactions and they were mapped to Dividends (expected type would be Taxes).
It uses the same eventType ssp_corporate_action_invoice_cash, but the Amount is negative this time.

Here's a full transaction json example:
vorabpauschale.json

@egorlukomsky egorlukomsky added the bug Something isn't working label Jan 25, 2025
@NiklasRosenstein
Copy link
Collaborator

Oof, that's a bit of a tricky one. I think we could have the Event._parse_type() function handle this:

diff --git a/pytr/event.py b/pytr/event.py
index ca44893..5857c98 100644
--- a/pytr/event.py
+++ b/pytr/event.py
@@ -99,19 +99,29 @@ class Event:
             Event: Event object
         """
         date: datetime = datetime.fromisoformat(event_dict["timestamp"][:19])
-        event_type: Optional[EventType] = cls._parse_type(event_dict)
-        title: str = event_dict["title"]
         value: Optional[float] = (
             v if (v := event_dict.get("amount", {}).get("value", None)) is not None and v != 0.0 else None
         )
+        event_type: Optional[EventType] = cls._parse_type(event_dict, value)
+        title: str = event_dict["title"]
         fees, isin, note, shares, taxes = cls._parse_type_dependent_params(event_type, event_dict)
         return cls(date, title, event_type, fees, isin, note, shares, taxes, value)
 
     @staticmethod
-    def _parse_type(event_dict: Dict[Any, Any]) -> Optional[EventType]:
-        event_type: Optional[EventType] = tr_event_type_mapping.get(event_dict.get("eventType", ""), None)
-        if event_dict.get("status", "").lower() == "canceled":
-            event_type = None
+    def _parse_type(event_dict: Dict[Any, Any], value: Optional[float]) -> Optional[EventType]:
+        raw_event_type = event_dict.get("eventType", "")
+
+        if raw_event_type == "ssp_corporate_action_invoice_cash":
+            # This is usually dividends, but with a negative value this is a "Vorabpauschale" (German tax
+            # that is applied to non-distributing ETFs before they are realized since 2018).
+            assert value is not None, "no value associated with `ssp_corporate_action_invoice_cash` event?"
+            event_type = PPEventType.TAXES if value < 0 else PPEventType.DIVIDEND
+
+        else:
+            event_type: Optional[EventType] = tr_event_type_mapping.get(raw_event_type, None)
+            if event_dict.get("status", "").lower() == "canceled":
+                event_type = None
+
         return event_type

But then the timeline has its own bit of mapping logic for the subfolder, which isn't bijective compared to the PPEventType mapping, and I'd want to avoid duplicating more of that logic.

pytr/pytr/timeline.py

Lines 141 to 148 in f1484b6

subfolder = {
"benefits_saveback_execution": "Saveback",
"benefits_spare_change_execution": "RoundUp",
"ssp_corporate_action_invoice_cash": "Dividende",
"CREDIT": "Dividende",
"INTEREST_PAYOUT_CREATED": "Zinsen",
"SAVINGS_PLAN_EXECUTED": "Sparplan",
}.get(event["eventType"])

tr_event_type_mapping = {

Medium-term I suppose we could consider taking on some of the work already discussed in #98 and using a set of rules not only to determine the output folders, but also to normalize event types and data fields.

@NiklasRosenstein NiklasRosenstein added the help wanted Extra attention is needed label Feb 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants