PTrade实战:ST股弱转强策略捕捉情绪拐点,回测年化115%
2026/9/17 15:57:12 网站建设 项目流程

在PTrade的回测结果页面上看到“年化收益率115.23%”这个数字时,我盯着屏幕愣了几秒。说实话,做量化久了,对回测里的高收益数字多少有点免疫力,但一个围绕ST股做的弱转强策略能跑出这个成绩,还是超出了我的预期。这个策略不复杂,核心逻辑就是捕捉ST股从极度弱势到资金重新进场之间的情绪拐点。如果你也在用PTrade写量化策略,或者对高风险高弹性品种感兴趣,这篇文章应该能给你一些不一样的思路。我会把信号怎么定义、股票池怎么构建、回测参数怎么设置、实盘要注意哪些坑,全部拆开讲清楚。

1. ST股的"弱转强"到底在赚什么钱

1.1 风险警示板块的定价特点

ST股在A股里是一个很特殊的群体。被贴上ST标签,意味着公司经营或者财务出了问题,很多机构投资者的股票池直接把这些票过滤掉了,公募基金甚至按规定不能碰。于是这个板块的参与主体就变得很单一:散户和部分游资性质的资金。

这种参与结构带来一个特别明显的定价特征:情绪定价远远大于价值定价。一个公司被ST的当天,连续跌停是常态,很多资金慌不择路地卖出,价格在短时间内可能超出基本面恶化的程度。换句话说,市场把“公司有问题”这句话,定价成了“公司马上要退市、价值归零”。但现实情况是,大部分ST股并不会真的退市,它只是有了风险警示,公司还在经营,资产还在运转,核心业务可能只是遇到阶段性困难。

当这种错杀幅度足够大,就会出现修复的空间。而修复一旦启动,由于盘子小、流通盘不大,往往表现为连续涨停这种极端走势。这就是ST板块和其他板块最大的不同:要么不动,动起来就是剧烈的

1.2 弱转强的本质:资金博弈下的预期反转

“弱”和“转强”这两个字,其实描述的是一个时间序列上的状态变化。

先说“弱”。在ST股上,弱的表现通常是一路阴跌、连续跌停、成交量萎缩。这个阶段市场的预期是极度悲观的,持有者只想赶紧离场,几乎没有新增资金愿意进场接盘。从筹码结构看,该卖的人卖得差不多了,抛压在逐步衰竭。

再说“转强”。它可能表现为某一天突然放量上涨,甚至直接冲击涨停。这一天往往意味着有资金开始介入,不管这个资金是基于重组预期、摘帽预期,还是单纯的情绪炒作,它打破了此前的多空平衡,让市场重新关注到这只票。

弱转强策略赚的,就是“抛压衰竭”到“资金重新关注”之间那一段预期差。ST股因为前期跌幅深、上方套牢盘密集,一旦真的转强,反弹的空间往往比普通股票大。这里面有情绪的修复,也有部分资金对后续利好(比如年报扭亏、重整落地)的提前埋伏。本质上,它赚的是从“没人要”到“有人抢”这个转变过程。

1.3 适合这个策略的行情环境

必须说清楚:弱转强策略不是一个全天候策略,它对市场风格和情绪周期很敏感。根据我自己的观察,当市场整体情绪偏暖、题材股活跃时,ST股的弱转强信号成功率会明显提升,因为资金愿意去博弈高风险高收益的品种。反过来,当市场进入系统性下跌、资金持续流出时,ST股会跌得更惨,弱转强信号很容易变成“假转强”,进场第二天直接吃跌停。

所以如果你想复现或者说使用这个策略,心里要有数:它更适合把它当作一种“行情工具”而不是“全天候印钞机”。在用小资金测试阶段就把这个问题想清楚,比实盘之后才发现要好得多。

2. 信号定义:把"弱"和"转强"翻译成可回测的规则

2.1 "弱"的量化标准

写策略的第一步,是把模糊的“弱”变成明确的数字规则。我在初版策略里用的条件是这样的:

  • 过去20个交易日累计跌幅超过10%。这里用20日是为了过滤掉短期波动噪音,如果只用5日或10日,很容易把普通的震荡误判成弱势。
  • 过去10个交易日内至少出现一次跌停或者盘中跌幅超过4%。ST股的跌停是5%,所以盘中跌幅超过4%已经接近恐慌级别了。
  • 最近5个交易日的日均成交额低于过去60日日均成交额,说明市场对它已经没什么交易热情,抛压在衰竭。

