246 lines
8.4 KiB
Python
246 lines
8.4 KiB
Python
"""
|
||
资金流因子 - 使用Polars实现
|
||
包含主力资金流、散户资金流等相关因子计算
|
||
"""
|
||
|
||
import polars as pl
|
||
import numpy as np
|
||
from typing import Dict, List, Optional, Any
|
||
from operator_framework import StockWiseOperator, OperatorConfig
|
||
|
||
|
||
class MoneyFlowIntensityOperator(StockWiseOperator):
|
||
"""主力资金流强度算子"""
|
||
|
||
def __init__(self):
|
||
config = OperatorConfig(
|
||
name="money_flow_intensity",
|
||
description="主力资金流强度",
|
||
required_columns=['buy_lg_vol', 'buy_elg_vol', 'sell_lg_vol', 'sell_elg_vol', 'vol'],
|
||
output_columns=['flow_lg_elg_intensity'],
|
||
parameters={}
|
||
)
|
||
super().__init__(config)
|
||
|
||
def apply_stock(self, stock_df: pl.DataFrame, **kwargs) -> pl.DataFrame:
|
||
"""计算主力资金流强度"""
|
||
epsilon = 1e-8
|
||
|
||
# 计算大单+超大单净买入量
|
||
lg_elg_net_buy_vol = (
|
||
pl.col('buy_lg_vol') + pl.col('buy_elg_vol') -
|
||
pl.col('sell_lg_vol') - pl.col('sell_elg_vol')
|
||
)
|
||
|
||
# 计算资金流强度
|
||
flow_intensity = lg_elg_net_buy_vol / (pl.col('vol') + epsilon)
|
||
|
||
return stock_df.with_columns(flow_intensity.alias('flow_lg_elg_intensity'))
|
||
|
||
|
||
class FlowDivergenceRatioOperator(StockWiseOperator):
|
||
"""散户与主力背离度算子"""
|
||
|
||
def __init__(self):
|
||
config = OperatorConfig(
|
||
name="flow_divergence_ratio",
|
||
description="散户与主力背离度比率",
|
||
required_columns=['buy_sm_vol', 'sell_sm_vol', 'buy_lg_vol', 'buy_elg_vol',
|
||
'sell_lg_vol', 'sell_elg_vol'],
|
||
output_columns=['flow_divergence_ratio'],
|
||
parameters={}
|
||
)
|
||
super().__init__(config)
|
||
|
||
def apply_stock(self, stock_df: pl.DataFrame, **kwargs) -> pl.DataFrame:
|
||
"""计算散户与主力背离度比率"""
|
||
epsilon = 1e-8
|
||
|
||
# 计算小单净买入量
|
||
sm_net_buy_vol = pl.col('buy_sm_vol') - pl.col('sell_sm_vol')
|
||
|
||
# 计算大单+超大单净买入量
|
||
lg_elg_net_buy_vol = (
|
||
pl.col('buy_lg_vol') + pl.col('buy_elg_vol') -
|
||
pl.col('sell_lg_vol') - pl.col('sell_elg_vol')
|
||
)
|
||
|
||
# 计算背离度比率,处理分母为0的情况
|
||
divergence_ratio = sm_net_buy_vol / (
|
||
lg_elg_net_buy_vol + pl.when(lg_elg_net_buy_vol == 0).then(epsilon).otherwise(0) + epsilon
|
||
)
|
||
|
||
return stock_df.with_columns(divergence_ratio.alias('flow_divergence_ratio'))
|
||
|
||
|
||
class FlowStructureChangeOperator(StockWiseOperator):
|
||
"""资金流结构变动算子"""
|
||
|
||
def __init__(self):
|
||
config = OperatorConfig(
|
||
name="flow_structure_change",
|
||
description="资金流结构变动",
|
||
required_columns=['buy_sm_vol', 'buy_lg_vol', 'buy_elg_vol'],
|
||
output_columns=['flow_struct_buy_change'],
|
||
parameters={}
|
||
)
|
||
super().__init__(config)
|
||
|
||
def apply_stock(self, stock_df: pl.DataFrame, **kwargs) -> pl.DataFrame:
|
||
"""计算资金流结构变动"""
|
||
epsilon = 1e-8
|
||
|
||
# 计算总买入量
|
||
total_buy_vol = pl.col('buy_sm_vol') + pl.col('buy_lg_vol') + pl.col('buy_elg_vol')
|
||
|
||
# 计算大单+超大单买入占比
|
||
lg_elg_buy_prop = (pl.col('buy_lg_vol') + pl.col('buy_elg_vol')) / (total_buy_vol + epsilon)
|
||
|
||
# 计算1日变化
|
||
struct_change = lg_elg_buy_prop.diff()
|
||
|
||
return stock_df.with_columns(struct_change.alias('flow_struct_buy_change'))
|
||
|
||
|
||
class FlowAccelerationOperator(StockWiseOperator):
|
||
"""资金流加速度算子"""
|
||
|
||
def __init__(self):
|
||
config = OperatorConfig(
|
||
name="flow_acceleration",
|
||
description="资金流加速度",
|
||
required_columns=['buy_lg_vol', 'buy_elg_vol', 'sell_lg_vol', 'sell_elg_vol'],
|
||
output_columns=['flow_lg_elg_accel'],
|
||
parameters={}
|
||
)
|
||
super().__init__(config)
|
||
|
||
def apply_stock(self, stock_df: pl.DataFrame, **kwargs) -> pl.DataFrame:
|
||
"""计算资金流加速度"""
|
||
# 计算大单+超大单净买入量
|
||
lg_elg_net_buy_vol = (
|
||
pl.col('buy_lg_vol') + pl.col('buy_elg_vol') -
|
||
pl.col('sell_lg_vol') - pl.col('sell_elg_vol')
|
||
)
|
||
|
||
# 计算一阶变化
|
||
first_diff = lg_elg_net_buy_vol.diff()
|
||
|
||
# 计算二阶变化(加速度)
|
||
acceleration = first_diff.diff()
|
||
|
||
return stock_df.with_columns(acceleration.alias('flow_lg_elg_accel'))
|
||
|
||
|
||
class LargeFlowMomentumCorrelationOperator(StockWiseOperator):
|
||
"""大单资金流与价格动量相关性算子"""
|
||
|
||
def __init__(self, n: int = 20, m: int = 60):
|
||
config = OperatorConfig(
|
||
name=f"lg_flow_mom_corr_{n}_{m}",
|
||
description=f"{n}日大单资金流与{m}日价格动量相关性",
|
||
required_columns=['buy_lg_vol', 'buy_elg_vol', 'sell_lg_vol', 'sell_elg_vol',
|
||
'close', 'vol'],
|
||
output_columns=[f'lg_flow_mom_corr_{n}_{m}'],
|
||
parameters={'n': n, 'm': m}
|
||
)
|
||
super().__init__(config)
|
||
self.n = n
|
||
self.m = m
|
||
|
||
def apply_stock(self, stock_df: pl.DataFrame, **kwargs) -> pl.DataFrame:
|
||
"""计算大单资金流与价格动量相关性"""
|
||
# 计算大单净额
|
||
net_lg_flow_val = (
|
||
(pl.col('buy_lg_vol') + pl.col('buy_elg_vol') -
|
||
pl.col('sell_lg_vol') - pl.col('sell_elg_vol')) * pl.col('close')
|
||
)
|
||
|
||
# 计算滚动净大单流
|
||
rolling_net_lg_flow = net_lg_flow_val.rolling_sum(window=self.n)
|
||
|
||
# 计算价格动量
|
||
price_mom = pl.col('close').pct_change(self.n)
|
||
|
||
# 计算相关性
|
||
# Polars的rolling_corr需要两个表达式
|
||
correlation = rolling_net_lg_flow.rolling_corr(price_mom, window=self.m)
|
||
|
||
return stock_df.with_columns(
|
||
correlation.alias(f'lg_flow_mom_corr_{self.n}_{self.m}')
|
||
)
|
||
|
||
|
||
class LargeBuyConsolidationOperator(StockWiseOperator):
|
||
"""大单买入盘整期算子"""
|
||
|
||
def __init__(self, n: int = 20, vol_quantile: float = 0.2):
|
||
config = OperatorConfig(
|
||
name=f"lg_buy_consolidation_{n}",
|
||
description=f"{n}日大单买入盘整期",
|
||
required_columns=['close', 'buy_lg_vol', 'buy_elg_vol', 'sell_lg_vol',
|
||
'sell_elg_vol', 'vol'],
|
||
output_columns=[f'lg_buy_consolidation_{n}'],
|
||
parameters={'n': n, 'vol_quantile': vol_quantile}
|
||
)
|
||
super().__init__(config)
|
||
self.n = n
|
||
self.vol_quantile = vol_quantile
|
||
|
||
def apply_stock(self, stock_df: pl.DataFrame, **kwargs) -> pl.DataFrame:
|
||
"""计算大单买入盘整期"""
|
||
epsilon = 1e-8
|
||
|
||
# 计算收盘价滚动标准差
|
||
rolling_std = pl.col('close').rolling_std(window=self.n)
|
||
|
||
# 计算大单净流比率
|
||
net_lg_flow_ratio = (
|
||
(pl.col('buy_lg_vol') + pl.col('buy_elg_vol') -
|
||
pl.col('sell_lg_vol') - pl.col('sell_elg_vol')) /
|
||
(pl.col('vol') + epsilon)
|
||
)
|
||
|
||
# 计算滚动均值
|
||
rolling_mean_ratio = net_lg_flow_ratio.rolling_mean(window=self.n)
|
||
|
||
# 计算低波动阈值
|
||
# 这里需要按日期分组计算分位数,比较复杂,简化处理
|
||
# 在实际使用时,可能需要DateWiseOperator来处理横截面分位数
|
||
|
||
return stock_df.with_columns(
|
||
rolling_mean_ratio.alias(f'lg_buy_consolidation_{self.n}')
|
||
)
|
||
|
||
|
||
# 资金流因子集合
|
||
MONEY_FLOW_OPERATORS = [
|
||
MoneyFlowIntensityOperator(),
|
||
FlowDivergenceRatioOperator(),
|
||
FlowStructureChangeOperator(),
|
||
FlowAccelerationOperator(),
|
||
LargeFlowMomentumCorrelationOperator(),
|
||
LargeBuyConsolidationOperator(),
|
||
]
|
||
|
||
|
||
def apply_money_flow_factors(df: pl.DataFrame, operators: List = None) -> pl.DataFrame:
|
||
"""
|
||
应用所有资金流因子
|
||
|
||
Args:
|
||
df: 输入的Polars DataFrame
|
||
operators: 要应用的算子列表,如果为None则使用默认列表
|
||
|
||
Returns:
|
||
添加了资金流因子的DataFrame
|
||
"""
|
||
if operators is None:
|
||
operators = MONEY_FLOW_OPERATORS
|
||
|
||
result_df = df
|
||
for operator in operators:
|
||
result_df = operator(result_df)
|
||
|
||
return result_df
|