Portfolio Transformer#

Format detection and table transposition utilities, plus the PyArrow-to-pandas bridge shared by the market and portfolio pipelines.

Portfolio data transformation utilities.

This module provides functions for transforming portfolio data between different representations and formats.

Functions are organized by transformation type: - Format Detection: detect_portfolio_format - Table Operations: transpose_vertical_to_horizontal - Date Validation: validate_portfolio_date_range - Entity Conversion: entity_to_weights_dict

detect_portfolio_format(first_column_name: str, error_class: type[Exception]) → str[source]#

Detect portfolio layout (horizontal vs vertical) based on the first column name.

Horizontal format starts with “Ticker”/”ticker”; vertical format starts with “Date”/”date”.

Parameters:
  • first_column_name (str) – Name of the first column in the portfolio file.

  • error_class (Type[Exception]) – Exception class to raise if format is invalid.

Returns:

“horizontal” or “vertical”.

Return type:

str

Raises:

error_class – If the first column is neither expected ticker nor date names.

entity_to_weights_dict(entity: PortfolioEntity) → dict[Timestamp, dict[str, Scalar]][source]#

Convert a PortfolioEntity into a time-indexed weights dictionary.

The result maps normalized timestamps (rebalancing dates) to “ticker -> weight” maps. Dates are parsed using supported formats and normalized to midnight.

Parameters:

entity (PortfolioEntity) – A validated portfolio entity containing asset weights organized by date columns.

Returns:

Mapping from rebalancing date to ticker weights.

Return type:

dict[pd.Timestamp, dict[str, pa.Scalar]]

Raises:

PortfolioEntityError – If date columns cannot be parsed using supported formats.

Notes

  • Only date columns with valid weights are kept.

  • Empty weight sets for specific dates are excluded.

transpose_vertical_to_horizontal(table: Table) → Table[source]#

Transpose a vertical-format PyArrow table (dates as rows, tickers as columns) into a horizontal-format table (tickers as rows, dates as columns).

This transformation is commonly required when the portfolio is initially specified as:

  • One row per date.

  • One column per ticker.

But the internal engine requires:
  • One row per ticker.

  • One column per date.

Vertical format (input)#

Date | AAPL | MSFT | GOOG | … 2024-01-01 | 0.5 | 0.3 | 0.2 | … 2024-01-02 | 0.6 | 0.2 | 0.2 | … … (N dates)

Horizontal format (output)#

Ticker | 2024-01-01 | 2024-01-02 | … AAPL | 0.5 | 0.6 | … MSFT | 0.3 | 0.2 | … GOOG | 0.2 | 0.2 | …

param table:

A vertical-format table where: - The first column is date (string). - Subsequent columns are ticker symbols.

type table:

pa.Table

returns:

A horizontal-format table with: - Column 0 -> “Ticker” - Columns 1..N -> one column per date - One row per ticker.

rtype:

pa.Table

Notes

  • Date values remain as strings (not cast to timestamps).

  • Order of tickers and dates is preserved exactly as in the input.

  • This function does not normalize or validate portfolio weights.

validate_portfolio_date_range(table: Table, start_date: date | Literal['auto'] | None, end_date: date | Literal['auto'] | None, source_name: str) → None[source]#

Fail fast if the configured date range doesn’t overlap a portfolio table’s dates.

Parses the table’s date columns (every column but “Ticker”) and raises immediately when start_date/end_date exclude all of them. Portfolio and benchmark weight files are cheap to load, so this check is meant to run right after they’re read and before any heavier market data, factor returns, or benchmark files are loaded — surfacing a misconfigured date range in milliseconds instead of after minutes of unrelated I/O.

Parameters:
  • table (pa.Table) – Horizontal-format table with columns [Ticker, date1, date2, ...].

  • start_date (datetime.date or {"auto"} or None) – Configured lower bound. "auto" or None skips the check.

  • end_date (datetime.date or {"auto"} or None) – Configured upper bound. "auto" or None skips the check.

  • source_name (str) – Human-readable description of the table’s origin, used in the error message (e.g. "portfolio 'portfolio_weights'").

Raises:

DateRangeError – If start_date is after every date in table, or end_date is before every date in table.

Conversion utilities for bridging PyArrow tables to pandas DataFrames.

Provides functions to convert PyArrow tables produced by the market data and portfolio pipelines into pandas DataFrames with proper datetime indexing, as well as a standalone returns computation function.

compute_returns_from_prices(price_df: DataFrame) → DataFrame[source]#
portfolio_table_to_pandas(table: Table) → DataFrame[source]#
pyarrow_table_to_pandas(table: Table, date_column: str) → DataFrame[source]#