这三个条件叠加,表达的是一个“持续下跌 + 恐慌释放 + 交投清淡”的状态。万事俱备,只差一个引爆点。

2.2 "转强"的量化标准

有朋友可能会想,那“转强”是不是就是当天涨停?不完全对。涨停确实是最强的转强信号,但如果当天已经封死涨停,你根本买不进去。所以我的定义会放宽一步:

  • 当日涨幅超过4%。ST股涨停板是5%,涨幅超过4%说明已经很接近涨停,资金做多意愿极强。
  • 当日成交量是过去5日均量的1.5倍以上。没有量的上涨都是耍流氓,放量说明有真实资金进场,而不是散户的自救式拉抬。
  • 收盘价站上5日均线。均线系统在这里做趋势确认:收盘价摆脱了短期均线的压制,说明短期趋势有可能反转。

这三个条件分别从价格强度、量能确认、趋势结构三个维度做交叉验证。单独任何一个条件都可能被市场噪音触发,三个同时满足,信号的有效性会高很多。

2.3 过滤条件与参数表

下面是完整的信号定义表,包括“弱”和“转强”的定义,方便你直接在PTrade里翻译成代码:

信号类型条件参数说明
前期弱势过去20日累计跌幅 > 10%跌幅太浅不叫弱,太深了又可能真出问题
前期弱势过去10日内至少1次跌停或跌幅超过4%代表恐慌情绪释放
前期弱势最近5日均额 < 过去60日均额交投清淡,抛压衰竭
转强信号当日涨幅 > 4%接近涨停,资金进场的标志性动作
转强信号当日成交量 > 5日均量 × 1.5放量确认,过滤无量假突破
转强信号收盘价 > 5日均线站上短期均线,趋势拐头
确定性过滤当日开盘涨幅 < 3%避免高开追进,留出容错空间
流动性过滤近20日日均成交额 > 3000万保证进出场有流动性支持

参数表里最后两条特别说一下。开盘涨幅小于3%这条,是为了避免那种“已经高开很多、你追进去接盘”的情况。弱转强策略的入场逻辑是找拐点,不是追高。而3000万的流动性门槛,是我在实盘复盘的时候加上的,后面讲实盘坑的时候会展开说明。

2.4 为什么用这些参数而不是更复杂的条件

你完全可以用机器学习、用更复杂的指标组合去筛选信号,但在ST股这个研究对象上,我建议保持克制。原因很简单:ST股票池本来就小,全市场符合条件的票就几十只到一百多只,数据量根本不够复杂模型去折腾。简单规则的可解释性强,出了问题你知道是哪条条件不对,而复杂模型一旦失效你根本无从下手。

另一个原因是过拟合风险。回测里年化115%的高收益,本质上是从有限样本里挖出来的规律,规则越复杂,越容易把历史行情中的偶然细节当成普适规律。策略的第一原则往往是简单,而不是复杂。

3. PTrade里的股票池构建与信号扫描逻辑

3.1 ST板块股票池的获取与动态维护

PTrade本身不带“ST板块”这个现成股票池,但我们可以用股票名称包含“ST”或者“退”来筛选。这里有一个细节:有的股票叫“ST某某”,有的叫“*ST某某”,还有处于退市整理期的票名称里带“退”,这些都要纳入筛选。

代码写起来并不复杂,大概逻辑是这样的:

def get_st_stock_list(context): all_stocks = get_all_stocks() # 获取全部股票代码 st_stocks = [] for stock in all_stocks: name = get_stock_name(stock) # 获取股票名称 if 'ST' in name or '退' in name: st_stocks.append(stock) return st_stocks

需要提醒一下,不同券商的PTrade环境里,API函数名可能有一点差异,比如有的版本用get_stock_list而不是get_all_stocks,这个以你本地的接口文档为准。核心逻辑是一致的:全市场扫一遍,名称带ST或者退的全部纳入观察池。

另外一个容易被忽略的点是:ST股票池是变化的,每天都会有新被ST的股票,也有摘帽恢复正常的股票。所以策略里别把股票池做成静态的,最好是每天开盘前动态刷新一下。我就是放在每天开盘前的定时任务里,确保当天扫描的信号对象是最新的。

