Converting Investment Transaction to DIVIDEND_REINVEST

john.vogtle+infinitekind's Avatar

john.vogtle+infinitekind

15 Nov, 2024 12:57 PM

Hi

My brokerage sends statements that show Dividend Reinvestments but the OFX downloads are two separate transactions:

  • One is InvestTxnType.DIVIDEND (technically the parent txn)
  • One is InvestTxnType.BUY I want to delete the DIVIDEND transaction and convert the BUY to DIVIDEND_REINVEST. In the UI, I usually just delete the DIV transaction and change the type of the other to DivReinvest

From a code standpoint:

  • The delete is easy.
  • Is the conversion of the BUY to DIVIDEND_INVEST as simple as changing the transaction type or do I need to do something like:
parent_txn = txn.getParentTxn()
fields = InvestFields()
fields.setFieldStatus(InvestTxnType.DIVIDEND_REINVEST, parent_txn)
fields.storeFields(parent_txn)
parent_txn.syncItem()

Thanks in advance...

  1. Support Staff 1 Posted by Sean Reilly on 15 Nov, 2024 01:06 PM

    Sean Reilly's Avatar

    Hi John,

    That is very close! What I would do is something like this:

    fields = InvestFields()
    fields.setFieldStatus(buyTxn) // loads the details of the buy (price, #shares, amount, fee) since that's what you want to keep
    fields.txnType = InvestTxnType.DIVIDEND_REINVEST
    fields.category = dividendIncomeCategory
    fields.storeFields(buyTxn)
    buyTxn.syncItem()
    

    It is on my to-do list to add an option to automatically merge separate dividend and reinvest transactions.

    Thanks,
    Sean

    --
    Sean Reilly
    Developer, The Infinite Kind
    https://infinitekind.com

  2. 2 Posted by john.vogtle+inf... on 15 Nov, 2024 04:18 PM

    john.vogtle+infinitekind's Avatar

    Thanks, Sean. I'll give it a shot and report back!

  3. 3 Posted by john.vogtle+inf... on 29 Nov, 2024 04:53 PM

    john.vogtle+infinitekind's Avatar

    Hi Sean -

    Just getting back to this after an "interesting" couple of weeks. I think I'm almost there but while the transaction now says DivReinvest, it acts in the account register like a Buy. I've attached a screen shot showing the weirdness.

    If I the visibly no-op operation of setting the transaction in the UI to DivReinvest, the calculation straightens out.

    Here's the current code for converting the transactions.

    def cvt_divbuy_to_divreinvest(account_name = None):
        div_txns = dict()
        investment_acct = ra.getAccountByName(account_name)
    
        txn_cnt = 0
    
        acct_txns = moneydance_data.getTransactionSet().getTransactionsForAccount(investment_acct)
        all_txns = moneydance_data.getTransactionSet()
        for txn in acct_txns:
    
            if txn.getClearedStatus() != AbstractTxn.ClearedStatus.CLEARED:
                parent_txn = txn.getParentTxn()
    
                date = parent_txn.getDateInt()
                description = txn.getDescription()
                amt = txn.getValue()
    
                key = (date, description, abs(amt))
                div_txns.setdefault(key, [])
                div_txns.get(key).append(txn)
    
        for key in div_txns.keys():
            print repr(key), len(div_txns.get(key))
            if len(div_txns.get(key)) == 2:
                for txn in div_txns.get(key):
                    parent_txn = txn.getParentTxn()
                    if parent_txn.getInvestTxnType() == InvestTxnType.DIVIDEND:
                        if not dry_run:
                            print "About to delete transaction: {}".format(repr(txn))
                            all_txns.removeTxn(txn)
                        else:
                            print "Need to delete" + repr(txn)
    
                    elif parent_txn.getInvestTxnType() == InvestTxnType.BUY:
                        print "Need to convert to DIVIDEND_REINVEST" + repr(parent_txn)
    
                        # From Sean
                        fields = InvestFields()
                        # loads the details of the buy (price, #shares, amount, fee) since that's what you want to keep
                        fields.setFieldStatus(txn)
                        fields.txnType = InvestTxnType.DIVIDEND_REINVEST
                        fields.category = AccountUtil.getDefaultCategoryForAcct(investment_acct)
                        print "       New Investment Field Settings: " + str(fields)
                        txn_cnt += 1
    
                        if not dry_run:
                            fields.storeFields(txn)
                            txn.syncItem()
    
        if txn_cnt == 0:
            print "No DIV/BUY transactions needed to be converted to DIV_REINVEST in {}".format(account_name)
    
  4. 4 Posted by john.vogtle+inf... on 08 Dec, 2024 10:29 PM

    john.vogtle+infinitekind's Avatar

    @Sean - can you have a look at the code above and report what I might be missing...

  5. 5 Posted by Stuart Beesley ... on 09 Dec, 2024 07:13 AM

    Stuart Beesley (Mr Toolbox)'s Avatar

    Can you right click the txn after your code runs and grab show raw details. Then noop edit it and grab a new raw details. Post both here. I suspect there’s a leftover parameter that needs clearing out. With the raw details it will be easy to spot.

  6. 6 Posted by Stuart Beesley ... on 09 Dec, 2024 07:43 AM

    Stuart Beesley (Mr Toolbox)'s Avatar

    Ok. I haven’t tested this but taking a quick peek tells me you need to do this too:

    fields.hasCategory = True
    

    …right before you set the fields.category

    Then everything else should fire into place

    Let me know?

  7. 7 Posted by john.vogtle+inf... on 09 Dec, 2024 03:15 PM

    john.vogtle+infinitekind's Avatar

    Just saw this Stuart. I'll respond back with my findings.

  8. 8 Posted by john.vogtle+inf... on 10 Dec, 2024 01:31 AM

    john.vogtle+infinitekind's Avatar

    Hey Stuart. Busy work day. Here's what I've found:

    Raw Output Post Script

    0.acctid: 0f550735-75d1-4af2-9782-379c07151e19
    0.desc: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L
    0.id: 664915ea-1161-4d11-8ade-e35c7f80ed2c
    0.invest.splittype: sec
    0.obj_type: 
    0.pamt: -248
    0.samt: 25500
    0.stat:
    acctid: 68803903-60c3-40e5-b15e-018caed07ec8 chk: desc: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L dt: 20241202 dtentered: 1733757269614 id: 393ae0e1-8235-43a0-9fb0-9be9c71cdcad invest.txntype: divr memo: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L obj_type: txn ol.match-status: 1 ol.match-type: 0 ol.orig-memo: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L ol.orig-payee: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L ol.orig-txn: { "dtinit-int" = "20241202" "dtpstd-int" = "20241202" "fitxnid" = "464HR7100000051241202008055329" "invst.buytype" = "BUY" "invst.commission" = "0" "invst.fees" = "0" "invst.load" = "0" "invst.numshares" = "0.255" "invst.ofxtxntype" = "BUYMF" "invst.securityid" = "94904P831" "invst.securityidtype" = "CUSIP" "invst.shareprice" = "9.7254902" "invst.subaccfund" = "OTHER" "invst.subaccttype" = "OTHER" "invst.taxes" = "0" "invst.totalamt" = "-248" "invst.txntype" = "buy" "memo" = "Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L" "orig_data" = "<BUYMF> <INVBUY> <INVTRAN> <FITID>464HR7100000051241202008055329 <DTTRADE>20241202120000.000[-5:EST] <DTSETTLE>20241202120000.000[-5:EST] <MEMO>Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L </INVTRAN> <SECID> <UNIQUEID>94904P831 <UNIQUEIDTYPE>CUSIP </SECID> <UNITS>0.255 <UNITPRICE>9.7254902 <COMMISSION>0.00 <TAXES>0.00 <FEES>0.00 <TOTAL>-2.48 <SUBACCTSEC>OTHER <SUBACCTFUND>OTHER </INVBUY> <BUYTYPE>BUY </BUYMF> " }


    ol_fitid_1: 464HR7100000051241202008055329 reinvest: true stat:
    td: 20241202 ts: 1733782880450 xfer_type: xfrtp_dividend
    After "no-op" DivReinvest
    0.acctid: 0f550735-75d1-4af2-9782-379c07151e19
    0.desc: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L
    0.id: 664915ea-1161-4d11-8ade-e35c7f80ed2c
    0.invest.splittype: sec
    0.obj_type: 
    0.pamt: -248
    0.rate: 102.8225806451613
    0.samt: 25500
    0.stat:
    1.acctid: 0e0b3d4f-12cd-4ea9-987c-a17e0ce3a884 1.desc: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L 1.id: fab26ce3-4de6-4d78-a28b-149baaa2645c 1.invest.splittype: inc 1.obj_type: 1.pamt: 248 1.samt: -248 acctid: 68803903-60c3-40e5-b15e-018caed07ec8 chk: desc: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L dt: 20241202 dtentered: 1733757269614 id: 393ae0e1-8235-43a0-9fb0-9be9c71cdcad invest.txntype: divr memo: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L obj_type: txn ol.match-status: 1 ol.match-type: 0 ol.orig-memo: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L ol.orig-payee: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L ol.orig-txn: { "dtinit-int" = "20241202" "dtpstd-int" = "20241202" "fitxnid" = "464HR7100000051241202008055329" "invst.buytype" = "BUY" "invst.commission" = "0" "invst.fees" = "0" "invst.load" = "0" "invst.numshares" = "0.255" "invst.ofxtxntype" = "BUYMF" "invst.securityid" = "94904P831" "invst.securityidtype" = "CUSIP" "invst.shareprice" = "9.7254902" "invst.subaccfund" = "OTHER" "invst.subaccttype" = "OTHER" "invst.taxes" = "0" "invst.totalamt" = "-248" "invst.txntype" = "buy" "memo" = "Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L" "orig_data" = "<BUYMF> <INVBUY> <INVTRAN> <FITID>464HR7100000051241202008055329 <DTTRADE>20241202120000.000[-5:EST] <DTSETTLE>20241202120000.000[-5:EST] <MEMO>Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L </INVTRAN> <SECID> <UNIQUEID>94904P831 <UNIQUEIDTYPE>CUSIP </SECID> <UNITS>0.255 <UNITPRICE>9.7254902 <COMMISSION>0.00 <TAXES>0.00 <FEES>0.00 <TOTAL>-2.48 <SUBACCTSEC>OTHER <SUBACCTFUND>OTHER </INVBUY> <BUYTYPE>BUY </BUYMF> " }


    ol_fitid_1: 464HR7100000051241202008055329 reinvest: true stat:
    td: 20241202 ts: 1733783075673 xfer_type: xfrtp_dividend
    The difference seems to be the addition of several lines:
    0.rate: 102.8225806451613
    0.samt: 25500                -- Unchanged
    0.stat:                             -- Unchanged
    1.acctid: 0e0b3d4f-12cd-4ea9-987c-a17e0ce3a884
    1.desc: Purchased 0.255 shares @ $9.7254902 WEITZ CORE PLUS INCOME FUND INSTL CL N/L
    1.id: fab26ce3-4de6-4d78-a28b-149baaa2645c
    1.invest.splittype: inc
    1.obj_type: 
    1.pamt: 248
    1.samt: -248
    
    I then added the fields.hasCategory = True to the script as you suggested and it worked like a champ!

    Thanks so much! Can you tell me where you found the fields documented or did you decompile a Java class to find out?

    Thanks again.
    -John

Reply to this discussion

Internal reply

Formatting help / Preview (switch to plain text) No formatting (switch to Markdown)

Attaching KB article:

»

Attached Files

You can attach files up to 10MB

If you don't have an account yet, we need to confirm you're human and not a machine trying to post spam.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac