Download webui/factor_score.py from sgfw/kronos: direct link, hf CLI and curl.
- Browser
- Download file 7.35 kB
-
https://huggingface.co/spaces/sgfw/kronos/resolve/main/webui/factor_score.py
- Command line
-
hf download hf://spaces/sgfw/kronos/webui/factor_score.py
-
curl -L -o factor_score.py https://huggingface.co/spaces/sgfw/kronos/resolve/main/webui/factor_score.py
7.35 kB
| # -*- coding: utf-8 -*- | |
| """ | |
| 蒸鱼股票分析系统 - 多维因子评分体系 | |
| 基于QuantGPT iteration.py compute_factor_score适配 | |
| 6维度评分: IC Mean 15% + IC IR 15% + 稳定性 15% + 反过拟合 15% + 分组回测 15% + Cloud对齐 25% | |
| """ | |
| import numpy as np | |
| import pandas as pd | |
| from datetime import datetime | |
| import warnings | |
| warnings.filterwarnings('ignore') | |
| # 评分权重配置 | |
| SCORE_WEIGHTS = { | |
| 'ic_mean': 0.15, | |
| 'ic_ir': 0.15, | |
| 'stability': 0.15, | |
| 'anti_overfit': 0.15, | |
| 'backtest': 0.15, | |
| 'cloud_alignment': 0.25, | |
| } | |
| def compute_factor_score(backtest_result, anti_overfit_result=None, cloud_result=None): | |
| """ | |
| 计算因子综合评分(0-100) | |
| Parameters | |
| ---------- | |
| backtest_result : dict | |
| run_factor_backtest的返回结果 | |
| anti_overfit_result : dict, optional | |
| 反过拟合检测结果 | |
| cloud_result : dict, optional | |
| 云端因子库对齐评分 {'ic_mean': float, 'ic_ir': float, 'turnover': float, 'sufficiency': float} | |
| Returns | |
| ------- | |
| dict : 6维度评分 + 综合评分 + 评级 | |
| """ | |
| if not backtest_result or not backtest_result.get('success'): | |
| return {'overall': 0, 'grade': 'N/A', 'dimensions': {}, 'error': '回测结果无效'} | |
| summary = backtest_result.get('summary', {}) | |
| performance = backtest_result.get('performance', {}) | |
| scores = {} | |
| # ─── 维度1: IC Mean(15%)─── | |
| ic_mean = abs(summary.get('ic_mean', 0)) | |
| scores['ic_mean'] = min(ic_mean / 0.05, 1.0) * 100 | |
| # ─── 维度2: IC IR(15%)─── | |
| ic_ir = abs(summary.get('ic_ir', 0)) | |
| scores['ic_ir'] = min(ic_ir / 1.5, 1.0) * 100 | |
| # ─── 维度3: 稳定性(15%)─── | |
| ic_win_rate = summary.get('ic_win_rate', 0) | |
| # Sharpe稳定性:比较第1组和最后1组的Sharpe符号一致性 | |
| g1_sharpe = performance.get('group_1', {}).get('sharpe', 0) | |
| gn_sharpe = performance.get('group_5', {}).get('sharpe', 0) | |
| sharpe_consistent = 1 if g1_sharpe * gn_sharpe <= 0 else 0 # 一正一负为好 | |
| stability_score = ic_win_rate * 100 * 0.6 + sharpe_consistent * 40 | |
| scores['stability'] = min(stability_score, 100) | |
| # ─── 维度4: 反过拟合(15%)─── | |
| if anti_overfit_result: | |
| ao_score = anti_overfit_result.get('overall_score', 0) | |
| scores['anti_overfit'] = min(float(ao_score), 100) | |
| else: | |
| # 无反过拟合数据时用IC胜率近似 | |
| scores['anti_overfit'] = ic_win_rate * 100 * 0.7 | |
| # ─── 维度5: 分组回测(15%)─── | |
| ls_sharpe = abs(performance.get('long_short', {}).get('sharpe', 0)) | |
| mono = abs(performance.get('monotonicity', 0)) | |
| spread = abs(performance.get('spread', 0)) | |
| bt_score = (min(ls_sharpe / 2.0, 1) * 40 + min(mono, 1) * 40 + min(spread / 0.1, 1) * 20) | |
| scores['backtest'] = min(bt_score, 100) | |
| # ─── 维度6: Cloud对齐(25%)─── | |
| if cloud_result: | |
| c_ic = cloud_result.get('ic_mean', 0) | |
| c_ir = cloud_result.get('ic_ir', 0) | |
| c_turn = cloud_result.get('turnover', 0.5) | |
| c_suff = cloud_result.get('sufficiency', 0.5) | |
| scores['cloud_alignment'] = ( | |
| min(abs(c_ic) / 0.05, 1) * 30 + | |
| min(abs(c_ir) / 1.0, 1) * 30 + | |
| min(c_turn, 1) * 20 + | |
| min(c_suff, 1) * 20 | |
| ) | |
| else: | |
| # 无Cloud数据时,用本地指标的置信度加权 | |
| local_confidence = (scores['ic_mean'] + scores['ic_ir']) / 200 | |
| scores['cloud_alignment'] = local_confidence * 100 | |
| # ─── 综合评分 ─── | |
| overall = 0 | |
| for key, weight in SCORE_WEIGHTS.items(): | |
| overall += scores.get(key, 0) * weight | |
| overall = round(overall, 2) | |
| # ─── 评级 ─── | |
| if overall >= 80: | |
| grade = 'S' | |
| elif overall >= 70: | |
| grade = 'A' | |
| elif overall >= 55: | |
| grade = 'B' | |
| elif overall >= 40: | |
| grade = 'C' | |
| elif overall >= 25: | |
| grade = 'D' | |
| else: | |
| grade = 'F' | |
| return { | |
| 'overall': overall, | |
| 'grade': grade, | |
| 'grade_label': _grade_label(grade), | |
| 'weights': SCORE_WEIGHTS, | |
| 'dimensions': {k: round(v, 2) for k, v in scores.items()}, | |
| 'timestamp': datetime.now().isoformat(), | |
| } | |
| def _grade_label(grade): | |
| labels = { | |
| 'S': '卓越因子,强烈推荐', | |
| 'A': '优秀因子,推荐使用', | |
| 'B': '良好因子,可考虑', | |
| 'C': '一般因子,需谨慎', | |
| 'D': '较弱因子,不建议', | |
| 'F': '无效因子,不推荐', | |
| } | |
| return labels.get(grade, '未知') | |
| def compare_factors(factor_results): | |
| """ | |
| 比较多个因子的评分 | |
| Parameters | |
| ---------- | |
| factor_results : list of dict | |
| [{'name': str, 'score': dict from compute_factor_score}, ...] | |
| Returns | |
| ------- | |
| dict : 排名结果 | |
| """ | |
| ranked = sorted(factor_results, key=lambda x: x['score']['overall'], reverse=True) | |
| comparison = { | |
| 'factors': ranked, | |
| 'n_factors': len(ranked), | |
| 'best': ranked[0]['name'] if ranked else None, | |
| 'ranking': [], | |
| } | |
| for i, f in enumerate(ranked): | |
| comparison['ranking'].append({ | |
| 'rank': i + 1, | |
| 'name': f['name'], | |
| 'overall': f['score']['overall'], | |
| 'grade': f['score']['grade'], | |
| }) | |
| return comparison | |
| # 常用因子评估预设 | |
| FACTOR_EVAL_PRESETS = { | |
| 'fast_momentum': { | |
| 'name': '快速动量', | |
| 'expression': 'ts_rank(ts_delta(close, 5), 20)', | |
| 'category': '动量', | |
| 'expected_ic': 0.03, | |
| }, | |
| 'medium_momentum': { | |
| 'name': '中期动量', | |
| 'expression': 'ts_rank(ts_delta(close, 20), 60)', | |
| 'category': '动量', | |
| 'expected_ic': 0.04, | |
| }, | |
| 'mean_reversion': { | |
| 'name': '均值回归', | |
| 'expression': '-ts_zscore(close, 20)', | |
| 'category': '反转', | |
| 'expected_ic': 0.02, | |
| }, | |
| 'volatility': { | |
| 'name': '波动率因子', | |
| 'expression': 'ts_std(close / delay(close, 1) - 1, 20)', | |
| 'category': '波动率', | |
| 'expected_ic': 0.01, | |
| }, | |
| 'volume_momentum': { | |
| 'name': '量价动量', | |
| 'expression': 'ts_corr(close, volume, 20)', | |
| 'category': '量价', | |
| 'expected_ic': 0.02, | |
| }, | |
| 'boll_deviation': { | |
| 'name': '布林偏离', | |
| 'expression': '(close - boll_mid(close, 20)) / ts_std(close, 20)', | |
| 'category': '技术', | |
| 'expected_ic': 0.03, | |
| }, | |
| 'rsi_extreme': { | |
| 'name': 'RSI极值', | |
| 'expression': 'rsi(close, 14) - 50', | |
| 'category': '技术', | |
| 'expected_ic': 0.02, | |
| }, | |
| } | |