jeffliulab commited on
Commit
cfbab36
·
verified ·
1 Parent(s): efddba2

iso_ne_fetch: fetch_long_history_mwh for Chronos's 720h context

Browse files
Files changed (1) hide show
  1. iso_ne_fetch.py +42 -3
iso_ne_fetch.py CHANGED
@@ -49,6 +49,7 @@ assert abs(ZONE_PROPORTIONS.sum() - 1.0) < 1e-3
49
 
50
  ASSETS_DIR = Path(__file__).parent / "assets"
51
  SAMPLE_CSV = ASSETS_DIR / "sample_demand_2022.csv"
 
52
 
53
  # In-memory cache: {timestamp_hash: (timestamp, ndarray)}
54
  _CACHE: dict = {}
@@ -134,8 +135,46 @@ def fetch_recent_demand_mwh(end_dt: Optional[datetime] = None):
134
  return arr, "sample-2022"
135
 
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  if __name__ == "__main__":
138
  arr, src = fetch_recent_demand_mwh()
139
- print(f"source: {src}")
140
- print(f"shape: {arr.shape}")
141
- print(f"per-zone first hour: {dict(zip(ZONE_COLS, arr[0]))}")
 
49
 
50
  ASSETS_DIR = Path(__file__).parent / "assets"
51
  SAMPLE_CSV = ASSETS_DIR / "sample_demand_2022.csv"
52
+ SAMPLE_CSV_LONG = ASSETS_DIR / "sample_demand_2022_long.csv" # 720 h, 2022-12-02..12-31
53
 
54
  # In-memory cache: {timestamp_hash: (timestamp, ndarray)}
55
  _CACHE: dict = {}
 
135
  return arr, "sample-2022"
136
 
137
 
138
+ def fetch_long_history_mwh(end_dt: Optional[datetime] = None,
139
+ hours: int = 720):
140
+ """Fetch a long per-zone demand history (default 720 h = 30 days) ending
141
+ at end_dt, for use as Chronos-Bolt context.
142
+
143
+ Strategy:
144
+ 1. Read the bundled long-history CSV (720 hourly rows from 2022-12).
145
+ 2. Splice in the 24 freshest hours from the live API / cache (so the
146
+ tail of the history reflects recent live demand) when available.
147
+
148
+ Returns:
149
+ (array of shape (hours, 8), source_label). source_label ends in
150
+ "+live" when the tail 24 h came from the API, "+sample" otherwise.
151
+ """
152
+ if end_dt is None:
153
+ end_dt = datetime.now(timezone.utc).replace(minute=0, second=0, microsecond=0)
154
+
155
+ # 1. Bundled long-history CSV (always present)
156
+ if not SAMPLE_CSV_LONG.exists():
157
+ # Fall back to short CSV repeated; less faithful but never crashes.
158
+ short = _load_sample_csv()
159
+ long_arr = np.tile(short, (hours // 24 + 1, 1))[:hours]
160
+ return long_arr.astype(np.float32), "sample-2022-tiled"
161
+
162
+ df = pd.read_csv(SAMPLE_CSV_LONG)
163
+ long_arr = df[ZONE_COLS].tail(hours).to_numpy(dtype=np.float32)
164
+ if long_arr.shape != (hours, 8):
165
+ # Something odd; return what we have and tag.
166
+ return long_arr.astype(np.float32), "sample-2022-short"
167
+
168
+ # 2. Try to splice 24 freshest hours from the live API
169
+ fresh = _try_iso_ne_api(end_dt)
170
+ if fresh is not None and fresh.shape == (24, 8):
171
+ long_arr[-24:] = fresh
172
+ return long_arr, "sample-2022+live"
173
+ return long_arr, "sample-2022"
174
+
175
+
176
  if __name__ == "__main__":
177
  arr, src = fetch_recent_demand_mwh()
178
+ print(f"recent (24 h): source={src}, shape={arr.shape}")
179
+ long_arr, long_src = fetch_long_history_mwh()
180
+ print(f"long ({len(long_arr)} h): source={long_src}, shape={long_arr.shape}")