Máscaras de adjacência entre grupos macro para atenção a ativos
Resumo
Este utilitário cria uma matriz booleana de adjacência entre ativos a partir dos rótulos dos grupos de ativos e de conexões opcionais entre grupos. Ativos atribuídos ao mesmo grupo macro são conectados entre si, e cada conexão fornecida entre grupos conecta todos os membros dos dois grupos em ambas as direções. Conexões próprias opcionais permitem que cada ativo preste atenção a si mesmo. Ativos sem mapeamento são atribuídos a um grupo desconhecido e, assim, são conectados a outros ativos não mapeados.
Uma segunda função converte a matriz de adjacência em uma máscara de atenção, marcando pares não adjacentes como não permitidos. O código verifica se a matriz de entrada é quadrada antes da conversão. Isso oferece uma forma simples de codificar uma hipótese prévia de agrupamento macro em um modelo de atenção, mas não estima grupos ou relações com base em dados de mercado; sua utilidade depende da qualidade e da atualidade do mapeamento fornecido e das conexões entre grupos. O documento apresenta detalhes de implementação, não resultados empíricos nem uma avaliação de trading.
Ideias principais
- Ativos do mesmo grupo recebem conexões mútuas na matriz de adjacência.
- Conexões entre grupos ligam simetricamente cada ativo de um grupo a todos os ativos do outro.
- Um parâmetro permite incluir ou omitir conexões do ativo consigo mesmo.
- Ativos sem mapeamento compartilham um grupo desconhecido e, portanto, conectam-se entre si.
- A máscara de atenção marca cada par de ativos não adjacentes como não permitido.
Tags
Texto completo
# graph.py
```py
"""Macroeconomic graph prior utilities.
Builds an asset-level adjacency matrix from macro group labels and
cross-group edges for adjacency-masked attention in DeePM.
"""
from __future__ import annotations
from collections.abc import Iterable, Sequence
from dataclasses import dataclass
import numpy as np
@dataclass(frozen=True, slots=True)
class MacroGraph:
"""Asset-level macro graph."""
assets: list[str]
groups: list[str]
adjacency: np.ndarray # Boolean (N, N)
def build_macro_adjacency(
*,
assets: Sequence[str],
asset_to_group: dict[str, str],
cross_group_edges: Iterable[tuple[str, str]] = (),
include_self_loops: bool = True,
) -> MacroGraph:
"""Build a boolean adjacency matrix from group labels and group edges.
Parameters
----------
assets: Asset identifiers matching the price panel columns.
asset_to_group: Mapping from asset -> macro group label.
cross_group_edges: Undirected (group_a, group_b) edges.
include_self_loops: If True, sets A[i,i] = True.
"""
assets_list = [str(a) for a in assets]
groups = [str(asset_to_group.get(a, "UNKNOWN")) for a in assets_list]
n = len(assets_list)
adj = np.zeros((n, n), dtype=bool)
if include_self_loops:
np.fill_diagonal(adj, True)
group_to_indices: dict[str, list[int]] = {}
for i, g in enumerate(groups):
group_to_indices.setdefault(g, []).append(i)
for indices in group_to_indices.values():
idx = np.array(indices, dtype=int)
adj[np.ix_(idx, idx)] = True
for g1, g2 in cross_group_edges:
idx1 = group_to_indices.get(g1, [])
idx2 = group_to_indices.get(g2, [])
if not idx1 or not idx2:
continue
a = np.array(idx1, dtype=int)
b = np.array(idx2, dtype=int)
adj[np.ix_(a, b)] = True
adj[np.ix_(b, a)] = True
return MacroGraph(assets=assets_list, groups=groups, adjacency=adj)
def adjacency_to_attn_mask(adjacency: np.ndarray) -> np.ndarray:
"""Convert boolean adjacency to attention mask (True = disallowed)."""
if adjacency.ndim != 2 or adjacency.shape[0] != adjacency.shape[1]:
raise ValueError("adjacency must be square (N,N)")
return ~adjacency
```Exibido na íntegra, com atribuição conforme a licença da fonte. Licença: MIT
Este resumo foi escrito pelo agente de pesquisa da Stratmill com base no original; não é uma cópia da fonte.