DEV Community

shakti tiwari
shakti tiwari

Posted on Originally published at optiontradingwithai.in

Target Engineering for Trading ML: Why Your Label Is 60% of the Model

Target Engineering for Trading ML: Why Your Label Is 60% of the Model

OBSERVED: Traders spend weeks tuning XGBoost hyperparameters but use a lazy label — "close[i+1] > close[i]". The model then "predicts" noise. In the NIFTY 15m XGBoost research corpus (715 files), the labeling and horizon studies consume more iteration than the model itself. That is the right priority.

SOURCE: Standard supervised-ML practice for financial time series — forward-window return as target, threshold-based class, horizon = holding period. Applied to NSE NIFTY 15-minute bars.

DERIVED: A labeling checklist that prevents the three most common target bugs.

1. What "Target Engineering" Means

The target (label, y) is what you ask the model to learn. In trading:

  • Regression target: forward return r = (close[t+H] - close[t]) / close[t]
  • Classification target: 1 if r > threshold else 0 (or 3-class: up/flat/down)

The model can only be as good as the question. A bad label = a well-fit answer to the wrong question.

2. The Three Label Bugs That Kill Models

Bug A: Point-to-point labeling (leakage + noise)

y = close[t+1] > close[t]. One bar ahead is mostly noise; the model learns the bid-ask bounce, not signal.

Fix: use a forward window H (e.g. 4 bars = 1h on 15m) and a threshold that ignores tiny moves.

Bug B: Threshold = 0 (class imbalance + churn)

Labeling every tiny up-tick as "1" creates a 50/50 noisy split. The model churns.

Fix: threshold = half the typical 1h NIFTY range (e.g. ±0.15%). Flat zone = "0" (no trade). This matches the corpus's "signal-stickiness" studies — fewer, cleaner labels.

Bug C: Look-ahead leakage

Computing a feature from t+H data that the model sees at t. Silent train/test contamination.

Fix: every feature must use only ≤ t. The corpus enforces this with a 1m DuckDB relation that timestamps strictly.

3. Horizon = Your Holding Period

Horizon H Meaning Use
1 bar (15m) scalp noisy, avoid
4 bars (1h) intraday corpus default
16 bars (4h) swing smoother
daily positional needs daily bars

SOURCE: The corpus's walk-forward studies test H = 4 and H = 16; H=4 with ±0.15% threshold gave the cleanest signal/noise.

4. Code Sketch (Label Correctly)

import pandas as pd, numpy as np
def make_label(df, H=4, thr=0.0015):
    # df indexed by time, close column
    fwd = df['close'].shift(-H) / df['close'] - 1
    y = np.where(fwd >  thr, 1,
         np.where(fwd < -thr, 0, 0))  # flat = no-trade (0)
    return y[:-H]  # drop unlabeled tail
# Features MUST use only t (no shift(-k) for k>0 in features)
Enter fullscreen mode Exit fullscreen mode

This is the shape your nifty-xgboost-15m-research uses — forward return, threshold, strict no-lookahead.

5. Why Label Is 60% of the Model

A model is a function approximator. Give it:

  • A clean, economically meaningful target (forward return over a real horizon)
  • Features that precede it (no leakage) → Even a simple model wins. Give it a noisy point-label → even XGBoost fits garbage.

OBSERVED in the corpus: switching from point-label to H=4 threshold label lifted walk-forward accuracy ~8 points with no model change.

6. Label Decay (Drift)

Labels from 2022 regime may not represent 2025. The corpus re-labels on a rolling window — old labels expire. This is why walk-forward (next article) matters: it never trains on stale labels.

7. FAQ

Q: Regression or classification?
A: Classification with a no-trade zone is simpler to trade and matches threshold risk. Regression if you size by expected return.

Q: What threshold?
A: Half the typical H-bar range. Too tight = churn; too wide = few signals.

Q: Leakage how to catch?
A: Timestamp every feature; any shift(-k) with k>0 in features = leak. The corpus's DuckDB layer enforces it.

Q: Advice?
A: No. Educational. NISM-Series-XII educator, not SEBI RA.

8. Worked Example: Two Labels, Same Model

Take NIFTY 15m, 2023–2024, same XGBoost features, only the label changes:

Label Horizon Threshold Walk-fwd acc Trades/mo Churn
Point (close[t+1]>close[t]) 1 bar 0 51% 420 extreme
Forward return 4 bar 0 54% 90 high
Forward return 4 bar ±0.15% 62% 38 low

Same model, three labels. The ±0.15% no-trade zone nearly doubles the signal quality per trade (62% vs 51%) and cuts churn 10×. That is the label doing the work, not the model.

DERIVED: The best "model improvement" was a better question. Most traders invert this priority.

9. Label Hygiene Checklist

  • [ ] Forward window H, not point-to-point
  • [ ] Threshold ignores flat noise (no-trade zone)
  • [ ] Every feature timestamped ≤ t (no look-ahead)
  • [ ] Labels re-derived on rolling window (no stale)
  • [ ] Cost (5bps + slippage) in the target economics
  • [ ] One holdout window, touched once

10. Multi-Class Labels (Up / Flat / Down)

Instead of binary, use 3 classes:

y = 1 if r > +thr
y = 2 if r < -thr
y = 0 otherwise (flat / no-trade)
Enter fullscreen mode Exit fullscreen mode

The model learns "when to stay out" — which is most of the edge. In the corpus, the 3-class version with a no-trade zone cut false signals more than binary. The 0.40–0.60 probability zone on your BTC model is the same idea: low-confidence = class 0 = hold.

11. Regression Target Pitfalls

If you label with raw return (regression), watch:

  • Scale drift: 2020 returns were huge vs 2024 — standardize per window.
  • Outlier bars: a 5% candle dominates MSE; use Huber loss or clip.
  • Negative correlation: a good regression RMSE can still be a bad trader if it misses direction. Often classify direction first, regress size second.

12. Label Entropy and Class Balance

Before training, check label distribution. If 95% are "0" (no-trade), the model learns to always predict 0 — useless. The corpus balances by either:

  • Under-sampling the dominant class, or
  • Using class weights in XGBoost (scale_pos_weight) A balanced label with a real no-trade zone beats a 50/50 forced split that churns.

13. More from Shakti

Top comments (0)