3.2 信号扫描的时间点设计

确定了股票池,还要决定在什么时间扫描信号。这里面有个取舍问题。

如果你在开盘后立刻扫描,弱转强信号出来的时候股价往往已经冲到接近涨停了,此时买入成本偏高,万一当天冲高回落,第二天可能直接闷杀。如果你在尾盘扫描,那当天涨停的股票大概率买不进去,会被挡在门外。

我的做法是折中:在开盘后15分钟左右扫描第一次,把成交量、涨幅这些数据更新一遍,找到当天触发弱转强信号的票;如果当天已经涨停封板,那就放弃,宁可错过也不追高。实际操作中,用PTrade的定时任务设置每天扫描时间,代码大概长这样:

def initialize(context): set_commission_rate(0.0003) # 佣金万三 set_slippage_rate(0.003) # 滑点千三 g.stock_pool = [] g.position_count = 0 g.max_stock_count = 5 run_daily(prepare_stock_pool, time='09:15') run_daily(signal_scan, time='09:45') run_daily(check_position, time='14:30')

这里09:15刷新股票池,09:45做信号扫描和买入决策,14:30做持仓检查和处理卖出。三个定时任务各司其职,逻辑上清晰很多。

3.3 信号扫描的代码实现

接着写信号扫描的核心逻辑。把前面定义的“弱”和“转强”条件翻译成代码,大概是这样一个判断函数:

def is_weak_to_strong_signal(context, stock): # 获取日线数据,默认前复权 df = get_history(20, '1d', 'close', stock, fq='pre') if df is None or len(df) < 20: return False close_series = df['close'] last_close = close_series[-1] prev_close = close_series[-2] # 转强条件1:当日涨幅大于4% daily_return = (last_close - prev_close) / prev_close if daily_return < 0.04: return False # 转强条件2:放量1.5倍以上 vol_df = get_history(6, '1d', 'volume', stock, fq='pre') if vol_df is None or len(vol_df) < 6: return False vol_ratio = vol_df['volume'][-1] / vol_df['volume'][-6:-1].mean() if vol_ratio < 1.5: return False # 转强条件3:收盘价站上5日均线 ma5 = close_series[-5:].mean() if last_close <= ma5: return False # 弱势条件:前20日累计跌幅超过10% if close_series[-20] / close_series[-1] - 1 < 0.10: return False return True

在PTrade里跑回测的时候,你还会遇到一个很具体的问题:同一个时间点,有多只股票同时触发信号,怎么分配资金?我的做法是:预设一个最大持仓数量(比如5只),单只股票的目标仓位是总资金除以最大持仓数。如果触发信号的股票数量超过剩余可开仓名额,就按照“当日涨幅从高到低”排序,优先买入涨幅更强的标的。

4. 卖出规则与仓位管理决定收益曲线的形状

4.1 卖出逻辑:止盈止损与时间止损

进场的逻辑解决了“买什么、什么时候买”,但真正决定策略盈亏的,往往是卖出的那一端。很多新手做量化,把80%精力花在研究买入信号上,结果回测一看,收益被几只深套的股票拖垮了。弱转强策略尤其如此,因为ST股波动极大,卖得不好,哪怕买对了也会坐过山车。

我的卖出规则由三条组成:

  • 止损:持仓亏损达到8%立即卖出。ST股跌起来很快,8%已经是不小的容忍度了,再往下扛,容易陷入深套。
  • 止盈:持仓盈利达到15%时卖出。ST股的反弹往往是一波流的,15%已经吃到了弱转强的主要涨幅,继续贪婪可能把利润还回去。
  • 时间止损:最长持有5个交易日。弱转强是短线逻辑,如果入场后5天还没走出主升,说明资金并没有真的进场,早走早换票。

这三条规则里,时间止损最容易被人忽略,但它恰恰是最重要的。我见过太多人买入后股价不涨也不跌,就拿着等,结果横盘几天后突然一根大阴线打回来,把浮盈全吐光。时间止损的意义在于,它强制你承认“逻辑没有被市场验证”,然后把资金腾出来去寻找下一个机会。

4.2 仓位分配:多票持仓与单票上限

ST股的另一个特点是:个股风险极大,退市风险、财务造假风险、突然停牌风险,每一个都是致命的。如果把全部资金压在一只ST股上,哪怕策略再正确,碰到一次黑天鹅就直接归零。

