Spaces:
Running
Running
Sync from GitHub (tests passed)
Browse files- backtest/runner.py +15 -1
backtest/runner.py
CHANGED
|
@@ -200,6 +200,9 @@ class BacktestRunner:
|
|
| 200 |
pivot = prices.pivot(index='date', columns='symbol', values='close')
|
| 201 |
pivot = pivot.sort_index()
|
| 202 |
|
|
|
|
|
|
|
|
|
|
| 203 |
# Compute returns
|
| 204 |
returns = pivot.pct_change()
|
| 205 |
|
|
@@ -218,6 +221,11 @@ class BacktestRunner:
|
|
| 218 |
if symbol == target_symbol:
|
| 219 |
continue
|
| 220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
# Price ratio to target
|
| 222 |
features[f'{symbol}_ratio'] = pivot[symbol] / pivot[target_symbol]
|
| 223 |
|
|
@@ -234,7 +242,13 @@ class BacktestRunner:
|
|
| 234 |
features['target_vol_20d'] = returns[target_symbol].rolling(20).std()
|
| 235 |
features['target_mom_10d'] = pivot[target_symbol].pct_change(10)
|
| 236 |
|
| 237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
|
| 239 |
def train_and_predict(
|
| 240 |
self,
|
|
|
|
| 200 |
pivot = prices.pivot(index='date', columns='symbol', values='close')
|
| 201 |
pivot = pivot.sort_index()
|
| 202 |
|
| 203 |
+
# Forward fill missing values for symbols with sparse data
|
| 204 |
+
pivot = pivot.ffill()
|
| 205 |
+
|
| 206 |
# Compute returns
|
| 207 |
returns = pivot.pct_change()
|
| 208 |
|
|
|
|
| 221 |
if symbol == target_symbol:
|
| 222 |
continue
|
| 223 |
|
| 224 |
+
# Skip if symbol has too many missing values
|
| 225 |
+
if pivot[symbol].isna().sum() > len(pivot) * 0.5:
|
| 226 |
+
logger.warning(f"Skipping {symbol}: too many missing values")
|
| 227 |
+
continue
|
| 228 |
+
|
| 229 |
# Price ratio to target
|
| 230 |
features[f'{symbol}_ratio'] = pivot[symbol] / pivot[target_symbol]
|
| 231 |
|
|
|
|
| 242 |
features['target_vol_20d'] = returns[target_symbol].rolling(20).std()
|
| 243 |
features['target_mom_10d'] = pivot[target_symbol].pct_change(10)
|
| 244 |
|
| 245 |
+
# Only drop rows where TARGET values are missing (not all features)
|
| 246 |
+
features = features.dropna(subset=['y_target', 'y_current'])
|
| 247 |
+
|
| 248 |
+
# Fill remaining NaN in features with 0 (for model training)
|
| 249 |
+
features = features.fillna(0)
|
| 250 |
+
|
| 251 |
+
return features
|
| 252 |
|
| 253 |
def train_and_predict(
|
| 254 |
self,
|