Skip to main content

Analytics and market-data networking layer for the crypto tracker ecosystem

Project description

coinlytics

PyPI version Python versions License CI

Python library for crypto portfolio analytics and market data — sits above the coinbasis cost-basis engine and handles all networking, caching, and analytics an app needs to run.

I built coinlytics as the data and analytics layer for a multi-tier crypto tracker ecosystem. It provides a resilient CoinGecko price client (keyless by default, automatic keyed fallback on HTTP 429, exponential backoff, TTL on-disk cache, and offline last-good serving), tax-aware portfolio rebalancing that simulates sells through coinbasis to estimate HIFO realized gains, daily portfolio value/P&L reconstruction by replaying the transaction ledger, performance metrics via coinbasis.stats, staking yield analytics via DefiLlama, and a news sentiment feed sourced from RSS and CryptoPanic. The package is intentionally minimal — it depends only on requests and coinbasis, with no ML or heavy analytics libraries.

Features

  • Resilient CoinGecko client — tries the public keyless endpoint first; on HTTP 429 automatically retries with a configured Demo or Pro API key (routing the correct base URL and auth header); exponential backoff with Retry-After header support; TTL on-disk JSON cache (atomic writes); offline last-good fallback with PriceBook.stale flag.
  • MockClient — satisfies the same PriceSource protocol as the real client; deterministic, no network; a fail_ids set exercises error-handling paths without mocking requests.
  • Tax-aware rebalancing — Band and Full strategies; drift calculation vs. target weights (equal, market-cap, or custom); HIFO realized-gain estimate for each proposed sell, computed by appending a simulated Sell to a throwaway coinbasis.Portfolio and reading the gain delta.
  • Historical P&L reconstruction — replays the full transaction ledger up to each target date using coinbasis.Portfolio.from_transactions, then values holdings at per-coin historical prices.
  • Performance metrics — daily Snapshot dataclass; delegates volatility, Sharpe ratio, max drawdown, and cumulative return to coinbasis.stats.
  • DefiLlama staking APY — fetches pool yields for a list of symbols; selects the highest-TVL exact-match pool per symbol.
  • News + sentimentfetch_rss and fetch_cryptopanic with a DOCTYPE entity-expansion guard (stdlib only, no defusedxml); naive keyword-lexicon sentiment classification (bullish/bearish/neutral) using whole-word regex matching.
  • Analytics helpers — Pearson correlation, correlation matrix, portfolio volatility, annualized volatility.

Tech Stack

Layer Choice
Language Python >= 3.10
Cost-basis engine coinbasis >= 0.1, < 0.2
HTTP requests >= 2.28, < 3
XML parsing xml.etree.ElementTree (stdlib)
Money math decimal.Decimal throughout
Build setuptools >= 68
Lint / format ruff
Tests pytest

Getting Started

pip install coinlytics

For local development against an unpublished coinbasis:

pip install -e ../coinbasis-py   # local coinbasis first
pip install -e ".[dev]"          # coinlytics + pytest + ruff

Fetch current prices (keyless, no API key needed)

from coinlytics import CoinGeckoClient, CoinGeckoConfig

cfg = CoinGeckoConfig(cache_dir="~/.cache/coinlytics")
client = CoinGeckoClient(cfg)
pb = client.prices(["bitcoin", "ethereum"])

print(pb.quotes["bitcoin"].price)   # decimal.Decimal
print(pb.stale)                      # True if served from offline cache
prices_map = pb.prices_map()         # dict[str, Decimal] for coinbasis.Portfolio.valuation()

With a Demo API key (keyed fallback on 429)

cfg = CoinGeckoConfig(
    api_key="your-demo-key",
    plan="demo",
    cache_dir="~/.cache/coinlytics",
    cache_ttl=120,
)
client = CoinGeckoClient(cfg)

Tax-aware rebalancing

from decimal import Decimal
from coinlytics import compute_trades, target_weights, RebalanceStrategy
import coinbasis

# portfolio is a coinbasis.Portfolio built from your ledger
weights = target_weights("equal", ["bitcoin", "ethereum"])
plan = compute_trades(
    current_values={"bitcoin": Decimal("70000"), "ethereum": Decimal("30000")},
    target_weights_map=weights,
    prices={"bitcoin": Decimal("50000"), "ethereum": Decimal("3000")},
    strategy=RebalanceStrategy.BAND,
    band=Decimal("0.05"),
    portfolio=portfolio,   # optional: attaches TaxEstimate to sells
)
for action in plan.actions:
    print(action.asset, action.side, action.amount_usd)
    if action.tax:
        print("  estimated HIFO gain:", action.tax.realized_gain)

Historical portfolio value/P&L

from coinlytics import reconstruct_series

series = reconstruct_series(
    txs=portfolio.transactions,
    price_by_coin_date={"bitcoin": {"2024-01-01": 42000.0, "2024-01-02": 43500.0}},
    dates=["2024-01-01", "2024-01-02"],
)
for day in series:
    print(day["date"], day["value"], day["pl"])

