Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
date,revenue_proxy,expenses_proxy
2026-01-03,250.0,0.0
2026-01-05,300.0,20.0
2026-01-07,180.0,0.0
2026-01-09,100.0,0.0
2026-01-02,0.0,120.0
2026-01-04,0.0,800.0
2026-01-06,0.0,50.0
date,revenue_proxy,expenses_proxy,net_proxy
2026-01-02,0.00,120.00,-120.00
2026-01-03,250.00,0.00,250.00
2026-01-04,0.00,800.00,-800.00
2026-01-05,300.00,20.00,280.00
2026-01-06,0.00,50.00,-50.00
2026-01-07,180.00,0.00,180.00
2026-01-09,100.00,0.00,100.00
28 changes: 28 additions & 0 deletions docs/source/workbook/track_d_byod.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,34 @@ Validate the normalized tables:

pystatsv1 trackd validate --datadir byod/my_project/normalized --profile core_gl

PyPI-only setup (no Git required)
----------------------------------------------

If you just want to *use* Track D tools (you don’t need to clone the repo):

1. Create a virtual environment.
2. Install PyStatsV1 from PyPI.
3. Use the CLI + the workbook downloads in this section.

.. code-block:: console

python -m venv .venv

# Windows (Git Bash)
source .venv/Scripts/activate

# macOS/Linux
# source .venv/bin/activate

python -m pip install -U pip
pip install "pystatsv1[workbook]"

(Optional) sanity check:

.. code-block:: console

pystatsv1 doctor

Next: choose a tutorial
-----------------------

Expand Down
8 changes: 7 additions & 1 deletion docs/source/workbook/track_d_byod_gnucash.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Export a CSV that includes your accounts and the date range that covers your dem
Step 4 — Initialize a Track D BYOD project
------------------------------------------

From your PyStatsV1 repo root (or any folder you like):
From any folder you like (your BYOD projects can live anywhere):

.. code-block:: console

Expand Down Expand Up @@ -123,6 +123,12 @@ The adapter reads this file and writes the canonical tables to ``normalized/``.

If you want to test without GnuCash, copy the demo export instead:

If you installed PyStatsV1 from PyPI (no repo clone), download **"Demo export (complex/multi-line)"** above
and copy that file to ``byod/gnucash_demo/tables/gl_journal.csv``.

If you have the repo source code, you can copy the demo export from this docs folder:


.. code-block:: console

# (Windows PowerShell)
Expand Down
77 changes: 29 additions & 48 deletions docs/source/workbook/track_d_byod_gnucash_demo_analysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ What we’ll build
A small daily table:

- ``date``
- ``revenue_proxy`` (credits to Income accounts)
- ``expenses_proxy`` (debits to Expense accounts)
- ``revenue_proxy`` (net credits to Revenue accounts)
- ``expenses_proxy`` (net debits to Expense accounts)
- ``net_proxy`` (revenue_proxy − expenses_proxy)

Download (prebuilt)
-------------------
Expand All @@ -31,62 +32,42 @@ Assume your BYOD project is at ``byod/gnucash_demo`` and you have:
- ``byod/gnucash_demo/normalized/gl_journal.csv``
- ``byod/gnucash_demo/normalized/chart_of_accounts.csv``

Create a tiny script (for example ``scripts/gnucash_daily_totals.py``) with:
Run the built-in helper:

.. code-block:: python

from pathlib import Path
import pandas as pd

root = Path("byod/gnucash_demo")

gl = pd.read_csv(root / "normalized" / "gl_journal.csv")
coa = pd.read_csv(root / "normalized" / "chart_of_accounts.csv")

gl["date"] = pd.to_datetime(gl["date"], errors="coerce")

gl["debit"] = pd.to_numeric(gl["debit"], errors="coerce").fillna(0.0)
gl["credit"] = pd.to_numeric(gl["credit"], errors="coerce").fillna(0.0)
.. code-block:: console

gl = gl.merge(coa[["account_id", "account_type"]], on="account_id", how="left")
pystatsv1 trackd byod daily-totals --project byod/gnucash_demo

revenue = (
gl.query("account_type == 'Income'")
.groupby(gl["date"].dt.date)["credit"]
.sum()
.rename("revenue_proxy")
)
This writes:

