Metadata-Version: 2.4
Name: tzla
Version: 0.2.0
Summary: Terminal crypto portfolio + daily-compounding growth tracker (DexScreener/Solana prices)
Author: Daniel Radosa
License-Expression: MIT
Project-URL: Homepage, https://github.com/danielradosa/tzla
Project-URL: Repository, https://github.com/danielradosa/tzla
Keywords: crypto,portfolio,solana,jupiter,cli,terminal,compounding
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31
Requires-Dist: rich>=13
Requires-Dist: plotext>=5.2
Provides-Extra: test
Requires-Dist: pytest>=7; extra == "test"
Requires-Dist: build>=1; extra == "test"
Requires-Dist: twine>=5; extra == "test"
Dynamic: license-file

# tzla

Terminal crypto portfolio + **daily-compounding growth tracker**. Live prices from
[DexScreener](https://dexscreener.com) and candle charts from the
[Jupiter](https://jup.ag) (Solana) public API — no API key. Set a fixed growth
plan once and each day see whether you're **ahead or behind** the curve.

Running `tzla --grow` tracks today's live portfolio total against a **fixed** growth plan:

| Day | Date | Plan balance | TZLA amount | Multiple |
|----:|:-----|-------------:|------------:|---------:|
| **0** (today) | 2026-01-01 | $1,000.00 | 1,000 | 1.00x |
| 1 | 2026-01-02 | $1,003.69 | 1,004 | 1.00x |
| … | … | … | … | … |
| 7 | 2026-01-08 | $1,026.12 | 1,026 | 1.03x |
| 30 | 2026-01-31 | $1,116.83 | 1,117 | 1.12x |
| 365 | 2027-01-01 | $3,835.77 | 3,836 | 3.84x |

> Day 0 of 365 · plan today **$1,000.00** · actual **$1,000.00** · on plan (+0.0% vs plan)

*In the terminal it renders as a colored, full-width table — near-term days first
(today, tomorrow, +7, +30), then a monthly cadence out to the target.*

## Install

`tzla` is a normal Python CLI. The cross-platform way to install it is
[pipx](https://pipx.pypa.io) (Linux, macOS, **and** Windows/PowerShell — it puts
`tzla` on your PATH in an isolated venv).

```bash
# from a local clone
pipx install ./tools/tzla

# straight from git (once pushed)
pipx install "git+https://github.com/danielradosa/tzla"

# after it's published to PyPI
pipx install tzla
```

No pipx? `pip install --user ./tools/tzla` works too. For development:
`pip install -e ./tools/tzla` (editable).

### Windows / Homebrew / Scoop

- **PowerShell**: install pipx (`py -m pip install --user pipx; py -m pipx ensurepath`)
  then `pipx install tzla`. The `tzla` command works in any shell afterwards.
- **Homebrew** and **Scoop** are possible once a release artifact exists (PyPI sdist
  or a GitHub release tarball, needed to pin a checksum). Starter templates live in
  [`packaging/`](packaging/) — fill in the URL + `sha256` after the first publish.

## Usage

```bash
tzla                 # portfolio table + price chart(s)
tzla --no-chart      # table only
tzla -d 90           # 90-day chart history
tzla --coin <mint>   # chart only one token
tzla --grow          # growth-plan tracker (ahead/behind vs the fixed plan)
tzla --grow --history  # overlay your recorded daily actuals on the plan curve
tzla --grow --watch 30 # live refresh every 30s, with a behind-plan alert
tzla --verify        # cross-check each price against a live Jupiter quote
tzla --wallet <addr> # read holdings live from a Solana wallet (read-only)
tzla --no-pnl        # hide the Cost/PnL columns
tzla --where         # show where config files live
tzla --version
```

### The growth plan

`--grow` projects a **fixed** baseline (start date, start value, daily rate,
horizon) and compares today's live total against it:

```bash
tzla --grow                                   # first run auto-anchors to today's total
tzla --grow --reset-plan                      # re-anchor to today
tzla --grow --reset-plan --principal 1000 --rate 0.369 --grow-days 365
```

The plan never re-anchors on its own, so editing your holdings daily can't move
the goal line — the ahead/behind number stays honest.

## Config

Two JSON files in your per-user config dir (`tzla --where` to see exact paths):

| File | Default location | What it is |
|------|------------------|------------|
| `portfolio.json` | `~/.config/tzla/portfolio.json` | Your holdings — edit this daily |
| `plan.json` | `~/.config/tzla/plan.json` | The fixed growth anchor — set once (auto-created on first `--grow`) |

They're deliberately separate so a daily holdings edit can't clobber the plan.
On first run a starter `portfolio.json` is written from the bundled example.

Override locations with `--config` / `--plan`, or point the whole config dir
elsewhere with `$TZLA_HOME` (e.g. `TZLA_HOME=./mydata tzla`). Standard
`$XDG_CONFIG_HOME` is honored.

**portfolio.json** — holdings keyed by Solana token mint address:

```json
{
  "currency": "usd",
  "holdings": {
    "4tWMJCW6tdpVUkwDpX1NEQURbtuQDg7H9DfkjEpGnq5D": { "symbol": "TZLA", "amount": 0 }
  }
}
```

The bundled starter ships with `amount: 0` — set it to your real holding. Existing
configs are never overwritten, so your numbers stay put across upgrades.
Add more entries to track several tokens. The `TZLA amount` column in `--grow`
only appears for single-asset portfolios (where "amount" is unambiguous).

### Optional fields

All of these are additive — omit them and behavior is unchanged.

| Field | Where | Effect |
|-------|-------|--------|
| `"currency"` | top level | `"eur"`, `"gbp"`, … convert all amounts via live ECB rates ([Frankfurter](https://frankfurter.dev)); `"usd"` skips the FX call |
| `"wallet"` | top level | a base58 Solana address → amounts are read **live from chain** (`getTokenAccountsByOwner` + SOL); wallet-only tokens are surfaced automatically. **Read-only — never a private key.** |
| `"rpc"` | top level | override the public Solana RPC (e.g. a Helius/QuickNode URL) |
| `"invested"` / `"cost_basis"` | per holding | USD cost basis (total) → adds **Cost / PnL / PnL%** columns + an Unrealized PnL line |
| `"buy_price"` | per holding | USD cost basis **per unit** (cost = `buy_price × amount`) |

```json
{
  "currency": "eur",
  "wallet": "YourBase58WalletAddress…",
  "holdings": {
    "4tWMJCW6tdpVUkwDpX1NEQURbtuQDg7H9DfkjEpGnq5D": {
      "symbol": "TZLA", "amount": 2232, "buy_price": 0.20
    }
  }
}
```

Per-run overrides: `--wallet <addr>`, `--rpc <url>`, `--no-wallet`, `--no-pnl`.
`--grow` logs a daily snapshot to `~/.config/tzla/history.jsonl`; `--grow --history`
charts those recorded actuals against the plan (needs ≥2 logged days).

See [`src/tzla/data/`](src/tzla/data/) for the example files.

## Notes

- A daily rate like `0.369%` compounds to ~**+284%/year** — that's an idealized
  assumption, not a forecast. The tracker just tells you how far reality drifts
  from it.
- `--verify` and `--wallet` add network round-trips (a Jupiter quote per holding,
  and a Solana RPC call); a flaky endpoint degrades gracefully rather than aborting.

MIT licensed.
