├── doc ├── alpha101.pdf └── functions.md ├── alpha ├── alpha32 │ ├── cast.md │ └── README.md ├── archive │ ├── alpha1 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha2 │ │ ├── cast.md │ │ ├── README.md │ │ └── alpha_calculator.py │ ├── alpha3 │ │ ├── cast.md │ │ ├── README.md │ │ └── alpha_calculator.py │ ├── alpha4 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha5 │ │ └── cast.md │ ├── alpha8 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha6 │ │ ├── cast.md │ │ ├── README.md │ │ └── alpha_calculator.py │ ├── alpha22 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha26 │ │ ├── cast.md │ │ ├── README.md │ │ └── alpha_calculator.py │ ├── alpha27 │ │ ├── cast.md │ │ ├── README.md │ │ └── alpha_calculator.py │ ├── alpha16 │ │ └── cast.md │ ├── alpha17 │ │ └── cast.md │ ├── alpha21 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha7 │ │ └── cast.md │ ├── alpha18 │ │ └── cast.md │ ├── alpha9 │ │ └── cast.md │ ├── alpha28 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha11 │ │ ├── cast.md │ │ └── alpha_calculator.py │ ├── alpha19 │ │ └── cast.md │ ├── alpha20 │ │ ├── cast.md │ │ └── README.md │ ├── alpha23 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha10 │ │ └── cast.md │ ├── alpha24 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha25 │ │ ├── cast.md │ │ ├── alpha_calculator.py │ │ └── README.md │ ├── alpha29 │ │ ├── cast.md │ │ └── alpha_calculator.py │ └── alpha30 │ │ ├── cast.md │ │ └── alpha_calculator.py ├── alpha33 │ ├── cast.md │ ├── README.md │ └── alpha_calculator.py ├── alpha37 │ ├── cast.md │ └── README.md ├── alpha34 │ ├── cast.md │ └── README.md ├── alpha36 │ ├── cast.md │ └── README.md ├── alpha38 │ ├── cast.md │ └── README.md ├── alpha31 │ ├── cast.md │ └── README.md ├── alpha35 │ ├── cast.md │ ├── alpha_calculator.py │ └── README.md ├── alpha41 │ ├── cast.md │ ├── alpha_calculator.py │ └── README.md ├── alpha39 │ └── cast.md └── alpha40 │ ├── cast.md │ └── README.md ├── requirements.txt ├── CONTRIBUTING.md ├── README.md ├── .gitignore └── data └── generate_mock_data.py /doc/alpha101.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kuhung/alpha-mining/HEAD/doc/alpha101.pdf -------------------------------------------------------------------------------- /alpha/alpha32/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#32 长短结合 2 | 3 | Alpha#32 是一个结合短期趋势和长期量价关系的多因子策略。其核心在于: 4 | 5 | 1. **短期趋势捕捉**:通过计算短期均线与当前价格的偏离并进行标准化,衡量价格相对于近期走势的强度。 6 | 2. **长期量价相关性**:分析成交量加权平均价 (`vwap`) 与滞后收盘价在较长周期内的相关性,以识别长期市场情绪或资金流向。 7 | 8 | 该策略旨在综合利用不同时间维度的信息,以期捕捉价格动量和潜在的市场结构变化。 9 | -------------------------------------------------------------------------------- /alpha/archive/alpha1/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#1 筛选近期强势资产 2 | 3 | 总结:Alpha#1 策略通过结合近期(5日)的动量效应和截面相对强度,筛选出那些在特定条件下(下跌看波动率,上涨看价格水平)表现出强劲信号的资产。 4 | 5 | --- 6 | 7 | ### 日本語訳 8 | 9 | 101の量的要因の解釈|Alpha#1 最近の強力な資産のスクリーニング 10 | 11 | まとめ:Alpha#1 戦略は、最近(5日間)のモメンタム効果とクロスセクション相対強度を組み合わせることで、特定の条件下(下落時はボラティリティ、上昇時は価格水準を見る)で強力なシグナルを示す資産を選別します。 12 | -------------------------------------------------------------------------------- /alpha/archive/alpha2/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#2 成交量与日内收益 2 | 3 | 总结:Alpha#2 策略通过计算成交量变化排名与日内收益率排名的负相关性,识别出成交量异动与价格表现相反的资产,可能反映市场情绪与理性定价的分歧。 4 | 5 | --- 6 | 7 | ### 日本語訳 8 | 9 | 101の量的要因の解釈|Alpha#2 取引量と日中リターン 10 | 11 | まとめ:Alpha#2 戦略は、取引量の変化ランキングと日中リターンランキングの負の相関を計算することにより、取引量の異常な変動と価格パフォーマンスが反対である資産を特定します。これは、市場センチメントと合理的な価格設定の間の不一致を反映している可能性があります。 12 | -------------------------------------------------------------------------------- /alpha/alpha33/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#33 价格反转因子 2 | 3 | **公式**: `rank((-1 * ((1 - (open / close))^1)))` 4 | 5 | **核心逻辑**: 6 | Alpha#33 旨在捕捉基于开盘价和收盘价关系的价格反转信号。其核心逻辑如下: 7 | 8 | 1. **开盘价/收盘价比率**: 计算 `(open / close)`,反映当日价格变动。 9 | 2. **反向价格变动**: `(1 - (open / close))` 再乘以 `-1`,将价格上涨转化为正值,下跌转化为负值,以衡量反转潜力。 10 | 3. **截面排名**: 对所有资产的上述结果进行截面排名,排名越高表示其反转信号越强(即相对下跌越多或上涨越少)。 11 | -------------------------------------------------------------------------------- /alpha/archive/alpha3/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#3 成交量与开盘价 2 | 3 | Alpha#3 策略计算开盘价排名与交易量排名之间10日滚动相关系数的负值,用于捕捉价格与成交量关系的异常模式。 4 | 5 | **应用场景**: 流动性分析、市场情绪识别、价量关系套利。 6 | 7 | --- 8 | 9 | ### 日本語訳 10 | 11 | 101の量的要因の解釈|Alpha#3 取引量と始値 12 | 13 | Alpha#3 戦略は、始値ランキングと取引量ランキングの間の10日間ローリング相関係数の負の値を計算し、価格と取引量の関係における異常なパターンを捉えます。 14 | 15 | **応用シナリオ**: 流動性分析、市場センチメントの識別、価格と出来高の関係を利用した裁定取引。 16 | -------------------------------------------------------------------------------- /alpha/archive/alpha4/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#4 反向低价时序因子 2 | 3 | 总结:Alpha#4策略通过对股票最低价的截面排名进行时间序列分析,识别价格水平在短期内的相对变化趋势,并采用反向逻辑寻找可能的均值回归机会。该因子结合了价格水平分析和短期动量反转特性,适用于捕捉短期过度表现的股票。 4 | 5 | --- 6 | 7 | ### 日本語訳 8 | 9 | 101の量的要因の解釈|Alpha#4 逆張り低価格時系列ファクター 10 | 11 | まとめ:Alpha#4 戦略は、株式の最安値のクロスセクションランキングに対して時系列分析を行い、短期的な価格水準の相対的な変化傾向を識別し、逆張りロジックを用いて平均回帰の機会を探ります。このファクターは、価格水準分析と短期的なモメンタムリバーサルの特性を組み合わせ、短期的に過剰にパフォーマンスした株式を捉えるのに適しています。 12 | -------------------------------------------------------------------------------- /alpha/alpha37/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#37 短期价格动量与历史相关性 2 | 3 | **因子公式:** `(rank(correlation(delay((open - close), 1), close, 200)) + rank((open - close)))` 4 | 5 | Alpha#37 识别出在市场中具有特定动量特征和历史价格行为模式的资产,可用于多空策略的信号。 6 | 7 | 1. **开盘-收盘差值 (`open - close`)**: 反映当日市场情绪和动量。 8 | 2. **延迟开盘-收盘差值与收盘价的相关性**: 衡量前一日动量与当前收盘价在过去200个交易日内的关系,捕捉动量持续性或反转信号。 9 | 3. **截面排名求和**: 对上述两个指标的截面排名进行加总,旨在识别那些兼具近期强势表现和特定历史相关性模式的资产。 10 | 11 | **预期效果:** 识别出在市场中具有特定动量特征和历史价格行为模式的资产,可用于多空策略的信号。 12 | -------------------------------------------------------------------------------- /alpha/alpha34/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#34 波动反转因子 2 | 3 | Alpha#34 是一个综合性截面因子,它结合了短期和长期回报率波动性(通过标准差比率衡量)以及价格的短期动量(通过日间收盘价变化)。 4 | 5 | 核心思想在于捕捉市场在波动性收敛时(预示可能趋势稳定或反转)以及短期价格回调后(寻找超卖反弹机会)的表现。因子通过两次截面排序,强化了相对表现的重要性。 6 | 7 | ## 主要组成: 8 | 9 | * **波动性相对强度**: `(stddev(returns, 2) / stddev(returns, 5))`。这个比率越小,表明短期波动性相对于长期波动性越低,可能意味着市场趋于稳定或酝酿反转。 10 | * **短期价格动量**: `delta(close, 1)`。衡量最新的价格变化,负值表示价格下跌。 11 | 12 | 通过对这两个分量进行逆序截面排序并相加,最后再进行一次截面排序,Alpha#34 旨在识别那些波动性趋于平稳且近期经历小幅回调的资产,从而发现潜在的买入机会。 13 | -------------------------------------------------------------------------------- /alpha/alpha36/cast.md: -------------------------------------------------------------------------------- 1 | ## 解读101个量化因子|Alpha#36: 多因子动量与价值策略 2 | 3 | Alpha#36 是一个高度复杂的合成因子,它融合了多个维度的数据,包括日内动量、成交量、历史回报、VWAP、平均成交额以及价值指标。 4 | 5 | 其核心逻辑是通过五个加权项的组合,从不同角度捕捉市场的复杂动态: 6 | 7 | 1. **日内动量与成交量相关性**: 捕捉价量关系模式。 8 | 2. **日内反转**: 寻找与日内趋势相反的信号。 9 | 3. **历史回报的时间序列排名**: 关注资产在过去一段时间内的相对强弱。 10 | 4. **价格与流动性相关性**: 衡量 VWAP 与平均成交额变化的关联强度。 11 | 5. **价值与动量交互**: 结合长期价值(200日均线)与短期开盘/收盘价行为,识别价值偏离后的日内走势。 12 | 13 | 通过将这五个经过截面排序的独立逻辑分量加权求和,Alpha#36 旨在识别那些在多个维度上同时表现出特定行为模式的资产,从而构建一个稳健且多维度的投资策略。 14 | -------------------------------------------------------------------------------- /alpha/alpha38/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#38 反向时间序列排名与日内波动排名 2 | 3 | **因子公式:** `((-1 * rank(Ts_Rank(close, 10))) * rank((close / open)))` 4 | 5 | Alpha#38 该因子旨在识别短期内相对弱势但日内表现出一定反弹或企稳迹象的资产。 6 | 7 | 1. **日内波动排名 (`rank((close / open))`)**: 反映当日收盘价相对于开盘价的相对涨跌幅,排名越高表明日内表现越强。 8 | 2. **反向短期时间序列排名 (`-1 * rank(Ts_Rank(close, 10))`)**: 衡量当前收盘价在过去10天中的相对位置,并进行反向排名。该部分值越高,表明资产近期表现越弱(超卖),可能存在反转机会。 9 | 3. **乘积**: 将两者相乘,旨在捕捉那些近期超卖但当日开始企稳或反弹的资产。 10 | 11 | **预期效果:** 识别出可能处于短期底部并开始反弹的资产,适用于短线交易或反转策略。 12 | -------------------------------------------------------------------------------- /alpha/archive/alpha5/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#5 VWAP偏差交互因子 2 | 3 | 总结:Alpha#5策略通过分析开盘价相对于VWAP移动平均的偏差和收盘价相对于当日VWAP的偏差,识别价格相对于成交量加权基准的偏离情况。该因子结合了中期VWAP基准比较和当日VWAP表现评估,采用反向逻辑寻找价格偏离过度的交易机会,适用于基于VWAP的均值回归和日内反转策略。 4 | 5 | --- 6 | 7 | ### 日本語訳 8 | 9 | 101の量的要因の解釈|Alpha#5 VWAP乖離相互作用ファクター 10 | 11 | まとめ:Alpha#5 戦略は、VWAP移動平均に対する始値の乖離と、当日のVWAPに対する終値の乖離を分析することにより、出来高加重基準に対する価格の乖離状況を識別します。このファクターは、中期的なVWAP基準比較と当日のVWAPパフォーマンス評価を組み合わせ、逆張りロジックを用いて価格が過度に乖離した取引機会を探し、VWAPベースの平均回帰戦略および日中リバーサル戦略に適しています。 12 | -------------------------------------------------------------------------------- /alpha/archive/alpha8/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#8 开盘价与回报率 2 | 3 | Alpha#8: `-1 * rank(((sum(open, 5) * sum(returns, 5)) - delay((sum(open, 5) * sum(returns, 5)), 10)))` 4 | 5 | ## 核心逻辑 6 | 7 | 捕捉开盘价与回报率短期相关性的变化,通过计算5天总和的乘积与10天前乘积的差值,并对差值排名取负值,生成反向信号。 8 | 9 | --- 10 | 11 | ### 日本語訳 12 | 13 | 101の量的要因の解釈|Alpha#8 始値とリターン率 14 | 15 | Alpha#8: `-1 * rank(((sum(open, 5) * sum(returns, 5)) - delay((sum(open, 5) * sum(returns, 5)), 10)))` 16 | 17 | ## コアロジック 18 | 19 | 始値とリターン率の短期的な相関性の変化を捉え、5日間の合計の積と10日前の積との差を計算し、その差のランキングの負の値を取ることで逆シグナルを生成します。 20 | -------------------------------------------------------------------------------- /alpha/archive/alpha6/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#6 量价因子 2 | 3 | Alpha#6: (-1 * correlation(open, volume, 10)) 4 | 5 | 总结:Alpha#6策略通过计算每日开盘价与成交量在过去10天的皮尔逊相关系数并取其相反数,专注于识别并量化市场中短期的"价量背离"现象。高Alpha值(正值)指示显著的负相关性(如开盘放量下跌或缩量上涨),可作为捕捉特定市场情绪或短期交易机会的信号。 6 | 7 | --- 8 | 9 | ### 日本語訳 10 | 11 | 101の量的要因の解釈|Alpha#6 価格出来高ファクター 12 | 13 | Alpha#6: (-1 * correlation(open, volume, 10)) 14 | 15 | まとめ:Alpha#6 戦略は、毎日の始値と出来高の過去10日間のピアソン相関係数を計算し、その逆数を取ることで、市場における短期的な「価格と出来高の乖離」現象を特定し、定量化することに焦点を当てています。高いAlpha値(正の値)は、顕著な負の相関(例:出来高を伴う始値の下落、または出来高減少を伴う上昇)を示し、特定の市場センチメントや短期的な取引機会を捉えるシグナルとして機能します。 16 | -------------------------------------------------------------------------------- /alpha/alpha31/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#31 多因子组合策略 2 | 3 | **公式**: `((rank(rank(rank(decay_linear((-1 * rank(rank(delta(close, 10)))), 10)))) + rank((-1 * delta(close, 3)))) + sign(scale(correlation(adv20, low, 12))))` 4 | 5 | **核心逻辑**: 6 | Alpha#31 是一个复合因子,旨在通过整合市场价格趋势的持续性、短期反转机会以及量价关系的方向,生成一个综合性的交易信号。它主要由以下三个独立计算后相加的部分构成: 7 | 8 | 1. **趋势与动量部分**: `rank(rank(rank(decay_linear((-1 * rank(rank(delta(close, 10)))), 10))))` 9 | 对收盘价10日变化的负向双重排名结果进行10日衰减线性加权,再进行三次排名,以捕捉平滑后的价格动量强度。 10 | 2. **短期反转部分**: `rank((-1 * delta(close, 3)))` 11 | 对收盘价3日变化的负值进行排名,以捕捉短期价格反转信号。 12 | 3. **量价关系部分**: `sign(scale(correlation(adv20, low, 12)))` 13 | 取20日平均成交量与每日最低价在12日内的时序相关性的截面标准化值的符号,以判断量价配合的方向。 14 | -------------------------------------------------------------------------------- /alpha/archive/alpha22/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#22 相关性变化与波动率排序 2 | 3 | **公式**: `-1 * (delta(correlation(high, volume, 5), 5) * rank(stddev(close, 20)))` 4 | 5 | **核心逻辑**: 6 | 7 | - 关注高价与成交量5日相关性的变化,结合收盘价20日波动率的截面排名。 8 | - 相关性上升且波动率高时,信号为负,反之为正。 9 | 10 | **概述**: 11 | 本因子通过捕捉价格与量能相关性的结构性变化,并结合波动率排序,反映市场情绪突变或结构转折。适合用于监测异常波动和量价关系突变。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101のクオンツファクター解説|Alpha#22 相関変化とボラティリティ順位 18 | 19 | **数式**: `-1 * (delta(correlation(high, volume, 5), 5) * rank(stddev(close, 20)))` 20 | 21 | **コアロジック**: 22 | 23 | - 高値と出来高の5日相関変化に注目し、終値20日ボラティリティの順位と組み合わせる。 24 | - 相関上昇かつボラティリティが高い時はマイナス、逆はプラス。 25 | 26 | **概要**: 27 | 本ファクターは価格と出来高の関係性変化とボラティリティを同時に捉え、市場構造の転換点や異常な動きを検知するのに有効です。 28 | -------------------------------------------------------------------------------- /alpha/alpha35/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#35 交易量与价格综合因子 2 | 3 | Alpha#35 是一个结合了交易量、价格波动(通过 `(close + high) - low` 衡量)和回报率时间序列排名的综合性因子。该因子倾向于在交易量较大、价格动量或波动相对较小、且近期回报率相对较低的市场条件下产生较高的值。 4 | 5 | ## 核心思想: 6 | 7 | 该因子通过以下三个关键组成部分的组合,旨在捕捉市场中的特定模式: 8 | 9 | * **交易量排名 (`Ts_Rank(volume, 32)`)**: 衡量近期市场活跃度,较高的交易量排名通常表示市场关注度高。 10 | * **价格波动反向排名 (`1 - Ts_Rank(((close + high) - low), 16)`)**: 捕捉价格动量或波动相对较小的资产。`((close + high) - low)` 可以反映每日价格的涨跌幅和波动范围。 11 | * **回报率反向排名 (`1 - Ts_Rank(returns, 32)`)**: 识别近期回报率相对较低的资产,可能预示着超跌反弹或价值回归的机会。 12 | 13 | 最终的 Alpha#35 通过将这些经过转化的排名相乘,以识别那些在活跃交易量背景下,价格波动相对平稳且近期表现不佳的资产。 14 | 15 | ## 使用方法: 16 | 17 | 在 `alpha/alpha35/` 目录下运行 `python alpha_calculator.py` 脚本,即可计算 Alpha#35 并生成 `alpha35_results.csv`. 18 | -------------------------------------------------------------------------------- /alpha/archive/alpha26/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#26 成交量与价格高点排名相关性分析 2 | 3 | **公式**: `(-1 * ts_max(correlation(ts_rank(volume, 5), ts_rank(high, 5), 5), 3))` 4 | 5 | **核心逻辑**: 6 | - 通过排名方式分析成交量和最高价的相关性 7 | - 多重时间窗口(5日排名、5日相关、3日最大值) 8 | - 寻找价量背离的市场异常信号 9 | 10 | **概述**: 11 | 本因子通过分析成交量和价格高点的排名相关性,识别市场可能的转折点。当价格创新高而成交量配合不足时,往往预示着上涨动能的减弱。适合用于趋势交易的风险控制。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101のクオンツファクター解説|Alpha#26 出来高と価格高値のランク相関分析 18 | 19 | **数式**: `(-1 * ts_max(correlation(ts_rank(volume, 5), ts_rank(high, 5), 5), 3))` 20 | 21 | **コアロジック**: 22 | - ランキング方式による出来高と高値の相関性分析 23 | - 複数時間枠(5日ランク、5日相関、3日最大値) 24 | - 価格と出来高の乖離による市場異常シグナルの検出 25 | 26 | **概要**: 27 | 本ファクターは、出来高と価格高値のランク相関性を分析し、市場の転換点を識別します。価格が新高値を更新しても出来高が伴わない場合、上昇モメンタムの弱まりを示唆することが多く、トレンドフォロー戦略のリスク管理に適しています。 -------------------------------------------------------------------------------- /alpha/alpha41/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#41 价格几何平均与VWAP偏离度 2 | 3 | **因子公式**: `(((high * low)^0.5) - vwap)` 4 | 5 | **因子描述**: 6 | 7 | * **核心思想**: 该因子旨在捕捉当日内价格的"内在价值"与其"成交重心"之间的偏离程度。它衡量了最高价与最低价的几何平均数与成交量加权平均价(VWAP)之间的差值。 8 | * **主要组成**: 9 | * `(high * low)^0.5`: 最高价与最低价的几何平均数。这可以被看作是当日价格波动范围的一个中心倾向的度量,相比算术平均,它对极端值不那么敏感。 10 | * `vwap`: 成交量加权平均价,代表了当日市场上大部分交易发生的平均成本。 11 | * **预期效果**: 12 | * 当几何平均价高于VWAP时(因子值为正),可能意味着尽管整体成交重心较低,但价格高点强劲,市场可能存在向上的动力或买方力量较强。 13 | * 当几何平均价低于VWAP时(因子值为负),可能表明市场在较高位置的成交量更大,但价格低点拖累了内在价值,可能存在向下的压力或卖方力量占优。 14 | 15 | **数据要求**: 16 | * `high`: 当日最高价 17 | * `low`: 当日最低价 18 | * `vwap`: 当日成交量加权平均价 19 | 20 | **输出信息**: 21 | * `alpha41_results.csv`: 包含计算结果的CSV文件,其中包括原始数据列、中间计算列 (`geometric_mean_high_low`) 和最终的 `alpha41` 值。 -------------------------------------------------------------------------------- /alpha/archive/alpha27/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#27 成交量与均价排名趋势判断 2 | 3 | **公式**: `((0.5 < rank((sum(correlation(rank(volume), rank(vwap), 6), 2) / 2.0))) ? (-1 * 1) : 1)` 4 | 5 | **核心逻辑**: 6 | 7 | - 基于成交量和均价排名的相关性分析 8 | - 通过相关性的短期变化判断趋势 9 | - 生成明确的做多(1)或做空(-1)信号 10 | 11 | **概述**: 12 | 本因子通过分析成交量和成交均价的排名相关性,判断市场趋势的强弱。当相关性排名较高时,表明当前趋势可能即将转折,反之则表明趋势有望持续。适合用于趋势跟踪策略的信号生成。 13 | 14 | --- 15 | 16 | ### 日本語訳 17 | 18 | 101のクオンツファクター解説|Alpha#27 出来高と平均価格のランクトレンド判断 19 | 20 | **数式**: `((0.5 < rank((sum(correlation(rank(volume), rank(vwap), 6), 2) / 2.0))) ? (-1 * 1) : 1)` 21 | 22 | **コアロジック**: 23 | 24 | - 出来高と平均価格のランク相関性分析 25 | - 相関性の短期変化によるトレンド判断 26 | - 明確なロング(1)またはショート(-1)シグナル生成 27 | 28 | **概要**: 29 | 本ファクターは、出来高と約定平均価格のランク相関性を分析し、市場トレンドの強弱を判断します。相関性のランクが高い場合、現在のトレンドが転換する可能性を示唆し、逆の場合はトレンドの継続を示唆します。トレンドフォロー戦略のシグナル生成に適しています。 30 | -------------------------------------------------------------------------------- /alpha/archive/alpha16/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#16: 最高价与成交量排名协方差反转 2 | 3 | **公式**: `(-1 * rank(covariance(rank(high), rank(volume), 5)))` 4 | 5 | **核心逻辑**: 6 | 1. 对每日最高价和成交量进行横截面排名。 7 | 2. 计算每只股票过去5日"最高价排名"与"成交量排名"序列的协方差。 8 | 3. 对此协方差进行横截面排名,然后乘以-1。 9 | 10 | **解读**: 11 | Alpha#16 寻找"最高价排名"和"成交量排名"在过去5天内呈负相关或弱正相关的股票。因子值越高,表明价量配合越差(或背离越明显),且这种关系在全市场中相对突出。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101の量的要因の解釈|Alpha#16:最高値・出来高ランキング共分散リバーサル 18 | 19 | **数式**: `(-1 * rank(covariance(rank(high), rank(volume), 5)))` 20 | 21 | **コアロジック**: 22 | 1. 毎日の最高値と出来高をクロスセクションでランキングします。 23 | 2. 各銘柄の過去5日間の「最高値ランキング」と「出来高ランキング」系列の共分散を計算します。 24 | 3. この共分散をクロスセクションでランキングし、-1を乗じます。 25 | 26 | **解釈**: 27 | Alpha#16は、過去5日間で「最高値ランキング」と「出来高ランキング」が負の相関または弱い正の相関を示す銘柄を探します。つまり、ファクター値が高いほど、価格(最高値)と出来高の連携が悪い(または乖離がより明確である)ことを示し、その関係が市場全体で相対的に顕著であることを意味します。 -------------------------------------------------------------------------------- /alpha/alpha39/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#39 复合因子策略 2 | 3 | **因子公式:** `((-1 * rank((delta(close, 7) * (1 - rank(decay_linear((volume / adv20), 9)))))) * (1 + rank(sum(returns, 250))))` 4 | 5 | Alpha#39 旨在识别价格变化强劲但不受异常成交量过度影响,并由强劲长期正收益放大的股票。 6 | 7 | 1. **动量与成交量调整 (`(-1 * rank((delta(close, 7) * (1 - rank(decay_linear((volume / adv20), 9))))))`)**: 捕捉短期价格动量,并剔除掉由过高异常成交量驱动的部分,然后进行反向排名,旨在寻找在这些条件下的低排名(更负值)股票。 8 | 2. **长期收益持续性 (`(1 + rank(sum(returns, 250)))`)**: 衡量过去250个交易日的总收益率,并进行排名和正向缩放,旨在识别具有长期上涨趋势的股票。 9 | 3. **乘积**: 将两者相乘,旨在放大那些既有特定动量-成交量特征又兼具强劲长期收益的股票的信号。 10 | 11 | **预期效果:** 识别出在剔除噪音后短期动量良好,且同时具有长期积极收益持续性的股票,适用于寻找高质量的趋势跟踪或反转机会。 12 | 13 | ## 数据要求 14 | 15 | * `close`: 收盘价。 16 | * `volume`: 成交量。 17 | * `returns`: 收益率。 18 | 19 | ## 输出 20 | 21 | 生成 `alpha39_results.csv` 文件,其中包含计算出的 `alpha39` 值和相关的中间列,所有数值均保留两位小数。原始数据列也会保留。`alpha39` 列为 `NaN` 的行将不被写入。 22 | -------------------------------------------------------------------------------- /alpha/alpha40/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#40 波动率与相关性反转策略 2 | 3 | **因子公式:** `((-1 * rank(stddev(high, 10))) * correlation(high, volume, 10))` 4 | 5 | Alpha#40 是一个旨在利用资产波动性与价量关系进行反转交易的因子。其核心思想是,高波动性与高价量正相关性同时出现,可能预示着趋势的衰竭或反转,因此构成一个负面(做空)信号。 6 | 7 | 1. 反转的波动率排名 (`-1 * rank(stddev(high, 10))`): 此部分对资产的短期(10日)价格波动率进行排名,然后取负。这意味着策略偏好低波动率的资产(给予更高分),而惩罚高波动率的资产(给予更低分)。 8 | 2. 价量相关性 (`correlation(high, volume, 10)`): 此部分衡量资产的最高价与成交量在短期(10日)内的相关性。正相关(价涨量增)通常被视为趋势健康的标志,但在此策略中与其他部分结合,可能被解读为过热信号。 9 | 3. 乘积: 将上述两个部分相乘。当一个资产波动率高(`-1 * rank` 为大的负数)且价量正相关时,最终的 Alpha 值会是一个较大的负数,构成一个强烈的卖出或做空信号。反之,当价量为负相关时,可能会产生正的 Alpha 值,尤其是在高波动率的情况下。 10 | 11 | 预期效果: 识别出那些价格波动剧烈且成交量跟随价格上涨(可能预示着非理性繁荣或趋势末端)的资产,并将其作为潜在的做空目标。 12 | 13 | ## 数据要求 14 | 15 | * `high`: 每日最高价。 16 | * `volume`: 每日成交量。 17 | 18 | ## 输出 19 | 20 | 生成 `alpha40_results.csv` 文件,其中包含计算出的 `alpha40` 值及其中间列(如 `stddev_high_10`, `rank_stddev_high_10`, `corr_high_volume_10`),所有数值均保留两位小数。`alpha40` 列为 `NaN` 的行将被剔除。 21 | -------------------------------------------------------------------------------- /alpha/archive/alpha17/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#17 多因子组合策略 2 | 3 | **公式**: `(((-1 * rank(ts_rank(close, 10))) * rank(delta(delta(close, 1), 1))) * rank(ts_rank((volume / adv20), 5)))` 4 | 5 | **核心逻辑**: 6 | 该因子通过结合三个部分的截面排名乘积来识别潜在的投资机会: 7 | 8 | 1. **反转的价格趋势强度**: 捕捉近期价格趋势在市场中相对较弱(或表现出反转信号)的资产。 9 | 2. **价格变化加速度**: 捕捉价格变动速度最快的资产。 10 | 3. **成交量爆发强度**: 捕捉近期成交量显著放大且在市场中表现突出的资产。 11 | 12 | 综合来看,Alpha#17 旨在寻找那些同时展现出价格趋势反转迹象、快速的价格变化以及显著成交量爆发的资产。 13 | 14 | --- 15 | 16 | ### 日本語訳 17 | 18 | 101の量的要因の解釈|Alpha#17 マルチファクター組み合わせ戦略 19 | 20 | **数式**: `(((-1 * rank(ts_rank(close, 10))) * rank(delta(delta(close, 1), 1))) * rank(ts_rank((volume / adv20), 5)))` 21 | 22 | **コアロジック**: 23 | このファクターは、3つの主要コンポーネントのクロスセクションランキングの積を組み合わせることで、潜在的な投資機会を特定します: 24 | 25 | 1. **反転した価格トレンドの強さ**: 最近の価格トレンドが市場で比較的弱い(または反転シグナルを示している)資産を捉えます。 26 | 2. **価格変動の加速度**: 価格変動が最も速い資産を捉えます。 27 | 3. **出来高の爆発的な強さ**: 最近の出来高が著しく増加し、市場で際立っている資産を捉えます。 28 | 29 | 総合的に、Alpha#17は、価格トレンドの反転の兆候、急速な価格変動、および顕著な出来高の爆発を同時に示す資産を見つけることを目的としています。 30 | -------------------------------------------------------------------------------- /alpha/archive/alpha21/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#21 均值-波动率条件反转 2 | 3 | **公式**: `((((sum(close, 8) / 8) + stddev(close, 8)) < (sum(close, 2) / 2)) ? (-1) : (((sum(close, 2) / 2) < ((sum(close, 8) / 8) - stddev(close, 8))) ? 1 : (((1 < (volume / adv20)) || ((volume / adv20) == 1)) ? 1 : -1)))` 4 | 5 | **核心逻辑**: 6 | - 若短期均价高于均值带宽,预期回落(-1); 7 | - 若短期均价低于均值带宽,预期反弹(+1); 8 | - 否则看量能,量大则多(+1),量小则空(-1)。 9 | 10 | **概述**: 11 | 本因子结合短期均值、波动率与成交量,动态判断价格的超买超卖与量能驱动,适合捕捉短线反转和量能异动信号。信号简洁,便于与其他因子叠加。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101のクオンツファクター解説|Alpha#21 平均・ボラティリティ条件付きリバーサル 18 | 19 | **数式**: `((((sum(close, 8) / 8) + stddev(close, 8)) < (sum(close, 2) / 2)) ? (-1) : (((sum(close, 2) / 2) < ((sum(close, 8) / 8) - stddev(close, 8))) ? 1 : (((1 < (volume / adv20)) || ((volume / adv20) == 1)) ? 1 : -1)))` 20 | 21 | **コアロジック**: 22 | - 短期平均がバンド上限を超えたら下落予想(-1) 23 | - 短期平均がバンド下限を下回れば反発予想(+1) 24 | - それ以外は出来高で判定、多ければ買い(+1)、少なければ売り(-1) 25 | 26 | **概要**: 27 | 本ファクターは短期平均・ボラティリティ・出来高を組み合わせ、短期の過熱感や出来高変動を捉えます。シグナルはシンプルで、他のファクターとの併用にも適しています。 -------------------------------------------------------------------------------- /alpha/archive/alpha7/cast.md: -------------------------------------------------------------------------------- 1 | **解读101个量化因子|Alpha#7 反转因子** 2 | 3 | **公式**: `((adv20 < volume) ? ((-1 * ts_rank(abs(delta(close, 7)), 60)) * sign(delta(close, 7))) : (-1*1))` 4 | 5 | **核心逻辑**: 6 | 7 | 1. **交易量激增时**: 若当日成交量(`volume`)大于过去20日平均成交量(`adv20`),则启用反转逻辑。 8 | * 反转逻辑: `-1 * sign(过去7日价格变动) * (过去7日价格绝对变动幅度在过去60日中的排名)`。 9 | * 即,若近期上涨且涨幅大,则信号为负;若近期下跌且跌幅大,则信号为正。 10 | 2. **交易量未激增时**: 策略固定输出 `-1`。 11 | 12 | **解读**: Alpha#7 在市场活跃(成交量放大)时,捕捉近期价格大幅度变动后的反转机会。若市场不活跃,则不认为有反转。 13 | 14 | --- 15 | 16 | ### 日本語訳 17 | 18 | **101の量的要因の解釈|Alpha#7 リバーサルファクター** 19 | 20 | **数式**: `((adv20 < volume) ? ((-1 * ts_rank(abs(delta(close, 7)), 60)) * sign(delta(close, 7))) : (-1*1))` 21 | 22 | **コアロジック**: 23 | 24 | 1. **取引量急増時**: 当日の取引量 (`volume`) が過去20日間の平均取引量 (`adv20`) より大きい場合、リバーサルロジックを有効にします。 25 | * リバーサルロジック: `-1 * sign(過去7日間の価格変動) * (過去7日間の価格絶対変動幅の過去60日間におけるランキング)`。 26 | * つまり、最近上昇し、上昇幅が大きい場合はシグナルは負となり、最近下落し、下落幅が大きい場合はシグナルは正となります。 27 | 2. **取引量が急増していない場合**: 戦略は固定で `-1` を出力します。 28 | 29 | **解釈**: Alpha#7 は、市場が活況(取引量が増加)な時に、最近の価格の大幅な変動後のリバーサルの機会を捉えます。市場が活況でない場合は、リバーサルはないと見なします。 30 | -------------------------------------------------------------------------------- /alpha/archive/alpha18/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#18: 波动、趋势与相关性的综合排名 2 | 3 | **公式**: `(-1 * rank(((stddev(abs((close - open)), 5) + (close - open)) + correlation(close, open, 10))))` 4 | 5 | **核心逻辑**: 6 | 该因子通过结合三个部分的综合指标来识别潜在的投资机会: 7 | 8 | 1. **日内振幅的波动性**: 捕捉近期价格日内波动的稳定性,通过计算日内振幅(收盘价与开盘价之差的绝对值)的5日标准差来衡量。 9 | 2. **日内价格趋势**: 直接通过当日收盘价与开盘价的差值来衡量价格变动的方向和幅度。 10 | 3. **价格联动性**: 通过计算10日开盘价与收盘价的相关系数来衡量价格的短期联动关系。 11 | 12 | 综合来看,Alpha#18 旨在寻找那些近期日内波动较小、价格趋势温和、开收盘价联动性较弱的资产。这种组合可能有助于识别出相对稳定且预测性较强的交易机会。 13 | 14 | --- 15 | 16 | ### 日本語訳 17 | 18 | 101の量的要因の解釈|Alpha#18:ボラティリティ、トレンド、相関の総合ランキング 19 | 20 | **数式**: `(-1 * rank(((stddev(abs((close - open)), 5) + (close - open)) + correlation(close, open, 10))))` 21 | 22 | **コアロジック**: 23 | このファクターは、3つの主要な要素を組み合わせて潜在的な投資機会を特定します: 24 | 25 | 1. **日中のボラティリティ**: 終値と始値の差の絶対値の5日間標準偏差を計算することで、最近の価格の日中変動の安定性を捉えます。 26 | 2. **日中価格トレンド**: 当日の終値と始値の差を直接計算することで、価格変動の方向と大きさを測定します。 27 | 3. **価格の連動性**: 10日間の始値と終値の相関係数を計算することで、価格の短期的な連動関係を測定します。 28 | 29 | 総合的に見て、Alpha#18は、最近の日中変動が小さく、価格トレンドが穏やかで、始値と終値の連動性が比較的弱い資産を探すことを目的としています。この組み合わせは、比較的安定して予測可能な取引機会を特定するのに役立つ可能性があります。 -------------------------------------------------------------------------------- /alpha/archive/alpha9/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#9 条件趋势策略 2 | 3 | **公式**: `((0 < ts_min(delta(close, 1), 5)) ? delta(close, 1) : ((ts_max(delta(close, 1), 5) < 0) ? delta(close, 1) : (-1 * delta(close, 1))))` 4 | 5 | **核心逻辑**: 根据过去5天的日价格变动判断市场状态: 6 | 7 | 1. **持续上涨**: 若过去5天每日最低涨幅 > 0,则跟随当日趋势 (`delta(close, 1)`). 8 | 2. **持续下跌**: 若过去5天每日最高涨幅 < 0 (即每天都跌),则跟随当日趋势 (`delta(close, 1)`). 9 | 3. **震荡市**: 其他情况(有涨有跌),则反转当日趋势 (`-1 * delta(close, 1)`). 10 | 11 | **解读**: 在短期趋势明朗(全涨或全跌)时顺势而为;在短期趋势不明(震荡)时则采取反向操作。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101の量的要因の解釈|Alpha#9 条件付きトレンド戦略 18 | 19 | **数式**: `((0 < ts_min(delta(close, 1), 5)) ? delta(close, 1) : ((ts_max(delta(close, 1), 5) < 0) ? delta(close, 1) : (-1 * delta(close, 1))))` 20 | 21 | **コアロジック**: 過去5日間の日次価格変動に基づいて市場の状態を判断します: 22 | 23 | 1. **継続的な上昇**: 過去5日間の毎日の最低上昇率 > 0 の場合、当日のトレンドに従います (`delta(close, 1)`)。 24 | 2. **継続的な下落**: 過去5日間の毎日の最高上昇率 < 0 (つまり毎日下落) の場合、当日のトレンドに従います (`delta(close, 1)`)。 25 | 3. **レンジ相場**: その他の状況(上昇と下落の両方がある場合)、当日のトレンドを反転させます (`-1 * delta(close, 1)`)。 26 | 27 | **解釈**: 短期的なトレンドが明確な場合(全て上昇または全て下落)はトレンドに従い、短期的なトレンドが不明確な場合(レンジ相場)は逆の操作を行います。 28 | -------------------------------------------------------------------------------- /alpha/archive/alpha28/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#28: 成交量最低价相关性与价格中枢偏离的标准化 2 | 3 | **原始公式**: 4 | 5 | ``` 6 | scale(((correlation(adv20, low, 5) + ((high + low) / 2)) - close)) 7 | ``` 8 | 9 | **核心逻辑**: 10 | 该因子首先计算20日平均成交量 (`adv20`) 和当日的中间价 (`(high + low) / 2`)。然后,计算 `adv20` 与最低价 `low` 在过去5日的相关系数。将此相关系数与中间价相加,再减去当日收盘价 `close`。最后,对得到的结果进行横截面标准化 (`scale`)。 11 | 12 | **解读**: 13 | 14 | Alpha#28 结合了成交量动态(20日平均成交量与最低价的5日相关性)、价格日内位置(中间价与收盘价的差值),旨在寻找那些综合表现(经过横截面标准化后)偏离市场均值的股票。因子值为正,通常表示该股票在特定模式下表现相对较强;为负则表示相对较弱。 15 | 16 | --- 17 | 18 | ### 日本語訳 19 | 20 | # 101の量的要因の解釈|Alpha#28: 出来高・安値相関と価格中心からの乖離の標準化 21 | 22 | **数式**: 23 | 24 | ``` 25 | scale(((correlation(adv20, low, 5) + ((high + low) / 2)) - close)) 26 | ``` 27 | 28 | **コアロジック**: 29 | このファクターは、まず20日平均出来高(`adv20`)と当日の中心価格(`(高値 + 安値) / 2`)を計算します。次に、`adv20`と安値(`low`)の過去5日間の相関係数を計算します。この相関係数を中心価格に加算し、そこから当日の終値(`close`)を減算します。最後に、得られた結果をクロスセクションで標準化(`scale`)します。 30 | 31 | **解釈**: 32 | Alpha#28は、出来高の動態(20日平均出来高と安値の5日間相関)、日中の価格位置(中心価格と終値の差)を組み合わせ、その総合的なパフォーマンス(クロスセクション標準化後)が市場平均から乖離している銘柄を探すことを目的としています。ファクター値が正の場合、通常、その銘柄が特定のパターンにおいて相対的に強いパフォーマンスを示していることを意味し、負の場合は相対的に弱いことを示します。 33 | -------------------------------------------------------------------------------- /alpha/archive/alpha11/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#11 VWAP、收盘价差值与成交量变动 2 | 3 | **公式**: `((rank(ts_max((vwap - close), 3)) + rank(ts_min((vwap - close), 3))) * rank(delta(volume, 3)))` 4 | 5 | **核心逻辑**: 6 | 7 | 1. **价格偏离极值**: 计算过去3天内"VWAP与收盘价差值" (`vwap - close`) 的最大值和最小值,并分别对其进行截面排名 (`rank`)。 8 | 2. **成交量变动**: 计算过去3天成交量 (`volume`) 的变化 (`delta`),并对其进行截面排名 (`rank`)。 9 | 3. **综合信号**: 将步骤1中的两个排名相加,然后乘以步骤2中的排名。 10 | 11 | **解读**: 该因子试图捕捉那些近期价格偏离其日内成交均线达到某种极端状态(最大和最小差值的排名之和较高),并且成交量也发生显著变化(成交量变化排名较高)的资产。它综合考虑了价格短期波动的极端性和成交量变化的显著性。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101の量的要因の解釈|Alpha#11 VWAP、終値の差と出来高の変動 18 | 19 | **数式**: `((rank(ts_max((vwap - close), 3)) + rank(ts_min((vwap - close), 3))) * rank(delta(volume, 3)))` 20 | 21 | **コアロジック**: 22 | 23 | 1. **価格乖離の極値**: 過去3日間の「VWAPと終値の差」 (`vwap - close`) の最大値と最小値を計算し、それぞれをクロスセクションでランク付けします (`rank`)。 24 | 2. **出来高の変動**: 過去3日間の出来高 (`volume`) の変化 (`delta`) を計算し、クロスセクションでランク付けします (`rank`)。 25 | 3. **総合シグナル**: ステップ1の2つのランクを加算し、その結果にステップ2のランクを乗じます。 26 | 27 | **解釈**: このファクターは、最近の価格が日中の出来高加重平均線から何らかの極端な状態に乖離し(最大差と最小差のランクの合計が高い)、かつ出来高も顕著に変化した(出来高変化のランクが高い)資産を捉えようとします。価格の短期的な変動の極端さと出来高変化の顕著性を総合的に考慮しています。 -------------------------------------------------------------------------------- /alpha/archive/alpha19/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#19: 趋势反转与长期回报的动态平衡 2 | 3 | **公式**: `((-1 * sign(((close - delay(close, 7)) + delta(close, 7)))) * (1 + rank((1 + sum(returns, 250)))))` 4 | 5 | **核心逻辑**: 6 | 该因子通过结合短期趋势反转信号和长期回报排名来构建投资策略: 7 | 8 | 1. **趋势反转信号**: 通过对7日价格变动的符号取反来捕捉短期反转机会。当价格在7天内上涨时,给出负向信号;下跌时,给出正向信号。 9 | 2. **长期回报增强**: 基于过去250天(约一年)的累计回报进行截面排名,并将排名结果转化为放大因子。回报表现越好,放大效应越强。 10 | 11 | 这种设计试图在短期反转交易和长期动量效应之间取得平衡。当一个资产经历了良好的长期表现后出现短期回调时,因子会给出较强的正向信号;反之,如果一个长期表现优异的资产继续保持短期上涨,则给出较强的负向信号。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101の量的要因の解釈|Alpha#19:トレンド反転と長期リターンのダイナミックバランス 18 | 19 | **数式**: `((-1 * sign(((close - delay(close, 7)) + delta(close, 7)))) * (1 + rank((1 + sum(returns, 250)))))` 20 | 21 | **コアロジック**: 22 | このファクターは、短期トレンド反転シグナルと長期リターンランキングを組み合わせて投資戦略を構築します: 23 | 24 | 1. **トレンド反転シグナル**: 7日間の価格変動の符号を反転させることで、短期的な反転機会を捉えます。価格が7日間で上昇した場合は負のシグナル、下落した場合は正のシグナルを生成します。 25 | 2. **長期リターン強化**: 過去250日間(約1年)の累積リターンのクロスセクションランキングを行い、そのランキング結果を増幅因子に変換します。リターンのパフォーマンスが良いほど、増幅効果が強くなります。 26 | 27 | この設計は、短期的な反転取引と長期的なモメンタム効果のバランスを取ることを目指しています。長期的に良好なパフォーマンスを示した資産が短期的な調整を経験した場合、強い正のシグナルを生成し、逆に長期的に優れたパフォーマンスを示す資産が短期的な上昇を続ける場合は、強い負のシグナルを生成します。 -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | av==13.1.0 2 | beautifulsoup4==4.13.4 3 | certifi==2025.4.26 4 | cffi==1.17.1 5 | charset-normalizer==3.4.2 6 | click==8.2.1 7 | cloup==3.0.7 8 | coloredlogs==15.0.1 9 | cryptography==45.0.3 10 | Cython==3.1.1 11 | decorator==5.2.1 12 | flatbuffers==25.2.10 13 | glcontext==3.0.0 14 | humanfriendly==10.0 15 | idna==3.10 16 | isosurfaces==0.1.2 17 | magika==0.6.2 18 | manim==0.19.0 19 | ManimPango==0.6.0 20 | mapbox_earcut==1.0.3 21 | markdown-it-py==3.0.0 22 | markdownify==1.1.0 23 | markitdown==0.1.1 24 | mdurl==0.1.2 25 | moderngl==5.12.0 26 | moderngl-window==3.1.1 27 | mpmath==1.3.0 28 | networkx==3.4.2 29 | numpy==2.2.6 30 | onnxruntime==1.22.0 31 | packaging==25.0 32 | pandas==2.2.3 33 | pdfminer.six==20250506 34 | pillow==11.2.1 35 | protobuf==6.31.0 36 | pycairo==1.28.0 37 | pycparser==2.22 38 | pydub==0.25.1 39 | pyglet==2.1.6 40 | pyglm==2.8.2 41 | Pygments==2.19.1 42 | pyobjc-core==11.0 43 | pyobjc-framework-Cocoa==11.0 44 | python-dateutil==2.9.0.post0 45 | python-dotenv==1.1.0 46 | pytz==2025.2 47 | requests==2.32.3 48 | rich==14.0.0 49 | scipy==1.15.3 50 | screeninfo==0.8.1 51 | six==1.17.0 52 | skia-pathops==0.8.0.post2 53 | soupsieve==2.7 54 | srt==3.5.3 55 | svgelements==1.9.6 56 | sympy==1.14.0 57 | tqdm==4.67.1 58 | typing_extensions==4.13.2 59 | tzdata==2025.2 60 | urllib3==2.4.0 61 | watchdog==6.0.0 62 | -------------------------------------------------------------------------------- /alpha/archive/alpha20/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子| Alpha#20 开盘价与昨日关键点位差异的综合排名 2 | 3 | ## 因子公式 4 | 5 | ```python 6 | Alpha#20 = (((-1 * rank((open - delay(high, 1)))) * rank((open - delay(close, 1)))) * rank((open - delay(low, 1)))) 7 | ``` 8 | 9 | ## 核心逻辑 10 | 11 | 该因子通过比较当日开盘价与昨日(前一日)的最高价、收盘价和最低价的差异,并对这些差异进行排名后相乘,来评估开盘情况。 12 | 13 | ### 主要组成 14 | 15 | 1. `-1 * rank(open - delay(high, 1))`:开盘价与昨日最高价差异的排名(取负)。 16 | 2. `rank(open - delay(close, 1))`:开盘价与昨日收盘价差异的排名。 17 | 3. `rank(open - delay(low, 1))`:开盘价与昨日最低价差异的排名。 18 | 19 | ## 总结 20 | 21 | Alpha#20 通过捕捉开盘价与昨日关键价格点(最高、收盘、最低)的相对位置关系,并将其排名相乘,来综合评估当日开盘的强度和潜在方向。因子的负号部分暗示了对向上突破昨日高点行为的逆向观点。 22 | 23 | --- 24 | 25 | # Alpha#20:始値と昨日の主要価格ポイントの差異の総合ランキング 26 | 27 | ## 計算式 28 | 29 | ```python 30 | Alpha#20 = (((-1 * rank((open - delay(high, 1)))) * rank((open - delay(close, 1)))) * rank((open - delay(low, 1)))) 31 | ``` 32 | 33 | ## コアロジック 34 | 35 | このファクターは、当日の始値と昨日(前日)の最高値、終値、最安値との差を比較し、これらの差をランキングして乗算することで、寄り付き状況を評価します。 36 | 37 | ### 主な構成要素 38 | 39 | 1. `-1 * rank(open - delay(high, 1))`:始値と昨日の最高値の差のランキング(負の値を取る)。 40 | 2. `rank(open - delay(close, 1))`:始値と昨日の終値の差のランキング。 41 | 3. `rank(open - delay(low, 1))`:始値と昨日の最安値の差のランキング。 42 | 43 | ## まとめ 44 | 45 | Alpha#20は、始値と昨日の主要な価格ポイント(最高値、終値、最安値)との相対的な位置関係を捉え、それらのランキングを乗算することにより、当日の寄り付きの強さと潜在的な方向性を総合的に評価します。因子の一部が負の符号を持つことは、昨日高値を上抜ける動きに対する逆張りの視点を示唆しています。 46 | -------------------------------------------------------------------------------- /alpha/archive/alpha23/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#23 高价与移动平均的条件差分策略 2 | 3 | **公式**: `(((sum(high, 20) / 20) < high) ? (-1 * delta(high, 2)) : 0)` 4 | 5 | **核心逻辑**: 6 | - 监测最高价与其20日移动平均的关系 7 | - 在价格突破均线时,通过2日差分的负值生成信号 8 | - 在价格低于均线时保持中性 9 | 10 | **概述**: 11 | 本因子通过观察价格突破后的短期变动来捕捉可能的反转机会。适合用于高波动性市场的短线交易,特别是在价格突破后的获利回吐阶段。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101のクオンツファクター解説|Alpha#23 高値と移動平均の条件付き差分戦略 18 | 19 | **数式**: `(((sum(high, 20) / 20) < high) ? (-1 * delta(high, 2)) : 0)` 20 | 21 | **コアロジック**: 22 | - 高値と20日移動平均の関係を監視 23 | - 価格がラインを突破した時、2日間の差分のマイナス値でシグナルを生成 24 | - 価格が移動平均以下の時は中立を維持 25 | 26 | **概要**: 27 | 本ファクターは価格突破後の短期的な変動を観察し、反転の機会を捉えます。高ボラティリティ市場での短期取引、特に価格突破後の利益確定フェーズに適しています。 28 | 29 | ## 策略描述 30 | 31 | Alpha#23 = (((sum(high, 20) / 20) < high) ? (-1 * delta(high, 2)) : 0) 32 | 33 | ## 核心思想 34 | 35 | 1. 这是一个基于价格突破的条件反转策略 36 | 2. 策略仅在价格突破20日均线时生效 37 | 3. 通过观察2日价格变化的反向信号来预测短期走势 38 | 39 | ## 信号特点 40 | 41 | 1. 突破后继续上涨 → 负信号(预期回调) 42 | 2. 突破后价格回落 → 正信号(预期反弹) 43 | 3. 未突破均线时 → 零信号(保持中性) 44 | 45 | ## 应用场景 46 | 47 | 1. 适用于高波动性市场 48 | 2. 可用于捕捉价格突破后的短期反转机会 49 | 3. 适合日内或短线交易策略 50 | 51 | ## 优势 52 | 53 | 1. 逻辑简单清晰 54 | 2. 计算成本低 55 | 3. 有明确的信号触发条件 56 | 57 | ## 局限性 58 | 59 | 1. 需要至少20天的历史数据 60 | 2. 可能错过未突破均线时的交易机会 61 | 3. 在震荡市场中可能产生过多假信号 62 | 63 | ## 风险提示 64 | 65 | 1. 策略依赖价格突破,可能受到虚假突破的影响 66 | 2. 短期反转信号可能与长期趋势相悖 67 | 3. 建议与其他技术指标结合使用 68 | -------------------------------------------------------------------------------- /alpha/archive/alpha10/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#10: 条件趋势策略 2 | 3 | **公式**: `rank(((0 < ts_min(delta(close, 1), 4)) ? delta(close, 1) : ((ts_max(delta(close, 1), 4) < 0) ? delta(close, 1) : (-1 * delta(close, 1)))))` 4 | 5 | **核心逻辑**: 6 | 7 | 1. **持续上涨?**: 若过去4天每日价格均上涨 (`ts_min(delta(close,1),4) > 0`),则取今日价格变动 `delta(close,1)` (趋势跟随)。 8 | 2. **持续下跌?**: 否则,若过去4天每日价格均下跌 (`ts_max(delta(close,1),4) < 0`),则取今日价格变动 `delta(close,1)` (趋势跟随)。 9 | 3. **盘整/波动?**: 否则 (即过去4天有涨有跌),则取今日价格变动的相反数 `-1 * delta(close,1)` (反转)。 10 | 4. **排名**: 对上述条件逻辑产生的值进行横截面排名,得到最终 Alpha。 11 | 12 | **解读**: 在短期趋势明朗(持续上涨或下跌)时,因子倾向于跟随趋势;在短期趋势不明朗(震荡)时,因子倾向于反转今日的日内变动。 13 | 14 | --- 15 | 16 | ### 日本語訳 17 | 18 | 101の量的要因の解釈|Alpha#10: 条件付きトレンド戦略 19 | 20 | **数式**: `rank(((0 < ts_min(delta(close, 1), 4)) ? delta(close, 1) : ((ts_max(delta(close, 1), 4) < 0) ? delta(close, 1) : (-1 * delta(close, 1)))))` 21 | 22 | **コアロジック**: 23 | 24 | 1. **継続的な上昇?**: 過去4日間、毎日の価格が上昇した場合 (`ts_min(delta(close,1),4) > 0`)、本日の価格変動 `delta(close,1)` を取ります(トレンドフォロー)。 25 | 2. **継続的な下落?**: そうでなければ、過去4日間、毎日の価格が下落した場合 (`ts_max(delta(close,1),4) < 0`)、本日の価格変動 `delta(close,1)` を取ります(トレンドフォロー)。 26 | 3. **横ばい/変動?**: そうでなければ(つまり過去4日間に上昇と下落があった場合)、本日の価格変動の逆数 `-1 * delta(close,1)` を取ります(リバーサル)。 27 | 4. **ランキング**: 上記の条件ロジックによって生成された値に対してクロスセクションランキングを行い、最終的なAlphaを取得します。 28 | 29 | **解釈**: 短期的なトレンドが明確な場合(継続的な上昇または下落)、ファクターはトレンドに従う傾向があります。短期的なトレンドが不明確な場合(横ばい)、ファクターは本日の日中変動を反転させる傾向があります。 30 | -------------------------------------------------------------------------------- /alpha/archive/alpha24/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#24 价格变化率与历史最小值的条件选择策略 2 | 3 | **公式**: `((((delta((sum(close, 100) / 100), 100) / delay(close, 100)) < 0.05) || ((delta((sum(close, 100) / 100), 100) / delay(close, 100)) == 0.05)) ? (-1 * (close - ts_min(close, 100))) : (-1 * delta(close, 3)))` 4 | 5 | **核心逻辑**: 6 | - 根据100日移动平均的变化率自动切换策略 7 | - 在低波动环境(变化率≤5%)关注价格与历史最低点的距离 8 | - 在高波动环境(变化率>5%)关注短期价格变化 9 | 10 | **概述**: 11 | 本因子通过市场环境的自动识别来选择合适的交易信号生成方式。在不同的市场条件下采用不同的策略,体现了较强的自适应性。适合用于长期投资,特别是在市场环境发生变化时。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101のクオンツファクター解説|Alpha#24 価格変化率と過去最安値の条件付き選択戦略 18 | 19 | **数式**: `((((delta((sum(close, 100) / 100), 100) / delay(close, 100)) < 0.05) || ((delta((sum(close, 100) / 100), 100) / delay(close, 100)) == 0.05)) ? (-1 * (close - ts_min(close, 100))) : (-1 * delta(close, 3)))` 20 | 21 | **コアロジック**: 22 | - 100日移動平均の変化率に基づき戦略を自動切り替え 23 | - 低ボラティリティ環境(変化率≤5%)では価格と過去最安値との距離に注目 24 | - 高ボラティリティ環境(変化率>5%)では短期的な価格変動に注目 25 | 26 | **概要**: 27 | 本ファクターは市場環境を自動的に識別し、適切な取引シグナル生成方法を選択します。異なる市場条件下で異なる戦略を採用し、高い適応性を示します。長期投資、特に市場環境の変化時に適しています。 28 | 29 | ## 应用场景 30 | 1. 适用于多种市场环境 31 | 2. 特别适合长期投资策略 32 | 3. 可用于市场环境的自动识别和策略切换 33 | 34 | ## 优势 35 | 1. 自适应性强 36 | 2. 综合考虑长短期因素 37 | 3. 具有市场环境识别能力 38 | 4. 风险控制机制内置(通过阈值设置) 39 | 40 | ## 局限性 41 | 1. 需要较长的历史数据(至少100天) 42 | 2. 可能在市场转折点反应滞后 43 | 3. 阈值(5%)的选择可能影响策略效果 44 | 4. 计算复杂度相对较高 45 | 46 | ## 风险提示 47 | 1. 策略在市场环境转换期可能表现不佳 48 | 2. 历史最低价参考可能在牛市中产生过多卖出信号 49 | 3. 短期反转信号可能与主趋势冲突 50 | 4. 建议结合其他技术指标和基本面分析使用 -------------------------------------------------------------------------------- /alpha/archive/alpha25/cast.md: -------------------------------------------------------------------------------- 1 | 解读101个量化因子|Alpha#25 多因子综合排名策略 2 | 3 | **公式**: `rank(((((-1 * returns) * adv20) * vwap) * (high - close)))` 4 | 5 | **核心逻辑**: 6 | - 结合回报率反转、成交量、价格水平和日内价格变动 7 | - 通过多个因子的乘积来强化信号 8 | - 最终通过排名来标准化不同资产间的信号强度 9 | 10 | **概述**: 11 | 本因子通过多维度指标的综合来捕捉市场机会,特别关注高流动性、价格回落和可能反转的资产。适合用于大规模资产组合的相对价值策略,尤其是在日内交易中。 12 | 13 | --- 14 | 15 | ### 日本語訳 16 | 17 | 101のクオンツファクター解説|Alpha#25 マルチファクター総合ランキング戦略 18 | 19 | **数式**: `rank(((((-1 * returns) * adv20) * vwap) * (high - close)))` 20 | 21 | **コアロジック**: 22 | - リターン反転、出来高、価格水準、日中価格変動を組み合わせ 23 | - 複数のファクターの積によりシグナルを強化 24 | - 最終的にランキングで異なる資産間のシグナル強度を標準化 25 | 26 | **概要**: 27 | 本ファクターは多次元指標の組み合わせにより市場機会を捉え、特に高流動性、価格下落、反転可能性のある資産に注目します。大規模資産ポートフォリオの相対価値戦略、特にデイトレードに適しています。 28 | 29 | ## 策略描述 30 | 31 | Alpha#25 = rank(((((-1 * returns) * adv20) * vwap) * (high - close))) 32 | 33 | ## 核心思想 34 | 35 | 1. 这是一个多因子综合排名策略 36 | 2. 通过多个市场指标的乘积来强化信号 37 | 3. 最终通过排名来标准化不同资产间的信号强度 38 | 39 | ## 信号特点 40 | 41 | 1. 回报率反转: 42 | * 负向回报率产生正信号 43 | * 体现均值回归思想 44 | 2. 成交量权重: 45 | * 高流动性资产信号更强 46 | * 增强策略可执行性 47 | 3. 价格结构: 48 | * 关注日内价格回落 49 | * VWAP提供价值锚定 50 | 51 | ## 应用场景 52 | 53 | 1. 适用于大规模资产组合 54 | 2. 适合日内交易策略 55 | 3. 特别适合高流动性市场 56 | 57 | ## 优势 58 | 59 | 1. 多维度信号合成 60 | 2. 自动标准化处理 61 | 3. 考虑交易实现性 62 | 4. 信号强度动态调整 63 | 64 | ## 局限性 65 | 66 | 1. 需要完整的市场数据 67 | 2. 对数据质量要求高 68 | 3. 计算相对复杂 69 | 4. 可能存在因子共线性 70 | 71 | ## 风险提示 72 | 73 | 1. 多因子可能相互抵消 74 | 2. 排名可能不稳定 75 | 3. 需要注意极端值处理 76 | 4. 建议进行因子正交化处理 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Alpha Mining Project 2 | 3 | 我们非常欢迎并感谢您对 Alpha Mining 项目的贡献!无论是报告错误、提交功能请求,还是直接贡献代码,您的帮助对我们都至关重要。 4 | 5 | ## 如何贡献 6 | 7 | ### 报告 Bug (Bug Reports) 8 | 9 | 如果您在项目中发现了 Bug,请通过以下方式告诉我们: 10 | 11 | - **检查现有问题**:在提交新的 Bug 报告之前,请先搜索现有的 [GitHub Issues](https://github.com/kuhung/alpha-mining/issues) ,确保该 Bug 尚未被报告。 12 | - **详细描述**:请提供尽可能详细的信息,包括: 13 | - Bug 发生的具体步骤。 14 | - 您期望的结果和实际发生的结果。 15 | - 您的操作系统、Python 版本以及相关库的版本。 16 | - 任何相关的错误信息或截图。 17 | 18 | ### 功能建议 (Feature Requests) 19 | 20 | 如果您有关于新功能或改进现有功能的建议: 21 | 22 | - **检查现有建议**:同样,请先搜索现有的 [GitHub Issues](https://github.com/kuhung/alpha-mining/issues) ,看看是否已有人提出类似的建议。 23 | - **清晰阐述**:请详细描述您建议的功能,以及它为什么对项目有益。 24 | 25 | ### 代码贡献 (Pull Requests) 26 | 27 | 我们欢迎任何形式的代码贡献,包括 Bug 修复和新功能实现。 28 | 29 | 1. **Fork 仓库**:将项目 Fork到您自己的 GitHub 账户下。 30 | 2. **创建分支**:从 `main` (或 `master`) 分支创建一个新的特性分支 (e.g., `git checkout -b feature/amazing-feature`) 或 Bug 修复分支 (e.g., `git checkout -b fix/bug-description`)。 31 | 3. **编码**:进行您的修改。请确保您的代码遵循项目的编码风格 (如果项目有定义的话)。 32 | 4. **测试**:如果适用,请为您的代码添加测试用例,并确保所有测试通过。 33 | 5. **Commit 信息**:请编写清晰、规范的 Commit 信息。 34 | 6. **Push 分支**:将您的分支 Push 到您 Fork 的仓库 (`git push origin feature/amazing-feature`)。 35 | 7. **创建 Pull Request (PR)**:回到原始项目仓库,针对 `main` (或 `master`) 分支创建一个 Pull Request。 36 | - 在 PR 描述中,请清晰地说明您的修改内容和目的。 37 | - 如果您的 PR 是为了解决某个特定的 Issue,请在描述中链接该 Issue (e.g., "Closes #123")。 38 | 39 | 40 | ## 问题与讨论 41 | 42 | 如果您有任何疑问或想讨论项目相关内容,欢迎通过 [GitHub Issues](https://github.com/kuhung/alpha-mining/issues) 与我们交流。 43 | 44 | 再次感谢您的贡献! 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alpha 策略研究与可视化项目 2 | 3 | 本项目通过 Alpha 策略计算、大语言模型 (LLM) 及 Manim 动画引擎,实现策略研发、评估至可视化的流程。 4 | 5 | 项目可视化样例:https://www.bilibili.com/video/BV1YC7Hz5EJ6 6 | 7 | ## 核心流程 8 | 9 | 1. **数据准备**: Alpha 策略原始数据位于 `data/` (mock 数据)。 10 | 2. **策略计算与文档**: 在各 `alpha/alpha_/` 目录下,其 `README` 文件包含或引用计算逻辑,执行后生成结果与说明。 11 | 3. **LLM 交互**: 提取策略 `README` 中的核心信息,交由 LLM 生成 Manim 动画脚本。 12 | 4. **Manim 脚本存储**: LLM 生成的 `.py` 脚本保存至 `manim/scripts/`。 13 | 5. **Manim 视频渲染**: 使用 Manim 渲染脚本,如 `manim -qk manim/scripts/script_name.py SceneName`。视频保存至 `manim/outputs/`。 14 | 6. **结果整合**: 完整产出包括策略源文件、计算结果、Manim 脚本和视频,可被 `doc/` 引用。 15 | 16 | ## 环境设置 17 | 18 | 1. 克隆仓库并进入目录。 19 | 2. 创建并激活 Python 虚拟环境 (推荐 Python 3.12): 20 | 21 | ```bash 22 | python3 -m venv .venv 23 | source .venv/bin/activate 24 | ``` 25 | 3. 安装依赖: 26 | 27 | - 推荐使用 [uv](https://github.com/astral-sh/uv)(更快的 Python 包管理器): 28 | ```bash 29 | pip install uv 30 | uv pip install -r requirements.txt 31 | ``` 32 | - 或使用传统 pip(若有 `requirements.txt`): 33 | ```bash 34 | pip install -r requirements.txt 35 | ``` 36 | 37 | (否则根据需要手动安装 `manim`, `pandas`, `numpy` 等) 38 | 39 | ## 流程最佳实践 40 | 41 | 1. 在doc/目录下,选取需要实现的alpha因子 42 | 1. 进入对话框 43 | 2. 选取任意两个已实现的alpha因子 44 | 3. 输入提示词 45 | 2. 生成readme文件、python文件后,执行python文件,获得数据详情 46 | 3. 选择生产的数据,输入提示词更新readme文档 47 | 4. 根据readme文档,选择已经生成的可视化脚本,输入提示词 48 | 5. 微调可视化脚本,配音乐上传 49 | 50 | ## 目录结构 51 | 52 | * `.venv/`: Python 虚拟环境。 53 | * `alpha/`: Alpha 策略子目录。 54 | * `alpha_strategy_name/README.md`: 策略描述、计算逻辑、结果。 55 | * `data/`: **Mock 数据**。 56 | * `doc/`: 项目文档。 57 | * `manim/`: Manim 相关。 58 | * `scripts/`: Manim Python 脚本。 59 | * `outputs/`: Manim 输出 (视频/图片)。 60 | * `README.md`: 本项目说明。 61 | 62 | ## 注意 63 | 64 | * **Mock 数据**: 所有计算和演示基于 mock 数据。 65 | 66 | 欢迎使用本项目! 67 | -------------------------------------------------------------------------------- /alpha/archive/alpha8/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | # 读取数据 4 | def load_data(): 5 | # 假设数据存储在data文件夹下的某个CSV文件中 6 | data_path = '../../data/mock_data.csv' 7 | df = pd.read_csv(data_path) 8 | # 确保 'date' 列是 datetime 对象,以便正确排序和分组 9 | df['date'] = pd.to_datetime(df['date']) 10 | return df 11 | 12 | # 计算Alpha#8 13 | def calculate_alpha8(df): 14 | # 确保数据按 asset_id 和 date 排序 15 | df = df.sort_values(by=['asset_id', 'date']).reset_index(drop=True) 16 | 17 | # 按 asset_id 分组计算时间序列相关的指标 18 | df['sum_open_5'] = df.groupby('asset_id')['open'].rolling(window=5).sum().reset_index(level=0, drop=True).round(2) 19 | df['sum_returns_5'] = df.groupby('asset_id')['returns'].rolling(window=5).sum().reset_index(level=0, drop=True).round(2) 20 | 21 | df['open_returns_product'] = (df['sum_open_5'] * df['sum_returns_5']).round(2) 22 | 23 | # 按 asset_id 分组进行 shift 操作 24 | df['delayed_product'] = df.groupby('asset_id')['open_returns_product'].transform(lambda x: x.shift(10)).round(2) 25 | 26 | df['product_diff'] = (df['open_returns_product'] - df['delayed_product']).round(2) 27 | 28 | # 按 date 分组进行截面排名 29 | df['rank_diff'] = df.groupby('date')['product_diff'].rank(method='average', ascending=True, pct=True, na_option='keep') 30 | 31 | # 对排名结果取负值,得到Alpha#8,并保留两位小数 32 | df['alpha8'] = (-1 * df['rank_diff']).round(2) 33 | 34 | return df 35 | 36 | # 保存结果 37 | def save_results(df): 38 | output_path = 'alpha8_results.csv' 39 | df.to_csv(output_path, index=False) 40 | print(f"结果已保存到 {output_path}") 41 | 42 | # 主函数 43 | def main(): 44 | # 加载数据 45 | df = load_data() 46 | 47 | # 计算Alpha#8 48 | df = calculate_alpha8(df) 49 | 50 | # 保存结果 51 | save_results(df) 52 | 53 | if __name__ == "__main__": 54 | main() -------------------------------------------------------------------------------- /alpha/archive/alpha29/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#29: 复杂价格变换与延迟负收益时序排名的加和 2 | 3 | **原始公式**: 4 | 5 | ``` 6 | (min(product(rank(rank(scale(log(sum(ts_min(rank(rank((-1 * rank(delta((close - 1), 5))))), 2), 1))))), 1), 5) + ts_rank(delay((-1 * returns), 6), 5)) 7 | ``` 8 | 9 | **核心逻辑**: 10 | Alpha#29由两部分 (`part1` 和 `part2`) 相加而成。 11 | 12 | * **`part1`**: 核心是对 `(收盘价 - 1)` 的5日价格变动进行一系列深度处理:多次横截面排名、取负、2日时序最小值、1日求和(实际为取值)、对数变换(对绝对值取对数以处理潜在非正数)、横截面标准化、再次多次横截面排名、1日乘积(实际为取值),最后取过去5日的时序最小值。 13 | * **`part2`**: 计算负的日收益率,将其延迟6天,然后计算其在过去5天窗口内的时序百分位排名。 14 | 15 | 最终因子是 `part1` 和 `part2` 的和。 16 | 17 | **解读**: 18 | Alpha#29 是一个结构极其复杂的因子,它融合了对价格变动(`part1`)和延迟负收益率(`part2`)的深度加工信号。 19 | `part1` 旨在从价格的短期变化中提取经过多重筛选和强化的信号,可能捕捉动量、反转或波动性的某些特征。 20 | `part2` 关注的是稍早前(6日前)的负收益表现,并通过时序排名来衡量其在近期的相对强度,这带有一定的反转择时意味。 21 | 两者的结合,使得该因子试图在多个维度和时间尺度上识别出具有特定复杂模式的资产。其具体市场含义和有效性高度依赖于严格的实证检验。 22 | 23 | --- 24 | 25 | ### 日本語訳 26 | 27 | # 101の量的要因の解釈|Alpha#29: 複雑な価格変換と遅延マイナスリターン時系列ランキングの加算 28 | 29 | **数式**: 30 | 31 | ``` 32 | (min(product(rank(rank(scale(log(sum(ts_min(rank(rank((-1 * rank(delta((close - 1), 5))))), 2), 1))))), 1), 5) + ts_rank(delay((-1 * returns), 6), 5)) 33 | ``` 34 | 35 | **コアロジック**: 36 | Alpha#29は2つの部分(`part1`と`part2`)の合計で構成されています。 37 | 38 | * **`part1`**: 主に `(終値 - 1)` の5日間価格変動に対する一連の高度な処理です。具体的には、複数回のクロスセクションランキング、符号反転、2日間の時系列最小値、1日間の合計(実質的には値の取得)、対数変換(潜在的な非正数を処理するための絶対値に対する対数)、クロスセクション標準化、再度複数回のクロスセクションランキング、1日間の積(実質的には値の取得)、最後に過去5日間の時系列最小値を取得します。 39 | * **`part2`**: マイナスの日次リターンを計算し、それを6日間遅延させ、その後、過去5日間ウィンドウでの時系列パーセンタイルランキングを計算します。 40 | 41 | 最終的なファクターは `part1` と `part2` の合計です。 42 | 43 | **解釈**: 44 | Alpha#29は非常に複雑な構造を持つファクターであり、価格変動(`part1`)と遅延マイナスリターン(`part2`)の高度に処理されたシグナルを融合しています。 45 | `part1`は、価格の短期的な変動から多重のフィルタリングと強化を経たシグナルを抽出することを目的としており、モメンタム、リバーサル、またはボラティリティの特定の特性を捉える可能性があります。 46 | `part2`は、少し前(6日前)のマイナスリターンパフォーマンスに注目し、時系列ランキングを通じて最近の相対的な強度を測定します。これには一定のリバーサルタイミングの意味合いが含まれています。 47 | 両者を組み合わせることで、このファクターは複数の次元と時間スケールで特定の複雑なパターンを持つ資産を識別しようとします。その具体的な市場の意味と有効性は、厳密な実証検証に大きく依存します。 -------------------------------------------------------------------------------- /alpha/archive/alpha23/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from pathlib import Path 4 | 5 | def calculate_alpha23(df: pd.DataFrame) -> pd.DataFrame: 6 | """ 7 | 计算 Alpha#23: (((sum(high, 20) / 20) < high) ? (-1 * delta(high, 2)) : 0) 8 | 9 | 参数: 10 | df (pd.DataFrame): 包含必要数据的DataFrame,需要包含 'high' 列 11 | 12 | 返回: 13 | pd.DataFrame: 包含原始数据和计算得到的Alpha#23值的DataFrame 14 | """ 15 | # 按资产分组进行计算 16 | result_df = df.copy() 17 | 18 | # 计算20日高价移动平均 19 | result_df['high_ma_20'] = df.groupby('asset_id')['high'].transform( 20 | lambda x: x.rolling(window=20, min_periods=20).mean() 21 | ) 22 | 23 | # 计算2日价格差分 24 | result_df['delta_high_2'] = df.groupby('asset_id')['high'].transform( 25 | lambda x: x.diff(2) 26 | ) 27 | 28 | # 计算Alpha#23 29 | # 当high > high_ma_20时,返回-1 * delta_high_2;否则返回0 30 | result_df['alpha23'] = np.where( 31 | result_df['high'] > result_df['high_ma_20'], 32 | -1 * result_df['delta_high_2'], 33 | 0 34 | ) 35 | 36 | # 保留两位有效数字 37 | result_df['alpha23'] = result_df['alpha23'].round(2) 38 | 39 | return result_df 40 | 41 | def main(): 42 | # 读取数据 43 | data_path = Path('../../data/mock_data.csv') 44 | df = pd.read_csv(data_path) 45 | 46 | # 确保数据按日期和资产ID排序 47 | df = df.sort_values(['date', 'asset_id']) 48 | 49 | # 计算Alpha#23 50 | result_df = calculate_alpha23(df) 51 | 52 | # 保存结果 53 | output_path = Path('./alpha23_results.csv') 54 | result_df.to_csv(output_path, index=False) 55 | 56 | # 打印部分结果和统计信息 57 | print("\nAlpha#23 计算完成!") 58 | print("\n前5行结果:") 59 | print(result_df[['date', 'asset_id', 'high', 'high_ma_20', 'delta_high_2', 'alpha23']].head()) 60 | print("\n后5行结果:") 61 | print(result_df[['date', 'asset_id', 'high', 'high_ma_20', 'delta_high_2', 'alpha23']].tail()) 62 | print("\nAlpha#23统计信息:") 63 | print(result_df['alpha23'].describe()) 64 | 65 | if __name__ == '__main__': 66 | main() -------------------------------------------------------------------------------- /alpha/archive/alpha30/cast.md: -------------------------------------------------------------------------------- 1 | # 解读101个量化因子|Alpha#30: 价格变动符号排名与成交量比率的乘积 2 | 3 | **原始公式**: 4 | 5 | ``` 6 | (((1.0 - rank(((sign((close - delay(close, 1))) + sign((delay(close, 1) - delay(close, 2)))) + sign((delay(close, 2) - delay(close, 3)))))) * sum(volume, 5)) / sum(volume, 20)) 7 | ``` 8 | 9 | **核心逻辑**: 10 | 该因子首先计算过去三天每日价格变动的符号之和 (`sign_sum`)。这个 `sign_sum` 反映了价格在短期内的趋势方向和一致性。然后,对 `sign_sum` 进行横截面百分位排名,并从1.0中减去该排名值 (`rank_transformed`),这意味着原始 `sign_sum` 排名越低(例如,持续下跌),`rank_transformed` 的值越高。 11 | 同时,计算5日累计成交量与20日累计成交量的比率 (`volume_ratio`),这反映了近期成交量的相对活跃度。 12 | 最终的 Alpha 值为 `rank_transformed` 乘以 `volume_ratio` (需要注意处理 `sum(volume, 20)` 可能为零的情况)。 13 | 14 | 15 | Alpha#30 结合了价格变动的短期持续性信号(经过排名和反转处理)与成交量的相对强度信号。 16 | `1.0 - rank(sign_sum)` 这部分倾向于给那些近期价格表现疲软(例如连续下跌导致 `sign_sum` 较低,从而 `rank` 较低,最终 `1.0 - rank` 较高)的资产赋予更高的权重。 17 | 当这种价格行为特征与特定的成交量模式(例如,短期成交量相对于中长期显著放大或萎缩)相结合时,因子值会相应调整。例如,一个持续下跌(`rank_transformed` 较高)且近期成交量激增(`volume_ratio` 较高)的股票,可能会得到一个相对较高的 Alpha#30 值,这可能被解读为潜在的"恐慌抛售"或"下跌末端放量"信号。 18 | 19 | --- 20 | 21 | ### 日本語訳 22 | 23 | # 101の量的要因の解釈|Alpha#30: 価格変動符号ランキングと出来高比率の積 24 | 25 | **数式**: 26 | 27 | ``` 28 | (((1.0 - rank(((sign((close - delay(close, 1))) + sign((delay(close, 1) - delay(close, 2)))) + sign((delay(close, 2) - delay(close, 3)))))) * sum(volume, 5)) / sum(volume, 20)) 29 | ``` 30 | 31 | **コアロジック**: 32 | このファクターは、まず過去3日間の日次価格変動の符号の合計(`sign_sum`)を計算します。この `sign_sum` は、短期的な価格のトレンド方向と一貫性を反映します。次に、`sign_sum` をクロスセクションでパーセンタイルランキングし、そのランキング値を1.0から減算します(`rank_transformed`)。これは、元の `sign_sum` のランキングが低い(例えば、連続下落)ほど、`rank_transformed` の値が高くなることを意味します。 33 | 同時に、5日間累積出来高と20日間累積出来高の比率(`volume_ratio`)を計算します。これは、最近の出来高の相対的な活発度を反映します。 34 | 最終的なAlpha値は、`rank_transformed` に `volume_ratio` を乗じたものです(`sum(volume, 20)` がゼロになる可能性に対処する必要があります)。 35 | 36 | **解釈**: 37 | Alpha#30は、価格変動の短期的な持続性シグナル(ランキングと反転処理を経たもの)と出来高の相対的な強度シグナルを組み合わせたものです。 38 | `1.0 - rank(sign_sum)` の部分は、最近の価格パフォーマンスが弱い(例えば、連続下落により `sign_sum` が低くなり、結果として `rank` が低くなり、最終的に `1.0 - rank` が高くなる)資産に、より高い重みを与える傾向があります。 39 | この価格行動特性が特定の出来高パターン(例えば、短期出来高が中長期出来高に対して著しく増加または減少)と組み合わさると、ファクター値は相応に調整されます。例えば、連続下落(`rank_transformed` が高い)し、かつ最近の出来高が急増(`volume_ratio` が高い)している株式は、比較的に高いAlpha#30値を得る可能性があり、これは潜在的な「パニック売り」または「下落最終局面での出来高増加」シグナルと解釈されるかもしれません。 40 | -------------------------------------------------------------------------------- /alpha/archive/alpha25/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from pathlib import Path 4 | 5 | def calculate_alpha25(df: pd.DataFrame) -> pd.DataFrame: 6 | """ 7 | 计算 Alpha#25: rank(((((-1 * returns) * adv20) * vwap) * (high - close))) 8 | 9 | 参数: 10 | df (pd.DataFrame): 包含必要数据的DataFrame,需要包含 returns, volume, vwap, high, close 列 11 | 12 | 返回: 13 | pd.DataFrame: 包含原始数据和计算得到的Alpha#25值的DataFrame 14 | """ 15 | # 按资产分组进行计算 16 | result_df = df.copy() 17 | 18 | # 计算20日平均成交量 19 | result_df['adv20'] = df.groupby('asset_id')['volume'].transform( 20 | lambda x: x.rolling(window=20, min_periods=20).mean() 21 | ) 22 | 23 | # 计算日内价格差值 24 | result_df['high_close_diff'] = df['high'] - df['close'] 25 | 26 | # 计算因子乘积 27 | result_df['factor'] = ((-1 * df['returns']) * 28 | result_df['adv20'] * 29 | df['vwap'] * 30 | result_df['high_close_diff']) 31 | 32 | # 按日期分组计算排名 33 | result_df['alpha25'] = result_df.groupby('date')['factor'].transform( 34 | lambda x: x.rank(pct=True) 35 | ) 36 | 37 | # 保留两位有效数字 38 | result_df['alpha25'] = result_df['alpha25'].round(2) 39 | 40 | return result_df 41 | 42 | def main(): 43 | # 读取数据 44 | data_path = Path('../../data/mock_data.csv') 45 | df = pd.read_csv(data_path) 46 | 47 | # 确保数据按日期和资产ID排序 48 | df = df.sort_values(['date', 'asset_id']) 49 | 50 | # 如果returns列不存在,计算returns 51 | if 'returns' not in df.columns: 52 | df['returns'] = df.groupby('asset_id')['close'].pct_change() 53 | 54 | # 计算Alpha#25 55 | result_df = calculate_alpha25(df) 56 | 57 | # 保存结果 58 | output_path = Path('./alpha25_results.csv') 59 | result_df.to_csv(output_path, index=False) 60 | 61 | # 打印部分结果和统计信息 62 | print("\nAlpha#25 计算完成!") 63 | print("\n前5行结果:") 64 | print(result_df[['date', 'asset_id', 'returns', 'adv20', 'vwap', 'high_close_diff', 'factor', 'alpha25']].head()) 65 | print("\n后5行结果:") 66 | print(result_df[['date', 'asset_id', 'returns', 'adv20', 'vwap', 'high_close_diff', 'factor', 'alpha25']].tail()) 67 | print("\nAlpha#25统计信息:") 68 | print(result_df['alpha25'].describe()) 69 | 70 | if __name__ == '__main__': 71 | main() -------------------------------------------------------------------------------- /doc/functions.md: -------------------------------------------------------------------------------- 1 | A.1. Functions and Operators 2 | 3 | (Below “{ }” stands for a placeholder. All expressions are case insensitive.) 4 | 5 | abs(x), log(x), sign(x) = standard definitions; same for the operators “+”, “-”, “*”, “/”, “>”, “<”, 6 | “==”, “||”, “x ? y : z” 7 | 8 | rank(x) = cross-sectional rank 9 | 10 | delay(x, d) = value of x d days ago 11 | 12 | correlation(x, y, d) = time-serial correlation of x and y for the past d days 13 | 14 | covariance(x, y, d) = time-serial covariance of x and y for the past d days 15 | 16 | scale(x, a) = rescaled x such that sum(abs(x)) = a (the default is a = 1) 17 | 18 | delta(x, d) = today’s value of x minus the value of x d days ago 19 | 20 | signedpower(x, a) = x^a 21 | 22 | decay_linear(x, d) = weighted moving average over the past d days with linearly decaying 23 | weights d, d – 1, …, 1 (rescaled to sum up to 1) 24 | 25 | indneutralize(x, g) = x cross-sectionally neutralized against groups g (subindustries, industries, 26 | sectors, etc.), i.e., x is cross-sectionally demeaned within each group g 27 | 28 | ts_{O}(x, d) = operator O applied across the time-series for the past d days; non-integer number 29 | of days d is converted to floor(d) 30 | 31 | ts_min(x, d) = time-series min over the past d days 32 | 33 | 15 34 | 35 | ts_max(x, d) = time-series max over the past d days 36 | 37 | ts_argmax(x, d) = which day ts_max(x, d) occurred on 38 | 39 | ts_argmin(x, d) = which day ts_min(x, d) occurred on 40 | 41 | ts_rank(x, d) = time-series rank in the past d days 42 | 43 | min(x, d) = ts_min(x, d) 44 | 45 | max(x, d) = ts_max(x, d) 46 | 47 | sum(x, d) = time-series sum over the past d days 48 | 49 | product(x, d) = time-series product over the past d days 50 | 51 | stddev(x, d) = moving time-series standard deviation over the past d days 52 | 53 | A.2. Input Data 54 | 55 | returns = daily close-to-close returns 56 | 57 | open, close, high, low, volume = standard definitions for daily price and volume data 58 | 59 | vwap = daily volume-weighted average price 60 | 61 | cap = market cap 62 | 63 | adv{d} = average daily dollar volume for the past d days 64 | 65 | IndClass = a generic placeholder for a binary industry classification such as GICS, BICS, NAICS, 66 | SIC, etc., in indneutralize(x, IndClass.level), where level = sector, industry, subindustry, etc. 67 | Multiple IndClass in the same alpha need not correspond to the same industry classification. 68 | -------------------------------------------------------------------------------- /alpha/archive/alpha28/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def scale(df): 5 | """ 6 | Standardize a series to have zero mean and unit variance 7 | """ 8 | return (df - df.mean()) / df.std() 9 | 10 | def calculate_alpha28(df): 11 | """ 12 | Calculates Alpha#28 based on the given formula: 13 | scale(((correlation(adv20, low, 5) + ((high + low) / 2)) - close)) 14 | """ 15 | # Ensure data is sorted by date for rolling calculations 16 | df = df.sort_values(by=['asset_id', 'date']) 17 | 18 | # Calculate 20-day average volume (adv20) 19 | df['adv20'] = df.groupby('asset_id')['volume'].transform( 20 | lambda x: x.rolling(window=20, min_periods=1).mean() 21 | ) 22 | 23 | # Calculate mid price 24 | df['mid_price'] = (df['high'] + df['low']) / 2 25 | 26 | # Calculate correlation between adv20 and low price 27 | df['correlation'] = df.groupby('asset_id').apply( 28 | lambda x: x['adv20'].rolling(window=5, min_periods=5).corr(x['low']) 29 | ).reset_index(level=0, drop=True) 30 | 31 | # Calculate combined result before scaling 32 | df['result'] = df['correlation'] + df['mid_price'] - df['close'] 33 | 34 | # Apply scaling by group (date) 35 | df['alpha28'] = df.groupby('date')['result'].transform(lambda x: scale(x)) 36 | 37 | # Round to 2 decimal places 38 | df['alpha28'] = round(df['alpha28'], 2) 39 | 40 | # Select and return relevant columns 41 | return df[['date', 'asset_id', 'volume', 'high', 'low', 'close', 'alpha28']] 42 | 43 | if __name__ == "__main__": 44 | # Load data 45 | try: 46 | data_df = pd.read_csv("/Users/kuhung/roy/alpha-mining/data/mock_data.csv", parse_dates=['date']) 47 | except FileNotFoundError: 48 | print("Error: mock_data.csv not found. Please ensure the data file exists.") 49 | exit() 50 | 51 | # Calculate Alpha 52 | alpha_df = calculate_alpha28(data_df.copy()) # Use a copy to avoid modifying original df 53 | 54 | # Save results 55 | output_file = "alpha28_results.csv" 56 | alpha_df.to_csv(output_file, index=False) 57 | 58 | print(f"Alpha#28 calculated and results saved to {output_file}") 59 | print("\nFirst 5 rows of Alpha results:") 60 | print(alpha_df.head()) 61 | print("\nLast 5 rows of Alpha results:") 62 | print(alpha_df.tail()) 63 | print("\nDescriptive statistics of Alpha28:") 64 | print(alpha_df['alpha28'].describe()) -------------------------------------------------------------------------------- /alpha/archive/alpha22/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def format_float_to_2_sig_figs(val): 5 | if pd.isna(val): 6 | return "" 7 | if val == 0: 8 | return "0.00" 9 | try: 10 | float_val = float(val) 11 | return f"{float_val:.2g}" 12 | except (ValueError, TypeError): 13 | return str(val) 14 | 15 | def calculate_alpha22(df): 16 | required_cols = ['high', 'close', 'volume'] 17 | for col in required_cols: 18 | if col not in df.columns: 19 | raise ValueError(f"数据缺少必要列: {col}") 20 | df = df.sort_values(['asset_id', 'date']).copy() 21 | # 5日相关性 22 | def rolling_corr(x): 23 | return x['high'].rolling(5, min_periods=5).corr(x['volume']) 24 | df['corr_high_vol_5'] = df.groupby('asset_id', group_keys=False).apply(rolling_corr).reset_index(level=0, drop=True) 25 | # 5日delta 26 | df['delta_corr_5'] = df.groupby('asset_id')['corr_high_vol_5'].diff(5) 27 | # 20日收盘价波动率 28 | df['stddev_close_20'] = df.groupby('asset_id')['close'].transform(lambda x: x.rolling(20, min_periods=20).std()) 29 | # 截面排名 30 | df = df.sort_values(['date', 'asset_id']) 31 | df['rank_stddev_close_20'] = df.groupby('date')['stddev_close_20'].rank(method='average', pct=True) 32 | # 公式实现 33 | df['alpha22'] = -1 * (df['delta_corr_5'] * df['rank_stddev_close_20']) 34 | # 输出列 35 | base_cols = [col for col in ['date', 'asset_id', 'open', 'high', 'low', 'close', 'volume'] if col in df.columns] 36 | calc_cols = ['corr_high_vol_5', 'delta_corr_5', 'stddev_close_20', 'rank_stddev_close_20', 'alpha22'] 37 | out_cols = base_cols + [c for c in calc_cols if c not in base_cols] 38 | df_out = df[out_cols].copy() 39 | # 保留两位有效数字 40 | for col in ['corr_high_vol_5', 'delta_corr_5', 'stddev_close_20', 'rank_stddev_close_20', 'alpha22']: 41 | if col in df_out.columns: 42 | df_out[col] = df_out[col].apply(format_float_to_2_sig_figs) 43 | return df_out 44 | 45 | if __name__ == "__main__": 46 | DATA_FILE_PATH = "../../data/mock_data.csv" 47 | OUTPUT_FILE_PATH = "alpha22_results.csv" 48 | try: 49 | print(f"加载数据: {DATA_FILE_PATH}") 50 | input_df = pd.read_csv(DATA_FILE_PATH, parse_dates=['date']) 51 | print("数据加载成功。") 52 | except Exception as e: 53 | print(f"数据加载失败: {e}") 54 | exit(1) 55 | try: 56 | alpha_df = calculate_alpha22(input_df) 57 | print("Alpha#22 计算完成。") 58 | except Exception as e: 59 | print(f"计算失败: {e}") 60 | exit(1) 61 | try: 62 | alpha_df.to_csv(OUTPUT_FILE_PATH, index=False) 63 | print(f"结果已保存到 {OUTPUT_FILE_PATH}") 64 | except Exception as e: 65 | print(f"保存失败: {e}") 66 | exit(1) -------------------------------------------------------------------------------- /alpha/archive/alpha22/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#22: 相关性变化与波动率排序因子 2 | 3 | ## 描述 4 | 5 | Alpha#22 的计算公式为: 6 | 7 | ``` 8 | Alpha#22 = -1 * (delta(correlation(high, volume, 5), 5) * rank(stddev(close, 20))) 9 | ``` 10 | 11 | 该因子结合了高价与成交量的相关性变化和收盘价波动率的截面排序,旨在捕捉市场结构变化带来的交易机会。 12 | 13 | **核心逻辑**: 14 | 1. 计算5日窗口内 high 与 volume 的相关性。 15 | 2. 计算该相关性5日变化(delta)。 16 | 3. 计算20日收盘价波动率,并在每个截面做排名。 17 | 4. 用相关性变化与波动率排名的乘积,取相反数,作为最终信号。 18 | 19 | ## 项目结构 20 | 21 | ``` 22 | alpha-mining/ 23 | ├── data/ 24 | │ └── mock_data.csv 25 | ├── alpha/alpha22/ 26 | │ ├── alpha_calculator.py 27 | │ ├── alpha22_results.csv 28 | │ ├── README.md 29 | │ └── cast.md 30 | ``` 31 | 32 | ## 使用步骤 33 | 34 | 1. 确保已安装 pandas、numpy。 35 | 2. 数据文件 `data/mock_data.csv` 需包含 `date`, `asset_id`, `high`, `close`, `volume`。 36 | 3. 运行 `alpha/alpha22/alpha_calculator.py`,结果输出到 `alpha22_results.csv`。 37 | 38 | ```bash 39 | cd alpha/alpha22 40 | python alpha_calculator.py 41 | ``` 42 | 43 | ## 数据需求 44 | - `date`: 交易日期 45 | - `asset_id`: 资产ID 46 | - `high`: 最高价 47 | - `close`: 收盘价 48 | - `volume`: 成交量 49 | 50 | ## 输出格式 51 | 输出CSV包含: 52 | - 原始数据列(如有):`date`, `asset_id`, `open`, `high`, `low`, `close`, `volume` 53 | - 计算列: 54 | - `corr_high_vol_5`:5日窗口 high 与 volume 的相关系数 55 | - `delta_corr_5`:5日相关性变化 56 | - `stddev_close_20`:20日收盘价标准差 57 | - `rank_stddev_close_20`:20日波动率的截面排名(百分比) 58 | - `alpha22`:最终信号,保留两位有效数字 59 | 60 | | 字段名 | 含义 | 备注 | 61 | |-----------------------|------------------------------|----------------| 62 | | corr_high_vol_5 | 5日窗口 high-volume 相关系数 | | 63 | | delta_corr_5 | 5日相关性变化 | | 64 | | stddev_close_20 | 20日收盘价标准差 | | 65 | | rank_stddev_close_20 | 20日波动率截面排名 | 0~1 | 66 | | alpha22 | 最终信号 | 两位有效数字 | 67 | 68 | ## 计算步骤示例 69 | 70 | 以某资产2025-01-25为例: 71 | 72 | | date | asset_id | high | close | volume | corr_high_vol_5 | delta_corr_5 | stddev_close_20 | rank_stddev_close_20 | alpha22 | 73 | |------------|----------|-------|-------|--------|-----------------|--------------|-----------------|---------------------|---------| 74 | | 2025-01-25 | asset_1 | 101.2 | 99.8 | 12000 | 0.85 | 0.12 | 1.30 | 0.80 | -0.10 | 75 | 76 | - `corr_high_vol_5` = 0.85 77 | - `delta_corr_5` = 0.12 78 | - `stddev_close_20` = 1.30 79 | - `rank_stddev_close_20` = 0.80 80 | - `alpha22 = -1 * (0.12 * 0.80) = -0.10` 81 | 82 | ## NaN与窗口期说明 83 | - 需至少25天数据,前24天alpha22为NaN。 84 | - 相关中间变量如`corr_high_vol_5`、`stddev_close_20`等,窗口不足时为NaN。 85 | - 每个资产独立计算窗口。 86 | 87 | ## 信号解读 88 | - alpha22>0:相关性上升且波动率高,预期回落/做空 89 | - alpha22<0:相关性下降且波动率高,预期反弹/做多 90 | 91 | ## 注意事项 92 | - 仅在数据缺失且无法由现有数据推导时,才修改data脚本。 93 | - 相关性和波动率对极端值敏感,建议先行数据清洗。 94 | - 本因子为示例,实际效果需回测验证。 -------------------------------------------------------------------------------- /alpha/archive/alpha11/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | # 读取数据 4 | def load_data(): 5 | data_path = '../../data/mock_data.csv' 6 | df = pd.read_csv(data_path) 7 | df['date'] = pd.to_datetime(df['date']) 8 | # 确保数据包含所有需要的列 9 | required_columns = ['date', 'asset_id', 'close', 'vwap', 'volume'] 10 | for col in required_columns: 11 | if col not in df.columns: 12 | raise ValueError(f"错误:输入数据缺少必要列: {col}") 13 | return df 14 | 15 | # 计算Alpha#11 16 | def calculate_alpha11(df): 17 | # 确保数据按 asset_id 和 date 排序 18 | df = df.sort_values(by=['asset_id', 'date']).reset_index(drop=True) 19 | 20 | # 计算 vwap - close 21 | df['vwap_close_diff'] = (df['vwap'] - df['close']).round(4) # 保留更多小数位以提高中间计算精度 22 | 23 | # 按 asset_id 分组计算时间序列相关的指标 24 | # ts_max((vwap - close), 3) 25 | df['ts_max_diff_3'] = df.groupby('asset_id')['vwap_close_diff'].rolling(window=3, min_periods=3).max().reset_index(level=0, drop=True).round(4) 26 | 27 | # ts_min((vwap - close), 3) 28 | df['ts_min_diff_3'] = df.groupby('asset_id')['vwap_close_diff'].rolling(window=3, min_periods=3).min().reset_index(level=0, drop=True).round(4) 29 | 30 | # delta(volume, 3) 31 | df['delta_volume_3'] = df.groupby('asset_id')['volume'].transform(lambda x: x.diff(3)).round(4) 32 | 33 | # 按 date 分组进行截面排名 (pct=True 将排名转换为百分比形式 0-1) 34 | df['rank_ts_max_diff_3'] = df.groupby('date')['ts_max_diff_3'].rank(method='average', ascending=True, pct=True, na_option='keep') 35 | df['rank_ts_min_diff_3'] = df.groupby('date')['ts_min_diff_3'].rank(method='average', ascending=True, pct=True, na_option='keep') 36 | df['rank_delta_volume_3'] = df.groupby('date')['delta_volume_3'].rank(method='average', ascending=True, pct=True, na_option='keep') 37 | 38 | # 计算 Alpha#11: ((rank(ts_max((vwap - close), 3)) + rank(ts_min((vwap - close), 3))) * rank(delta(volume, 3))) 39 | df['alpha11'] = ((df['rank_ts_max_diff_3'] + df['rank_ts_min_diff_3']) * df['rank_delta_volume_3']).round(2) 40 | 41 | # 选择输出列,包含原始数据和最终alpha值以及关键中间值 42 | output_columns = [ 43 | 'date', 'asset_id', 'close', 'vwap', 'volume', 44 | 'vwap_close_diff', 'ts_max_diff_3', 'ts_min_diff_3', 'delta_volume_3', 45 | 'rank_ts_max_diff_3', 'rank_ts_min_diff_3', 'rank_delta_volume_3', 46 | 'alpha11' 47 | ] 48 | return df[output_columns] 49 | 50 | # 保存结果 51 | def save_results(df): 52 | output_path = 'alpha11_results.csv' 53 | df.to_csv(output_path, index=False, float_format='%.2f') # 确保alpha11和其他浮点数按需格式化 54 | print(f"结果已保存到 {output_path}") 55 | 56 | # 主函数 57 | def main(): 58 | # 加载数据 59 | df = load_data() 60 | 61 | # 计算Alpha#11 62 | df_alpha = calculate_alpha11(df) 63 | 64 | # 保存结果 65 | save_results(df_alpha) 66 | 67 | if __name__ == "__main__": 68 | main() -------------------------------------------------------------------------------- /alpha/archive/alpha30/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def calculate_alpha30(df): 5 | """ 6 | Calculates Alpha#30 based on the given formula: 7 | (((1.0 - rank(((sign((close - delay(close, 1))) + sign((delay(close, 1) - delay(close, 2)))) + 8 | sign((delay(close, 2) - delay(close, 3)))))) * sum(volume, 5)) / sum(volume, 20)) 9 | """ 10 | # Ensure data is sorted by date for rolling calculations 11 | df = df.sort_values(by=['asset_id', 'date']) 12 | 13 | # Calculate price differences 14 | df['diff1'] = df.groupby('asset_id')['close'].transform(lambda x: x - x.shift(1)) 15 | df['diff2'] = df.groupby('asset_id')['close'].transform(lambda x: x.shift(1) - x.shift(2)) 16 | df['diff3'] = df.groupby('asset_id')['close'].transform(lambda x: x.shift(2) - x.shift(3)) 17 | 18 | # Calculate signs 19 | df['sign1'] = np.sign(df['diff1']) 20 | df['sign2'] = np.sign(df['diff2']) 21 | df['sign3'] = np.sign(df['diff3']) 22 | 23 | # Sum signs and calculate rank 24 | df['sign_sum'] = df['sign1'] + df['sign2'] + df['sign3'] 25 | df['rank_result'] = 1.0 - df.groupby('date')['sign_sum'].rank(pct=True) 26 | 27 | # Calculate volume sums 28 | df['vol_5'] = df.groupby('asset_id')['volume'].transform( 29 | lambda x: x.rolling(window=5, min_periods=5).sum() 30 | ) 31 | df['vol_20'] = df.groupby('asset_id')['volume'].transform( 32 | lambda x: x.rolling(window=20, min_periods=20).sum() 33 | ) 34 | 35 | # Calculate final alpha 36 | # Handle potential division by zero 37 | df['alpha30'] = np.where( 38 | df['vol_20'] != 0, 39 | (df['rank_result'] * df['vol_5']) / df['vol_20'], 40 | 0 41 | ) 42 | 43 | # Round to 2 decimal places 44 | df['alpha30'] = round(df['alpha30'], 2) 45 | 46 | # Select and return relevant columns 47 | return df[['date', 'asset_id', 'close', 'volume', 'alpha30']] 48 | 49 | if __name__ == "__main__": 50 | # Load data 51 | try: 52 | data_df = pd.read_csv("/Users/kuhung/roy/alpha-mining/data/mock_data.csv", parse_dates=['date']) 53 | except FileNotFoundError: 54 | print("Error: mock_data.csv not found. Please ensure the data file exists.") 55 | exit() 56 | 57 | # Calculate Alpha 58 | alpha_df = calculate_alpha30(data_df.copy()) # Use a copy to avoid modifying original df 59 | 60 | # Save results 61 | output_file = "alpha30_results.csv" 62 | alpha_df.to_csv(output_file, index=False) 63 | 64 | print(f"Alpha#30 calculated and results saved to {output_file}") 65 | print("\nFirst 5 rows of Alpha results:") 66 | print(alpha_df.head()) 67 | print("\nLast 5 rows of Alpha results:") 68 | print(alpha_df.tail()) 69 | print("\nDescriptive statistics of Alpha30:") 70 | print(alpha_df['alpha30'].describe()) -------------------------------------------------------------------------------- /alpha/alpha35/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import os 4 | 5 | def ts_rank(series, window): 6 | """ 7 | Calculates the time-series rank of a series over a specified window. 8 | For each element, it ranks the current value against the values in the preceding window, 9 | and then normalizes it to a [0, 1] range (percentile rank). 10 | """ 11 | return series.rolling(window=window).apply(lambda x: pd.Series(x).rank(method='average').iloc[-1] / len(x), raw=False) 12 | 13 | def calculate_alpha35(df): 14 | """ 15 | Calculates Alpha#35 based on the given DataFrame. 16 | Formula: ((Ts_Rank(volume, 32) * (1 - Ts_Rank(((close + high) - low), 16))) * (1 - Ts_Rank(returns, 32))) 17 | """ 18 | # Ensure necessary columns exist 19 | required_cols = ['close', 'high', 'low', 'volume', 'returns'] 20 | if not all(col in df.columns for col in required_cols): 21 | raise ValueError(f"Missing required columns. Ensure {required_cols} are in the DataFrame.") 22 | 23 | # Calculate intermediate terms 24 | df['price_term'] = (df['close'] + df['high'] - df['low']) 25 | 26 | # Apply Ts_Rank 27 | df['ts_rank_volume_32'] = ts_rank(df['volume'], 32) 28 | df['ts_rank_price_term_16'] = ts_rank(df['price_term'], 16) 29 | df['ts_rank_returns_32'] = ts_rank(df['returns'], 32) 30 | 31 | # Calculate Alpha#35 32 | alpha35_values = (df['ts_rank_volume_32'] * 33 | (1 - df['ts_rank_price_term_16']) * 34 | (1 - df['ts_rank_returns_32'])) 35 | 36 | return alpha35_values 37 | 38 | def main(): 39 | script_dir = os.path.dirname(__file__) 40 | data_path = os.path.join(script_dir, '..', '..', 'data', 'mock_data.csv') 41 | output_path = os.path.join(script_dir, 'alpha35_results.csv') 42 | 43 | try: 44 | df = pd.read_csv(data_path) 45 | except FileNotFoundError: 46 | print(f"Error: Data file not found at {data_path}. Please ensure mock_data.csv exists in the data/ directory.") 47 | return 48 | 49 | # Assuming 'returns' needs to be calculated if not present 50 | if 'returns' not in df.columns: 51 | if 'close' in df.columns: 52 | df['returns'] = df['close'].pct_change() 53 | print("Note: 'returns' column was calculated from 'close' prices.") 54 | else: 55 | print("Error: 'close' column not found to calculate 'returns'. Please ensure 'close' or 'returns' is in the data.") 56 | return 57 | 58 | # Calculate Alpha#35 59 | df['Alpha#35'] = calculate_alpha35(df) 60 | 61 | # Keep original data and Alpha#35, drop intermediate columns 62 | final_df = df.drop(columns=['price_term', 'ts_rank_volume_32', 'ts_rank_price_term_16', 'ts_rank_returns_32'], errors='ignore') 63 | 64 | # Round Alpha#35 to two decimal places 65 | final_df['Alpha#35'] = final_df['Alpha#35'].round(2) 66 | 67 | # Save results 68 | final_df.to_csv(output_path, index=False) 69 | print(f"Alpha#35 calculated and saved to {output_path}") 70 | 71 | if __name__ == "__main__": 72 | main() -------------------------------------------------------------------------------- /alpha/archive/alpha21/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def format_float_to_2_sig_figs(val): 5 | if pd.isna(val): 6 | return "" 7 | if val == 0: 8 | return "0.00" 9 | try: 10 | float_val = float(val) 11 | return f"{float_val:.2g}" 12 | except (ValueError, TypeError): 13 | return str(val) 14 | 15 | def calculate_alpha21(df): 16 | required_cols = ['close', 'volume'] 17 | for col in required_cols: 18 | if col not in df.columns: 19 | raise ValueError(f"数据缺少必要列: {col}") 20 | df = df.sort_values(['asset_id', 'date']).copy() 21 | # 8日均价 22 | df['close_mean_8'] = df.groupby('asset_id')['close'].transform(lambda x: x.rolling(8, min_periods=8).mean()) 23 | # 8日波动率 24 | df['close_std_8'] = df.groupby('asset_id')['close'].transform(lambda x: x.rolling(8, min_periods=8).std()) 25 | # 2日均价 26 | df['close_mean_2'] = df.groupby('asset_id')['close'].transform(lambda x: x.rolling(2, min_periods=2).mean()) 27 | # 20日均量 28 | df['adv20'] = df.groupby('asset_id')['volume'].transform(lambda x: x.rolling(20, min_periods=20).mean()) 29 | # volume/adv20 30 | df['volume_over_adv20'] = df['volume'] / df['adv20'] 31 | # 条件判断 32 | df['cond1'] = (df['close_mean_8'] + df['close_std_8']) < df['close_mean_2'] 33 | df['cond2'] = df['close_mean_2'] < (df['close_mean_8'] - df['close_std_8']) 34 | df['cond3'] = (df['volume_over_adv20'] > 1) | (np.isclose(df['volume_over_adv20'], 1)) 35 | # 公式实现 36 | df['alpha21'] = np.where(df['cond1'], -1, 37 | np.where(df['cond2'], 1, 38 | np.where(df['cond3'], 1, -1))) 39 | # 输出列 40 | base_cols = [col for col in ['date', 'asset_id', 'open', 'high', 'low', 'close', 'volume'] if col in df.columns] 41 | calc_cols = ['close_mean_8', 'close_std_8', 'close_mean_2', 'adv20', 'volume_over_adv20', 'cond1', 'cond2', 'cond3', 'alpha21'] 42 | out_cols = base_cols + [c for c in calc_cols if c not in base_cols] 43 | df_out = df[out_cols].copy() 44 | # 保留两位有效数字 45 | for col in ['close_mean_8', 'close_std_8', 'close_mean_2', 'adv20', 'volume_over_adv20', 'alpha21']: 46 | if col in df_out.columns: 47 | df_out[col] = df_out[col].apply(format_float_to_2_sig_figs) 48 | return df_out 49 | 50 | if __name__ == "__main__": 51 | DATA_FILE_PATH = "../../data/mock_data.csv" 52 | OUTPUT_FILE_PATH = "alpha21_results.csv" 53 | try: 54 | print(f"加载数据: {DATA_FILE_PATH}") 55 | input_df = pd.read_csv(DATA_FILE_PATH, parse_dates=['date']) 56 | print("数据加载成功。") 57 | except Exception as e: 58 | print(f"数据加载失败: {e}") 59 | exit(1) 60 | try: 61 | alpha_df = calculate_alpha21(input_df) 62 | print("Alpha#21 计算完成。") 63 | except Exception as e: 64 | print(f"计算失败: {e}") 65 | exit(1) 66 | try: 67 | alpha_df.to_csv(OUTPUT_FILE_PATH, index=False) 68 | print(f"结果已保存到 {OUTPUT_FILE_PATH}") 69 | except Exception as e: 70 | print(f"保存失败: {e}") 71 | exit(1) -------------------------------------------------------------------------------- /alpha/archive/alpha23/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#23: 高价与移动平均的条件差分策略 2 | 3 | ## 描述 4 | 5 | Alpha#23 的计算公式为: 6 | 7 | ``` 8 | (((sum(high, 20) / 20) < high) ? (-1 * delta(high, 2)) : 0) 9 | ``` 10 | 11 | 该 Alpha 策略包含两个主要部分: 12 | 13 | 1. **条件判断部分**: 14 | * `sum(high, 20) / 20`: 计算最近20天的最高价移动平均 15 | * `< high`: 将当前最高价与20日移动平均比较 16 | 17 | 2. **信号生成部分**: 18 | * 当价格高于移动平均时:`-1 * delta(high, 2)` (最高价2日差分的负值) 19 | * 当价格不高于移动平均时:0 (不产生信号) 20 | 21 | ## 项目结构 22 | 23 | ``` 24 | alpha-mining/ 25 | ├── data/ 26 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 27 | │ └── mock_data.csv # 生成的模拟数据文件 28 | ├── alpha/alpha23/ 29 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#23 30 | │ ├── alpha23_results.csv # 计算得到的 Alpha#23 结果文件 31 | │ ├── README.md # 本说明文档 32 | │ └── cast.md # Alpha#23 策略总结 33 | ... 34 | ``` 35 | 36 | ## 使用步骤 37 | 38 | ### 1. 环境准备 39 | 40 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库: 41 | 42 | ```bash 43 | pip install pandas numpy 44 | ``` 45 | 46 | ### 2. 数据准备 47 | 48 | 本 Alpha 依赖于 `date`, `asset_id`, `high` 数据。这些数据应存在于 `../../data/mock_data.csv` 文件中。 49 | 50 | ### 3. 计算 Alpha#23 因子 51 | 52 | 进入 `alpha/alpha23` 目录并运行 `alpha_calculator.py` 脚本: 53 | 54 | ```bash 55 | python alpha_calculator.py 56 | ``` 57 | 58 | ## Alpha#23 策略解读与计算示例 59 | 60 | 以下示例使用 `alpha23_results.csv` 中的实际数据来展示计算过程。我们以 `asset_2` 在 `2025-01-20` 的数据为例: 61 | 62 | **背景数据**: 63 | - 日期: `2025-01-20` 64 | - 资产ID: `asset_2` 65 | - 当日最高价 (`high`): `103.45` 66 | - 20日移动平均 (`high_ma_20`): `102.9635` 67 | - 2日最高价差分 (`delta_high_2`): `1.28` 68 | - 最终Alpha值 (`alpha23`): `-1.28` 69 | 70 | **计算步骤**: 71 | 72 | 1. **计算20日移动平均**: 73 | * `high_ma_20 = 102.9635` 74 | * 这是过去20天(含当天)最高价的平均值 75 | 76 | 2. **条件判断**: 77 | * 当日最高价 `103.45` > 20日移动平均 `102.9635` 78 | * 条件成立,继续计算信号 79 | 80 | 3. **计算2日最高价差分**: 81 | * `delta_high_2 = high_today - high_2_days_ago` 82 | * `delta_high_2 = 103.45 - 102.17 = 1.28` 83 | 84 | 4. **生成Alpha信号**: 85 | * 由于条件成立,计算 `-1 * delta_high_2` 86 | * `alpha23 = -1 * 1.28 = -1.28` 87 | 88 | 这个示例展示了一个典型的信号生成过程: 89 | - 当价格突破20日移动平均时(`103.45 > 102.9635`) 90 | - 且最近两日价格在上升(`delta_high_2`为正) 91 | - 生成了一个负向信号(`-1.28`) 92 | - 这表明策略预期价格可能会回落 93 | 94 | ## 数据需求 95 | 96 | - `date`: 交易日期 (YYYY-MM-DD) 97 | - `asset_id`: 资产ID 98 | - `high`: 每日最高价 99 | 100 | ## 输出格式 101 | 102 | 输出的 CSV 文件 (`alpha23_results.csv`) 包含以下列: 103 | 104 | - `date`: 交易日期 105 | - `asset_id`: 资产ID 106 | - `high`: 当日最高价(原始数据) 107 | - `high_ma_20`: 20日最高价移动平均(中间计算值,保留四位小数) 108 | - `delta_high_2`: 2日最高价差分(中间计算值) 109 | - `alpha23`: 计算得到的 Alpha#23 值,保留两位有效数字 110 | 111 | ## 注意事项与风险提示 112 | 113 | 1. **数据窗口要求**: 114 | - 需要至少20天的历史数据来计算移动平均 115 | - 需要至少2天的历史数据来计算差分 116 | - 每个资产序列的前19个Alpha值将为NaN 117 | 118 | 2. **信号特点**: 119 | - 只在价格突破移动平均时产生信号 120 | - 信号强度取决于近期价格变动幅度 121 | - 适合捕捉价格突破后的反转机会 122 | 123 | 3. **潜在风险**: 124 | - 在震荡市场中可能产生过多假信号 125 | - 对于长期趋势行情可能错过部分机会 126 | - 需要结合其他指标来过滤信号 127 | 128 | 4. **实践建议**: 129 | - 考虑添加信号过滤条件(如成交量确认) 130 | - 可以调整移动平均和差分的时间窗口 131 | - 建议进行充分的回测验证 132 | -------------------------------------------------------------------------------- /alpha/alpha41/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import os 4 | 5 | def calculate_alpha41(df: pd.DataFrame) -> pd.DataFrame: 6 | """ 7 | 计算 Alpha#41: (((high * low)^0.5) - vwap) 8 | """ 9 | required_cols = ['high', 'low', 'vwap'] 10 | for col in required_cols: 11 | if col not in df.columns: 12 | raise ValueError(f"缺少必需列 '{col}'") 13 | 14 | # 确保数据按日期和资产ID排序 15 | df = df.sort_values(by=['date', 'asset_id']).copy() 16 | 17 | # --- Alpha#41 计算 --- 18 | # 步骤1: 计算 high 和 low 的几何平均数 19 | df['geometric_mean_high_low'] = (df['high'] * df['low']) ** 0.5 20 | 21 | # 步骤2: 减去 vwap 22 | df['alpha41'] = df['geometric_mean_high_low'] - df['vwap'] 23 | 24 | # --- 格式化输出 --- 25 | # 将alpha及相关中间列四舍五入到两位小数 26 | cols_to_round = ['geometric_mean_high_low', 'alpha41'] 27 | for col in cols_to_round: 28 | if col in df.columns: 29 | df[col] = df[col].round(2) 30 | 31 | return df 32 | 33 | if __name__ == "__main__": 34 | # --- 配置 --- 35 | # 假设此脚本位于 alpha/alpha41/ 36 | # 数据文件位于 data/ 37 | # 输出文件保存到当前目录 38 | ALPHA_NUMBER = 41 39 | DATA_FILE_PATH = os.path.join(os.path.dirname(__file__), '..', '..', 'data', 'mock_data.csv') 40 | OUTPUT_DIR = os.path.dirname(__file__) 41 | OUTPUT_FILE_PATH = os.path.join(OUTPUT_DIR, f'alpha{ALPHA_NUMBER}_results.csv') 42 | 43 | # --- 加载数据 --- 44 | try: 45 | print(f"正在从 {DATA_FILE_PATH} 加载数据...") 46 | input_df = pd.read_csv(DATA_FILE_PATH) 47 | print("数据加载成功。") 48 | except FileNotFoundError: 49 | print(f"错误: 在 {DATA_FILE_PATH} 未找到数据文件。") 50 | exit(1) 51 | 52 | # --- 数据预处理 --- 53 | input_df['date'] = pd.to_datetime(input_df['date']) 54 | if 'asset_id' in input_df.columns: 55 | input_df['asset_id'] = input_df['asset_id'].astype(str) 56 | print("数据预处理完成。") 57 | 58 | # --- 计算 Alpha --- 59 | try: 60 | print(f"正在计算 Alpha#{ALPHA_NUMBER}...") 61 | alpha_df = calculate_alpha41(input_df.copy()) 62 | print(f"Alpha#{ALPHA_NUMBER} 计算完成。") 63 | except ValueError as ve: 64 | print(f"计算Alpha时出错: {ve}") 65 | exit(1) 66 | 67 | # --- 后处理和保存 --- 68 | # 筛选掉 alpha 列为 NaN 的行 69 | alpha_df_filtered = alpha_df.dropna(subset=[f'alpha{ALPHA_NUMBER}']) 70 | print(f"已移除 alpha{ALPHA_NUMBER} 为 NaN 的行,剩余 {len(alpha_df_filtered)} 条记录。") 71 | 72 | # 确保所有原始列都包含在输出中 73 | original_cols = list(input_df.columns) 74 | new_cols = ['geometric_mean_high_low', f'alpha{ALPHA_NUMBER}'] 75 | output_cols = original_cols + [col for col in new_cols if col not in original_cols] 76 | 77 | # 重新排列列顺序,将新列放在最后 78 | final_df = alpha_df_filtered[output_cols] 79 | 80 | try: 81 | final_df.to_csv(OUTPUT_FILE_PATH, index=False, float_format='%.2f') 82 | print(f"Alpha#{ALPHA_NUMBER} 结果已保存至 {OUTPUT_FILE_PATH}") 83 | except Exception as e: 84 | print(f"保存结果至CSV时出错: {e}") 85 | exit(1) 86 | 87 | # --- 显示示例结果 --- 88 | print(f"\n--- Alpha#{ALPHA_NUMBER} 结果示例 ---") 89 | if not final_df.empty: 90 | print(final_df.head().to_string()) 91 | else: 92 | print("结果DataFrame为空。") -------------------------------------------------------------------------------- /alpha/archive/alpha1/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def signed_power(series, exponent): 5 | """ 6 | Computes sign(series) * (abs(series) ** exponent). 7 | """ 8 | return np.sign(series) * (np.abs(series) ** exponent) 9 | 10 | def ts_arg_max(series, window): 11 | """ 12 | 对每一天,返回过去window天内最大值出现的位置(0为今天,1为昨天,依此类推)。 13 | """ 14 | def argmax_pos(x): 15 | # x为长度window的Series 16 | return window - 1 - np.argmax(x.values[::-1]) 17 | return series.rolling(window=window, min_periods=1).apply(argmax_pos, raw=False) 18 | 19 | 20 | def calculate_alpha1(df, stddev_window=20, ts_argmax_window=5): 21 | """ 22 | Calculates Alpha#1 based on the given formula. 23 | 24 | Alpha#1: (rank(Ts_ArgMax(SignedPower(((returns < 0) ? stddev(returns, 20) : close), 2.), 5)) - 0.5) 25 | 其中 Ts_ArgMax 返回最大值出现的相对天数(0为今天,1为昨天...) 26 | """ 27 | # Ensure data is sorted by date for rolling calculations 28 | df = df.sort_values(by=['asset_id', 'date']) 29 | 30 | # Calculate stddev_returns for each asset 31 | df['stddev_returns'] = df.groupby('asset_id')['returns'].transform( 32 | lambda x: x.rolling(window=stddev_window, min_periods=1).std() 33 | ) 34 | 35 | # Condition: (returns < 0) ? stddev(returns, 20) : close 36 | df['conditional_value'] = np.where(df['returns'] < 0, df['stddev_returns'], df['close']) 37 | 38 | # SignedPower(conditional_value, 2.) 39 | df['signed_power_value'] = df.groupby('asset_id')['conditional_value'].transform( 40 | lambda x: signed_power(x, 2.0) 41 | ) 42 | # Fill NaNs that might result from signed_power if conditional_value was NaN (e.g. early stddev) 43 | df['signed_power_value'] = df['signed_power_value'].fillna(0) 44 | 45 | # Ts_ArgMax(SignedPower_value, 5) 46 | # 返回最大值出现的相对天数 47 | df['ts_argmax_value'] = df.groupby('asset_id')['signed_power_value'].transform( 48 | lambda x: ts_arg_max(x, window=ts_argmax_window) 49 | ) 50 | 51 | # rank(ts_argmax_value) 52 | # Rank is calculated daily across all assets 53 | df['rank_ts_argmax'] = df.groupby('date')['ts_argmax_value'].rank(pct=True, method='average') 54 | 55 | # Final Alpha: (rank - 0.5) 56 | df['alpha1'] = round(df['rank_ts_argmax'] - 0.5, 2) 57 | 58 | return df[['date', 'asset_id', 'close', 'returns', 'alpha1']] 59 | 60 | if __name__ == "__main__": 61 | # Load mock data 62 | try: 63 | data_df = pd.read_csv("/Users/kuhung/roy/alpha-mining/data/mock_data.csv", parse_dates=['date']) 64 | except FileNotFoundError: 65 | print("Error: mock_data.csv not found. Please run generate_mock_data.py first.") 66 | exit() 67 | 68 | # Calculate Alpha 69 | alpha_df = calculate_alpha1(data_df.copy()) # Use a copy to avoid modifying original df in some pandas versions 70 | 71 | # Save results 72 | alpha_df.to_csv("alpha1_results.csv", index=False) 73 | print("Alpha#1 calculated and results saved to alpha1_results.csv") 74 | print("\nFirst 5 rows of Alpha results:") 75 | print(alpha_df.head()) 76 | print("\nLast 5 rows of Alpha results:") 77 | print(alpha_df.tail()) 78 | print("\nDescriptive statistics of Alpha1:") 79 | print(alpha_df['alpha1'].describe()) -------------------------------------------------------------------------------- /alpha/archive/alpha24/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from pathlib import Path 4 | 5 | def calculate_alpha24(df: pd.DataFrame) -> pd.DataFrame: 6 | """ 7 | 计算 Alpha#24: 8 | ((((delta((sum(close, 100) / 100), 100) / delay(close, 100)) < 0.05) || 9 | ((delta((sum(close, 100) / 100), 100) / delay(close, 100)) == 0.05)) ? 10 | (-1 * (close - ts_min(close, 100))) : (-1 * delta(close, 3))) 11 | 12 | 参数: 13 | df (pd.DataFrame): 包含必要数据的DataFrame,需要包含 'close' 列 14 | 15 | 返回: 16 | pd.DataFrame: 包含原始数据和计算得到的Alpha#24值的DataFrame 17 | """ 18 | # 按资产分组进行计算 19 | result_df = df.copy() 20 | 21 | # 对每个资产进行分组计算 22 | for asset_id in result_df['asset_id'].unique(): 23 | asset_data = result_df[result_df['asset_id'] == asset_id].copy() 24 | 25 | # 计算100日移动平均 26 | ma_100 = asset_data['close'].rolling(window=100, min_periods=100).mean() 27 | 28 | # 计算移动平均的100日差分 29 | delta_ma_100 = ma_100 - ma_100.shift(100) 30 | 31 | # 计算100日前的收盘价 32 | delay_close_100 = asset_data['close'].shift(100) 33 | 34 | # 计算变化率 35 | change_rate = delta_ma_100 / delay_close_100 36 | 37 | # 计算100日最小值 38 | min_close_100 = asset_data['close'].rolling(window=100, min_periods=100).min() 39 | 40 | # 计算当前价格与最小值的差 41 | price_min_diff = asset_data['close'] - min_close_100 42 | 43 | # 计算3日价格差分 44 | delta_close_3 = asset_data['close'] - asset_data['close'].shift(3) 45 | 46 | # 根据条件计算Alpha#24 47 | alpha24 = np.where( 48 | (change_rate <= 0.05), 49 | -1 * price_min_diff, 50 | -1 * delta_close_3 51 | ) 52 | 53 | # 更新结果DataFrame 54 | result_df.loc[result_df['asset_id'] == asset_id, 'ma_100'] = ma_100 55 | result_df.loc[result_df['asset_id'] == asset_id, 'delta_ma_100'] = delta_ma_100 56 | result_df.loc[result_df['asset_id'] == asset_id, 'change_rate'] = change_rate 57 | result_df.loc[result_df['asset_id'] == asset_id, 'min_close_100'] = min_close_100 58 | result_df.loc[result_df['asset_id'] == asset_id, 'delta_close_3'] = delta_close_3 59 | result_df.loc[result_df['asset_id'] == asset_id, 'alpha24'] = alpha24 60 | 61 | # 保留两位有效数字 62 | result_df['alpha24'] = result_df['alpha24'].round(2) 63 | 64 | return result_df 65 | 66 | def main(): 67 | # 读取数据 68 | data_path = Path('../../data/mock_data.csv') 69 | df = pd.read_csv(data_path) 70 | 71 | # 确保数据按日期和资产ID排序 72 | df = df.sort_values(['date', 'asset_id']) 73 | 74 | # 计算Alpha#24 75 | result_df = calculate_alpha24(df) 76 | 77 | # 保存结果 78 | output_path = Path('./alpha24_results.csv') 79 | result_df.to_csv(output_path, index=False) 80 | 81 | # 打印部分结果和统计信息 82 | print("\nAlpha#24 计算完成!") 83 | print("\n前5行结果:") 84 | print(result_df[['date', 'asset_id', 'close', 'change_rate', 'min_close_100', 'delta_close_3', 'alpha24']].head()) 85 | print("\n后5行结果:") 86 | print(result_df[['date', 'asset_id', 'close', 'change_rate', 'min_close_100', 'delta_close_3', 'alpha24']].tail()) 87 | print("\nAlpha#24统计信息:") 88 | print(result_df['alpha24'].describe()) 89 | 90 | if __name__ == '__main__': 91 | main() -------------------------------------------------------------------------------- /alpha/archive/alpha25/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#25: 多因子综合排名策略 2 | 3 | ## 描述 4 | 5 | Alpha#25 的计算公式为: 6 | 7 | ``` 8 | rank(((((-1 * returns) * adv20) * vwap) * (high - close))) 9 | ``` 10 | 11 | 该 Alpha 策略包含四个主要组成部分: 12 | 13 | 1. **回报率反转**: 14 | * `-1 * returns`: 对回报率取负值,用于捕捉反转机会 15 | 16 | 2. **成交量加权**: 17 | * `adv20`: 20日平均成交量,用于衡量流动性 18 | * `vwap`: 成交量加权平均价格,反映真实交易价格水平 19 | 20 | 3. **价格差异**: 21 | * `high - close`: 当日最高价与收盘价的差值,反映日内价格变动 22 | 23 | 4. **排名标准化**: 24 | * `rank(...)`: 对所有资产的信号值进行排名,实现跨资产的标准化 25 | 26 | ## 项目结构 27 | 28 | ``` 29 | alpha-mining/ 30 | ├── data/ 31 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 32 | │ └── mock_data.csv # 生成的模拟数据文件 33 | ├── alpha/alpha25/ 34 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#25 35 | │ ├── alpha25_results.csv # 计算得到的 Alpha#25 结果文件 36 | │ ├── README.md # 本说明文档 37 | │ └── cast.md # Alpha#25 策略总结 38 | ... 39 | ``` 40 | 41 | ## 使用步骤 42 | 43 | ### 1. 环境准备 44 | 45 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库: 46 | 47 | ```bash 48 | pip install pandas numpy 49 | ``` 50 | 51 | ### 2. 数据准备 52 | 53 | 本 Alpha 依赖于 `date`, `asset_id`, `high`, `close`, `volume`, `vwap`, `returns` 数据。这些数据应存在于 `../../data/mock_data.csv` 文件中。 54 | 55 | ### 3. 计算 Alpha#25 因子 56 | 57 | 进入 `alpha/alpha25` 目录并运行 `alpha_calculator.py` 脚本: 58 | 59 | ```bash 60 | python alpha_calculator.py 61 | ``` 62 | 63 | ## Alpha#25 策略解读与计算示例 64 | 65 | 以下示例使用 `alpha25_results.csv` 中的实际数据来展示计算过程。我们以 `2025-02-06` 的数据为例: 66 | 67 | **背景数据**: 68 | - 日期: `2025-02-06` 69 | - 资产: `asset_3` 70 | - 收盘价 (`close`): `90.5` 71 | - 最高价 (`high`): `95.4` 72 | - 回报率 (`returns`): `-0.0352` 73 | - 20日平均成交量 (`adv20`): `1106227.3` 74 | - 成交量加权价格 (`vwap`): `92.3` 75 | - 最终Alpha值 (`alpha25`): `1.0`(排名后的标准化值) 76 | 77 | **计算步骤**: 78 | 79 | 1. **计算回报率反转**: 80 | * `-1 * returns = -1 * (-0.0352) = 0.0352` 81 | 82 | 2. **计算价格差异**: 83 | * `high - close = 95.4 - 90.5 = 4.9` 84 | 85 | 3. **计算因子原始值**: 86 | * `factor = (0.0352 * 1106227.3 * 92.3 * 4.9` 87 | * `factor = 17611032.418`(这是一个较大的正值,表明信号强度较强) 88 | 89 | 4. **排名标准化**: 90 | * 将所有资产的因子值排序 91 | * 转换为[0,1]区间的排名值 92 | * 该资产在当日获得最高排名1.0 93 | 94 | 这个示例展示了一个典型的多因子组合信号: 95 | - 价格出现较大跌幅(负回报率) 96 | - 日内价格波动较大(高低价差距大) 97 | - 成交量和价格水平都处于合理区间 98 | - 最终产生了最强的信号(排名第一) 99 | 100 | ## 数据需求 101 | 102 | - `date`: 交易日期 (YYYY-MM-DD) 103 | - `asset_id`: 资产ID 104 | - `high`: 最高价 105 | - `close`: 收盘价 106 | - `volume`: 成交量 107 | - `vwap`: 成交量加权平均价格 108 | - `returns`: 收益率 109 | 110 | ## 输出格式 111 | 112 | 输出的 CSV 文件 (`alpha25_results.csv`) 包含以下列: 113 | 114 | - `date`: 交易日期 115 | - `asset_id`: 资产ID 116 | - `high`: 最高价(原始数据) 117 | - `close`: 收盘价(原始数据) 118 | - `returns`: 收益率(原始数据) 119 | - `adv20`: 20日平均成交量(中间计算值) 120 | - `vwap`: 成交量加权平均价格(原始数据) 121 | - `high_close_diff`: 最高价与收盘价的差值(中间计算值) 122 | - `factor`: 排名前的原始因子值(中间计算值) 123 | - `alpha25`: 计算得到的 Alpha#25 值,为[0,1]区间的排名值 124 | 125 | ## 注意事项与风险提示 126 | 127 | 1. **数据要求**: 128 | - 需要至少20天的历史数据来计算平均成交量 129 | - 需要准确的日内价格和成交量数据 130 | - 每个资产序列的前19个Alpha值将为NaN 131 | 132 | 2. **信号特点**: 133 | - 综合考虑价格、成交量和波动性 134 | - 通过排名实现跨资产标准化 135 | - 偏好高流动性、价格回落和可能反转的资产 136 | 137 | 3. **潜在风险**: 138 | - 对数据质量要求较高 139 | - 排名可能受极端值影响 140 | - 需要足够多的资产才能实现有效排名 141 | 142 | 4. **实践建议**: 143 | - 可以调整平均成交量的计算周期(20日) 144 | - 考虑添加其他价格水平指标 145 | - 建议结合其他Alpha因子使用 -------------------------------------------------------------------------------- /alpha/archive/alpha2/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#2 策略模拟与计算 2 | 3 | 本项目演示了如何根据给定的 Alpha#2 公式生成模拟金融数据、计算 Alpha 因子,并对结果进行分析。 4 | 5 | ## Alpha#2 公式 6 | 7 | Alpha#2 的计算公式如下: 8 | 9 | ``` 10 | (-1 * correlation(rank(delta(log(volume), 2)), rank(((close - open) / open)), 6)) 11 | ``` 12 | 13 | 其中: 14 | 15 | * `volume`: 资产的日成交量。 16 | * `close`: 资产的日收盘价。 17 | * `open`: 资产的日开盘价。 18 | * `log(volume)`: 成交量的自然对数。 19 | * `delta(series, N)`: 计算时间序列 `series` 的 N 期差分,即 `series[t] - series[t-N]`。 20 | * `rank(series)`: 计算 `series` 中每个值在当日所有资产间的排序百分比(0到1之间)。值越大,排名越高。 21 | * `correlation(x, y, N)`: 计算时间序列 `x` 和 `y` 在过去 `N` 天的滚动相关系数。 22 | * `((close - open) / open)`: 日内收益率,即开盘到收盘的价格变化率。 23 | 24 | ## 项目结构 25 | 26 | ``` 27 | alpha-mining/ 28 | ├── alpha/ 29 | │ └── alpha2/ 30 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#2 31 | │ ├── alpha2_results.csv # 计算得到的 Alpha#2 结果文件 32 | │ ├── cast.md # Alpha#2 策略简要说明 33 | │ └── README.md # 本说明文档 34 | ├── data/ 35 | │ └── mock_data.csv # 模拟数据文件(包含volume和open字段) 36 | └── ... 37 | ``` 38 | 39 | ## 使用步骤 40 | 41 | ### 1. 环境准备 42 | 43 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 44 | 45 | ```bash 46 | pip install pandas numpy 47 | ``` 48 | 49 | ### 2. 数据准备 50 | 51 | 确保 `data/mock_data.csv` 文件包含以下必要字段: 52 | 53 | - `date`: 交易日期 54 | - `asset_id`: 资产标识 55 | - `close`: 收盘价 56 | - `open`: 开盘价 57 | - `volume`: 成交量 58 | 59 | ### 3. 计算 Alpha#2 因子 60 | 61 | 运行 `alpha_calculator.py` 脚本来计算 Alpha#2 因子。该脚本会读取 `data/mock_data.csv`,执行公式中的计算,并将结果保存到 `alpha2_results.csv`。 62 | 63 | ```bash 64 | cd alpha/alpha2 65 | python alpha_calculator.py 66 | ``` 67 | 68 | 脚本执行完毕后,会在终端打印出结果文件的前5行、后5行以及 Alpha#2 值的描述性统计信息。 69 | 70 | ## Alpha#2 策略解读 71 | 72 | 该 Alpha 策略试图捕捉成交量变化与日内收益率之间的负相关关系。 73 | 74 | 为了更好地理解计算过程,我们假设有以下模拟数据片段: 75 | 76 | | date | asset_id | open | close | volume | 77 | | ---------- | -------- | ------ | ------ | ------- | 78 | | 2025-01-20 | asset_1 | 99.93 | 100.5 | 3507861 | 79 | | 2025-01-21 | asset_1 | 100.79 | 99.6 | 1016495 | 80 | | 2025-01-22 | asset_1 | 98.92 | 101.6 | 825693 | 81 | | 2025-01-23 | asset_1 | 103.09 | 102.5 | 1496721 | 82 | | 2025-01-24 | asset_1 | 102.22 | 100.9 | 1692425 | 83 | | 2025-01-25 | asset_1 | 98.64 | 102.4 | 1677999 | 84 | 85 | 下面是 Alpha#2 计算的详细步骤: 86 | 87 | 1. **成交量对数差分 (`delta(log(volume), 2)`)**: 88 | 89 | * 首先计算成交量的自然对数:`log(volume)` 90 | * 然后计算2期差分:`log(volume)[t] - log(volume)[t-2]` 91 | 92 | *示例 (asset_1, 2025-01-22)*: 93 | ` ` = `13.624 - 15.070` = `-1.446` 94 | 2. **日内收益率 (`(close - open) / open`)**: 95 | 96 | * 计算每日的开盘到收盘收益率 97 | 98 | *示例 (asset_1, 2025-01-22)*: 99 | `(101.6 - 98.92) / 98.92` = `0.0271` 100 | 3. **排名计算 (`rank(...)`)**: 101 | 102 | * 分别对成交量对数差分和日内收益率进行当日横截面排名 103 | * 排名结果为0到1之间的百分位数 104 | 4. **滚动相关系数 (`correlation(..., 6)`)**: 105 | 106 | * 计算两个排名序列在过去6天的滚动相关系数 107 | * 相关系数范围在-1到1之间 108 | 5. **取负值 (`-1 * ...`)**: 109 | 110 | * 将相关系数取负值,使得负相关变为正的Alpha值 111 | * 这意味着当成交量变化与日内收益率呈负相关时,Alpha值为正 112 | 113 | ## 策略逻辑 114 | 115 | Alpha#2 的核心逻辑是: 116 | 117 | 1. **成交量动量**: 通过 `delta(log(volume), 2)` 捕捉成交量的变化趋势 118 | 2. **日内表现**: 通过 `(close - open) / open` 衡量日内价格表现 119 | 3. **负相关信号**: 当成交量增加而日内表现较差时(或成交量减少而日内表现较好时),产生正的Alpha信号 120 | 121 | 这种策略可能反映了以下市场现象: 122 | 123 | - 恐慌性抛售:成交量放大但价格下跌 124 | - 理性回调:成交量萎缩但价格稳定或小幅上涨 125 | 126 | 如需帮助或有建议,欢迎交流! 127 | -------------------------------------------------------------------------------- /alpha/archive/alpha26/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#26 - 成交量与价格高点排名相关性因子 2 | 3 | ## 因子公式 4 | 5 | `(-1 * ts_max(correlation(ts_rank(volume, 5), ts_rank(high, 5), 5), 3))` 6 | 7 | ## 因子逻辑 8 | 9 | Alpha#26 通过分析成交量和最高价的排名相关性来识别市场异常。具体步骤: 10 | 11 | 1. 分别计算成交量和最高价的5日排名 12 | 2. 计算这两个排名序列的5日相关系数 13 | 3. 取相关系数的3日最大值 14 | 4. 对结果取负值 15 | 16 | 这个因子主要用于捕捉价格和成交量的背离现象,帮助识别潜在的市场转折点。 17 | 18 | ## 项目结构 19 | 20 | ``` 21 | alpha-mining/ 22 | ├── data/ 23 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 24 | │ └── mock_data.csv # 生成的模拟数据文件 25 | ├── alpha/alpha26/ 26 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#26 27 | │ ├── alpha26_results.csv # 计算得到的 Alpha#26 结果文件 28 | │ ├── README.md # 本说明文档 29 | │ └── cast.md # Alpha#26 策略总结 30 | ... 31 | ``` 32 | 33 | ## 使用步骤 34 | 35 | ### 1. 环境准备 36 | 37 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库: 38 | 39 | ```bash 40 | pip install pandas numpy 41 | ``` 42 | 43 | ### 2. 数据准备 44 | 45 | 本 Alpha 依赖于 `date`, `asset_id`, `high`, `volume` 数据。这些数据应存在于 `../../data/mock_data.csv` 文件中。 46 | 47 | ### 3. 计算 Alpha#26 因子 48 | 49 | 进入 `alpha/alpha26` 目录并运行 `alpha_calculator.py` 脚本: 50 | 51 | ```bash 52 | python alpha_calculator.py 53 | ``` 54 | 55 | ## Alpha#26 策略解读与计算示例 56 | 57 | 以下示例使用 `alpha26_results.csv` 中的实际数据来展示计算过程。我们以 `2025-01-11` 的数据为例 (假设 asset_id 为 asset_1): 58 | 59 | **背景数据**: 60 | - 日期: `2025-01-11` 61 | - 资产: `asset_1` 62 | - 成交量 (`volume`): `539969` (示例,非真实计算依赖) 63 | - 最高价 (`high`): `99.71` (示例,非真实计算依赖) 64 | - 最终Alpha值 (`alpha26`): `-0.7` 65 | 66 | **计算步骤**: 67 | 68 | 1. **计算成交量5日排名 (`ts_rank(volume, 5)`)**: 69 | * 取最近5日的成交量数据,计算当日成交量在过去5日内的百分比排名。 70 | * 例如,若 `volume` 在 `asset_1` 于 `2025-01-07` 至 `2025-01-11` 的数据中排名较低,则得到一个较小的百分比值。 71 | 72 | 2. **计算最高价5日排名 (`ts_rank(high, 5)`)**: 73 | * 取最近5日的最高价数据,计算当日最高价在过去5日内的百分比排名。 74 | * 例如,若 `high` 在 `asset_1` 于 `2025-01-07` 至 `2025-01-11` 的数据中排名也较低,则得到一个较小的百分比值。 75 | 76 | 3. **计算排名序列的5日相关系数 (`correlation(ts_rank(volume, 5), ts_rank(high, 5), 5)`)**: 77 | * 将步骤1和2得到的两个排名序列,计算它们在过去5日的相关系数。 78 | * 如果成交量排名和最高价排名同步变化(例如,成交量排名高时,最高价排名也高),相关系数趋向于1。如果反向变化,趋向于-1。 79 | 80 | 4. **取相关系数的3日最大值 (`ts_max(correlation(...), 3)`)**: 81 | * 取步骤3计算得到的相关系数序列,在过去3日内的最大值。 82 | * 例如,若过去三天的相关系数分别为 `0.6`, `0.7`, `0.5`,则最大值为 `0.7`。 83 | 84 | 5. **取负值**: 85 | * `-1 * ts_max_correlation = -1 * 0.7 = -0.7` 86 | 87 | 这个示例展示了一个典型的信号生成过程: 88 | - 成交量和最高价在近期排名不高,并且它们之间的相关性在近期达到了一个较高的正值。 89 | - 因子最终取这个相关性最大值的负数,得到 `-0.7`。 90 | - 这可能表示近期价量关系的一种特定模式,具体解释需结合更多市场背景。 91 | 92 | ## 数据需求 93 | 94 | - `date`: 交易日期 (YYYY-MM-DD) 95 | - `asset_id`: 资产ID 96 | - `volume`: 成交量 97 | - `high`: 最高价 98 | 99 | ## 输出格式 100 | 101 | 输出的 CSV 文件 (`alpha26_results.csv`) 包含以下列: 102 | 103 | - `date`: 交易日期 104 | - `volume`: 成交量(原始数据) 105 | - `high`: 最高价(原始数据) 106 | - `alpha26`: 计算得到的 Alpha#26 值,保留两位有效数字 107 | 108 | ## 应用场景 109 | 110 | 1. 市场趋势转折点预测 111 | 2. 价量背离信号识别 112 | 3. 市场异常行为监测 113 | 4. 风险控制系统的补充指标 114 | 115 | ## 优势 116 | 117 | 1. 通过排名降低异常值影响 118 | 2. 多重时间窗口提供更稳定的信号 119 | 3. 价量结合提供更全面的市场视角 120 | 4. 适用于不同市场环境 121 | 122 | ## 局限性 123 | 124 | 1. 需要足够的历史数据(至少5日) 125 | 2. 排名计算可能存在滞后性 126 | 3. 在剧烈波动市场中可能产生误判 127 | 4. 计算复杂度相对较高 128 | 129 | ## 风险提示 130 | 131 | 1. 因子信号可能存在滞后性 132 | 2. 不同市场环境下表现不一 133 | 3. 建议与其他技术指标配合使用 134 | 4. 需要定期评估因子有效性 135 | 136 | ## 注意事项 137 | 138 | 1. 参数设置(5日和3日窗口)可能需要根据实际情况调整 139 | 2. 建议结合基本面分析使用 140 | 3. 在实盘中需要考虑交易成本 141 | 4. 适当设置止损止盈策略 -------------------------------------------------------------------------------- /alpha/archive/alpha27/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#27 - 成交量与均价排名相关性趋势因子 2 | 3 | ## 因子公式 4 | 5 | `((0.5 < rank((sum(correlation(rank(volume), rank(vwap), 6), 2) / 2.0))) ? (-1 * 1) : 1)` 6 | 7 | ## 因子逻辑 8 | 9 | Alpha#27 通过分析成交量和成交均价的排名相关性来判断市场趋势的强弱。具体步骤: 10 | 11 | 1. 计算成交量和VWAP的排名 12 | 2. 计算两个排名序列的6日相关系数 13 | 3. 对相关系数进行2日求和并取平均 14 | 4. 对结果进行排名,与0.5比较 15 | 5. 生成最终信号:大于0.5返回-1,否则返回1 16 | 17 | 这个因子主要用于判断市场趋势的持续性和转折可能。 18 | 19 | ## 项目结构 20 | 21 | ``` 22 | alpha-mining/ 23 | ├── data/ 24 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 25 | │ └── mock_data.csv # 生成的模拟数据文件 26 | ├── alpha/alpha27/ 27 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#27 28 | │ ├── alpha27_results.csv # 计算得到的 Alpha#27 结果文件 29 | │ ├── README.md # 本说明文档 30 | │ └── cast.md # Alpha#27 策略总结 31 | ... 32 | ``` 33 | 34 | ## 使用步骤 35 | 36 | ### 1. 环境准备 37 | 38 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库: 39 | 40 | ```bash 41 | pip install pandas numpy 42 | ``` 43 | 44 | ### 2. 数据准备 45 | 46 | 本 Alpha 依赖于 `date`, `asset_id`, `volume`, `vwap` 数据。这些数据应存在于 `../../data/mock_data.csv` 文件中。 47 | 48 | ### 3. 计算 Alpha#27 因子 49 | 50 | 进入 `alpha/alpha27` 目录并运行 `alpha_calculator.py` 脚本: 51 | 52 | ```bash 53 | python alpha_calculator.py 54 | ``` 55 | 56 | ## Alpha#27 策略解读与计算示例 57 | 58 | 以下示例使用 `alpha27_results.csv` 中的实际数据来展示计算过程。我们以 `2025-01-07` 的数据为例 (假设 asset_id 为 asset_1): 59 | 60 | **背景数据**: 61 | - 日期: `2025-01-07` 62 | - 资产: `asset_1` 63 | - 成交量 (`volume`): `2713351` 64 | - 成交量加权平均价 (`vwap`): `101.6` 65 | - 最终Alpha值 (`alpha27`): `-1.0` 66 | 67 | **计算步骤**: 68 | 69 | 1. **计算成交量排名 (`rank(volume)`)**: 70 | * 对当日所有资产的成交量进行横向比较,并计算其百分比排名。例如,`asset_1` 的成交量 `2713351` 在当日所有资产中可能处于较高水平,得到一个较高的排名值(如0.8)。 71 | 72 | 2. **计算VWAP排名 (`rank(vwap)`)**: 73 | * 对当日所有资产的VWAP进行横向比较,并计算其百分比排名。例如,`asset_1` 的VWAP `101.6` 在当日所有资产中也可能处于较高水平,得到一个较高的排名值(如0.75)。 74 | 75 | 3. **计算排名序列的6日相关系数 (`correlation(rank(volume), rank(vwap), 6)`)**: 76 | * 对于 `asset_1`,获取过去6日的成交量排名序列和VWAP排名序列。 77 | * 计算这两个时间序列之间的相关系数。 78 | 79 | 4. **相关系数的2日加总并平均 (`sum(correlation(...), 2) / 2.0`)**: 80 | * 取步骤3得到的相关系数序列,计算其最近2日的和,然后除以2,得到一个平滑后的相关性指标。 81 | 82 | 5. **对平滑后的相关性指标进行排名 (`rank((sum(...) / 2.0))`)**: 83 | * 将步骤4中计算得到的平滑相关性指标,在当日所有资产间进行横向百分比排名。 84 | * 假设 `asset_1` 在此步骤的排名值为 `0.6`。 85 | 86 | 6. **条件判断并生成信号**: 87 | * 判断 `0.5 < rank_value` (即 `0.5 < 0.6`)。此条件为真。 88 | * 因为条件为真,所以 Alpha#27 的值为 `-1`。 89 | 90 | 这个示例展示了一个典型的信号生成过程: 91 | - 成交量和VWAP的排名,以及它们之间的相关性变化,共同决定了最终的因子值。 92 | - 当一系列计算后的最终排名超过0.5时,因子输出-1,可能表示一种趋势反转或特定市场状态的信号。 93 | 94 | ## 数据需求 95 | 96 | - `date`: 交易日期 (YYYY-MM-DD) 97 | - `asset_id`: 资产ID 98 | - `volume`: 成交量 99 | - `vwap`: 成交量加权平均价格 100 | 101 | ## 输出格式 102 | 103 | 输出的 CSV 文件 (`alpha27_results.csv`) 包含以下列: 104 | 105 | - `date`: 交易日期 106 | - `volume`: 成交量(原始数据) 107 | - `vwap`: 成交量加权平均价格(原始数据) 108 | - `alpha27`: 计算得到的 Alpha#27 值(-1 或 1),保留两位有效数字 109 | 110 | ## 应用场景 111 | 112 | 1. 市场趋势强度判断 113 | 2. 趋势持续性预测 114 | 3. 交易量价关系分析 115 | 4. 市场情绪监测 116 | 117 | ## 优势 118 | 119 | 1. 信号明确(1或-1) 120 | 2. 考虑了量价关系的动态变化 121 | 3. 通过排名消除数值差异影响 122 | 4. 适合趋势跟踪策略 123 | 124 | ## 局限性 125 | 126 | 1. 需要足够的历史数据(至少6日) 127 | 2. 可能错过快速反转机会 128 | 3. 在震荡市场中可能频繁变换信号 129 | 4. 依赖VWAP的准确计算 130 | 131 | ## 风险提示 132 | 133 | 1. 信号切换可能带来过高换手率 134 | 2. 在高波动期可能产生误判 135 | 3. 需要考虑交易成本的影响 136 | 4. 建议配合其他指标使用 137 | 138 | ## 注意事项 139 | 140 | 1. 参数设置(6日和2日窗口)可能需要调整 141 | 2. 建议设置信号过滤机制 142 | 3. 考虑加入止损策略 143 | 4. 定期评估因子有效性 -------------------------------------------------------------------------------- /alpha/archive/alpha24/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#24: 价格变化率与历史最小值的条件选择策略 2 | 3 | ## 描述 4 | 5 | Alpha#24 的计算公式为: 6 | 7 | ``` 8 | ((((delta((sum(close, 100) / 100), 100) / delay(close, 100)) < 0.05) || 9 | ((delta((sum(close, 100) / 100), 100) / delay(close, 100)) == 0.05)) ? (-1 * (close - ts_min(close, 10 | 100))) : (-1 * delta(close, 3))) 11 | ``` 12 | 13 | 该 Alpha 策略包含两个主要部分: 14 | 15 | 1. **条件判断部分**: 16 | * `delta((sum(close, 100) / 100), 100) / delay(close, 100)`: 计算100日移动平均的变化率 17 | * `< 0.05 || == 0.05`: 判断变化率是否小于等于5% 18 | 19 | 2. **信号生成部分**: 20 | * 当变化率≤5%时:`-1 * (close - ts_min(close, 100))` (当前价格与100日最低价之差的负值) 21 | * 当变化率>5%时:`-1 * delta(close, 3)` (3日价格差分的负值) 22 | 23 | ## 项目结构 24 | 25 | ``` 26 | alpha-mining/ 27 | ├── data/ 28 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 29 | │ └── mock_data.csv # 生成的模拟数据文件 30 | ├── alpha/alpha24/ 31 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#24 32 | │ ├── alpha24_results.csv # 计算得到的 Alpha#24 结果文件 33 | │ ├── README.md # 本说明文档 34 | │ └── cast.md # Alpha#24 策略总结 35 | ``` 36 | 37 | ## 使用步骤 38 | 39 | ### 1. 环境准备 40 | 41 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 42 | 43 | ```bash 44 | pip install pandas numpy 45 | ``` 46 | 47 | ### 2. 数据准备 48 | 49 | 本 Alpha 策略依赖于 `close` 数据。请确保 `../../data/mock_data.csv` 文件存在并包含以下必要字段: 50 | - `date`: 交易日期 51 | - `asset_id`: 资产标识 52 | - `close`: 收盘价 53 | 54 | ### 3. 计算 Alpha#24 因子 55 | 56 | 进入 `alpha/alpha24` 目录并运行 `alpha_calculator.py` 脚本: 57 | 58 | ```bash 59 | cd alpha/alpha24 60 | python alpha_calculator.py 61 | ``` 62 | 63 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#24,并将结果保存到当前目录下的 `alpha24_results.csv`。同时会在终端打印部分结果和统计信息。 64 | 65 | ## Alpha#24 策略解读与计算示例 66 | 67 | 以下示例使用 `alpha24_results.csv` 中的实际数据来展示计算过程。我们以 `asset_5` 在 `2025-02-02` 的数据为例: 68 | 69 | **背景数据**: 70 | - 日期: `2025-02-02` 71 | - 资产ID: `asset_5` 72 | - 当日收盘价 (`close`): `115.6` 73 | - 3日价格差分 (`delta_close_3`): `9.6` 74 | - 最终Alpha值 (`alpha24`): `-9.6` 75 | 76 | **计算步骤**: 77 | 78 | 1. **计算100日移动平均的变化率**: 79 | * 由于数据量不足100天,我们暂时无法计算这个值 80 | * 在实际应用中,这个值用于判断市场环境 81 | 82 | 2. **条件判断**: 83 | * 在数据量不足的情况下,默认使用3日差分策略 84 | * 即 `-1 * delta(close, 3)` 85 | 86 | 3. **计算3日价格差分**: 87 | * `delta_close_3 = close_today - close_3_days_ago` 88 | * `delta_close_3 = 115.6 - 106.0 = 9.6` 89 | 90 | 4. **生成Alpha信号**: 91 | * 计算 `-1 * delta_close_3` 92 | * `alpha24 = -1 * 9.6 = -9.6` 93 | 94 | 这个示例展示了一个典型的信号生成过程: 95 | - 在3日内价格大幅上涨(`delta_close_3`为正且较大) 96 | - 生成了一个较大的负向信号(`-9.6`) 97 | - 这表明策略预期价格可能会回落 98 | 99 | ## 数据需求 100 | 101 | - `date`: 交易日期 (YYYY-MM-DD) 102 | - `asset_id`: 资产ID 103 | - `close`: 每日收盘价 104 | 105 | ## 输出格式 106 | 107 | 输出的 CSV 文件 (`alpha24_results.csv`) 包含以下列: 108 | 109 | - `date`: 交易日期 110 | - `asset_id`: 资产ID 111 | - `close`: 当日收盘价(原始数据) 112 | - `ma_100`: 100日移动平均(中间计算值,保留四位小数) 113 | - `delta_ma_100`: 100日移动平均的变化值(中间计算值) 114 | - `change_rate`: 变化率(中间计算值) 115 | - `min_close_100`: 100日最低价(中间计算值) 116 | - `delta_close_3`: 3日价格差分(中间计算值) 117 | - `alpha24`: 计算得到的 Alpha#24 值,保留两位有效数字 118 | 119 | ## 注意事项与风险提示 120 | 121 | 1. **数据窗口要求**: 122 | - 需要至少100天的历史数据来计算移动平均和最低价 123 | - 需要至少3天的历史数据来计算差分 124 | - 每个资产序列的前99个Alpha值将为NaN 125 | 126 | 2. **信号特点**: 127 | - 根据市场环境自动切换策略 128 | - 在低波动环境下关注价格与历史最低点的距离 129 | - 在高波动环境下关注短期价格变化 130 | 131 | 3. **潜在风险**: 132 | - 在市场环境转换点可能产生错误信号 133 | - 对历史数据依赖性较强 134 | - 需要较长的数据积累期 135 | 136 | 4. **实践建议**: 137 | - 可以调整变化率阈值(5%)以适应不同市场 138 | - 考虑添加其他市场环境判断指标 139 | - 建议进行充分的回测验证 -------------------------------------------------------------------------------- /alpha/alpha41/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#41: 价格几何平均与VWAP偏离度策略 2 | 3 | ## 描述 4 | 5 | Alpha#41 的计算公式为: 6 | 7 | ``` 8 | Alpha#41 = ((high * low)^0.5) - vwap 9 | ``` 10 | 11 | 这个 Alpha 策略旨在捕捉日内价格的一个"内在价值"与其"市场成交重心"之间的偏离。它由两个核心部分组成: 12 | 13 | 1. **几何平均价**: `(high * low)^0.5` 14 | * 计算当日最高价 (`high`) 和最低价 (`low`) 的几何平均数。 15 | * 与算术平均数 `(high + low) / 2` 相比,几何平均数对极端价格的敏感度较低,能更稳健地代表当日价格范围的中心水平。可以将其视为当日价格的一个"内在价值中枢"。 16 | 17 | 2. **成交量加权平均价**: `vwap` 18 | * `vwap` (Volume-Weighted Average Price) 是当日的总成交额除以总成交量得到的平均价格。 19 | * 它代表了市场中大部分交易发生的平均成本,即当日的"市场成交重心"。 20 | 21 | 最终的 Alpha#41 值为这两者之差。一个正值表示内在价值中枢高于市场成交重心,可能暗示看涨情绪;一个负值则反之,可能暗示看跌情绪。 22 | 23 | ## 项目结构 24 | 25 | ``` 26 | alpha-mining/ 27 | ├── data/ 28 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (确保包含 high, low, vwap) 29 | │ └── mock_data.csv # 生成的模拟数据文件 30 | ├── alpha/alpha41/ 31 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#41 32 | │ ├── alpha41_results.csv # 计算得到的 Alpha#41 结果文件 33 | │ ├── README.md # 本说明文档 34 | │ └── cast.md # Alpha#41 策略简介 35 | ``` 36 | 37 | ## 使用步骤 38 | 39 | ### 1. 环境准备 40 | 41 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。 42 | 43 | ```bash 44 | pip install pandas numpy 45 | ``` 46 | 47 | ### 2. 检查模拟数据 48 | 49 | 本 Alpha 依赖于 `high`, `low`, 和 `vwap` 数据。请确保 `data/mock_data.csv` 文件存在且包含这些列。如果文件不存在或数据不完整,请运行或修改 `data/generate_mock_data.py`。 50 | 51 | ### 3. 计算 Alpha#41 因子 52 | 53 | 进入 `alpha/alpha41` 目录并运行 `alpha_calculator.py` 脚本: 54 | 55 | ```bash 56 | python alpha_calculator.py 57 | ``` 58 | 59 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#41,并将结果保存到当前目录下的 `alpha41_results.csv`。 60 | 61 | ## Alpha#41 策略解读与计算示例 62 | 63 | 为了更好地理解该因子的计算过程,我们以 `alpha41_results.csv` 中 `asset_1` 在 `2024-06-01` 的数据为例进行拆解。 64 | 65 | **背景数据 (源自 `alpha41_results.csv`):** 66 | - `date`: 2024-06-01 67 | - `asset_id`: asset_1 68 | - `high`: 100.28 69 | - `low`: 99.08 70 | - `vwap`: 99.41 71 | 72 | **计算步骤:** 73 | 74 | 1. **计算几何平均价 (`geometric_mean_high_low`)**: 75 | ``` 76 | geometric_mean = (high * low)^0.5 77 | geometric_mean = (100.28 * 99.08)^0.5 78 | geometric_mean = (9935.7824)^0.5 79 | geometric_mean = 99.678... 80 | ``` 81 | 四舍五入到两位小数后,得到 `99.68`。 82 | 83 | 2. **计算 Alpha#41**: 84 | ``` 85 | Alpha#41 = geometric_mean - vwap 86 | Alpha#41 = 99.68 - 99.41 87 | Alpha#41 = 0.27 88 | ``` 89 | 90 | 此结果与 `alpha41_results.csv` 文件中对应行的 `alpha41` 值 `0.27` 相符。这表明,在 `2024-06-01` 这一天,`asset_1` 的价格内在价值中枢略高于其市场成交重心。 91 | 92 | ## 数据要求 93 | 94 | - `date`: 交易日期 (datetime) 95 | - `asset_id`: 资产ID (string/object) 96 | - `high`: 当日最高价 (float) 97 | - `low`: 当日最低价 (float) 98 | - `vwap`: 当日成交量加权平均价 (float) 99 | 100 | ## 输出格式 101 | 102 | 输出的 CSV 文件 (`alpha41_results.csv`) 将包含所有原始数据列以及以下新列,所有数值型 alpha 相关列均保留两位小数: 103 | 104 | - `geometric_mean_high_low`: `high` 和 `low` 的几何平均数,作为中间计算结果。 105 | - `alpha41`: 最终计算的 Alpha#41 值。 106 | 107 | 在保存到CSV之前,所有 `alpha41` 值为 NaN 的行都会被移除。 108 | 109 | ## 注意事项与风险提示 110 | 111 | - **数据完整性**: `alpha_calculator.py` 脚本会检查 `high`, `low`, `vwap` 等必需列是否存在。如果任一数据缺失,将导致该行的 `alpha41` 值为 NaN,并最终被从输出结果中剔除。 112 | - **因子解释**: 113 | * **正值**: 表明价格内在价值高于市场成交重心。这可能是一个看涨信号,暗示市场有潜在的上涨动力,或者当日的买入力量主要集中在较高的价格区间。 114 | * **负值**: 表明价格内在价值低于市场成交重心。这可能是一个看跌信号,暗示市场承受着下行压力,或者当日的主要成交量发生在比价格中枢更高的位置,形成了压力位。 115 | - **市场适用性**: 该因子是一个日内指标,其有效性可能在不同波动性、不同流动性的市场或资产上表现各异。建议进行充分的回测和验证。 116 | - **与其他因子结合**: Alpha#41 关注的是日内价格结构,可作为多元化投资组合中的一个因子,与其他基于趋势、动量或价值的因子结合使用。 117 | - **无未来保证**: 任何历史数据分析和因子构建都不保证未来的盈利能力。市场条件会不断变化。 -------------------------------------------------------------------------------- /alpha/archive/alpha21/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#21: 均值与波动率条件反转因子 2 | 3 | ## 描述 4 | 5 | Alpha#21 的计算公式为: 6 | 7 | ``` 8 | Alpha#21 = ((((sum(close, 8) / 8) + stddev(close, 8)) < (sum(close, 2) / 2)) ? (-1) : (((sum(close, 2) / 2) < ((sum(close, 8) / 8) - stddev(close, 8))) ? 1 : (((1 < (volume / adv20)) || ((volume / adv20) == 1)) ? 1 : -1))) 9 | ``` 10 | 11 | 该因子通过均值、波动率和成交量的多重条件,捕捉价格短期反转与量能驱动信号。 12 | 13 | **核心逻辑**: 14 | 1. 计算8日均价 `sum(close, 8) / 8` 和8日波动率 `stddev(close, 8)`。 15 | 2. 计算2日均价 `sum(close, 2) / 2`。 16 | 3. 若"8日均价+8日波动率"小于2日均价,给出-1信号(短期价格偏高,预期回落)。 17 | 4. 若2日均价小于"8日均价-8日波动率",给出+1信号(短期价格偏低,预期反弹)。 18 | 5. 否则,若成交量大于等于20日均量,给出+1信号(量能驱动上涨);否则给出-1信号。 19 | 20 | ## 项目结构 21 | 22 | ``` 23 | alpha-mining/ 24 | ├── data/ 25 | │ └── mock_data.csv 26 | ├── alpha/alpha21/ 27 | │ ├── alpha_calculator.py 28 | │ ├── alpha21_results.csv 29 | │ ├── README.md 30 | │ └── cast.md 31 | ``` 32 | 33 | ## 使用步骤 34 | 35 | 1. 确保已安装 pandas、numpy。 36 | 2. 数据文件 `data/mock_data.csv` 需包含 `date`, `asset_id`, `close`, `volume`。 37 | 3. 运行 `alpha/alpha21/alpha_calculator.py`,结果输出到 `alpha21_results.csv`。 38 | 39 | ```bash 40 | cd alpha/alpha21 41 | python alpha_calculator.py 42 | ``` 43 | 44 | ## 数据需求 45 | - `date`: 交易日期 46 | - `asset_id`: 资产ID 47 | - `close`: 收盘价 48 | - `volume`: 成交量 49 | 50 | ## 输出格式 51 | 输出CSV包含: 52 | - 原始数据列(如有):`date`, `asset_id`, `open`, `high`, `low`, `close`, `volume` 53 | - 计算列: 54 | - `close_mean_8`:8日均价 55 | - `close_std_8`:8日收盘价标准差 56 | - `close_mean_2`:2日均价 57 | - `adv20`:20日均量 58 | - `volume_over_adv20`:成交量/20日均量 59 | - `cond1`:条件1(8日均价+8日波动率 < 2日均价) 60 | - `cond2`:条件2(2日均价 < 8日均价-8日波动率) 61 | - `cond3`:条件3(成交量大于等于20日均量) 62 | - `alpha21`:最终信号,取值为1或-1,保留两位有效数字 63 | 64 | | 字段名 | 含义 | 备注 | 65 | |---------------------|------------------------------|----------------| 66 | | close_mean_8 | 8日均价 | | 67 | | close_std_8 | 8日收盘价标准差 | | 68 | | close_mean_2 | 2日均价 | | 69 | | adv20 | 20日均量 | | 70 | | volume_over_adv20 | 成交量/20日均量 | | 71 | | cond1 | 条件1 | 布尔值 | 72 | | cond2 | 条件2 | 布尔值 | 73 | | cond3 | 条件3 | 布尔值 | 74 | | alpha21 | 最终信号 | 1或-1,两位有效数字 | 75 | 76 | ## 计算步骤示例 77 | 78 | 以某资产2025-01-21为例: 79 | 80 | | date | asset_id | close | volume | close_mean_8 | close_std_8 | close_mean_2 | adv20 | volume_over_adv20 | cond1 | cond2 | cond3 | alpha21 | 81 | |------------|----------|-------|--------|--------------|-------------|--------------|-------|-------------------|-------|-------|-------|---------| 82 | | 2025-01-21 | asset_1 | 98.20 | 12000 | 97.50 | 1.20 | 98.00 | 11000 | 1.09 | False | True | True | 1 | 83 | 84 | - `close_mean_8` = 97.50 85 | - `close_std_8` = 1.20 86 | - `close_mean_2` = 98.00 87 | - `adv20` = 11000 88 | - `volume_over_adv20` = 1.09 89 | - `cond1` = False 90 | - `cond2` = True 91 | - `cond3` = True 92 | - 满足cond2,alpha21=1 93 | 94 | ## NaN与窗口期说明 95 | - 需至少20天数据,前19天alpha21为NaN。 96 | - 相关中间变量如`close_mean_8`、`adv20`等,窗口不足时为NaN。 97 | - 每个资产独立计算窗口。 98 | 99 | ## 信号解读 100 | - alpha21=1:短期价格偏低或量能放大,预期反弹/上涨 101 | - alpha21=-1:短期价格偏高或量能不足,预期回落/下跌 102 | 103 | ## 注意事项 104 | - 仅在数据缺失且无法由现有数据推导时,才修改data脚本。 105 | - 量价数据异常会影响因子表现,建议先行数据清洗。 106 | - 本因子为示例,实际效果需回测验证。 -------------------------------------------------------------------------------- /alpha/alpha33/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#33: 价格反转因子 2 | 3 | ## 描述 4 | 5 | Alpha#33 的计算公式为: 6 | 7 | ``` 8 | Alpha#33: rank((-1 * ((1 - (open / close))^1))) 9 | ``` 10 | 11 | 这个 Alpha 策略旨在捕捉基于开盘价和收盘价关系的价格反转信号。公式可以简化为 `rank(-1 * (1 - (open / close)))`。 12 | 13 | 1. **开盘价与收盘价的比率**: `(open / close)` 14 | * 计算每日开盘价与收盘价的比率。 15 | 2. **1 减去比率**: `(1 - (open / close))` 16 | * 这个值反映了当日价格变化的幅度。如果收盘价高于开盘价(上涨),则此值小于1,`1 - (open / close)` 为负数;如果收盘价低于开盘价(下跌),则此值大于1,`1 - (open / close)` 为正数。 17 | 3. **取负值**: `-1 * (1 - (open / close))` 18 | * 对上述结果取负。这意味着如果当日上涨,结果为正;如果当日下跌,结果为负。这将其转换为一个"反转"信号:上涨越多,这个值越正;下跌越多,这个值越负。 19 | 4. **截面排名**: `rank(...)` 20 | * 对每日所有资产的计算结果进行截面排名。排名越高,表示该资产当日的反转信号越强(即,下跌越多,或上涨越少,相对而言更可能是反转的候选)。 21 | 22 | 最终的 Alpha#33 值是上述计算结果的截面排名。 23 | 24 | ## 项目结构 25 | 26 | ``` 27 | alpha-mining/ 28 | ├── data/ 29 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (确保包含 open, close 字段) 30 | │ └── mock_data.csv # 生成的模拟数据文件 31 | ├── alpha/alpha33/ 32 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#33 33 | │ ├── alpha33_results.csv # 计算得到的 Alpha#33 结果文件 34 | │ ├── README.md # 本说明文档 35 | │ └── cast.md # Alpha#33 策略简介 36 | ``` 37 | 38 | ## 使用步骤 39 | 40 | ### 1. 环境准备 41 | 42 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 43 | 44 | ```bash 45 | pip install pandas numpy 46 | ``` 47 | 48 | ### 2. 检查模拟数据 49 | 50 | 本 Alpha 依赖于 `open` 和 `close` 数据。请确保 `data/mock_data.csv` 文件存在,并且包含了 `date`, `asset_id`, `open`, `close` 列。如果文件不存在或数据不完整,请运行或修改 `data/generate_mock_data.py` 脚本。 51 | 52 | ```bash 53 | # 检查或生成数据 (如果需要) 54 | cd ../../data # 假设当前在 alpha/alpha33 目录 55 | python generate_mock_data.py # 假设此脚本能生成所需字段 56 | cd ../alpha/alpha33 57 | ``` 58 | 59 | ### 3. 计算 Alpha#33 因子 60 | 61 | 进入 `alpha/alpha33` 目录并运行 `alpha_calculator.py` 脚本: 62 | 63 | ```bash 64 | python alpha_calculator.py 65 | ``` 66 | 67 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#33,并将结果保存到当前目录下的 `alpha33_results.csv`。 68 | 69 | ## 数据需求 70 | 71 | - `date`: 交易日期 (datetime) 72 | - `asset_id`: 资产ID (string/object) 73 | - `open`: 每日开盘价 (float) 74 | - `close`: 每日收盘价 (float) 75 | - (脚本还会包含 `high`, `low`, `volume`, `vwap`, `returns` 等在 `mock_data.csv` 中的其他列,以保持数据完整性) 76 | 77 | ## 输出格式 78 | 79 | 输出的 CSV 文件 (`alpha33_results.csv`) 将包含以下列(除了原始数据列),所有数值型 alpha 相关列均保留两位小数: 80 | 81 | - `date`: 交易日期 82 | - `asset_id`: 资产ID 83 | - `open`, `high`, `low`, `close`, `volume`, `vwap`, `returns`: 原始数据中的对应列 84 | - `alpha33`: 最终计算的 Alpha#33 值。 85 | 86 | ## 注意事项与风险提示 87 | 88 | - **NaN 值**: 如果 `open` 或 `close` 数据缺失,相应的 Alpha 值将为 NaN。 89 | - **排名方法**: `pandas` 的 `rank(method='average', pct=True)` 通常用于截面排名,结果是百分比形式。 90 | - **小数位数**: 最终的 Alpha#33 值按要求保留两位小数。 91 | - **市场适用性**: 此因子在不同市场环境或资产类别上表现可能迥异。务必进行充分的回测和验证。 92 | - **数据质量**: 输入数据的准确性和完整性至关重要。 93 | 94 | Alpha#33 是一个基于价格关系的因子,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 95 | 96 | ## 策略解读与计算示例 97 | 98 | 我们将以 `asset_1` 在日期 `2025-01-01` 的数据为例,展示 Alpha#33 的计算。 99 | 100 | **背景数据 (源自 `alpha33_results.csv` for `asset_1` on `2025-01-01`):** 101 | - `open`: 100.30 102 | - `close`: 100.00 103 | - `alpha33`: 0.80 104 | 105 | **计算 Alpha#33:** 106 | 1. 计算 `(1 - (open / close))`: 107 | `1 - (100.30 / 100.00) = 1 - 1.003 = -0.003` 108 | 2. 乘以 `-1`: 109 | `-1 * (-0.003) = 0.003` 110 | 3. 对所有资产在 `2025-01-01` 的此中间结果进行截面排名: 111 | * `asset_1`: 0.003 112 | * `asset_2`: 0.0053 113 | * `asset_3`: -0.0008 114 | * `asset_4`: -0.0034 115 | * `asset_5`: -0.001 116 | 117 | 按照数值从小到大排序,并进行百分比排名: 118 | - `asset_4` (-0.0034) -> 排名 0.20 119 | - `asset_5` (-0.001) -> 排名 0.40 120 | - `asset_3` (-0.0008) -> 排名 0.60 121 | - `asset_1` (0.003) -> 排名 0.80 122 | - `asset_2` (0.0053) -> 排名 1.00 123 | 124 | 因此,`Alpha#33` 对 `asset_1` 在 `2025-01-01` 的最终计算值为 `0.80`。 125 | 126 | 此值与 `alpha33_results.csv` 中 `asset_1` 在 `2025-01-01` 的 `alpha33` 列的值 `0.80` 相符。 -------------------------------------------------------------------------------- /alpha/alpha35/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#35: 交易量与价格综合因子 2 | 3 | ## 因子定义 4 | 5 | ``` 6 | ((Ts_Rank(volume, 32) * (1 - Ts_Rank(((close + high) - low), 16))) * (1 - Ts_Rank(returns, 32))) 7 | ``` 8 | 9 | ## 计算逻辑 10 | 11 | Alpha#35 是一个结合了交易量、价格波动和回报率时间序列排名的综合因子。其旨在捕捉市场中由这些基本指标共同驱动的潜在机会。 12 | 13 | 1. **`Ts_Rank(volume, 32)`**: 计算过去32天交易量的时间序列排名。较高的排名表示近期交易量相对较大,可能反映市场活跃度。 14 | 2. **`Ts_Rank(((close + high) - low), 16)`**: 计算过去16天 `(收盘价 + 最高价 - 最低价)` 这个价格项的时间序列排名。这个价格项可以看作是衡量每日价格动量和波动范围的指标。`1 - Ts_Rank(...)` 意味着当该价格项的排名较低时(例如,价格动量或波动相对较小),对Alpha值贡献越大。 15 | 3. **`Ts_Rank(returns, 32)`**: 计算过去32天每日回报率的时间序列排名。`1 - Ts_Rank(...)` 意味着当回报率的排名较低时(例如,近期回报率相对较差),对Alpha值贡献越大,可能暗示某种反转或超跌机会。 16 | 17 | 最终的 Alpha#35 值通过将这三个组件(经过适当的转换和排名)相乘得到。该因子倾向于在交易量较大、价格动量或波动相对较小、且近期回报率相对较低的市场条件下产生较高的值。 18 | 19 | ## 项目结构 20 | 21 | ``` 22 | alpha-mining/ 23 | ├── data/ 24 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (确保包含 close, high, low, volume, returns 字段) 25 | │ └── mock_data.csv # 生成的模拟数据文件 26 | ├── alpha/alpha35/ 27 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#35 28 | │ ├── alpha35_results.csv # 计算得到的 Alpha#35 结果文件 29 | │ ├── README.md # 本说明文档 30 | │ └── cast.md # Alpha#35 策略简介 31 | ``` 32 | 33 | ## 使用步骤 34 | 35 | ### 1. 环境准备 36 | 37 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 38 | 39 | ```bash 40 | pip install pandas numpy 41 | ``` 42 | 43 | ### 2. 检查模拟数据 44 | 45 | 本 Alpha 依赖于 `close`, `high`, `low`, `volume`, `returns` 数据。请确保 `data/mock_data.csv` 文件存在,并且包含了所有必需的列。如果文件不存在或数据不完整,请运行或修改 `data/generate_mock_data.py` 脚本。 46 | 47 | ```bash 48 | # 检查或生成数据 (如果需要) 49 | cd ../../data # 假设当前在 alpha/alpha35 目录 50 | python generate_mock_data.py # 假设此脚本能生成所需字段 51 | cd ../alpha/alpha35 52 | ``` 53 | 54 | ### 3. 计算 Alpha#35 因子 55 | 56 | 进入 `alpha/alpha35` 目录并运行 `alpha_calculator.py` 脚本: 57 | 58 | ```bash 59 | python alpha_calculator.py 60 | ``` 61 | 62 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#35,并将结果保存到当前目录下的 `alpha35_results.csv`。 63 | 64 | ## 数据输入 65 | 66 | * `volume`: 每日成交量。 67 | * `close`: 每日收盘价。 68 | * `high`: 每日最高价。 69 | * `low`: 每日最低价。 70 | * `returns`: 每日收盘价到收盘价的回报。 71 | 72 | 这些数据预计从 `../../data/mock_data.csv` 文件中获取。 73 | 74 | ## 输出格式 75 | 76 | 输出的 CSV 文件 (`alpha35_results.csv`) 将包含所有原始数据列以及计算得到的 `Alpha#35` 值。所有数值型 Alpha 相关列均保留两位小数。 77 | 78 | ## 因子数值范围 79 | 80 | `Alpha#35` 的理论数值区间为 `[0, 1]`。 81 | 82 | 这主要归因于 `ts_rank` 函数的实现。在 `alpha_calculator.py` 中,`ts_rank` 函数返回的是时间序列在指定窗口内的百分位排名,其值域被归一化到 `[0, 1]` 之间。 83 | 84 | * `Ts_Rank(volume, 32)`: 返回 `[0, 1]` 范围内的值。 85 | * `1 - Ts_Rank(((close + high) - low), 16)`: `Ts_Rank` 返回 `[0, 1]`,因此 `1 - Ts_Rank` 也返回 `[0, 1]`。 86 | * `1 - Ts_Rank(returns, 32)`: `Ts_Rank` 返回 `[0, 1]`,因此 `1 - Ts_Rank` 也返回 `[0, 1]`。 87 | 88 | 最终的 `Alpha#35` 是这三个 `[0, 1]` 范围内的值的乘积,因此其结果也自然落在 `[0, 1]` 的区间内。 89 | 90 | ## 策略解读与计算示例 91 | 92 | 为了更好地理解Alpha#35的计算逻辑和数值特性,我们假设在某个交易日,对于某个资产,各分量的时间序列排名(归一化至[0,1]区间)如下: 93 | 94 | * `Ts_Rank(volume, 32)` = 0.80 (表示当前交易量在过去32天中相对较高) 95 | * `Ts_Rank(((close + high) - low), 16)` = 0.20 (表示价格动量/波动在过去16天中相对较低) 96 | * `Ts_Rank(returns, 32)` = 0.10 (表示回报率在过去32天中相对较低) 97 | 98 | 根据公式: 99 | `Alpha#35 = (Ts_Rank(volume, 32) * (1 - Ts_Rank(((close + high) - low), 16))) * (1 - Ts_Rank(returns, 32))` 100 | 101 | 代入假设值进行计算: 102 | 103 | * `1 - Ts_Rank(((close + high) - low), 16)` = `1 - 0.20 = 0.80` 104 | * `1 - Ts_Rank(returns, 32)` = `1 - 0.10 = 0.90` 105 | 106 | 因此: 107 | `Alpha#35 = 0.80 * 0.80 * 0.90 = 0.64 * 0.90 = 0.576` 108 | 109 | 四舍五入到两位小数后,结果为 `0.58`。 110 | 111 | 这个例子说明,当交易量排名较高,同时价格动量和回报率排名较低时,Alpha#35 因子将产生较高的值,这符合因子旨在捕捉特定市场模式的预期。 112 | 113 | ## 注意事项与风险提示 114 | 115 | * **NaN 值**: 如果输入数据缺失,相应的 Alpha 值将为 NaN。请确保数据完整性。 116 | * **时间序列排名**: `Ts_Rank` 函数的计算基于过去指定天数的数据。在数据序列的开头,由于历史数据不足,可能会出现 NaN 值。 117 | * **小数位数**: 最终的 Alpha#35 值按要求保留两位小数。 118 | * **市场适用性**: 此因子在不同市场环境或资产类别上表现可能迥异。务必进行充分的回测和验证。 119 | * **数据质量**: 输入数据的准确性和完整性至关重要。 120 | 121 | Alpha#35 因子不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 122 | -------------------------------------------------------------------------------- /alpha/archive/alpha26/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from typing import Union, Optional 4 | from pathlib import Path 5 | import logging 6 | 7 | # 设置日志 8 | logging.basicConfig(level=logging.INFO) 9 | logger = logging.getLogger(__name__) 10 | 11 | class Alpha26Calculator: 12 | """Alpha#26 因子计算器 13 | 14 | 计算公式: (-1 * ts_max(correlation(ts_rank(volume, 5), ts_rank(high, 5), 5), 3)) 15 | """ 16 | 17 | def __init__(self, data_path: Union[str, Path]): 18 | """初始化计算器 19 | 20 | Args: 21 | data_path: 数据文件路径 22 | """ 23 | self.data_path = Path(data_path) 24 | self.data = None 25 | self.result = None 26 | 27 | def load_data(self) -> None: 28 | """加载数据""" 29 | logger.info(f"正在从 {self.data_path} 加载数据...") 30 | try: 31 | self.data = pd.read_csv(self.data_path, index_col=0) 32 | self.data.index = pd.to_datetime(self.data.index) 33 | logger.info(f"数据加载完成,共 {len(self.data)} 条记录") 34 | except Exception as e: 35 | logger.error(f"数据加载失败: {e}") 36 | raise 37 | 38 | def ts_rank(self, series: pd.Series, window: int) -> pd.Series: 39 | """计算时序排名 40 | 41 | Args: 42 | series: 输入序列 43 | window: 窗口大小 44 | 45 | Returns: 46 | 排名序列 47 | """ 48 | return series.rolling(window).rank(pct=True) 49 | 50 | def calculate_alpha(self) -> None: 51 | """计算 Alpha#26 因子值""" 52 | try: 53 | # 确保数据已加载 54 | if self.data is None: 55 | self.load_data() 56 | 57 | # 计算成交量和最高价的5日排名 58 | volume_rank = self.ts_rank(self.data['volume'], 5) 59 | high_rank = self.ts_rank(self.data['high'], 5) 60 | 61 | # 计算5日相关系数 62 | correlation = volume_rank.rolling(5).corr(high_rank) 63 | 64 | # 计算3日最大值 65 | max_correlation = correlation.rolling(3).max() 66 | 67 | # 取负值并保留两位小数 68 | self.result = (-1 * max_correlation).round(2) 69 | 70 | # 添加原始数据列 71 | result_df = pd.DataFrame({ 72 | 'volume': self.data['volume'], 73 | 'high': self.data['high'], 74 | 'alpha26': self.result 75 | }) 76 | 77 | self.result = result_df 78 | logger.info("Alpha#26 因子计算完成") 79 | 80 | except Exception as e: 81 | logger.error(f"因子计算失败: {e}") 82 | raise 83 | 84 | def save_result(self, save_path: Optional[Union[str, Path]] = None) -> None: 85 | """保存计算结果 86 | 87 | Args: 88 | save_path: 保存路径,默认为当前目录下的 alpha26_results.csv 89 | """ 90 | if self.result is None: 91 | logger.warning("没有可保存的结果") 92 | return 93 | 94 | save_path = Path(save_path) if save_path else Path('alpha26_results.csv') 95 | try: 96 | self.result.to_csv(save_path) 97 | logger.info(f"结果已保存至 {save_path}") 98 | except Exception as e: 99 | logger.error(f"结果保存失败: {e}") 100 | raise 101 | 102 | def main(): 103 | """主函数""" 104 | # 设置数据路径 105 | data_path = Path("../../data/mock_data.csv") 106 | 107 | # 创建计算器实例 108 | calculator = Alpha26Calculator(data_path) 109 | 110 | try: 111 | # 计算因子 112 | calculator.calculate_alpha() 113 | 114 | # 保存结果 115 | save_path = Path("alpha26_results.csv") 116 | calculator.save_result(save_path) 117 | 118 | except Exception as e: 119 | logger.error(f"程序执行失败: {e}") 120 | raise 121 | 122 | if __name__ == "__main__": 123 | main() -------------------------------------------------------------------------------- /alpha/archive/alpha4/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def ts_rank(series, window): 5 | """ 6 | Computes the time-series rank of the current value within the past 'window' days. 7 | Returns the percentile rank of the current value among the past window values. 8 | 9 | Args: 10 | series: pandas Series with time series data 11 | window: int, number of periods to look back 12 | 13 | Returns: 14 | pandas Series with time-series rank values (0-1) 15 | """ 16 | def compute_ts_rank(x): 17 | if len(x) < 1: 18 | return np.nan 19 | current_value = x.iloc[-1] # Current value (most recent) 20 | window_values = x.values # All values in the window 21 | 22 | # Count how many values are less than current value 23 | rank_position = np.sum(window_values < current_value) 24 | # Add 0.5 for ties (average rank) 25 | rank_position += 0.5 * np.sum(window_values == current_value) 26 | 27 | # Convert to percentile rank (0-1) 28 | percentile_rank = rank_position / len(window_values) 29 | return percentile_rank 30 | 31 | return series.rolling(window=window, min_periods=1).apply(compute_ts_rank, raw=False) 32 | 33 | 34 | def calculate_alpha4(df, ts_rank_window=9): 35 | """ 36 | Calculates Alpha#4 based on the given formula. 37 | 38 | Alpha#4: (-1 * Ts_Rank(rank(low), 9)) 39 | 40 | Args: 41 | df: DataFrame with columns ['date', 'asset_id', 'low', ...] 42 | ts_rank_window: int, window for time-series rank calculation (default=9) 43 | 44 | Returns: 45 | DataFrame with Alpha#4 values 46 | """ 47 | # Ensure data is sorted by date for rolling calculations 48 | df = df.sort_values(by=['asset_id', 'date']) 49 | 50 | # Step 1: rank(low) - Cross-sectional ranking of low prices each day 51 | df['rank_low'] = df.groupby('date')['low'].rank(pct=True, method='average') 52 | 53 | # Step 2: Ts_Rank(rank(low), 9) - Time-series ranking for each asset 54 | df['ts_rank_value'] = df.groupby('asset_id')['rank_low'].transform( 55 | lambda x: ts_rank(x, window=ts_rank_window).round(2) 56 | ) 57 | 58 | # Step 3: (-1 * Ts_Rank(...)) - Apply negative sign 59 | df['alpha4'] = -1 * df['ts_rank_value'] 60 | 61 | # Round to 4 decimal places for clarity 62 | df['alpha4'] = df['alpha4'].round(4) 63 | 64 | return df[['date', 'asset_id', 'low', 'rank_low', 'ts_rank_value', 'alpha4']] 65 | 66 | 67 | if __name__ == "__main__": 68 | # Load mock data 69 | try: 70 | data_df = pd.read_csv("/Users/kuhung/roy/alpha-mining/data/mock_data.csv", parse_dates=['date']) 71 | except FileNotFoundError: 72 | print("Error: mock_data.csv not found. Please run generate_mock_data.py first.") 73 | exit() 74 | 75 | # Check if 'low' column exists 76 | if 'low' not in data_df.columns: 77 | print("Error: 'low' column not found in data. Please update generate_mock_data.py to include high/low prices.") 78 | exit() 79 | 80 | # Calculate Alpha#4 81 | alpha_df = calculate_alpha4(data_df.copy()) 82 | 83 | # Save results 84 | alpha_df.to_csv("alpha4_results.csv", index=False) 85 | print("Alpha#4 calculated and results saved to alpha4_results.csv") 86 | print("\nFirst 5 rows of Alpha#4 results:") 87 | print(alpha_df.head()) 88 | print("\nLast 5 rows of Alpha#4 results:") 89 | print(alpha_df.tail()) 90 | print("\nDescriptive statistics of Alpha#4:") 91 | print(alpha_df['alpha4'].describe()) 92 | 93 | # Additional analysis 94 | print("\nAlpha#4 distribution by asset:") 95 | print(alpha_df.groupby('asset_id')['alpha4'].agg(['mean', 'std', 'min', 'max']).round(4)) 96 | 97 | print("\nDaily Alpha#4 statistics (last 10 days):") 98 | daily_stats = alpha_df.groupby('date')['alpha4'].agg(['mean', 'std']).tail(10).round(4) 99 | print(daily_stats) -------------------------------------------------------------------------------- /alpha/archive/alpha27/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from typing import Union, Optional 4 | from pathlib import Path 5 | import logging 6 | 7 | # 设置日志 8 | logging.basicConfig(level=logging.INFO) 9 | logger = logging.getLogger(__name__) 10 | 11 | class Alpha27Calculator: 12 | """Alpha#27 因子计算器 13 | 14 | 计算公式: ((0.5 < rank((sum(correlation(rank(volume), rank(vwap), 6), 2) / 2.0))) ? (-1 * 1) : 1) 15 | """ 16 | 17 | def __init__(self, data_path: Union[str, Path]): 18 | """初始化计算器 19 | 20 | Args: 21 | data_path: 数据文件路径 22 | """ 23 | self.data_path = Path(data_path) 24 | self.data = None 25 | self.result = None 26 | 27 | def load_data(self) -> None: 28 | """加载数据""" 29 | logger.info(f"正在从 {self.data_path} 加载数据...") 30 | try: 31 | self.data = pd.read_csv(self.data_path, index_col=0) 32 | self.data.index = pd.to_datetime(self.data.index) 33 | logger.info(f"数据加载完成,共 {len(self.data)} 条记录") 34 | except Exception as e: 35 | logger.error(f"数据加载失败: {e}") 36 | raise 37 | 38 | def rank(self, series: pd.Series) -> pd.Series: 39 | """计算横截面排名 40 | 41 | Args: 42 | series: 输入序列 43 | 44 | Returns: 45 | 排名序列 46 | """ 47 | return series.rank(pct=True) 48 | 49 | def calculate_alpha(self) -> None: 50 | """计算 Alpha#27 因子值""" 51 | try: 52 | # 确保数据已加载 53 | if self.data is None: 54 | self.load_data() 55 | 56 | # 计算成交量和VWAP的排名 57 | volume_rank = self.rank(self.data['volume']) 58 | vwap_rank = self.rank(self.data['vwap']) 59 | 60 | # 计算6日相关系数 61 | correlation = volume_rank.rolling(6).corr(vwap_rank) 62 | 63 | # 计算2日求和并除以2 64 | corr_sum_mean = correlation.rolling(2).sum() / 2.0 65 | 66 | # 计算排名并与0.5比较 67 | final_rank = self.rank(corr_sum_mean) 68 | 69 | # 生成信号并保留两位小数 70 | self.result = np.where(final_rank > 0.5, -1, 1).astype(float).round(2) 71 | 72 | # 添加原始数据列 73 | result_df = pd.DataFrame({ 74 | 'volume': self.data['volume'], 75 | 'vwap': self.data['vwap'], 76 | 'alpha27': self.result 77 | }) 78 | 79 | self.result = result_df 80 | logger.info("Alpha#27 因子计算完成") 81 | 82 | except Exception as e: 83 | logger.error(f"因子计算失败: {e}") 84 | raise 85 | 86 | def save_result(self, save_path: Optional[Union[str, Path]] = None) -> None: 87 | """保存计算结果 88 | 89 | Args: 90 | save_path: 保存路径,默认为当前目录下的 alpha27_results.csv 91 | """ 92 | if self.result is None: 93 | logger.warning("没有可保存的结果") 94 | return 95 | 96 | save_path = Path(save_path) if save_path else Path('alpha27_results.csv') 97 | try: 98 | self.result.to_csv(save_path) 99 | logger.info(f"结果已保存至 {save_path}") 100 | except Exception as e: 101 | logger.error(f"结果保存失败: {e}") 102 | raise 103 | 104 | def main(): 105 | """主函数""" 106 | # 设置数据路径 107 | data_path = Path("../../data/mock_data.csv") 108 | 109 | # 创建计算器实例 110 | calculator = Alpha27Calculator(data_path) 111 | 112 | try: 113 | # 计算因子 114 | calculator.calculate_alpha() 115 | 116 | # 保存结果 117 | save_path = Path("alpha27_results.csv") 118 | calculator.save_result(save_path) 119 | 120 | except Exception as e: 121 | logger.error(f"程序执行失败: {e}") 122 | raise 123 | 124 | if __name__ == "__main__": 125 | main() -------------------------------------------------------------------------------- /alpha/archive/alpha29/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def scale(df): 5 | """ 6 | Standardize a series to have zero mean and unit variance 7 | """ 8 | return (df - df.mean()) / df.std() 9 | 10 | def delta(series, window): 11 | """ 12 | Calculate the difference between the current value and the value 'window' days ago 13 | """ 14 | return series - series.shift(window) 15 | 16 | def ts_rank(series, window): 17 | """ 18 | Calculate the rolling rank for a time series 19 | """ 20 | return series.rolling(window=window).rank(pct=True) 21 | 22 | def calculate_alpha29(df): 23 | """ 24 | Calculates Alpha#29 based on the given formula: 25 | (min(product(rank(rank(scale(log(sum(ts_min(rank(rank((-1 * rank(delta((close - 1), 26 | 5))))), 2), 1))))), 1), 5) + ts_rank(delay((-1 * returns), 6), 5)) 27 | """ 28 | # Ensure data is sorted by date for rolling calculations 29 | df = df.sort_values(by=['asset_id', 'date']) 30 | 31 | # Part 1 calculation 32 | # Calculate initial difference 33 | df['diff'] = df.groupby('asset_id').apply( 34 | lambda x: delta(x['close'] - 1, 5) 35 | ).reset_index(level=0, drop=True) 36 | 37 | # Multiple rank operations 38 | df['part1'] = df.groupby('date')['diff'].rank(pct=True) # First rank 39 | df['part1'] = -1 * df['part1'] # Negative 40 | df['part1'] = df.groupby('date')['part1'].rank(pct=True) # Second rank 41 | df['part1'] = df.groupby('date')['part1'].rank(pct=True) # Third rank 42 | 43 | # Time series operations 44 | df['part1'] = df.groupby('asset_id')['part1'].transform( 45 | lambda x: x.rolling(window=2, min_periods=2).min() # ts_min 46 | ) 47 | df['part1'] = df.groupby('asset_id')['part1'].transform( 48 | lambda x: x.rolling(window=1, min_periods=1).sum() # sum 49 | ) 50 | 51 | # Mathematical transformations 52 | df['part1'] = np.log(df['part1'].abs()) # log of absolute value to handle negative numbers 53 | df['part1'] = df.groupby('date')['part1'].transform(lambda x: scale(x)) # scale 54 | 55 | # Final transformations for part1 56 | df['part1'] = df.groupby('date')['part1'].rank(pct=True) # rank 57 | df['part1'] = df.groupby('date')['part1'].rank(pct=True) # rank again 58 | df['part1'] = df.groupby('asset_id')['part1'].transform( 59 | lambda x: x.rolling(window=1, min_periods=1).apply(np.prod) # product 60 | ) 61 | df['part1'] = df.groupby('asset_id')['part1'].transform( 62 | lambda x: x.rolling(window=5, min_periods=5).min() # min 63 | ) 64 | 65 | # Part 2 calculation 66 | df['part2'] = -1 * df['returns'] # Negative returns 67 | df['part2'] = df.groupby('asset_id')['part2'].shift(6) # delay 68 | df['part2'] = df.groupby('asset_id')['part2'].transform( 69 | lambda x: ts_rank(x, 5) # ts_rank 70 | ) 71 | 72 | # Combine parts and calculate final alpha 73 | df['alpha29'] = df['part1'] + df['part2'] 74 | 75 | # Round to 2 decimal places 76 | df['alpha29'] = round(df['alpha29'], 2) 77 | 78 | # Select and return relevant columns 79 | return df[['date', 'asset_id', 'close', 'returns', 'alpha29']] 80 | 81 | if __name__ == "__main__": 82 | # Load data 83 | try: 84 | data_df = pd.read_csv("/Users/kuhung/roy/alpha-mining/data/mock_data.csv", parse_dates=['date']) 85 | except FileNotFoundError: 86 | print("Error: mock_data.csv not found. Please ensure the data file exists.") 87 | exit() 88 | 89 | # Calculate Alpha 90 | alpha_df = calculate_alpha29(data_df.copy()) # Use a copy to avoid modifying original df 91 | 92 | # Save results 93 | output_file = "alpha29_results.csv" 94 | alpha_df.to_csv(output_file, index=False) 95 | 96 | print(f"Alpha#29 calculated and results saved to {output_file}") 97 | print("\nFirst 5 rows of Alpha results:") 98 | print(alpha_df.head()) 99 | print("\nLast 5 rows of Alpha results:") 100 | print(alpha_df.tail()) 101 | print("\nDescriptive statistics of Alpha29:") 102 | print(alpha_df['alpha29'].describe()) -------------------------------------------------------------------------------- /alpha/alpha33/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | # --- Helper Functions --- 5 | 6 | def cs_rank(series: pd.Series) -> pd.Series: 7 | """Cross-sectional rank (percentage).""" 8 | # Ensure only non-NaN values are ranked. NaNs will remain NaN. 9 | return series.rank(method='average', pct=True) 10 | 11 | # --- Main Alpha Calculation Function --- 12 | 13 | def calculate_alpha33(df: pd.DataFrame) -> pd.DataFrame: 14 | """ 15 | Calculate Alpha#33: 16 | rank((-1 * ((1 - (open / close))^1))) 17 | """ 18 | required_cols = ['open', 'close'] 19 | for col in required_cols: 20 | if col not in df.columns: 21 | raise ValueError(f"Required column '{col}' not found in DataFrame.") 22 | 23 | # Ensure data is sorted by date first for cross-sectional operations 24 | df = df.sort_values(by=['date', 'asset_id']).copy() 25 | 26 | # Calculate (1 - (open / close)) 27 | # Handle division by zero for 'close' price 28 | # If close is 0, the ratio will be inf, and (1 - inf) will be -inf, which will propagate to NaN after rank 29 | # We'll let pandas handle inf/-inf and resulting NaNs. Rank handles NaNs by default. 30 | df['intermediate_ratio'] = (1 - (df['open'] / df['close'])) 31 | 32 | # Calculate -1 * (1 - (open / close)) 33 | df['intermediate_negated'] = -1 * df['intermediate_ratio'] 34 | 35 | # Apply cross-sectional rank 36 | df['alpha33'] = df.groupby('date')['intermediate_negated'].transform(cs_rank) 37 | 38 | # Rounding alpha33 to two decimal places 39 | df['alpha33'] = df['alpha33'].round(2) 40 | 41 | # Define columns to keep, ensuring original data + new alpha 42 | # Use a set to avoid duplicates and preserve order for original columns 43 | original_cols_ordered = ['date', 'asset_id', 'open', 'high', 'low', 'close', 'volume', 'vwap', 'returns'] 44 | output_cols = [col for col in original_cols_ordered if col in df.columns] 45 | 46 | # Add alpha33 to the end, if not already present 47 | if 'alpha33' not in output_cols: 48 | output_cols.append('alpha33') 49 | 50 | # Re-sort by date and asset_id for final output consistency 51 | df = df.sort_values(by=['date', 'asset_id']).reset_index(drop=True) 52 | 53 | return df[output_cols] 54 | 55 | 56 | if __name__ == "__main__": 57 | # --- Configuration --- 58 | # Assuming mock_data.csv is in ../../data/ relative to this script's location (alpha/alpha33/) 59 | DATA_FILE_PATH = "../../data/mock_data.csv" 60 | OUTPUT_FILE_PATH = "alpha33_results.csv" 61 | 62 | # --- Load Data --- 63 | try: 64 | print(f"Loading data from {DATA_FILE_PATH}...") 65 | input_df = pd.read_csv(DATA_FILE_PATH) 66 | print("Data loaded successfully.") 67 | except FileNotFoundError: 68 | print(f"Error: Data file not found at {DATA_FILE_PATH}.") 69 | exit(1) 70 | except Exception as e: 71 | print(f"Error loading data: {e}") 72 | exit(1) 73 | 74 | # --- Data Preprocessing --- 75 | try: 76 | input_df['date'] = pd.to_datetime(input_df['date']) 77 | # Ensure asset_id is treated as object/string to avoid issues with numeric IDs being misinterpreted 78 | if 'asset_id' in input_df.columns: 79 | input_df['asset_id'] = input_df['asset_id'].astype(str) 80 | 81 | print("Data preprocessing (date conversion, asset_id type) complete.") 82 | except Exception as e: 83 | print(f"Error during data preprocessing: {e}") 84 | exit(1) 85 | 86 | # --- Calculate Alpha --- 87 | try: 88 | print("Calculating Alpha#33...") 89 | # Pass a copy to avoid modifying the original input_df in memory if it's used elsewhere 90 | results_df = calculate_alpha33(input_df.copy()) 91 | print("Alpha#33 calculation complete.") 92 | except Exception as e: 93 | print(f"Error calculating Alpha#33: {e}") 94 | exit(1) 95 | 96 | # --- Save Results --- 97 | try: 98 | results_df.to_csv(OUTPUT_FILE_PATH, index=False, float_format='%.2f') 99 | print(f"Alpha#33 results saved to {OUTPUT_FILE_PATH}") 100 | except Exception as e: 101 | print(f"Error saving results: {e}") 102 | exit(1) -------------------------------------------------------------------------------- /alpha/alpha32/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#32: 趋势跟踪与量价相关性组合策略 2 | 3 | ## 描述 4 | 5 | Alpha#32 的计算公式为: 6 | 7 | ``` 8 | Alpha#32: (scale(((sum(close, 7) / 7) - close)) + (20 * scale(correlation(vwap, delay(close, 5), 9 | 230)))) 10 | ``` 11 | 12 | 这个 Alpha 策略结合了短期价格趋势和长期量价相关性,旨在捕捉市场中不同时间维度的信号: 13 | 14 | 1. **部分 A**: `scale(((sum(close, 7) / 7) - close))` 15 | 16 | * `sum(close, 7) / 7`:计算过去7天的收盘价均值,代表短期均线。 17 | * `(sum(close, 7) / 7) - close`:计算短期均线与当前收盘价的差值,反映短期价格趋势。如果均线高于收盘价,表示下跌趋势;反之,上涨趋势。 18 | * `scale(...)`:对上述差值进行截面标准化。标准化有助于因子在不同资产间进行比较。 19 | * 这个部分旨在衡量短期价格相对于其近期均值的偏离程度,以捕捉短期趋势或反转。 20 | 2. **部分 B**: `(20 * scale(correlation(vwap, delay(close, 5), 230)))` 21 | 22 | * `delay(close, 5)`:获取5天前的收盘价,引入滞后性。 23 | * `correlation(vwap, delay(close, 5), 230)`:计算成交量加权平均价 (`vwap`) 与5天前收盘价在过去230天内的时序相关性。`vwap` 反映了交易的实际价格水平,与滞后收盘价的相关性可能揭示市场情绪或资金流向与价格走势的长期关系。 24 | * `scale(...)`:对计算出的相关性系数进行截面标准化。 25 | * `20 * ...`:将标准化后的相关性因子乘以20。这个乘数用于调整该部分在总 Alpha 值中的权重或影响力。 26 | * 这个部分旨在捕捉成交量和价格之间长期、滞后的关系,其强度可能预示趋势的持续性或反转。 27 | 28 | 最终的 Alpha#32 值为这两个部分的加权和。 29 | 30 | ## 项目结构 31 | 32 | ``` 33 | alpha-mining/ 34 | ├── data/ 35 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (确保包含 close, vwap 字段) 36 | │ └── mock_data.csv # 生成的模拟数据文件 37 | ├── alpha/alpha32/ 38 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#32 39 | │ ├── alpha32_results.csv # 计算得到的 Alpha#32 结果文件 40 | │ ├── README.md # 本说明文档 41 | │ └── cast.md # Alpha#32 策略简介 42 | ``` 43 | 44 | ## 使用步骤 45 | 46 | ### 1. 环境准备 47 | 48 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 49 | 50 | ```bash 51 | pip install pandas numpy 52 | ``` 53 | 54 | ### 2. 检查模拟数据 55 | 56 | 本 Alpha 依赖于 `close` 和 `vwap` 数据。请确保 `data/mock_data.csv` 文件存在,并且包含了 `date`, `asset_id`, `close`, `vwap` 列。如果文件不存在或数据不完整,请运行或修改 `data/generate_mock_data.py` 脚本。 57 | 58 | ```bash 59 | # 检查或生成数据 (如果需要) 60 | cd ../../data # 假设当前在 alpha/alpha32 目录 61 | python generate_mock_data.py # 假设此脚本能生成所需字段 62 | cd ../alpha/alpha32 63 | ``` 64 | 65 | ### 3. 计算 Alpha#32 因子 66 | 67 | 进入 `alpha/alpha32` 目录并运行 `alpha_calculator.py` 脚本: 68 | 69 | ```bash 70 | python alpha_calculator.py 71 | ``` 72 | 73 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#32,并将结果保存到当前目录下的 `alpha32_results.csv`。 74 | 75 | ## 策略解读与计算示例 76 | 77 | 我们将以 `asset_1` 在日期 `2025-04-10` 的数据为例,展示 Alpha#32 的计算。 78 | 79 | **背景数据 (源自 `alpha32_results.csv` for `asset_1` on `2025-04-10`):** 80 | - `close`: 93.10 81 | - `vwap`: 91.76 82 | - `part_A`: -0.92 83 | - `part_B`: 0.00 (注意:由于模拟数据长度限制,`correlation` 函数的 230 天窗口可能未被完全满足,导致 `part_B` 在此示例中为 0。在实际足够长的数据中,`part_B` 将会有非零值。) 84 | 85 | **计算 Alpha#32:** 86 | `Alpha#32 = part_A + part_B` 87 | `Alpha#32 = -0.92 + 0.00 = -0.92` 88 | 89 | 此值与 `alpha32_results.csv` 中 `asset_1` 在 `2025-04-10` 的 `alpha32` 列的值 `-0.92` 相符。 90 | 各部分 (`part_A`, `part_B`) 的详细计算步骤可参考 `alpha_calculator.py` 脚本中的实现。 91 | 92 | ## 数据需求 93 | 94 | - `date`: 交易日期 (datetime) 95 | - `asset_id`: 资产ID (string/object) 96 | - `close`: 每日收盘价 (float) 97 | - `vwap`: 每日成交量加权平均价 (float) 98 | - (脚本还会包含 `open`, `high`, `low`, `volume`, `returns` 等在 `mock_data.csv` 中的其他列,以保持数据完整性) 99 | 100 | ## 输出格式 101 | 102 | 输出的 CSV 文件 (`alpha32_results.csv`) 将包含以下列(除了原始数据列),所有数值型 alpha 相关列均保留两位小数: 103 | 104 | - `date`: 交易日期 105 | - `asset_id`: 资产ID 106 | - `open`, `high`, `low`, `close`, `volume`, `vwap`, `returns`: 原始数据中的对应列 107 | - `part_A`: Alpha#32 公式中第一部分的最终计算结果 108 | - `part_B`: Alpha#32 公式中第二部分的最终计算结果 109 | - `alpha32`: 最终计算的 Alpha#32 值。 110 | 111 | ## 注意事项与风险提示 112 | 113 | - **数据窗口与NaN值**: 114 | - **`sum(close, 7)` 和 `delay(close, 5)`**: 计算会引入 NaN 值,例如 `sum(close, 7)` 需要7个数据点,前6个数据点会是 NaN。 115 | - **`correlation(vwap, delay(close, 5), 230)`**: 需要230个数据点来计算相关性。这意味着每个资产的前229个数据点将无法计算出有效的相关性值,导致 `part_B` 在这些日期为 NaN。 116 | - **`alpha32`**: 最终的 `alpha32` 值将受到各部分中最大窗口期的影响。因此,`alpha32` 的第一个非 NaN 值将出现在每个资产的第230个交易日。 117 | - **标准化 (`scale`)**: 通常指减去均值后除以标准差。`scale(x)` 一般表示 `(x - mean(x)) / std(x)`,按截面计算。需要处理标准差为零的情况。 118 | - **相关性计算**: `pandas` 的 `rolling().corr()`。注意窗口期内数据不足或标准差为零的情况。 119 | - **小数位数**: 最终的 Alpha#32 值和所有中间计算的 Alpha 相关列均按要求保留两位小数。 120 | - **因子组合的复杂性**: 复杂因子可能导致模型解释性下降,且各部分之间的相互作用可能复杂。 121 | - **市场适用性**: 此复杂因子在不同市场环境或资产类别上表现可能迥异。务必进行充分的回测和验证。 122 | - **数据质量**: 输入数据的准确性和完整性至关重要。 123 | 124 | Alpha#32 是一个基于多种信号的复杂因子,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 125 | -------------------------------------------------------------------------------- /alpha/archive/alpha3/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#3 策略模拟与计算 2 | 3 | 本项目演示了如何根据给定的 Alpha#3 公式生成模拟金融数据、计算 Alpha 因子,并对结果进行分析。 4 | 5 | ## Alpha#3 公式 6 | 7 | Alpha#3 的计算公式如下: 8 | 9 | ``` 10 | (-1 * correlation(rank(open), rank(volume), 10)) 11 | ``` 12 | 13 | 其中: 14 | 15 | * `open`: 资产的日开盘价。 16 | * `volume`: 资产的日交易量。 17 | * `rank(series)`: 计算 `series` 中每个值在当日所有资产间的排序百分比(0到1之间)。值越大,排名越高。 18 | * `correlation(x, y, N)`: 计算时间序列 `x` 和 `y` 在过去 `N` 天的滚动相关系数。 19 | * `(-1 *)`: 对相关系数取负值,使得负相关变为正的Alpha信号。 20 | 21 | ## 项目结构 22 | 23 | ``` 24 | alpha3/ 25 | ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#3 26 | ├── alpha3_results.csv # 计算得到的 Alpha#3 结果文件 27 | ├── cast.md # 策略简要说明 28 | └── README.md # 本说明文档 29 | ``` 30 | 31 | ## 使用步骤 32 | 33 | ### 1. 环境准备 34 | 35 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 36 | 37 | ```bash 38 | pip install pandas numpy 39 | ``` 40 | 41 | ### 2. 数据准备 42 | 43 | 确保在 `../../data/` 目录下有 `mock_data.csv` 文件,该文件应包含以下列: 44 | - `date`: 交易日期 45 | - `asset_id`: 资产标识符 46 | - `open`: 开盘价 47 | - `volume`: 交易量 48 | 49 | ### 3. 计算 Alpha#3 因子 50 | 51 | 运行 `alpha_calculator.py` 脚本来计算 Alpha#3 因子。该脚本会读取模拟数据,执行公式中的计算,并将结果保存到 `alpha3_results.csv`。 52 | 53 | ```bash 54 | cd alpha/alpha3 55 | python alpha_calculator.py 56 | ``` 57 | 58 | 脚本执行完毕后,会在终端打印出结果文件的前5行、后5行以及 Alpha#3 值的描述性统计信息。 59 | 60 | ## Alpha#3 策略解读 61 | 62 | 该 Alpha 策略试图捕捉开盘价排名与交易量排名之间的相关关系模式。 63 | 64 | ### 实际计算结果统计 65 | 66 | 基于模拟数据的计算结果: 67 | 68 | - **数据规模**: 5个资产,每个资产100天数据,共500条记录 69 | - **Alpha#3值域**: -1.0000 到 1.0000 70 | - **平均值**: -0.0341 71 | - **标准差**: 0.3155 72 | - **中位数**: 0.0000 73 | - **非零值数量**: 391个(78.2%) 74 | 75 | ### 计算步骤详解 76 | 77 | 以实际数据中的2025-01-20为例: 78 | 79 | | date | asset_id | open | volume | alpha3 | 80 | |------------|----------|---------|----------|---------| 81 | | 2025-01-20 | asset_1 | 99.93 | 3507861 | -0.3081 | 82 | | 2025-01-20 | asset_2 | 116.03 | 1274534 | -0.0000 | 83 | | 2025-01-20 | asset_3 | 103.88 | 992619 | -0.1584 | 84 | | 2025-01-20 | asset_4 | 96.97 | 736510 | -0.4062 | 85 | | 2025-01-20 | asset_5 | 97.57 | 551061 | -0.1301 | 86 | 87 | #### 1. **计算开盘价排名 (`rank(open)`)** 88 | 89 | 在2025-01-20这一天,各资产开盘价排名: 90 | - asset_2 (116.03): 排名 1.0 (最高) 91 | - asset_3 (103.88): 排名 0.8 (第2高) 92 | - asset_1 (99.93): 排名 0.6 (第3高) 93 | - asset_5 (97.57): 排名 0.4 (第4高) 94 | - asset_4 (96.97): 排名 0.2 (最低) 95 | 96 | #### 2. **计算交易量排名 (`rank(volume)`)** 97 | 98 | 同日各资产交易量排名: 99 | - asset_1 (3507861): 排名 1.0 (最高) 100 | - asset_2 (1274534): 排名 0.8 (第2高) 101 | - asset_3 (992619): 排名 0.6 (第3高) 102 | - asset_4 (736510): 排名 0.4 (第4高) 103 | - asset_5 (551061): 排名 0.2 (最低) 104 | 105 | #### 3. **观察到的相关性模式** 106 | 107 | 从实际结果可以看出: 108 | - **asset_1**: 中等开盘价但最高交易量,Alpha#3为-0.3081,表明其历史上开盘价排名与交易量排名呈正相关 109 | - **asset_2**: 最高开盘价和第二高交易量,Alpha#3为0.0000,表明相关性接近中性 110 | - **asset_4**: 最低开盘价和第四高交易量,Alpha#3为-0.4062,显示较强的正相关模式 111 | 112 | ### 策略含义分析 113 | 114 | 基于实际计算结果的观察: 115 | 116 | #### **负值Alpha#3占主导** 117 | 在我们的结果中,大部分Alpha#3值为负数,这表明: 118 | - 开盘价排名与交易量排名之间普遍存在**正相关关系** 119 | - 开盘价较高的股票往往也有较高的交易量 120 | - 这可能反映了市场对高价股票的关注度和活跃交易 121 | 122 | #### **数值分布特征** 123 | - **接近0的值**: 约22%的观测值为0,主要出现在早期数据(缺乏足够历史数据)或相关性很弱的时期 124 | - **极端值**: 出现-1.0和1.0的极端值,通常在数据序列早期,当历史数据较少时相关系数容易出现极值 125 | - **稳定期**: 随着历史数据积累,Alpha#3值趋于稳定,大多分布在-0.5到0.5之间 126 | 127 | #### **时间演化模式** 128 | 从数据中可以观察到: 129 | 1. **初始阶段** (前几天): Alpha#3值为0,因为缺乏足够的历史数据 130 | 2. **波动阶段** (第5-15天): 出现较大波动,包括极端值 131 | 3. **稳定阶段** (第15天后): Alpha#3值趋于稳定,反映更可靠的相关性模式 132 | 133 | ### 投资逻辑与应用 134 | 135 | 基于实际结果的投资含义: 136 | 137 | #### **流动性分析** 138 | - **负Alpha#3**: 表明价格与成交量同向变动,可能暗示正常的市场流动性 139 | - **正Alpha#3**: 表明价格与成交量反向变动,可能暗示流动性异常或特殊市场情况 140 | 141 | #### **市场情绪识别** 142 | - 持续的负Alpha#3可能表明市场处于正常的风险偏好状态 143 | - Alpha#3值的突然转正可能预示市场情绪的转变 144 | 145 | #### **交易策略应用** 146 | 1. **趋势跟踪**: 负Alpha#3较强时,可能适合跟踪高价高量的股票 147 | 2. **反转策略**: Alpha#3转正时,可能存在反转机会 148 | 3. **风险管理**: 极端Alpha#3值可能预示异常市场条件 149 | 150 | ## 注意事项 151 | 152 | 1. **数据要求**: 该因子需要至少10天的历史数据才能计算出稳定的相关系数 153 | 2. **早期偏差**: 前10天的Alpha#3值可能不够可靠,建议关注稳定期的数据 154 | 3. **极端值处理**: 算法已自动处理无穷大值,将其设置为0 155 | 4. **市场环境**: 相关系数的稳定性依赖于市场环境的一致性,在市场结构性变化时需要重新评估 156 | 157 | ## 实际表现总结 158 | 159 | 根据模拟数据的计算结果: 160 | - Alpha#3成功捕捉了价格-成交量关系的动态变化 161 | - 大部分时间显示正相关模式(负Alpha#3值) 162 | - 提供了有意义的市场微观结构信息 163 | - 可作为量化交易策略的有效因子之一 164 | 165 | 如需帮助或有建议,欢迎交流! -------------------------------------------------------------------------------- /alpha/alpha40/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#40: 波动率与相关性反转策略 2 | 3 | ## Formula 4 | 5 | ``` 6 | ((-1 * rank(stddev(high, 10))) * correlation(high, volume, 10)) 7 | ``` 8 | 9 | ## Description 10 | 11 | Alpha#40 是一个结合了市场波动性、成交量行为和资产间反转效应的量化策略。该策略的核心思想是识别并利用那些表现出低波动性但其价格(`high`)与成交量(`volume`)呈正相关的资产。策略预期这类资产在未来可能会表现不佳(即因子值为负)。 12 | 13 | ### Components: 14 | 15 | 1. **`stddev(high, 10)`**: 计算过去10个周期的最高价(`high`)的标准差。这衡量了资产近期价格的波动性或不确定性。标准差越高,表明价格波动越剧烈。 16 | 2. **`rank(stddev(high, 10))`**: 对计算出的10周期波动率进行横截面排名。波动性最高的资产获得最高的排名(接近1.0),而波动性最低的资产获得最低的排名(接近0.0)。 17 | 3. **`-1 * rank(stddev(high, 10))`**: 将波动率排名取负。这一步意味着策略偏好(给予更高正值)那些近期波动性较低的资产,而惩罚(给予更低负值)那些波动性较高的资产。 18 | 4. **`correlation(high, volume, 10)`**: 计算过去10个周期的最高价(`high`)与成交量(`volume`)之间的滚动相关性。 19 | * **正相关** (接近 +1.0) 可能表示"价涨量增",这通常被看作是趋势持续的健康信号,但也可能预示着趋势的顶部,因为大量交易可能在价格高点发生。 20 | * **负相关** (接近 -1.0) 可能表示"价涨量缩"或"价跌量增",这可能暗示趋势的强度不足或恐慌性抛售。 21 | 5. **最终公式**: 将反转后的波动率排名(`-1 * rank(...)`)与价量相关性相乘。 22 | * 当一个资产**波动率低**(排名低,因此 `-1 * rank` 为一个接近于0的负数或小的正数)且**价量正相关**时,最终的 Alpha 值会趋向于一个较小的负数。 23 | * 当一个资产**波动率高**(排名高,因此 `-1 * rank` 为一个较大的负数)且**价量正相关**时,最终的 Alpha 值会是一个较大的负数,这是策略主要的做空信号。 24 | * 当**价量呈负相关**时,它会反转 `-1 * rank` 部分的符号,可能导致因子值为正,这可能被视为一个买入信号,特别是在高波动率的情况下(大负数乘以负数得到大正数)。 25 | 26 | 该策略旨在做空那些价格波动剧烈且交易量跟随价格上涨的资产,同时可能做多那些在高波动性下出现价量背离的资产。 27 | 28 | ## Calculation Steps 29 | 30 | 1. **数据准备**: 加载 `high` 和 `volume` 数据。 31 | 2. **计算波动率**: 对于每个资产,计算其过去10个周期的最高价 `high` 的滚动标准差 `stddev_high_10`。 32 | 3. **波动率排名**: 在每个时间点上,对所有资产的 `stddev_high_10` 进行横截面排名,得到 `rank_stddev_high_10`。 33 | 4. **计算相关性**: 对于每个资产,计算其过去10个周期的 `high` 和 `volume` 之间的滚动相关性,得到 `corr_high_volume_10`。 34 | 5. **计算最终Alpha值**: 根据公式 `alpha40 = (-1 * rank_stddev_high_10) * corr_high_volume_10` 计算最终值。 35 | 6. **结果处理**: 将计算出的所有中间列和最终 `alpha40` 列四舍五入至两位小数,并过滤掉 `alpha40` 为 `NaN` 的行后,保存到CSV文件。 36 | 37 | ## 项目结构 38 | 39 | ``` 40 | alpha-mining/ 41 | ├── data/ 42 | │ ├── generate_mock_data.py 43 | │ └── mock_data.csv 44 | ├── alpha/alpha40/ 45 | │ ├── alpha_calculator.py # 脚本:计算 Alpha#40 46 | │ ├── alpha40_results.csv # 计算结果 47 | │ ├── README.md # 本文档 48 | │ └── cast.md # 策略简介 49 | ``` 50 | 51 | ## 使用步骤 52 | 53 | ### 1. 环境准备 54 | 55 | 确保已安装 `pandas` 和 `numpy`: 56 | 57 | ```bash 58 | pip install pandas numpy 59 | ``` 60 | 61 | ### 2. 检查数据 62 | 63 | 本 Alpha 依赖于 `high` 和 `volume` 数据。请确保 `data/mock_data.csv` 文件存在并包含所需列。 64 | 65 | ### 3. 计算 Alpha#40 66 | 67 | 在项目根目录下运行 `alpha_calculator.py` 脚本: 68 | 69 | ```bash 70 | python alpha/alpha40/alpha_calculator.py 71 | ``` 72 | 73 | 脚本将读取 `data/mock_data.csv`,计算 Alpha#40,并将结果保存到 `alpha/alpha40/alpha40_results.csv`。 74 | 75 | ## 数据输入 76 | 77 | * `high`: 每日最高价。 78 | * `volume`: 每日成交量。 79 | 80 | 数据从 `data/mock_data.csv` 文件中获取。 81 | 82 | ## 输出格式 83 | 84 | 输出的 CSV 文件 (`alpha40_results.csv`) 将包含以下列(除了原始数据列),所有数值型 alpha 相关列均保留两位小数: 85 | 86 | - `date`: 交易日期 87 | - `asset_id`: 资产ID 88 | - `open`, `high`, `low`, `close`, `volume`, `vwap`, `returns`: 原始数据 89 | - `stddev_high_10`: 10日最高价滚动标准差 90 | - `rank_stddev_high_10`: 10日最高价滚动标准差的横截面排名 91 | - `corr_high_volume_10`: 10日最高价与成交量的滚动相关性 92 | - `alpha40`: 最终计算的 Alpha#40 值 93 | 94 | ## 注意事项与风险提示 95 | 96 | - **NaN 值**: 在计算初期(前9个数据点),由于滚动窗口不足,结果将为 `NaN`。这些行在最终输出前被移除。 97 | - **数据质量**: 输入数据的准确性对波动率和相关性的计算至关重要。异常值可能会扭曲结果。 98 | - **市场适用性**: 此因子表现可能因市场环境(如牛市、熊市、高波动期)而异。 99 | - **相关性解读**: 价量相关性是一个复杂的指标,其解释可能需要结合其他市场信息。 100 | 101 | ## 策略解读与计算示例 102 | 103 | 我们将以 `asset_1` 在日期 `2024-06-10` 的数据为例,展示 Alpha#40 的计算。 104 | 105 | **背景数据 (源自 `alpha40_results.csv` for `asset_1` on `2024-06-10`):** 106 | - `stddev_high_10`: 1.85 107 | - `rank_stddev_high_10`: 0.40 108 | - `corr_high_volume_10`: 0.48 109 | - `alpha40`: -0.19 110 | 111 | **计算 Alpha#40:** 112 | 113 | 1. **准备中间值**: 114 | * 首先,脚本已计算出 `asset_1` 在 `2024-06-10` 的10日最高价标准差为 `1.85`。 115 | * 然后,在当日所有资产中对该值进行排名,得到排名百分比 `rank_stddev_high_10` 为 `0.40`。 116 | * 同时,计算出 `asset_1` 在该日期的10日最高价与成交量的相关性 `corr_high_volume_10` 为 `0.48`。 117 | 118 | 2. **代入公式**: 119 | * `alpha40 = (-1 * rank_stddev_high_10) * corr_high_volume_10` 120 | * `alpha40 = (-1 * 0.40) * 0.48` 121 | * `alpha40 = -0.40 * 0.48` 122 | * `alpha40 = -0.192` 123 | 124 | 3. **结果取整**: 125 | * 保留两位有效数字后,最终值为 `-0.19`。 126 | 127 | 这个计算结果与 `alpha40_results.csv` 中 `asset_1` 在 `2024-06-10` 的 `alpha40` 值 `-0.19` 相符。这表明该资产当天具有中等偏低的波动率排名和中等程度的价量正相关性,因此产生了一个负的 Alpha 信号。 -------------------------------------------------------------------------------- /alpha/archive/alpha4/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#4 策略模拟与计算 2 | 3 | 本项目演示了如何根据给定的 Alpha#4 公式生成模拟金融数据、计算 Alpha 因子,并对结果进行分析。 4 | 5 | ## Alpha#4 公式 6 | 7 | Alpha#4 的计算公式如下: 8 | 9 | ``` 10 | (-1 * Ts_Rank(rank(low), 9)) 11 | ``` 12 | 13 | 其中: 14 | 15 | * `low`: 资产的日最低价。 16 | * `rank(series)`: 计算 `series` 中每个值在当日所有资产间的排序百分比(0到1之间)。值越大,排名越高。 17 | * `Ts_Rank(series, N)`: 计算 `series` 在过去 `N` 天的时间序列排名。返回当前值在过去N天中的排名百分比。 18 | * `(-1 *)`: 对结果取负值,实现反向逻辑。 19 | 20 | ## 项目结构 21 | 22 | ``` 23 | alpha-mining/ 24 | ├── data/ 25 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据(包含high, low字段) 26 | │ └── mock_data.csv # 生成的模拟数据文件 27 | ├── alpha/alpha4/ 28 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#4 29 | │ ├── alpha4_results.csv # 计算得到的 Alpha#4 结果文件 30 | │ ├── README.md # 本说明文档 31 | │ └── cast.md # Alpha#4 策略总结 32 | ``` 33 | 34 | ## 使用步骤 35 | 36 | ### 1. 环境准备 37 | 38 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 39 | 40 | ```bash 41 | pip install pandas numpy 42 | ``` 43 | 44 | ### 2. 生成模拟数据 45 | 46 | 如果数据文件不存在或需要更新,运行 `data/generate_mock_data.py` 脚本以生成包含high、low字段的模拟数据: 47 | 48 | ```bash 49 | cd data 50 | python generate_mock_data.py 51 | cd .. 52 | ``` 53 | 54 | 该脚本默认生成5只资产100天的数据,包含open、high、low、close、volume和returns字段。 55 | 56 | ### 3. 计算 Alpha#4 因子 57 | 58 | 生成模拟数据后,运行 `alpha_calculator.py` 脚本来计算 Alpha#4 因子。该脚本会读取 `data/mock_data.csv`,执行公式中的计算,并将结果保存到 `alpha4_results.csv`。 59 | 60 | ```bash 61 | cd alpha/alpha4 62 | python alpha_calculator.py 63 | ``` 64 | 65 | 脚本执行完毕后,会在终端打印出结果文件的前5行、后5行以及 Alpha#4 值的描述性统计信息。 66 | 67 | ## Alpha#4 策略解读 68 | 69 | Alpha#4 是一个**反向低价因子**,该策略试图捕捉低价股票的时间序列相对表现。 70 | 71 | 为了更好地理解计算过程,我们以实际生成的数据为例,展示 asset_1 在 2025-01-24 前后的计算过程: 72 | 73 | ### 实际数据示例 74 | 75 | | date | asset_id | low | rank_low | ts_rank_value | alpha4 | 76 | | ---------- | -------- | ------ | -------- | ------------- | ------ | 77 | | 2025-01-16 | asset_1 | 98.35 | 0.4 | 0.28 | -0.28 | 78 | | 2025-01-17 | asset_1 | 98.85 | 0.4 | 0.33 | -0.33 | 79 | | 2025-01-18 | asset_1 | 100.46 | 0.4 | 0.39 | -0.39 | 80 | | 2025-01-19 | asset_1 | 100.82 | 0.4 | 0.44 | -0.44 | 81 | | 2025-01-20 | asset_1 | 100.23 | 0.4 | 0.44 | -0.44 | 82 | | 2025-01-21 | asset_1 | 99.90 | 0.4 | 0.44 | -0.44 | 83 | | 2025-01-22 | asset_1 | 101.29 | 0.4 | 0.44 | -0.44 | 84 | | 2025-01-23 | asset_1 | 101.19 | 0.4 | 0.44 | -0.44 | 85 | | 2025-01-24 | asset_1 | 101.37 | 0.4 | 0.50 | -0.50 | 86 | 87 | ### 计算步骤详解 88 | 89 | #### 1. **截面排名 (`rank(low)`)**: 90 | 91 | 以 2025-01-24 为例,当天5只资产的最低价分别为: 92 | 93 | - asset_1: 101.37 (排名: 0.4 - 第2名) 94 | - asset_2: 94.01 (排名: 0.2 - 第1名,最低价) 95 | - asset_3: 109.72 (排名: 1.0 - 第5名,最高价) 96 | - asset_4: 101.94 (排名: 0.6 - 第3名) 97 | - asset_5: 108.91 (排名: 0.8 - 第4名) 98 | 99 | 可以看出,asset_1 的低价水平在当天排第2位(rank_low = 0.4)。 100 | 101 | #### 2. **时间序列排名 (`Ts_Rank(..., 9)`)**: 102 | 103 | 对于 asset_1 在 2025-01-24,我们观察其过去9天的 rank_low 值: 104 | `[0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4]` 105 | 106 | 由于这9天中所有值都相等(都是0.4),当前值 0.4 在这9个值中的时间序列排名为: 107 | - 排名计算:所有9个值都相等,所以排名为 (0 + 0.5 × 9) / 9 = 0.5 108 | - Ts_Rank = 0.50 109 | 110 | #### 3. **反向化 (`(-1 *)`)**: 111 | 112 | Alpha#4 = -1 × 0.50 = **-0.50** 113 | 114 | ### 特殊情况示例 115 | 116 | 从数据中我们还可以看到一些有趣的案例: 117 | 118 | **案例1:2025-01-25 的 asset_1** 119 | - low: 103.04, rank_low: 0.6 (排名上升) 120 | - ts_rank_value: 0.94 (在过去9天中排名很高) 121 | - alpha4: -0.94 (强烈的反向信号) 122 | 123 | **案例2:asset_2 的稳定模式** 124 | - asset_2 在很长时间内 rank_low 都保持在 0.2 (总是最低价) 125 | - ts_rank_value 稳定在 0.5 126 | - alpha4 稳定在 -0.5 127 | 128 | ## 策略含义 129 | 130 | Alpha#4 的核心逻辑是: 131 | 132 | 1. **低价偏好的反向**: 传统上,低价股票可能被认为具有价值或反弹潜力。但Alpha#4采用反向逻辑。 133 | 134 | 2. **时间序列相对性**: 不仅考虑当前的低价水平,还考虑这一水平在过去9天中的相对位置。 135 | 136 | 3. **均值回归假设**: 如果一只股票的低价在过去9天中排名相对较高(即相对高价),Alpha#4给出负信号,暗示可能的价格回调。 137 | 138 | 4. **短期动量反转**: 9天的时间窗口捕捉短期价格动量,并基于反转逻辑进行交易。 139 | 140 | ### 实际结果统计 141 | 142 | 基于生成的500个观测值: 143 | - **平均值**: -0.4963 (整体偏向负值) 144 | - **标准差**: 0.1921 (波动适中) 145 | - **范围**: -0.9444 到 -0.0556 (全部为负值,符合反向逻辑) 146 | - **分布**: 25%分位数为-0.5556,75%分位数为-0.4444 147 | 148 | 该策略适用于: 149 | - 寻找短期过度表现的股票进行反向操作 150 | - 基于价格水平的相对变化进行交易决策 151 | - 利用股票价格的短期均值回归特性 152 | 153 | ## 风险提示 154 | 155 | - Alpha#4 是基于历史价格模式的统计策略,不保证未来表现 156 | - 策略的有效性可能随市场环境变化而变化 157 | - 建议与其他因子结合使用,构建多因子投资组合 158 | - 请注意交易成本和市场流动性对实际表现的影响 159 | 160 | 如需帮助或有建议,欢迎交流! 161 | -------------------------------------------------------------------------------- /alpha/alpha34/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#34: 截面合成因子 2 | 3 | ## 因子定义 4 | 5 | ``` 6 | rank(((1 - rank((stddev(returns, 2) / stddev(returns, 5)))) + (1 - rank(delta(close, 1))))) 7 | ``` 8 | 9 | ## 计算逻辑 10 | 11 | 该因子结合了多项技术分析指标,旨在从不同的时间尺度和视角捕捉市场动量和趋势反转。 12 | 13 | 1. **`stddev(returns, 2)` / `stddev(returns, 5)`**: 14 | * 计算过去2天和过去5天回报率的标准差。标准差衡量价格波动的幅度。 15 | * 两者之比可以反映短期波动性与长期波动性之间的关系。如果短期波动性相对于长期波动性较低,可能预示着趋势的稳定或潜在的反转。 16 | 17 | 2. **`1 - rank((stddev(returns, 2) / stddev(returns, 5)))`**: 18 | * 对上述比率进行截面排序,并用1减去排序结果。 19 | * 这意味着比率越小(短期波动性相对于长期波动性越低),该部分的因子值越大。 20 | 21 | 3. **`delta(close, 1)`**: 22 | * 计算今日收盘价与昨日收盘价的差值(即一日涨跌幅)。 23 | * 这是衡量短期价格变动最直接的指标。 24 | 25 | 4. **`1 - rank(delta(close, 1))`**: 26 | * 对昨日收盘价差进行截面排序,并用1减去排序结果。 27 | * 这意味着价格跌幅越大(`delta(close, 1)`越小,排序值越小),该部分的因子值越大;反之,价格涨幅越大,该部分的因子值越小。 28 | 29 | 5. **最终因子值**: 30 | * 将步骤2和步骤4的结果相加,并对总和进行最终的截面排序。 31 | * 该最终排序值即为 Alpha#34 的输出。高的因子值通常意味着: 32 | * 短期波动性相对于长期波动性较低(可能预示稳定或反转)。 33 | * 近一日价格下跌(可能预示超卖或反弹机会)。 34 | 35 | ## 项目结构 36 | 37 | ``` 38 | alpha-mining/ 39 | ├── data/ 40 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (确保包含 returns, close 字段) 41 | │ └── mock_data.csv # 生成的模拟数据文件 42 | ├── alpha/alpha34/ 43 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#34 44 | │ ├── alpha34_results.csv # 计算得到的 Alpha#34 结果文件 45 | │ ├── README.md # 本说明文档 46 | │ └── cast.md # Alpha#34 策略简介 47 | ``` 48 | 49 | ## 使用步骤 50 | 51 | ### 1. 环境准备 52 | 53 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 54 | 55 | ```bash 56 | pip install pandas numpy 57 | ``` 58 | 59 | ### 2. 检查模拟数据 60 | 61 | 本 Alpha 依赖于 `returns` 和 `close` 数据。请确保 `data/mock_data.csv` 文件存在,并且包含了 `date`, `asset_id`, `returns`, `close` 列。如果文件不存在或数据不完整,请运行或修改 `data/generate_mock_data.py` 脚本。 62 | 63 | ```bash 64 | # 检查或生成数据 (如果需要) 65 | cd ../../data # 假设当前在 alpha/alpha34 目录 66 | python generate_mock_data.py # 假设此脚本能生成所需字段 67 | cd ../alpha/alpha34 68 | ``` 69 | 70 | ### 3. 计算 Alpha#34 因子 71 | 72 | 进入 `alpha/alpha34` 目录并运行 `alpha_calculator.py` 脚本: 73 | 74 | ```bash 75 | python alpha_calculator.py 76 | ``` 77 | 78 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#34,并将结果保存到当前目录下的 `alpha34_results.csv`。 79 | 80 | ## 数据输入 81 | 82 | * `returns`: 每日收盘价到收盘价的回报。 83 | * `close`: 每日收盘价数据。 84 | 85 | 这些数据预计从 `../../data/mock_data.csv` 文件中获取。 86 | 87 | ## 输出格式 88 | 89 | 输出的 CSV 文件 (`alpha34_results.csv`) 将包含以下列(除了原始数据列),所有数值型 alpha 相关列均保留两位小数: 90 | 91 | - `date`: 交易日期 92 | - `asset_id`: 资产ID 93 | - `open`, `high`, `low`, `close`, `volume`, `vwap`, `returns`: 原始数据中的对应列 94 | - `part_A`: 中间计算结果 `1 - rank((stddev(returns, 2) / stddev(returns, 5)))` 95 | - `part_B`: 中间计算结果 `1 - rank(delta(close, 1))` 96 | - `sum_parts_AB`: `part_A` 和 `part_B` 的总和 97 | - `alpha34`: 最终计算的 Alpha#34 值。 98 | 99 | ## 注意事项与风险提示 100 | 101 | - **NaN 值**: 如果输入数据缺失,相应的 Alpha 值将为 NaN。请确保数据完整性。 102 | - **排名方法**: `pandas` 的 `rank(method='average', pct=True)` 通常用于截面排名,结果是百分比形式。 103 | - **小数位数**: 最终的 Alpha#34 值及中间结果按要求保留两位小数。 104 | - **市场适用性**: 此因子在不同市场环境或资产类别上表现可能迥异。务必进行充分的回测和验证。 105 | - **数据质量**: 输入数据的准确性和完整性至关重要。 106 | 107 | Alpha#34 是一个基于多项指标合成的因子,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 108 | 109 | ## 策略解读与计算示例 110 | 111 | 我们将以 `asset_1` 在日期 `2025-01-05` 的数据为例,展示 Alpha#34 的计算。 112 | 113 | **背景数据 (源自 `alpha34_results.csv` for `asset_1` on `2025-01-05`):** 114 | - `returns` (2025-01-05): 0.01 115 | - `close` (2025-01-05): 100.50 116 | - `close` (2025-01-04): 99.40 117 | - `part_A` (intermediate): 0.20 118 | - `part_B` (intermediate): 0.40 119 | - `sum_parts_AB` (intermediate): 0.60 120 | - `alpha34`: 0.40 121 | 122 | **计算 Alpha#34 (简化示例,使用中间结果):** 123 | 124 | 1. **`delta(close, 1)`**: 125 | `close` (2025-01-05) - `close` (2025-01-04) = `100.50 - 99.40 = 1.10` 126 | 127 | 2. **`1 - rank((stddev(returns, 2) / stddev(returns, 5)))` (Part A):** 128 | 此部分经过内部计算和截面排序,对于 `asset_1` 在 `2025-01-05` 的结果为 `part_A = 0.20`。 129 | 130 | 3. **`1 - rank(delta(close, 1))` (Part B):** 131 | `delta(close, 1)` 的值(`1.10`)经过截面排序并用1减去排名后,对于 `asset_1` 在 `2025-01-05` 的结果为 `part_B = 0.40`。 132 | 133 | 4. **求和**: 134 | `part_A + part_B = 0.20 + 0.40 = 0.60` 135 | 136 | 5. **最终排名**: 137 | 对所有资产在 `2025-01-05` 的 `sum_parts_AB` 值进行截面排名。 138 | 假设在 `2025-01-05`,所有资产的 `sum_parts_AB` 值经过排序后,`asset_1` 的排名对应百分比为 `0.40`。 139 | 140 | 因此,`Alpha#34` 对 `asset_1` 在 `2025-01-05` 的最终计算值为 `0.40`。 141 | 142 | 此值与 `alpha34_results.csv` 中 `asset_1` 在 `2025-01-05` 的 `alpha34` 列的值 `0.40` 相符。 -------------------------------------------------------------------------------- /alpha/archive/alpha2/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def delta(series, period): 5 | """ 6 | Computes the difference between current value and value 'period' periods ago. 7 | delta(series, N) = series[t] - series[t-N] 8 | """ 9 | return series - series.shift(period) 10 | 11 | def rolling_correlation(x, y, window): 12 | """ 13 | Computes rolling correlation between two series over a specified window. 14 | """ 15 | return x.rolling(window=window, min_periods=1).corr(y) 16 | 17 | def calculate_alpha2(df, delta_period=2, correlation_window=6): 18 | """ 19 | Calculates Alpha#2 based on the given formula. 20 | 21 | Alpha#2: (-1 * correlation(rank(delta(log(volume), 2)), rank(((close - open) / open)), 6)) 22 | """ 23 | # Ensure data is sorted by date for rolling calculations 24 | df = df.sort_values(by=['asset_id', 'date']) 25 | 26 | # Check if required columns exist 27 | required_columns = ['date', 'asset_id', 'close', 'open', 'volume'] 28 | missing_columns = [col for col in required_columns if col not in df.columns] 29 | if missing_columns: 30 | raise ValueError(f"Missing required columns: {missing_columns}") 31 | 32 | # Calculate log(volume) 33 | df['log_volume'] = np.log(df['volume']) 34 | 35 | # Calculate delta(log(volume), 2) for each asset 36 | df['delta_log_volume'] = df.groupby('asset_id')['log_volume'].transform( 37 | lambda x: delta(x, delta_period) 38 | ) 39 | 40 | # Calculate intraday return: (close - open) / open 41 | df['intraday_return'] = (df['close'] - df['open']) / df['open'] 42 | 43 | # Calculate daily cross-sectional ranks 44 | df['rank_delta_log_volume'] = df.groupby('date')['delta_log_volume'].rank(pct=True, method='average') 45 | df['rank_intraday_return'] = df.groupby('date')['intraday_return'].rank(pct=True, method='average') 46 | 47 | # Calculate rolling correlation for each asset 48 | def calculate_correlation_for_group(group): 49 | return rolling_correlation( 50 | group['rank_delta_log_volume'], 51 | group['rank_intraday_return'], 52 | correlation_window 53 | ) 54 | 55 | df['correlation'] = df.groupby('asset_id').apply( 56 | calculate_correlation_for_group 57 | ).reset_index(level=0, drop=True) 58 | 59 | # Final Alpha#2: -1 * correlation 60 | df['alpha2'] = -1 * df['correlation'] 61 | 62 | # Round to 4 decimal places for better readability 63 | df['alpha2'] = df['alpha2'].round(4) 64 | 65 | # Handle NaN values (set to 0 for early periods where correlation cannot be calculated) 66 | df['alpha2'] = df['alpha2'].fillna(0) 67 | 68 | return df[['date', 'asset_id', 'open', 'close', 'volume', 'alpha2']] 69 | 70 | if __name__ == "__main__": 71 | # Load mock data 72 | try: 73 | data_df = pd.read_csv("../../data/mock_data.csv", parse_dates=['date']) 74 | except FileNotFoundError: 75 | print("Error: ../../data/mock_data.csv not found. Please ensure the mock data file exists.") 76 | print("The file should contain columns: date, asset_id, open, close, volume") 77 | exit() 78 | 79 | # Check if required columns exist 80 | required_columns = ['date', 'asset_id', 'close', 'open', 'volume'] 81 | missing_columns = [col for col in required_columns if col not in data_df.columns] 82 | if missing_columns: 83 | print(f"Error: Missing required columns in mock_data.csv: {missing_columns}") 84 | print("Required columns: date, asset_id, open, close, volume") 85 | exit() 86 | 87 | # Calculate Alpha#2 88 | try: 89 | alpha_df = calculate_alpha2(data_df.copy()) 90 | 91 | # Save results 92 | alpha_df.to_csv("alpha2_results.csv", index=False) 93 | print("Alpha#2 calculated and results saved to alpha2_results.csv") 94 | print("\nFirst 5 rows of Alpha#2 results:") 95 | print(alpha_df.head()) 96 | print("\nLast 5 rows of Alpha#2 results:") 97 | print(alpha_df.tail()) 98 | print("\nDescriptive statistics of Alpha#2:") 99 | print(alpha_df['alpha2'].describe()) 100 | 101 | # Additional statistics 102 | print(f"\nNumber of non-zero Alpha#2 values: {(alpha_df['alpha2'] != 0).sum()}") 103 | print(f"Number of NaN Alpha#2 values: {alpha_df['alpha2'].isna().sum()}") 104 | 105 | except Exception as e: 106 | print(f"Error calculating Alpha#2: {str(e)}") 107 | exit() -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # macOS 132 | .DS_Store 133 | .AppleDouble 134 | .LSOverride 135 | 136 | # Icon must end with two \r 137 | Icon 138 | 139 | # Thumbnails 140 | ._* 141 | 142 | # Files that might appear in the root of a volume 143 | .DocumentRevisions-V100 144 | .fseventsd 145 | .Spotlight-V100 146 | .TemporaryItems 147 | .Trashes 148 | .VolumeIcon.icns 149 | .com.apple.timemachine.donotpresent 150 | 151 | # Directories potentially created on remote AFP share 152 | .AppleDB 153 | .AppleDesktop 154 | Network Trash Folder 155 | Temporary Items 156 | .apdisk 157 | 158 | # Windows 159 | Thumbs.db 160 | Thumbs.db:encryptable 161 | ehthumbs.db 162 | ehthumbs_vista.db 163 | 164 | # Dump file 165 | *.stackdump 166 | 167 | # Folder config file 168 | [Dd]esktop.ini 169 | 170 | # Recycle Bin used on file shares 171 | $RECYCLE.BIN/ 172 | 173 | # Windows Installer files 174 | *.cab 175 | *.msi 176 | *.msix 177 | *.msm 178 | *.msp 179 | 180 | # Windows shortcuts 181 | *.lnk 182 | 183 | # Linux 184 | *~ 185 | 186 | # temporary files which can be created if a process still has a handle open of a deleted file 187 | .fuse_hidden* 188 | 189 | # KDE directory preferences 190 | .directory 191 | 192 | # Linux trash folder which might appear on any partition or disk 193 | .Trash-* 194 | 195 | # .nfs files are created when an open file is removed but is still being accessed 196 | .nfs* 197 | 198 | # IDE 199 | .vscode/ 200 | .idea/ 201 | *.swp 202 | *.swo 203 | *~ 204 | 205 | # Project specific 206 | outputs/temp/ 207 | *.tmp 208 | *.bak 209 | 210 | # Data files (可根据需要调整) 211 | *.csv 212 | *.json 213 | *.xml 214 | *.xlsx 215 | *.png 216 | *.jpg 217 | *.jpeg 218 | *.gif 219 | *.mp4 220 | *.avi 221 | *.mov 222 | doc/alpha_* 223 | manim/scripts/ja/* 224 | # Logs 225 | prompt/ 226 | *.mp3 227 | *.log 228 | logs/ 229 | .cursorignore 230 | 231 | # API keys and secrets 232 | .env.local 233 | .env.production 234 | config/secrets.py 235 | secrets.json 236 | 237 | # Manim specific (如果使用Manim) 238 | media/ 239 | .manim_cache/ 240 | 241 | # Jupyter 242 | *.ipynb_checkpoints/ 243 | 244 | # Virtual environments 245 | alpha-mining-env/ 246 | venv-*/ 247 | 248 | 249 | # Archives - do not commit 250 | alpha/archive/ 251 | manim/scripts/archive/ 252 | process/* 253 | -------------------------------------------------------------------------------- /data/generate_mock_data.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from datetime import datetime, timedelta 4 | 5 | def generate_data(num_assets=5, num_days=300): 6 | """ 7 | Generates mock financial data for multiple assets. 8 | 9 | Args: 10 | num_assets (int): Number of assets. 11 | num_days (int): Number of trading days. 12 | 13 | Returns: 14 | pandas.DataFrame: DataFrame with columns ['date', 'asset_id', 'open', 'high', 'low', 'close', 'volume', 'vwap', 'returns']. 15 | """ 16 | data = [] 17 | start_date = datetime(2024, 6, 1) 18 | 19 | for asset_idx in range(num_assets): 20 | asset_id = f"asset_{asset_idx + 1}" 21 | # Simulate closing prices with a random walk 22 | prices = [100.0] # Initial price 23 | for _ in range(1, num_days): 24 | change = round(np.random.normal(0, 1.5), 1) 25 | prices.append(round(max(1, prices[-1] + change), 1)) # Ensure price is positive 26 | 27 | for day_idx in range(num_days): 28 | date = start_date + timedelta(days=day_idx) 29 | close_price = prices[day_idx] 30 | 31 | # Generate open price (usually close to previous close or current close) 32 | if day_idx == 0: 33 | open_price = round(close_price + np.random.normal(0, 0.5), 2) 34 | else: 35 | # Open price is usually close to previous close with some gap 36 | gap = np.random.normal(0, 0.8) # Random gap up/down 37 | open_price = round(max(1, prices[day_idx-1] + gap), 2) 38 | 39 | # Generate high and low prices 40 | # High should be >= max(open, close) 41 | # Low should be <= min(open, close) 42 | base_high = max(open_price, close_price) 43 | base_low = min(open_price, close_price) 44 | 45 | # Add some random variations for high and low 46 | high_variation = abs(np.random.normal(0, 0.5)) # Always positive 47 | low_variation = abs(np.random.normal(0, 0.5)) # Always positive 48 | 49 | high_price = round(base_high + high_variation, 2) 50 | low_price = round(max(0.01, base_low - low_variation), 2) # Ensure positive 51 | 52 | # Generate volume (log-normal distribution for realistic volume patterns) 53 | base_volume = 1000000 # 1 million base volume 54 | volume_multiplier = np.random.lognormal(0, 0.5) # Log-normal for realistic volume distribution 55 | volume = int(base_volume * volume_multiplier) 56 | 57 | # Calculate VWAP (Volume Weighted Average Price) 58 | # Simplified VWAP calculation: average of high, low, close weighted equally 59 | # In reality, VWAP is calculated as cumulative(price * volume) / cumulative(volume) throughout the day 60 | # For simplicity, we'll approximate it as a weighted average of key price points 61 | typical_price = (high_price + low_price + close_price) / 3 62 | # Add some random variation to make it more realistic (±0.5% of typical price) 63 | vwap_noise = np.random.normal(0, typical_price * 0.005) 64 | vwap = round(typical_price + vwap_noise, 2) 65 | # Ensure VWAP is within reasonable bounds (between low and high) 66 | vwap = round(max(low_price, min(high_price, vwap)), 2) 67 | 68 | # Calculate returns based on close prices 69 | if day_idx == 0: 70 | daily_return = round(np.random.normal(0, 0.05), 4) # Small random return for the first day 71 | else: 72 | daily_return = round(((prices[day_idx] / prices[day_idx-1]) - 1) , 4) 73 | 74 | data.append({ 75 | "date": date.strftime('%Y-%m-%d'), 76 | "asset_id": asset_id, 77 | "open": open_price, 78 | "high": high_price, 79 | "low": low_price, 80 | "close": close_price, 81 | "volume": volume, 82 | "vwap": vwap, 83 | "returns": daily_return 84 | }) 85 | 86 | df = pd.DataFrame(data) 87 | df['date'] = pd.to_datetime(df['date']) 88 | df = df.sort_values(by=['asset_id', 'date']).reset_index(drop=True) 89 | return df 90 | 91 | if __name__ == "__main__": 92 | mock_df = generate_data(num_assets=5, num_days=300) 93 | mock_df.to_csv("mock_data.csv", index=False) 94 | print("mock_data.csv generated successfully with open, high, low, close, volume, vwap and returns data.") 95 | print("\nFirst 5 rows of generated data:") 96 | print(mock_df.head()) 97 | print("\nData columns:", list(mock_df.columns)) -------------------------------------------------------------------------------- /alpha/alpha38/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#38: 反向时间序列排名与日内波动排名 2 | 3 | ## 因子定义 4 | 5 | ``` 6 | ((-1 * rank(Ts_Rank(close, 10))) * rank((close / open))) 7 | ``` 8 | 9 | ## 计算逻辑 10 | 11 | 该因子结合了收盘价在短期时间序列中的反向排名与日内价格波动(开盘价与收盘价之比)的截面排名,旨在识别那些近期表现相对较弱,但日内波动较大的资产。它可能捕捉到短期超卖且具有潜在反转动力的股票。 12 | 13 | 1. **`(close / open)`**: 14 | * 计算每日收盘价与开盘价的比值。这代表了当日的价格变化。如果比值大于1,表示收涨;小于1则表示收跌。 15 | 16 | 2. **`rank((close / open))`**: 17 | * 对每日 `(close / open)` 的结果进行截面排名。排名越高,表示当日收盘价相对于开盘价的涨幅越大,或跌幅越小(如果排序是升序)。 18 | 19 | 3. **`Ts_Rank(close, 10)`**: 20 | * 计算当前 `close` 价格在过去10个交易日中的时间序列排名。这反映了当前收盘价在近期历史中的相对位置。例如,如果 `Ts_Rank` 接近1,表示当前收盘价是过去10天中的最高点之一;如果接近0,则表示最低点之一。 21 | 22 | 4. **`rank(Ts_Rank(close, 10))`**: 23 | * 对上述 `Ts_Rank(close, 10)` 的结果进行截面排名。排名越高,表示该资产的近期收盘价在所有资产中处于近期历史高位。 24 | 25 | 5. **`(-1 * rank(Ts_Rank(close, 10)))`**: 26 | * 将步骤4的结果乘以-1。这意味着,如果一个资产的近期收盘价在截面上处于历史高位(`rank(Ts_Rank(close, 10))` 值高),那么这一部分的值会是负数且绝对值大。反之,如果近期收盘价在截面上处于历史低位,则这一部分的值会是正数且绝对值大。这旨在筛选出近期表现相对较弱的资产。 27 | 28 | 6. **最终因子值**: 29 | * 将步骤5(反向时间序列排名)和步骤2(日内波动排名)的结果相乘。 30 | * 高的因子值通常意味着: 31 | * 资产近期收盘价在截面上处于历史低位(即 `Ts_Rank` 值小,乘以-1后变大)。 32 | * 当日的收盘价与开盘价的比值在截面上相对较大(收盘价相对于开盘价涨幅大或跌幅小)。 33 | * 此组合旨在寻找那些近期下跌但当日出现企稳或反弹迹象的资产。 34 | 35 | ## 项目结构 36 | 37 | ``` 38 | alpha-mining/ 39 | ├── data/ 40 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (确保包含 open, close 字段) 41 | │ └── mock_data.csv # 生成的模拟数据文件 42 | ├── alpha/alpha38/ 43 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#38 44 | │ ├── alpha38_results.csv # 计算得到的 Alpha#38 结果文件 45 | │ ├── README.md # 本说明文档 46 | │ └── cast.md # Alpha#38 策略简介 47 | ``` 48 | 49 | ## 使用步骤 50 | 51 | ### 1. 环境准备 52 | 53 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 54 | 55 | ```bash 56 | pip install pandas numpy 57 | ``` 58 | 59 | ### 2. 检查模拟数据 60 | 61 | 本 Alpha 依赖于 `open` 和 `close` 数据。请确保 `data/mock_data.csv` 文件存在,并且包含了 `date`, `asset_id`, `open`, `close` 列。如果文件不存在或数据不完整,请运行或修改 `data/generate_mock_data.py` 脚本。 62 | 63 | ```bash 64 | # 检查或生成数据 (如果需要) 65 | cd ../../data # 假设当前在 alpha/alpha38 目录 66 | python generate_mock_data.py # 假设此脚本能生成所需字段 67 | cd ../alpha/alpha38 68 | ``` 69 | 70 | ### 3. 计算 Alpha#38 因子 71 | 72 | 进入 `alpha/alpha38` 目录并运行 `alpha_calculator.py` 脚本: 73 | 74 | ```bash 75 | python alpha_calculator.py 76 | ``` 77 | 78 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#38,并将结果保存到当前目录下的 `alpha38_results.csv`。 79 | 80 | ## 数据输入 81 | 82 | * `open`: 每日开盘价数据。 83 | * `close`: 每日收盘价数据。 84 | 85 | 这些数据预计从 `../../data/mock_data.csv` 文件中获取。 86 | 87 | ## 输出格式 88 | 89 | 输出的 CSV 文件 (`alpha38_results.csv`) 将包含以下列(除了原始数据列),所有数值型 alpha 相关列均保留两位小数: 90 | 91 | - `date`: 交易日期 92 | - `asset_id`: 资产ID 93 | - `open`, `high`, `low`, `close`, `volume`, `vwap`, `returns`: 原始数据中的对应列 94 | - `close_over_open`: `(close / open)` 中间计算结果 95 | - `ranked_close_over_open`: `rank((close / open))` 中间计算结果 96 | - `ts_rank_close_10`: `Ts_Rank(close, 10)` 中间计算结果 97 | - `ranked_ts_rank_close_10`: `rank(Ts_Rank(close, 10))` 中间计算结果 98 | - `neg_ranked_ts_rank`: `(-1 * rank(Ts_Rank(close, 10)))` 中间计算结果 99 | - `alpha38`: 最终计算的 Alpha#38 值。 100 | 101 | ## 注意事项与风险提示 102 | 103 | - **NaN 值**: 如果输入数据缺失或计算中出现 `NaN`(例如,排名或时间序列操作需要足够的数据点),相应的 Alpha 值将为 `NaN`。请确保数据完整性。 104 | - **排名方法**: `pandas` 的 `rank(method='average', pct=True)` 通常用于截面排名,结果是百分比形式。 105 | - **小数位数**: 最终的 Alpha#38 值及中间结果按要求保留两位小数。 106 | - **市场适用性**: 此因子在不同市场环境或资产类别上表现可能迥异。务必进行充分的回测和验证。 107 | - **数据质量**: 输入数据的准确性和完整性至关重要。 108 | 109 | Alpha#38 是一个基于多项指标合成的因子,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 110 | 111 | ## 策略解读与计算示例 112 | 113 | 我们将以 `asset_1` 在日期 `2024-06-10` 的数据为例,展示 Alpha#38 的计算。 114 | 115 | **背景数据 (源自 `alpha38_results.csv` for `asset_1` on `2024-06-10`):** 116 | - `open` (2024-06-10): 104.28 117 | - `close` (2024-06-10): 105.80 118 | - `ts_rank_close_10` (2024-06-10): 1.00 119 | 120 | **计算 Alpha#38 (简化示例,使用中间结果):** 121 | 122 | 1. **`(close / open)` (2024-06-10):** 123 | `105.80 / 104.28 = 1.01` (保留两位小数) 124 | 125 | 2. **`rank((close / open))` (2024-06-10):** 126 | 假设对所有资产在 `2024-06-10` 的 `(close / open)` 值进行截面排名,`asset_1` 得到 `0.80`。 127 | 128 | 3. **`Ts_Rank(close, 10)` (2024-06-10):** 129 | 在 `2024-06-10`,`asset_1` 的 `close` 价格在过去10天的 `Ts_Rank` 为 `1.00`。 130 | 131 | 4. **`rank(Ts_Rank(close, 10))` (2024-06-10):** 132 | 假设对所有资产在 `2024-06-10` 的 `Ts_Rank(close, 10)` 值进行截面排名,`asset_1` 得到 `0.90`。 133 | 134 | 5. **`(-1 * rank(Ts_Rank(close, 10)))` (2024-06-10):** 135 | `-1 * 0.90 = -0.90` 136 | 137 | 6. **最终 Alpha#38 值**: 138 | `neg_ranked_ts_rank * ranked_close_over_open = -0.90 * 0.80 = -0.72` 139 | 140 | 因此,`Alpha#38` 对 `asset_1` 在 `2024-06-10` 的最终计算值为 `-0.72`。 141 | 这个值应与 `alpha38_results.csv` 中 `asset_1` 在 `2024-06-10` 的 `alpha38` 列的值相符。 -------------------------------------------------------------------------------- /alpha/alpha36/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#36: 多因子动量与价值策略 2 | 3 | ## 因子定义 4 | 5 | ``` 6 | (((((2.21 * rank(correlation((close - open), delay(volume, 1), 15))) + (0.7 * rank((open - close)))) + (0.73 * rank(Ts_Rank(delay((-1 * returns), 6), 5)))) + rank(abs(correlation(vwap, adv20, 6)))) + (0.6 * rank((((sum(close, 200) / 200) - open) * (close - open))))) 7 | ``` 8 | 9 | ## 计算逻辑 10 | 11 | 该因子是一个复杂的多因子模型,结合了价格动量、成交量、价值和波动性指标,旨在识别具有特定行为模式的资产。 12 | 13 | 1. **`term1: 2.21 * rank(correlation((close - open), delay(volume, 1), 15))`** 14 | * `close - open`: 当日日内价格变动,反映日内动量。 15 | * `delay(volume, 1)`: 昨日成交量。 16 | * `correlation(..., 15)`: 计算过去15天日内价格变动与昨日成交量的相关性。这可能用于捕捉"价涨量增"或"价跌量缩"等模式。 17 | * `rank(...)`: 对该相关性进行截面排名。 18 | * `2.21 * ...`: 给予该项较高的权重。 19 | 20 | 2. **`term2: 0.7 * rank(open - close)`** 21 | * `open - close`: 日内价格反转信号(与 term1 中的 `close - open` 相反)。 22 | * `rank(...)`: 对该信号进行截面排名。 23 | * `0.7 * ...`: 给予该项一个权重。 24 | 25 | 3. **`term3: 0.73 * rank(Ts_Rank(delay((-1 * returns), 6), 5))`** 26 | * `delay((-1 * returns), 6)`: 6天前回报率的负值。 27 | * `Ts_Rank(..., 5)`: 在过去5天的时间序列中对上述值进行排名。这捕捉了近期(6天前至10天前)的历史回报表现。 28 | * `rank(...)`: 对该时间序列排名进行截面排名。 29 | * `0.73 * ...`: 给予该项一个权重。 30 | 31 | 4. **`term4: rank(abs(correlation(vwap, adv20, 6)))`** 32 | * `adv20`: 过去20天的平均日成交额。 33 | * `correlation(vwap, adv20, 6)`: 计算过去6天VWAP(成交量加权平均价)与20日平均成交额的相关性。这衡量了价格(VWAP)与流动性变化的关联强度。 34 | * `abs(...)`: 取相关性的绝对值,关注其强度而非方向。 35 | * `rank(...)`: 对该强度进行截面排名。 36 | 37 | 5. **`term5: 0.6 * rank((((sum(close, 200) / 200) - open) * (close - open)))`** 38 | * `sum(close, 200) / 200`: 过去200天的移动平均收盘价,一个长期价值基准。 39 | * `( ... - open)`: 当日开盘价与长期价值基准的偏离。 40 | * `(close - open)`: 当日日内动量。 41 | * 两者相乘,形成一个交互项,可能用于识别开盘价偏离长期价值后,日内走势是回归还是延续。 42 | * `rank(...)`: 对该交互项进行截面排名。 43 | * `0.6 * ...`: 给予该项一个权重。 44 | 45 | 6. **最终因子值**: 46 | * 将上述五项的结果加权求和,得到最终的 Alpha#36 值。 47 | 48 | ## 因子数值范围 49 | 50 | `Alpha#36` 的理论数值区间为 `[0, 5.24]`。 51 | 52 | 该因子由五个加权项组成,每个项在截面排名后都归一化到 `[0, 1]` 的范围。因此,每个项的取值范围为: 53 | * **`term1`**: `2.21 * rank(...)`,范围 `[0, 2.21 * 1]` 即 `[0, 2.21]`。 54 | * **`term2`**: `0.7 * rank(...)`,范围 `[0, 0.7 * 1]` 即 `[0, 0.7]`。 55 | * **`term3`**: `0.73 * rank(...)`,范围 `[0, 0.73 * 1]` 即 `[0, 0.73]`。 56 | * **`term4`**: `rank(abs(correlation(...)))`,范围 `[0, 1]`。 57 | * **`term5`**: `0.6 * rank(...)`,范围 `[0, 0.6 * 1]` 即 `[0, 0.6]`。 58 | 59 | 将这些项的最大值相加,可以得到最终 Alpha 值的最大理论范围:`2.21 + 0.7 + 0.73 + 1 + 0.6 = 5.24`。因此,理论上 `Alpha#36` 的值介于 `[0, 5.24]` 之间。 60 | 61 | ## 策略解读与计算示例 62 | 63 | 为了更好地理解 Alpha#36 的计算逻辑和数值特性,我们假设在某个交易日,对于某个资产,各分量经过截面排名(归一化至[0,1]区间)或相关性计算后的值如下: 64 | 65 | * `rank(correlation((close - open), delay(volume, 1), 15))` = `0.50` 66 | * `rank((open - close))` = `0.30` 67 | * `rank(Ts_Rank(delay((-1 * returns), 6), 5))` = `0.70` 68 | * `rank(abs(correlation(vwap, adv20, 6)))` = `0.80` 69 | * `rank((((sum(close, 200) / 200) - open) * (close - open)))` = `0.60` 70 | 71 | 根据公式各部分计算: 72 | 73 | 1. **`term1`**: `2.21 * 0.50 = 1.105` 74 | 2. **`term2`**: `0.7 * 0.30 = 0.21` 75 | 3. **`term3`**: `0.73 * 0.70 = 0.511` 76 | 4. **`term4`**: `0.80` 77 | 5. **`term5`**: `0.6 * 0.60 = 0.36` 78 | 79 | 因此: 80 | `Alpha#36 = 1.105 + 0.21 + 0.511 + 0.80 + 0.36 = 2.986` 81 | 82 | 四舍五入到两位小数后,结果为 `2.99`。 83 | 84 | 这个例子展示了如何结合各个子项的贡献来计算最终的 Alpha#36 值,以及该因子如何反映多个市场驱动因素的综合效应。 85 | 86 | ## 项目结构 87 | 88 | ``` 89 | alpha-mining/ 90 | ├── data/ 91 | │ ├── generate_mock_data.py 92 | │ └── mock_data.csv 93 | ├── alpha/alpha36/ 94 | │ ├── alpha_calculator.py 95 | │ ├── alpha36_results.csv 96 | │ ├── README.md 97 | │ └── cast.md 98 | ``` 99 | 100 | ## 使用步骤 101 | 102 | ### 1. 环境准备 103 | 确保安装 `pandas` 和 `numpy`。 104 | ```bash 105 | pip install pandas numpy 106 | ``` 107 | 108 | ### 2. 检查模拟数据 109 | 本 Alpha 依赖于 `open`, `close`, `volume`, `returns`, `vwap`。脚本会自动计算 `adv20`。请确保 `data/mock_data.csv` 存在且包含所需列。 110 | 111 | ### 3. 计算 Alpha#36 因子 112 | 进入 `alpha/alpha36` 目录并运行 `alpha_calculator.py`。 113 | ```bash 114 | python alpha_calculator.py 115 | ``` 116 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#36,并将结果保存到 `alpha36_results.csv`。 117 | 118 | ## 数据输入 119 | * `open`, `close`, `high`, `low`, `volume`: 标准日度数据。 120 | * `vwap`: 日度成交量加权平均价。 121 | * `returns`: 日度收盘-收盘回报率。 122 | * `adv20`: 过去20日平均成交额(将由脚本从 `close` 和 `volume` 计算得出)。 123 | 124 | ## 输出格式 125 | 输出的 CSV 文件 (`alpha36_results.csv`) 将包含原始数据列、关键中间计算列以及最终的 Alpha#36 值,所有数值列保留两位小数。 126 | - `date`, `asset_id`, ... (原始列) 127 | - `term1`, `term2`, `term3`, `term4`, `term5`: 五个主要部分的中间结果。 128 | - `alpha36`: 最终计算的 Alpha#36 值。 129 | 130 | ## 注意事项与风险提示 131 | - **NaN 值**: 大量的窗口计算(如15、200天)可能导致数据序列初始阶段出现较多 NaN 值。这是正常的计算特性,若需要更长期的有效数据,请考虑在 `data/generate_mock_data.py` 中生成更多历史数据。 132 | - **数据质量**: 输入数据的准确性和完整性至关重要。 133 | - **参数敏感性**: 因子表现可能对窗口大小(如15, 6, 5, 200)和权重(2.21, 0.7等)高度敏感。 134 | - **市场适用性**: 这是一个复杂的因子,在不同市场环境下表现可能迥异,务必进行充分的回测和验证。 -------------------------------------------------------------------------------- /alpha/alpha37/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#37: 截面合成因子 2 | 3 | ## 因子定义 4 | 5 | ``` 6 | (rank(correlation(delay((open - close), 1), close, 200)) + rank((open - close))) 7 | ``` 8 | 9 | ## 计算逻辑 10 | 11 | 该因子结合了时间序列相关性分析和截面排名,旨在捕捉市场中开盘价与收盘价差异的动量效应。 12 | 13 | 1. **`(open - close)`**: 14 | * 计算每日开盘价与收盘价的差值。这代表了当日的价格动量或反转信号,正值表示收涨,负值表示收跌。 15 | 16 | 2. **`delay((open - close), 1)`**: 17 | * 获取前一日的 `(open - close)` 值。 18 | 19 | 3. **`correlation(delay((open - close), 1), close, 200)`**: 20 | * 计算前一日的 `(open - close)` 值与当日 `close` 价格在过去200个交易日的时间序列相关性。 21 | * 此部分旨在衡量历史动量与当前收盘价之间的关系强度和方向。正相关性可能意味着前一日的动量与今日收盘价同向变动,反之亦然。 22 | 23 | 4. **`rank(correlation(delay((open - close), 1), close, 200))`**: 24 | * 对上述200日时间序列相关性结果进行截面排名。排名越高,表示相关性在截面上越强(无论是正向还是负向),或者在所有资产中排名前列。 25 | 26 | 5. **`rank((open - close))`**: 27 | * 对当日的 `(open - close)` 值进行截面排名。排名越高,表示当日开盘价与收盘价的差值越大(通常意味着当日表现更强劲或更弱势,取决于原始差值的方向)。 28 | 29 | 6. **最终因子值**: 30 | * 将步骤4和步骤5的结果相加。 31 | * 该最终结果即为 Alpha#37 的值。高的因子值通常意味着: 32 | * 前一日动量与当前收盘价之间存在显著的时间序列相关性(经过排名)。 33 | * 当日的开盘价与收盘价的差异在截面上相对较大(经过排名)。 34 | 35 | ## 项目结构 36 | 37 | ``` 38 | alpha-mining/ 39 | ├── data/ 40 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (确保包含 open, close 字段) 41 | │ └── mock_data.csv # 生成的模拟数据文件 42 | ├── alpha/alpha37/ 43 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#37 44 | │ ├── alpha37_results.csv # 计算得到的 Alpha#37 结果文件 45 | │ ├── README.md # 本说明文档 46 | │ └── cast.md # Alpha#37 策略简介 47 | ``` 48 | 49 | ## 使用步骤 50 | 51 | ### 1. 环境准备 52 | 53 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 54 | 55 | ```bash 56 | pip install pandas numpy 57 | ``` 58 | 59 | ### 2. 检查模拟数据 60 | 61 | 本 Alpha 依赖于 `open` 和 `close` 数据。请确保 `data/mock_data.csv` 文件存在,并且包含了 `date`, `asset_id`, `open`, `close` 列。如果文件不存在或数据不完整,请运行或修改 `data/generate_mock_data.py` 脚本。 62 | 63 | ```bash 64 | # 检查或生成数据 (如果需要) 65 | cd ../../data # 假设当前在 alpha/alpha37 目录 66 | python generate_mock_data.py # 假设此脚本能生成所需字段 67 | cd ../alpha/alpha37 68 | ``` 69 | 70 | ### 3. 计算 Alpha#37 因子 71 | 72 | 进入 `alpha/alpha37` 目录并运行 `alpha_calculator.py` 脚本: 73 | 74 | ```bash 75 | python alpha_calculator.py 76 | ``` 77 | 78 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#37,并将结果保存到当前目录下的 `alpha37_results.csv`。 79 | 80 | ## 数据输入 81 | 82 | * `open`: 每日开盘价数据。 83 | * `close`: 每日收盘价数据。 84 | 85 | 这些数据预计从 `../../data/mock_data.csv` 文件中获取。 86 | 87 | ## 输出格式 88 | 89 | 输出的 CSV 文件 (`alpha37_results.csv`) 将包含以下列(除了原始数据列),所有数值型 alpha 相关列均保留两位小数: 90 | 91 | - `date`: 交易日期 92 | - `asset_id`: 资产ID 93 | - `open`, `high`, `low`, `close`, `volume`, `vwap`, `returns`: 原始数据中的对应列 94 | - `oc_diff`: `(open - close)` 中间计算结果 95 | - `corr_oc_delay1_close_200`: `correlation(delay((open - close), 1), close, 200)` 中间计算结果 96 | - `ranked_corr`: `rank(correlation(delay((open - close), 1), close, 200))` 中间计算结果 97 | - `ranked_oc_diff`: `rank((open - close))` 中间计算结果 98 | - `alpha37`: 最终计算的 Alpha#37 值。 99 | 100 | ## 注意事项与风险提示 101 | 102 | - **NaN 值**: 如果输入数据缺失或计算中出现 `NaN`(例如,相关性计算需要足够的数据点),相应的 Alpha 值将为 `NaN`。请确保数据完整性。 103 | - **排名方法**: `pandas` 的 `rank(method='average', pct=True)` 通常用于截面排名,结果是百分比形式。 104 | - **小数位数**: 最终的 Alpha#37 值及中间结果按要求保留两位小数。 105 | - **市场适用性**: 此因子在不同市场环境或资产类别上表现可能迥异。务必进行充分的回测和验证。 106 | - **数据质量**: 输入数据的准确性和完整性至关重要。 107 | 108 | Alpha#37 是一个基于多项指标合成的因子,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 109 | 110 | ## 策略解读与计算示例 111 | 112 | 我们将以 `asset_1` 在日期 `2025-01-05` 的数据为例,展示 Alpha#37 的计算。 113 | 114 | **背景数据 (源自 `alpha37_results.csv` for `asset_1` on `2025-01-05`):** 115 | - `open` (2025-01-05): 100.00 116 | - `close` (2025-01-05): 99.50 117 | - `open` (2025-01-04): 101.00 118 | - `close` (2025-01-04): 100.00 119 | - `oc_diff` (2025-01-05): 0.50 120 | - `corr_oc_delay1_close_200` (intermediate for 2025-01-05): 0.15 (假设值) 121 | - `ranked_corr` (intermediate for 2025-01-05): 0.70 (假设值) 122 | - `ranked_oc_diff` (intermediate for 2025-01-05): 0.30 (假设值) 123 | - `alpha37` (2025-01-05): 1.00 (假设值) 124 | 125 | **计算 Alpha#37 (简化示例,使用中间结果):** 126 | 127 | 1. **`(open - close)` (2025-01-05):** 128 | `100.00 - 99.50 = 0.50` 129 | 130 | 2. **`delay((open - close), 1)` (2025-01-05 对应的 2025-01-04):** 131 | `open` (2025-01-04) - `close` (2025-01-04) = `101.00 - 100.00 = 1.00` 132 | 133 | 3. **`correlation(delay((open - close), 1), close, 200)` (2025-01-05):** 134 | 假设经过200日时间序列相关性计算,在 `2025-01-05` 得到 `0.15`。 135 | 136 | 4. **`rank(correlation(delay((open - close), 1), close, 200))` (2025-01-05):** 137 | 假设对所有资产在 `2025-01-05` 的相关性值进行截面排名,`asset_1` 得到 `0.70`。 138 | 139 | 5. **`rank((open - close))` (2025-01-05):** 140 | 假设对所有资产在 `2025-01-05` 的 `(open - close)` 值进行截面排名,`asset_1` 得到 `0.30`。 141 | 142 | 6. **最终 Alpha#37 值**: 143 | `ranked_corr + ranked_oc_diff = 0.70 + 0.30 = 1.00` 144 | 145 | 因此,`Alpha#37` 对 `asset_1` 在 `2025-01-05` 的最终计算值为 `1.00`。 146 | 这个值应与 `alpha37_results.csv` 中 `asset_1` 在 `2025-01-05` 的 `alpha37` 列的值相符。 -------------------------------------------------------------------------------- /alpha/archive/alpha1/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#1 策略模拟与计算 2 | 3 | 本项目演示了如何根据给定的 Alpha#1 公式生成模拟金融数据、计算 Alpha 因子,并对结果进行分析。 4 | 5 | ## Alpha#1 公式 6 | 7 | Alpha#1 的计算公式如下: 8 | 9 | ``` 10 | (rank(Ts_ArgMax(SignedPower(((returns < 0) ? stddev(returns, 20) : close), 2.), 5)) - 0.5) 11 | ``` 12 | 13 | 其中: 14 | 15 | * `returns`: 资产的日回报率。 16 | * `close`: 资产的日收盘价。 17 | * `stddev(series, N)`: 计算时间序列 `series` 在过去 `N` 天的滚动标准差。 18 | * `SignedPower(series, A)`: 计算 `sign(series) * (abs(series) ** A)`。 19 | * `Ts_ArgMax(series, N)`: 返回过去 N 天内 `series` 达到最大值时的位置(相对于当前的天数)。例如,如果过去5天 `SignedPower` 的值分别是 `[10, -5, 12, 8, 9]`,则 `Ts_ArgMax` 返回 3(因为最大值 12 出现在 3 天前)。 20 | * `rank(series)`: 计算 `series` 中每个值在当日所有资产间的排序百分比(0到1之间)。值越大,排名越高。 21 | 22 | ## 项目结构 23 | 24 | ``` 25 | alpha-mining/ 26 | ├── generate_mock_data.py # 脚本:生成模拟金融数据 27 | ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#1 28 | ├── mock_data.csv # 生成的模拟数据文件 29 | ├── alpha1_results.csv # 计算得到的 Alpha#1 结果文件 30 | └── README.md # 本说明文档 31 | ``` 32 | 33 | ## 使用步骤 34 | 35 | ### 1. 环境准备 36 | 37 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 38 | 39 | ```bash 40 | pip install pandas numpy 41 | ``` 42 | 43 | ### 2. 生成模拟数据 44 | 45 | 运行 `generate_mock_data.py` 脚本以生成模拟的收盘价和回报率数据。此脚本将创建一个名为 `mock_data.csv` 的文件。 46 | 47 | ```bash 48 | python generate_mock_data.py 49 | ``` 50 | 51 | 该脚本默认生成5只资产100天的数据。 52 | 53 | ### 3. 计算 Alpha#1 因子 54 | 55 | 生成模拟数据后,运行 `alpha_calculator.py` 脚本来计算 Alpha#1 因子。该脚本会读取 `mock_data.csv`,执行公式中的计算,并将结果保存到 `alpha1_results.csv`。 56 | 57 | ```bash 58 | python alpha_calculator.py 59 | ``` 60 | 61 | 脚本执行完毕后,会在终端打印出结果文件的前5行、后5行以及 Alpha#1 值的描述性统计信息。 62 | 63 | ## Alpha#1 策略解读 64 | 65 | 该 Alpha 策略试图捕捉基于特定条件下的资产表现强度。 66 | 67 | 为了更好地理解计算过程,我们假设有以下模拟数据片段(来自 `mock_data.csv` 的对应部分,并结合 `alpha1_results.csv` 的数据): 68 | 69 | | date | asset_id | close | returns | 70 | |------------|----------|---------|------------| 71 | | 2025-01-20 | asset_1 | 102.4 | 0.0261 | 72 | | 2025-01-21 | asset_1 | 102.4 | 0.0 | 73 | | 2025-01-22 | asset_1 | 103.8 | 0.0137 | 74 | | 2025-01-23 | asset_1 | 101.8 | -0.0193 | 75 | | 2025-01-24 | asset_1 | 101.9 | 0.001 | 76 | | 2025-01-25 | asset_1 | 101.3 | -0.0059 | 77 | 78 | 并且,假设在 `2025-01-25`,`asset_1` 过去20天的回报率标准差(`stddev(returns, 20)`)计算结果为 `0.015` (这是一个示例值,实际计算会动态获取)。 79 | 80 | 下面是 Alpha#1 计算的详细步骤: 81 | 82 | 1. **条件价值 (`(returns < 0) ? stddev(returns, 20) : close`)**: 83 | 84 | * 如果资产的当日回报率为负(即下跌),则使用其过去20天的回报率标准差(波动率)作为基础值。 85 | * 如果资产的当日回报率为正或零(即上涨或持平),则使用其当日收盘价作为基础值。 86 | 这个步骤的含义是,对于下跌的股票,我们关注其波动性;对于上涨或持平的股票,我们关注其价格水平。 87 | 88 | *示例 (asset_1, 2025-01-25)*: 89 | `returns` 为 `-0.0059` (小于0),所以我们使用 `stddev(returns, 20)` 的值,即假设的 `0.015`。 90 | 91 | *示例 (asset_1, 2025-01-24)*: 92 | `returns` 为 `0.001` (大于0),所以我们使用 `close` 的值,即 `101.9`。 93 | 94 | 2. **符号幂 (`SignedPower(..., 2.)`)**: 95 | 96 | * 将上述条件价值进行平方处理,同时保留其原始符号。这会放大绝对值较大的值,无论是正还是负。 97 | 98 | *示例 (asset_1, 2025-01-25)*: 99 | 条件价值是 `0.015`。`SignedPower(0.015, 2.)` = `sign(0.015) * (abs(0.015) ** 2)` = `1 * (0.015 ** 2)` = `0.000225`。 100 | 101 | *示例 (asset_1, 2025-01-24)*: 102 | 条件价值是 `101.9`。`SignedPower(101.9, 2.)` = `sign(101.9) * (abs(101.9) ** 2)` = `1 * (101.9 ** 2)` = `10383.61`。 103 | 104 | 3. **时间序列最大值 (`Ts_ArgMax(..., 5)`)**: 105 | 106 | * 对于每只资产,观察其过去5天的 `SignedPower` 值,并找出这5天中的最大值。 107 | * 这个操作关注的是近期(5天内)表现最强的信号(经过 `SignedPower` 转换后的值)。 108 | 109 | *示例 (asset_1, 2025-01-25)*: 110 | 假设 `asset_1` 在 `2025-01-21` 到 `2025-01-25` 这5天的 `SignedPower` 值,结合上面计算的 `2025-01-24` 和 `2025-01-25` 的值,可能如下(其余为假设值): 111 | `[9000.0, 9500.0, 9800.0, 10383.61, 0.000225]` (分别对应 01-21 到 01-25 日) 112 | 如果这些就是过去5天的所有值,则 `Ts_ArgMax` 在 `2025-01-25` 这一天会返回 1(因为最大值 10383.61 出现在 1 天前)。 113 | 114 | 4. **排名 (`rank(...)`)**: 115 | 116 | * 在每个交易日,将所有资产的 `Ts_ArgMax` 值进行横向比较,并计算其百分位排名。排名越高,说明该资产在当天的信号值越突出。 117 | 118 | *示例 (2025-01-25)*: 119 | 假设 `asset_1` 当天通过上述步骤计算得到的 `Ts_ArgMax` 值为 `10383.61`。 120 | 再假设当天其他4只资产计算得到的 `Ts_ArgMax` 值分别为(仅为示意): 121 | asset_2: `12000.0` 122 | asset_3: `10000.0` 123 | asset_4: `10500.0` 124 | asset_5: `11000.0` 125 | 进行排名(从小到大排序后,`asset_1` 的 `10383.61` 位于 `10000.0` 和 `10500.0` 之间,但低于 `10500.0`,`11000.0`,`12000.0`)。 126 | 如果 `asset_1` 的 `rank` 值为 `0.8` (对应 `alpha1_results.csv` 中 `asset_1` 在 `2025-01-25` 的 `alpha1` 值为 `0.3`,因此 `rank = 0.3 + 0.5 = 0.8`)。 127 | 128 | (注意:实际 `rank` 的计算方式在 `alpha_calculator.py` 中使用的是 `rank(pct=True)`。为简化示例,此处直接使用由最终 alpha 值反推的 rank。) 129 | 130 | 5. **中心化 (`... - 0.5`)**: 131 | 132 | * 将排名值减去0.5,使得 Alpha 值的范围大致在 -0.5 到 0.5 之间。正值表示高于平均水平,负值表示低于平均水平。 133 | 134 | *示例 (asset_1, 2025-01-25)*: 135 | `rank` 值为 `0.8`。Alpha#1 = `0.8 - 0.5` = `0.3`。 136 | 这与 `alpha1_results.csv` 中 `asset_1` 在 `2025-01-25` 的 `alpha1` 值 `0.3` 相符。 137 | 138 | 总的来说,Alpha#1 倾向于选择那些在近期(5日内)表现出强劲\"条件价值\"(考虑了下跌时的波动率或上涨时的价格水平,并进行了平方放大)的资产。它是一个结合了动量(通过 `Ts_ArgMax`)和相对强度(通过 `rank`)的因子。 139 | 140 | 如需帮助或有建议,欢迎交流! 141 | -------------------------------------------------------------------------------- /alpha/archive/alpha3/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def rolling_correlation(x, y, window): 5 | """ 6 | Computes rolling correlation between two series over a specified window. 7 | """ 8 | correlation = x.rolling(window=window, min_periods=1).corr(y) 9 | # Handle infinite values and replace with 0 10 | correlation = correlation.replace([np.inf, -np.inf], 0) 11 | return correlation 12 | 13 | def calculate_alpha3(df, correlation_window=10): 14 | """ 15 | Calculates Alpha#3 based on the given formula. 16 | 17 | Alpha#3: (-1 * correlation(rank(open), rank(volume), 10)) 18 | 19 | Args: 20 | df: DataFrame containing date, asset_id, open, volume columns 21 | correlation_window: Window size for correlation calculation (default: 10) 22 | 23 | Returns: 24 | DataFrame with Alpha#3 values 25 | """ 26 | # Ensure data is sorted by date for rolling calculations 27 | df = df.sort_values(by=['asset_id', 'date']) 28 | 29 | # Check if required columns exist 30 | required_columns = ['date', 'asset_id', 'open', 'volume'] 31 | missing_columns = [col for col in required_columns if col not in df.columns] 32 | if missing_columns: 33 | raise ValueError(f"Missing required columns: {missing_columns}") 34 | 35 | # Calculate daily cross-sectional ranks 36 | # rank(open): rank of opening price across all assets on each day 37 | df['rank_open'] = df.groupby('date')['open'].rank(pct=True, method='average') 38 | 39 | # rank(volume): rank of volume across all assets on each day 40 | df['rank_volume'] = df.groupby('date')['volume'].rank(pct=True, method='average') 41 | 42 | # Calculate rolling correlation for each asset 43 | def calculate_correlation_for_group(group): 44 | correlation = rolling_correlation( 45 | group['rank_open'], 46 | group['rank_volume'], 47 | correlation_window 48 | ) 49 | return correlation 50 | 51 | df['correlation'] = df.groupby('asset_id', group_keys=False).apply( 52 | calculate_correlation_for_group 53 | ) 54 | 55 | # Final Alpha#3: -1 * correlation 56 | df['alpha3'] = -1 * df['correlation'] 57 | 58 | # Handle infinite and NaN values 59 | df['alpha3'] = df['alpha3'].replace([np.inf, -np.inf], 0) 60 | df['alpha3'] = df['alpha3'].fillna(0) 61 | 62 | # Round to 4 decimal places for better readability 63 | df['alpha3'] = df['alpha3'].round(4) 64 | 65 | return df[['date', 'asset_id', 'open', 'volume', 'alpha3']] 66 | 67 | if __name__ == "__main__": 68 | # Load mock data 69 | try: 70 | data_df = pd.read_csv("../../data/mock_data.csv", parse_dates=['date']) 71 | except FileNotFoundError: 72 | print("Error: ../../data/mock_data.csv not found. Please ensure the mock data file exists.") 73 | print("The file should contain columns: date, asset_id, open, volume") 74 | exit() 75 | 76 | # Check if required columns exist 77 | required_columns = ['date', 'asset_id', 'open', 'volume'] 78 | missing_columns = [col for col in required_columns if col not in data_df.columns] 79 | if missing_columns: 80 | print(f"Error: Missing required columns in mock_data.csv: {missing_columns}") 81 | print("Required columns: date, asset_id, open, volume") 82 | exit() 83 | 84 | # Calculate Alpha#3 85 | try: 86 | alpha_df = calculate_alpha3(data_df.copy()) 87 | 88 | # Save results 89 | alpha_df.to_csv("alpha3_results.csv", index=False) 90 | print("Alpha#3 calculated and results saved to alpha3_results.csv") 91 | print("\nFirst 5 rows of Alpha#3 results:") 92 | print(alpha_df.head()) 93 | print("\nLast 5 rows of Alpha#3 results:") 94 | print(alpha_df.tail()) 95 | print("\nDescriptive statistics of Alpha#3:") 96 | print(alpha_df['alpha3'].describe()) 97 | 98 | # Additional statistics 99 | print(f"\nNumber of non-zero Alpha#3 values: {(alpha_df['alpha3'] != 0).sum()}") 100 | print(f"Number of NaN Alpha#3 values: {alpha_df['alpha3'].isna().sum()}") 101 | 102 | # Correlation analysis 103 | print(f"\nCorrelation statistics:") 104 | print(f"Mean Alpha#3: {alpha_df['alpha3'].mean():.4f}") 105 | print(f"Std Alpha#3: {alpha_df['alpha3'].std():.4f}") 106 | print(f"Min Alpha#3: {alpha_df['alpha3'].min():.4f}") 107 | print(f"Max Alpha#3: {alpha_df['alpha3'].max():.4f}") 108 | 109 | # Check for extreme values 110 | extreme_values = alpha_df[(alpha_df['alpha3'] > 1) | (alpha_df['alpha3'] < -1)] 111 | if len(extreme_values) > 0: 112 | print(f"\nNumber of extreme values (|alpha3| > 1): {len(extreme_values)}") 113 | 114 | except Exception as e: 115 | print(f"Error calculating Alpha#3: {str(e)}") 116 | exit() -------------------------------------------------------------------------------- /alpha/archive/alpha8/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#8: 开盘价与回报率的短期相关性变化 2 | 3 | ## 描述 4 | 5 | Alpha#8 的计算公式为: 6 | 7 | ``` 8 | Alpha#8: (-1 * rank(((sum(open, 5) * sum(returns, 5)) - delay((sum(open, 5) * sum(returns, 5)), 10)))) 9 | ``` 10 | 11 | 这个 Alpha 策略旨在捕捉开盘价(open)和回报率(returns)在短期内的相关性变化。它通过计算过去5天的开盘价总和与回报率总和的乘积,并与10天前的相同乘积进行比较,最后对差值进行排名并取负值。这种设计可以捕捉到价格与回报率之间相关性的动态变化,从而产生潜在的交易信号。 12 | 13 | ## 项目结构 14 | 15 | ``` 16 | alpha-mining/ 17 | ├── data/ 18 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据(包含open, returns字段) 19 | │ └── mock_data.csv # 生成的模拟数据文件 20 | ├── alpha/alpha8/ 21 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#8 22 | │ ├── alpha8_results.csv # 计算得到的 Alpha#8 结果文件 23 | │ ├── README.md # 本说明文档 24 | │ └── cast.md # Alpha#8 策略总结 25 | ``` 26 | 27 | ## 使用步骤 28 | 29 | ### 1. 环境准备 30 | 31 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 32 | 33 | ```bash 34 | pip install pandas numpy 35 | ``` 36 | 37 | ### 2. 生成模拟数据 (如果需要) 38 | 39 | 本 Alpha 依赖于 `open` 和 `returns` 数据。`data/generate_mock_data.py` 脚本可以生成这些数据。如果 `data/mock_data.csv` 不存在或需要更新: 40 | 41 | ```bash 42 | cd data 43 | python generate_mock_data.py 44 | cd .. 45 | ``` 46 | 47 | 该脚本默认生成5只资产100天的数据。 48 | 49 | ### 3. 计算 Alpha#8 因子 50 | 51 | 进入 `alpha/alpha8` 目录并运行 `alpha_calculator.py` 脚本: 52 | 53 | ```bash 54 | cd alpha/alpha8 55 | python alpha_calculator.py 56 | ``` 57 | 58 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#8,并将结果保存到当前目录下的 `alpha8_results.csv`。同时会在终端打印部分结果和统计信息。 59 | 60 | ## Alpha#8 策略解读与计算示例 61 | 62 | Alpha#8 是一个**开盘价与回报率短期相关性变化因子**。它通过以下步骤捕捉价格与回报率之间的动态关系: 63 | 64 | 1. **短期累积(5天窗口)**: 65 | 66 | - 计算过去5天开盘价的总和 `sum(open, 5)` 67 | - 计算过去5天回报率的总和 `sum(returns, 5)` 68 | - 将两个总和相乘,得到短期相关性指标 69 | 2. **相关性变化(10天对比)**: 70 | 71 | - 计算当前的相关性指标与10天前的差值 72 | - 这个差值反映了短期相关性的变化程度 73 | 3. **信号生成**: 74 | 75 | - 对差值进行排名 `rank(...)` 76 | - 取排名的负值 `-1 * rank(...)` 77 | - 较大的负值表示相关性增强,较大的正值表示相关性减弱 78 | 79 | ### 实际数据示例 (asset_1 from alpha8_results.csv) 80 | 81 | 以下为 `asset_1` 在 `alpha8_results.csv` 中部分日期的计算结果: 82 | 83 | | date | asset_id | open | returns | sum_open_5 | sum_returns_5 | open_returns_product | delayed_product | product_diff | rank_diff | alpha8 | 84 | | ---------- | -------- | ------ | ------- | ---------- | ------------- | -------------------- | --------------- | ------------ | --------- | ------ | 85 | | 2025-01-11 | asset_1 | 99.58 | -0.0119 | 501.21 | -0.01 | -5.01 | NaN | NaN | NaN | NaN | 86 | | 2025-01-12 | asset_1 | 100.42 | -0.003 | 500.95 | -0.03 | -15.03 | NaN | NaN | NaN | NaN | 87 | | 2025-01-13 | asset_1 | 98.46 | -0.002 | 498.62 | -0.01 | -4.99 | NaN | NaN | NaN | NaN | 88 | | 2025-01-14 | asset_1 | 98.54 | 0.002 | 496.45 | -0.01 | -4.96 | NaN | NaN | NaN | NaN | 89 | | 2025-01-15 | asset_1 | 99.38 | -0.0232 | 496.38 | -0.04 | -19.86 | 20.07 | -39.93 | 0.4 | -0.4 | 90 | 91 | ### 计算步骤详解 92 | 93 | 以 `asset_1` 在 `2025-01-15` 的数据为例 (数据来源于 `alpha8_results.csv`): 94 | 95 | 1. **计算5天总和**: 96 | 97 | * `sum_open_5` = 496.38 (过去5天开盘价总和) 98 | * `sum_returns_5` = -0.04 (过去5天回报率总和) 99 | 2. **计算乘积**: 100 | 101 | * 当前乘积 (`open_returns_product`) = 496.38 * (-0.04) = -19.86 102 | * 10天前乘积 (`delayed_product`) = 20.07 (10个交易日前的 `open_returns_product` 值) 103 | 3. **计算差值**: 104 | 105 | * 差值 (`product_diff`) = -19.86 - 20.07 = -39.93 106 | 4. **排名并取负**: 107 | 108 | * 该差值在当日所有资产的 `product_diff` 值中的排名 (`rank_diff`) 为 0.4 (具体排名方法见 `alpha_calculator.py`,此处为示例) 109 | * `alpha8` = -1 * 0.4 = -0.4 110 | 111 | ### 策略逻辑与解读 112 | 113 | - **正向信号(alpha8 > 0)**: 114 | 115 | - 表示相关性变化较弱或为负 116 | - 可能暗示价格与回报率的关系不稳定,存在套利机会 117 | - **负向信号(alpha8 < 0)**: 118 | 119 | - 表示相关性变化较强或为正 120 | - 可能暗示价格与回报率的关系趋于稳定 121 | 122 | ## 数据需求 123 | 124 | - `date`: 交易日期 125 | - `asset_id`: 资产ID 126 | - `open`: 每日开盘价 127 | - `returns`: 每日回报率 128 | 129 | ## 输出格式 130 | 131 | 输出的 CSV 文件 (`alpha8_results.csv`) 包含以下列: 132 | 133 | - `date`: 交易日期 134 | - `asset_id`: 资产ID 135 | - `open`: 当日开盘价(原始数据) 136 | - `returns`: 当日回报率(原始数据) 137 | - `sum_open_5`: 5天开盘价总和(中间计算值) 138 | - `sum_returns_5`: 5天回报率总和(中间计算值) 139 | - `open_returns_product`: `sum_open_5` 和 `sum_returns_5` 的乘积(中间计算值) 140 | - `delayed_product`: 10天前的 `open_returns_product` 值(中间计算值) 141 | - `product_diff`: `open_returns_product` 和 `delayed_product` 的差值(中间计算值) 142 | - `rank_diff`: `product_diff` 在当日所有资产中的排名(中间计算值) 143 | - `alpha8`: 计算得到的 Alpha#8 值,保留两位小数 144 | 145 | ## 注意事项与风险提示 146 | 147 | - **数据窗口**: 148 | 149 | - 需要至少5天数据计算总和 150 | - 需要至少10天数据计算延迟差值 151 | - 窗口期不足时会产生 NaN 值 152 | - **精度控制**: 153 | 154 | - 所有中间计算结果(除排名外)和最终 Alpha 值均保留两位小数 155 | - 排名方法可能影响因子表现,`alpha_calculator.py` 中使用的是 `method='average'` 156 | - **市场环境**: 157 | 158 | - 价格与回报率的关系可能随市场环境变化 159 | - 建议结合其他因子使用 160 | - 需要进行充分的回测验证 161 | - **数据质量**: 162 | 163 | - 确保输入数据中 `open` 和 `returns` 的质量 164 | - 处理异常值和缺失值 165 | - 注意数据更新的及时性 166 | 167 | Alpha#8 是基于历史价格和回报率模式的统计策略,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 168 | 169 | 如需帮助或有建议,欢迎交流! 170 | -------------------------------------------------------------------------------- /alpha/archive/alpha6/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#6: (-1 * correlation(open, volume, 10)) 2 | 3 | ## 描述 4 | 5 | Alpha#6 的计算公式为:`(-1 * correlation(open, volume, 10))` 6 | 7 | 这个 Alpha 策略旨在捕捉开盘价(open)和成交量(volume)在过去10天内的负相关性。当开盘价和成交量的相关性为负,并且这种负相关性越强时,Alpha 的值就越大。这可能意味着当成交量放大时,开盘价有相反的走势(例如,成交量放大伴随开盘价下跌,或成交量萎缩伴随开盘价上涨),反之亦然。 8 | 9 | ## 项目结构 10 | 11 | ``` 12 | alpha-mining/ 13 | ├── data/ 14 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据(包含open, volume字段) 15 | │ └── mock_data.csv # 生成的模拟数据文件 16 | ├── alpha/alpha6/ 17 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#6 18 | │ ├── alpha6_results.csv # 计算得到的 Alpha#6 结果文件 19 | │ ├── README.md # 本说明文档 20 | │ └── cast.md # Alpha#6 策略总结 21 | ``` 22 | 23 | ## 使用步骤 24 | 25 | ### 1. 环境准备 26 | 27 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 28 | 29 | ```bash 30 | pip install pandas numpy 31 | ``` 32 | 33 | ### 2. 生成模拟数据 (如果需要) 34 | 35 | 本 Alpha 依赖于 `open` 和 `volume` 数据。`data/generate_mock_data.py` 脚本可以生成这些数据。如果 `data/mock_data.csv` 不存在或需要更新: 36 | 37 | ```bash 38 | cd data 39 | python generate_mock_data.py 40 | cd .. 41 | ``` 42 | 该脚本默认生成5只资产100天的数据。 43 | 44 | ### 3. 计算 Alpha#6 因子 45 | 46 | 进入 `alpha/alpha6` 目录并运行 `alpha_calculator.py` 脚本: 47 | 48 | ```bash 49 | cd alpha/alpha6 50 | python alpha_calculator.py 51 | ``` 52 | 53 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#6,并将结果保存到当前目录下的 `alpha6_results.csv`。同时会在终端打印部分结果和统计信息。 54 | 55 | ## Alpha#6 策略解读与计算示例 56 | 57 | Alpha#6 是一个**开盘价与成交量短期负相关性因子**。它通过计算过去10天开盘价与成交量的皮尔逊相关系数,并取其相反数,来寻找那些呈现"价量反向"模式的资产。 58 | 59 | ### 实际数据示例 (asset_1 from alpha6_results.csv) 60 | 61 | 以下为 `asset_1` 在 `alpha6_results.csv` 中部分日期的计算结果: 62 | 63 | | date | asset_id | open | volume | alpha6 | 64 | |------------|----------|--------|----------|--------| 65 | | 2025-01-01 | asset_1 | 100.30 | 690896 | NaN | 66 | | ... | ... | ... | ... | ... | 67 | | 2025-01-09 | asset_1 | 100.71 | 811805 | NaN | 68 | | 2025-01-10 | asset_1 | 99.45 | 1548483 | 0.03 | 69 | | 2025-01-11 | asset_1 | 99.58 | 539969 | -0.07 | 70 | | 2025-01-12 | asset_1 | 100.42 | 1035398 | -0.07 | 71 | | 2025-01-13 | asset_1 | 98.46 | 1214585 | -0.10 | 72 | | 2025-01-14 | asset_1 | 98.54 | 1277920 | -0.08 | 73 | | 2025-01-15 | asset_1 | 99.38 | 1409656 | -0.08 | 74 | | 2025-01-16 | asset_1 | 95.90 | 791336 | -0.19 | 75 | | 2025-01-17 | asset_1 | 97.88 | 763238 | 0.04 | 76 | | 2025-01-18 | asset_1 | 97.85 | 1487560 | -0.03 | 77 | | 2025-01-19 | asset_1 | 98.31 | 2061421 | -0.09 | 78 | | 2025-01-20 | asset_1 | 97.93 | 1698241 | 0.02 | 79 | 80 | 81 | ### 计算步骤详解 (以 asset_1 在 2025-01-10 为例) 82 | 83 | 假设我们关注 `asset_1` 在 `2025-01-10` 的 Alpha 值计算。我们需要 `asset_1` 从 `2025-01-01` 到 `2025-01-10` (共10天) 的 `open` 和 `volume` 数据。 84 | 85 | 1. **收集数据**: 86 | * `open` 序列 (10天): `[100.30, 100.53, 100.88, 101.01, 98.99, 102.35, 100.68, 100.79, 100.71, 99.45]` 87 | * `volume` 序列 (10天): `[690896, 1236310, 794092, 1279416, 1327947, 1421350, 2713351, 594738, 811805, 1548483]` 88 | 89 | 2. **计算相关性**: 90 | * 使用上述两个10天长度的序列计算皮尔逊相关系数。 91 | * 例如,`correlation([100.30, ..., 99.45], [690896, ..., 1548483])` 得到的值约为 `-0.03` (具体数值取决于计算精度,这里仅为示例,实际脚本中 pandas 会精确计算)。 92 | 93 | 3. **乘以 -1**: 94 | * `alpha6 = -1 * correlation_value` 95 | * `alpha6 = -1 * (-0.03) = 0.03` 96 | 97 | 4. **结果**: 98 | * `asset_1` 在 `2025-01-10` 的 `alpha6` 值为 `0.03`。 99 | 100 | ### 策略逻辑与解读 101 | 102 | * **高 Alpha 值 (正值)**: 103 | * 例如 `asset_1` 在 `2025-01-10` 的 Alpha 值为 `0.03`。这表示在过去10天,该资产的开盘价和成交量呈现轻微的负相关性 (`correlation ≈ -0.03`)。当这个 Alpha 值更大时(例如 `0.5`),意味着负相关性更强。 104 | * 场景:可能是成交量上升时开盘价下跌(放量下跌的开盘),或者成交量萎缩时开盘价上涨(缩量上涨的开盘)。这种模式可能被市场解读为特定信号(如恐慌抛售的开始,或惜售情绪)。 105 | 106 | * **低 Alpha 值 (负值)**: 107 | * 例如 `asset_1` 在 `2025-01-16` 的 Alpha 值为 `-0.19`。这表示在过去10天,开盘价和成交量呈现正相关性 (`correlation ≈ 0.19`)。 108 | * 场景:可能是成交量上升时开盘价也上涨(价涨量增的开盘),或者成交量下降时开盘价也下跌(价跌量缩的开盘)。 109 | 110 | * **接近0的Alpha值**: 111 | * 表明开盘价和成交量在过去10天内的线性关系不强,或接近不相关。 112 | 113 | ### 实际结果统计 (基于 alpha6_results.csv) 114 | 115 | 从 `alpha_calculator.py` 脚本运行得到的 `alpha6_results.csv` (共500行,5个资产,100天数据): 116 | * **NaN 值数量**: 45 (每个资产的前9天无法计算10日相关性,5 assets * 9 days/asset = 45 NaN) 117 | * **Alpha6 统计 (排除NaN后共455个值)**: 118 | * 均值 (mean): ~0.003 119 | * 标准差 (std): ~0.312 120 | * 最小值 (min): -0.76 121 | * 25% 分位数: -0.22 122 | * 中位数 (50%): 0.01 123 | * 75% 分位数: 0.24 124 | * 最大值 (max): 0.80 125 | 126 | 这些统计数据表明,模拟数据中 Alpha#6 的值分布在 -0.76 到 0.80 之间,均值接近0,表明模拟数据中价量正负相关的情况大致均衡。 127 | 128 | ## 数据需求 129 | * 每个交易日的 `date` 130 | * 每个资产的 `asset_id` 131 | * 每个交易日的 `open` (开盘价) 132 | * 每个交易日的 `volume` (成交量) 133 | 134 | ## 输出格式 135 | 输出的 CSV 文件将包含以下列: 136 | * `date`: 交易日期 137 | * `asset_id`: 资产ID 138 | * `open`: 当日开盘价 (原始数据) 139 | * `volume`: 当日成交量 (原始数据) 140 | * `alpha6`: 计算得到的 Alpha#6 值,保留两位小数。如果因数据不足无法计算相关性,则为 NaN。 141 | 142 | ## 注意事项与风险提示 143 | * **数据质量**: 确保输入数据中 `open` 和 `volume` 没有过多缺失值,特别是在计算相关性的窗口期内,否则会导致大量 NaN 输出。 144 | * **窗口选择**: 相关性的计算对窗口大小(此处为10天)敏感。不同的窗口期可能会捕捉到不同周期的价量关系。 145 | * **线性关系**: 皮尔逊相关系数主要衡量线性关系,可能无法捕捉复杂的非线性价量模式。 146 | * **市场环境**: 价量关系可能随市场整体牛熊、特定行业周期或宏观事件而变化,历史统计关系不代表未来。 147 | * **异常值**: 极端的开盘价或成交量(如因特殊事件导致)可能会扭曲相关性计算,需要考虑异常值处理。 148 | * **多重共线性**: 在多因子模型中,需注意此Alpha与其他价量因子的潜在共线性。 149 | * Alpha#6 是基于历史价格和成交量模式的统计策略,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 150 | 151 | 如需帮助或有建议,欢迎交流! -------------------------------------------------------------------------------- /alpha/archive/alpha6/alpha_calculator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | # 定义Alpha函数 5 | def calculate_alpha6(df, window=10): 6 | """ 7 | Calculate Alpha#6: (-1 * correlation(open, volume, 10)) 8 | 9 | Args: 10 | df (pd.DataFrame): DataFrame with 'asset_id', 'date', 'open', 'volume'. 11 | It's assumed that the DataFrame is sorted by 'asset_id' and 'date'. 12 | window (int): Rolling window size for correlation calculation. 13 | 14 | Returns: 15 | pd.DataFrame: DataFrame with 'date', 'asset_id', 'open', 'volume', 'alpha6'. 16 | """ 17 | 18 | # Ensure required columns are present 19 | required_cols = ['open', 'volume'] 20 | for col in required_cols: 21 | if col not in df.columns: 22 | raise ValueError(f"Required column '{col}' not found in DataFrame.") 23 | 24 | # Calculate rolling correlation between 'open' and 'volume' for each asset 25 | # The min_periods ensures that we have enough data points to calculate correlation 26 | df['correlation_open_volume'] = df.groupby('asset_id', group_keys=False)[['open', 'volume']].apply( 27 | lambda x: x['open'].rolling(window=window, min_periods=window).corr(x['volume']) 28 | ) 29 | 30 | # Calculate alpha6 31 | df['alpha6'] = -1 * df['correlation_open_volume'] 32 | 33 | # Round alpha6 to two decimal places 34 | df['alpha6'] = df['alpha6'].round(2) 35 | 36 | # Select and return relevant columns, including raw data 37 | result_df = df[['date', 'asset_id', 'open', 'volume', 'alpha6']].copy() 38 | 39 | return result_df 40 | 41 | if __name__ == "__main__": 42 | # --- Configuration --- 43 | DATA_FILE_PATH = "../../data/mock_data.csv" # Path to the input data 44 | OUTPUT_FILE_PATH = "alpha6_results.csv" # Path for the output CSV 45 | CORRELATION_WINDOW = 10 46 | NUM_ASSETS_TO_DISPLAY = 2 # Number of assets to show in head() and tail() 47 | ROWS_PER_ASSET_DISPLAY = 5 # Number of rows per asset to show 48 | 49 | # --- Load Data --- 50 | try: 51 | print(f"Loading data from {DATA_FILE_PATH}...") 52 | input_df = pd.read_csv(DATA_FILE_PATH) 53 | print("Data loaded successfully.") 54 | except FileNotFoundError: 55 | print(f"Error: Data file not found at {DATA_FILE_PATH}. Please ensure the file exists.") 56 | exit(1) 57 | except Exception as e: 58 | print(f"Error loading data: {e}") 59 | exit(1) 60 | 61 | # --- Data Preprocessing (ensure correct types and sort) --- 62 | try: 63 | input_df['date'] = pd.to_datetime(input_df['date']) 64 | # Ensure data is sorted correctly for rolling calculations 65 | input_df = input_df.sort_values(by=['asset_id', 'date']).reset_index(drop=True) 66 | print("Data preprocessing (date conversion and sorting) complete.") 67 | except Exception as e: 68 | print(f"Error during data preprocessing: {e}") 69 | exit(1) 70 | 71 | # --- Calculate Alpha --- 72 | try: 73 | print(f"Calculating Alpha#6 with a window of {CORRELATION_WINDOW} days...") 74 | alpha_df = calculate_alpha6(input_df.copy(), window=CORRELATION_WINDOW) # Use .copy() to avoid SettingWithCopyWarning 75 | print("Alpha#6 calculation complete.") 76 | except ValueError as ve: 77 | print(f"Error during Alpha calculation: {ve}") 78 | exit(1) 79 | except Exception as e: 80 | print(f"An unexpected error occurred during Alpha calculation: {e}") 81 | exit(1) 82 | 83 | # --- Save Results --- 84 | try: 85 | alpha_df.to_csv(OUTPUT_FILE_PATH, index=False) 86 | print(f"Alpha#6 results saved to {OUTPUT_FILE_PATH}") 87 | except Exception as e: 88 | print(f"Error saving results to CSV: {e}") 89 | exit(1) 90 | 91 | # --- Display Sample Results --- 92 | print("\n--- Sample of Alpha#6 Results ---") 93 | if not alpha_df.empty: 94 | # Display head and tail for a couple of assets to check NaN and calculations 95 | asset_ids = alpha_df['asset_id'].unique() 96 | if len(asset_ids) >= NUM_ASSETS_TO_DISPLAY: 97 | selected_assets = asset_ids[:NUM_ASSETS_TO_DISPLAY] 98 | else: 99 | selected_assets = asset_ids 100 | 101 | for i, asset_id in enumerate(selected_assets): 102 | asset_data = alpha_df[alpha_df['asset_id'] == asset_id] 103 | print(f"\nAsset ID: {asset_id}") 104 | print(f"First {ROWS_PER_ASSET_DISPLAY} rows:") 105 | print(asset_data.head(ROWS_PER_ASSET_DISPLAY)) 106 | if len(asset_data) > ROWS_PER_ASSET_DISPLAY: 107 | print(f"\nLast {ROWS_PER_ASSET_DISPLAY} rows for {asset_id}:") 108 | print(asset_data.tail(ROWS_PER_ASSET_DISPLAY)) 109 | if i < len(selected_assets) - 1: 110 | print("-" * 30) 111 | 112 | # Show general info 113 | print("\n--- General Information ---") 114 | print(f"Total rows in result: {len(alpha_df)}") 115 | print(f"Number of unique assets: {alpha_df['asset_id'].nunique()}") 116 | nan_alpha_counts = alpha_df['alpha6'].isna().sum() 117 | print(f"Number of NaN values in alpha6 column: {nan_alpha_counts} (expected due to initial window period)") 118 | if len(alpha_df) > 0: 119 | print("\nAlpha6 column statistics (excluding NaNs):") 120 | print(alpha_df['alpha6'].dropna().describe()) 121 | 122 | else: 123 | print("Resulting DataFrame is empty.") 124 | 125 | print("\nScript execution finished.") -------------------------------------------------------------------------------- /alpha/alpha31/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#31: 多因子组合策略 2 | 3 | ## 描述 4 | 5 | Alpha#31 的计算公式为: 6 | 7 | ``` 8 | Alpha#31: ((rank(rank(rank(decay_linear((-1 * rank(rank(delta(close, 10)))), 10)))) + rank((-1 * delta(close, 3)))) + sign(scale(correlation(adv20, low, 12)))) 9 | ``` 10 | 11 | 这个 Alpha 策略是一个多因子组合模型,结合了市场价格的趋势、短期反转以及量价关系特征。它由三个主要部分构成: 12 | 13 | 1. **部分 A**: `rank(rank(rank(decay_linear((-1 * rank(rank(delta(close, 10)))), 10))))` 14 | 15 | * 计算收盘价在过去10天的变化 (`delta(close, 10)`)。 16 | * 对这个变化值进行两次截面排名 (`rank(rank(delta(close, 10)))`)。 17 | * 取其负值 (`-1 * ...`)。 18 | * 对上述结果应用10天的衰减线性加权 (`decay_linear(..., 10)`)。 19 | * 最后再进行三次截面排名。 20 | * 这个部分旨在捕捉价格动量的持续性和相对强度,经过多次排名和衰减加权平滑处理。 21 | 2. **部分 B**: `rank((-1 * delta(close, 3)))` 22 | 23 | * 计算收盘价在过去3天的变化 (`delta(close, 3)`)。 24 | * 取其负值,表示短期价格变化的反向。 25 | * 对该反向变化值进行截面排名。 26 | * 这个部分旨在捕捉短期价格反转的信号。 27 | 3. **部分 C**: `sign(scale(correlation(adv20, low, 12)))` 28 | 29 | * 计算20日平均成交量 (`adv20`) 和每日最低价 (`low`) 在过去12天内的时序相关性 (`correlation(adv20, low, 12)`)。 30 | * 对计算出的相关性系数进行截面标准化 (`scale(...)`)。 31 | * 取标准化后相关性系数的符号 (`sign(...)`)。 32 | * 这个部分旨在捕捉成交量与价格之间的关系方向。例如,价跌量增(负相关)或价跌量缩(正相关)等模式。 33 | 34 | 最终的 Alpha#31 值为这三个部分的总和。 35 | 36 | ## 项目结构 37 | 38 | ``` 39 | alpha-mining/ 40 | ├── data/ 41 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (确保包含 close, adv20, low 字段) 42 | │ └── mock_data.csv # 生成的模拟数据文件 43 | ├── alpha/alpha31/ 44 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#31 45 | │ ├── alpha31_results.csv # 计算得到的 Alpha#31 结果文件 46 | │ ├── README.md # 本说明文档 47 | │ └── cast.md # Alpha#31 策略简介 48 | ``` 49 | 50 | ## 使用步骤 51 | 52 | ### 1. 环境准备 53 | 54 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 55 | 56 | ```bash 57 | pip install pandas numpy scipy 58 | # scipy 可能用于 decay_linear 的实现,如果 pandas 内置函数不足够 59 | ``` 60 | 61 | ### 2. 检查模拟数据 62 | 63 | 本 Alpha 依赖于 `close`, `adv20` (假设为20日平均成交量), 和 `low` 数据。请确保 `data/mock_data.csv` 文件存在,并且包含了 `date`, `asset_id`, `close`, `adv20`, `low` 列。如果文件不存在或数据不完整,请运行或修改 `data/generate_mock_data.py` 脚本。 64 | 65 | ```bash 66 | # 检查或生成数据 (如果需要) 67 | cd ../../data # 假设当前在 alpha/alpha31 目录 68 | python generate_mock_data.py # 假设此脚本能生成所需字段 69 | cd ../alpha/alpha31 70 | ``` 71 | 72 | ### 3. 计算 Alpha#31 因子 73 | 74 | 进入 `alpha/alpha31` 目录并运行 `alpha_calculator.py` 脚本: 75 | 76 | ```bash 77 | python alpha_calculator.py 78 | ``` 79 | 80 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#31,并将结果保存到当前目录下的 `alpha31_results.csv`。 81 | 82 | ## Alpha#31 策略解读与计算示例 83 | 84 | 由于公式较为复杂,此处提供一个基于实际输出 `alpha31_results.csv` 的概念性拆解。 85 | 我们将以 `asset_1` 在日期 `2025-01-26` 的数据为例。这是 `part_C` 开始对 `alpha31` 产生非零贡献的日期。 86 | 87 | **背景数据 (源自 `alpha31_results.csv` for `asset_1` on `2025-01-26`):** 88 | - `adv20`: 1359053.75 (假设由脚本根据 `volume` 计算得出,或从原始数据读取) 89 | - `part_A`: 0.80 90 | - `part_B`: 0.80 91 | - `part_C`: -1.00 92 | 93 | **计算 Alpha#31:** 94 | `Alpha#31 = part_A + part_B + part_C` 95 | `Alpha#31 = 0.80 + 0.80 + (-1.00) = 0.60` 96 | 97 | 此值与 `alpha31_results.csv` 中 `asset_1` 在 `2025-01-26` 的 `alpha31` 列的值 `0.60` 相符。 98 | 各部分 (`part_A`, `part_B`, `part_C`) 的详细计算步骤涉及多次排名、差分、衰减加权、相关性、标准化和符号提取,具体可参考 `alpha_calculator.py` 脚本中的实现。 99 | 100 | ## 数据需求 101 | 102 | - `date`: 交易日期 (datetime) 103 | - `asset_id`: 资产ID (string/object) 104 | - `close`: 每日收盘价 (float) 105 | - `low`: 每日最低价 (float) 106 | - `adv20`: 过去20日平均成交量 (float) - *假设 `adv20` 是已经预计算好或可以直接从数据源获取的字段。如果不是,`alpha_calculator.py` 中可能需要先计算它 (例如,基于 `volume` 列)。* 107 | - (脚本还会包含 `open`, `high`, `volume`, `vwap`, `returns` 等在 `mock_data.csv` 中的其他列,以保持数据完整性) 108 | 109 | ## 输出格式 110 | 111 | 输出的 CSV 文件 (`alpha31_results.csv`) 将包含以下列(除了原始数据列),所有数值型 alpha 相关列均保留两位小数: 112 | 113 | - `date`: 交易日期 114 | - `asset_id`: 资产ID 115 | - `open`, `high`, `low`, `close`, `volume`, `vwap`, `returns`: 原始数据中的对应列 116 | - `adv20`: 20日平均成交量 (如果从 `volume` 计算得出,则会包含此列;如果是原始输入,则保留原始输入) 117 | - `part_A`: Alpha#31 公式中第一部分的最终计算结果 (经过多次排名和衰减加权) 118 | - `part_B`: Alpha#31 公式中第二部分的最终计算结果 (短期反转信号) 119 | - `part_C`: Alpha#31 公式中第三部分的最终计算结果 (量价关系符号) 120 | - `alpha31`: 最终计算的 Alpha#31 值。 121 | 122 | ## 注意事项与风险提示 123 | 124 | - **数据窗口与NaN值** (基于 `alpha31_results.csv` 观察): 125 | - **`adv20`**: 如果基于 `volume` 列计算 (默认20日窗口,`min_periods=15`),每个资产的前14个交易日其值为NaN。在示例数据中,`adv20` 从第15个交易日 (`2025-01-15`) 开始有值。 126 | - **`part_A`**: (`delta(close,10)`, `decay_linear(...,10)`) 每个资产的前19个交易日其值为NaN。在示例数据中,`part_A` 从第20个交易日 (`2025-01-20`) 开始有值。 127 | - **`part_B`**: (`delta(close,3)`) 每个资产的前3个交易日其值为NaN。在示例数据中,`part_B` 从第4个交易日 (`2025-01-04`) 开始有值。 128 | - **`part_C`**: (`correlation(adv20,low,12)`) 依赖于 `adv20`。若 `adv20` 有14个NaN,加上12日相关性窗口(需要12个 `adv20` 的值,即 `adv20` 的第 `14+11=25` 个非NaN值之后),`corr_adv20_low_12` 会有约25个NaN。`cs_scale` 在其输入序列没有足够多非NaN值时返回0,因此 `part_C` (即 `sign(scale(...))`) 在早期可能为 `0.0`。在示例数据中,`part_C` 从第26个交易日 (`2025-01-26`) 开始出现非零值。 129 | - **`alpha31`**: `alpha31 = part_A + part_B + part_C`。其第一个非NaN值取决于 `part_A` (最早出现在第20天)。在第20至25天,`alpha31` 的计算中 `part_C` 的贡献为0。从第26天开始,`part_C` 开始贡献非零值。因此,每个资产时间序列的前19个交易日 `alpha31` 值为NaN。 130 | - **排名方法**:`pandas` 的 `rank(method='average', pct=True)` 通常用于截面排名,结果是百分比形式。 131 | - **衰减线性加权 (`decay_linear`)**: 具体实现方式会影响结果。通常是指对最近的数据赋予更高的权重,权重随时间线性递减。可以使用 `numpy.average` 配合自定义权重数组,或寻找现有的金融库函数。 132 | - **标准化 (`scale`)**: 通常指减去均值后除以标准差。`scale(x)` 一般表示 `(x - mean(x)) / std(x)`,按截面计算。 133 | - **相关性计算**: `pandas` 的 `rolling().corr()`。注意窗口期内数据不足或标准差为零的情况。 134 | - **`adv20`的来源**: 需要明确 `adv20` 是直接提供还是需要基于原始 `volume` 计算。如果是后者,其计算本身也会引入窗口期(通常是20天)。 135 | - **小数位数**: 最终的 Alpha#31 值和所有中间计算的 Alpha 相关列均按要求保留两位小数。 136 | - **因子组合的复杂性**: 多因子组合可能导致模型解释性下降,且各部分之间的相互作用可能复杂。 137 | - **市场适用性**: 此复杂因子在不同市场环境或资产类别上表现可能迥异。务必进行充分的回测和验证。 138 | - **数据质量**: 输入数据的准确性和完整性至关重要。 139 | 140 | Alpha#31 是一个基于多种信号的复杂因子,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 141 | -------------------------------------------------------------------------------- /alpha/archive/alpha28/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#28: 成交量最低价相关性与价格中枢偏离的标准化 2 | 3 | 本项目实现了 Alpha#28 因子的计算逻辑。 4 | 5 | ## 1. Alpha#28 公式 6 | 7 | Alpha#28 的计算公式如下: 8 | 9 | ``` 10 | scale(((correlation(adv20, low, 5) + ((high + low) / 2)) - close)) 11 | ``` 12 | 13 | **公式各项说明**: 14 | 15 | * `adv20`: 资产过去20日的平均成交量。 16 | * `low`: 资产的日最低价。 17 | * `high`: 资产的日最高价。 18 | * `close`: 资产的日收盘价。 19 | * `correlation(x, y, N)`: 计算序列 `x` 和 `y` 在过去 `N` 天窗口内的皮尔逊相关系数。 20 | * `scale(x)`: 对序列 `x` 进行横截面标准化处理,使其均值为0,标准差为1。 21 | 22 | ## 2. 核心逻辑 23 | 24 | 计算 Alpha#28 的主要步骤如下: 25 | 26 | 1. **计算20日平均成交量 (`adv20`)**: 27 | * 对于每只资产,计算其过去20个交易日的平均成交量。 28 | 2. **计算中间价格 (`mid_price`)**: 29 | * 对于每只资产,计算当日的最高价和最低价的平均值:`(high + low) / 2`。 30 | 3. **计算相关系数 (`correlation`)**: 31 | * 对于每只资产,计算其过去5日的 `adv20` 序列与 `low` 序列之间的相关系数。 32 | 4. **组合与差值**: 33 | * 将步骤3中得到的相关系数与步骤2中得到的中间价格相加。 34 | * 从上述结果中减去当日的收盘价 `close`。 35 | 5. **横截面标准化 (`scale`)**: 36 | * 对步骤4中得到的结果,在每个交易日的所有资产间进行标准化处理,得到最终的 Alpha#28 值。 37 | 38 | ## 3. 策略解读 39 | 40 | Alpha#28 试图捕捉市场中成交量、价格结构与收盘价之间的复杂关系。 41 | 42 | * **成交量与最低价的相关性 (`correlation(adv20, low, 5)`)**: 43 | * 正相关可能表示在成交量放大(或缩小)的同时,最低价也倾向于上升(或下降),这可能反映了市场对价格底部的确认或突破的强度。 44 | * 负相关则可能表示成交量变化与最低价变化方向相反,例如放量下跌或缩量上涨的底部试探。 45 | * **价格中枢与收盘价的偏离 (`((high + low) / 2) - close`)**: 46 | * 这部分衡量了收盘价相对于当日价格波动中枢的位置。 47 | * 如果收盘价远低于中枢价,可能表明当日存在一定的抛压或下跌动能。 48 | * 如果收盘价远高于中枢价,可能表明当日购买意愿较强或上涨动能。 49 | * **组合信号的意义**: 50 | * 因子将上述两部分信号(成交量-最低价相关性 和 价格中枢-收盘价偏离)结合起来。 51 | * 例如,一个较高的正相关系数(价量同向)加上一个较大的正偏离(收盘价高于中枢),可能会被因子视为一个强烈的看多或看空信号(具体方向需结合标准化后的符号判断)。 52 | * **标准化的作用 (`scale`)**: 53 | * 最后的 `scale` 操作将每日所有资产的因子值进行标准化,使其具有可比性,剔除了市场的整体波动影响,更关注个股的相对强弱。因子值为正,通常表示该股票在特定模式下表现相对较强;为负则表示相对较弱。 54 | 55 | 因子倾向于寻找那些在成交量与最低价表现出特定相关性,并且其日内价格行为(中间价与收盘价的关系)也符合一定模式的资产。 56 | 57 | ## 4. 项目结构 58 | 59 | ```text 60 | alpha-mining/ 61 | ├── data/ 62 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 63 | │ └── mock_data.csv # 生成的模拟数据文件 64 | ├── alpha/alpha28/ 65 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#28 66 | │ ├── alpha28_results.csv # 计算得到的 Alpha#28 结果文件 67 | │ ├── README.md # 本说明文档 68 | │ └── cast.md # Alpha#28 策略总结与转换说明 69 | ``` 70 | 71 | ## 5. 使用步骤 72 | 73 | ### 5.1. 环境准备 74 | 75 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。 76 | 77 | ```bash 78 | pip install pandas numpy 79 | ``` 80 | 81 | ### 5.2. 数据准备 82 | 83 | 运行 `alpha_calculator.py` 脚本需要 `mock_data.csv` 文件位于项目根目录下的 `data/` 目录中。该 CSV 文件必须至少包含以下列: 84 | 85 | * `date` (日期) 86 | * `asset_id` (资产ID) 87 | * `volume` (成交量) 88 | * `high` (最高价) 89 | * `low` (最低价) 90 | * `close` (收盘价) 91 | 92 | 如果数据文件不存在或需要更新,您可以运行 `data/generate_mock_data.py` (请确保该脚本会生成上述所有必需列)。 93 | 94 | ### 5.3. 计算 Alpha#28 因子 95 | 96 | 在 `alpha/alpha28/` 目录下,通过命令行运行 `alpha_calculator.py` 脚本: 97 | 98 | ```bash 99 | python alpha_calculator.py 100 | ``` 101 | 102 | 脚本将: 103 | 1. 读取 `../../data/mock_data.csv` 文件。 104 | 2. 计算 Alpha#28 因子。 105 | 3. 将结果(包括部分原始数据列和计算得到的 `alpha28` 列)保存到当前目录下的 `alpha28_results.csv` 文件中。 106 | 4. 在终端打印输出文件的前5行、后5行以及 `alpha28` 列的描述性统计信息,方便快速查阅。 107 | 108 | ## 6. Alpha#28 计算示例 (基于实际输出) 109 | 110 | ### 6.1. 数据快照 111 | 112 | 根据 `alpha28_results.csv` 的实际输出数据,我们选取 `asset_1` 在 `2025-01-05` 的数据作为示例: 113 | 114 | | date | asset_id | volume | high | low | close | alpha28 | 115 | |:-----------|:---------|:---------|:-------|:------|:------|:--------| 116 | | 2025-01-05 | asset_1 | 1327947 | 100.58 | 98.69 | 100.5 | -0.61 | 117 | 118 | *(注: `alpha28` 的值直接来自生成的结果文件。空值表示因计算窗口期不足等原因无法计算)* 119 | 120 | ### 6.2. 计算步骤详解 (以 asset_1, 2025-01-05 为例) 121 | 122 | 为计算 `asset_1` 在 `2025-01-05` 的 `alpha28` 值,`alpha_calculator.py` 脚本会执行以下操作: 123 | 124 | * **获取所需数据**:获取 `asset_1` 在 `2025-01-05` 及之前的 `volume`, `high`, `low`, `close` 数据。 125 | * **计算 `adv20`**: 计算 `asset_1` 截至 `2025-01-05` 的过去20日平均成交量。 126 | * **计算 `mid_price`**: `(100.58 + 98.69) / 2 = 99.635`。 127 | * **计算 `correlation(adv20, low, 5)`**: 计算 `asset_1` 截至 `2025-01-05` 的过去5日 `adv20` 序列与 `low` 序列的相关系数。 128 | * **计算组合与差值**: `correlation_value + mid_price - close_price`。 129 | * **横截面标准化 `scale`**: 将上述计算得到的未标准化值,与 `2025-01-05` 当日所有其他资产计算得到的未标准化值一起进行标准化(减去均值后除以标准差),得到最终的 `alpha28` 值为 `-0.61`。 130 | 131 | **对 `alpha28 = -0.61` 的解读**: 132 | 在 `2025-01-05` 这一天,`asset_1` 的 `alpha28` 值为 `-0.61`。负值表明,在综合考虑了其成交量与最低价的相关性、当日价格中枢以及收盘价之后,经过市场整体标准化比较,`asset_1` 当日的因子表现弱于市场平均水平。 133 | 134 | ## 7. 数据列说明 135 | 136 | ### 7.1. 输入数据 (`mock_data.csv`) 137 | 138 | * `date`: 交易日期 (例如 `YYYY-MM-DD` 格式)。 139 | * `asset_id`: 资产的唯一标识符 (例如 `asset_1`, `asset_2`)。 140 | * `volume`: 当日成交量 (数值型) - **核心计算列**。 141 | * `high`: 当日最高价 (数值型) - **核心计算列**。 142 | * `low`: 当日最低价 (数值型) - **核心计算列**。 143 | * `close`: 当日收盘价 (数值型) - **核心计算列**。 144 | * *(脚本会保留输入数据中的其他列如 `open`, `returns` 等到输出文件,以保持数据完整性,但它们不直接参与 Alpha#28 的核心计算)* 145 | 146 | ### 7.2. 输出数据 (`alpha28_results.csv`) 147 | 148 | 输出的 CSV 文件将包含原始数据中的所有列,并附加一列 `alpha28`: 149 | 150 | * `date`, `asset_id`, `volume`, `high`, `low`, `close` (及其他原始列) 151 | * `alpha28`: 计算得到的 Alpha#28 因子值 (浮点数,通常保留两位小数)。空值(NaN)表示因计算窗口期不足等原因无法计算。 152 | 153 | ## 8. 注意事项与风险提示 154 | 155 | * **数据窗口期**: 156 | * `adv20` 的计算使用了20日的滚动窗口 (脚本中 `min_periods=1` 允许在数据不足20天时也开始计算,但早期值可能不稳)。 157 | * `correlation` 函数的窗口期为5日。 158 | * 因此,首个完整且相对稳定的 `alpha28` 值大约在数据序列的第20个有效交易日之后才能获得(因为 `adv20` 需要稳定)。根据 `alpha28_results.csv` 的示例输出,第一个非空值出现在 `2025-01-05`,这表明脚本实现中对窗口期有灵活处理。 159 | * **`scale` 函数的稳健性**: 标准化是按每个交易日进行的。如果某日只有一个资产,或者当日所有资产计算出的待标准化值的标准差为零,`scale` 操作可能会导致结果为 NaN 或无穷大。实际交易策略中需要对这类极端情况进行额外处理。 160 | * **因子有效性**: Alpha#28 是一个基于历史价量数据统计构建的因子,其历史表现不代表未来收益。在实际应用前,建议进行充分的回测验证,并考虑与其他因子结合使用以分散风险。 161 | * **数据质量**: 输入数据的准确性和完整性对因子计算结果至关重要。 162 | 163 | --- 164 | 165 | 如需帮助或对本文档及代码有任何建议,欢迎随时交流! -------------------------------------------------------------------------------- /alpha/archive/alpha20/README.md: -------------------------------------------------------------------------------- 1 | # Alpha#20: 开盘价与昨日价格关键点位差异的综合排名 2 | 3 | ## 描述 4 | 5 | Alpha#20 的计算公式为: 6 | 7 | ``` 8 | Alpha#20: (((-1 * rank((open - delay(high, 1)))) * rank((open - delay(close, 1)))) * rank((open - delay(low, 1)))) 9 | ``` 10 | 11 | 这个 Alpha 策略通过比较当日开盘价 (`open`) 与昨日(`delay(..., 1)`)的最高价 (`high`)、收盘价 (`close`) 和最低价 (`low`) 的差异,并对这些差异进行排名和组合,来生成交易信号。策略包含三个主要部分: 12 | 13 | 1. **开盘价与昨日最高价的差异**: `(-1 * rank((open - delay(high, 1))))` 14 | * `open - delay(high, 1)`: 当日开盘价减去昨日最高价。如果开盘价比昨日最高价还高(向上跳空),则为正。 15 | * `rank(...)`: 对这个差异进行截面排名。 16 | * `-1 * rank(...)`: 对排名取负。这意味着,如果开盘价远高于昨日最高价(差异值大,排名高),则此部分贡献一个较大的负值。 17 | 18 | 2. **开盘价与昨日收盘价的差异**: `rank((open - delay(close, 1)))` 19 | * `open - delay(close, 1)`: 当日开盘价减去昨日收盘价,即隔夜跳空幅度。 20 | * `rank(...)`: 对这个差异进行截面排名。正值表示向上跳空,负值表示向下跳空。 21 | 22 | 3. **开盘价与昨日最低价的差异**: `rank((open - delay(low, 1)))` 23 | * `open - delay(low, 1)`: 当日开盘价减去昨日最低价。 24 | * `rank(...)`: 对这个差异进行截面排名。值越大表示开盘价相对昨日最低价越高。 25 | 26 | ## 项目结构 27 | 28 | ``` 29 | alpha-mining/ 30 | ├── data/ 31 | │ ├── generate_mock_data.py # 脚本:生成模拟金融数据 (需包含 open, high, low, close) 32 | │ └── mock_data.csv # 生成的模拟数据文件 33 | ├── alpha/alpha20/ 34 | │ ├── alpha_calculator.py # 脚本:根据公式计算 Alpha#20 35 | │ ├── alpha20_results.csv # 计算得到的 Alpha#20 结果文件 36 | │ ├── README.md # 本说明文档 37 | │ └── cast.md # Alpha#20 策略简介 38 | ``` 39 | 40 | ## 使用步骤 41 | 42 | ### 1. 环境准备 43 | 44 | 确保您的 Python 环境中安装了 `pandas` 和 `numpy` 库。如果未安装,可以通过 pip 安装: 45 | 46 | ```bash 47 | pip install pandas numpy 48 | ``` 49 | 50 | ### 2. 检查模拟数据 51 | 52 | 本 Alpha 依赖于 `open`, `high`, `low`, `close` 数据。请确保 `data/mock_data.csv` 文件存在,并且包含了这些列。 53 | 54 | ```bash 55 | cd ../../data # 假设当前在 alpha/alpha20 目录 56 | python generate_mock_data.py # 确保生成所需字段 57 | cd ../alpha/alpha20 58 | ``` 59 | 60 | ### 3. 计算 Alpha#20 因子 61 | 62 | 进入 `alpha/alpha20` 目录并运行 `alpha_calculator.py` 脚本: 63 | 64 | ```bash 65 | python alpha_calculator.py 66 | ``` 67 | 68 | 脚本将读取 `../../data/mock_data.csv`,计算 Alpha#20,并将结果保存到 `alpha20_results.csv`。 69 | 70 | ## Alpha#20 策略解读与计算步骤概述 71 | 72 | 1. **计算开盘价与昨日价格的差异**: 73 | * 对每个资产,计算 `diff_open_prev_high = open - delay(high, 1)` 74 | * 对每个资产,计算 `diff_open_prev_close = open - delay(close, 1)` 75 | * 对每个资产,计算 `diff_open_prev_low = open - delay(low, 1)` 76 | 77 | 2. **计算差异的截面排名**: 78 | * 对每个资产,计算 `rank_diff_oph = rank(diff_open_prev_high)` 79 | * 对每个资产,计算 `rank_diff_opc = rank(diff_open_prev_close)` 80 | * 对每个资产,计算 `rank_diff_opl = rank(diff_open_prev_low)` 81 | 82 | 3. **计算最终Alpha值**: 83 | * `Alpha#20 = (-1 * rank_diff_oph) * rank_diff_opc * rank_diff_opl` 84 | 85 | ## Alpha#20 策略解读与计算示例 86 | 87 | ### 数据快照 (asset_1, 2025-01-24) 88 | 89 | 根据 `alpha20_results.csv` 的实际数据,我们选取 `asset_1` 在 `2025-01-24` 的数据作为示例: 90 | 91 | | date | asset_id | open | prev_high | prev_close | prev_low | diff_oph | diff_opc | diff_opl | rank_oph | rank_opc | rank_opl | alpha20 | 92 | |------------|----------|-------|-----------|------------|----------|----------|----------|----------|----------|----------|----------|---------| 93 | | 2025-01-24 | asset_1 | 97.20 | 98.50 | 97.80 | 97.00 | -1.30 | -0.60 | 0.20 | 0.300 | 0.400 | 0.600 | -0.072 | 94 | 95 | ### 计算步骤详解 (asset_1, 2025-01-24): 96 | 97 | 1. **开盘价与昨日价格的差异**: 98 | * `diff_open_prev_high = 97.20 - 98.50 = -1.30` 99 | * `diff_open_prev_close = 97.20 - 97.80 = -0.60` 100 | * `diff_open_prev_low = 97.20 - 97.00 = 0.20` 101 | 102 | 2. **差异的截面排名**: 103 | * `rank_diff_oph = 0.300` (表示在当日所有资产中排在第30%分位) 104 | * `rank_diff_opc = 0.400` (表示在当日所有资产中排在第40%分位) 105 | * `rank_diff_opl = 0.600` (表示在当日所有资产中排在第60%分位) 106 | 107 | 3. **最终 Alpha#20 值**: 108 | * `alpha20 = (-1 * 0.300) * 0.400 * 0.600 = -0.072` 109 | 110 | **解读 (asset_1, 2025-01-24)**: 111 | 在 `2025-01-24` 这一天,`asset_1`: 112 | * 开盘价低于昨日最高价(`diff_oph = -1.30`) 113 | * 开盘价低于昨日收盘价(`diff_opc = -0.60`),表示向下跳空 114 | * 开盘价高于昨日最低价(`diff_opl = 0.20`) 115 | * 三个排名值分别为30%、40%和60%分位,相乘后得到一个较小的负Alpha值(-0.072) 116 | * 这个较小的负值表明该资产在当日的开盘价格模式相对不太显著 117 | 118 | ## 数据需求 119 | 120 | - `date`: 交易日期 (datetime) 121 | - `asset_id`: 资产ID (string/object) 122 | - `open`: 当日开盘价 (float) 123 | - `high`: 当日最高价 (float) (用于计算 `delay(high,1)`) 124 | - `low`: 当日最低价 (float) (用于计算 `delay(low,1)`) 125 | - `close`: 当日收盘价 (float) (用于计算 `delay(close,1)`) 126 | - (脚本可能包含 `volume`, `returns` 等其他列以保持数据完整性) 127 | 128 | ## 输出格式 129 | 130 | 输出的 CSV 文件 (`alpha20_results.csv`) 将包含以下列(除了原始数据列),所有数值型 alpha 相关列均保留一定小数位数,最终 Alpha#20 保留两位有效数字: 131 | 132 | - `date`: 交易日期 133 | - `asset_id`: 资产ID 134 | - `open`, `high`, `low`, `close`, `volume`, `returns`: 原始数据中的对应列(如果存在) 135 | - `prev_high`: 昨日最高价 (`delay(high, 1)`) 136 | - `prev_close`: 昨日收盘价 (`delay(close, 1)`) 137 | - `prev_low`: 昨日最低价 (`delay(low, 1)`) 138 | - `diff_open_prev_high`: `open - prev_high` 139 | - `diff_open_prev_close`: `open - prev_close` 140 | - `diff_open_prev_low`: `open - prev_low` 141 | - `rank_diff_oph`: `rank(diff_open_prev_high)` (截面百分比排名) 142 | - `rank_diff_opc`: `rank(diff_open_prev_close)` (截面百分比排名) 143 | - `rank_diff_opl`: `rank(diff_open_prev_low)` (截面百分比排名) 144 | - `alpha20`: 最终计算的 Alpha#20 值 145 | 146 | ## 注意事项与风险提示 147 | 148 | - **数据窗口期**: 149 | * 所有 `delay` 操作都是 `delay(..., 1)`,因此每个资产的第一天无法计算这些延迟值。 150 | * 每个资产数据序列的第1行其 `alpha20` 将为 NaN。 151 | - **排名方法**: `pandas` 的 `rank(pct=True)` 方法用于所有截面排名,这意味着结果是百分比形式的排名。 152 | - **乘法组合**: 由于 Alpha 值是三个排名(其中一个取负)的乘积,其值的范围和分布可能比较特殊,需要通过回测仔细分析其特性。 153 | - **小数位数**: 中间步骤建议保留足够精度,最终 Alpha#20 结果将按要求格式化为两位有效数字。 154 | - **市场跳空行为**: 此因子高度依赖开盘价和昨日价格的关系,对市场开盘跳空行为敏感。 155 | - **市场适用性**: 此因子表现可能因市场环境、资产类别而异。需进行充分回测验证。 156 | - **数据质量**: 输入数据的准确性和完整性至关重要,特别是开盘价和前一日的各项价格数据。 157 | - **极端情况处理**: 当市场出现剧烈波动或异常交易时,价格跳空幅度可能较大,可能导致因子值出现极值。 158 | 159 | Alpha#20 是一个基于开盘价相对位置的复合因子,不保证未来表现。建议与其他因子结合使用,并进行充分的回测验证。 --------------------------------------------------------------------------------