a-share-constraints.md(配套4)

A股交易规则约束全集

本文档为A股量化投研系统的交易规则参考手册,涵盖交易时间、涨跌停、交易成本、停牌、退市、分红送转、融资融券及指数成分股变动等核心约束。


1. 交易时间与规则

1.1 各板块交易时间

板块 连续竞价时间 开盘集合竞价 收盘集合竞价
沪深主板 9:30-11:30, 13:00-15:00 9:15-9:25 14:57-15:00
科创板(688xxx) 同上 同上 同上
创业板(300xxx) 同上 同上 同上
北交所(8xxxxx) 9:30-11:30, 13:00-15:00 9:15-9:25 14:57-15:00

1.2 集合竞价规则

  • 开盘集合竞价:9:15-9:25,其中9:15-9:20可撤单,9:20-9:25不可撤单。
  • 收盘集合竞价:14:57-15:00,期间不可撤单。
  • 有效竞价范围:
    • 主板:开盘集合竞价 ±10%(以昨收盘价为基准)
    • 科创板/创业板:开盘集合竞价 ±20%
    • 北交所:开盘集合竞价 ±30%

1.3 T+1 交易规则

当日买入的证券,下一个交易日才能卖出。资金方面,卖出所得资金当日可用(可买入),但需下一交易日方可转出(银证转账)。

def is_tradable(buy_date: str, sell_date: str) -> bool:
    """检查T+1规则下是否可卖出"""
    from datetime import datetime, timedelta
    buy_dt = datetime.strptime(buy_date, "%Y-%m-%d")
    sell_dt = datetime.strptime(sell_date, "%Y-%m-%d")
    # T+1: 卖出日期必须晚于买入日期至少一个交易日
    return sell_dt > buy_dt

1.4 交易日历

A股法定节假日及周末休市,每年由沪深交易所公布交易日历。量化回测中需使用交易日历过滤非交易日。

import pandas as pd

def get_trading_days(start: str, end: str) -> pd.DatetimeIndex:
    """获取交易日历(示例,实际应从交易所或数据源获取)"""
    # 使用 pandas 内置的交易日历或第三方库如 exchange_calendars
    import exchange_calendars as ec
    xshg = ec.get_calendar("XSHG")
    return xshg.valid_days(start_date=start, end_date=end)

2. 涨跌停限制(按板块和时期)

2.1 各板块涨跌停幅度

板块 时期 日涨跌停幅度
沪深主板 2020年前 ±10%
沪深主板 2023年全面注册制后 ±10%(维持不变)
科创板(688xxx) 2019年7月起 ±20%
创业板(300xxx) 2020年8月注册制改革后 ±20%
北交所(8xxxxx) 2021年11月起 ±30%
ST / *ST 所有板块 ±5%
新股上市首日 主板(注册制后) 无涨跌停,有效竞价范围±20%
新股上市首日 科创板/创业板 前5个交易日无涨跌停
新股上市首日 北交所 首日无涨跌停

2.2 涨跌停价格计算

def calc_price_limit(
    prev_close: float,
    board: str,
    is_st: bool = False,
    is_new_stock: bool = False,
    new_stock_day: int = 0,
    reform_date: str = "2023-04-10",
) -> dict:
    """
    计算涨跌停价格

    Parameters
    ----------
    prev_close : float
        前一交易日收盘价
    board : str
        板块标识: 'main' / 'star' / 'gem' / 'bse'
    is_st : bool
        是否ST或*ST
    is_new_stock : bool
        是否新股
    new_stock_day : int
        新股上市第几天(0=首日)
    reform_date : str
        注册制改革日期

    Returns
    -------
    dict : {'upper_limit': float, 'lower_limit': float, 'limit_pct': float}
    """
    if is_st:
        limit_pct = 0.05
    elif board == "bse":
        limit_pct = 0.30
    elif board in ("star", "gem"):
        if is_new_stock and new_stock_day < 5:
            limit_pct = None  # 无涨跌停
        else:
            limit_pct = 0.20
    elif board == "main":
        if is_new_stock and new_stock_day == 0:
            limit_pct = None  # 注册制后首日无涨跌停
        else:
            limit_pct = 0.10
    else:
        limit_pct = 0.10

    if limit_pct is None:
        return {"upper_limit": None, "lower_limit": None, "limit_pct": None}

    # 四舍五入到分(0.01元)
    upper = round(prev_close * (1 + limit_pct), 2)
    lower = round(prev_close * (1 - limit_pct), 2)
    return {"upper_limit": upper, "lower_limit": lower, "limit_pct": limit_pct}

