{
  "contract_version": "factor-formula.v1",
  "submission": {
    "intraday_expression": {
      "type": "string",
      "required": false
    },
    "interday_expression": {
      "type": "string",
      "required": true,
      "default_when_intraday_exists": "Feature"
    },
    "operators.py": {
      "type": "utf-8 python source",
      "required": false,
      "max_size_kib": 32
    },
    "neutralization": {
      "type": "object",
      "required": false,
      "description": "可选横截面中性化配置；enabled=true 时对最终日频因子做逐日截面 OLS 残差中性化。",
      "properties": {
        "enabled": {
          "type": "boolean",
          "required": true
        },
        "exposures": {
          "type": "array",
          "required": false,
          "items": {
            "enum": [
              "industry",
              "return",
              "barra"
            ]
          },
          "description": "缺省为全部三类；industry=申万一级行业，return=20日滚动收益，barra=Barra风格暴露。"
        },
        "barra_columns": {
          "type": "array",
          "required": false,
          "items": {
            "enum": [
              "BETA",
              "MOMENTUM",
              "SIZE",
              "EARNYILD",
              "RESVOL",
              "GROWTH",
              "BTOP",
              "LEVERAGE",
              "LIQUIDTY",
              "SIZENL"
            ]
          },
          "description": "启用 barra 时使用的风格子集，缺省为全部 10 个。"
        },
        "return_window": {
          "type": "integer",
          "required": false,
          "minimum": 1,
          "maximum": 250,
          "description": "启用 return 时的滚动收益窗口（交易日），缺省 20。"
        }
      }
    }
  },
  "fields": [
    {
      "name": "VWAP",
      "frequency": "分钟",
      "label": "成交均价",
      "unit": "价格",
      "description": "该股票当前分钟成交额除以成交量得到的成交量加权平均价。"
    },
    {
      "name": "Amount",
      "frequency": "分钟",
      "label": "成交额",
      "unit": "金额",
      "description": "该股票当前分钟内累计成交金额。"
    },
    {
      "name": "Volume",
      "frequency": "分钟",
      "label": "成交量",
      "unit": "股数",
      "description": "该股票当前分钟内累计成交股数。"
    },
    {
      "name": "Close",
      "frequency": "分钟",
      "label": "收盘价",
      "unit": "价格",
      "description": "该股票当前分钟最后一笔有效成交对应的收盘价。"
    },
    {
      "name": "Return",
      "frequency": "分钟",
      "label": "收益率",
      "unit": "小数",
      "description": "当前分钟 Close 相对上一分钟 Close 的变化率；每日开盘重新起算。"
    },
    {
      "name": "DailyReturn",
      "frequency": "日频",
      "label": "日收益率",
      "unit": "小数",
      "description": "正式日收益率字段由百分数转换为小数，例如 1.5% 转换为 0.015。"
    },
    {
      "name": "DailyClose",
      "frequency": "日频",
      "label": "复权收盘价",
      "unit": "价格",
      "description": "使用正式复权因子处理后的日收盘价。"
    },
    {
      "name": "DailyHigh",
      "frequency": "日频",
      "label": "复权最高价",
      "unit": "价格",
      "description": "使用正式复权因子处理后的日最高价。"
    },
    {
      "name": "DailyLow",
      "frequency": "日频",
      "label": "复权最低价",
      "unit": "价格",
      "description": "使用正式复权因子处理后的日最低价。"
    },
    {
      "name": "DailyAmount",
      "frequency": "日频",
      "label": "成交额",
      "unit": "金额",
      "description": "该股票当日累计成交金额。"
    },
    {
      "name": "DailyVolume",
      "frequency": "日频",
      "label": "成交量",
      "unit": "股数",
      "description": "该股票当日累计成交量。"
    },
    {
      "name": "DailyTurnover",
      "frequency": "日频",
      "label": "自由流通换手率",
      "unit": "百分数",
      "description": "该股票当日自由流通换手率，保持正式日频源字段口径。"
    },
    {
      "name": "DailyFreeShare",
      "frequency": "日频",
      "label": "自由流通股本",
      "unit": "股数",
      "description": "该股票当日自由流通股本。"
    },
    {
      "name": "DailyTotalMV",
      "frequency": "日频",
      "label": "总市值",
      "unit": "金额",
      "description": "该股票当日总市值。"
    },
    {
      "name": "DailyTotalShare",
      "frequency": "日频",
      "label": "总股本",
      "unit": "股数",
      "description": "该股票当日总股本。"
    }
  ],
  "level2_daily_features": {
    "groups": [
      {
        "name": "ORDER",
        "label": "逐笔委托",
        "features": [
          {
            "name": "order__cancel_pressure",
            "description": "撤单量 /（新增委托量 + 撤单量）。"
          },
          {
            "name": "order__order_flow_imbalance",
            "description": "［（新增买量−撤单买量）−（新增卖量−撤单卖量）］/（新增委托量 + 撤单量）。"
          }
        ]
      },
      {
        "name": "TRADE",
        "label": "逐笔成交",
        "features": [
          {
            "name": "trade__trade_directional_coverage",
            "description": "（主动买成交量 + 主动卖成交量）/ 全部成交量。"
          },
          {
            "name": "trade__trade_imbalance",
            "description": "（主动买成交量−主动卖成交量）/（主动买成交量 + 主动卖成交量）。"
          }
        ]
      },
      {
        "name": "SNAPSHOT",
        "label": "五档盘口快照",
        "features": [
          {
            "name": "snapshot__mean_relative_spread",
            "description": "日内平均（卖一价−买一价）/ 中间价。"
          },
          {
            "name": "snapshot__mean_depth_imbalance",
            "description": "日内平均（五档买量−五档卖量）/（五档买量 + 五档卖量）。"
          },
          {
            "name": "snapshot__mean_top_depth_imbalance",
            "description": "日内平均（买一量−卖一量）/（买一量 + 卖一量）。"
          },
          {
            "name": "snapshot__midpoint_realized_volatility",
            "description": "sqrt(Σ[log(midpoint_t)−log(midpoint_t−1)]²)。"
          },
          {
            "name": "snapshot__mean_snapshot_quote_churn",
            "description": "相邻快照20个五档价格/数量字段发生变化的比例，再取日均值。"
          }
        ]
      }
    ],
    "presence_flags": [
      {
        "name": "order__present",
        "description": "该股票当天是否有有效的逐笔委托日频结果。"
      },
      {
        "name": "trade__present",
        "description": "该股票当天是否有有效的逐笔成交日频结果。"
      },
      {
        "name": "snapshot__present",
        "description": "该股票当天是否有有效的五档盘口日频结果。"
      }
    ],
    "snapshot_sessions": [
      "09:30:00-11:30:00",
      "13:00:00-14:56:59"
    ],
    "snapshot_minimum_observations": 3842,
    "snapshot_expected_observations": 4802,
    "snapshot_minimum_coverage": 0.8
  },
  "operator_groups": [
    {
      "name": "算术运算",
      "description": "对同频率、同日期或时点、同股票轴的输入逐元素计算。输入既可以是原始字段和常量，也可以是时间序列算子、截面算子或其他算术算子的输出；算子可以嵌套组合。",
      "operators": [
        {
          "name": "Add",
          "signature": "Add(x, y)",
          "description": "逐元素相加。",
          "example": "Add(Return, 0.001)"
        },
        {
          "name": "Sub",
          "signature": "Sub(x, y)",
          "description": "逐元素计算 x - y。",
          "example": "Sub(Return, CsMean(Return))"
        },
        {
          "name": "Mul",
          "signature": "Mul(x, y)",
          "description": "逐元素相乘。",
          "example": "Mul(CsZScore(Return), CsRank(Volume))"
        },
        {
          "name": "Div",
          "signature": "Div(x, y)",
          "description": "安全除法；分母绝对值不大于 1e-12 时返回 NaN。",
          "example": "Div(Amount, CsMean(Amount))"
        },
        {
          "name": "Neg",
          "signature": "Neg(x)",
          "description": "逐元素取相反数。",
          "example": "Neg(TsStd(Return, 20))"
        },
        {
          "name": "Abs",
          "signature": "Abs(x)",
          "description": "逐元素取绝对值。",
          "example": "Abs(Return)"
        },
        {
          "name": "Sign",
          "signature": "Sign(x)",
          "description": "返回元素符号：负数为 -1、零为 0、正数为 1。",
          "example": "Sign(Return)"
        },
        {
          "name": "Log",
          "signature": "Log(x)",
          "description": "计算自然对数；非正数返回 NaN。",
          "example": "Log(Amount)"
        },
        {
          "name": "Inv",
          "signature": "Inv(x)",
          "description": "逐元素取倒数；接近零的值返回 NaN。",
          "example": "Inv(Amount)"
        },
        {
          "name": "Exp",
          "signature": "Exp(x)",
          "description": "逐元素计算以 e 为底的指数；溢出返回 NaN。",
          "example": "Exp(Return)"
        },
        {
          "name": "Sqrt",
          "signature": "Sqrt(x)",
          "description": "逐元素开平方；负数返回 NaN。",
          "example": "Sqrt(Volume)"
        },
        {
          "name": "Pow",
          "signature": "Pow(x, exponent)",
          "description": "逐元素计算指定次幂；非实数或溢出结果返回 NaN。",
          "example": "Pow(Return, 2)"
        },
        {
          "name": "Min",
          "signature": "Min(x, y)",
          "description": "逐元素取较小值。",
          "example": "Min(VWAP, Close)"
        },
        {
          "name": "Max",
          "signature": "Max(x, y)",
          "description": "逐元素取较大值。",
          "example": "Max(VWAP, Close)"
        }
      ]
    },
    {
      "name": "截面运算",
      "description": "在同一时点或同一交易日沿股票轴计算。分钟表达式按每分钟截面处理，最终日频表达式按每日截面处理。截面运算不会移除股票轴，输出仍与输入面板对齐，可以继续传给算术、时间序列或聚合算子。",
      "operators": [
        {
          "name": "CsRank",
          "signature": "CsRank(x)",
          "description": "沿股票轴计算稳定的截面百分位排名，有效值范围为 (0, 1]；输出与原面板对齐，可继续参与其他运算。",
          "example": "CsRank(Div(Amount, CsMean(Amount)))"
        },
        {
          "name": "CsMean",
          "signature": "CsMean(x)",
          "description": "沿股票轴计算有效值均值，并将均值广播回该截面的每只有效股票，可用于去均值、相对均值等计算。",
          "example": "CsMean(Abs(Return))"
        },
        {
          "name": "CsZScore",
          "signature": "CsZScore(x)",
          "description": "沿股票轴去均值并除以样本标准差；输出与原面板对齐，可继续参与其他运算。",
          "example": "CsZScore(Sub(Return, CsMean(Return)))"
        }
      ]
    },
    {
      "name": "时间序列",
      "description": "沿每个交易日内部的分钟轴滚动计算，不跨交易日。",
      "operators": [
        {
          "name": "TsMean",
          "signature": "TsMean(x, window)",
          "description": "日内滚动均值；窗口形成前返回 NaN。",
          "example": "TsMean(Amount, 20)"
        },
        {
          "name": "TsStd",
          "signature": "TsStd(x, window)",
          "description": "日内滚动样本标准差；窗口形成前返回 NaN。",
          "example": "TsStd(Return, 20)"
        },
        {
          "name": "TsSum",
          "signature": "TsSum(x, window)",
          "description": "日内滚动求和。",
          "example": "TsSum(Volume, 20)"
        },
        {
          "name": "TsMin",
          "signature": "TsMin(x, window)",
          "description": "日内滚动最小值。",
          "example": "TsMin(Return, 20)"
        },
        {
          "name": "TsMax",
          "signature": "TsMax(x, window)",
          "description": "日内滚动最大值。",
          "example": "TsMax(Return, 20)"
        },
        {
          "name": "TsDelay",
          "signature": "TsDelay(x, periods)",
          "description": "在当日分钟轴滞后，不跨交易日。",
          "example": "TsDelay(Close, 5)"
        },
        {
          "name": "TsDelta",
          "signature": "TsDelta(x, periods)",
          "description": "当前值减去日内滞后值。",
          "example": "TsDelta(Close, 5)"
        },
        {
          "name": "TsRank",
          "signature": "TsRank(x, window)",
          "description": "当前值在日内滚动窗口中的百分位排名。",
          "example": "TsRank(Amount, 20)"
        },
        {
          "name": "TsZScore",
          "signature": "TsZScore(x, window)",
          "description": "当前值相对日内滚动均值和样本标准差的标准分。",
          "example": "TsZScore(Return, 20)"
        },
        {
          "name": "TsCorr",
          "signature": "TsCorr(x, y, window)",
          "description": "两组分钟序列的日内滚动相关系数。",
          "example": "TsCorr(Return, Volume, 20)"
        },
        {
          "name": "TsCov",
          "signature": "TsCov(x, y, window)",
          "description": "两组分钟序列的日内滚动样本协方差。",
          "example": "TsCov(Return, Volume, 20)"
        },
        {
          "name": "TsAutoCorr",
          "signature": "TsAutoCorr(x, window, lag)",
          "description": "日内滚动自相关；lag 必须是小于 window 的正整数。",
          "example": "TsAutoCorr(Return, 20, 1)"
        },
        {
          "name": "TsArgMax",
          "signature": "TsArgMax(x, window)",
          "description": "滚动最大值位置占窗口长度的比例，越接近 1 表示越靠近当前。",
          "example": "TsArgMax(Amount, 20)"
        },
        {
          "name": "TsArgMin",
          "signature": "TsArgMin(x, window)",
          "description": "滚动最小值位置占窗口长度的比例，越接近 1 表示越靠近当前。",
          "example": "TsArgMin(Amount, 20)"
        },
        {
          "name": "TsDecayLinear",
          "signature": "TsDecayLinear(x, window)",
          "description": "线性衰减均值，越靠近当前时点权重越高。",
          "example": "TsDecayLinear(Return, 20)"
        },
        {
          "name": "TsDemean",
          "signature": "TsDemean(x, window)",
          "description": "当前值减去日内滚动均值。",
          "example": "TsDemean(Return, 20)"
        },
        {
          "name": "TsReturn",
          "signature": "TsReturn(x, periods)",
          "description": "当前值相对日内滞后值的变化率。",
          "example": "TsReturn(Close, 5)"
        },
        {
          "name": "TsMedian",
          "signature": "TsMedian(x, window)",
          "description": "日内滚动中位数。",
          "example": "TsMedian(Amount, 20)"
        },
        {
          "name": "TsVar",
          "signature": "TsVar(x, window)",
          "description": "日内滚动样本方差。",
          "example": "TsVar(Return, 20)"
        },
        {
          "name": "TsSkew",
          "signature": "TsSkew(x, window)",
          "description": "日内滚动偏度。",
          "example": "TsSkew(Return, 20)"
        },
        {
          "name": "TsKurt",
          "signature": "TsKurt(x, window)",
          "description": "日内滚动超额峰度。",
          "example": "TsKurt(Return, 20)"
        },
        {
          "name": "TsQuantile",
          "signature": "TsQuantile(x, q, window)",
          "description": "日内滚动 q 分位数，q 必须位于 [0, 1]。",
          "example": "TsQuantile(Amount, 0.9, 20)"
        }
      ]
    },
    {
      "name": "日内聚合（必选其一）",
      "description": "只能作为日内表达式最外层，把分钟结果压缩为每日 Feature。",
      "operators": [
        {
          "name": "DayMean",
          "signature": "DayMean(x)",
          "description": "取全天分钟均值。",
          "example": "DayMean(Neg(Return))"
        },
        {
          "name": "DaySum",
          "signature": "DaySum(x)",
          "description": "取全天分钟合计。",
          "example": "DaySum(Volume)"
        },
        {
          "name": "DayLast",
          "signature": "DayLast(x)",
          "description": "取当日最后一个有效分钟值。",
          "example": "DayLast(CsRank(Return))"
        },
        {
          "name": "PeriodMean",
          "signature": "PeriodMean(start_time, end_time, x)",
          "description": "对闭区间内的分钟值取均值。",
          "example": "PeriodMean(145000, 150000, Return)"
        },
        {
          "name": "PeriodSum",
          "signature": "PeriodSum(start_time, end_time, x)",
          "description": "对闭区间内的分钟值求和。",
          "example": "PeriodSum(93000, 100000, Volume)"
        },
        {
          "name": "PeriodLast",
          "signature": "PeriodLast(start_time, end_time, x)",
          "description": "取闭区间内最后一个有效分钟值。",
          "example": "PeriodLast(145000, 150000, CsRank(Return))"
        }
      ]
    },
    {
      "name": "日间运算（选填）",
      "description": "在 Feature 与 Daily 前缀字段上跨交易日计算；留空等同于 Feature。",
      "operators": [
        {
          "name": "DailyMean",
          "signature": "DailyMean(Feature, window)",
          "description": "跨交易日滚动均值。",
          "example": "DailyMean(Feature, 5)"
        },
        {
          "name": "DailyEMA",
          "signature": "DailyEMA(Feature, window)",
          "description": "跨交易日指数移动平均，alpha = 2 / (window + 1)。",
          "example": "DailyEMA(Feature, 10)"
        },
        {
          "name": "DailyStd",
          "signature": "DailyStd(Feature, window)",
          "description": "跨交易日滚动样本标准差。",
          "example": "DailyStd(Feature, 20)"
        },
        {
          "name": "DailySum",
          "signature": "DailySum(Feature, window)",
          "description": "跨交易日滚动求和。",
          "example": "DailySum(Feature, 5)"
        },
        {
          "name": "DailyMin",
          "signature": "DailyMin(Feature, window)",
          "description": "跨交易日滚动最小值。",
          "example": "DailyMin(Feature, 20)"
        },
        {
          "name": "DailyMax",
          "signature": "DailyMax(Feature, window)",
          "description": "跨交易日滚动最大值。",
          "example": "DailyMax(Feature, 20)"
        },
        {
          "name": "DailyRank",
          "signature": "DailyRank(Feature, window)",
          "description": "当前值在跨日滚动窗口中的百分位排名。",
          "example": "DailyRank(Feature, 20)"
        },
        {
          "name": "DailyZScore",
          "signature": "DailyZScore(Feature, window)",
          "description": "当前值相对跨日滚动均值和样本标准差的标准分。",
          "example": "DailyZScore(Feature, 20)"
        },
        {
          "name": "Delay",
          "signature": "Delay(Feature, periods)",
          "description": "按交易日滞后，正数只读取历史。",
          "example": "Delay(Feature, 1)"
        },
        {
          "name": "Delta",
          "signature": "Delta(Feature, periods)",
          "description": "当前 Feature 减去跨日滞后值。",
          "example": "Delta(Feature, 5)"
        },
        {
          "name": "Correlation",
          "signature": "Correlation(x, y, window)",
          "description": "两组日频表达式的跨日滚动相关系数。",
          "example": "Correlation(Feature, Delay(Feature, 1), 20)"
        }
      ]
    }
  ],
  "rules": [
    "公式既可写成单个表达式，也可写成顺序赋值；分段写法的最后一个赋值变量作为输出，支持换行、英文分号和中文分号。",
    "分段公式的局部变量必须以小写字母开头，只能引用前面已经定义的变量，且不能重复赋值。",
    "使用分钟数据时，第一栏最终输出必须是 DayMean、DaySum、DayLast、PeriodMean、PeriodSum 或 PeriodLast 的日内降频结果；降频后的日频运算应放在第二栏。",
    "日内表达式可引用 Daily 字段；系统按日期、股票广播，信号按收盘后形成。",
    "日内滚动窗口必须是正整数，且每天重新开始计算。",
    "日间表达式只能引用 Feature、Daily 前缀字段、公开日间算子，以及本次提交唯一的自定义 Python 算子。",
    "日间表达式留空等同于 Feature。",
    "第一步和第二步都留空但提供 operators.py 时，入口函数参数名必须都是 Daily 字段名，系统会自动生成日间自定义算子调用；包含 window、alpha 等数字参数时必须显式填写日间表达式。",
    "公共算子支持嵌套组合；算术算子可以接收字段、常量以及时间序列、截面和其他算术算子的输出。CsMean 等截面统计结果会广播并保持原股票轴，不会变成无法继续计算的单一标量。",
    "缺失值不会自动填充为零。",
    "中性化为选填：启用后对最终日频因子逐日做横截面 OLS 回归取残差；暴露变量可选行业（申万一级）、收益（20日滚动）与 Barra 风格（10因子，含规模），可多选。参数固定：zscore 标准化、clip 4.0、min_obs 30。"
  ]
}