Sydney Stock Exchange – view trading on a particular day

Select a date to view details of that day's trading (if any).

In [ ]:
# This notebook is designed to run in Voila as an app (with the code hidden).
# To launch this notebook in Voila, just select 'View > Open with Voila in New Browser Tab'
# Your browser might ask for permission to open the new tab as a popup.
In [ ]:
import datetime
import os
from collections import Counter
from urllib.parse import parse_qs, quote_plus

import arrow
import ipywidgets as widgets
import pandas as pd
from IPython.display import HTML, Image, display

from page_data_master import pages_per_vol

SESSIONS = {"M": "Morning", "N": "Noon", "A": "Afternoon", "U": "Unknown"}

CLOUDSTOR_URL = "https://cloudstor.aarnet.edu.au/plus/s/i02k4gxeEpMAUkm"
In [ ]:
def get_pages(vol_num, page_num):
    for key, pages in pages_per_vol.items():
        vols = key.split("_")
        vols = [int(y) for y in vols]
        if len(vols) == 2:
            vols = list(range(vols[0], vols[1] + 1))
        if vol_num in vols:
            for p_key, p_pages in pages.items():
                p_range = p_key.split("_")
                if p_range[1] == "*":
                    if page_num >= int(p_range[0]):
                        return p_pages
                else:
                    if page_num >= int(p_range[0]) and page_num <= int(p_range[1]):
                        return p_pages
In [ ]:
# Get the list of dates
df_dates = pd.read_csv("complete_date_list.csv", parse_dates=["date"])
# Get the list of pages
df_pages = pd.read_csv("complete_page_list.csv", parse_dates=["date"])
# Merge dates and pages on the date field
df = pd.merge(df_dates, df_pages, how="left", on="date").sort_values(
    by=["date", "page_num"]
)
In [ ]:
def highlight_missing(row):
    """
    Highlight missing pages.
    """
    if row["pages expected"] == row["pages found"]:
        return ["", ""]
    else:
        return ["", "background-color: yellow"]


def find_pages():
    results.clear_output()
    date = arrow.get(date_picker.value)
    with results:
        display(HTML(f'<h2>{date.format("D MMMM YYYY")}</h2>'))
        rows = df.loc[df["date"] == pd.Timestamp(date_picker.value)]
        first_page = rows.iloc[0]["page_num"]
        vol_num = rows.iloc[0]["vol_num"]
        num_pages = rows.iloc[0]["pages"]
        if date.weekday() < 6 and pd.notnull(vol_num):

            # Get the expected number of pages
            expected = get_pages(int(vol_num), int(first_page))
            if date.weekday() < 5:
                expected_pages = expected["weekday"]
            elif date.weekday() == 5:
                expected_pages = expected["saturday"]
            expected_num_pages = expected_pages[0]
            display(
                HTML(
                    f"<p><b>Number of pages</b>: {expected_num_pages} expected / {int(num_pages)} found</p>"
                )
            )

            # Display a breakdown of the number of pages per session
            expected_sessions = dict(Counter(expected_pages[1]))
            actual_sessions = rows["session"].value_counts().to_dict()
            sessions = []
            for session, number in expected_sessions.items():
                try:
                    sessions.append(
                        {
                            "session": SESSIONS[session],
                            "pages expected": number,
                            "pages found": actual_sessions[session],
                        }
                    )
                except KeyError:
                    sessions.append(
                        {
                            "session": SESSIONS[session],
                            "pages expected": number,
                            "pages found": 0,
                        }
                    )
            display(
                pd.DataFrame(sessions)
                .set_index(keys="session")
                .style.apply(highlight_missing, axis=1)
            )

        # Show page images
        for row in rows.itertuples():
            if pd.isnull(row.vol_title):
                print(row.reason)
            else:
                image_url = f"{CLOUDSTOR_URL}/download?path={quote_plus(row.vol_title)}&files=N193-{int(row.vol_num):03}_{int(row.page_num):04}.jpg"
                display(
                    HTML(
                        f'<h4>{SESSIONS[row.session]}</h4><p>{row.vol_title}, page {int(row.page_num)} – <a href="{image_url}">Download image</a></p>'
                    )
                )
                display(Image(url=image_url))
In [ ]:
def start(b):
    find_pages()


date_picker = widgets.DatePicker(
    description="Pick a Date", disabled=False, value=datetime.date(1901, 1, 1)
)

# with results:
#    print(os.environ.get('QUERY_STRING', ''))
query_string = os.environ.get("QUERY_STRING", "")
parameters = parse_qs(query_string)
date = parameters.get("date")

find = widgets.Button(
    description="Find pages",
    disabled=False,
    button_style="primary",  # 'success', 'info', 'warning', 'danger' or ''
    tooltip="Click me",
    icon="search",
)

find.on_click(start)
results = widgets.Output()
display(widgets.VBox([widgets.HBox([date_picker, find]), results]))
# display(widgets.HBox([date_picker, find]))
# display(results)


if date:
    date_picker.value = arrow.get(date[0]).date()
    find_pages()

Created by Tim Sherratt for the GLAM Workbench.