首页 > 解决方案 > Python Scipy fsolve函数返回等于起点的根

问题描述

我需要得到一个标量方程的所有根。但是 fsolve 每次调用只能返回 1 个根。所以我设计了一个fsolve的自调用功能find_root_recursively。此函数将调用自身,直到新根等于前一个根,这意味着fsovle已找到所有根,不会再添加新根。我使用这个逻辑来结束自我调用。但在某些情况下fsolve会返回一个与起点完全相同的根。one_root=start总是。显然这start不是根。所以list_root总是在添加新的根,它永远不会结束。

    min_value = df_group['strike'].min()
    start_point = int(float(min_value) * 0.8)
def find_root_by_small_step(function, start_0, increment):
                    start = start_0
                    one_root = fsolve(function, start)


def get_transaction_data(self, expiry_date, df_group):
    return df_group[df_group['expiration_date'] == expiry_date].loc[(df_group['type'] == 1) & (df_group['position'] == 1)], \
           df_group[df_group['expiration_date'] == expiry_date].loc[(df_group['type'] == 1) & (df_group['position'] == 0)], \
           df_group[df_group['expiration_date'] == expiry_date].loc[(df_group['type'] == 0) & (df_group['position'] == 1)], \
           df_group[df_group['expiration_date'] == expiry_date].loc[(df_group['type'] == 0) & (df_group['position'] == 0)]

def calculate_one_payoff(self, stock_price, df_long_call, df_short_call, df_long_put, df_short_put):
    # buy call

    df_buy_call_executed = df_long_call[stock_price >= df_long_call['strike']]
    if len(df_buy_call_executed) > 0:
        buy_call_executed_sum = ((stock_price - df_buy_call_executed['breakeven_price']) * df_buy_call_executed['option_amount']).sum()
    else:
        buy_call_executed_sum = 0

    df_buy_call_noExec = df_long_call[stock_price < df_long_call['strike']]
    if len(df_buy_call_noExec) > 0:
        buy_call_noExec_sum = (-1 * df_buy_call_noExec['option_price'] * df_buy_call_noExec['option_amount']).sum()
    else:
        buy_call_noExec_sum = 0

    # sell call
    df_sell_call_executed = df_short_call[stock_price >= df_short_call['strike']]
    if len(df_sell_call_executed) > 0:
        sell_call_executed_sum = ((df_sell_call_executed['breakeven_price'] - stock_price) * df_sell_call_executed['option_amount']).sum()
    else:
        sell_call_executed_sum = 0

    df_sell_call_noExec = df_short_call[stock_price < df_short_call['strike']]
    if len(df_sell_call_noExec) > 0:
        sell_call_noExec_sum = (df_sell_call_noExec['option_price'] * df_sell_call_noExec['option_amount']).sum()
    else:
        sell_call_noExec_sum = 0

    # buy put
    df_buy_put_executed = df_long_put[stock_price < df_long_put['strike']]
    if len(df_buy_put_executed) > 0:
        buy_put_executed_sum = ((df_buy_put_executed['breakeven_price'] - stock_price) * df_buy_put_executed['option_amount']).sum()
    else:
        buy_put_executed_sum = 0

    df_buy_put_noExec = df_long_put[stock_price >= df_long_put['strike']]
    if len(df_buy_put_noExec) > 0:
        buy_put_noExec_sum = (-1 * df_buy_put_noExec['option_price'] * df_buy_put_noExec['option_amount']).sum()
    else:
        buy_put_noExec_sum = 0

    # sell put
    df_sell_put_executed = df_short_put[stock_price < df_short_put['strike']]
    if len(df_sell_put_executed) > 0:
        sell_put_executed_sum = ((stock_price - df_sell_put_executed['breakeven_price']) * df_sell_put_executed['option_amount']).sum()
    else:
        sell_put_executed_sum = 0
    df_sell_put_noExec = df_short_put[stock_price >= df_short_put['strike']]
    if len(df_sell_put_noExec) > 0:
        sell_put_noExec_sum = (df_sell_put_noExec['option_price'] * df_sell_put_noExec['option_amount']).sum()
    else:
        sell_put_noExec_sum = 0

    one_stock_price_sum = buy_call_executed_sum + buy_call_noExec_sum + sell_call_executed_sum + sell_call_noExec_sum + \
                          buy_put_executed_sum + buy_put_noExec_sum + sell_put_executed_sum + sell_put_noExec_sum
    one_stock_price_sum = float(one_stock_price_sum)
    return one_stock_price_sum

df_long_call, df_short_call, df_long_put, df_short_put = self.get_transaction_data(expiry_date, df_group)

find_root_by_small_step(function=calculate_one_payoff, start=start_point, increment=increment)

ticker  type    position    expiration_date strike  option_price    option_amount   breakeven_price
AAPL    1   0   2021-11-19  145.0000    5.1700  2500.0000   150.1700
AAPL    0   1   2021-11-19  145.0000    2.9700  2500.0000   142.0300
AAPL    0   1   2021-11-19  145.0000    2.7000  5000.0000   142.3000
AAPL    1   1   2021-11-19  145.0000    5.8500  5000.0000   150.8500
AAPL    1   1   2021-11-19  155.0000    1.6000  1050.0000   156.6000

True root = 139.9 and 159.0

    

标签: pythonscipyrootequation

解决方案


推荐阅读