重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
aqr-factor-investing by copyleftdev/sk1llz
npx skills add https://github.com/copyleftdev/sk1llz --skill aqr-factor-investingAQR(应用量化研究)由高盛的克里夫·阿斯内斯和其他学者创立,是一家管理着约1000亿美元资产的量化投资公司。他们以将学术因子研究应用于实际投资而闻名,强调透明度、严谨的方法论以及量化技术的普及化。
"金融领域的最佳理念源于严谨的学术研究,而非华尔街的直觉。"
"因子之所以有效,是因为风险、行为或结构——在投资前先理解是哪一种。"
"如果你无法简单地解释它,说明你理解得还不够透彻。"
AQR 认为,系统性因子(价值、动量、质量等)代表了可以通过纪律性实施来获取的持续回报来源。他们强调理解策略 为什么 有效,而不仅仅是 知道 它们有效。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
class FactorBuilder:
"""
AQR 风格的因子构建:稳健、分散化、投资级别。
"""
def __init__(self, data_provider):
self.data = data_provider
def build_value_factor(self,
universe: List[str],
date: date) -> pd.Series:
"""
价值因子:多个价值指标的复合。
AQR 使用账面价值/价格、盈利/价格、预测盈利/价格等。
"""
metrics = {}
# 账面价值与价格比(经典的法玛-弗伦奇模型)
metrics['book_to_price'] = self.data.get_fundamentals(
universe, 'book_value', date
) / self.data.get_prices(universe, date)
# 盈利与价格比
metrics['earnings_to_price'] = self.data.get_fundamentals(
universe, 'trailing_earnings', date
) / self.data.get_prices(universe, date)
# 远期盈利与价格比(分析师预测)
metrics['forward_ep'] = self.data.get_fundamentals(
universe, 'forward_earnings', date
) / self.data.get_prices(universe, date)
# 现金流与价格比
metrics['cf_to_price'] = self.data.get_fundamentals(
universe, 'operating_cf', date
) / self.data.get_prices(universe, date)
# 复合:z 分数化并取平均值
composite = pd.DataFrame(metrics)
z_scores = composite.apply(lambda x: self.winsorize_and_zscore(x), axis=0)
return z_scores.mean(axis=1)
def build_momentum_factor(self,
universe: List[str],
date: date) -> pd.Series:
"""
动量:12个月回报,跳过最近一个月。
经典的 Jegadeesh-Titman 模型,结合 AQR 的改进。
"""
# 12-1 动量(跳过上个月以避免反转效应)
prices = self.data.get_price_history(universe, date, lookback_months=13)
# 从 t-12 到 t-1 的回报
momentum_12_1 = prices.iloc[-22] / prices.iloc[0] - 1 # 跳过最后一个月
# AQR 增强:同时考虑中期动量
momentum_6_1 = prices.iloc[-22] / prices.iloc[-132] - 1
# 行业调整(避免行业押注)
industries = self.data.get_industries(universe)
mom_adj = momentum_12_1.groupby(industries).transform(
lambda x: x - x.mean()
)
return self.winsorize_and_zscore(mom_adj)
def build_quality_factor(self,
universe: List[str],
date: date) -> pd.Series:
"""
质量:盈利能力、稳定性和财务健康状况。
基于 AQR 的 "Quality Minus Junk" 研究。
"""
profitability = self.calculate_profitability(universe, date)
growth = self.calculate_growth_stability(universe, date)
safety = self.calculate_safety(universe, date)
payout = self.calculate_payout(universe, date)
# 复合质量分数
quality = pd.DataFrame({
'profitability': self.winsorize_and_zscore(profitability),
'growth': self.winsorize_and_zscore(growth),
'safety': self.winsorize_and_zscore(safety),
'payout': self.winsorize_and_zscore(payout)
})
return quality.mean(axis=1)
def calculate_profitability(self, universe, date):
"""毛利润 / 资产,ROE,ROA 等。"""
gp = self.data.get_fundamentals(universe, 'gross_profit', date)
assets = self.data.get_fundamentals(universe, 'total_assets', date)
return gp / assets
def calculate_safety(self, universe, date):
"""低杠杆、低波动性、低贝塔。"""
leverage = self.data.get_fundamentals(universe, 'debt_to_equity', date)
volatility = self.data.get_volatility(universe, date, lookback_days=252)
# 取反,使数值越高越好
return -(leverage.rank() + volatility.rank()) / 2
def winsorize_and_zscore(self, series: pd.Series, clip_std: float = 3.0):
"""对异常值进行缩尾处理并标准化。"""
z = (series - series.mean()) / series.std()
z = z.clip(-clip_std, clip_std)
return (z - z.mean()) / z.std()
class FactorPortfolio:
"""
AQR 的投资组合构建:具有风险管理的因子敞口。
"""
def __init__(self, factors: Dict[str, FactorBuilder],
risk_model: RiskModel,
transaction_cost_model: TCostModel):
self.factors = factors
self.risk = risk_model
self.tcost = transaction_cost_model
def construct_portfolio(self,
universe: List[str],
date: date,
factor_weights: Dict[str, float],
risk_target: float = 0.10) -> pd.Series:
"""
构建具有目标因子敞口的投资组合。
"""
# 计算因子分数
factor_scores = {}
for name, builder in self.factors.items():
factor_scores[name] = builder.build(universe, date)
# 按权重组合因子
combined_score = sum(
factor_scores[name] * weight
for name, weight in factor_weights.items()
)
# 将分数转换为权重(多空)
raw_weights = self.scores_to_weights(combined_score)
# 缩放至目标风险水平
portfolio_vol = self.risk.estimate_volatility(raw_weights)
scaled_weights = raw_weights * (risk_target / portfolio_vol)
return scaled_weights
def scores_to_weights(self, scores: pd.Series) -> pd.Series:
"""
将 z 分数转换为投资组合权重。
AQR 方法:与分数成比例,并带有约束。
"""
# 做多前三分之一,做空后三分之一
n = len(scores)
tercile = n // 3
sorted_idx = scores.sort_values().index
weights = pd.Series(0.0, index=scores.index)
weights[sorted_idx[:tercile]] = -1.0 / tercile # 做空底部
weights[sorted_idx[-tercile:]] = 1.0 / tercile # 做多顶部
return weights
def calculate_turnover_cost(self,
current: pd.Series,
target: pd.Series,
date: date) -> float:
"""
估算再平衡产生的交易成本。
"""
trades = (target - current).abs()
costs = self.tcost.estimate(trades, date)
return costs.sum()
def optimize_with_turnover(self,
current: pd.Series,
target: pd.Series,
max_turnover_cost: float) -> pd.Series:
"""
向目标交易,但遵守换手率预算。
"""
trades = target - current
# 如果无约束成本可接受,则完全交易
full_cost = self.calculate_turnover_cost(current, target, date)
if full_cost <= max_turnover_cost:
return target
# 否则,部分交易(按比例)
trade_fraction = max_turnover_cost / full_cost
return current + trades * trade_fraction
class FactorAttribution:
"""
AQR 风格的透明绩效归因。
准确理解回报的来源。
"""
def __init__(self, factor_returns: pd.DataFrame):
self.factor_returns = factor_returns
def attribute_returns(self,
portfolio_returns: pd.Series,
factor_exposures: pd.DataFrame) -> AttributionResult:
"""
将投资组合回报分解为因子贡献。
R_p = Σ(β_i * F_i) + α + ε
"""
# 对齐数据
common_dates = portfolio_returns.index.intersection(
self.factor_returns.index
)
port_ret = portfolio_returns.loc[common_dates]
fact_ret = self.factor_returns.loc[common_dates]
exposures = factor_exposures.loc[common_dates]
# 计算因子贡献
contributions = {}
total_factor_return = 0
for factor in fact_ret.columns:
factor_contribution = (exposures[factor] * fact_ret[factor]).sum()
contributions[factor] = {
'avg_exposure': exposures[factor].mean(),
'factor_return': fact_ret[factor].sum(),
'contribution': factor_contribution,
'contribution_pct': factor_contribution / port_ret.sum() * 100
}
total_factor_return += factor_contribution
# Alpha 是无法解释的回报
alpha = port_ret.sum() - total_factor_return
return AttributionResult(
total_return=port_ret.sum(),
factor_contributions=contributions,
alpha=alpha,
r_squared=self.calculate_r_squared(port_ret, fact_ret, exposures)
)
def factor_performance_report(self,
start_date: date,
end_date: date) -> pd.DataFrame:
"""
生成因子绩效摘要。
AQR 定期发布这些报告以保持透明度。
"""
returns = self.factor_returns.loc[start_date:end_date]
report = pd.DataFrame({
'Total Return': returns.sum(),
'Annualized Return': returns.mean() * 252,
'Volatility': returns.std() * np.sqrt(252),
'Sharpe Ratio': returns.mean() / returns.std() * np.sqrt(252),
'Max Drawdown': self.calculate_max_drawdown(returns),
'Hit Rate': (returns > 0).mean()
})
return report
class RealisticBacktest:
"""
AQR 强调纸上回报与实际回报之间的差距。
真实地模拟所有摩擦。
"""
def __init__(self,
tcost_model: TransactionCostModel,
borrow_cost_model: BorrowCostModel,
market_impact_model: MarketImpactModel):
self.tcost = tcost_model
self.borrow = borrow_cost_model
self.impact = market_impact_model
def run_backtest(self,
strategy: Strategy,
start_date: date,
end_date: date,
initial_capital: float = 1e8) -> BacktestResult:
"""
使用真实的交易成本和摩擦进行回测。
"""
capital = initial_capital
positions = pd.Series(dtype=float)
results = []
for date in trading_days(start_date, end_date):
# 生成目标投资组合
target = strategy.generate_positions(date, capital)
# 计算交易成本
trades = target - positions
trading_cost = self.tcost.estimate(trades, date)
market_impact = self.impact.estimate(trades, date)
# 空头头寸的借入成本
short_positions = positions[positions < 0]
borrow_cost = self.borrow.estimate(short_positions, date)
# 执行交易(根据成本调整)
capital -= trading_cost + market_impact
positions = target
# 计算回报
price_returns = self.get_returns(positions.index, date)
gross_pnl = (positions * price_returns).sum()
net_pnl = gross_pnl - trading_cost - market_impact - borrow_cost
capital += net_pnl
results.append({
'date': date,
'gross_pnl': gross_pnl,
'trading_cost': trading_cost,
'market_impact': market_impact,
'borrow_cost': borrow_cost,
'net_pnl': net_pnl,
'capital': capital,
'turnover': trades.abs().sum() / capital
})
return self.analyze_results(pd.DataFrame(results))
def analyze_results(self, results: pd.DataFrame) -> BacktestResult:
"""计算包含成本细分的绩效指标。"""
gross_returns = results['gross_pnl'] / results['capital'].shift(1)
net_returns = results['net_pnl'] / results['capital'].shift(1)
return BacktestResult(
gross_sharpe=gross_returns.mean() / gross_returns.std() * np.sqrt(252),
net_sharpe=net_returns.mean() / net_returns.std() * np.sqrt(252),
implementation_drag=(gross_returns.sum() - net_returns.sum()) / len(results) * 252,
avg_turnover=results['turnover'].mean(),
total_trading_costs=results['trading_cost'].sum(),
total_impact_costs=results['market_impact'].sum(),
total_borrow_costs=results['borrow_cost'].sum()
)
AQR 通过以下问题来研究因子投资:
每周安装数
21
代码仓库
GitHub 星标数
3
首次出现
2026年2月1日
安全审计
已安装于
gemini-cli19
github-copilot18
codex18
opencode18
cursor18
cline15
AQR (Applied Quantitative Research), founded by Cliff Asness and other academics from Goldman Sachs, is a quantitative investment firm managing ~$100B. Known for bringing academic factor research to practical investing, they emphasize transparency, rigorous methodology, and the democratization of quantitative techniques.
"The best ideas in finance come from rigorous academic research, not from Wall Street intuition."
"Factors work because of risk, behavior, or structure—understand which before you invest."
"If you can't explain it simply, you don't understand it well enough."
AQR believes that systematic factors (value, momentum, quality, etc.) represent persistent sources of returns that can be harvested through disciplined implementation. They emphasize understanding why strategies work, not just that they work.
Academic Foundation : Start with peer-reviewed research.
Factor Discipline : Stick to factors with economic rationale.
Transparency : Publish methodology, admit mistakes.
Diversification : Across factors, geographies, and asset classes.
Implementation Matters : Transaction costs can kill paper returns.
class FactorBuilder:
"""
AQR-style factor construction: robust, diversified, investment-grade.
"""
def __init__(self, data_provider):
self.data = data_provider
def build_value_factor(self,
universe: List[str],
date: date) -> pd.Series:
"""
Value factor: composite of multiple value metrics.
AQR uses book/price, earnings/price, forecast earnings/price, etc.
"""
metrics = {}
# Book to Price (classic Fama-French)
metrics['book_to_price'] = self.data.get_fundamentals(
universe, 'book_value', date
) / self.data.get_prices(universe, date)
# Earnings to Price
metrics['earnings_to_price'] = self.data.get_fundamentals(
universe, 'trailing_earnings', date
) / self.data.get_prices(universe, date)
# Forward Earnings to Price (analyst estimates)
metrics['forward_ep'] = self.data.get_fundamentals(
universe, 'forward_earnings', date
) / self.data.get_prices(universe, date)
# Cash Flow to Price
metrics['cf_to_price'] = self.data.get_fundamentals(
universe, 'operating_cf', date
) / self.data.get_prices(universe, date)
# Composite: z-score and average
composite = pd.DataFrame(metrics)
z_scores = composite.apply(lambda x: self.winsorize_and_zscore(x), axis=0)
return z_scores.mean(axis=1)
def build_momentum_factor(self,
universe: List[str],
date: date) -> pd.Series:
"""
Momentum: 12-month return, skipping most recent month.
Classic Jegadeesh-Titman with AQR refinements.
"""
# 12-1 momentum (skip last month to avoid reversal)
prices = self.data.get_price_history(universe, date, lookback_months=13)
# Return from t-12 to t-1
momentum_12_1 = prices.iloc[-22] / prices.iloc[0] - 1 # Skip last month
# AQR enhancement: also consider intermediate momentum
momentum_6_1 = prices.iloc[-22] / prices.iloc[-132] - 1
# Industry-adjusted (avoid sector bets)
industries = self.data.get_industries(universe)
mom_adj = momentum_12_1.groupby(industries).transform(
lambda x: x - x.mean()
)
return self.winsorize_and_zscore(mom_adj)
def build_quality_factor(self,
universe: List[str],
date: date) -> pd.Series:
"""
Quality: profitability, stability, and financial health.
Based on AQR's "Quality Minus Junk" research.
"""
profitability = self.calculate_profitability(universe, date)
growth = self.calculate_growth_stability(universe, date)
safety = self.calculate_safety(universe, date)
payout = self.calculate_payout(universe, date)
# Composite quality score
quality = pd.DataFrame({
'profitability': self.winsorize_and_zscore(profitability),
'growth': self.winsorize_and_zscore(growth),
'safety': self.winsorize_and_zscore(safety),
'payout': self.winsorize_and_zscore(payout)
})
return quality.mean(axis=1)
def calculate_profitability(self, universe, date):
"""Gross profits / assets, ROE, ROA, etc."""
gp = self.data.get_fundamentals(universe, 'gross_profit', date)
assets = self.data.get_fundamentals(universe, 'total_assets', date)
return gp / assets
def calculate_safety(self, universe, date):
"""Low leverage, low volatility, low beta."""
leverage = self.data.get_fundamentals(universe, 'debt_to_equity', date)
volatility = self.data.get_volatility(universe, date, lookback_days=252)
# Invert so higher is better
return -(leverage.rank() + volatility.rank()) / 2
def winsorize_and_zscore(self, series: pd.Series, clip_std: float = 3.0):
"""Winsorize outliers and standardize."""
z = (series - series.mean()) / series.std()
z = z.clip(-clip_std, clip_std)
return (z - z.mean()) / z.std()
class FactorPortfolio:
"""
AQR's portfolio construction: factor exposure with risk management.
"""
def __init__(self, factors: Dict[str, FactorBuilder],
risk_model: RiskModel,
transaction_cost_model: TCostModel):
self.factors = factors
self.risk = risk_model
self.tcost = transaction_cost_model
def construct_portfolio(self,
universe: List[str],
date: date,
factor_weights: Dict[str, float],
risk_target: float = 0.10) -> pd.Series:
"""
Build a portfolio with target factor exposures.
"""
# Calculate factor scores
factor_scores = {}
for name, builder in self.factors.items():
factor_scores[name] = builder.build(universe, date)
# Combine factors with weights
combined_score = sum(
factor_scores[name] * weight
for name, weight in factor_weights.items()
)
# Convert scores to weights (long-short)
raw_weights = self.scores_to_weights(combined_score)
# Scale to target risk
portfolio_vol = self.risk.estimate_volatility(raw_weights)
scaled_weights = raw_weights * (risk_target / portfolio_vol)
return scaled_weights
def scores_to_weights(self, scores: pd.Series) -> pd.Series:
"""
Convert z-scores to portfolio weights.
AQR approach: proportional to score, with constraints.
"""
# Long top tercile, short bottom tercile
n = len(scores)
tercile = n // 3
sorted_idx = scores.sort_values().index
weights = pd.Series(0.0, index=scores.index)
weights[sorted_idx[:tercile]] = -1.0 / tercile # Short bottom
weights[sorted_idx[-tercile:]] = 1.0 / tercile # Long top
return weights
def calculate_turnover_cost(self,
current: pd.Series,
target: pd.Series,
date: date) -> float:
"""
Estimate transaction costs from rebalancing.
"""
trades = (target - current).abs()
costs = self.tcost.estimate(trades, date)
return costs.sum()
def optimize_with_turnover(self,
current: pd.Series,
target: pd.Series,
max_turnover_cost: float) -> pd.Series:
"""
Trade toward target, but respect turnover budget.
"""
trades = target - current
# If unconstrained cost is acceptable, trade fully
full_cost = self.calculate_turnover_cost(current, target, date)
if full_cost <= max_turnover_cost:
return target
# Otherwise, trade partially (proportionally)
trade_fraction = max_turnover_cost / full_cost
return current + trades * trade_fraction
class FactorAttribution:
"""
AQR-style transparent performance attribution.
Understand exactly where returns came from.
"""
def __init__(self, factor_returns: pd.DataFrame):
self.factor_returns = factor_returns
def attribute_returns(self,
portfolio_returns: pd.Series,
factor_exposures: pd.DataFrame) -> AttributionResult:
"""
Decompose portfolio returns into factor contributions.
R_p = Σ(β_i * F_i) + α + ε
"""
# Align data
common_dates = portfolio_returns.index.intersection(
self.factor_returns.index
)
port_ret = portfolio_returns.loc[common_dates]
fact_ret = self.factor_returns.loc[common_dates]
exposures = factor_exposures.loc[common_dates]
# Calculate factor contributions
contributions = {}
total_factor_return = 0
for factor in fact_ret.columns:
factor_contribution = (exposures[factor] * fact_ret[factor]).sum()
contributions[factor] = {
'avg_exposure': exposures[factor].mean(),
'factor_return': fact_ret[factor].sum(),
'contribution': factor_contribution,
'contribution_pct': factor_contribution / port_ret.sum() * 100
}
total_factor_return += factor_contribution
# Alpha is unexplained return
alpha = port_ret.sum() - total_factor_return
return AttributionResult(
total_return=port_ret.sum(),
factor_contributions=contributions,
alpha=alpha,
r_squared=self.calculate_r_squared(port_ret, fact_ret, exposures)
)
def factor_performance_report(self,
start_date: date,
end_date: date) -> pd.DataFrame:
"""
Generate factor performance summary.
AQR publishes these regularly for transparency.
"""
returns = self.factor_returns.loc[start_date:end_date]
report = pd.DataFrame({
'Total Return': returns.sum(),
'Annualized Return': returns.mean() * 252,
'Volatility': returns.std() * np.sqrt(252),
'Sharpe Ratio': returns.mean() / returns.std() * np.sqrt(252),
'Max Drawdown': self.calculate_max_drawdown(returns),
'Hit Rate': (returns > 0).mean()
})
return report
class RealisticBacktest:
"""
AQR emphasizes the gap between paper and real returns.
Model all frictions realistically.
"""
def __init__(self,
tcost_model: TransactionCostModel,
borrow_cost_model: BorrowCostModel,
market_impact_model: MarketImpactModel):
self.tcost = tcost_model
self.borrow = borrow_cost_model
self.impact = market_impact_model
def run_backtest(self,
strategy: Strategy,
start_date: date,
end_date: date,
initial_capital: float = 1e8) -> BacktestResult:
"""
Backtest with realistic transaction costs and frictions.
"""
capital = initial_capital
positions = pd.Series(dtype=float)
results = []
for date in trading_days(start_date, end_date):
# Generate target portfolio
target = strategy.generate_positions(date, capital)
# Calculate trading costs
trades = target - positions
trading_cost = self.tcost.estimate(trades, date)
market_impact = self.impact.estimate(trades, date)
# Borrow costs for short positions
short_positions = positions[positions < 0]
borrow_cost = self.borrow.estimate(short_positions, date)
# Execute trades (adjust for costs)
capital -= trading_cost + market_impact
positions = target
# Calculate return
price_returns = self.get_returns(positions.index, date)
gross_pnl = (positions * price_returns).sum()
net_pnl = gross_pnl - trading_cost - market_impact - borrow_cost
capital += net_pnl
results.append({
'date': date,
'gross_pnl': gross_pnl,
'trading_cost': trading_cost,
'market_impact': market_impact,
'borrow_cost': borrow_cost,
'net_pnl': net_pnl,
'capital': capital,
'turnover': trades.abs().sum() / capital
})
return self.analyze_results(pd.DataFrame(results))
def analyze_results(self, results: pd.DataFrame) -> BacktestResult:
"""Compute performance metrics with cost breakdown."""
gross_returns = results['gross_pnl'] / results['capital'].shift(1)
net_returns = results['net_pnl'] / results['capital'].shift(1)
return BacktestResult(
gross_sharpe=gross_returns.mean() / gross_returns.std() * np.sqrt(252),
net_sharpe=net_returns.mean() / net_returns.std() * np.sqrt(252),
implementation_drag=(gross_returns.sum() - net_returns.sum()) / len(results) * 252,
avg_turnover=results['turnover'].mean(),
total_trading_costs=results['trading_cost'].sum(),
total_impact_costs=results['market_impact'].sum(),
total_borrow_costs=results['borrow_cost'].sum()
)
AQR approaches factor investing by asking:
Weekly Installs
21
Repository
GitHub Stars
3
First Seen
Feb 1, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli19
github-copilot18
codex18
opencode18
cursor18
cline15
前端代码审计工具 - 自动化检测可访问性、性能、响应式设计、主题化与反模式
57,700 周安装
Instagram Graph API 使用指南:读取与发布内容,获取媒体和话题标签数据
208 周安装
Nansen Trading 命令行工具:Solana 和 Base 链上代币交易与报价执行指南
209 周安装
uni-app原生App打包指南:Android/iOS离线打包、签名配置与原生插件集成
45 周安装
Nansen智能提醒CLI工具:区块链链上监控与聪明钱追踪
210 周安装
Encore前端集成:自动生成TypeScript客户端,连接React与后端API
208 周安装
PubChem 数据库 Python 使用指南:化学结构搜索、性质检索与生物活性数据分析
212 周安装