359 lines
15 KiB
Python
359 lines
15 KiB
Python
"""
|
||
公式元数据注册表
|
||
|
||
用于将计算引擎中的每个公式节点(含子公式)映射到唯一的 code、名称、公式说明以及排序,
|
||
以便在 valuation_calculation_steps 表中进行结构化记录,并最终生成可读的计算报告。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
from decimal import Decimal
|
||
from typing import Dict, List, Optional
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class FormulaMeta:
|
||
code: str
|
||
name: str
|
||
formula: str
|
||
order: Decimal
|
||
parent_code: Optional[str]
|
||
group_code: str
|
||
|
||
|
||
FormulaTreeNode = Dict[str, object]
|
||
|
||
|
||
def _node(
|
||
code: str,
|
||
name: str,
|
||
formula: str,
|
||
order: str,
|
||
children: Optional[List[FormulaTreeNode]] = None,
|
||
group: Optional[str] = None,
|
||
) -> FormulaTreeNode:
|
||
return {
|
||
"code": code,
|
||
"name": name,
|
||
"formula": formula,
|
||
"order": order,
|
||
"group_code": group,
|
||
"children": children or [],
|
||
}
|
||
|
||
|
||
FORMULA_TREE: List[FormulaTreeNode] = [
|
||
_node(
|
||
"FINAL_A",
|
||
"最终估值A",
|
||
"最终估值A = 模型估值B × 0.7 + 市场估值C × 0.3",
|
||
"10",
|
||
children=[
|
||
_node(
|
||
"MODEL_B",
|
||
"模型估值B",
|
||
"模型估值B = (经济价值B1 × 0.7 + 文化价值B2 × 0.3) × 风险调整系数B3",
|
||
"20",
|
||
group="MODEL_B",
|
||
children=[
|
||
_node(
|
||
"MODEL_B_ECON_B1",
|
||
"经济价值B1",
|
||
"经济价值B1 = 基础价值B11 × (1 + 流量因子B12) × 政策乘数B13",
|
||
"21",
|
||
children=[
|
||
_node(
|
||
"MODEL_B_ECON_B11",
|
||
"基础价值B11",
|
||
"基础价值B11 = 财务价值F × (0.45 + 0.05 × 行业系数I) + 法律强度L × (0.35 + 0.05 × 行业系数I) + 发展潜力D × 0.2",
|
||
"21.1",
|
||
children=[
|
||
_node(
|
||
"MODEL_B_ECON_B11_FINANCIAL_VALUE",
|
||
"财务价值F",
|
||
"财务价值F = [3年内年均收益 × (1 + 增长率)^5] ÷ 5",
|
||
"21.11",
|
||
),
|
||
_node(
|
||
"MODEL_B_ECON_B11_LEGAL_STRENGTH",
|
||
"法律强度L",
|
||
"法律强度L = 专利分 × 0.4 + 普及分 × 0.3 + 侵权分 × 0.3",
|
||
"21.12",
|
||
),
|
||
_node(
|
||
"MODEL_B_ECON_B11_DEVELOPMENT_POTENTIAL",
|
||
"发展潜力D",
|
||
"发展潜力D = 专利分 × 0.5 + ESG分 × 0.2 + 创新投入比 × 0.3",
|
||
"21.13",
|
||
),
|
||
_node(
|
||
"MODEL_B_ECON_B11_INDUSTRY_COEFFICIENT",
|
||
"行业系数I",
|
||
"行业系数I = (目标行业平均ROE - 基准行业ROE) ÷ 基准行业ROE",
|
||
"21.14",
|
||
),
|
||
],
|
||
),
|
||
_node(
|
||
"MODEL_B_FLOW_B12",
|
||
"流量因子B12",
|
||
"流量因子B12 = ln(S1 ÷ S2) × 0.3 + 社交媒体传播度S3 × 0.7",
|
||
"21.2",
|
||
children=[
|
||
_node(
|
||
"MODEL_B_FLOW_B12_INTERACTION_INDEX",
|
||
"互动量指数",
|
||
"互动量指数 = (点赞 + 评论 + 分享) ÷ 1000",
|
||
"21.21",
|
||
),
|
||
_node(
|
||
"MODEL_B_FLOW_B12_COVERAGE_INDEX",
|
||
"覆盖人群指数",
|
||
"覆盖人群指数 = 粉丝数 ÷ 10000",
|
||
"21.22",
|
||
),
|
||
_node(
|
||
"MODEL_B_FLOW_B12_CONVERSION_EFFICIENCY",
|
||
"转化效率",
|
||
"转化效率 = 商品链接点击量 ÷ 内容浏览量",
|
||
"21.23",
|
||
),
|
||
_node(
|
||
"MODEL_B_FLOW_B12_SOCIAL_SPREAD",
|
||
"社交媒体传播度S3",
|
||
"社交媒体传播度S3 = 互动量指数 × 0.4 + 覆盖人群指数 × 0.3 + 转化效率 × 0.3",
|
||
"21.24",
|
||
),
|
||
],
|
||
),
|
||
_node(
|
||
"MODEL_B_POLICY_B13",
|
||
"政策乘数B13",
|
||
"政策乘数B13 = 1 + 政策契合度评分P × 0.15,其中 P = 政策匹配度 × 0.4 + 实施阶段评分 × 0.3 + 资金支持度 × 0.3",
|
||
"21.3",
|
||
),
|
||
],
|
||
),
|
||
_node(
|
||
"MODEL_B_CULTURAL_B2",
|
||
"文化价值B2",
|
||
"文化价值B2 = 活态传承系数B21 × 0.6 + (纹样基因值B22 ÷ 10) × 0.4",
|
||
"22",
|
||
children=[
|
||
_node(
|
||
"MODEL_B_CULTURAL_B21",
|
||
"活态传承系数B21",
|
||
"活态传承系数B21 = 传承人等级系数 × 0.4 + 教学传播频次 × 0.3 + 跨界合作深度 × 0.3",
|
||
"22.1",
|
||
children=[
|
||
_node(
|
||
"MODEL_B_CULTURAL_B21_TEACHING_FREQ",
|
||
"教学传播频次",
|
||
"教学传播频次 = 线下传习次数 × 0.6 + 线上课程点击量(万) × 0.4",
|
||
"22.11",
|
||
),
|
||
],
|
||
),
|
||
_node(
|
||
"MODEL_B_CULTURAL_B22",
|
||
"纹样基因值B22",
|
||
"纹样基因值B22 = (结构复杂度SC × 0.6 + 归一化信息熵H × 0.4) × 历史传承度HI × 10",
|
||
"22.2",
|
||
),
|
||
],
|
||
),
|
||
_node(
|
||
"MODEL_B_RISK_B3",
|
||
"风险调整系数B3",
|
||
"风险调整系数B3 = 0.8 + 风险评分总和R × 0.4,其中 R = 市场风险 × 0.3 + 法律风险 × 0.4 + 传承风险 × 0.3",
|
||
"23",
|
||
children=[
|
||
_node(
|
||
"MODEL_B_RISK_B3_MARKET",
|
||
"市场风险",
|
||
"市场风险依据价格波动率:波动率 ≤5% 计10分,5-15%计5分,>15%计0分",
|
||
"23.1",
|
||
),
|
||
_node(
|
||
"MODEL_B_RISK_B3_LEGAL",
|
||
"法律风险",
|
||
"法律风险根据诉讼状态评分(无诉讼/已解决/未解决)",
|
||
"23.2",
|
||
),
|
||
_node(
|
||
"MODEL_B_RISK_B3_INHERITANCE",
|
||
"传承风险",
|
||
"传承风险依据传承人年龄:≤50岁10分,50-70岁5分,>70岁0分,取最高分",
|
||
"23.3",
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
_node(
|
||
"MARKET_C",
|
||
"市场估值C",
|
||
"市场估值C = 市场竞价C1 × 热度系数C2 × 稀缺性乘数C3 × 时效性衰减C4",
|
||
"30",
|
||
group="MARKET_C",
|
||
children=[
|
||
_node(
|
||
"MARKET_C_C1",
|
||
"市场竞价C1",
|
||
"市场竞价C1 结合历史交易价格、人工竞价与专家估值的加权结果",
|
||
"30.1",
|
||
),
|
||
_node(
|
||
"MARKET_C_C2",
|
||
"热度系数C2",
|
||
"热度系数C2 = 1 + 浏览热度分(依据日均浏览量与收藏数量)",
|
||
"30.2",
|
||
),
|
||
_node(
|
||
"MARKET_C_C3",
|
||
"稀缺性乘数C3",
|
||
"稀缺性乘数C3 = 1 + 稀缺等级分",
|
||
"30.3",
|
||
),
|
||
_node(
|
||
"MARKET_C_C4",
|
||
"时效性衰减C4",
|
||
"时效性衰减C4 依据距最近市场活动天数的衰减系数",
|
||
"30.4",
|
||
),
|
||
],
|
||
),
|
||
_node(
|
||
"DYNAMIC_PLEDGE_RATE",
|
||
"动态质押率DPR",
|
||
"动态质押率DPR = 基础质押率 × (1 + 流量修正系数) + 政策加成系数 - 流动性调节因子",
|
||
"40",
|
||
group="DYNAMIC_PLEDGE",
|
||
),
|
||
# API查询结果记录
|
||
_node(
|
||
"API_ESG_QUERY",
|
||
"ESG评分查询",
|
||
"根据行业名称查询ESG基准分",
|
||
"50.1",
|
||
group="API_QUERY",
|
||
),
|
||
_node(
|
||
"API_INDUSTRY_QUERY",
|
||
"行业系数查询",
|
||
"根据行业名称查询行业修正系数I",
|
||
"50.2",
|
||
group="API_QUERY",
|
||
),
|
||
_node(
|
||
"API_POLICY_QUERY",
|
||
"政策匹配度查询",
|
||
"根据行业名称查询政策匹配度评分",
|
||
"50.3",
|
||
group="API_QUERY",
|
||
),
|
||
_node(
|
||
"API_JUDICIAL_QUERY",
|
||
"司法诉讼查询",
|
||
"根据机构名称查询诉讼状态,映射为法律风险评分(无诉讼:10分, 已解决:7分, 未解决:0分)",
|
||
"50.4",
|
||
group="API_QUERY",
|
||
),
|
||
_node(
|
||
"API_PATENT_QUERY",
|
||
"专利信息查询",
|
||
"根据专利申请号查询专利数量和剩余年限,计算专利评分",
|
||
"50.5",
|
||
group="API_QUERY",
|
||
),
|
||
_node(
|
||
"API_WECHAT_INDEX",
|
||
"微信指数查询",
|
||
"根据资产名称查询微信指数,计算搜索指数S1 = 微信指数 / 10",
|
||
"50.6",
|
||
group="API_QUERY",
|
||
),
|
||
# 参数映射记录
|
||
_node(
|
||
"MAPPING_CROSS_BORDER_DEPTH",
|
||
"跨界合作深度映射",
|
||
"用户选项映射为评分:无(0分), 品牌联名(3分), 科技载体(5分), 国家外交礼品(10分)",
|
||
"51.1",
|
||
group="PARAM_MAPPING",
|
||
),
|
||
_node(
|
||
"MAPPING_INHERITOR_LEVEL",
|
||
"传承人等级映射",
|
||
"用户选项映射为系数:国家级(10分), 省级(7分), 市级及以下(4分)",
|
||
"51.2",
|
||
group="PARAM_MAPPING",
|
||
),
|
||
# 权重计算记录
|
||
_node(
|
||
"CALC_HISTORICAL_INHERITANCE",
|
||
"历史传承度计算",
|
||
"HI = 出土实物×1.0 + 古代文献×0.8 + 传承人佐证×0.6 + 现代研究×0.4",
|
||
"52.1",
|
||
group="PARAM_CALC",
|
||
),
|
||
_node(
|
||
"CALC_INHERITANCE_RISK",
|
||
"传承风险年龄转换",
|
||
"根据各年龄段传承人数量计算传承风险评分:≤50岁(10分), 50-70岁(5分), >70岁(0分), 取最高分",
|
||
"52.2",
|
||
group="PARAM_CALC",
|
||
),
|
||
_node(
|
||
"CALC_MARKET_RISK",
|
||
"市场风险价格波动",
|
||
"根据30天价格波动计算市场风险评分:波动率≤5%(10分), 5-15%(5分), >15%(0分)",
|
||
"52.3",
|
||
group="PARAM_CALC",
|
||
),
|
||
],
|
||
)
|
||
]
|
||
|
||
|
||
def _build_index() -> Dict[str, FormulaMeta]:
|
||
index: Dict[str, FormulaMeta] = {}
|
||
|
||
def dfs(nodes: List[FormulaTreeNode], parent_code: Optional[str], group_code: Optional[str]):
|
||
for node in nodes:
|
||
code = node["code"]
|
||
name = node["name"]
|
||
formula = node["formula"]
|
||
order = Decimal(str(node["order"]))
|
||
explicit_group = node.get("group_code")
|
||
if explicit_group:
|
||
current_group = explicit_group
|
||
elif parent_code is None:
|
||
current_group = code
|
||
else:
|
||
current_group = group_code or parent_code
|
||
meta = FormulaMeta(
|
||
code=code,
|
||
name=name,
|
||
formula=formula,
|
||
order=order,
|
||
parent_code=parent_code,
|
||
group_code=current_group,
|
||
)
|
||
index[code] = meta
|
||
dfs(node.get("children", []), code, current_group)
|
||
|
||
dfs(FORMULA_TREE, None, None)
|
||
return index
|
||
|
||
|
||
FORMULA_INDEX: Dict[str, FormulaMeta] = _build_index()
|
||
|
||
|
||
def get_formula_meta(code: str) -> FormulaMeta:
|
||
meta = FORMULA_INDEX.get(code)
|
||
if not meta:
|
||
raise KeyError(f"公式编码未注册: {code}")
|
||
return meta
|
||
|