2.3 涨跌幅计算与除权除息修正

涨跌幅计算需使用前复权价格,以消除除权除息影响:

涨跌幅 = (当日收盘价 - 前复权前收盘价) / 前复权前收盘价 × 100%

3. 交易成本详细清单

3.1 费用项目汇总

费用类型 收取方向 费率 最低收费 备注
佣金 双向(买卖) 默认万2.5(0.025%) 5元/笔 可协商至万1或更低
印花税 单向(卖出) 千0.5(0.05%) 无 2023年8月28日起减半
过户费 双向(买卖) 十万分之1(0.001%) 无 2022年4月29日起调整
证管费 双向 万分之0.2(0.002%) 无 通常含在佣金中
经手费(沪) 双向 万分之0.341 无 通常含在佣金中
经手费(深) 双向 万分之0.487 无 通常含在佣金中

3.2 完整成本计算函数

def calc_trade_cost(
    price: float,
    volume: int,
    direction: str,
    commission_rate: float = 0.00025,
    min_commission: float = 5.0,
    stamp_tax_rate: float = 0.0005,
    transfer_fee_rate: float = 0.00001,
) -> dict:
    """
    计算A股单笔交易成本

    Parameters
    ----------
    price : float
        成交价格
    volume : int
        成交数量(股)
    direction : str
        交易方向: 'buy' / 'sell'
    commission_rate : float
        佣金费率,默认万2.5
    min_commission : float
        最低佣金,默认5元
    stamp_tax_rate : float
        印花税率,默认千0.5(2023年8月28日后)
    transfer_fee_rate : float
        过户费率,默认十万分之1(2022年4月29日后)

    Returns
    -------
    dict : 各项费用明细及总成本
    """
    turnover = price * volume  # 成交金额

    # 佣金(双向收取)
    commission = max(turnover * commission_rate, min_commission)

    # 印花税(仅卖出收取)
    stamp_tax = turnover * stamp_tax_rate if direction == "sell" else 0.0

    # 过户费(双向收取)
    transfer_fee = turnover * transfer_fee_rate

    # 总成本
    total_cost = commission + stamp_tax + transfer_fee

    return {
        "turnover": round(turnover, 2),
        "commission": round(commission, 2),
        "stamp_tax": round(stamp_tax, 2),
        "transfer_fee": round(transfer_fee, 2),
        "total_cost": round(total_cost, 2),
    }


def calc_round_trip_cost(
    buy_price: float,
    sell_price: float,
    volume: int,
    commission_rate: float = 0.00025,
    min_commission: float = 5.0,
) -> dict:
    """
    计算完整的一买一卖往返成本

    Parameters
    ----------
    buy_price : float
        买入价格
    sell_price : float
        卖出价格
    volume : int
        交易数量(股)
    commission_rate : float
        佣金费率
    min_commission : float
        最低佣金

    Returns
    -------
    dict : 买入成本、卖出成本及总成本
    """
    buy_cost = calc_trade_cost(buy_price, volume, "buy", commission_rate, min_commission)
    sell_cost = calc_trade_cost(sell_price, volume, "sell", commission_rate, min_commission)

    return {
        "buy_cost": buy_cost,
        "sell_cost": sell_cost,
        "total_cost": round(buy_cost["total_cost"] + sell_cost["total_cost"], 2),
        "cost_ratio": round(
            (buy_cost["total_cost"] + sell_cost["total_cost"]) / (buy_price * volume) * 100, 4
        ),
    }

3.3 融资融券利息

项目 费率 备注
融资利率 年化 6%-8% 按日计提,按季结算
融券费率 年化 8%-10% 因券源而异
def calc_margin_interest(
    principal: float,
    annual_rate: float,
    holding_days: int,
) -> float:
    """
    计算融资融券利息

    Parameters
    ----------
    principal : float
        融资/融券金额
    annual_rate : float
        年化利率(如0.06表示6%)
    holding_days : int
    持有天数

    Returns
    -------
    float : 利息费用
    """
    daily_rate = annual_rate / 360  # A股按360天计算
    interest = principal * daily_rate * holding_days
    return round(interest, 2)

4. 停牌规则

4.1 停牌类型