News sentiment

from coinlytics import fetch_rss, filter_items, sentiment_summary, keywords_for

items = fetch_rss("https://cointelegraph.com/rss")
btc_items = filter_items(items, keywords_for("bitcoin", {}))
summary = sentiment_summary(btc_items)
print(summary["overall"])   # 'bullish' | 'bearish' | 'neutral'

Examples

Runnable scripts live in examples/ — one self-contained script per file. Run any of them with python examples/<name>.py.

The offline examples need no network and no API key:

Example What it shows
mock_client.py MockClient as a drop-in PriceSource — prices, history, market caps, sparklines, and the fail_ids error path. Fully offline.
rebalance.py Tax-aware rebalancing: builds a coinbasis ledger, computes trades toward equal weights, and attaches a HIFO TaxEstimate to each sell.
performance.py Daily Snapshot history, dedup_append, and metrics (volatility, Sharpe, max drawdown, cumulative return) via coinbasis.stats.
history.py Daily value/P&L reconstruction by replaying a ledger with reconstruct_series, plus point-in-time holdings_as_of.
staking.py Effective APYs (API match vs. manual fallback), projected yield, rewards summary, and combined P&L.
news.py Keyword filtering (whole-word) and lexicon sentiment (classify_sentiment, sentiment_summary) over news-item dicts.

The two live-price examples hit the network (and are clearly marked); they guard their network calls so they print a friendly message rather than crash when offline:

Example What it shows
prices_keyless.py Real CoinGeckoClient against the public keyless endpoint. Needs internet.
prices_with_key.py Real CoinGeckoClient with a Demo API key (keyed fallback on HTTP 429). Needs internet and COINGECKO_API_KEY.

The offline examples are exercised by tests/test_examples.py; the network ones are skipped there.

Development

# Run tests
pytest

# Lint
ruff check src/ tests/

# Build a distribution
python -m build

Project Structure

coinlytics-py/
├── src/
│   └── coinlytics/
│       ├── __init__.py          # public re-exports
│       ├── errors.py            # typed exception hierarchy
│       ├── analytics.py         # correlation, portfolio volatility, annualize
│       ├── defillama.py         # DefiLlama APY fetcher
│       ├── history.py           # ledger-replay P&L reconstruction
│       ├── news.py              # keyword filter + lexicon sentiment
│       ├── perf.py              # Snapshot, PerfMetrics, metrics()
│       ├── rebalance.py         # Band/Full strategies + tax estimate
│       ├── rss.py               # RSS + CryptoPanic fetchers
│       ├── staking.py           # effective APY, projected yield, rewards summary
│       └── prices/
│           ├── __init__.py
│           ├── client.py        # CoinGeckoClient (keyless→keyed→cache→offline)
│           ├── cache.py         # DiskCache (TTL, atomic writes)
│           ├── mock.py          # MockClient (PriceSource protocol, no network)
│           └── models.py        # Quote, PriceBook, HistoryPoint, PriceSource
├── tests/
│   ├── conftest.py
│   ├── test_client.py
│   ├── test_cache.py
│   ├── test_mock_client.py
│   ├── test_rebalance.py
│   ├── test_history.py
│   ├── test_perf.py
│   ├── test_staking.py
│   ├── test_defillama.py
│   ├── test_rss.py
│   ├── test_news.py
│   └── test_analytics.py
├── pyproject.toml
└── README.md

License

MIT OR Apache-2.0

Author

Jacob Kanfer — github.com/Technical-1

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

coinlytics-0.1.0.tar.gz (56.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

coinlytics-0.1.0-py3-none-any.whl (33.4 kB view details)

Uploaded Python 3

File details

Details for the file coinlytics-0.1.0.tar.gz.

File metadata

  • Download URL: coinlytics-0.1.0.tar.gz
  • Upload date:
  • Size: 56.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for coinlytics-0.1.0.tar.gz
Algorithm Hash digest
SHA256 46751a6f85e591758a91453f90a5547e3dfd9fbce047083f370cf40d38b1853f
MD5 3a2a0239d78ca64c69a062a1e00b3a8c
BLAKE2b-256 53161e80d0fbe307c2e3ae002cc4fb93ad62d0351dea3df09eacfd11ed9db1bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for coinlytics-0.1.0.tar.gz:

Publisher: publish.yml on Technical-1/coinlytics-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file coinlytics-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: coinlytics-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 33.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for coinlytics-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2880aeedbc6357b0e5dfbe87e2560fa78850e7d89b807116b82c14b8ec531dc2
MD5 616bf3fa2604d7c2f8ca99b45cd37cc6
BLAKE2b-256 4441a247733ca9bbaf7df6e121182c120c3e50025d448ed3beff5babe1f244aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for coinlytics-0.1.0-py3-none-any.whl:

Publisher: publish.yml on Technical-1/coinlytics-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page