Step 1. Load Up Announcement Data

! pip3 install rich[jupyter] tabula-py rich-dataframe >> /dev/null

import tabula
import os
import glob
import pandas as pd
from rich import print
import plotly.express as px

from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))

from jinja2 import Template
from IPython.display import display, HTML, JSON

from google.colab import data_table
data_table.enable_dataframe_formatter()
#data_table.disable_dataframe_formatter() ### Change display of dataframe in colabs

files_to_process = glob.glob("*.pdf")

complete_df = pd.DataFrame([])

for file_to_process in files_to_process: 
   tables = tabula.read_pdf(file_to_process, pages="all", silent=True, pandas_options={'header': None})
   for index, table in enumerate(tables):
       table.columns = ['ASX Code', 'ETF','Outstanding Units' ]
       if index == 0:
           table = table.iloc[1: , :]  ## select all rows after the first row
   df = pd.concat(tables)
   df['Month'] = file_to_process.split(".")[0]
   complete_df = pd.concat([complete_df, df])

complete_df = complete_df[complete_df['ASX Code'] != 'ASX Code']

complete_df['Month'] = pd.to_datetime(complete_df['Month']).dt.date
complete_df          =  complete_df.sort_values(by=['ASX Code' , 'Month'])
complete_df['Outstanding Units'] = complete_df['Outstanding Units'].str.replace(',', '').astype('int')

pivoted_df = complete_df.pivot(index=["ASX Code", "ETF"], columns="Month", values="Outstanding Units").reset_index()
pivoted_df.columns = pivoted_df.columns.astype(str)
pivoted_df.fillna(0, inplace=True)
#for col in list(pivoted_df.columns):
#  if col.startswith('20'):
#      pivoted_df[col] = pivoted_df[col].str.replace(',', '').astype('int')

print(len(pivoted_df), "EFT's Loaded", 'Up :thumbsup:')
51 EFT's Loaded Up 👍

Step 2. Review Raw Data as Table

Noting Betashare have 51 ETFs and 6 new ones in the last year.

#data_table.DataTable(pivoted_df, include_index=False, num_rows_per_page=52)


## Generic Approach to render data frame through jinja2 template in notebook
template = Template('''
<table class="formattedTable" width="100%">
  <thead>
    <tr>
      {% for c in columns %}
      <th>{{ c }}</th>
      {% endfor %}
    </tr>
  </thead>
  <tbody>
     {% for row in rows %}
     <tr class="{{ loop.cycle('odd', 'even') }}" >
     {% for k, v in row.items() %}
        {% if v|int != 0 or v == 0 %}
          <td><div>{{"%.0f"|format(v|int)}}</div></td>
        {% else %}
          <td><div>{{v}}</div></td>
        {% endif %}
     {% endfor %}
     </tr>
     {% endfor %}
  </tbody>
</table>
<style>
table.formattedTable {
      border: 1px solid lightgray;
      border-bottom: 1px solid lightgray;
      border-spacing: 0;
}
table.formattedTable th {
  border: thin solid grey;
  background : lightgray;
  color: black;
  min-width: 90px;
  text-align: center;
  padding: 5px;
}
table.formattedTable td {
  border: thin solid grey;
  min-width: 90px;
  text-align: center;
  padding: 5px;
}

table.formattedTable.odd {
   background: #0D1424;
}
.even {
   background: lightgrey;
}
</style>''')

