Chuyển đến nội dung
Tất cả tài liệu trong thư viện

Autoencoder có điều kiện cho định giá tài sản theo đặc trưng

Mã Machine Learning for Trading

Tóm tắt

Phần triển khai này mô tả autoencoder có điều kiện cho định giá tài sản. Mạng beta (beta network) ánh xạ đặc trưng của từng cổ phiếu thành hệ số tải lên các nhân tố tiềm ẩn, trong khi mạng nhân tố tuyến tính ánh xạ lợi suất danh mục được quản lý thành lợi suất nhân tố. Mô hình dự báo lợi suất cổ phiếu bằng tổng các tích giữa hệ số tải và lợi suất nhân tố tương ứng, cho phép mức độ tiếp xúc thay đổi theo đặc trưng doanh nghiệp trong khi các nhân tố được suy ra từ công cụ danh mục.

Mã nguồn cũng cung cấp các hàm truy xuất hệ số tải và nhân tố đã học, hỗ trợ kiểm tra các thành phần của mô hình. Hình phạt L1 chỉ áp dụng cho trọng số ở các lớp ẩn của mạng beta; hình phạt không áp dụng cho độ chệch và lớp hệ số tải cuối cùng, đồng thời trả về không nếu không có lớp ẩn. Đây là tài liệu tham khảo về kiến trúc chứ không phải nghiên cứu thực nghiệm: tài liệu không cung cấp quy trình huấn luyện, bộ dữ liệu, kết quả dự báo hoặc so sánh với các mô hình định giá tài sản khác.

Ý chính

  • Mạng beta (beta network) chuyển đặc trưng cổ phiếu thành hệ số tải lên các nhân tố tiềm ẩn riêng cho từng cổ phiếu.
  • Mạng tuyến tính ánh xạ lợi suất danh mục được quản lý thành lợi suất nhân tố.
  • Lợi suất dự báo được tạo bằng tổng các tích giữa hệ số tải và giá trị nhân tố.
  • Bộ điều chuẩn khuyến khích tính thưa của trọng số lớp ẩn trong mạng beta mà không phạt lớp đầu ra.
  • Phần triển khai xác định cấu trúc mô hình nhưng không cung cấp đánh giá thực nghiệm.

Thẻ

Toàn văn
# cae.py


```py
"""Conditional Autoencoder for Asset Pricing (GKX 2021).

Architecture:


- ConditionalAutoencoder: predicted return = dot(betas, factors)

Reference: Gu, Kelly, Xiu (2021) "Autoencoder Asset Pricing Models"
"""

from __future__ import annotations

import torch
import torch.nn as nn


class BetaNetwork(nn.Module):
    """Maps stock characteristics to per-stock factor loadings."""

    def __init__(self, n_characteristics: int, n_factors: int, hidden_units: tuple = (32,)):
        super().__init__()

        layers: list[nn.Module] = []
        in_features = n_characteristics

        for units in hidden_units:
            layers.append(nn.Linear(in_features, units))
            layers.append(nn.ReLU())
            in_features = units

        layers.append(nn.Linear(in_features, n_factors))
        self.network = nn.Sequential(*layers)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.network(x)


class FactorNetwork(nn.Module):
    """Maps managed portfolio returns to factor returns (linear, no activation)."""

    def __init__(self, n_instruments: int, n_factors: int):
        super().__init__()
        self.linear = nn.Linear(n_instruments, n_factors, bias=False)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.linear(x)


class ConditionalAutoencoder(nn.Module):
    """Conditional Autoencoder for Asset Pricing (GKX Architecture).

    Architecture:
    - Beta Network: characteristics -> ReLU -> factor loadings (with L1 regularization)
    - Factor Network: managed portfolios -> factor returns (linear)
    - Output: dot product of betas and factors

    Args:
        n_characteristics: Number of stock characteristics (L)
        n_instruments: Number of managed portfolio instruments (L+1 typically)
        n_factors: Number of latent factors (K)
        hidden_units: Tuple of hidden layer sizes for BetaNetwork
    """

    def __init__(
        self,
        n_characteristics: int,
        n_instruments: int,
        n_factors: int = 6,
        hidden_units: tuple = (32,),
    ):
        super().__init__()

        self.n_factors = n_factors
        self.n_characteristics = n_characteristics
        self.n_instruments = n_instruments

        self.beta_net = BetaNetwork(n_characteristics, n_factors, hidden_units)
        self.factor_net = FactorNetwork(n_instruments, n_factors)

    def forward(self, characteristics: torch.Tensor, portfolios: torch.Tensor) -> torch.Tensor:
        """Forward pass.

        Args:
            characteristics: (batch_size, n_characteristics) per-stock
            portfolios: (batch_size, n_instruments) managed portfolio features

        Returns:
            predicted_returns: (batch_size,)
        """
        betas = self.beta_net(characteristics)  # (batch, n_factors)
        factors = self.factor_net(portfolios)  # (batch, n_factors)
        pred = (betas * factors).sum(dim=1)
        return pred

    def get_betas(self, characteristics: torch.Tensor) -> torch.Tensor:
        """Extract factor loadings."""
        return self.beta_net(characteristics)

    def get_factors(self, portfolios: torch.Tensor) -> torch.Tensor:
        """Extract factor returns."""
        return self.factor_net(portfolios)


def l1_regularization(model: ConditionalAutoencoder, lambda_l1: float) -> torch.Tensor:
    """L1 regularization on BetaNetwork hidden Dense weights only.

    Matches the GKX (2021) reference, which applies ``kernel_regularizer='L1'``
    only to the *hidden* Dense layers. We exclude biases (sparsity is not
    meaningful) and the final output ``Linear(in, n_factors)`` layer (factor
    loadings should not be pushed to zero by an external regularizer — the
    autoencoder itself learns their magnitudes).
    """
    layers = [m for m in model.beta_net.network if isinstance(m, nn.Linear)]
    if len(layers) <= 1:
        # No hidden layers (CA0 — direct linear projection); no L1 to apply.
        return torch.zeros((), device=next(model.parameters()).device)
    hidden_layers = layers[:-1]  # exclude the final output Linear
    l1 = sum(layer.weight.abs().sum() for layer in hidden_layers)
    return lambda_l1 * l1

```

Hiển thị toàn văn kèm ghi nguồn theo giấy phép của tài liệu gốc. Giấy phép: MIT

Bản tóm tắt này do tác nhân nghiên cứu của Stratmill biên soạn từ tài liệu gốc; đây không phải bản sao của tài liệu.