类型 触发条件 典型时长
例行停牌 定期报告披露(年报、半年报) 1个交易日
紧急停牌 重大资产重组、股权变动、异常波动 不定,数日至数月
监管停牌 信息披露违规、股价异常波动 视情节而定

4.2 停牌期间约束

  • 停牌期间无法进行买卖申报。
  • 持仓冻结,不可转出。
  • 停牌期间不计算涨跌幅。
  • 基金估值中停牌股票需使用估值价格。

4.3 复牌规则

  • 长期停牌复牌后,首日不设涨跌停限制的情况包括:
    • 停牌时间超过20个交易日的重大资产重组复牌。
    • 其他交易所认定的特殊情况。
  • 一般停牌复牌后仍适用正常涨跌停限制。

4.4 数据标记

def check_suspension(df: pd.DataFrame) -> pd.DataFrame:
    """
    标记停牌数据

    在行情数据中,停牌股票通常表现为:
    - 成交量为0
    - 开盘价=收盘价=最高价=最低价=前收盘价
    - 或数据源直接提供 is_suspended 字段

    Parameters
    ----------
    df : pd.DataFrame
        日线行情数据,需包含 open, high, low, close, volume 列

    Returns
    -------
    pd.DataFrame : 增加 is_suspended 列
    """
    df = df.copy()
    df["is_suspended"] = (
        (df["volume"] == 0)
        & (df["open"] == df["close"])
        & (df["high"] == df["low"])
        & (df["open"] == df["high"])
    )
    return df

5. 退市规则(2024年最新)

5.1 退市标准体系

5.1.1 交易类退市

指标 退市条件
面值退市 连续20个交易日每日收盘价低于1元
市值退市 连续20个交易日市值低于3亿元(主板)/ 5亿元(创业板)
成交量退市 连续120个交易日累计成交量低于500万股

5.1.2 财务类退市

指标 退市条件
利润+营收 最近一个会计年度净利润为负且营收低于1亿元
审计意见 最近一个会计年度被出具无法表示意见或否定意见的审计报告
净资产 最近一个会计年度净资产为负
营收扣除 扣除非主营收入后营收低于1亿元(2024年新规)

5.1.3 规范类退市

  • 信息披露重大违规。
  • 未在法定期限内披露年度报告或半年度报告。
  • 半数以上董事无法保证年报或半年报真实性。
  • 公司被控股股东及其关联方非经营性占用资金余额达到2亿元以上或占净资产30%以上。

5.1.4 重大违法退市

  • 欺诈发行。
  • 重大信息披露违法。
  • 涉及国家安全、公共安全等领域的重大违法行为。

5.2 退市整理期

  • 退市整理期:30个交易日。
  • 期间涨跌停限制为 ±10%(ST为±5%)。
  • 整理期届满后摘牌,转入全国中小企业股份转让系统(三板)。