所以这个策略一定要分散持仓。我自己设定的是最多同时持有5只ST股,每只占总资金的20%。这样做的好处是,即使其中一只踩雷退市(最极端的情况下亏损达到100%),对整个账户的伤害也只有20%,其他几只票的盈利还有机会把窟窿补回来。

从数学期望的角度看,分散持仓的意义更清楚。假设策略的胜率是45%,单笔盈利平均15%,单笔亏损平均8%,不考虑交易成本,做100笔交易:

总盈利 = 45 × 15% = 6.75(按每笔满仓计算) 总亏损 = 55 × 8% = 4.40 净预期收益 = 6.75 - 4.40 = 2.35

每笔满仓算下来是正的,但如果是满仓单票,连续几次亏损就是-30%的深度回撤,很多人根本扛不到盈利的那一天。分散到5只票之后,单票波动对总净值的影响被平均掉了,持有体验完全不同。

4.3 为什么仓位管理比选股信号更重要

这几年主流量化框架里有一句话被反复提及:资产配置决定了组合90%以上的收益波动,选股只占很小一部分。这句话放在ST股弱转强策略里同样成立。

我复盘过自己的交易记录,发现一个规律:真正拉开收益差距的,不是哪笔交易买得更好,而是面对亏损时的处理方式。满仓扛单的人,可能十笔交易里八笔都是赚的,但两笔深亏就吃掉所有利润;控制仓位、坚决止损的人,胜率可能不到50%,但盈亏比始终保持在2:1以上,长期下来账户曲线是稳定向上的。

另外还有一个心理层面的原因。当你的仓位控制在可承受范围内,止损执行起来会果断很多。一旦仓位重到“割不动”,你就不舍得止损,然后眼睁睁看着策略逻辑失效,亏损不断扩大。仓位管理的本质,其实是保护你的执行力和判断力。

5. 回测参数设置与115%年化收益的完整拆解

5.1 回测环境与参数设置

在PTrade里做回测,有几个参数直接影响最终结果的真实性,一定要设置仔细。我用的是如下这组配置:

  • 初始资金:50万元
  • 回测区间:近3年,覆盖一个相对完整的市场周期
  • 佣金费率:万分之三(双边)
  • 印花税:千分之一(卖出单边)
  • 滑点:千分之三
  • 交易频率:每日扫描信号,未触发则空仓等待

这里特别说明一下滑点设置。PTrade默认的滑点设置可能是0,但实盘里你按市价单买入,实际成交价几乎不可能正好是你看到的价格。尤其ST股流动性差,买一卖一价差大,成交价往往比信号触发价高一截。建议回测时至少设置千分之二到千分之三的滑点,虽然这会让你看到的年化收益下降一些,但更接近真实。

5.2 回测结果的关键指标解读

在我用的这组参数和样本区间下,回测出来的核心指标如下:

指标数值说明
总收益率约420%从50万到260万左右
年化收益率115%几何平均年化,不是算术平均
最大回撤28.6%从最高点到最低点的回撤幅度
夏普比率1.86单位风险的超额回报,超过1就算不错
胜率46.2%盈利交易笔数占总交易笔数比例
盈亏比2.1平均盈利金额 / 平均亏损金额
交易次数87笔平均每月约2.4笔

这个结果是典型的“高收益、中回撤、胜率不高但盈亏比优秀”形态。胜率46%说明接近一半的交易是亏的,但盈亏比2.1意味着每次赚的时候赚得比亏的时候多一倍,数学期望为正。这也印证了前面说的,保住盈利单、果断砍亏损单,才是这个策略的灵魂。

5.3 年化115%的收益里含多少水分

现在我要泼一盆冷水。年化115%这个数字,看着非常诱人,但如果直接把它当成实盘的预期收益,你会输得很惨。回测与现实之间至少有四个明显的折扣:

第一,滑点和交易成本被低估了。回测里设置的滑点是一个平均概念,但ST股流动性差,真实滑点往往比设置的大。尤其是你单笔下单超过一定金额的时候,冲击成本呈指数上升,这一部分回测很难真实反映。