expenses = (
gl.query("account_type == 'Expenses'")
.groupby(gl["date"].dt.date)["debit"]
.sum()
.rename("expenses_proxy")
)
- ``byod/gnucash_demo/normalized/daily_totals.csv``

daily = (
pd.concat([revenue, expenses], axis=1)
.fillna(0.0)
.reset_index()
.rename(columns={"index": "date"})
)
Option B — Quick first analysis (no repo clone required)
--------------------------------------------------------

out = root / "normalized" / "daily_totals.csv"
daily.to_csv(out, index=False)
print("Wrote:", out)
print(daily)
Once you have ``normalized/daily_totals.csv``, you can do a quick first pass with pandas.
This snippet prints a few summary stats and writes a simple plot:

Option B — Run the existing “My Own Data” explore scaffold
----------------------------------------------------------
.. code-block:: console

PyStatsV1 includes a beginner-friendly scaffold script:
python - <<'PY'
import pandas as pd
import matplotlib.pyplot as plt
from pathlib import Path

``scripts/my_data_01_explore.py``
csv_path = Path("byod/gnucash_demo/normalized/daily_totals.csv")
outdir = Path("outputs/gnucash_demo")
outdir.mkdir(parents=True, exist_ok=True)

Run it against the daily totals CSV (either the prebuilt download, or the file you generated above):
df = pd.read_csv(csv_path, parse_dates=["date"])
df = df.sort_values("date")

.. code-block:: console
print(df.describe(include="all"))

python scripts/my_data_01_explore.py --csv byod/gnucash_demo/normalized/daily_totals.csv --outdir outputs/gnucash_demo
ax = df.plot(x="date", y=["revenue_proxy", "expenses_proxy", "net_proxy"])
ax.figure.tight_layout()
ax.figure.savefig(outdir / "daily_totals.png")
print(f"Wrote: {outdir / 'daily_totals.png'}")
PY

This will write a few simple outputs under ``outputs/gnucash_demo/`` (tables + quick plots).
(If you *are* working from the repo source, you can also adapt ``scripts/my_data_01_explore.py`` to your needs.)
4 changes: 4 additions & 0 deletions examples/trackd_byod_gnucash_demo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ This is a small runnable example project for the Track D BYOD pipeline using the
## Run

```bash
# 1) Normalize the raw export into canonical Track D tables
pystatsv1 trackd byod normalize --project .

# 2) Produce an analysis-ready daily time series
pystatsv1 trackd byod daily-totals --project .
```

Outputs are written under `normalized/`.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pystatsv1"
version = "0.22.3"
version = "0.22.4"
description = "PyStatsV1: applied statistics labs in Python."
readme = "README.md"
requires-python = ">=3.10"
Expand Down
39 changes: 39 additions & 0 deletions src/pystatsv1/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,30 @@ def cmd_trackd_byod_normalize(args: argparse.Namespace) -> int:
return 0


def cmd_trackd_byod_daily_totals(args: argparse.Namespace) -> int:
from pystatsv1.trackd import TrackDDataError
from pystatsv1.trackd.byod import build_daily_totals

try:
report = build_daily_totals(args.project, out=args.out)
except TrackDDataError as e:
print(str(e))
return 1

print(
textwrap.dedent(
f"""\
Track D BYOD daily totals written.

Project: {report.get('project')}
Output: {report.get('out')}
Days: {report.get('days')}
"""
).rstrip()
)
return 0


def build_parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(
prog="pystatsv1",
Expand Down Expand Up @@ -609,6 +633,21 @@ def build_parser() -> argparse.ArgumentParser:
)
p_byod_norm.set_defaults(func=cmd_trackd_byod_normalize)

p_byod_daily = byod_sub.add_parser(
"daily-totals",
help="Compute daily revenue/expense proxies from normalized tables.",
)
p_byod_daily.add_argument(
"--project",
required=True,
help="Path to a BYOD project folder created by 'pystatsv1 trackd byod init'.",
)
p_byod_daily.add_argument(
"--out",
default=None,
help="Optional output CSV path (default: <project>/normalized/daily_totals.csv).",
)
p_byod_daily.set_defaults(func=cmd_trackd_byod_daily_totals)

return p

Expand Down
Loading