> ## Documentation Index
> Fetch the complete documentation index at: https://takeprofit.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# External data overview

> Use your own data in Indie indicators. Overview of external CSV data sources, the three ways to consume them, and how external data is fetched.

Indicators normally work with market data that the platform provides. External data sources let an indicator also
use data you bring yourself: your own candle series, trading signals, ML model outputs, risk factors or any other
time-stamped values.

You publish the data yourself — as a CSV file at a public HTTPS URL, or as a live feed server — and declare it in
the indicator code with a source descriptor:

```py theme={null}
from indie.data import sources

sources.Csv('https://example.com/data.csv')            # a file: frozen history
sources.DataFeed('wss://feeds.example.com/signal')     # a live feed: records as they happen
```

TakeProfit servers fetch and validate the data and deliver its rows to your indicator. The Indie code itself never
performs any network or file I/O — it only declares the dependency and reads ready-made values, the same way it reads
market data.

A CSV is a snapshot: fetched once, frozen, right for backtests and reproducible runs. A feed is live: records keep
arriving while the indicator runs, and the recent past is filled in on a best-effort basis. See
[Live data from a feed](https://takeprofit.com/docs/indie/External-data/Live-data-from-a-feed.md).

## Three ways to use external data

What you write depends on what is in the file:

* If the file contains OHLCV candles, write a `@sec_context` callback and attach it with
  `Context.calc_on(source=...)`, the same way you attach an additional instrument. See
  [External candles from CSV](https://takeprofit.com/docs/indie/External-data/External-candles-from-CSV.md).
* If the rows have their own shape and each row needs processing, describe the row with a `@dataclass` and write a
  `@data_context` callback for `Context.calc_on(source=...)`. See
  [Typed external data](https://takeprofit.com/docs/indie/External-data/Typed-external-data.md).
* If you only need the latest row value on each chart bar, skip the callback and read the rows directly with
  `request_series[T](source=...)`.

A live feed uses the same typed model: declare it with `sources.DataFeed` and process the records with
`@data_context` or `request_series`. Feeds have no candle mode and no time frame. See
[Live data from a feed](https://takeprofit.com/docs/indie/External-data/Live-data-from-a-feed.md).

## Quick example

This indicator plots the daily close prices from an external candle CSV on any chart:

```py External candle close theme={null}
# indie:lang_version = 5
from indie import indicator, sec_context, MainContext, TimeFrame
from indie.data import sources

@sec_context
def ExternalCandles(self):
    return self.close[0]

@indicator('External candle close')
class Main(MainContext):
    def __init__(self):
        self._ext_close = self.calc_on(
            ExternalCandles,
            time_frame=TimeFrame.from_str('1D'),
            source=sources.Csv('https://example.com/candles.csv'))

    def calc(self):
        return self._ext_close[0]
```

## A CSV file is a snapshot

The file is fetched once, when the indicator instance is created. After that the data is frozen: the indicator works
with the file's history and receives no live updates, even if the file changes on your server. To pick up a new
version, re-add the indicator to the chart. A cached copy may be served for up to about 10 minutes after the previous fetch.

> [!NOTE]
>
> The platform does not archive your file. If it changes, the next run of the indicator or backtest can see different
> data. Keep a stable copy of the file if you need reproducible backtests.

## Rules common to all external sources

* External sources count toward the same limit as additional instruments requested with `Context.calc_on()`.
  Identical requests are counted once. For a CSV, a request that differs in URL, `time_column`, time frame or
  `lookahead` counts as a separate instrument; for a feed, one that differs in URL or `stale_after` does.
* The time frame belongs to the call site, not to the file: you pass `time_frame=` to `Context.calc_on()` or
  `request_series()`. For candle CSVs it is required, for typed data it is optional, and tick time frames are not
  supported. Feeds take no time frame at all.
* The source must be publicly reachable over a secure scheme with a valid certificate; authentication headers
  cannot be sent. See [CSV format and limits](https://takeprofit.com/docs/indie/External-data/CSV-format-and-limits.md) for file requirements
  and the error reference, and [Feed protocol and limits](https://takeprofit.com/docs/indie/External-data/Feed-protocol-and-limits.md) for feed
  server requirements.

> [!NOTE]
>
> Indicators that use external data sources cannot be published to the TakeProfit marketplace.

> [!NOTE]
>
> The platform's own [TPO profiles](https://takeprofit.com/docs/indie/Profile-data/TPO-profiles.md) are read through a source descriptor too, but they are internal
> data: none of the rules on this page apply to `sources.Tpo`, and an indicator that uses only TPO can be published like
> any other.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.