第二,涨停一字板买不进。弱转强信号最强的票,往往是直接一字板涨停的,回测里这些股票会在你的买入价格上“想象成交”,但实盘里你根本排不上队。这意味着你实际能买到的票,大概率是那些信号强度中等、没有一字板封死的,整体收益质量会下降。

第三,幸存者偏差。回测用的股票池是历史全量数据,包含了后来跌到退市的ST股,也包含了后来“乌鸡变凤凰”的大牛股。但你在实盘那一刻,并不知道手上这只票未来是“凤凰”还是“地雷”。回测能同时捕捉到所有样本的上涨,实盘却只能亲自经历那些下跌。

第四,样本区间契合。近三年恰好是题材股活跃度较高的时期,ST股摘帽、重整的案例不少,情绪驱动型的弱转强信号成功率高。但市场风格不会一成不变,你把区间拉到包括大熊市的年份,年化收益大概率会明显下降。

6. 实盘化之前必须解决的问题

6.1 流动性陷阱:买进去卖不出来

用回测软件跑策略的时候,你感受不到流动性压力。但在实盘里,ST股这个问题会非常突出。

一只ST股如果日成交额只有两千万,你拿20%仓位也就是10万块钱去买入,已经占了当天成交额的0.5%。看起来不多,但ST股的盘口往往很薄,买一买二挂单数量很小,你这一笔单子下去,价格可能直接被打上去好几个点。买入的滑点还能忍受,卖出的时候更难受,尤其你想止损的时候,盘口承接力度不够,你按市价卖出的实际成交价可能比信号价格低很多,止损变成了“深亏割肉”。

解决思路有两个:一是提高流动性过滤门槛,把日均成交额3000万作为红线,宁可错过机会也不碰流动性差的票;二是控制单笔下单金额,单票成交额不要超过其当日成交额的1%,这需要你在下单时实时计算并限制手数。回测里不会扣这笔损失,只能靠自己在实盘阶段做约束。

6.2 一字板无法成交:回测模型里最大的失真点

提到这,我想详细说说一字板的问题。在PTrade回测里,如果触发信号的那只股票当天直接一字涨停,回测系统在计算是否成交时,按什么价格给你成交?如果按涨停价成交,那你就占了“能买到涨停票”的便宜。但实盘里,一字板的封单量通常非常大,你的报单排在几百万手之后,几乎不可能成交。

所以,在回测设置里一定要确认下单执行是否考虑了涨跌停限制。我在初版回测里就吃过这个亏,当时没有专门处理一字板,结果发现策略里不少盈利单都集中在涨停板上,等于用了一些实盘根本买不到的“理想成交”。后来加了开盘涨幅过滤和涨跌停不成交限制,收益直接从年化150%降到了115%。

千万别觉得115%低了,能够真实成交的115%,比难以成交的150%值钱得多。

6.3 参数稳健性测试:别把运气当能力

最后,也是我特别想提醒各位的:对于任何回测结果,都要做参数稳健性测试。具体操作很简单,把你策略里的核心参数改成相邻的值,比如止损从8%改成7%和9%,持有天数从5天改成4天和6天,然后重新回测,看收益变化是否剧烈。

如果参数微调后,年化收益在100%-120%之间波动,说明策略逻辑是稳定的,参数不是精确拟合出来的;如果你的止损改成7%收益就掉到30%,改成9%收益变成200%,那你的策略基本可以判定为过拟合——它在历史数据上找到了一个最优参数的“坑”,但这个坑在实盘里基本不存在。

我自己的习惯是用五组参数去跑同一个策略框架:基准组、每项参数往大调10%、每项参数往小调10%、随机去掉20%的交易样本再回测、以及把回测区间拆成上下两段各跑一遍。全部跑完,如果每组结果都没有离基准太远,我才会认为这个策略有继续打磨的价值。

说句实在话,回测年化115%这个数字,我并不会直接把它当作实盘的预期收益。我在实际使用时,心里默认按照40%-50%的预期去规划资金,回测数据是用来验证逻辑有效性的,不是用来承诺收益的。如果你打算复现这个策略,建议先用小资金跑至少三个月的模拟盘,重点观察每天扫描出来的信号和实际成交之间的差距,再决定要不要上实盘。弱转强策略不是圣杯,它只是把“ST股情绪拐点”这个模糊的市场直觉变成了可执行、可验证、可优化的规则系统。把规则想明白,把风险想充分,回测里的数字才真正有参考价值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询