Metadata-Version: 2.4
Name: tickerinside
Version: 0.2.0
Summary: Python client for the free TickerInside API: the full holdings of US ETFs, which funds hold a stock, fund overlap and portfolio look-through.
Project-URL: Homepage, https://tickerinside.com
Project-URL: Documentation, https://tickerinside.com/api/
Author-email: TickerInside <contact@tickerinside.com>
License-Expression: MIT
License-File: LICENSE
Keywords: api,etf,etf holdings,etf overlap,finance,look-through,n-port,portfolio,sec
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Office/Business :: Financial :: Investment
Classifier: Typing :: Typed
Requires-Python: >=3.9
Provides-Extra: pandas
Requires-Dist: pandas>=1.3; extra == 'pandas'
Description-Content-Type: text/markdown

# tickerinside

A Python client for the free TickerInside API, which serves the full holdings of US ETFs, the funds that hold each stock, and the overlap and look-through computed from them.

The funds come from two sources: the issuers' own holdings files, read every weekday night, and, for the other US stock ETFs, their latest SEC Form N-PORT filing, which is months older. This README gives no count, because it is published far less often than the data moves: the counts of the day are in the `coverage` object of https://tickerinside.com/api/v1/index.json, and `ti.funds()` lists the funds of both sources.

## Install

```
pip install tickerinside
```

The package uses only the Python standard library and runs on Python 3.9 or later. There is no API key and no account to create. pandas is optional: install it (or `pip install "tickerinside[pandas]"`) and every result also offers a `.df` DataFrame.

## Examples

```python
import tickerinside as ti
```

The holdings of VOO as a DataFrame, heaviest first:

```python
voo = ti.holdings("VOO", names=True)
voo.holdings_as_of        # '2026-08-31', the date of the issuer's file
voo.df.head(3)
#   ticker        name  weight_pct
# 0   NVDA      Nvidia      8.0927
# 1   AAPL  Apple Inc.      7.0432
# 2   MSFT   Microsoft      5.7033
```

Which ETFs hold NVDA, and at what weight:

```python
nvda = ti.holders("NVDA")
nvda.data["counts"]       # how many funds hold it, per source: {'issuer': ..., 'sec_nport': ...}
nvda.df[["fund", "weight_pct", "holdings_as_of"]].head(3)
#    fund  weight_pct holdings_as_of
# 0  GXPT     19.9100     2026-09-24
# 1   VGT     17.7869     2026-08-31
# 2  VUSG     16.9500     2026-09-25
```

Funds covered from their issuers' own files and funds covered from SEC Form N-PORT filings, which are months older, are kept apart in `nvda.data["issuer"]` and `nvda.data["sec_nport"]` (None only for a stock file that carries no list from SEC filings). `.df` lists the issuer rows first and the SEC rows after them, without merging the two by weight.

How much VOO and QQQ overlap:

```python
c = ti.compare("VOO", "QQQ")
c.data["overlap"]["by_weight"]    # 53.9, the smaller weight of each shared company, summed
c.data["overlap"]["share_of_b"]   # 93.7, the part of QQQ held in companies VOO also holds
c.data["correlation_3y"]          # 0.95, from three years of weekly returns
```

What a small portfolio holds underneath, in percent and in money:

```python
lt = ti.look_through({"VOO": 6000, "QQQ": 3000, "SCHD": 1000})
lt.df.head(2)
#   ticker  weight_pct   value  via_VOO  via_QQQ  via_SCHD
# 0   NVDA       7.312  731.24   4.8556   2.4568       0.0
# 1   AAPL       6.449  644.88   4.2259   2.2229       0.0
```

What changed in SPY's holdings from one issuer file to the next, since a date, one row per line that entered, exited or moved by 0.05 points or more:

