Price

Most recent price, useful as a cross-asset reference

Price is the simplest feature: it returns the latest known price for a market. Its main use is cross-asset reference: read the VIX, or a benchmark ETF price, or a prediction-market implied probability, from inside an equity strategy.

Import

python
from horizon.features import Price

Signature

python
Price(market: str | None = None)
marketstr | None
If set, the feature is **pinned** to this market id regardless of the strategy's current market. Useful for cross-asset references. If None, the feature is computed for whichever market the strategy is iterating.

Behavior

python
def compute(self, market_id, history, feeds):
    last = history.last_price()
    if last is not None:
        return last
    feed = feeds.get(market_id)
    return feed.price if feed is not None else float("nan")

Returns:

  1. The last price in the market’s history (if any)
  2. Fall back to the current feed’s price
  3. Fall back to NaN if neither is available

Use cases

Cross-asset reference

Read the VIX from inside an equity strategy:

python
from horizon import Strategy, Signal
from horizon.asset_classes import Equity
from horizon.features import Price, Zscore

class VolAwareStrategy(Strategy):
    asset_classes = [Equity]
    features = {
        "vix": Price(market="CBOE:VIX"),    # always VIX, regardless of current market
        "z": Zscore(window=20),
    }

    def evaluate(self, f, universe):
        # f.vix[m.id] is the SAME value for every m. it's VIX
        vix_value = f.vix[universe[0].id] if universe else 0.0
        if vix_value > 30:
            return []    # skip trading in high-vol regime

        return [
            Signal.from_score(m, score=-f.z[m.id], edge_per_stdev=15)
            for m in universe
            if abs(f.z[m.id]) > 2
        ]

Reading a prediction market from an equity strategy

python
class RecessionHedge(Strategy):
    asset_classes = [Equity]
    features = {
        "recession_prob": Price(market="polymarket:recession-2025"),
        "beta": Beta(benchmark="SPY", window=60),
    }

    def evaluate(self, f, universe):
        prob = f.recession_prob[universe[0].id] if universe else 0.0
        if prob > 0.6:
            # Hedge. short high-beta names
            return [
                Signal.decrease(m, edge_bps=30)
                for m in universe
                if f.beta[m.id] > 1.2
            ]
        return []

Using as current market’s price

Without the market argument, Price() just returns the latest price of whichever market you’re iterating:

python
features = {"p": Price()}

def evaluate(self, f, universe):
    for m in universe:
        print(f"{m.id}: {f.p[m.id]}")

Returns NaN when

  • The market has no history and no current feed (shouldn’t happen in a well-formed backtest)
  • Bad data was rejected earlier and this is the first good tick

Pitfalls

Tests

python
# tests/test_features.py::TestPriceFeature
def test_returns_latest_price(self, store_with_history: FeatureStore) -> None:
    p = Price()
    ns = store_with_history.compute({"price": p}, ["TEST"], {})
    assert ns.price["TEST"] == 100.0

Next