HTML(template.render(
    rows=pivoted_df[['ASX Code', 'ETF', '2021-05-01', '2022-03-01']].to_dict(orient='records'),
    columns=pivoted_df[['ASX Code', 'ETF', '2021-05-01', '2022-03-01']].columns.to_list()
))
ASX Code ETF 2021-05-01 2022-03-01
A200
BetaShares Australia 200 ETF
10809229
17933943
AAA
BetaShares Australian High Interest Cash ETF
46442129
48737401
AGVT
BetaShares Australian Government Bond ETF
3565216
4785957
ASIA
BetaShares Asia Technology Tigers ETF
58639628
65322554
ATEC
BetaShares S&P/ASX Australian Technology ETF
8702734
8956023
BHYB
BetaShares Australian Major Bank Hybrids Index ETF
200000
10903145
BNKS
BetaShares Global Banks ETF – Currency Hedged
11421084
18434340
CLDD
BetaShares Cloud Computing ETF
2500000
4700931
CRED
BetaShares Australian Investment Grade Corporate Bond ETF
17779768
21009457
CRYP
BetaShares Crypto Innovators ETF
0
19200000
DBBF
BetaShares Ethical Diversified Balanced ETF
200499
551296
DGGF
BetaShares Ethical Diversified Growth ETF
206484
865082
DHHF
BetaShares Diversified All Growth ETF
1454731
5102899
DRIV
BetaShares Electric Vehicles and Future Mobility ETF
0
1100000
DRUG
BetaShares Global Healthcare ETF – Currency Hedged
14018623
20684793
DZZF
BetaShares Ethical Diversified High Growth ETF
250245
1209924
EEU
BetaShares Euro ETF
590000
740000
ERTH
BetaShares Climate Change Innovation ETF
4400000
15901572
ETHI
BetaShares Global Sustainability Leaders ETF
115920361
171614898
EX20
BetaShares Australian Ex-20 Portfolio Diversifier ETF
10132947
11365155
F100
BetaShares FTSE 100 ETF
32212507
44162284
FAIR
BetaShares Australian Sustainability Leaders ETF
51063087
66408134
FOOD
BetaShares Global Agriculture Companies ETF – Currency Hedged
4617143
9434223
FUEL
BetaShares Global Energy Companies ETF – Currency Hedged
71632349
49695938
GAME
BetaShares Video Games and E-Sports ETF
0
300000
GBND
BetaShares Sustainability Leaders Diversified Bond ETF - Currency Hedged
5130358
7657434
GGOV
BetaShares Global Government Bond 20+ Year ETF - Currency Hedged
160104
160535
HACK
BetaShares Global Cybersecurity ETF
53576469
73210287
HETH
BetaShares Global Sustainability Leaders ETF – Currency Hedged
8707368
13384229
HEUR
BetaShares Europe ETF - Currency Hedged
3117804
4024650
HJPN
BetaShares Japan ETF - Currency Hedged
3806099
6611943
HNDQ
BetaShares NASDAQ 100 ETF – Currency Hedged
2500016
3305908
HQLT
BetaShares Global Quality Leaders ETF - Currency Hedged
825111
1429101
IBUY
BetaShares Online Retail and E-Commerce ETF
0
200000
IIND
BetaShares India Quality ETF
5041403
7221713
INCM
BetaShares Global Income Leaders ETF
1278268
1506084
IPAY
BetaShares Future of Payments ETF
0
600000
MNRS
BetaShares Global Gold Miners ETF – Currency Hedged
9607042
10625880
NDQ
BetaShares NASDAQ 100 ETF
59128972
78311770
OOO
BetaShares Crude Oil Index ETF – Currency Hedged (Synthetic)
40396759
30611002
OZBD
BetaShares Australian Composite Bond ETF
0
120000
POU
BetaShares British Pound ETF
747235
847235
QAU
BetaShares Gold Bullion ETF – Currency Hedged
19421845
19579448
QFN
BetaShares Australian Financials Sector ETF
4399308
4512177
QLTY
BetaShares Global Quality Leaders ETF
6538490
12647108
QOZ
BetaShares FTSE RAFI Australia 200 ETF
23075138
26444434
QPON
BetaShares Australian Bank Senior Floating Rate Bond ETF
25789160
25152730
QRE
BetaShares Australian Resources Sector ETF
13144597
13291325
QUS
BetaShares S&P 500 Equal Weight ETF
3200413
4555123
RBTZ
BetaShares Global Robotics and Artificial Intelligence ETF
10824515
14772333
USD
BetaShares U.S. Dollar ETF
11018740
11518740

Step 3. Review Percentage Growth in Outstanding Units