5.3 ST/*ST 标记规则

def check_st_status(
    net_profit: float,
    revenue: float,
    audit_opinion: str,
    net_assets: float,
) -> str:
    """
    判断ST/*ST状态

    Parameters
    ----------
    net_profit : float
        最近年度净利润
    revenue : float
        最近年度营业收入(亿元)
    audit_opinion : str
        审计意见类型
    net_assets : float
        最近年度净资产

    Returns
    -------
    str : 'normal' / 'ST' / '*ST'
    """
    is_star = False  # *ST: 退市风险警示
    is_st = False    # ST: 其他风险警示

    # *ST 条件
    if net_profit < 0 and revenue < 1.0:
        is_star = True
    if audit_opinion in ("无法表示意见", "否定意见"):
        is_star = True
    if net_assets < 0:
        is_star = True

    # ST 条件(示例)
    if not is_star and audit_opinion == "保留意见":
        is_st = True

    if is_star:
        return "*ST"
    elif is_st:
        return "ST"
    else:
        return "normal"

6. 分红送转处理

6.1 除权除息日定义

  • 除权除息日(XR/DR/XD):在该日及之后买入的股票不再享有本次分红送转权利。
  • 股权登记日:除权除息日的前一交易日,收盘时持有该股票的投资者享有分红权利。
  • XR:除权(送股/转增),XD:除息(现金分红),DR:同时除权除息。

6.2 复权计算公式

前复权(Forward Adjustment)

以最新价格为基准,向前调整历史价格:

前复权价格 = 原始价格 × 复权因子

后复权(Backward Adjustment)

以最早价格为基准,向后调整当前价格:

后复权价格 = 原始价格 × 后复权因子

6.3 复权因子计算

def calc_adjust_factor(
    close: float,
    dividend: float = 0.0,
    bonus_share_ratio: float = 0.0,
    conversion_ratio: float = 0.0,
    rights_issue_price: float = 0.0,
    rights_issue_ratio: float = 0.0,
) -> float:
    """
    计算复权因子

    Parameters
    ----------
    close : float
        除权除息日前收盘价
    dividend : float
        每股现金分红(含税)
    bonus_share_ratio : float
        每股送股比例(如0.3表示每10股送3股)
    conversion_ratio : float
        每股转增比例(如0.5表示每10股转增5股)
    rights_issue_price : float
        配股价
    rights_issue_ratio : float
        每股配股比例

    Returns
    -------
    float : 复权因子
    """
    # 除权除息参考价
    total_shares = 1.0 + bonus_share_ratio + conversion_ratio + rights_issue_ratio
    ex_price = (close * (1 + bonus_share_ratio + conversion_ratio)
                - dividend + rights_issue_price * rights_issue_ratio) / total_shares

    # 前复权因子
    factor = ex_price / close
    return round(factor, 6)


def apply_forward_adjustment(
    df: pd.DataFrame,
    close_col: str = "close",
    factor_col: str = "adj_factor",
) -> pd.DataFrame:
    """
    应用前复权

    Parameters
    ----------
    df : pd.DataFrame
        行情数据
    close_col : str
        收盘价列名
    factor_col : str
        复权因子列名

    Returns
    -------
    pd.DataFrame : 增加前复权价格列
    """
    df = df.copy()
    # 累积复权因子
    df["cum_factor"] = df[factor_col].cumprod()
    df["adj_close"] = round(df[close_col] * df["cum_factor"], 3)
    return df

6.4 分红对持仓收益的影响

  • 现金分红:除息日股价会下调分红金额,但持仓市值减少的部分以现金形式返还,总资产不变(不考虑税)。
  • 分红税:持股超过1年免征;1个月至1年税率为10%;1个月以内税率为20%。
  • 送股/转增:股数增加,股价相应下调,总市值不变。
def calc_dividend_tax(
    dividend_per_share: float,
    holding_days: int,
    cost_per_share: float,
) -> float:
    """
    计算分红税

    Parameters
    ----------
    dividend_per_share : float
        每股分红金额
    holding_days : int
    持股天数
    cost_per_share : float
        每股成本

    Returns
    -------
    float : 分红税额
    """
    # 差额征税法:以持股成本为基准
    taxable_amount = max(dividend_per_share - cost_per_share * 0.05, 0)

    if holding_days > 365:
        tax_rate = 0.0
    elif holding_days > 30:
        tax_rate = 0.10
    else:
        tax_rate = 0.20

    return round(taxable_amount * tax_rate, 4)

7. 融资融券约束

7.1 两融标的范围

板块 标的要求
沪深主板 上市超过3个月,流通股本不低于1亿股或流通市值不低于5亿元
科创板 上市超过6个月,需满足特定流动性及市值要求
创业板 同科创板要求
北交所 暂未纳入融资融券标的

7.2 维保比例

def calc_maintenance_ratio(
    total_assets: float,
    total_liabilities: float,
) -> dict:
    """
    计算维保比例并判断状态

    Parameters
    ----------
    total_assets : float
        总资产(保证金+证券市值)
    total_liabilities : float
        总负债(融资买入额+融券卖出额+利息费用)

    Returns
    -------
    dict : 维保比例及状态
    """
    ratio = total_assets / total_liabilities if total_liabilities > 0 else float("inf")

    if ratio < 1.3:
        status = "danger"   # 低于130%,触发强制平仓
        action = "需追加保证金或自行平仓,否则券商强制平仓"
    elif ratio < 1.5:
        status = "warning"  # 低于150%,预警线
        action = "建议追加保证金或降低仓位"
    else:
        status = "safe"
        action = "正常"

    return {
        "maintenance_ratio": round(ratio, 4),
        "status": status,
        "action": action,
    }

7.3 融资利率与融券费率

项目 费率范围 计算方式
融资利率 年化 6%-8% 按日计提:利息 = 融资金额 × 年利率 / 360 × 天数
融券费率 年化 8%-10% 按日计提,部分券源费率更高

7.4 强制平仓规则

  • 平仓线:维保比例低于 130%,券商发出追加保证金通知。
  • 最低线:维保比例低于 110%(部分券商为115%),券商有权强制平仓。
  • 平仓顺序:优先平仓亏损头寸,其次平仓盈利头寸。
  • 平仓时间:T+1日(通知后次一交易日)执行。

8. 指数成分股变动

8.1 定期调整规则

指数 调整频率 审查周期 样本空间 纳入标准(核心)
沪深300 每半年 6月和12月 沪深两市非ST股票 按日均成交额和日均总市值排名
中证500 每半年 6月和12月 沪深两市非ST股票 剔除沪深300后按市值排名前500
中证1000 每半年 6月和12月 沪深两市非ST股票 剔除沪深300+中证500后按市值排名前1000

8.2 调整时间表

  • 审核截止日:每年5月和11月的最后一个交易日。
  • 生效日:每年6月和12月的第二个星期五的下一个交易日。
  • 缓冲规则:设置10%的缓冲区,排名靠前的10%新进入者优先替换排名靠后的10%原成分股,降低换手率。

8.3 临时调整规则

  • 退市处理:成分股被退市的,自退市日起从指数中剔除。
  • ST处理:被实施ST/*ST的股票,在下次定期调整时剔除。
  • 合并重组:吸收合并后存续公司若不符合指数纳入条件,予以剔除。

8.4 历史成分股数据获取

def get_index_constituents(
    index_code: str,
    date: str,
    source: str = "csindex",
) -> list:
    """
    获取指定日期的指数成分股列表

    Parameters
    ----------
    index_code : str
        指数代码,如 '000300'(沪深300)、'000905'(中证500)、'000852'(中证1000)
    date : str
        查询日期,格式 'YYYY-MM-DD'
    source : str
        数据源: 'csindex'(中证指数官网)、'tushare'、'akshare'

    Returns
    -------
    list : 成分股代码列表
    """
    if source == "akshare":
        import akshare as ak
        # 获取指数成分股
        df = ak.index_stock_cons(symbol=index_code)
        return df["品种代码"].tolist()
    elif source == "tushare":
        import tushare as ts
        pro = ts.pro_api()
        df = pro.index_weight(
            index_code=index_code,
            trade_date=date.replace("-", ""),
        )
        return df["con_code"].tolist()
    else:
        raise ValueError(f"不支持的数据源: {source}")


def get_index_changes(
    index_code: str,
    year: int,
    month: int,
) -> dict:
    """
    获取指数成分股调整信息

    Parameters
    ----------
    index_code : str
        指数代码
    year : int
        调整年份
    month : int
        调整月份(6或12)

    Returns
    -------
    dict : {'added': list, 'removed': list}
    """
    # 实际实现需调用中证指数公司API或数据源
    # 此处为示例框架
    import akshare as ak
    try:
        df = ak.index_stock_cons_change(symbol=index_code)
        # 按日期筛选调整记录
        target_month = f"{year}{month:02d}"
        changes = df[df["变更日期"].str.startswith(target_month)]
        added = changes[changes["变更类型"] == "纳入"]["品种代码"].tolist()
        removed = changes[changes["变更类型"] == "剔除"]["品种代码"].tolist()
        return {"added": added, "removed": removed}
    except Exception as e:
        print(f"获取成分股变动失败: {e}")
        return {"added": [], "removed": []}

附录:关键日期索引

事件 生效日期 影响
科创板设立 2019-07-22 涨跌停±20%
创业板注册制改革 2020-08-24 涨跌停±20%,新股前5日无限制
过户费下调 2022-04-29 万分之0.2 → 十万分之1
印花税减半 2023-08-28 千1 → 千0.5
主板全面注册制 2023-04-10 新股首日无涨跌停
退市新规完善 2024-04-12 新增市值退市、营收扣除退市等

注意:本文档中的规则基于截至2024年底的监管政策,后续如有政策调整需及时更新。所有费率均为参考值,实际费率以券商合同约定为准。回测系统中应将交易规则参数化配置,便于后续维护更新。

上述配置只作为个人学习参考示例,本文是作为本人技术学习记录,不代表本人投资建议,股市有风险投资需谨慎

这是一套完整的合集,上方的可以单独使用可以组合使用,使用方法,复制此行上方的完整信息,让trae帮你在本地生成一套完整的Skill,为了防止模型迷路我将完整的链接贴在下方。