You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
2.8 KiB
73 lines
2.8 KiB
"""
|
|
WQC Chapter2 速通脚本
|
|
生成20条Delay1-USA因子 -> 体检 -> 返回第一条五项全绿因子
|
|
"""
|
|
import pandas as pd
|
|
import numpy as np
|
|
from wq_core import alpha, get_univ # 网页Notebook已内置
|
|
|
|
# ---------- 参数 ----------
|
|
REGION = 'USA'
|
|
DELAY = 1
|
|
UNIV = get_univ('TOP3000') # 教学关默认宇宙
|
|
N_FACTOR = 20
|
|
METRICS = ['fitness','sharpe','turnover','max_weight','sub_univ_ok']
|
|
GREEN = {'fitness':1.0, 'sharpe':1.25, 'turnover':(1,70), 'max_weight':10, 'sub_univ_ok':True}
|
|
|
|
# ---------- 1. 因子定义池 ----------
|
|
raw_expr = {
|
|
'mom5' : 'rank(ts_return(close,5))',
|
|
'mom10' : 'rank(ts_return(close,10))',
|
|
'rev5' : 'rank(-ts_return(close,5))',
|
|
'rev10' : 'rank(-ts_return(close,10))',
|
|
'vol10' : 'rank(-ts_std(return,10))',
|
|
'vol20' : 'rank(-ts_std(return,20))',
|
|
'amt5' : 'rank(-ts_mean(amount,5))', # 短期缩量
|
|
'amt10' : 'rank(-ts_mean(amount,10))',
|
|
'illiq10': 'rank(ts_mean(abs(return)/amount,10))', # 非流动
|
|
'illiq20': 'rank(ts_mean(abs(return)/amount,20))',
|
|
# 以下再加半衰变体
|
|
'mom5_d7': 'rank(ts_decay_linear(ts_return(close,5),7))',
|
|
'mom5_d10':'rank(ts_decay_linear(ts_return(close,5),10))',
|
|
'rev5_d7': 'rank(-ts_decay_linear(ts_return(close,5),7))',
|
|
'vol10_d7':'rank(-ts_decay_linear(ts_std(return,10),7))',
|
|
'amt5_d7': 'rank(-ts_decay_linear(ts_mean(amount,5),7))',
|
|
'illiq10_d7':'rank(ts_decay_linear(ts_mean(abs(return)/amount,10),7))',
|
|
# 反转+波动组合
|
|
'rev_vol':'rank(-ts_return(close,5)*ts_std(return,10))',
|
|
'mom_vol':'rank(ts_return(close,5)/ts_std(return,10))',
|
|
'amt_rev':'rank(-ts_mean(amount,5)*ts_return(close,5))',
|
|
}
|
|
|
|
# ---------- 2. 批量生成+体检 ----------
|
|
result = []
|
|
for name, expr in raw_expr.items():
|
|
fac = alpha(expr, UNIV, delay=DELAY)
|
|
rpt = fac.test(region=REGION, delay=DELAY) # 返回dict
|
|
rpt['name'] = name
|
|
rpt['expr'] = expr
|
|
result.append(rpt)
|
|
|
|
df = pd.DataFrame(result)
|
|
|
|
# ---------- 3. 过滤全绿 ----------
|
|
def is_green(row):
|
|
ok = (row.fitness >= GREEN['fitness'] and
|
|
row.sharpe >= GREEN['sharpe'] and
|
|
GREEN['turnover'][0] <= row.turnover <= GREEN['turnover'][1] and
|
|
row.max_weight <= GREEN['max_weight'] and
|
|
row.sub_univ_ok == GREEN['sub_univ_ok'])
|
|
return ok
|
|
|
|
greens = df[df.apply(is_green, axis=1)].reset_index(drop=True)
|
|
|
|
# ---------- 4. 输出 ----------
|
|
if greens.empty:
|
|
print('>>> 暂无全绿因子,尝试调半衰期或再中性化 <<<')
|
|
else:
|
|
pick = greens.iloc[0] # 首条即可提交
|
|
print('>>> 发现全绿因子!直接复制下方代码去提交页 <<<')
|
|
print(f'# 因子名: {pick.name}')
|
|
print(f'expression = "{pick.expr}"')
|
|
print(f'# Fitness={pick.fitness:.2f} Sharpe={pick.sharpe:.2f} '
|
|
f'Turnover={pick.turnover:.1f}% MaxWeight={pick.max_weight:.1f}%') |