BHYB is number one in growth over the past year (excluding the ETF's released in the last year).

import numpy as np

pivoted_df['Percentage Change (%)'] = (pivoted_df['2022-03-01'] -  pivoted_df['2021-05-01'] ) /  pivoted_df['2021-05-01'] * 100
pivoted_df['Absolute Change']   = pivoted_df['2022-03-01'] -  pivoted_df['2021-05-01'] 

change_df = pivoted_df[['ASX Code', 'ETF', 'Percentage Change (%)', 'Absolute Change']].sort_values(by='Percentage Change (%)', ascending=False)

change_df.replace([np.inf, -np.inf], np.nan, inplace=True)
# Drop rows with NaN
change_df.dropna(inplace=True)



HTML(template.render(
    rows=change_df.to_dict(orient='records'),
    columns=change_df.columns.to_list()
))
ASX Code ETF Percentage Change (%) Absolute Change
BHYB
BetaShares Australian Major Bank Hybrids Index ETF
5351
10703145
DZZF
BetaShares Ethical Diversified High Growth ETF
383
959679
DGGF
BetaShares Ethical Diversified Growth ETF
318
658598
ERTH
BetaShares Climate Change Innovation ETF
261
11501572
DHHF
BetaShares Diversified All Growth ETF
250
3648168
DBBF
BetaShares Ethical Diversified Balanced ETF
174
350797
FOOD
BetaShares Global Agriculture Companies ETF – Currency Hedged
104
4817080
QLTY
BetaShares Global Quality Leaders ETF
93
6108618
CLDD
BetaShares Cloud Computing ETF
88
2200931
HJPN
BetaShares Japan ETF - Currency Hedged
73
2805844
HQLT
BetaShares Global Quality Leaders ETF - Currency Hedged
73
603990
A200
BetaShares Australia 200 ETF
65
7124714
BNKS
BetaShares Global Banks ETF – Currency Hedged
61
7013256
HETH
BetaShares Global Sustainability Leaders ETF – Currency Hedged
53
4676861
GBND
BetaShares Sustainability Leaders Diversified Bond ETF - Currency Hedged
49
2527076
ETHI
BetaShares Global Sustainability Leaders ETF
48
55694537
DRUG
BetaShares Global Healthcare ETF – Currency Hedged
47
6666170
IIND
BetaShares India Quality ETF
43
2180310
QUS
BetaShares S&P 500 Equal Weight ETF
42
1354710
F100
BetaShares FTSE 100 ETF
37
11949777
HACK
BetaShares Global Cybersecurity ETF
36
19633818
RBTZ
BetaShares Global Robotics and Artificial Intelligence ETF
36
3947818
AGVT
BetaShares Australian Government Bond ETF
34
1220741
NDQ
BetaShares NASDAQ 100 ETF
32
19182798
HNDQ
BetaShares NASDAQ 100 ETF – Currency Hedged
32
805892
FAIR
BetaShares Australian Sustainability Leaders ETF
30
15345047
HEUR
BetaShares Europe ETF - Currency Hedged
29
906846
EEU
BetaShares Euro ETF
25
150000
CRED
BetaShares Australian Investment Grade Corporate Bond ETF
18
3229689
INCM
BetaShares Global Income Leaders ETF
17
227816
QOZ
BetaShares FTSE RAFI Australia 200 ETF
14
3369296
POU
BetaShares British Pound ETF
13
100000
EX20
BetaShares Australian Ex-20 Portfolio Diversifier ETF
12
1232208
ASIA
BetaShares Asia Technology Tigers ETF
11
6682926
MNRS
BetaShares Global Gold Miners ETF – Currency Hedged
10
1018838
AAA
BetaShares Australian High Interest Cash ETF
4
2295272
USD
BetaShares U.S. Dollar ETF
4
500000
ATEC
BetaShares S&P/ASX Australian Technology ETF
2
253289
QFN
BetaShares Australian Financials Sector ETF
2
112869
QRE
BetaShares Australian Resources Sector ETF
1
146728
QAU
BetaShares Gold Bullion ETF – Currency Hedged
0.8114728544069835
157603
GGOV
BetaShares Global Government Bond 20+ Year ETF - Currency Hedged
0.26920001998700843
431
QPON
BetaShares Australian Bank Senior Floating Rate Bond ETF
-2
-636430
OOO
BetaShares Crude Oil Index ETF – Currency Hedged (Synthetic)
-24
-9785757
FUEL
BetaShares Global Energy Companies ETF – Currency Hedged
-30
-21936411

Step 4. Review Data (as Chart - Discrete Scales)

Each ETF has its own y axis scale - this chart shows relative growth.

fig = px.bar(complete_df, x="Month", y="Outstanding Units", color='ASX Code', facet_col="ASX Code", facet_col_wrap=6,  hover_data=['ASX Code', 'ETF'], height=1000).for_each_trace(lambda t: t.update(name=t.name.replace("Code", ""))).for_each_annotation(lambda a: a.update(text=a.text.split("=")[-1]))
 ## ['ASX Code'] == 'BHYB']
fig.update_yaxes(visible=False ,showticklabels=False, matches=None)
fig.update_xaxes(visible=False ,showticklabels=False)
fig.update_layout(showlegend=False).for_each_trace(lambda t: t.update(name=t.name.replace("ASX Code=", "")))
fig.show()