discounts.ipynb

List books currently at minimum observed price.

from datetime import datetime

import holoviews as hv
import polars as pl

import bookhoarder as bh
%opts magic unavailable (pyparsing cannot be imported)
%compositor magic unavailable (pyparsing cannot be imported)

We evaluate today’s date with:

date = datetime.today().date()

Next, we load the tables books and prices, collecting the list of books and of recorded prices, respectively.

books = bh.read_database(
    table_name="books",
    url="sqlite:///database.db",
    schema=bh.schema(),
)
prices = bh.read_database(
    table_name="prices",
    url="sqlite:///database.db",
    # schema=bh.schema_prices(),
)
books
shape: (2, 21)
isbnauthortitleyearpublisherlanguageformatfull_pricemin_priceadelphibuecherfeltrinellihoeplihugendubelibslibcooplibracciolibunimondadoriosianderrizzoli
strstrstrstrstrstrstrf64f64strstrstrstrstrstrstrstrstrstrstrstr
"9783866473256""Karl Marx""Das Kapital""2009""Anaconda"nullnull7.954.99"""https://www.buecher.de/artikel…nullnullnullnullnullnullnullnull"https://www.osiander.de/shop/h…null
"9781857988826""Ursula K. Le Guin""The Dispossessed""1999""Orion Publishing Co"nullnull13.09.49null"https://www.buecher.de/artikel…"https://www.lafeltrinelli.it/d…nullnull"https://www.ibs.it/dispossesse…nullnullnullnull"https://www.osiander.de/shop/h…null
prices
shape: (60, 4)
isbnsitepricedate
strstrf64str
"9783866473256""buecher"7.95"2024-10-10"
"9783866473256""osiander"4.99"2024-10-10"
"9781857988826""buecher"13.0"2024-10-10"
"9781857988826""feltrinelli"12.49"2024-10-10"
"9781857988826""ibs"11.87"2024-10-10"
"9783866473256""osiander"7.95"2024-10-19"
"9781857988826""buecher"9.49"2024-10-19"
"9781857988826""feltrinelli"12.49"2024-10-19"
"9781857988826""ibs"11.87"2024-10-19"
"9781857988826""osiander"9.69"2024-10-19"

Let us take for example the book Das Kapital with ISBN 9783866473256, with only recorded prices from osiander.de:

prices.filter(pl.col("isbn") == "9783866473256").filter(pl.col("site") == "osiander")
shape: (10, 4)
isbnsitepricedate
strstrf64str
"9783866473256""osiander"4.99"2024-10-10"
"9783866473256""osiander"4.99"2024-10-11"
"9783866473256""osiander"4.99"2024-10-12"
"9783866473256""osiander"4.99"2024-10-13"
"9783866473256""osiander"4.99"2024-10-14"
"9783866473256""osiander"4.99"2024-10-15"
"9783866473256""osiander"4.99"2024-10-16"
"9783866473256""osiander"7.95"2024-10-17"
"9783866473256""osiander"7.95"2024-10-18"
"9783866473256""osiander"7.95"2024-10-19"

We can plot this using the function plot_history to see the plot of recent price recording in a database. We can specify the attribute site if want to see the records for one specific website, and the black dashed line will specify the min_price.

isbn_1 = "9783866473256"
book_1 = books.filter(pl.col("isbn") == isbn_1)
plot_1 = bh.plot_history(
    prices.filter(pl.col("isbn") == isbn_1),
    book=book_1,
    hlines=["min"],
    width=1200,
    height=400,
)
plot_1

Oh no! We missed a big discount on Osiander! Now it seems to be back at full price.

How about the other book?

isbn_2 = "9781857988826"
book_2 = books.filter(pl.col("isbn") == isbn_2)
plot_2 = bh.plot_history(
    prices.filter(pl.col("isbn") == isbn_2),
    book=book_2,
    hlines=["min"],
    width=1200,
    height=400,
)
plot_2

We have discounts on both osiander and buecher. Cool!

As a sidenote, we can stack all plots in a column in the following way:

hv.Layout([plot_1, plot_2]).cols(1)