116 lines
3.4 KiB
Python
116 lines
3.4 KiB
Python
|
|
"""
|
|||
|
|
财务因子模块
|
|||
|
|
包含基于股票截面的财务因子实现
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import numpy as np
|
|||
|
|
import polars as pl
|
|||
|
|
from main.factor.operator_framework import DateWiseFactor, StockWiseFactor
|
|||
|
|
|
|||
|
|
|
|||
|
|
class CashflowToEVFactor(StockWiseFactor):
|
|||
|
|
"""现金流-to-企业价值因子"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
super().__init__(
|
|||
|
|
name="cashflow_to_ev",
|
|||
|
|
parameters={},
|
|||
|
|
required_factor_ids=["n_cashflow_act", "total_liab", "money_cap", "total_mv"]
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
|
|||
|
|
# 计算企业价值
|
|||
|
|
total_mv = group_df["total_mv"]
|
|||
|
|
total_liab = group_df["total_liab"]
|
|||
|
|
money_cap = group_df["money_cap"]
|
|||
|
|
|
|||
|
|
# 企业价值 = 市值 + 负债合计 - 货币资金
|
|||
|
|
enterprise_value = total_mv + total_liab - money_cap
|
|||
|
|
|
|||
|
|
# 计算现金流-to-EV比率
|
|||
|
|
n_cashflow_act = group_df["n_cashflow_act"]
|
|||
|
|
cashflow_ev_ratio = n_cashflow_act / (enterprise_value + 1e-8) # 避免除零
|
|||
|
|
|
|||
|
|
return cashflow_ev_ratio.alias(self.factor_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class BookToPriceFactor(StockWiseFactor):
|
|||
|
|
"""账面价值-to-价格因子"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
super().__init__(
|
|||
|
|
name="book_to_price",
|
|||
|
|
parameters={},
|
|||
|
|
required_factor_ids=["bps", "close"]
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
|
|||
|
|
# 计算账面价值-to-价格比率
|
|||
|
|
bps = group_df["bps"]
|
|||
|
|
close = group_df["close"]
|
|||
|
|
|
|||
|
|
book_to_price = bps / (close + 1e-8) # 避免除零
|
|||
|
|
|
|||
|
|
return book_to_price.alias(self.factor_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class DebtToEquityFactor(StockWiseFactor):
|
|||
|
|
"""资产负债率因子"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
super().__init__(
|
|||
|
|
name="debt_to_equity",
|
|||
|
|
parameters={},
|
|||
|
|
required_factor_ids=["total_liab", "equity"]
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
|
|||
|
|
# 计算资产负债率
|
|||
|
|
total_liab = group_df["total_liab"]
|
|||
|
|
equity = group_df["equity"]
|
|||
|
|
|
|||
|
|
debt_to_equity = total_liab / (equity + 1e-8) # 避免除零
|
|||
|
|
|
|||
|
|
return debt_to_equity.alias(self.factor_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class ProfitMarginFactor(StockWiseFactor):
|
|||
|
|
"""净利润率因子"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
super().__init__(
|
|||
|
|
name="profit_margin",
|
|||
|
|
parameters={},
|
|||
|
|
required_factor_ids=["net_profit", "revenue"]
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
|
|||
|
|
# 计算净利润率
|
|||
|
|
net_profit = group_df["net_profit"]
|
|||
|
|
revenue = group_df["revenue"]
|
|||
|
|
|
|||
|
|
profit_margin = net_profit / (revenue + 1e-8) # 避免除零
|
|||
|
|
|
|||
|
|
return profit_margin.alias(self.factor_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class BMFactor(StockWiseFactor):
|
|||
|
|
"""账面市值比(Book-to-Market, BM)因子"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
super().__init__(
|
|||
|
|
name="bm",
|
|||
|
|
parameters={},
|
|||
|
|
required_factor_ids=["total_hldr_eqy_exc_min_int", "total_mv"]
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
|
|||
|
|
book_value = group_df["total_hldr_eqy_exc_min_int"]
|
|||
|
|
market_cap = group_df["total_mv"]
|
|||
|
|
|
|||
|
|
bm = book_value / (market_cap + 1e-8)
|
|||
|
|
|
|||
|
|
# 可选:过滤无效值(如负权益)
|
|||
|
|
# bm = pl.when((book_value > 0) & (market_cap > 0)).then(bm).otherwise(None)
|
|||
|
|
|
|||
|
|
return bm.alias(self.factor_id)
|