3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 Pandas 中,使用 df.apply(..., axis=1) 是逐行处理数据(传入的 x 实际上是一个 pd.Series 代表当前行)。在 apply 的函数内部直接“删除”原 DataFrame 的行是不合适的,也是做不到的。
要实现你的需求,有两种主要思路:
在 Pandas 中,尽量避免使用 apply 逐行遍历,因为它的运行速度非常慢。你的逻辑完全可以使用 Pandas 和 NumPy 的向量化操作来实现,代码更简洁,运行速度快几十倍甚至上百倍。
你可以直接对整个 DataFrame 进行列运算和布尔索引过滤:
import pandas as pd
import numpy as np
def filter_options_arbitrage(df: pd.DataFrame, rf_rate: float, maturity: float) -> pd.DataFrame:
# 复制一份避免修改原数据(可选)
df_res = df.copy()
# 1. 向量化计算上下限
# 使用 np.maximum 替代 if-else
df_res['c_down_bound'] = np.maximum(df_res['call'] - df_res['put'], 0.0)
df_res['c_upper_bound'] = df_res['call'] - df_res['put'] + df_res['K'] * np.exp(-rf_rate * maturity)
df_res['p_down_bound'] = np.maximum(df_res['put'] - df_res['call'], 0.0)
df_res['p_upper_bound'] = df_res['K'] * np.exp(-rf_rate * maturity)
# 2. 构建保留条件 (注意:原问题描述中 put 的上限条件写重复了,这里修正为 put <= p_upper_bound)
valid_call = (df_res['call'] >= df_res['c_down_bound']) & (df_res['call'] <= df_res['c_upper_bound'])
valid_put = (df_res['put'] >= df_res['p_down_bound']) & (df_res['put'] <= df_res['p_upper_bound'])
# 3. 筛选出满足条件的行
df_filtered = df_res[valid_call & valid_put]
return df_filtered
# 调用方式:
# df_final = filter_options_arbitrage(df, rf_rate, maturity1)
apply如果你必须在 apply 的函数中处理,你可以让不符合条件的行返回 None(或全为 NaN 的 Series),然后在外部调用 dropna() 将这些行删掉。
def bound_filter_sub(x: pd.Series, rf_rate: float, maturity: float):
# 看涨期权无套利上下限
if x['call'] - x['put'] >= 0.0:
x['c_down_bound'] = x['call'] - x['put']
else:
x['c_down_bound'] = 0.0
x['c_upper_bound'] = x['call'] - x['put'] + x['K'] * np.exp(-rf_rate * maturity)
# 看跌期权无套利上下限
if x['put'] - x['call'] >= 0.0:
x['p_down_bound'] = x['put'] - x['call']
else:
x['p_down_bound'] = 0.0
x['p_upper_bound'] = x['K'] * np.exp(-rf_rate * maturity)
# 检查是否满足条件,如果不满足,返回 None
if (x['call'] < x['c_down_bound']) or (x['call'] > x['c_upper_bound']) or \
(x['put'] < x['p_down_bound']) or (x['put'] > x['p_upper_bound']): # 注意这里修正了你的笔误
return None
return x
# 调用方式:
# 1. apply 处理,不符合的行会变成 None/NaN
# 2. dropna(how='all') 删掉这些全为 NaN 的行
df_final = df.apply(lambda x: bound_filter_sub(x, rf_rate, maturity1), axis=1).dropna(how='all')
总结建议:强烈建议使用方法一。在量化数据处理中,养成使用向量化(Vectorization)替代循环和 apply 的习惯,对处理大规模期权数据至关重要。