Saltar al contenido
Todos los documentos de la biblioteca

Gestionar una población común de modelos para secuencias de opciones del S&P 500

Código Machine Learning for Trading

Resumen

Este cuaderno ejecuta el modelo NLinear de una población declarada de tres modelos de aprendizaje secuencial para opciones del S&P 500. Resuelve las solicitudes y los puntos de control de toda la población antes de ajustar este modelo, para que cuadernos posteriores puedan ejecutar los modelos LSTM y PatchTST sobre la misma captura. El dispositivo forma parte de la identidad de entrenamiento porque los cálculos con CPU y GPU pueden producir pesos ajustados distintos; por tanto, un dispositivo no canónico requiere su propio nombre de población.

El flujo de trabajo prioriza la reproducibilidad y la integridad: registra la pertenencia a la población, comprueba que la solicitud de NLinear sea única y verifica que el punto de control devuelto esté completo. La construcción de secuencias se describe como segura frente a brechas, con estado ajustado persistido, compatibilidad con reinicios y comprobaciones de claves admisibles. El documento no comunica el rendimiento del modelo, compara arquitecturas ni demuestra valor para el trading. Explica controles de ejecución e identidad para un flujo de modelado; el análisis del modelo y el backtesting quedan para trabajos posteriores.

Ideas clave

  • La población completa de configuraciones y puntos de control se resuelve antes de ejecutar el modelo NLinear.
  • El dispositivo de entrenamiento forma parte de la identidad del modelo porque las ejecuciones con CPU y GPU pueden producir pesos distintos.
  • Una captura de la población ayuda a conservar la pertenencia declarada si una ejecución de modelo falla o se actualiza.
  • El cuaderno comprueba que la solicitud de NLinear sea única y que su punto de control esté completo.
  • El rendimiento y las conclusiones sobre trading quedan fuera del alcance de este cuaderno.

Etiquetas

Texto completo
# 09_deep_learning.py


