使用 matplotlib 添加垂直线

问题描述 投票:0回答:1

我的目标是首先创建两个图(我正确创建的),每个图代表市场上仍然未平仓的看跌期权和看涨期权数量的 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()

有什么建议吗?

python matplotlib distribution
1个回答
0
投票

解决方案

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轴的罢工进行排序,然后通过定义我想要绘制垂直线的罢工的相应值,找到相应的索引,然后在中绘制线该索引。

© www.soinside.com 2019 - 2024. All rights reserved.