About
Markets move together for a while and then stop: gold with real yields, the yen with US rates, an index with its sector. This indicator measures that link while a backtest runs. It pairs the instrument's daily close with a date keyed feed, the same kind ctx.data reads (written by a data source plugin such as the FRED rates curve, or by you), and gives the correlation of their daily changes over a rolling window, the instrument's beta to the feed, and its relative strength over the window.
It is careful about time. Days are UTC days, as feeds are keyed, and only finished days count. A feed stores each value under the first day it was known, usually a day or two after the day it describes. By default (align "observed") the indicator reads the feed's own delay rule from its _meta block and pairs each day of the instrument with the feed's value for that same day, but only from the bar where that value was known; so a pair can arrive a day or two late, and it never arrives early. With align "known" each day is paired with the value known that day instead.
When the feed does not exist, or with align observed its delay rule is not one the kit knows, ctx.plugin_indicator returns None.
Parameters
| Name | Type | Default | Range or options | Description |
|---|---|---|---|---|
feed | text | "" | Required: the feed's name, as ctx.data reads it. | |
field | text | "" | For a feed that holds objects: the key of the number to use. Empty for a feed of numbers. | |
changes | choice | "returns" | returns, differences | How the feed's daily change is measured: returns for prices, differences for yields, rates and indices like the VIX. |
window | int | 60 | min 3, max 1000 | Day pairs in the rolling window. |
align | choice | "observed" | observed, known | observed pairs each day with the feed's value for that day, from the bar it was known; known pairs it with the value known on that day. |
Use it in a strategy
pythonpc = ctx.plugin_indicator("pair_correlation_beta", "correlation",
{"feed": "us_dgs10", "changes": "differences", "window": 60})
bars = ctx.bars(1)
# Reading the feed with ctx.data also makes the run fetch it before it starts.
if bars and ctx.data("us_dgs10", bars[-1].ts) is not None:
if pc is not None and pc.value is not None and abs(pc.value) > 0.6:
ctx.signal("EXIT")The feed must exist before the run: install and switch on the plugin that writes it, and read it once with ctx.data in the strategy (or tick "Fetch external data (news and plugin feeds)") so it is fetched first.
What it provides
value, correlationValue | Pearson correlation of the instrument's daily returns and the feed's daily changes over the window, -1 to 1; None until the window is full. |
betaValue | cov(instrument, feed) / var(feed) over the window: the instrument's return per unit of feed change. |
relative_strengthValue | (instrument now / at the window start) / (feed now / at the window start) - 1; only with changes returns, else None. |
overlap_daysValue | How many day pairs the window holds so far, up to window. |
Limits
- Daily changes only, on UTC days: an intraday strategy sees the figures of finished days. A weekly feed (like COT data) gives one change a week, not a daily series.
- Feeds carry their last value over days without a release. On such a day the feed's change is zero, and holidays the writing plugin skipped for a business day rule are not known here, so around them a pair can take the neighbouring value.
- Correlation is not causation and changes over time; a correlation from 60 days is a rough estimate.
- A plugin indicator is not drawn on the chart and is not available in Blocks, Pine, Rust or C#; it runs on the run's own instrument only.