Download source/project/data/reference_level_features.py from tmmycruise/forecasting-v3-checkpoints: direct link, hf CLI and curl.
- Browser
- Download file 12.8 kB
-
https://huggingface.co/tmmycruise/forecasting-v3-checkpoints/resolve/main/source/project/data/reference_level_features.py
- Command line
-
hf download hf://tmmycruise/forecasting-v3-checkpoints/source/project/data/reference_level_features.py
-
curl -L -o reference_level_features.py https://huggingface.co/tmmycruise/forecasting-v3-checkpoints/resolve/main/source/project/data/reference_level_features.py
12.8 kB
| """Causal anchor-time historical-reference features for forecasting.""" | |
| from __future__ import annotations | |
| from collections import deque | |
| from dataclasses import dataclass | |
| import numpy as np | |
| REFERENCE_WINDOWS = (1, 5, 20) | |
| WINDOW_FEATURES = ( | |
| "distance_to_peak_bps", | |
| "distance_to_bottom_bps", | |
| "range_width_bps", | |
| "range_position", | |
| "available", | |
| ) | |
| REFERENCE_FEATURE_NAMES = tuple( | |
| f"prior_{window}_session_{feature}" | |
| for window in REFERENCE_WINDOWS | |
| for feature in WINDOW_FEATURES | |
| ) | |
| SESSION_FEATURE_NAMES = ( | |
| "distance_to_session_open_bps", | |
| "distance_to_session_max_close_so_far_bps", | |
| "distance_to_session_min_close_so_far_bps", | |
| "session_range_position_so_far", | |
| "session_history_available", | |
| ) | |
| GENERIC_WINDOW_FEATURES = ( | |
| "net_return_bps", | |
| "rms_observed_return_bps", | |
| "range_width_bps", | |
| "terminal_drawdown_bps", | |
| "available", | |
| ) | |
| GENERIC_FEATURE_NAMES = tuple( | |
| f"prior_{window}_session_{feature}" | |
| for window in REFERENCE_WINDOWS | |
| for feature in GENERIC_WINDOW_FEATURES | |
| ) | |
| VISIBLE_FEATURE_NAMES = ( | |
| "visible_128_distance_to_peak_bps", | |
| "visible_128_distance_to_bottom_bps", | |
| "visible_128_range_width_bps", | |
| "visible_128_range_position", | |
| "visible_128_history_available", | |
| ) | |
| REFERENCE_TREATMENTS = ( | |
| "P0", | |
| "Pmask", | |
| "P1", | |
| "Pmulti", | |
| "Pgeneric", | |
| "P128", | |
| "Pstale", | |
| "Psession", | |
| ) | |
| class ReferenceFeatureBundle: | |
| reference_values: np.ndarray | |
| generic_values: np.ndarray | |
| stale_reference_values: np.ndarray | |
| visible_values: np.ndarray | |
| session_values: np.ndarray | |
| relative_log_close: np.ndarray | |
| def __post_init__(self) -> None: | |
| row_count = len(self.relative_log_close) | |
| if self.reference_values.shape != ( | |
| row_count, | |
| len(REFERENCE_FEATURE_NAMES), | |
| ): | |
| raise ValueError("reference feature shape is invalid") | |
| if self.generic_values.shape != ( | |
| row_count, | |
| len(GENERIC_FEATURE_NAMES), | |
| ): | |
| raise ValueError("generic feature shape is invalid") | |
| if self.stale_reference_values.shape != ( | |
| row_count, | |
| len(REFERENCE_FEATURE_NAMES), | |
| ): | |
| raise ValueError("stale reference feature shape is invalid") | |
| if self.visible_values.shape != ( | |
| row_count, | |
| len(VISIBLE_FEATURE_NAMES), | |
| ): | |
| raise ValueError("visible feature shape is invalid") | |
| if self.session_values.shape != ( | |
| row_count, | |
| len(SESSION_FEATURE_NAMES), | |
| ): | |
| raise ValueError("session feature shape is invalid") | |
| if not ( | |
| np.isfinite(self.reference_values).all() | |
| and np.isfinite(self.generic_values).all() | |
| and np.isfinite(self.stale_reference_values).all() | |
| and np.isfinite(self.visible_values).all() | |
| and np.isfinite(self.session_values).all() | |
| and np.isfinite(self.relative_log_close).all() | |
| ): | |
| raise ValueError("reference feature bundle contains nonfinite values") | |
| def _relative_log_close(features: dict[str, np.ndarray]) -> np.ndarray: | |
| values = np.asarray(features["X"]) | |
| if values.ndim != 2 or values.shape[1] < 2: | |
| raise ValueError("token feature matrix is invalid") | |
| returns = values[:, 0].astype(np.float64, copy=False) | |
| observed = values[:, 1] > 0.5 | |
| if not np.isfinite(returns).all(): | |
| raise ValueError("close-return stream contains nonfinite values") | |
| if np.any((~observed) & (returns != 0.0)): | |
| raise ValueError("unobserved rows contain nonzero close returns") | |
| return np.cumsum(returns, dtype=np.float64) | |
| def _session_runs(session_date: np.ndarray) -> tuple[np.ndarray, np.ndarray]: | |
| dates = np.asarray(session_date) | |
| if dates.ndim != 1 or not len(dates): | |
| raise ValueError("session dates must be a nonempty vector") | |
| changes = np.flatnonzero(dates[1:] != dates[:-1]) + 1 | |
| starts = np.concatenate(([0], changes)).astype(np.int64) | |
| stops = np.concatenate((changes, [len(dates)])).astype(np.int64) | |
| labels = dates[starts] | |
| if np.any(labels[1:] <= labels[:-1]): | |
| raise ValueError("session dates are not strictly increasing") | |
| return starts, stops | |
| def _geometry( | |
| anchor: np.ndarray, | |
| peak: float, | |
| bottom: float, | |
| ) -> np.ndarray: | |
| width = float(peak - bottom) | |
| denominator = max(width, np.finfo(np.float64).eps) | |
| return np.column_stack( | |
| ( | |
| 10_000.0 * (anchor - peak), | |
| 10_000.0 * (anchor - bottom), | |
| np.full(len(anchor), 10_000.0 * width), | |
| (anchor - bottom) / denominator, | |
| ) | |
| ) | |
| def _generic_summary(values: np.ndarray) -> np.ndarray: | |
| observed_returns = np.diff(values) | |
| rms_return = ( | |
| float(np.sqrt(np.mean(np.square(observed_returns)))) | |
| if len(observed_returns) | |
| else 0.0 | |
| ) | |
| peak = float(np.max(values)) | |
| bottom = float(np.min(values)) | |
| return np.array( | |
| ( | |
| 10_000.0 * float(values[-1] - values[0]), | |
| 10_000.0 * rms_return, | |
| 10_000.0 * (peak - bottom), | |
| 10_000.0 * float(values[-1] - peak), | |
| ), | |
| dtype=np.float64, | |
| ) | |
| def _visible_geometry( | |
| relative_close: np.ndarray, | |
| observed: np.ndarray, | |
| *, | |
| context_length: int = 128, | |
| ) -> np.ndarray: | |
| result = np.zeros( | |
| (len(relative_close), len(VISIBLE_FEATURE_NAMES)), | |
| dtype=np.float64, | |
| ) | |
| maximum: deque[int] = deque() | |
| minimum: deque[int] = deque() | |
| for index, value in enumerate(relative_close): | |
| first = index + 1 - context_length | |
| while maximum and maximum[0] < first: | |
| maximum.popleft() | |
| while minimum and minimum[0] < first: | |
| minimum.popleft() | |
| if not observed[index]: | |
| continue | |
| while maximum and relative_close[maximum[-1]] <= value: | |
| maximum.pop() | |
| while minimum and relative_close[minimum[-1]] >= value: | |
| minimum.pop() | |
| maximum.append(index) | |
| minimum.append(index) | |
| peak = float(relative_close[maximum[0]]) | |
| bottom = float(relative_close[minimum[0]]) | |
| result[index, :4] = _geometry( | |
| np.asarray([value]), | |
| peak, | |
| bottom, | |
| )[0] | |
| result[index, 4] = 1.0 | |
| return result | |
| def materialize_reference_features( | |
| features: dict[str, np.ndarray], | |
| ) -> ReferenceFeatureBundle: | |
| """Build close-only features available at each completed minute anchor.""" | |
| relative_close = _relative_log_close(features) | |
| dates = np.asarray(features["session_date"]) | |
| minute = np.asarray(features["minute_of_session"]) | |
| if len(dates) != len(relative_close) or len(minute) != len(relative_close): | |
| raise ValueError("feature row metadata has inconsistent lengths") | |
| observed = np.asarray(features["X"])[:, 1] > 0.5 | |
| starts, stops = _session_runs(dates) | |
| session_peak = np.full(len(starts), np.nan, dtype=np.float64) | |
| session_bottom = np.full(len(starts), np.nan, dtype=np.float64) | |
| session_available = np.zeros(len(starts), dtype=np.bool_) | |
| for index, (start, stop) in enumerate(zip(starts, stops, strict=True)): | |
| local = observed[start:stop] | |
| if np.any(local): | |
| values = relative_close[start:stop][local] | |
| session_peak[index] = float(np.max(values)) | |
| session_bottom[index] = float(np.min(values)) | |
| session_available[index] = True | |
| reference = np.zeros( | |
| (len(relative_close), len(REFERENCE_FEATURE_NAMES)), | |
| dtype=np.float64, | |
| ) | |
| generic = np.zeros( | |
| (len(relative_close), len(GENERIC_FEATURE_NAMES)), | |
| dtype=np.float64, | |
| ) | |
| stale_reference = np.zeros_like(reference) | |
| visible = _visible_geometry(relative_close, observed) | |
| session = np.zeros( | |
| (len(relative_close), len(SESSION_FEATURE_NAMES)), | |
| dtype=np.float64, | |
| ) | |
| for session_index, (start, stop) in enumerate( | |
| zip(starts, stops, strict=True) | |
| ): | |
| local_observed = observed[start:stop] | |
| if np.any(local_observed): | |
| rows = np.arange(start, stop)[local_observed] | |
| values = relative_close[rows] | |
| running_peak = np.maximum.accumulate(values) | |
| running_bottom = np.minimum.accumulate(values) | |
| opening = values[0] | |
| width = running_peak - running_bottom | |
| session[rows, :4] = np.column_stack( | |
| ( | |
| 10_000.0 * (values - opening), | |
| 10_000.0 * (values - running_peak), | |
| 10_000.0 * (values - running_bottom), | |
| (values - running_bottom) | |
| / np.maximum(width, np.finfo(np.float64).eps), | |
| ) | |
| ) | |
| session[rows, 4] = 1.0 | |
| for window_index, window in enumerate(REFERENCE_WINDOWS): | |
| first = session_index - window | |
| if first < 0: | |
| continue | |
| window_available = session_available[first:session_index] | |
| if not np.all(window_available) or not np.any(local_observed): | |
| continue | |
| peak = float(np.max(session_peak[first:session_index])) | |
| bottom = float(np.min(session_bottom[first:session_index])) | |
| rows = np.arange(start, stop)[local_observed] | |
| offset = window_index * len(WINDOW_FEATURES) | |
| reference[rows, offset : offset + 4] = _geometry( | |
| relative_close[rows], | |
| peak, | |
| bottom, | |
| ) | |
| reference[rows, offset + 4] = 1.0 | |
| source_start = starts[first] | |
| source_stop = stops[session_index - 1] | |
| source_observed = observed[source_start:source_stop] | |
| source_values = relative_close[source_start:source_stop][ | |
| source_observed | |
| ] | |
| generic[rows, offset : offset + 4] = _generic_summary( | |
| source_values | |
| ) | |
| generic[rows, offset + 4] = 1.0 | |
| stale_first = first - 1 | |
| stale_stop = session_index - 1 | |
| if stale_first < 0: | |
| continue | |
| stale_available = session_available[stale_first:stale_stop] | |
| if not np.all(stale_available): | |
| continue | |
| stale_peak = float( | |
| np.max(session_peak[stale_first:stale_stop]) | |
| ) | |
| stale_bottom = float( | |
| np.min(session_bottom[stale_first:stale_stop]) | |
| ) | |
| stale_reference[rows, offset : offset + 4] = _geometry( | |
| relative_close[rows], | |
| stale_peak, | |
| stale_bottom, | |
| ) | |
| stale_reference[rows, offset + 4] = 1.0 | |
| return ReferenceFeatureBundle( | |
| reference_values=reference.astype(np.float32), | |
| generic_values=generic.astype(np.float32), | |
| stale_reference_values=stale_reference.astype(np.float32), | |
| visible_values=visible.astype(np.float32), | |
| session_values=session.astype(np.float32), | |
| relative_log_close=relative_close, | |
| ) | |
| def treatment_values( | |
| bundle: ReferenceFeatureBundle, | |
| treatment: str, | |
| ) -> tuple[np.ndarray, tuple[str, ...]]: | |
| if treatment not in REFERENCE_TREATMENTS: | |
| raise ValueError(f"unknown reference treatment: {treatment}") | |
| if treatment == "Psession": | |
| return bundle.session_values.copy(), SESSION_FEATURE_NAMES | |
| if treatment == "P128": | |
| return bundle.visible_values.copy(), VISIBLE_FEATURE_NAMES | |
| if treatment == "Pgeneric": | |
| return bundle.generic_values.copy(), GENERIC_FEATURE_NAMES | |
| if treatment == "Pstale": | |
| return ( | |
| bundle.stale_reference_values.copy(), | |
| REFERENCE_FEATURE_NAMES, | |
| ) | |
| if treatment == "P1": | |
| width = len(WINDOW_FEATURES) | |
| return ( | |
| bundle.reference_values[:, :width].copy(), | |
| REFERENCE_FEATURE_NAMES[:width], | |
| ) | |
| values = np.zeros_like(bundle.reference_values) | |
| if treatment == "Pmask": | |
| mask_indices = np.arange( | |
| len(WINDOW_FEATURES) - 1, | |
| len(REFERENCE_FEATURE_NAMES), | |
| len(WINDOW_FEATURES), | |
| ) | |
| values[:, mask_indices] = bundle.reference_values[:, mask_indices] | |
| elif treatment == "Pmulti": | |
| values[:] = bundle.reference_values | |
| return values, REFERENCE_FEATURE_NAMES | |
| __all__ = [ | |
| "GENERIC_FEATURE_NAMES", | |
| "REFERENCE_FEATURE_NAMES", | |
| "REFERENCE_TREATMENTS", | |
| "REFERENCE_WINDOWS", | |
| "SESSION_FEATURE_NAMES", | |
| "VISIBLE_FEATURE_NAMES", | |
| "ReferenceFeatureBundle", | |
| "materialize_reference_features", | |
| "treatment_values", | |
| ] | |