# Talk:Comparison of accumulating ETFs and distributing ETFs

## Python table generation

The tables in this page were generated using a Python script. The source code for this script is below.

If Python is not available locally, run the script online with Repl.it, or similar. For example, for Repl.it, copy-and-paste the code into the source code editing window (left panel), and press "Run>". The output window (right panel) will contain the table formatted in wikitext.

Code listing
```  1#!/usr/bin/python3
2# -*- coding: utf-8 -*-
3# ... or run online through https://repl.it/languages/python3
4
5import math
6
7DIST_DIV = 0.03
8DIST_GAIN = 0.07
9YEARS = range(1, 11)
10
11
12class Holding:
13    def __init__(self, shares, nav, div, gain):
14        self.shares = shares
15        self.nav = nav
16        self.cash = 0.0
17        self.__div = div
18        self.__gain = gain
19
20    def balance(self):
21        return self.shares * self.nav
22
23    def annual(self):
24        dividend = (self.shares * self.nav) * self.__div
25        self.nav *= 1 + self.__gain
26        return dividend
27
29        frac_share, new_shares = math.modf(value / self.nav)
30        self.cash += frac_share * self.nav
31        self.shares += new_shares
32        while self.cash > self.nav:
33          self.shares += 1
34          self.cash -= self.nav
35
36    def sell(self, value):
37        sale_shares = math.floor(value / self.nav)
38        self.cash = sale_shares * self.nav
39        self.shares -= sale_shares
40
41
42dist = Holding(10000, 1.0, DIST_DIV, DIST_GAIN)
43accm = Holding(10000, 1.0, 0.0, DIST_DIV + DIST_GAIN)
44
45
46# Returns: (year,
47#          accm.nav, accm.shares, accm.balance(), accm.cash,
48#          dist.nav, dist.shares, dist.balance(), dist.cash)
49
50def record(year=None):
51    return (year,
52         accm.nav, accm.shares, accm.balance(), accm.cash,
53         dist.nav, dist.shares, dist.balance(), dist.cash)
54
55
56# Returns: [(year,
57#           accm.nav, accm.shares, accm.balance(), accm.cash,
58#           dist.nav, dist.shares, dist.balance(), dist.cash), ...]
59
60def accumulation():
61    data = [record()]
62    for year in YEARS:
63        dividend = dist.annual()
64        accm.annual()
66        data += [record(year)]
67    return data
68
69
70# Returns: [(year,
71#           accm.nav, accm.shares, accm.balance(), accm.cash,
72#           dist.nav, dist.shares, dist.balance(), dist.cash), ...],
73#           accm_total, dist_total
74
75def decumulation():
76    data = [record()]
77    (dist_total, accm_total) = (0.0, 0.0)
78    for year in YEARS:
79        dist.cash = dist.annual()
80        accm.annual()
81        accm.sell(dist.cash)
82        data += [record(year)]
83        accm_total += accm.cash
84        dist_total += dist.cash
85    return data, accm_total, dist_total
86
87
88# Returns: ['line', ...] in wikitable format
89
90def format_wiki_table(table_data, phase):
91
92    def __currency(value, places):
93        string = ('€{:,.%df}' % places).format(value)
94        if value > 100 and value < 1000:
95            return '{{0}}' + string
96        else:
97            return string
98
99    if phase == 'accumulation':
100        cash = 'Cash balance'
101    elif phase == 'decumulation':
102        cash = 'Cash withdrawal'
103
104    table = [
105        '{| class="wikitable mw-datatable" style="text-align: center;"',
106        '|+ Comparison of accumulating and distributing ETF investor outcomes,'
107        ' %s phase' % phase,
108        '|-',
109        '! scope="col" colspan="1" |',
110        '! scope="col" colspan="4" | Accumulating ETF investor',
111        '! scope="col" colspan="4" | Distributing ETF investor',
112        '|-',
113        '! scope="col" | Year',
114        '! scope="col" | ACCM net asset value',
115        '! scope="col" | Shares held',
116        '! scope="col" | Holding balance',
117        '! scope="col" | %s' % cash,
118        '! scope="col" | DIST net asset value',
119        '! scope="col" | Shares held',
120        '! scope="col" | Holding balance',
121        '! scope="col" | %s' % cash
122        ]
123    for elements in table_data:
124        table += ['|-']
125        year = elements
126        accm_cash = ' || %s' % __currency(elements, 2) if year else ' ||'
127        dist_cash = ' || %s' % __currency(elements, 2) if year else ' ||'
128        table += [('! %d' % year if year else '!')]
129        table += [' | %s' % __currency(elements, 4)
130                  + ' || %d' % elements
131                  + ' || %s' % __currency(elements, 2)
132                  + accm_cash
133                  + ' || %s' % __currency(elements, 4)
134                  + ' || %d' % elements
135                  + ' || %s' % __currency(elements, 2)
136                  + dist_cash
137                 ]
138    table += ['|}']
139    return table
140
141
142def main():
143    data = accumulation()
144    for line in format_wiki_table(data, 'accumulation'):
145        print(line)
146    print()
147
148    (dist.cash, accm.cash) = (0.0, 0.0)
149    (data, accm_total, dist_total) = decumulation()
150    for line in format_wiki_table(data, 'decumulation'):
151        print(line)
152    print()
153
154    print('Dist total withdrawal =', round(dist_total, 2))
155    print('Accm total withdrawal =', round(accm_total, 2))
156    print()
157
158    print('Dist investor result =',
159          round(dist.shares * dist.nav + dist_total, 2))
160    print('Accm investor result =',
161          round(accm.shares * accm.nav + accm_total, 2))
162
163
164if __name__ == '__main__':
165    main()
```

--TedSwippet 09:57, 18 August 2019 (UTC)
Updated: --TedSwippet 15:21, 30 December 2020 (UTC)