Caloogy Article
中文

Agent Factor Mining: Automated Factor Engineering and the Overfitting Defense

Date
Oct 12, 2025
Series
Quant Agents
Reading
5 min
Topics
Ai agentQuantFactor miningOverfitting

The one-sentence version

Letting an LLM Agent automatically mine factors is highly attractive: it can read papers, propose hypotheses, write code, and run backtests, attempting thousands of ideas overnight. However, this amplifies the oldest problem in quantitative research a thousandfold: the more you test, the easier it is to find "significant" results in noise (see Multiple Testing and the Factor Zoo). This article uses a simulation experiment to demonstrate: in a pool of 2,000 candidate factors where only one true factor exists, using a standard t>2t > 2 threshold will result in 60 "passing" candidates, 59 of which are fake. The solution is not to make the Agent try fewer times, but to establish unbypassable defenses: a locked-down out-of-sample "safe," thresholds that increase with the number of attempts, economic logic reviews, and complete attempt logs.

Disclaimer

This article is for technical educational purposes only and does not constitute any investment advice. The code in this article uses simulated data.


Layer 1: The Intuition

1.1 A Tireless Researcher

Imagine you have hired a researcher who:

The next morning, they hand you 60 reports of "significantly effective" factors. How much should you believe them?

1.2 Typical Agent Factor Mining Workflow

Yes

No

Read Paper / Data Description

Propose Factor Hypothesis

Write Factor Code

Backtest, Calculate IC

Significant?

Write Report

This loop itself is a multiple testing machine: the "No → Return to Hypothesis" arrow adds another attempt on the same dataset every time it completes a cycle.


Layer 2: Simulation Experiments

2.1 Setup

import numpy as np, pandas as pd
rng = np.random.default_rng(99)
T, N, K = 120, 300, 2000          # 120 months, 300 stocks, Agent generates 2000 candidate factors
fwd = rng.normal(size=(T, N))     # future returns
true_factor = rng.normal(size=(T, N)); fwd += 0.05 * true_factor   # only one true factor is hidden

def mean_ic(F, R):
    Fz = (F - F.mean(1, keepdims=True)) / F.std(1, keepdims=True)
    Rz = (R - R.mean(1, keepdims=True)) / R.std(1, keepdims=True)
    ic = (Fz * Rz).mean(1)
    return ic.mean(), ic.mean() / ic.std() * np.sqrt(len(ic))   # IC mean and t-statistic

split = 84   # first 7 years for Agent "research", last 3 years locked in a safe
res = []
for k in range(K):
    F = true_factor if k == 0 else rng.normal(size=(T, N))
    ic_is, t_is = mean_ic(F[:split], fwd[:split])
    ic_oos, t_oos = mean_ic(F[split:], fwd[split:])
    res.append((k, ic_is, t_is, ic_oos, t_oos))
df = pd.DataFrame(res, columns=["k", "ic_is", "t_is", "ic_oos", "t_oos"])

passed = df[df["t_is"] > 2]
print("Number of candidates with in-sample t>2:", len(passed), " (of which true factor:", int((passed['k'] == 0).sum()), ")")
print("Out-of-sample IC mean of these candidates:", round(passed["ic_oos"].mean(), 4))
print("Still t>2 out-of-sample:", int((passed["t_oos"] > 2).sum()), "; true factor in-sample t =",
      round(df.loc[0, "t_is"], 1), " out-of-sample t =", round(df.loc[0, "t_oos"], 1))
strict = df[df["t_is"] > 3.0]
print("Using t>3 threshold:", len(strict), " passed, of which true factor:", int((strict['k'] == 0).sum()), ")")

Output:

Candidates with in-sample t>2: 61 (including 1 true factor)
Out-of-sample mean IC of these candidates: 0.0014
Still t>2 out-of-sample: 3; true factor in-sample t = 7.4, out-of-sample t = 5.7
Using t>3 threshold: 7 passed, including 1 true factor

2.2 Interpretation

Step Result
Standard threshold t>2t > 2 61 pass, 60 are fake (under a one-sided test, approx. 2.3% of noise will pass; 2000×2.3%≈462000 \times 2.3\% \approx 46, plus random fluctuations)
Out-of-sample IC of these 61 Average approx. 0.001, essentially zero
Safe (out-of-sample) test Only 3 remain; the true factor is among them, with an out-of-sample t=5.7t = 5.7
Increasing threshold to t>3t > 3 7 pass, the number of fakes decreases significantly

Combining two defenses (increased threshold + out-of-sample safe) can suppress false discoveries to a very low level. However, note that even in the out-of-sample " t>2t > 2 " test, about 2% of noise might pass by chance, so 2 out of those 3 are still fake.


Layer 3: Defense Design

3.1 Out-of-Sample Safe

Rule Description
Physical Isolation Safe data is not placed in an environment accessible by the Agent; the Agent's tools cannot read it
One-time Use Each candidate factor can be opened for testing only once
Batch Unlocking Instead of unlocking each factor individually, a batch of candidates is tested together, and multiple testing correction is applied to the batch size
Periodic Replacement As time progresses, new data enters the safe; old safe data is downgraded to research data after being "used"

If the Agent can see the results from the safe and then go back to modify the factor, the safe becomes in-sample. This must be guaranteed by system permissions rather than Agent self-discipline (see Security Boundaries of Agent Trading Systems, Agent Permission Design).

3.2 Increasing Thresholds Based on Attempt Count

3.3 Economic Logic Review

Factors mined purely from data without a reasonable explanation are more likely to be noise. Every candidate factor is required to answer:

Question Description
Why is it effective? Risk premium or behavioral bias? Who is losing money to you?
Why hasn't it been arbitrated away? What constraints prevent others from exploiting it?
Where should it be ineffective? If the logic holds, in what market or period should it fail? Test this prediction

The third question is particularly powerful: a good explanation allows for falsifiable predictions. This is consistent with the "negative control" approach used in causal analysis to reduce financial hallucinations.

3.4 Other Defenses

Defense Description
Correlation with known factors If a new factor is just a combination of size, momentum, or industry, it is not a new discovery
Cross-market, cross-period testing If a factor is found in A-shares, is it also effective in US or HK stocks?
Parameter stability Does the effect persist if parameters are slightly changed? (see The Seven Sins of Backtesting)
Deducting costs Re-evaluate using a realistic cost model (see Trading Cost Modeling)
Diversity constraints Prevents the Agent from repeatedly generating minor variations of the same idea (these are essentially multiple counts of a single attempt, which distorts threshold estimation)
Manual review Human review of code and logic before final inclusion in the database

3.5 The True Value of an Agent

Under these defenses, Agent factor mining remains highly valuable, but the value lies not in "finding more significant factors," but in:


Summary

Layer Key points
Risk An Agent is a multiple testing machine; out of 2,000 attempts, t>2t > 2 will cause about 60 noise factors to "pass"
Safe Out-of-sample data is physically isolated, unlocked only once, and batch-corrected
Threshold The system records attempt counts and automatically increases thresholds
Review Economic logic, falsifiable predictions, incremental information, costs, and manual review