```py
# ---
# jupyter:
#   jupytext:
#     cell_metadata_filter: tags,-all
#     text_representation:
#       extension: .py
#       format_name: percent
#       format_version: '1.3'
#       jupytext_version: 1.19.3
#   kernelspec:
#     display_name: Python 3 (ipykernel)
#     language: python
#     name: python3
# ---

# %% [markdown]
# # S&P 500 Options: NLinear
#
# This notebook snapshots the complete three-model sequence population before fitting its NLinear
# member. `09a_lstm` and `09b_patchtst` execute the other declared members against the same
# immutable population. Every configured checkpoint remains eligible for model analysis and
# backtesting.
#
# Prerequisites: `03_financial_features`, `04_model_based_features`, and `05_evaluation`.

# %%
"""Fit NLinear within the declared S&P 500 options sequence population."""

import polars as pl

from case_studies.research import supersedes_for_run
from case_studies.sp500_options.research_workflow import (
    ALL_LABELS,
    declared_dl_device,
    model_request_catalog,
    open_study,
    published_dl_device,
    resolve_model_requests,
    resolved_model_plan,
    run_official_model_subset,
    run_resolved_model_requests,
    snapshot_official_model_catalog,
)

# %% tags=["parameters"]
EXECUTION_TIER = "canonical"
WORKSPACE: str = ""
PREVIEW_REDUCTIONS: dict = {}
DEVICE: str = ""

SEQUENCE_CONFIGS = ("nlinear", "lstm_h64", "patchtst")
POPULATION_NAME: str = ""
SUPERSEDES_POPULATION: str = "7a9dc8881c9e"

# %% [markdown]
# ### The device the population was fitted on
#
# A network trained on a GPU and the same network trained on a CPU accumulate their sums in a
# different order and reach different weights, so the device is part of what the fitted model is
# and sits inside the training identity rather than beside it. The device this population was
# fitted on is declared once, in `modeling.dl.device` in `config/setup.yaml`, and read from there
# by all four deep-learning notebooks rather than retyped in each. On a machine with no NVIDIA
# card the run stops here rather than quietly training something else: set `DEVICE="cpu"` and pass
# a `POPULATION_NAME` to fit the same requests there, under a name of their own.

# %%
CANONICAL_POPULATION_NAME = "sp500-options-sequence-validation-v1"

published_device = published_dl_device()
device = declared_dl_device(DEVICE)
population_name = POPULATION_NAME or CANONICAL_POPULATION_NAME
if device != published_device and population_name == CANONICAL_POPULATION_NAME:
    raise ValueError(
        f"this run fits on {device!r}, not the published {published_device!r}, so its "
        f"identities are not the ones {CANONICAL_POPULATION_NAME!r} holds; pass "
        f"POPULATION_NAME to give them a population of their own"
    )
print(f"training device: {device} (declared: {published_device})")

# %% [markdown]
# ## Complete sequence request population
#
# The case-wide table is resolved before the first member executes. Canonical execution snapshots
# all configuration-checkpoint identities so a failed member cannot disappear from later analysis.
#
# **A name holds one generation at a time**, and this notebook is the only one that writes this
# population - `09a_lstm` and `09b_patchtst` execute members of a snapshot that already exists.
# Anything that moves a training identity moves every prediction hash with it, so the members
# this run computes are no longer the members an earlier snapshot under the same name declared,
# and those two notebooks then refuse their own work as undeclared. `SUPERSEDES_POPULATION`
# names the snapshot such a run retires, and the value is part of what the population is hashed
# over. The value here names the snapshot this run retires; it is empty only for the first
# snapshot under a name.
#
# `create` refuses a changed member list under an existing name unless this names the current
# snapshot, so the parameter is what makes refreshing this population possible at all. Without
# it the refit stops at the write with the hash it needs, which is the right failure but not
# one this notebook could act on.

# %%
study = open_study(execution_tier=EXECUTION_TIER, workspace=WORKSPACE or None)
all_requests = model_request_catalog(
    "deep_learning",
    labels=ALL_LABELS,
    config_names=SEQUENCE_CONFIGS,
)
all_resolved = resolve_model_requests(
    study,
    all_requests,
    execution_tier=EXECUTION_TIER,
    overrides={"device": device},
    preview_reductions=PREVIEW_REDUCTIONS,
)
resolved_model_plan(all_resolved)

# %% [markdown]
# ## Execute NLinear
#
# NLinear shares the gap-safe sequence construction, fold boundaries, fitted-state persistence,
# restart, and exact eligible-key checks used by the other sequence configurations.

# %%
nlinear_resolved = tuple(
    request for request in all_resolved if request.spec["config_name"] == "nlinear"
)
if len(nlinear_resolved) != 1:
    raise ValueError("the sequence population must contain exactly one NLinear request")

if EXECUTION_TIER == "canonical":
    population = snapshot_official_model_catalog(
        study,
        all_requests,
        population_name=population_name,
        resolved_requests=all_resolved,
        supersedes=supersedes_for_run(
            study,
            population_name=population_name,
            declared=SUPERSEDES_POPULATION or None,
            execution_tier=EXECUTION_TIER,
        ),
    )
    execution, population = run_official_model_subset(
        study,
        nlinear_resolved,
        population=population,
    )
else:
    if not WORKSPACE or not PREVIEW_REDUCTIONS:
        raise ValueError("preview execution requires WORKSPACE and PREVIEW_REDUCTIONS")
    execution = run_resolved_model_requests(study, nlinear_resolved)
    population = None

# %% tags=["results"]
catalog = execution.catalog_rows.select(
    "family",
    "label",
    "config_name",
    "checkpoint_kind",
    "checkpoint_value",
    "execution_tier",
    "complete",
    "training_hash",
    "prediction_hash",
).sort("checkpoint_value")
if catalog.filter(~pl.col("complete")).height:
    raise RuntimeError("NLinear execution returned a partial checkpoint")
catalog

# %% [markdown]
# The NLinear checkpoint artifacts are complete. The official sequence population remains open
# until `09a_lstm` and `09b_patchtst` publish their declared members.

```

Se muestra íntegramente con atribución según la licencia de la fuente. Licencia: MIT

Este resumen lo redactó el agente de investigación de Stratmill a partir del original; no es una copia de la fuente.