i tried finding solutions of the data with python scipy.fsolve
my input data is here (link removed)
but Excel's goal seek determines the data has no solution.
my entire code is below
import scipy as sco
from scipy.optimize import fsolve
import pandas as pd
import numpy as np
from functools import partial
import matplotlib.pyplot as plt
data = pd.read_csv(r'local/data.csv', dtype=float, header=0 )
def goal_seek_eir(cf_df, guess=0.01
, cash_flow_bom='cash_bom', cash_flow_mom='cash_mom'
, cash_flow_eom='cash_eom', target_bel='target_bel', date_column_name='t'):
f = partial(npv, cf_df
, cash_flow_bom=cash_flow_bom, cash_flow_mom=cash_flow_mom
, cash_flow_eom=cash_flow_eom, target_bel=target_bel, date_column_name=date_column_name)
result_fsolve = fsolve(f, guess, full_output=True)
# result_fmin = sco.fmin(f, guess)
return result_fsolve
def npv(cf_df,rate
,cash_flow_bom='cash_bom',cash_flow_mom='cash_mom'
,cash_flow_eom='cash_eom',target_bel='target_bel',date_column_name='t'):
mapper = lambda x : _calculate_discounted(x[cash_flow_bom]
,x[cash_flow_mom]
,x[cash_flow_eom]
,round(x[target_bel])
,rate
,x[date_column_name])
return cf_df[[cash_flow_bom,cash_flow_mom,cash_flow_eom
,target_bel,date_column_name]].apply(mapper, axis=1).sum()
def _calculate_discounted(cf_bom, cf_mom, cf_eom, target_bel, rate, t):
return ( cf_bom / (1+rate)**(max(t-1,0)/12)
+ cf_mom / (1+rate)**(max(t-0.5,0)/12) + cf_eom / (1+rate)**(t/12)
- target_bel )
result_fsolve = goal_seek_eir(data)
result_fsolve
also, i drew the function of data and found this function is diverge.
(X axis is input rate, Y axis is result of cash_flow)
the red line is [terget_bel] of data(excel E2 cell)
and the blue line is [cash_flow_eom]+[cash_flow_mom]+ [cash_flow_eom]. (sum of excel columns F to H)
the target is [cash_flow_eom]+[cash_flow_mom]+[cash_flow_eom] - [terget_bel] (excel J2 cell)
i think this functions is diverge, because the red line do not cross the blue line.
drawing plot code
#function
def npv(cf_df,rate
,cash_flow_bom='cash_bom',cash_flow_mom='cash_mom'
,cash_flow_eom='cash_eom',target_bel='target_bel',date_column_name='t'):
mapper = lambda x : _calculate_discounted(x[cash_flow_bom]
,x[cash_flow_mom]
,x[cash_flow_eom]
,round(x[target_bel])
,rate
,x[date_column_name])
return cf_df[[cash_flow_bom,cash_flow_mom,cash_flow_eom
,target_bel,date_column_name]].apply(mapper, axis=1).sum()
f = partial(npv, data
, cash_flow_bom='cash_bom', cash_flow_mom='cash_mom'
, cash_flow_eom='cash_eom', target_bel='target_bel', date_column_name='t')
#plot
x = np.arange(-0.05,1,0.0002)
plt.plot(x, f(x))
plt.axhline(y=sum(data['target_bel']), color='r')
plt.xlabel('rate')
plt.show()
so this problem seems definitely diverge, BUT by fsolve function of scipy with python says this function is CONVERGE
and the solution is same with guess(initial value) and it changes by the guess value.(this is weird)
fsolve result when guess is 0.005. the solution is 0.005
fsolve result when guess is 0.01. the solution is 0.01
Q1. Can i ask why fsolve determines this function if converge? even though Excel says it's diverge.
Q2. why fsolve's solution is same with guess value?