```python
ch = ti.changes("SPY", since="2026-09-18")
ch.df[["date", "previous", "change", "ticker", "weight_before", "weight_after"]].head(6)
#          date    previous   change ticker  weight_before  weight_after
# 0  2026-09-18  2026-09-17  entered     BE            NaN        0.1187
# 1  2026-09-18  2026-09-17  entered   ILMN            NaN        0.0549
# 2  2026-09-18  2026-09-17  entered      P            NaN        0.0525
# 3  2026-09-18  2026-09-17   exited    TAP         0.0095           NaN
# 4  2026-09-18  2026-09-17   exited   BLDR         0.0094           NaN
# 5  2026-09-18  2026-09-17   exited    TTD         0.0093           NaN
```

`ti.history("SPY")` gives the whole file: each file date with its position count and top 10 weight, each step with its turnover measures, and how the fund's overlap with its ten closest funds moved. A step that is a change of the keys or of the reading of the files rather than a trade is marked restated. The history covers the funds read from their issuers' own files, from the first file the archive holds, and it is published under the TickerInside history terms rather than CC BY 4.0 (see below).

Citing a figure, with the line every result carries:

```python
print(c.cite)
# TickerInside, VOO vs QQQ, holdings files of 2026-08-31 and 2026-09-24, https://tickerinside.com/compare/voo-vs-qqq/, CC BY 4.0
c.page_url                # the page where a reader can check it
```

The figures above are from the files of 25 September 2026 and change as issuers publish new ones.

## What each call returns

The functions are `funds()`, `fund(ticker)`, `holdings(ticker)`, `holders(stock_ticker)`, `security(ticker)`, `compare(a, b)`, `overlap_matrix(tickers)`, `look_through(positions)`, `census()`, `history(ticker)` and `changes(ticker, since=None)`. Each returns a result with these attributes:

- `.data`: the answer as plain dicts and lists.
- `.df`: the same answer as a pandas DataFrame, when pandas is installed.
- `.as_of`: the date of the price data, and `.holdings_as_of`: the date of the holdings file, or a dict of dates by fund when the answer uses several funds.
- `.source`: where the holdings come from, `issuer` for the issuer's own file or `sec_nport` for a fund covered from its latest SEC Form N-PORT filing, which is months older. Like `.holdings_as_of`, it is a dict by fund when the answer uses several funds.
- `.cite`: a citation line naming the source, its date, a link and the licence.
- `.url`: the API file the answer was read from, and `.page_url`: the page on tickerinside.com where it can be checked.

Overlap, correlation and look-through are computed on your machine from the fund files, with the same arithmetic as the TickerInside website and MCP server, so the figures agree with theirs. A ticker that is not covered raises `tickerinside.NotCovered` with the API's own message, and a fund given to `holders()` or a stock given to `fund()` gets a message naming the call that fits it. A network failure raises `tickerinside.APIError` with the URL that failed, and so does a 404 that is not the API's own answer, which usually means a wrong base URL. Each file is kept in memory for an hour, so asking twice costs one request. `ti.Client(base_url=..., timeout=..., cache_ttl=...)` gives a session with other settings, and the `TICKERINSIDE_API` environment variable, when it is set, replaces the default base URL `https://tickerinside.com/api/v1` (the TickerInside MCP server reads the same variable). Requests identify themselves with the User-Agent `tickerinside-python/<version>`, and nothing else is sent anywhere.

## Licence and attribution

The code of this package is released under the MIT licence. The data it reads is published by TickerInside under the Creative Commons Attribution 4.0 licence (CC BY 4.0): you may use it, commercially as well, provided you credit TickerInside by name, in text or with a link to https://tickerinside.com; both are accepted. The `.cite` line on every result does both. The holdings history read by `history()` and `changes()` is the exception: it is published under the TickerInside history terms (https://tickerinside.com/legal/#history), free per request, commercial use included, with attribution, a link to the file and its date, and not for republishing the archive as a whole or extracting it systematically; its `.cite` line gives the link and the dates. The figures are measurements of what funds hold and how they have behaved, not investment advice.

The API reference, with every field and endpoint, is at https://tickerinside.com/api/, and the same reference as one text file for coding agents at https://tickerinside.com/llms-full.txt. The TickerInside MCP server answers at https://tickerinside.com/mcp, and locally with `npx -y tickerinside-mcp@latest`.
