标签settings.py属性详解

settings.py 是一个 Python 文件,里面定义一个 settings 字典。大部分时候你当 JSON 写就行。

大体结构一览

settings = {
    "is_enabled": True,
    "meta": { ... },
    "core": { ... },
    "data": { ... },
    "calculation": { ... },
    "tag_definitions": [ ... ],
}

下面逐块说明。

meta

标签元信息。

"meta": {
    "key": "volume_spike",           # 唯一标识,CLI 命令用这个名字
    "display_name": "放量标签",       # 显示名
    "description": "成交量超过均量2倍", # 描述
    "keywords": ["volume", "spike"], # 关键词
    "category": ["volume"],          # 分类
    "details": {},                  # 额外信息
}

key 是最重要的字段——CLI 命令用 python cli.py t volume_spike 找到这个标签场景。改了 key 等于换了一个标签场景。

core

标签私有参数。你想配什么就配什么,在 tag.py 里通过 ctx.settings.raw.get("core", {}) 读取。

"core": {
    "spike_multiplier": 2.0,
    "lookback_days": 20,
    "min_volume": 100000,
}

data

声明标签计算需要什么数据。

"data": {
    "base": {
        "data_key": "stock.kline.daily",     # 基础数据源
        "params": {"adjust": "qfq"},          # 前复权
        "indicators": {                        # 可选:附加指标
            "macd": [{"fast": 12, "slow": 26, "signal": 9}],
        },
    },
    "required": [                              # 可选:附加数据源
        {"data_key": "stock.finance.quarterly"},
    ],
    "min_required_records": 20,               # 最少需要多少条记录
}

base 是主数据源,required 是附加数据源。两者都会出现在 ctx.data.items 里。

base.data_key 决定了路由

系统根据 data.base.data_key 对应的数据契约(data contract)自动推断路由模式,不需要你手动指定:

数据契约的 scope/type

路由

说明

per_entity + 时序

per_entity

逐股票按日推进

global + 时序

global

全市场一份,按日推进

non_time_series

non_time_series

静态表,只算一次

per_entity 路由下还有子路由,由 calculation.execution.mode 决定。

calculation

计算执行配置。

"calculation": {
    "update_mode": "incremental",       # incremental / refresh
    "recompute": False,                  # 是否强制重算
    "is_dry_run": False,                 # 试运行,不写入数据库
    "execution": {
        "mode": "entity_based",         # entity_based / slice_based(仅 per_entity 需要)
        "start_date": "20200101",
        "end_date": "20241231",
    },
}

update_mode

模式

说明

适用场景

incremental

增量模式,从上次计算日期开始,只算新的

日常更新,速度快

refresh

全量重算,从头开始

数据出错需要重建

增量模式下,ctx.data.prior_value 会带上上次的标签值,你可以在 calculate_tag 里判断值是否变化,不变就返回 None 跳过写入。

execution.mode

模式

说明

适用

entity_based

按股票分组,每组独立跑完整时间线

少股票、长时间窗口

slice_based

按时间切片,每片处理全部股票

多股票、需要横截面计算

slice_based 模式下,如果你实现了 on_calendar_asof,系统会走横截面计算分支;否则走 calculate_tag 逐股计算。

global 和 non_time_series 路由不需要设 execution.mode。

start_date / end_date

回测时间窗口。格式 YYYYMMDD,如 "20200101"。留空则使用系统默认。

tag_definitions

定义这个标签场景产出哪些标签。一个标签场景可以产出多个标签。

"tag_definitions": [
    {
        "name": "is_spike",              # 唯一标识
        "display_name": "放量",           # 显示名
        "description": "成交量超过均量2倍", # 描述
    },
    {
        "name": "spike_ratio",
        "display_name": "放量倍数",
        "description": "今日成交量除以20日均量",
    },
]

name 必须在同一个标签场景内唯一。calculate_tag 返回的 value 会按 tag_definition 的 name 写入数据库。

如果只产出一个标签,列表里放一项就行。

顶层字段

字段

类型

默认值

说明

is_enabled

bool

False

标签场景是否启用。禁用的不会被批量计算选中

name

str

从 meta.key 派生

标签场景名称(自动生成,一般不需要手写)

core

dict

{}

策略私有参数

完整示例

逐股标签:RSI 超卖标记

settings = {
    "is_enabled": True,
    "meta": {
        "key": "rsi_oversold",
        "display_name": "RSI超卖",
        "description": "RSI低于30时标记为超卖",
    },
    "core": {
        "rsi_period": 14,
        "rsi_threshold": 30,
    },
    "data": {
        "base": {
            "data_key": "stock.kline.daily",
            "params": {"adjust": "qfq"},
        },
        "min_required_records": 14,
    },
    "calculation": {
        "update_mode": "incremental",
        "execution": {
            "mode": "entity_based",
            "start_date": "20200101",
            "end_date": "20241231",
        },
    },
    "tag_definitions": [
        {"name": "is_oversold", "display_name": "RSI超卖"},
        {"name": "rsi_value", "display_name": "RSI值"},
    ],
}

横截面标签:每日成交量排名前 10%

settings = {
    "is_enabled": True,
    "meta": {
        "key": "volume_top10",
        "display_name": "放量前10%",
        "description": "每日成交量排名前10%的股票",
    },
    "core": {
        "percentile": 0.1,
    },
    "data": {
        "base": {
            "data_key": "stock.kline.daily",
            "params": {"adjust": "qfq"},
        },
        "min_required_records": 1,
    },
    "calculation": {
        "update_mode": "incremental",
        "execution": {
            "mode": "slice_based",
            "start_date": "20200101",
            "end_date": "20241231",
        },
    },
    "tag_definitions": [
        {"name": "is_top10", "display_name": "放量前10%"},
    ],
}

全局标签:市场情绪指数

settings = {
    "is_enabled": True,
    "meta": {
        "key": "market_sentiment",
        "display_name": "市场情绪",
        "description": "全市场涨跌比,每日一个值",
    },
    "core": {},
    "data": {
        "base": {
            "data_key": "market.sentiment.daily",
        },
        "min_required_records": 1,
    },
    "calculation": {
        "update_mode": "incremental",
        # global 路由不需要 execution.mode
    },
    "tag_definitions": [
        {"name": "sentiment_score", "display_name": "情绪分数"},
    ],
}

静态标签:行业分类

settings = {
    "is_enabled": True,
    "meta": {
        "key": "industry_map",
        "display_name": "行业分类",
        "description": "股票的行业分类,静态不随时间变化",
    },
    "core": {},
    "data": {
        "base": {
            "data_key": "stock.industry_map",
        },
    },
    "calculation": {
        "update_mode": "refresh",
        # non_time_series 路由不需要 execution.mode
    },
    "tag_definitions": [
        {"name": "industry", "display_name": "所属行业"},
        {"name": "sector", "display_name": "所属板块"},
    ],
}

动态 settings - 但不建议您这么做

和策略的 settings.py 一样,你可以在 settings.py 里写 Python 逻辑:

import os

settings = {
    "meta": {
        "key": "rsi_oversold",
    },
    "core": {
        "rsi_threshold": int(os.environ.get("RSI_THRESHOLD", "30")),
    },
    # ... 其他配置
}

一般当 JSON 写就行。需要动态参数时才用 Python 特性。