Files
NewStock/main/factor/financial_factors.py
2025-11-29 00:23:12 +08:00

116 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
财务因子模块
包含基于股票截面的财务因子实现
"""
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)