date: 2026-06-02 updated: 2026-06-02 conversation_id: 4968cd4d-bcd1-4f19-9805-71ca574c6720 title: "股票池动态持仓计算逻辑" tags: [deepseek, conversation] ---
股票池动态持仓计算逻辑
创建时间: 2026-06-02 09:48
👤 用户:
我是个证券产品经理,需要做一个股票池的功能,只管每日更新股票池持仓情况,数量是不固定的,按照股票池动态平均持仓,计算收益率、胜率、净值等数值的逻辑应该如何定
💭 思考过程
嗯,用户是证券产品经理,需要设计一个股票池功能。核心需求是“每日更新股票池持仓情况”,并且是“动态平均持仓”,数量不固定。需要计算收益率、胜率、净值等指标。我需要从产品逻辑和金融计算角度给出建议。
首先理解场景:用户管理一个股票池,每天池子里的股票和持仓数量可能变化,而且是“动态平均持仓”。这个词可能意味着对池内所有股票进行等权重或按某种规则分配资金,并且每天会根据池子变化调整?需要明确。常见的“股票池”功能有两种:一种是模拟组合,每天根据选股规则更新成分股,然后对每个成分股分配相同资金(平均持仓);另一种是信号驱动,每天换仓。用户提到“只管每日更新股票池持仓情况”,说明每天可以知道池子里有哪些股票、每只股票持有多少股或者权重。数量不固定,所以需要动态分配资金。
核心计算逻辑:收益率、胜率、净值。这些是绩效评估指标。
- 净值:需要定义初始净值(通常为1)。每日净值 = 前一日净值 * (1 + 当日收益率)。所以关键在于计算当日收益率。
- 当日收益率:因为每日更新持仓,可能当天收盘后更新新的股票池,第二天开盘按新池子操作?或者当天收盘后立即调仓?需要明确时间点。常见做法:假设T日收盘后确定T+1日的持仓(股票池及权重),然后T+1日按照该持仓持有至收盘,计算T+1日收益率。或者更简单:每天记录收盘后的持仓市值,根据总市值变化计算日收益率。用户说“每日更新股票池持仓情况”,可能意味着每天收盘后得到新的持仓列表,那么当天收益率应该基于当天持仓的涨跌来计算?但注意:如果当天调仓,调仓前和调仓后持仓不同,收益率计算需要考虑交易成本和时间点。简化起见,可以假设每日调仓在收盘前完成,或者采用“每日再平衡”模型:每天开盘时以等权重买入股票池所有股票,持有至收盘卖出,计算日收益。但实际中更合理的是:每天记录收盘后的持仓(假设这是当天收盘时的实际持仓),那么当天的收益率 = (当天收盘总市值 - 前一天收盘总市值) / 前一天收盘总市值。但这样要求知道前一天收盘时持有的股票,而用户每天更新持仓,可能持仓会变。所以需要定义清楚。
建议采用“基于每日收盘持仓的日收益率”计算:假设每天收盘后可以得知当天该股票池的持仓情况(每只股票持有数量或市值权重)。那么当天的总资产 = sum(股票数量 当日收盘价)。前一天的收盘总资产 = sum(前一天持仓数量 前一日收盘价)。但注意如果持仓股票变化,直接相减会包含调仓带来的资金流动。为了准确反映投资表现,通常使用“时间加权收益率”,即假设每天调仓在收盘后进行,那么当天的收益率应当基于当天的持仓从开盘到收盘的涨跌。但由于不知道开盘价,更常见的做法是:假设每天收盘后根据新股票池进行再平衡,那么T日的收益率 = (T日收盘总市值) / (T日开盘总市值) - 1,而T日开盘总市值 = 根据T-1日收盘后的持仓(即T日开盘时的持仓)来计算。用户每日更新股票池,可以认为T-1日收盘后决定了T日的股票池和权重,那么T日开盘时按照该权重买入,持有至T日收盘,计算收益率。这样就需要记录两天的数据。
简化:对于产品MVP,可以假设用户每天提供当日的持仓列表(包括每只股票的成本价或持有数量),那么可以计算当日持仓的总市值,然后与前一日的总市值比较,但要注意如果调仓,这种比较会因资金进出而失真。更合理的是使用“每日收益率” = (当日持仓总市值 - 当日持仓的总成本) / 当日持仓的总成本?不,那是累计盈亏。
其实对于股票池模拟,常见做法是:设初始资金为C0,每天根据股票池进行等权重再平衡。每天收益率 = 所有股票当日涨跌幅的等权平均。因为动态平均持仓意味着每个股票分配相同资金。然后净值 = 初始净值 (1+日收益率1)(1+日收益率2)...。这个最简单,也符合“平均持仓”概念。用户说“按照股票池动态平均持仓”,可以理解为每个交易日,对股票池中的所有股票,分配等额资金(比如各占1/N)。那么每日收益率 = (1/N) sum(每只股票当日收益率)。其中每只股票当日收益率 = (收盘价 - 前收盘) / 前收盘。这样计算不需要知道具体股数,只需要股票列表和每日价格。非常干净。
胜率:通常指所有交易日中,收益率为正的比例。或者对于交易策略,也可指盈利交易次数占比。这里建议定义为:日胜率 = 日收益率>0的天数 / 总天数。也可以定义股票级别的胜率,比如每只股票被纳入池子期间上涨的天数占比,但用户可能只关心组合整体。
收益率:需要累计收益率和年化收益率。累计收益率 = 最终净值 - 1。年化收益率 = (最终净值)^(250/交易天数) - 1(假设一年250个交易日)。
净值:每日净值序列如上计算。
另外可能需要考虑最大回撤、夏普比率等,但用户只问了收益率、胜率、净值,可以先给出这些。
需要注意:动态平均持仓如何处理调仓?如果每天股票池数量变化,等权重分配会自然调整。例如今天有3只,各33.33%;明天新增一只变成4只,那么明天各25%。不需要额外处理,因为每天重新平衡。这相当于一个每日再平衡的等权组合。
还需要考虑交易成本?如果只用于展示绩效,可以暂时忽略,后续再迭代。
所以给用户的建议:定义清楚时间点,采用每日等权重再平衡模型,日收益率 = 池内股票当日涨跌幅的算术平均,净值递推。胜率 = 日收益率>0的天数占比。收益率可展示累计和年化。此外可以展示总资产曲线。
还需要考虑股票池更新的具体逻辑:用户每日提供股票代码列表,系统需要获取每个股票的前后收盘价。需要历史价格数据。
作为产品经理,还需要考虑数据源、计算频率、前端展示图表等。
最终回答应该清晰、有条理,给出计算逻辑的定义、公式、注意事项,并建议一些扩展指标。
作为证券产品经理,设计“动态平均持仓”的股票池功能时,核心挑战在于:股票数量每日变化,但希望每个交易日对池内所有股票保持“平均”的资金分配(例如等权重)。以下是一套清晰、可落地的计算逻辑,涵盖收益率、胜率、净值等关键指标。
一、核心假设与模型选择
采用“每日再平衡的等权组合”模型
- 每个交易日收盘后,根据当日最新的股票池名单,下一个交易日开盘时将总资金等额分配到池内每只股票。
- 当日收益率 = 池内所有股票当日涨跌幅的简单算术平均(因为每只股票权重相等)。
- 优点:无需处理复杂权重变化,天然适应股票数量动态变化,计算简单透明。
二、关键指标计算逻辑
1. 每日收益率(R_t)
- 公式:
\( Rt = \frac{1}{Nt} \sum{i=1}^{Nt} r{i,t} \) 其中 \( Nt \) 为 t 日股票池内股票数量,\( r_{i,t} \) 为股票 i 在 t 日的收益率(通常用复权收盘价计算)。
- 数据依赖:需要每个交易日池内各股票的前后收盘价。
2. 净值曲线(NAV_t)
- 公式:
\( NAVt = NAV{t-1} \times (1 + Rt) \) 初始净值 \( NAV0 = 1 \)(或 1000)。
- 说明:假设无交易成本、无现金留存,每日再平衡在开盘瞬间完成。
3. 累计收益率(Total Return)
- 公式:
\( TotalReturn = \frac{NAVT}{NAV0} - 1 = NAV_T - 1 \)
- 也可计算年化收益率:
\( AnnualizedReturn = (1 + TotalReturn)^{\frac{250}{T}} - 1 \)(假设一年250个交易日,T为实际交易天数)
4. 胜率(Win Rate)
提供两种视角,根据产品需求选择:
| 类型 | 计算方式 | 适用场景 |
|---|---|---|
| 日胜率 | 统计期间内 \( R_t > 0 \) 的天数 / 总交易天数 | 衡量策略日常稳定性 |
| 个股胜率 | 统计每只股票在纳入池子期间,上涨交易日占比,再对全样本平均 | 衡量选股质量 |
建议优先使用日胜率,与净值、回撤等组合指标更匹配。
5. 其他常用风控指标(可选)
- 最大回撤:\( MDD = \max{t} \left( \frac{NAVt - \max{s \le t} NAVs}{\max{s \le t} NAVs} \right) \)
- 夏普比率:\( \frac{平均(Rt) - Rf}{\sigma(Rt)} \)(\( Rf \) 可用无风险利率,如年化2%折算为日)
三、动态平均持仓的具体落地细节
场景示例
- 股票池在 T-1 日收盘后更新为 [A, B, C](3只)
- 总资金 = 1,000,000 元
- T 日开盘等权买入:每只股票分配 333,333 元
- T 日收盘,计算 A、B、C 当日收益率,算术平均得 R_t
- T 日收盘后,总资金变为 \( 1,000,000 \times (1+R_t) \)
- 若 T 日收盘后股票池变为 [A, C, D](3只,B换成D)
T+1 日开盘按新池子等权分配(基于最新总资金),继续计算。
关键处理规则
- 换股造成的资金流转:视为在收盘后瞬间卖出旧股票、买入新股票,不影响当日收益率(因为当日收益率已基于开盘持仓锁定)。
- 停牌股票:建议当日收益率记为 0,且仍占用权重(停牌期间无法交易,等权持有是合理假设)。
- 涨跌停无法买入/卖出:初期可忽略,进阶版可加入“次日无法开盘价成交则顺延”的逻辑。
四、产品实现建议(给开发团队)
数据表结构示例
| 日期 | 股票代码 | 复权收盘价 | 当日收益率 | 池子内股票数 |
|---|---|---|---|---|
| 2025-01-02 | 000001 | 10.5 | 0.02 | 3 |
| 2025-01-02 | 000002 | 20.0 | -0.01 | 3 |
| 2025-01-02 | 000003 | 15.0 | 0.01 | 3 |
每日聚合计算表:
| 日期 | 组合日收益率 | 累计净值 | 日胜率(滚动) | 最大回撤 |
|---|---|---|---|---|
| 2025-01-02 | 0.00667 | 1.00667 | 100% | 0% |
计算调度
- 每天收盘后(如15:30)触发任务:
- 获取当日最新股票池名单
- 获取池内所有股票当日复权收盘价
- 计算每只股票当日收益率
- 算术平均得到组合日收益率
- 更新净值、胜率等衍生指标
- 存储结果供前端展示
五、用户界面展示建议
- 曲线图:净值曲线 + 基准(如沪深300)对比
- 卡片指标:年化收益率、累计收益率、日胜率、最大回撤、当前池内股票数量
- 每日明细表:支持点击某一天,展示当天股票池名单及各股票涨跌贡献
- 胜率日历:用绿色/红色格子展示每日盈亏,直观感受胜率分布
六、常见问题 FAQ
Q:为什么不用加权平均(如按市值)? A:你明确要求“动态平均持仓”,等权是语义最匹配的。如果需要市值加权,可做成第二种模式让用户切换。
Q:每日再平衡是否过于频繁,与“仅更新持仓情况”矛盾? A:不矛盾。“每日更新持仓”可理解为:系统假设用户每天都会按照新池子调仓到等权。若用户实际调仓频率较低,则需改为“调仓日再平衡”模型,但计算会更复杂。
Q:如何避免日内价格计算的幸存者偏差? A:必须使用当时已知的股票池,不能事后纳入当日涨停的股票。每日股票池应基于前一个交易日收盘后的信息确定。
如果需要,我可以进一步提供伪代码、SQL示例或Excel模拟模板,帮助你快速验证这套逻辑。
👤 用户:
需要考虑盘中某个时刻对单个股票的增删情况处理
💭 思考过程
我们考虑用户作为证券产品经理,需要设计股票池功能,每日更新持仓,但要求“动态平均持仓”,现在进一步要求:需要考虑盘中某个时刻对单个股票的增删情况处理。这意味着股票池不是仅在每日收盘后变化,而是可能在盘中动态增删股票。那么对于收益率、净值、胜率等计算逻辑需要适应这种实时变化。
我们需要给出一个清晰的处理逻辑。主要挑战:资金分配如何调整?是立即调仓还是按规则延迟?收益率如何计算?胜率如何定义?需要给出合理且可落地的方案。
我将从几个层面回答:
- 核心原则:明确盘中增删的处理机制(立即再平衡 vs 日终再平衡 vs 分段计算)
- 推荐方案:采用“实时等权 + 触发式再平衡”或“累积单位净值法”
- 具体计算逻辑:盘中增删时刻对持仓权重、资金、收益率的影响
- 胜率、净值等指标如何连续计算
- 产品实现建议
注意用户说“只管每日更新股票池持仓情况”,但增加了盘中增删场景,所以需要兼顾。
针对“盘中某个时刻动态增删股票”的需求,原有的“每日再平衡”模型就不够用了。你需要一个支持实时调整持仓权重、并能连续计算收益率与净值的逻辑。核心难点在于:盘中增删股票时,资金需要立即重新平均分配,但日内多次调仓会导致收益率计算碎片化。
下面给出一个可落地、逻辑清晰的方案:“实时事件驱动 + 分段收益率连乘”。
一、总体原则
- 股票池是实时状态:任何时候(盘中某个时刻)用户增/删一只股票,股票池即变化。
- 资金始终保持等权分配:每次股票池变化时,立即将当前总资金等额分配到池内每只股票(实时再平衡)。
- 收益率按“事件段”计算:两次股票池变更之间视为一个“持有段”,段内持仓不变,段内收益率等于段内所有股票涨跌幅的算术平均。全天净值为各段收益率连乘。
- 不做高频碎股模拟:假设可无限分割资金,不计交易费用,且盘中调仓可以瞬间按当前价成交。
二、盘中增删时的具体处理流程
1. 定义事件点
- 初始:开盘时股票池为
List_A,总资金M0。 - 盘中任一时刻
t1,用户执行“新增股票X” 或 “删除股票Y” → 触发一次再平衡事件。
2. 事件发生时计算流程
假设在 t1 时刻,当前股票池为 [S1, S2, ..., Sk],总资金为 M(t1-)(事件前瞬间)。
第一步:计算从上一个事件到 t1 的段收益率
- 记录上一个事件发生时刻(或开盘时刻)为
t0。 - 获取
t0到t1期间每只股票的收益率: - 若
t0为开盘,用开盘价至t1时刻价格; - 若
t0为上一次再平衡时刻,用当时再平衡成交价(假设事件发生时瞬间按当时市价成交,即再平衡价同时也是新段起点价)。 - 段收益率 \( R{segment} = \frac{1}{k} \sum{i=1}^{k} r_i^{(t0\to t1)} \)
- 段内净值变化: \( M(t1-) = M(t0) \times (1 + R_{segment}) \)
第二步:执行股票池变更与资金再平衡
- 新股票池
List_B(例如新增一只股票,或移除一只)。 - 计算新池子数量
m。 - 将当前总资金
M(t1-)等额分配到m只股票,每只分配M(t1-)/m。 - 注意:对于被删除的股票,在
t1时刻立即卖出(按当前价),所得现金加入资金池一起重分;对于保留的股票,调整其持仓数量至新的目标金额(多退少补)。 - 再平衡完成后,新段开始,持仓金额 = 每只
M(t1-)/m,起点价格为t1时刻市价。
第三步:记录事件日志
- 记录事件时间、股票池变化、再平衡价格、段收益率等,用于后续计算与对账。
3. 收盘后处理
- 如果最后一笔事件后到收盘无新事件,则计算从最后一个事件时刻至收盘的段收益率。
- 全天净值 = 各段 (1+R_i) 连乘。
- 全天组合收益率 = 全天净值 - 1。
三、关键指标的计算公式(适应盘中增删)
1. 每日收益率(R_day)
- 公式:
\( R{day} = \prod{j=1}^{J} (1 + R_{segment,j}) - 1 \) 其中 \( J \) 为当日事件段数(含开盘至第一个事件、事件之间、最后一个事件至收盘)。
- 替代简便公式(如果认为盘中再平衡价格公允):直接用“收盘时总资金 / 开盘时总资金 - 1” 也可,但会丢失中间调仓细节。推荐用分段连乘法。
2. 净值(NAV_t)
- 按日更新: \( NAVt = NAV{t-1} \times (1 + R_{day}) \)
- 如果产品需要日内实时净值,则可在每个事件段后实时计算净值并推送。
3. 胜率
- 日胜率:仍按交易日计算,若 \( R_{day} > 0 \) 则该日胜。
- 个股胜率:注意因为盘中可能增删,某只股票可能只持有了部分时间。建议采用 “持有期日涨跌幅统计”:对于每只股票,取它实际被持有的那些交易日(不区分盘中介入退出时间),计算其日收益率 > 0 的比例。更精细的做法是计算“个股对组合贡献为正的天数占比”。
4. 最大回撤
- 基于分钟级或事件级净值序列计算:回撤 = (当前净值 - 历史最高净值)/历史最高净值。因为盘中可能再平衡导致净值跳跃,但回撤仍按真实净值曲线计算,无需特殊处理。
5. 年化收益率 / 夏普比率
- 年化收益率:基于日净值计算(与标准方法一致)。
- 夏普比率:使用日收益率序列计算(因为盘中再平衡的交易成本未计入,可先忽略)。
四、产品实现的关键设计
1. 数据模型
需要记录:
- 事件表:
日期,事件时间(毫秒),事件类型(新增/删除),股票代码,操作价格,再平衡后股票池快照 - 持仓快照表:每个事件后的每只股票的持仓数量、成本价(用于核算盈亏)
- 段收益表:每个事件段的起止时间、起始净值、结束净值、段内收益率
2. 实时计算引擎
- 监听股票池变更动作(用户通过界面增删)。
- 获取当前所有持仓股票的最新价格(从行情接口)。
- 执行段收益率计算、资金再平衡逻辑。
- 更新实时净值,并推送前端。
3. 对历史数据回测的支持
- 若需回测历史某天的盘中增删序列,需要当时时刻的价格数据(分钟级或Tick级)。一般回测时可简化:假设增删发生时刻的价格为当日收盘价或下一分钟价,但这样会引入偏差。建议在回测时使用1分钟K线。
4. 与“每日更新持仓”的兼容
- 如果你的产品主要定位是“每日更新股票池”,盘中增删只是特殊操作,可以设定一个规则:盘中增删后,当日晚间仍会按新池子进行标准收盘后再平衡。但这样一天内可能多次再平衡,计算复杂。另一种简单处理:盘中增删只影响实时展示,但每日收盘后统一以最终股票池为准重新计算当日收益(忽略盘中调仓)。两种逻辑差异较大,需要明确产品定位。
推荐:如果用户明确要求“盘中增删”,则必须采用上述分段连乘法,并提供完整的事件记录与收益归因。
五、简化替代方案(如果不想过于复杂)
如果产品不希望处理复杂的盘中再平衡,可以约定:
盘中增删股票仅影响未来的持仓(下一个开盘日起生效),当日持仓仍保持原有股票池的等权分配。
当日收益率仍按原股票池计算,净值更新在次日开盘时反映股票池变化。
这本质上退化为“每日再平衡”模型,盘中增删只是调整待更新的池子,不产生实时资金操作。这样实现最简单,大多数展示型股票池功能足够。
请根据你的实际场景选择:
- 若用户需要实时模拟调仓效果(如实盘跟单、策略信号),则必须实现分段连乘法。
- 若只是记录策略观点变化(展示池子变动,但计算收益时忽略盘中动作),则用每日再平衡+盘后批量更新即可。
六、最终建议
作为证券产品经理,建议你先明确业务场景:
| 场景 | 推荐逻辑 |
|---|---|
| 仅做绩效展示,不绑定真实交易 | 采用每日收盘后再平衡,盘中增删视为次日生效,简单可靠。 |
| 模拟真实交易,盘中调仓影响收益 | 采用实时事件驱动 + 分段收益率连乘,需开发实时计算引擎。 |
| 半实时(次日生效但展示盘中池子变化) | 盘中池子变化只影响前端展示,后台仍按每日收盘池子计算收益。 |
绝大多数非量化产品选择第一种或第三种。如果做策略平台、模拟交易比赛,则必须第二种。
如果你确定要完整支持盘中增删,我可以进一步提供事件段收益计算的伪代码、数据库表字段设计,以及前端如何展示分段净值曲线。
👤 用户:
不考虑仓位,仅通过每只股票的买卖价格来实现收益率计算
💭 思考过程
我们理解用户需求:不考虑仓位(即不考虑资金分配权重),仅通过每只股票的买卖价格来计算收益率。这本质上是“价格收益率”而非“组合收益率”。用户可能希望计算每个股票从买入到卖出的收益率,然后汇总(比如简单平均)。具体场景:股票池动态增减,每次增减时记录买入价(或卖出价),最终计算每只股票的已实现收益率,再组合成股票池的整体表现。
但原问题中提到“股票池动态平均持仓”、“计算收益率、胜率、净值”,现在要求“不考虑仓位,仅通过每只股票的买卖价格”。需要澄清:可能指的是不按资金加权,而是按股票数量等权重,每只股票的收益率贡献基于其价格变化,忽略实际持仓金额。或者更简单:把每只股票的买入价和卖出价作为盈亏计算依据,所有股票同等重要。
给出逻辑:
- 每次股票被加入池子时,记录当时的“买入价格”(可能是开盘价或加入时市价)。
- 每次股票被移除池子时,记录“卖出价格”(移除时市价)。
- 该股票的收益率 = (卖出价 - 买入价) / 买入价。
- 如果股票在池内持续多日,没有卖出,则期间不计算实现收益,但可计算浮动收益率(按最新价)。
- 对于尚未卖出的股票,可以计算未实现收益率,但通常组合净值需要将未实现盈亏纳入。
“不考虑仓位”意味着每只股票对组合收益的贡献与其价格变动成正比,而不是与投入资金量成正比。例如,股票A从10元涨到20元(+100%),股票B从100元涨到110元(+10%),则组合收益率 = (100% + 10%)/2 = 55%。这隐含了每只股票“持有相同份额”的假设,而不是相同金额。
因此,逻辑可定义为:
- 等份额模型:假设每只股票持有相同数量(如1股),那么组合价值变化直接由价格变化平均决定。组合收益率 = 所有股票当日价格变化率的算术平均。
- 这种模型下,无需考虑仓位(仓位恒为1股/每只)。
用户说“仅通过每只股票的买卖价格来实现收益率计算”,可能正是此意:不关心每只股票买了多少钱,只关心买入价和卖出价,计算每只的收益率,然后取平均值作为股票池收益率。
那么,针对盘中增删的处理,可以简化为:
- 当某股票被加入时,记录买入价(当时价格)。
- 当某股票被移除时,立即计算该股票的已实现收益率 = (卖出价 - 买入价)/买入价,并记录。
- 每日的股票池收益率 = 当天所有已实现收益率(如果有卖出)加上未实现收益率变化(对于池内未卖出的股票,按当日收盘价相对于买入价的变化)的平均?但注意,如果每天计算净值,通常需要计算每日的收益率(即当日组合价值变化率)。等份额模型下,每日收益率 = 当日池内所有股票当日价格变化率的算术平均(忽略买卖动作,因为买卖瞬间价格相同,不影响当日收益率)。这样更简洁。
用户明确要求“不考虑仓位”,并且“仅通过每只股票的买卖价格”,那么可能不需要每日再平衡权重,而是记录每只股票的进出价格,最终计算整个策略的收益率和胜率。
我建议提供两种可能解释,并给出相应逻辑。最终由用户确认。
明白了:你希望不考虑持仓金额(即忽略资金分配权重),仅依据每只股票的买入价格和卖出价格来计算股票池的整体收益率、胜率、净值等。这本质上是一种等份额模型(每只股票持有固定数量,如1股),组合的表现完全由价格变化驱动。
下面给出清晰、可落地的计算逻辑,同时兼容盘中动态增删股票。
一、核心模型:等份额价格模型
- 假设:股票池中每只股票持有相同数量(例如1股,或100股,比例恒定)。
- 组合价值 = 各只股票的当前价格之和(乘以固定份额,可归一化为价格和)。
- 无需考虑:每只股票投入了多少资金、仓位权重、再平衡现金流转。
- 收益率:完全由价格变化率决定,无需处理资金分配。
这种模型下,每日组合收益率 = 当日池内所有股票收益率(涨跌幅)的简单算术平均。与之前“动态平均持仓”的结果完全一致,但底层逻辑不同:之前是等金额,现在是等份额。由于份额固定,价格变化直接累加,计算更简单。
二、盘中增删股票的处理逻辑
1. 核心原则
- 股票被加入池子时:记录加入价格(当时市场价),作为该股票的“成本价”。
- 股票被移除池子时:记录移除价格(当时市场价),并立即计算该股票的已实现收益率。
- 股票在池内期间:每日按收盘价计算浮动盈亏。
- 组合的每日收益率:基于当日池内所有股票(在池一整天的股票)的日收益率(当日收盘价 / 前日收盘价 - 1)。对于盘中新增的股票,若加入时间在盘中,当日收益率如何处理?下面第3点给出明确方案。
2. 组合净值计算(推荐)
采用“持有期收益率连乘”方式,与资金无关,仅依赖价格:
- 将时间划分为事件段:相邻两次股票池变更(增/删)之间的时段。
- 在每个事件段内,股票池固定。该段的收益率 = 段内所有股票价格变化率的算术平均。
例如,段内无任何增删,从时刻 \(t0\) 到 \(t1\),股票池为 \(\{S1,...,Sk\}\),则该段收益率 \[ R{seg} = \frac{1}{k} \sum{i=1}^k \frac{Pi(t1) - Pi(t0)}{Pi(t0)} \]
- 全天净值 = 各段 (1+R_seg) 连乘。
优点:无需关心买卖价格(买卖只在事件点发生,且买卖价格等于当时的市价,不影响段收益率计算)。新增股票在加入时刻被纳入组合,其后续价格变动计入后续段;删除股票在删除时刻被移出,其价格变动只计算到删除前一刻。
3. 盘中新增/删除当日的收益率归属
- 场景A:股票在盘中 \(t\) 时刻被加入。
当日该股票的收益贡献如何拆分?建议采用“加入前不持有,加入后持有”原则:
- 若数据精度足够(有分钟级价格),则从加入时刻开始,该股票的后续价格变化计入当日组合。
- 当日组合收益率 = 从开盘到加入时刻的段(不含该股) + 从加入到收盘的段(含该股)。
- 场景B:股票在盘中 \(t\) 时刻被删除。
该股票在删除前的价格变化计入当日组合,删除后不再计入。
简化处理(如果不想搞得太复杂): 约定盘中增删只在开盘或收盘时生效,即:
- 日间增删指令,次日开盘生效;
- 盘中增删只影响实时展示,但当日收盘计算仍以开盘时的股票池为准。
这样回归到每日再平衡模型,完全避免盘中分段的复杂性。请根据你的产品定位选择。
三、具体指标计算公式(基于等份额价格模型)
1. 每日组合收益率(\(R_t\))
- 若采用每日收盘后再平衡(忽略盘中增删):
\( Rt = \frac{1}{Nt} \sum{i \in Poolt} \frac{P{i,t}^{close} - P{i,t-1}^{close}}{P{i,t-1}^{close}} \) 其中 \(Poolt\) 为当日开盘时的股票池(即前一日收盘后确定的池子)。
- 若支持盘中增删(分段连乘):
按上述事件段方法计算。
2. 净值(\(NAV_t\))
- 仍使用 \( NAVt = NAV{t-1} \times (1 + Rt) \),\(NAV0=1\)。
3. 胜率
- 日胜率:统计 \(R_t > 0\) 的天数占比。
- 个股胜率(基于“买卖价格”):
对每只股票,若它被移除时计算了已实现收益率(卖出价-买入价)/买入价,则统计所有已移除股票的收益率 > 0 的比例。 对于仍在池中的股票,可以暂不纳入个股胜率,或按浮动盈亏计算。
4. 累计收益率 / 年化收益率 / 最大回撤 / 夏普比率
- 与标准方法相同,基于每日净值序列计算。
四、产品实现建议(简化版)
如果不想处理复杂的盘中分段,推荐采用以下实用方案,它满足“不考虑仓位,仅通过买卖价格计算收益”的核心诉求,且易于实现:
- 每日收盘后更新股票池(盘中增删视为对次日池子的修改,不影响当日收益)。
- 每只股票记录两个价格:
- 加入日收盘价(作为买入价)
- 移除日收盘价(作为卖出价)
- 组合收益率:每个交易日,组合收益率 = 当日池内所有股票当日涨跌幅的算术平均。
- 个股已实现收益率:当股票被移除时,计算 (移除日收盘价 - 加入日收盘价) / 加入日收盘价。
- 胜率(个股维度):已移除股票中,实现收益率为正的比例。
- 净值曲线:基于每日组合收益率连乘得到。
这种方案下,盘中增删操作只是改变了未来的池子,不会导致当日收益计算的碎片化,用户理解成本低。
五、与用户原问题中“动态平均持仓”的关系
- 原问题要求“动态平均持仓”,通常意味着等金额权重。
- 现在要求“不考虑仓位”,则退化为等份额(价格)权重。
- 两者的每日收益率计算公式完全相同(都是股票日涨跌幅的算术平均),因此你完全可以用等份额模型来满足“动态平均持仓”的表象,同时避免处理仓位资金。
结论:你可以直接采用等份额模型,每日组合收益率 = 池内所有股票当日涨跌幅的平均值,净值连乘。盘中增删通过“次日生效”或“分段连乘”两种方式之一实现。推荐选择“次日生效”以降低复杂度。
如果需要,我可以进一步给出数据库表设计、每日计算任务的SQL伪代码,以及前端如何展示“买卖价格对”和个股胜率。请明确你选择盘中增删的处理方式(实时分段 or 次日生效),我会据此提供更具体的实现细节。