我的目标是首先创建两个图(我正确创建的),每个图代表市场上仍然未平仓的看跌期权和看涨期权数量的 CDF。 对于每个图,我还想绘制代表 40% 和 80% 百分位的垂直线。
但是,最终目标是合并两个图,并为两侧添加各自的垂直线(这就是问题)。 这就是我所做的:
创建两个单图(第一次调用):
plt.figure(figsize=(14, 6)) # Adjusting figure size
plt.bar(CALL.index, CALL['CDF'], width=0.5, color='lightgreen') # Using DataFrame index as x-axis ticks
plt.xlabel('STRIKE')
plt.ylabel('CDF')
plt.title('Cumulative Distribution Function (CDF) for CALL')
plt.xticks(CALL.index, CALL['STRIKE'], rotation=90) # Setting x-axis ticks to the Strike values with rotation
plt.grid(True)
# Find the nearest value to 40% in the 'Percentile' column
nearest_40_percentile_idx = (CALL['Percentile'] - 0.4).abs().idxmin()
nearest_40_percentile_strike = CALL.loc[nearest_40_percentile_idx, 'STRIKE']
# Add a vertical line at the corresponding 'Strike' value for 40th percentile
plt.axvline(x=nearest_40_percentile_idx, color='red', linestyle='--', label=f'Nearest to 40% ({nearest_40_percentile_strike})')
# Find the nearest value to 80% in the 'Percentile' column
nearest_80_percentile_idx = (CALL['Percentile'] - 0.8).abs().idxmin()
nearest_80_percentile_strike = CALL.loc[nearest_80_percentile_idx, 'STRIKE']
# Add a vertical line at the corresponding 'Strike' value for 80th percentile
plt.axvline(x=nearest_80_percentile_idx, color='blue', linestyle='--', label=f'Nearest to 80% ({nearest_80_percentile_strike})')
# Show legend
plt.legend()
plt.show()
PUT 基本一样,只是 df 的名字变了。
现在,我尝试将它们合并并以这种方式绘制垂直线,但是图形一团糟:
res = pd.concat([CALL, PUT])
# Set different colors for CALL and PUT bars
colors = {1: 'lightgreen', 2: 'orange'}
# Plot the bar chart
plt.figure(figsize=(16, 6))
sns.barplot(x='Strike', y='CDF', data=res, hue='hue', palette=colors)
# Calculate the nearest strike values to the 40th and 80th percentiles for both CALL and PUT
nearest_40_percentile_idx_call = (CALL['Percentile'] - 0.4).abs().idxmin()
nearest_40_percentile_strike_call = CALL.loc[nearest_40_percentile_idx_call, 'Strike']
nearest_40_percentile_idx_put = (PUT['Percentile'] - 0.4).abs().idxmin()
nearest_40_percentile_strike_put = PUT.loc[nearest_40_percentile_idx_put, 'Strike']
# Add vertical lines at the corresponding strike values for the 40th and 80th percentiles
plt.axvline(x=nearest_40_percentile_idx_call, color='blue', linestyle='--', label=f'40% for CALL ({nearest_40_percentile_strike_call})')
plt.axvline(x=nearest_40_percentile_idx_put, color='green', linestyle='--', label=f'40% for PUT ({nearest_40_percentile_strike_put})')
# Set labels and title
plt.xlabel('Strike')
plt.ylabel('Cumulative Distribution Function (CDF)')
plt.title('CDF for CALL and PUT')
# Rotate x-axis labels for better readability
plt.xticks(rotation=60)
# Show legend
plt.legend()
# Show the plot
plt.show()
有什么建议吗?
解决方案
res = pd.concat([CALL, PUT])
unique_strikes = sorted(res['STRIKE'].unique())
ind40call = 0
ind80call = 0
ind40put = 0
ind80put = 0
for i, v in enumerate(unique_strikes):
if v == nearest_80_percentile_call:
ind80call = i
if v == nearest_80_percentile_put:
ind80put = i
if v == nearest_40_percentile_call:
ind40call = i
if v == nearest_40_percentile_put:
ind40put = i
colors = {1: 'lightgreen', 2: 'orange'}
plt.figure(figsize=(16, 6))
sns.barplot(x='STRIKE', y='CDF', data=res, hue='hue', palette=colors)
plt.xlabel('Strike')
plt.ylabel('Open Interest')
plt.title('Open Interest for CALL and PUT')
plt.xticks(rotation=60)
plt.axvline(x=ind40put, color='red', linestyle='--')
plt.axvline(x=ind80call, color='red', linestyle='--')
plt.axvline(x=ind80put, color='red', linestyle='--')
plt.axvline(x=ind40call, color='red', linestyle='--')
plt.text(ind40put, res['CDF'].max(), f'40% - {nearest_40_percentile_put}', ha='left', va='top', color='blue')
plt.text(ind80call, res['CDF'].max(), f'80% - {nearest_80_percentile_call}', ha='left', va='top', color='blue')
plt.text(ind80put, res['CDF'].max(), f'80% - {nearest_80_percentile_put}', ha='left', va='top', color='blue')
plt.text(ind40call, res['CDF'].max(), f'40% - {nearest_40_percentile_call}', ha='left', va='top', color='blue')
# Create a custom legend
handles = [plt.Rectangle((0,0),1,1, color='lightgreen', ec="k"), plt.Rectangle((0,0),1,1, color='orange', ec="k")]
labels = ['CALL', 'PUT']
plt.legend(handles, labels)
plt.show()
这个想法是对所有代表x轴的罢工进行排序,然后通过定义我想要绘制垂直线的罢工的相应值,找到相应的索引,然后在中绘制线该索引。