期权产品收益组合分析:多类型期权状态计算方法咨询
结构化期权产品有效状态与收益曲线通用计算方法
核心逻辑基础
障碍触发存在严格的连续路径依赖:标的资产价格是连续变动的,只有先触达离初始价格更近的障碍,才可能触达同方向更远端的障碍,不存在跨级触发的合法路径。
步骤1:组件预处理与同障碍价位归并
首先对产品内嵌的所有期权做分类处理:
- Vanilla(香草期权):无状态变更,全存续期始终生效,直接作为所有状态的收益计算基底,不参与状态数统计。
- Ki/Ko障碍期权:按
barrier strike(障碍行权价)做分组归并,同一价位的所有障碍期权触发完全同步,按规则计算单组的状态贡献:- 单只Ki期权的状态贡献值为2(未激活/激活两个有效状态)
- 单只Ko期权的状态贡献值为1(仅初始激活为有效状态,触发后失效无后续收益)
- 同价位组的状态贡献取组内所有期权的最大值:只要组内存在至少1只Ki,该组贡献值为2;如果组内全为Ko,贡献值为1,触发后该路径直接终止,不再跟踪后续障碍。
步骤2:拆分排序双向障碍序列
以初始标的价格S0为分界点,将所有归并后的障碍组拆分为两个独立序列:
- 下跌侧序列:所有
barrier < S0的障碍组,按价格从高到低排序(离S0越近的障碍排序越靠前,越先被触发) - 上涨侧序列:所有
barrier > S0的障碍组,按价格从低到高排序(离S0越近的障碍排序越靠前,越先被触发)
示例:当S0=20.0,障碍价为18、19、21、22时,下跌侧排序为[19, 18],上涨侧排序为[21, 22],和题例的触发顺序完全一致。
步骤3:枚举所有合法有效状态
基于路径依赖约束,所有合法状态都可以用(n, m)二元组表示:n为下跌侧已触发的障碍数量(必须是排序后前n个近端障碍),m为上涨侧已触发的障碍数量(必须是排序后前m个近端障碍),枚举时剔除非法状态:
- 初始状态
(0,0)为第一个有效状态,对应所有障碍均未触发。 - 逐一枚举所有n、m的非负整数组合(n不超过下跌侧障碍总数,m不超过上涨侧障碍总数):
- 若n>0,检查下跌侧第n个障碍(即该路径下跌方向最后触发的障碍):如果该组全为Ko,说明触发该障碍后产品已失效,仅当m=0时该
(n,0)为有效终态,所有m>0的组合均为非法(失效后价格波动不再触发新的状态变更)。 - 若m>0,检查上涨侧第m个障碍:如果该组全为Ko,说明触发该障碍后产品已失效,仅当n=0时该
(0,m)为有效终态,所有n>0的组合均为非法。 - 其余未触发失效条件的组合均为有效状态。
- 若n>0,检查下跌侧第n个障碍(即该路径下跌方向最后触发的障碍):如果该组全为Ko,说明触发该障碍后产品已失效,仅当m=0时该
题例中4个障碍均为Ki(无Ko终止路径),所有n∈{0,1,2}、m∈{0,1,2}的组合共9个,和题例给出的状态表完全匹配。
步骤4:计算状态总数并生成payoff曲线
- 有效状态总数即为上述枚举得到的合法组合总数量。
- 对每个有效状态,按规则统计当前生效的期权头寸:
- 所有Vanilla期权全部生效
- Ki期权:所属障碍组在已触发集合内则生效,未触发则不贡献收益
- Ko期权:所属障碍组不在已触发集合内则生效,已触发则不贡献收益
- 基于每个状态下的生效期权组合,结合到期标的价格的全区间取值,逐段计算收益值,即可得到刻画产品全部收益特征的payoff曲线。
参考实现代码
def calc_product_states_and_payoff_base(options, initial_spot): # 分离香草期权与障碍期权 vanilla_opts = [opt for opt in options if opt["type"] == "vanilla"] barrier_group = dict() for opt in options: if opt["type"] == "vanilla": continue bar_price = opt["bar_strike"] if bar_price not in barrier_group: barrier_group[bar_price] = {"bar_strike": bar_price, "has_ki": False, "opts": []} # 标记组内是否存在Ki期权 if opt["type"] == "ki": barrier_group[bar_price]["has_ki"] = True barrier_group[bar_price]["opts"].append(opt) # 拆分并排序双向障碍序列 down_barriers = sorted( [g for bar, g in barrier_group.items() if bar < initial_spot], key=lambda x: -x["bar_strike"] ) up_barriers = sorted( [g for bar, g in barrier_group.items() if bar > initial_spot], key=lambda x: x["bar_strike"] ) valid_states = [] max_n = len(down_barriers) max_m = len(up_barriers) # 枚举所有合法(n,m)状态 for n in range(max_n + 1): down_terminated = False if n > 0: # 检查下跌路径是否已被Ko终止 down_terminated = not down_barriers[n-1]["has_ki"] for m in range(max_m + 1): if n == 0 and m == 0: # 初始状态 valid_states.append({ "triggered_down": n, "triggered_up": m, "active_opts": vanilla_opts + [ opt for g in down_barriers[:n] for opt in g["opts"] if opt["type"] == "ki" ] + [ opt for g in up_barriers[:m] for opt in g["opts"] if opt["type"] == "ki" ] + [ opt for g in down_barriers[n:] for opt in g["opts"] if opt["type"] == "ko" ] + [ opt for g in up_barriers[m:] for opt in g["opts"] if opt["type"] == "ko" ] }) continue up_terminated = False if m > 0: # 检查上涨路径是否已被Ko终止 up_terminated = not up_barriers[m-1]["has_ki"] # 跳过失效后的非法组合 if (down_terminated and m > 0) or (up_terminated and n > 0): continue # 记录有效状态及对应生效期权 valid_states.append({ "triggered_down": n, "triggered_up": m, "active_opts": vanilla_opts + [ opt for g in down_barriers[:n] for opt in g["opts"] if opt["type"] == "ki" ] + [ opt for g in up_barriers[:m] for opt in g["opts"] if opt["type"] == "ki" ] + [ opt for g in down_barriers[n:] for opt in g["opts"] if opt["type"] == "ko" ] + [ opt for g in up_barriers[m:] for opt in g["opts"] if opt["type"] == "ko" ] }) # 若单侧已终止,不再枚举该方向后续组合 if down_terminated or up_terminated: break if down_terminated: break return len(valid_states), valid_states
内容的提问来源于stack exchange,提问作者rafael ventura
相关产品推荐
相关产品推荐

