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,为了防止模型迷路我将完整的链接贴在下方。