Infoway API 返回的财务数据,每一条记录都由五个核心字段描述,包括:

  • itemId
  • itemName
  • itemGroup
  • itemValue
  • parentItemId

初看会觉得有点抽象,但理解之后你会发现它的设计非常规整,无论是损益表、现金流量表还是资产负债表,用的都是同一套字段体系。这篇内容将帮助你更好地理解我们的财报API,尤其是对于没有财务会计背景的同学。

1. itemId: 财务科目的机器编号

itemId 是每个财务科目的固定英文标识符,比如 net_income(净利润)、gross_profit(毛利润)、total_revenue(总收入)。

它的作用类似数据库里的主键:不管你查的是 A 股还是美股,不管返回的是中文名还是英文名,itemId 永远固定不变。这意味着你在代码里过滤数据时,应该始终用 itemId 做判断,而不是用 itemName,比如:

Python
# 正确做法:用 itemId 过滤
net_income_items = [i for i in data["data"] if i["itemId"] == "net_income"]

# 不推荐:用 itemName 可能因语言差异出错
net_income_items = [i for i in data["data"] if i["itemName"] == "净利润"]

2. itemName:科目的可读名称

itemNameitemId 对应的英文显示名称,比如 gross_profit 对应的 itemName"Gross Profit"net_income 对应的是 "Net Income"itemName 用于展示,itemId 用于代码逻辑中的过滤和判断。

这个字段只会返回英文,不会出现中文或其他语言。如果你的产品需要向用户展示本地化名称,需要自己维护一份 itemId 到目标语言的映射表:

Python
# 自定义中文名称映射
ITEM_NAMES_ZH = {
    "total_revenue":      "总收入",
    "cost_of_goods":      "营业成本",
    "gross_profit":       "毛利润",
    "operating_expenses": "运营费用",
    "operating_income":   "营业利润",
    "net_income":         "净利润",
    "cf_oper":            "经营活动现金流",
    "cf_invest":          "投资活动现金流",
    "cf_finance":         "筹资活动现金流",
    "total_assets":       "总资产",
    "total_liabilities":  "总负债",
    "total_equity":       "股东权益合计",
}

# 使用时:优先取自定义名称,没有则回退到 API 返回的英文
def get_display_name(item, lang="zh"):
    if lang == "zh":
        return ITEM_NAMES_ZH.get(item["itemId"], item["itemName"])
    return item["itemName"]

3. itemGroup:数据所属的报表分类

itemGroup 是一个固定的英文字符串,标识这条数据来自哪张财报或哪个指标类别。

这个字段在需要过滤特定类型数据时很有用。常见的 itemGroup 值包括:

itemGroup含义
Income Statement损益表科目
Cash Flow Statement现金流量表科目
Balance Sheet资产负债表科目
Valuation ratios估值比率(PE、PB 等)
Profitability ratios盈利能力指标(ROE、毛利率等)
Revenue by business按业务板块拆分的收入
Revenue by region按地区拆分的收入
Dividend股息相关指标
Python
# 只取估值类指标
valuation = [i for i in data["data"] if i["itemGroup"] == "Valuation ratios"]

4. itemValue:当期科目的数值

itemValue 是该科目在当前报告期的原始数值,单位是对应市场的货币基本单位,A 股是元(人民币),美股是美元,港股是港元。

你会注意到这些数字通常非常大,比如 21340000000。这是正常的,因为 API 直接返回原始值,没有做单位换算。展示时需要自己处理:

Python
val = item["itemValue"]

print(f"{val / 1e8:.2f} 亿")   # → 213.40 亿(适合 A 股展示)
print(f"${val / 1e9:.1f}B")    # → $21.3B(适合美股展示)

另外,itemValue 可以是负数。投资活动现金流通常为负,表示净资金流出,这是正常的财务含义,并非数据错误。

5. parentItemId:父科目的编号

这是五个字段里最需要花时间理解的一个。

财报中的科目存在上下级关系:毛利润是总收入的子项,运营费用是营业利润的子项。parentItemId 记录的就是当前项目的上级科目的 itemId 是什么。

API 返回的是一个扁平的列表,每条记录平铺在数组里,没有嵌套。但通过 parentItemId,你可以把这个扁平列表还原成树状的层级结构:

Python
total_revenue(总收入)          ← parentItemId = ""(顶层,无父级)
  ├── cost_of_goods(营业成本)   ← parentItemId = "total_revenue"
  └── gross_profit(毛利润)      ← parentItemId = "total_revenue"

operating_income(营业利润)     ← parentItemId = ""(顶层)
  └── operating_expenses(运营费用)← parentItemId = "operating_income"

net_income(净利润)             ← parentItemId = ""(顶层)

判断一个科目是否为顶层parentItemId 为空字符串 "" 时,说明它没有父级,是顶层科目。注意这里是空字符串,不是 None,代码判断时要用 if item["parentItemId"] 而不是 if item["parentItemId"] is not None

下面是把 API 返回的扁平列表重建为树形结构的完整代码:

Python
# 取最新报告期
latest_date = data["data"][0]["periodDate"]
items = [i for i in data["data"] if i["periodDate"] == latest_date]

# 建立 id → 节点 的映射
nodes = {i["itemId"]: {**i, "children": []} for i in items}

# 根据 parentItemId 挂载父子关系
roots = []
for item in items:
    pid = item.get("parentItemId", "")
    if pid and pid in nodes:
        nodes[pid]["children"].append(nodes[item["itemId"]])
    else:
        roots.append(nodes[item["itemId"]])

# 递归打印树
def print_tree(node, depth=0):
    indent = "  " * depth
    val = node["itemValue"]
    print(f"{indent}{node['itemName']}{node['itemId']}): {val / 1e8:.2f} 亿")
    for child in node.get("children", []):
        print_tree(child, depth + 1)

for root in roots:
    print_tree(root)

6. 三个值得注意的细节

1. 同一个 itemId 会出现多次

API 会把多个报告期的数据混在同一个数组里返回。如果不加过滤,net_income 这个科目可能出现十几条,分别对应不同季度。取最新一期数据的正确方式:

Python
latest_date = data["data"][0]["periodDate"]   # 第一条即最新期
latest = [i for i in data["data"] if i["periodDate"] == latest_date]

2. parentItemId 是空字符串,不是 None

顶层科目的 parentItemId 值是 ""(空字符串)。条件判断写 if item["parentItemId"] 即可——空字符串在 Python 中为假值,这样写能正确区分顶层和子级科目。

3. itemValue 的货币单位因市场而异

A 股的 itemValue 单位是人民币元,美股是美元,港股是港元,日股是日元。跨市场比较时,注意先统一换算货币,不能直接用原始数值做对比。