Report to show Security's dividend history (per share)

Stuart Beesley (Mr Toolbox)'s Avatar

Stuart Beesley (Mr Toolbox)

20 Feb, 2025 04:42 AM

[Question raised by @he] Is there anywhere in MD that captures dividend amount per share? My objective is to see dividend history (per share) independent of shares owned. I'm not seeking the total amount which is calculated by multiplying dividend amount by shares held, I know that's already available. I'm seeking just the dividend amount per share, preferably over time. Is this possible?

[Response by @dwg] You do not enter it at all, and I'm not aware of Moneydance calculating it. Strictly speaking having an action type of Div does not necessarily mean it is a dividend. The action type just determined how a transaction is to be processed by Moneydance.

[Response by @he] @dwg, you're right, a security's dividend amount is not calculated within MD. It's either entered manually as the total dividend amount or downloaded from the brokerage. To me, the distributed dividend per share is valuable information. Can it not be calculated in a report based on the dividend amount and number of shares owned as of that date? Mathematically, it would be something like: Dividend share amount = Total dividend amount (downloaded or entered manually) / number of shares owned as of dividend date.

  1. 1 Posted by Stuart Beesley ... on 20 Feb, 2025 04:47 AM

    Stuart Beesley (Mr Toolbox)'s Avatar

    Great question... As mentioned, this is a bit tricky as the source information is not entered. I see a couple of issues, but primarily this:

    The DIV transaction is not necessarily entered on the same date as the 'record date' (the date a share qualifies for a divvy). As such, if the share balance moves between the record date and the ex div date, then the backwards calculation from divvy amount / qty held will be wrong.. So at best, this is an attempt at a calculation (with risk).

    Anyway, here is a first shot at a script to extract this... Let me know how it works, and perhaps report issues you see... If it becomes 'good enough' perhaps we can turn it into a 'proper' report.

    ticker="SMIN"
    from com.infinitekind.moneydance.model import ParentTxn, Account, InvestFields, InvestTxnType, AccountUtil
    from com.infinitekind.util import StringUtils
    md=moneydance
    book=moneydance_data
    ct=book.getCurrencies()
    base=ct.getBaseType()
    fmt=moneydance.getPreferences().getShortDateFormatter()
    security=ct.getCurrencyByTickerSymbol(ticker)
    if security is None: raise Exception("Ticker '%s' not found - aborting" %(ticker))
    print "Found Security: %s" %(security)
    fields=InvestFields()
    tSet=book.getTransactionSet()
    txns=tSet.iterableTxns()
    print ".. analysing txns...:"
    foundTxns=[]
    for txn in txns:
     if not isinstance(txn, ParentTxn): continue
     pAcct=txn.getAccount()
     if pAcct.getAccountType() != Account.AccountType.INVESTMENT: continue
     fields.setFieldStatus(txn)
     if not fields.hasSecurity: continue
     if fields.secCurr != security: continue
     if fields.txnType not in [InvestTxnType.DIVIDEND, InvestTxnType.DIVIDENDXFR, InvestTxnType.DIVIDEND_REINVEST]: continue
     # OK - we got one!
     foundTxns.append(txn)
    foundTxns=sorted(foundTxns, key=lambda sort_t: sort_t.getDateInt())
    for txn in foundTxns:  # yes this is repetative...
     fields.setFieldStatus(txn)
     pAcct=txn.getAccount()
     secAcct=fields.security
     if fields.secCurr != security: raise Exception("LOGIC ERROR: - '%s' != '%s'!?" %(fields.secCurr, security))
     balAsOf=AccountUtil.getBalanceAsOfDate(book, secAcct, txn.getDateInt()) 
     totDivvy=fields.amount
     divvy=0.0 if balAsOf == 0L else fields.curr.getDoubleValue(totDivvy)/security.getDoubleValue(balAsOf)
     print "Date: %s, Type: %s, Shares held in acct: %s, Total Divvy: %s, Fee: %s, Calc Divvy: %s, Acct currency: %s, Security account: %s,"\
          %(fmt.format(txn.getDateInt()), fields.txnType, security.formatFancy(balAsOf, "."), fields.curr.formatFancy(totDivvy, "."), fields.fee, StringUtils.formatRate(divvy, ".",4), fields.curr, secAcct.getFullAccountName())
    print "FINISHED"
    

    (I'm not sure what effect splits has on this. It's probably OK as we are reporting the divvy and balance on the actual dates recorded, but I haven't tested this)

  2. 2 Posted by dwg on 20 Feb, 2025 05:10 AM

    dwg's Avatar

    Not having the record date will create questions around accuracy.

  3. 3 Posted by Mekky SB on 20 Feb, 2025 02:22 PM

    Mekky SB's Avatar

    Hi,

    Agree!

    I've wanted the dividend payout rates recorded in the dividend history too and MD uses this information to automatically calculate the entitled dividend amount based on the holdings on the record dates. This would be helpful when I look back to see the payout rate history and the payout frequency rather than just the dividend amounts paid.

    Looking forward to seeing this new functionality in MD.

    Thanks.

  4. 4 Posted by Stuart Beesley ... on 20 Feb, 2025 02:24 PM

    Stuart Beesley (Mr Toolbox)'s Avatar

    Run the script and see how it works for you? Edit line one to change the ticker

  5. System closed this discussion on 22 May, 2025 02:30 PM.

  6. Stuart Beesley (Mr Toolbox) re-opened this discussion on 20 Sep, 2025 01:55 PM

  7. 5 Posted by Stuart Beesley ... on 20 Sep, 2025 01:55 PM

    Stuart Beesley (Mr Toolbox)'s Avatar

    Keeping this open

  8. 6 Posted by Stuart Beesley ... on 20 Sep, 2025 01:57 PM

    Stuart Beesley (Mr Toolbox)'s Avatar

    Has anyone run my script and was it at all useful?

  9. 7 Posted by -Kevin N. on 20 Sep, 2025 04:48 PM

    -Kevin N.'s Avatar

    Hey Stuart,

    I just ran your script. It calculated the total div amount and amount of the div per share.

    I have shares of Home Depot that split on Jan 5, 2000, 1.5 for 1. The script accurately displays the total shares before and after the split. The div per share is also accurately reflected.

    Nice!

    For anyone who wants to try Stuart's script, copy and paste the above script into the upper pane of the Developer Console window. (MD Menu bar > Window > Show Developer Console)

    Enter the desired ticker into line 1 of the script.
    Click the 'Run Snippet' button.

    -Kevin N.

  10. 8 Posted by Dan on 25 Sep, 2025 02:30 AM

    Dan's Avatar

    Hey Stuart, thanks so much for sharing that script! I actually modified it a bit to spit out a CSV file. I've attached my tweaked version.

    ticker = "XGRO.TO"
    from com.infinitekind.moneydance.model import ParentTxn, Account, InvestFields, InvestTxnType, AccountUtil
    from com.infinitekind.util import StringUtils
    import csv
    import os

    md = moneydance
    book = moneydance_data
    ct = book.getCurrencies()
    base = ct.getBaseType()
    fmt = moneydance.getPreferences().getShortDateFormatter()
    security = ct.getCurrencyByTickerSymbol(ticker)
    if security is None:
        raise Exception("Ticker '%s' not found - aborting" % (ticker))
    print("Found Security: %s" % (security))

    fields = InvestFields()
    tSet = book.getTransactionSet()
    txns = tSet.iterableTxns()
    print(".. analysing txns...:")
    foundTxns = []

    for txn in txns:
        if not isinstance(txn, ParentTxn):
            continue
        pAcct = txn.getAccount()
        if pAcct.getAccountType() != Account.AccountType.INVESTMENT:
            continue
        fields.setFieldStatus(txn)
        if not fields.hasSecurity:
            continue
        if fields.secCurr != security:
            continue
        if fields.txnType not in [InvestTxnType.DIVIDEND, InvestTxnType.DIVIDENDXFR, InvestTxnType.DIVIDEND_REINVEST]:
            continue
        # OK - we got one!
        foundTxns.append(txn)

    foundTxns = sorted(foundTxns, key=lambda sort_t: sort_t.getDateInt())

    csv_data = []
    for txn in foundTxns:
        fields.setFieldStatus(txn)
        pAcct = txn.getAccount()
        secAcct = fields.security
        if fields.secCurr != security:
            raise Exception("LOGIC ERROR: - '%s' != '%s'!?" % (fields.secCurr, security))
        
        balAsOf = AccountUtil.getBalanceAsOfDate(book, secAcct, txn.getDateInt())
        totDivvy = fields.amount
        divvy = 0.0 if balAsOf == 0L else fields.curr.getDoubleValue(totDivvy) / security.getDoubleValue(balAsOf)

        row = [
            fmt.format(txn.getDateInt()),
            fields.txnType,
            security.formatFancy(balAsOf, "."),
            fields.curr.formatFancy(totDivvy, "."),
            fields.fee,
            StringUtils.formatRate(divvy, ".", 4),
            fields.curr,
            secAcct.getFullAccountName()
        ]
        csv_data.append(row)

    try:
        data_dir = "."
        import sys
        home_dir = os.path.expanduser("~")
        output_file = os.path.join(home_dir, "dividend_report_%s.csv" % ticker)
        with open(output_file, 'w') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerow([
                "Date",
                "Type",
                "Shares held in acct",
                "Total Divvy",
                "Fee",
                "Calc Divvy",
                "Acct currency",
                "Security account"
            ])
            writer.writerows(csv_data)
        print("CSV report generated: %s" % output_file)
    except Exception as e:
        print("Error writing CSV file: %s" % str(e))

  11. 9 Posted by he on 25 Sep, 2025 08:54 AM

    he's Avatar

    Stuart, I was just browsing this forum and came across this. Although I was the initial requestor, I was unaware that you'd worked on a solution until this morning.

    The dividend/share amount has always been an interesting number to me, especially for evaluating trends on long-held securities. I've found it odd that neither Quicken nor MD tracked it.

    I'm not sure I remember how to run scripts but I'll give yours a try later and will report back. Until then, thank you for your efforts to make MD better, it's appreciated. (I use CB daily, couldn't live without it.)

  12. 10 Posted by dwg on 25 Sep, 2025 09:50 AM

    dwg's Avatar

    For Moneydance and Quicken to track Dividends per share there would have to be a field for it and in all likelihood it would have to be manually entered. Without the record date the software cannot calculate it with certainty, the data I do not believe is in any Direct Connect data, OFX files, it is not part of the QIF specification or I believe in Moneydance+ downloads simply because it is not part of the transaction details the institutions would receive so I think would have to be manual entry.

  13. 11 Posted by he on 25 Sep, 2025 01:14 PM

    he's Avatar

    Hi Stuart, below is feedback on the script:

    a) I understand your point about the potential for inaccuracy if share quantity changes between "date of record" and the "payable date". I believe this is a risk we have to take, and an acceptable one at that.

    b) Decimal precision on some of my securities extends to 6 digits to the right of the decimal point. The script uses 4 and rounds to those digits. Any chance we can make it 6?

    c) Picking nits here, but any chance of adding the currency symbol to the Calc Divvy?

    d) Finally, and here I go with pivot tables, but... it would be extremely helpful and powerful to be able to view trends. For example, some of my securities pay monthly dividends, others pay quarterly. I'd like to see the trend of dividend payments only for Q3 for a specific stock or group of stocks. Or dividend payments for only the month of February. Can you make this happen?

    Thanks again for this improvement. I've used several personal financial software packages and none do this. Even Fund Manager, which I consider the gold standard for investing software, doesn't provide. This improvement, in my opinion, adds tremendous value to the investing portion of MD. Thank you for creating it.

  14. 12 Posted by he on 25 Sep, 2025 01:23 PM

    he's Avatar

    For the technologically challenged, like myself, below are steps to run the scripts.

    a) Launch MD and click on Window/Show Developer Console.

    b) Copy script and paste into Python Snippet (top half of developer console). OK to delete "Hello World" line.

    c) First line of script is: ticker="SMIN". Change this to any ticker symbol in your portfolio.

    d) Click Run Snippet on top half of window. Results appear in the bottom half.

  15. 13 Posted by -Kevin N. on 25 Sep, 2025 01:34 PM

    -Kevin N.'s Avatar

    Hi he,

    I posted the instructions in post 7. :)
    https://infinitekind.tenderapp.com/discussions/investments/9245-rep...

    -Kevin N.

  16. 14 Posted by Stuart Beesley ... on 25 Sep, 2025 07:09 PM

    Stuart Beesley (Mr Toolbox)'s Avatar

    @he. I don’t really understand point d) - pivot etc. Can you be clearer with what you actually want the script to do?

    @all - I think we need MD to optionally request 2 extra datapoints on dividends which would make this perfect 1/ record date
    2/ divvy per share.

    These can be calculated if missing.

    Any thoughts?

  17. 15 Posted by he on 25 Sep, 2025 10:21 PM

    he's Avatar

    Stuart, regarding point d, it may be helpful to explain what I'm seeking by starting with the objective. I'm looking for trends in dividend payments.

    An example might also be helpful: Let's say stock ABC pays quarterly dividends. If I own ABC for a full 5 years, there will be 20 dividend records -- one for each quarter x 5 years worth. I'd like to see, for example, only what ABC's Q4 did for the last 5 years without having to sift through ABC's other quarters data that I don't need and don't want to see (which only slows down analysis along with making it far too easy to misread a column or a row). This is particularly helpful for understanding trends in dividend payments and ultimately leads to better cash flow projections.

    Since we haven't yet seen the final product, my request may be premature but thought I'd put in the request. Thank you again for working on this.

  18. 16 Posted by Daniel Côté on 25 Sep, 2025 10:43 PM

    Daniel Côté's Avatar

    On 9/25/25 18:21, he wrote:

  19. 17 Posted by Stuart Beesley ... on 26 Sep, 2025 05:17 AM

    Stuart Beesley (Mr Toolbox)'s Avatar

    @Daniel Cote - empty message?? Don’t reply by email, post using the forum link.

  20. 18 Posted by Stuart Beesley ... on 26 Sep, 2025 11:45 AM

    Stuart Beesley (Mr Toolbox)'s Avatar

    @he - ref: "d". In short, no - sorry, I will not be doing what you want here.

  21. 19 Posted by Stuart Beesley ... on 26 Sep, 2025 11:49 AM

    Stuart Beesley (Mr Toolbox)'s Avatar

    @all - I have tweaked the script and put it into a runnable file - attached. To run:

    Load Developer Console
    Click "Open Script"
    Select the py file on disk
    Click "Run" (not Run Snippet).

    You can pre-edit lines 30-36 as follows (use True or False):

    ticker="SMIN"
    csvOutputFile="/Users/stu/Downloads/dividend_report_%s.csv" %(ticker)
    writeCSV=True
    outputScreen=True
    screenCSV=True
    divvyRounding=4
    prefixDivSymbol=False
    
    to configure whether you want a csv file created, csv output to screen, and what rounding to apply, also whether to output the currency symbol. In addition, when outputting csv to screen, it will pre-load your clipboard (so you can paste into Excel).

    Let me know if you use this and how it goes?

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