async def eval_budget(income: float, assets: float, retirement_expenses: float, expenses: List[float] = Query([]), categories: List[str] = Query([]), withdraw: float = 0.04, real_rate: float = 0.06, income_growth: float = 0.05): try: income /= 12 monthly_rate = (1 + (real_rate))**(1. / 12) - 1 fv = assets goal = retirement_expenses * sum(expenses) * 12 / withdraw original_month = 0 scaled_income = income net_worths = [] while fv < goal: fv = npf.fv(monthly_rate, 1, -(scaled_income - sum(expenses)), -fv) net_worths.append(fv) original_month += 1 scaled_income = scaled_income * (1 + income_growth / 12) graph = np.empty((2, ceil(original_month / 12))) curr_year = date.today().year graph[0] = [curr_year + i for i in range(ceil(original_month / 12))] count = 0 for index in range(len(net_worths)): if ((index + 1) % 12 == 0): graph[1][count] = net_worths[index] count += 1 if (count < len(net_worths)): graph[1][-1] = net_worths[-1] time = {} for cat in categories: new_expenses = sum(expenses) - expenses[categories.index(cat)] month = 0 fv = assets scaled_income = income while fv < goal: fv = npf.fv(monthly_rate, 1, -(scaled_income - new_expenses), -fv) month += 1 scaled_income = scaled_income * (1 + income_growth / 12) time[cat] = original_month - month return ({ 'months left': original_month, 'categories': time, 'graph': graph.tolist(), 'goal': goal }) except Exception as e: raise HTTPException(status_code=400, detail=str(e))
def simulate(simulation_trials, num_years): n = 0 # df_define() rate_index = a_transposed['rate'].loc[0] pmt_index = a_transposed['pmt'].loc[0] pv_index = abs(a_transposed['pv'].loc[0]) index_index = a_transposed['index'].loc[0] global fv_array global fv fv_array.append(abs(npf.fv(rate_index / 100, 1, pmt_index, pv_index))) for n in range(num_years - 1): n += 1 rate_index = a_transposed['rate'].loc[n] pmt_index = a_transposed['pmt'].loc[n] pv_index = fv_array[n - 1] index_index = a_transposed['index'].loc[n] fv = round(abs(npf.fv(rate_index / 100, 1, pmt_index, pv_index)), 2) fv_array.append(fv) # print("rate",amount) # print("rate_array",pmt_array) b.append(fv_array)
def test_when_is_end_float(self, when): args = (0.075, 20, -2000, 0) result = npf.fv(*args) if when is None else npf.fv(*args, when) assert_allclose( result, 86609.362673, # Computed using Google Sheet's FV rtol=1e-10, )
def test_when_is_end_decimal(self, when): args = ( Decimal('0.075'), Decimal('20'), Decimal('-2000'), Decimal('0'), ) result = npf.fv(*args) if when is None else npf.fv(*args, when) assert_almost_equal(result, Decimal('86609.362673'), decimal=5)
async def eval_budget(income: float, assets: float, curr_expenses: float, retirement_expenses: float, withdraw: float = 0.04, real_rate: float = 0.06, income_growth: float = 0.05): try: goal = retirement_expenses * curr_expenses / withdraw fv = assets year = 0 incomes = [] net_worths = [] while fv < goal: incomes.append(income) fv = npf.fv(real_rate, 1, -(income - curr_expenses), -fv) net_worths.append(fv) year += 1 income = income * (1 + income_growth) graph = np.empty((2, year)) curr_year = date.today().year graph[0] = [curr_year + i for i in range(year)] graph[1] = net_worths return ({'months left': year * 12, 'graph': graph.tolist()}) except Exception as e: raise HTTPException(status_code=400, detail=str(e))
def test_some_rates_zero(self): # Check that the logical indexing is working correctly. assert_allclose( npf.fv([0, 0.1], 5, 100, 0), [-500, -610.51], # Computed using Google Sheet's FV rtol=1e-10, )
def calc_parameter(ask_reply, input_string): """ calc_parameter is a calculator to calculate the final goal based on ino given by users. Parameters --------- Param1 : Dictionary The dictionary stores the float provided by user as value, stores corresponding terms as the key. Param2 : String The string is the specified goal for caculation. The string implies what the dictionary would be since each value is dependent to the remaining values. Returns ------ Return1 : Float The final result of requested value after caculation. """ user_fin_dict = ask_reply try: if (ask_reply['input_string']) == 'present value': output = abs( npf.pv(user_fin_dict["required rate per year"], user_fin_dict["required time period"], 0 - user_fin_dict["payment"], user_fin_dict["future value"])) elif (ask_reply['input_string']) == "future value": output = abs( npf.fv(user_fin_dict["required rate per year"], user_fin_dict["required time period"], 0 - user_fin_dict["payment"], 0 - user_fin_dict["present value"])) elif (ask_reply['input_string']) == "payment": output = abs( npf.pmt(user_fin_dict["required rate per year"], user_fin_dict["required time period"], 0 - user_fin_dict["present value"], user_fin_dict["future value"])) elif (ask_reply['input_string']) == "required rate per year": output = abs( npf.rate(user_fin_dict["required time period"], 0 - user_fin_dict["payment"], 0 - user_fin_dict["present value"], user_fin_dict["future value"])) elif (ask_reply['input_string']) == "required time period": output = abs( npf.nper(user_fin_dict["required rate per year"], 0 - user_fin_dict["payment"], 0 - user_fin_dict["present value"], user_fin_dict["future value"])) else: output = random.choice(unknown_input_reply) return output except KeyError: print("I'm dead because of you !") print("You should never have encountered this. What did you do?") return None
def test_when_is_begin_decimal(self, when): result = npf.fv( Decimal('0.075'), Decimal('20'), Decimal('-2000'), Decimal('0'), when, ) assert_almost_equal(result, Decimal('93105.064874'), decimal=5)
def infer_reasonable_share_price(ticker, financialreportingdf, stockpricedf, discountrate, marginrate): years = 2 # period dfprice = pd.DataFrame( columns=['ticker', 'annualgrowthrate', 'lasteps', 'futureeps']) pd.options.display.float_format = '{:20,.2f}'.format # Find EPS Annual Compounded Growth Rate # annualgrowthrate = financialreportingdf.epsgrowth.mean() #growth rate # print('financialreportdf:\n',financialreportingdf) try: # Calcuate the rate per period # parameter: periods , payment, present value, future value firstEPS = financialreportingdf.eps.iloc[0] lastEPS = financialreportingdf.eps.iloc[-1] # Adjust firstEPS at least 1 , prevent npf.rate get NaN if (firstEPS<1): adj = 1 - firstEPS firstEPS = firstEPS + adj lastEPS = lastEPS + adj annualgrowthrate = npf.rate(len(financialreportingdf.eps)-1, 0, -1 * firstEPS,lastEPS) #print("Annual Growth Rate %f" % annualgrowthrate) # Non Conservative #print(financialreportingdf) lasteps = financialreportingdf.eps.tail(1).values[0] # presentvalue #print('1st eps ',financialreportingdf.eps.iloc[0]) #print('last eps ',financialreportingdf.eps.iloc[-1]) #print('annual growth rate ',annualgrowthrate) # conservative # lasteps = financialreportingdf.eps.mean() # np.fv, compute the future value. parameters: interest rate , periods, payment, present value futureeps = abs(npf.fv(annualgrowthrate, years, 0, lasteps)) dfprice.loc[0] = [ticker, annualgrowthrate, lasteps, futureeps] except: print('eps does not exist') dfprice.set_index('ticker', inplace=True) # conservative dfprice['peratio'] = findMinimumPER(stockpricedf, financialreportingdf) # future stock price dfprice['FV'] = dfprice['futureeps'] * dfprice['peratio'] #print('dfprice:\n',dfprice) #print('discountrate: %s' % discountrate) dfprice['PV'] = abs(npf.pv(discountrate, years, 0, fv=dfprice['FV'])) if dfprice['FV'].values[0] > 0: dfprice['marginprice'] = dfprice['PV']*(1-marginrate) else: dfprice['marginprice'] = 0 dfprice['lastprice'] = stockpricedf.Close.tail(1).values[0] dfprice['suggestion'] = np.where( (dfprice['lastprice'] < dfprice['marginprice']), 'BUY', 'SELL') return dfprice
async def eval_budget(income: float, assets: float, curr_expenses: float, retirement_expenses: float, withdraw: float = 0.04, income_growth: float = 0.05): try: goal = retirement_expenses * curr_expenses / withdraw start_year = 1950 curr_year = date.today().year net_worths = [None] * 75 for i in range(len(net_worths)): init = np.random.randint(start_year, curr_year - 10) fv = assets counter = 0 net_worths[i] = [[], []] while fv < 2.5 * goal and counter + init < curr_year: if (sp_500[init + counter] != 0): fv = npf.fv( sp_500[init + counter], 1, -(income * (1 + income_growth * counter) - curr_expenses), -fv) net_worths[i][0].append(fv) if (fv >= goal and not net_worths[i][1]): net_worths[i][1] = counter counter += 1 net_worths = [row for row in net_worths if row[1]] net_worths.sort(key=lambda x: x[1]) graph = [[], [], [], []] graph[3] = net_worths[3 * len(net_worths) // 4 - 1] limit = graph[3][1] graph[0] = [curr_year + i for i in range(limit)] graph[1] = net_worths[len(net_worths) // 4 - 1][0][:limit] graph[2] = net_worths[len(net_worths) // 2 - 1][0][:limit] graph[3] = graph[3][0][:limit] lengths = [i[1] for i in net_worths] return ({'average_years': sum(lengths) / len(lengths), 'graph': graph}) except Exception as e: raise HTTPException(status_code=400, detail=str(e))
def futurevalue(num_years): n = 0 # df_define() rate_index = a_transposed['rate'].loc[0] pmt_index = a_transposed['pmt'].loc[0] pv_index = abs(a_transposed['pv'].loc[0]) index_index = a_transposed['index'].loc[0] global fv_array global fv fv_array.append( round(abs(npf.fv(rate_index / 100, 1, pmt_index, pv_index)), 2)) for n in range(num_years - 1): n += 1 rate_index = a_transposed['rate'].loc[n] pmt_index = a_transposed['pmt'].loc[n] pv_index = fv_array[n - 1] index_index = a_transposed['index'].loc[n] fv = round(abs(npf.fv(rate_index / 100, 1, pmt_index, pv_index)), 2) fv_array.append(fv) # print("rate",amount) # print("rate_array",pmt_array) a.append(fv_array) n = num_years - 1 print("rate", a_transposed['rate'].loc[n]) print("pmt", a_transposed['pmt'].loc[n]) print("PV1", fv_array[n - 1]) print("PV2", a_transposed['pmt'].loc[n]) print( "fv", round( npf.fv(a_transposed['rate'].loc[n] / 100, 1, a_transposed['pmt'].loc[n], fv_array[n - 1]), 2))
async def eval_category(income: float, assets: float, retirement_expenses: float, expenses: float, savings: float, withdraw: float = 0.04, real_rate: float = 0.06, income_growth: float = 0.05): try: monthly_rate = (1 + (real_rate))**(1. / 12) - 1 fv = assets goal = retirement_expenses * expenses * 12 / withdraw original_month = 0 scaled_income = income while fv < goal: fv = npf.fv(monthly_rate, 1, -(scaled_income - expenses), -fv) original_month += 1 scaled_income = scaled_income * (1 + income_growth / 12) new_expenses = expenses - savings month = 0 fv = assets scaled_income = income while fv < goal: fv = npf.fv(monthly_rate, 1, -(scaled_income - new_expenses), -fv) month += 1 scaled_income = scaled_income * (1 + income_growth / 12) time_saved = original_month - month return ({'months saved': time_saved}) except Exception as e: raise HTTPException(status_code=400, detail=str(e))
def get_reg_dep(self) -> float: _fv = (fv( self.rate / (100 * self.freq), self.freq * self.num_of_years, 0, self.ini_dep, self.dep_when, ) + self.fin_bal) self.reg_dep = -pmt( self.rate / (100 * self.freq), self.freq * self.num_of_years, 0, _fv, self.dep_when, ) return self.reg_dep
def generate_decision_1(ticker, financialdf, discountrate, marginrate, stockpriceserie, parameters): lasteps = financialdf.EPS.iloc[-1] dfprice = pd.DataFrame(columns=['ticker', 'lasteps', 'futureeps']) pd.options.display.float_format = '{:20,.2f}'.format # print('parameters', parameters) annualgrowthrate = float(parameters.annual_growth_rate) pe_ratio = float(parameters.pe) n_future_year = 5 try: if 1 + annualgrowthrate >= 0: futureeps = abs(npf.fv(annualgrowthrate, n_future_year, 0, lasteps)) else: # This is necessary to catch following condition: # 1. Last EPS is negative value # 2. 1 + annualgrowthrate < 0 # Necessary because if (1+annualgrowthrate)^5 will result in - value. # And this negative value will negate the negative EPS. # Positive result in this value is mathematicaly correct but against # a healthy understanding about business logic. futureeps = 0 # print('5.1', [ticker, lasteps, futureeps]) dfprice.loc[0] = [ticker, lasteps, futureeps] # print('5.2') except: # print('Last EPS:', lasteps) # print('Annual Growth Rate:', annualgrowthrate) print('EPS does not exist or annual growth rate is missing.') dfprice.set_index('ticker', inplace=True) dfprice['pe'] = pe_ratio dfprice['FV'] = dfprice['futureeps'] * dfprice['pe'] dfprice['PV'] = npf.pv(discountrate, n_future_year, 0, dfprice['FV']) * -1 # print(dfprice[['FV', 'PV']]) dfprice['marginprice'] = np.where((dfprice['futureeps'] > 0), dfprice['PV'] * (1 - marginrate), 0) dfprice['currentshareprice'] = stockpriceserie[-1] dfprice['decision'] = np.where( (dfprice['currentshareprice'] < dfprice['marginprice']), 'Buy', 'Sell') # open_in_excel(dfprice) return dfprice
def __init__(self, data) -> None: self.data = data self.rooms = self.data.get("rooms") self.TOTALS = {} self.O31_Y31 = [] self.D30_D39 = 15292 self.J18 = 36 self.broker = False # C11 self.debt_financing = True # J6 self.mezzanine_financing = True # J26 self.zip_code = self.data.get("zip_code") # C7 self.total_rooms = sum([tp[1] for tp in self.rooms]) # C29 # Sale Assumptions self.sale_period = 48 # C15 self.holding_period = self.sale_period // 12 # C14 self.selling_costs = 0.04 # C16 self.annual_appreciations = 0.03 # C17 # Tax Assumptions self.depreciation_life = 27.5 # C21 self.tax_rate = 0.2 # C22 self.capital_gain_tax = 0.25 # C23 # Operating Assumptions: Per Unit self.managment_per_unit = 35 # F7 self.pest_trash_per_unit = 250 # F8 self.insurance_per_unit = 1000 # F9 self.water_per_unit = 125 # F10 self.utilities_per_unit = 10 # F11 self.maintenance_per_unit = 50 # F12 self.snow_landscape_per_unit = 50 # F13 self.vacancy = 0.02 # F16 # Capex Assumptions self.initial_capex = 10000 # F19 if self.broker: self.capex = (-0.9) * ( 0.02 * self.data.get("price")) + self.initial_capex # O7 else: self.capex = self.initial_capex # Operating Assumptions self.taxes = self.data.get("taxes") self.managment = self.managment_per_unit * self.total_rooms * 12 # G7 self.pest_trash = self.pest_trash_per_unit * 12 # G8 self.insurance = self.insurance_per_unit * self.total_rooms # G9 self.water = self.water_per_unit * self.total_rooms * 12 # G10 self.utilities = self.utilities_per_unit * self.total_rooms * 12 # G11 self.maintenance = self.maintenance_per_unit * self.total_rooms * 12 # G12 self.snow_landscape = self.snow_landscape_per_unit * 12 # G13 self.opex_annual = sum( # G5 [ self.taxes, self.managment, self.pest_trash, self.insurance, self.water, self.utilities, self.maintenance, self.snow_landscape, ]) self.D29 = self.rent_roll_assumptions() # D29 # self.opex_ratio = ceil(self.opex_annual / (self.D29 * 12)) # G14 # Senior Debt Assumptions self.down_payment_percent = 0.25 # J7 self.down_payment_sum = self.down_payment_percent * self.data.get( "price") # J8 self.total_investment = int(self.down_payment_sum + self.initial_capex) self.assumed_value = np.fv( self.annual_appreciations / 12, self.sale_period, 0, -self.data.get("price"), ) self.sale_proceeds_cash_flow = self.assumed_value * ( 1 - self.selling_costs) self.loan_amount = self.senior_debt_assumptions().get("loan_amount") self.monthly_payment = self.senior_debt_assumptions().get( "monthly_payment") self.interest_rate = self.senior_debt_assumptions().get( "interest_rate") refi_table_interest = int(self.loan_amount * (self.interest_rate / 12)) refi_table_principal = self.monthly_payment - refi_table_interest self.REFI_TABLE = { 1: { "beginning_bal": self.loan_amount, "refi_table_interest": refi_table_interest, "refi_table_principal": refi_table_principal, "ending_bal": self.loan_amount - refi_table_principal, }, } for j in range(2, 361): refi_table_interest_dynamic = round( self.REFI_TABLE.get(j - 1).get("ending_bal") * self.interest_rate / 12) refi_table_principal_dynamic = (self.monthly_payment - refi_table_interest_dynamic) self.REFI_TABLE.update( { j: { "beginning_bal": self.REFI_TABLE.get(j - 1).get("ending_bal"), "refi_table_interest": refi_table_interest_dynamic, "refi_table_principal": refi_table_principal_dynamic, "ending_bal": self.REFI_TABLE.get(j - 1).get("ending_bal") - refi_table_principal_dynamic, } }, ) self.net_proceed = self.sale_proceeds_cash_flow - self.REFI_TABLE.get( # M24 self.sale_period).get("ending_bal") self.CASH_FLOW_TABLE = { 1: { "gpi": self.D30_D39, "vl": self.D30_D39 * self.vacancy, "opex": (self.opex_annual / 12), "capex": -self.capex / 12, "dbtsvrs": -(self.monthly_payment), } } for i in range(2, self.holding_period + 1): current_gpi = round( self.CASH_FLOW_TABLE[i - 1].get("gpi") + (self.CASH_FLOW_TABLE[i - 1].get("gpi") * 0.01), 0, ) current_opex = round(self.CASH_FLOW_TABLE[i - 1].get("opex") + (self.CASH_FLOW_TABLE[i - 1].get("opex") * 0.02)) current_capex = round(self.CASH_FLOW_TABLE[i - 1].get("capex") * 0, 0) self.CASH_FLOW_TABLE.update({ i: { "gpi": current_gpi, "vl": ceil(current_gpi * self.vacancy), "opex": current_opex, "capex": current_capex, "dbtsvrs": -(self.monthly_payment), }, })
# Calculate investment_1 investment_1 = npf.pv(rate=0.03, nper=15, pmt=0, fv=10000) # Note that the present value returned is negative, so we multiply the result by -1 print("Investment 1 is worth " + str(round(-investment_1, 2)) + " in today's dollars") # Calculate investment_2 investment_2 = npf.pv(rate=0.05, nper=10, pmt=0, fv=10000) print("Investment 2 is worth " + str(round(-investment_2, 2)) + " in today's dollars") import numpy_financial as npf # Calculate investment_1 investment_1 = npf.fv(rate=0.05, nper=15, pmt=0, pv=-10000) print("Investment 1 will yield a total of $" + str(round(investment_1, 2)) + " in 15 years") # Calculate investment_2 investment_2 = npf.fv(rate=0.08, nper=15, pmt=0, pv=-10000) print("Investment 2 will yield a total of $" + str(round(investment_2, 2)) + " in 15 years") import numpy as np import numpy_financial as npf # Calculate investment_1 investment_1 = npf.fv(rate=0.08, nper=10, pmt=0, pv=-10000) print("Investment 1 will yield a total of $" + str(round(investment_1, 2)) + " in 10 years")
future value : -> float 终值 ''' if interest_type == 'simple': final = principal * (1 + rate * n) elif interest_type == 'compound': final = principal * (1 + rate)**n elif interest_type == 'continuous': final = principal * np.exp(rate * n) else: raise Exception('Invalid Type!') return final #%% # 计算终值 npf.fv(0.1, 4, 0, -1000) # 计算现值 npf.pv(0.1, 4, 0, -1500) # 计算净现值 rate, cashflows = 0.08, [-40_000, 5_000, 8_000, 12_000, 30_000] npf.npv(rate, cashflows).round(5) #%% npf.pv(0.06, 3, -100, 0) npf.pv(0.06, 3, -100, 0, when='begin') # 验证 npf.pv(0.06, 3, 100, 0, when='begin') / npf.pv(0.06, 3, 100, 0) == 1.06
def test_float(self): assert_allclose( npf.fv(0.075, 20, -2000, 0, 0), 86609.362673042924, rtol=1e-10, )
def future_value(rate, nper, pmt, pv): global y # y = Decimal(npf.fv(rate, nper, pmt, pv)) y = (npf.fv(rate, nper, pmt, pv))
) #SAVING AND LOADING NUMPY OBJECTS arr_15 = np.array([[1, 2], [3, 4]]) np.save('randarray', arr_15) arr_16 = np.load('randarray.npy') arr_16 np.savetxt('randcsv.csv', arr_15) arr_17 = np.loadtxt('randcsv.csv') print(arr_17) print( "#**********************#FINANCIAL FUNCTIONS#**************************#") #FINANCIAL FUNCTIONS import numpy_financial as npf npf.fv(8 / 12, 10 * 12, -400, 400) period = np.arange(1 * 12) + 1 principle = 3000.00 ipmt = npf.ipmt(0.0925 / 12, period, 1 * 12, principle) ppmt = npf.ipmt(0.0925 / 12, period, 1 * 12, principle) for payment in period: index = payment - 1 principle = principle + ppmt[index] print( f"{payment} {np.round(ppmt[index],2)} {np.round(ipmt[index],2)} {np.round(principle,2)}" ) np.round(npf.nper(0.0925 / 12, -150, 3000.00), 2) npf.npv(0.08, [-1500, 4000, 5000, 6000, 7000])
def test_broadcast(self): result = npf.fv([[0.1], [0.2]], 5, 100, 0, [0, 1]) # All values computed using Google Sheet's FV desired = [[-610.510000, -671.561000], [-744.160000, -892.992000]] assert_allclose(result, desired, rtol=1e-10)
def plot_affordability( savings: int, saving_rate: int, r: float, income: int, rate_type: str, lti: float, target_date: str) -> Tuple[go.Figure, str, str, str, str, str]: """ Callback to populate data in the savings plot according to the input values entered by user. Assumes that all interest is paid monthly at a rate of 1/12 * r and all reinvested. Stores data to data-store. Args: savings: Total current savings saving_rate: Amount saved each month r: interest rate (%) income: user input income (£ thousands) rate_type: type of stamp duty rate payable lti: loan to income ratio target_date: purchase date with format YYYY-MM-DD """ if all(v is not None for v in [savings, saving_rate, r, income, lti, target_date]): fig = go.Figure() start_date = datetime.datetime.today().date() target_date = datetime.datetime.strptime(target_date, "%Y-%m-%d") periods = (target_date.year - start_date.year) * 12 + ( target_date.month - start_date.month) + 1 x = pd.date_range(datetime.datetime.now(), periods=periods, freq="M") savings_array = np.array([ npf.fv((r / 100) / 12, i, -saving_rate, -(savings * 1000)) for i in range(periods) ]) mortgage = lti * (income * 1000) budget = np.array([ iterative_p(s, mortgage, stamp_duty_payable, rate_type, target_date)[1] for s in savings_array ]) fig.add_trace( go.Scatter( x=x, y=budget, fillcolor="rgba(0,176,246,0.2)", line={ "color": "black", "width": 0.8 }, hovertemplate= "Date: %{x} \nMax affordable: £%{y:,.3r}<extra></extra>", )) # Work out the values on the target date start_date = datetime.datetime.today() num_months = (target_date.year - start_date.year) * 12 + ( target_date.month - start_date.month) mortgage = lti * income * 1000 savings_on_target_date = npf.fv((r / 100) / 12, num_months, -saving_rate, -(savings * 1000)) # Work out deposit, stamp duty and max affordable price for each mortgage size deposit, property_value, stamp_duty = iterative_p( savings_on_target_date, mortgage, stamp_duty_payable, rate_type, target_date) deposit_on_target_date_str = f"£{int(deposit): ,}" mortgage_on_target_date_str = f"£{int(mortgage): ,}" property_value_on_target_date_str = f"£{int(property_value): ,}" stamp_duty_on_target_date_str = f"£{int(stamp_duty): ,}" data_storage = { "savings": savings_on_target_date / 1000, "deposit": deposit, "mortgage": mortgage, "value": property_value, "stamp_duty": stamp_duty, "stamp_duty_rate": rate_type, "income": income, "target_date": target_date.strftime("%Y-%m-%d") } data_storage = json.dumps(data_storage) return ( fig, deposit_on_target_date_str, mortgage_on_target_date_str, property_value_on_target_date_str, stamp_duty_on_target_date_str, data_storage, ) else: raise PreventUpdate
import numpy_financial as npf res = npf.fv(rate=1, nper=1, pmt=0, pv=-100) print(res)
print('*'*50) while continue_yn=='y': if question == 'ask': question = input('Do you wish to (M)anually Calculate your PV & FV, or run the (A)ssignment Numbers (M or A)?').upper() if question == 'M': print() cash = float(input('Enter in the Original Price: ')) rate = float(input("Enter in the Intreset Rate (i.e. 5% is 0.05): ")) nper = float(input("Enter in the Number of Years: ")) pmt = float(input("Enter in the Yearly Revenue: ")) pv = np.pv(rate, nper, pmt, cash) fv = np.fv(rate, nper, pmt, pv) print('*'*50) print(f'Intial Investment:$ {cash}') print(f'Intrest Rate: {rate*100}%') print(f'Revenue:$ {pmt}') print(f'Number of Periods: {nper}') investmentGB(pv, fv) print() continue_yn = input('Do you wish to continue? (Y or N)').lower() print() elif question == 'A':
import numpy_financial as npf '''fv:计算预估投资价值''' rate = 0.035 nper = 20 pmt = -2000 pv = -1000000 fv = npf.fv(rate=rate / 12, nper=nper * 12, pmt=pmt, pv=pv) # rate:年化投资回报率 # nper:投资年数 # pmt:每月投入资金(负值) # pv:期初值(负值) print( f'期初资产¥{abs(pv)}元,每月再投入¥{abs(float(pmt)):.2f}元,年均收益率{rate * 100:.2f}%,{nper}年后期末价值为:¥{abs(fv):.2f}元。' ) '''pv:计算未来金额在现在的价值''' rate = 0.035 nper = 20 pmt = -2000 fv = 5000000 pv = npf.pv(rate=rate / 12, nper=nper * 12, pmt=pmt, fv=fv) # rate:年化投资回报率 # nper:投资年数 # pmt:每月投入资金(负值) # fv:预期达到的资产总值(正值) print( f'年均收益率{rate * 100:.2f}%,每月投入¥{abs(float(pmt)):.2f}元,投资{nper}年后,期末资产¥{abs(float(fv)):.2f}元,需要投入本金:¥{abs(pv):.2f}元。' ) '''pmt:计算每期支付金额''' rate = 0.075 nper = 20 pv = 1000000
def test_decimal(self): assert_almost_equal( npf.fv(Decimal('0.075'), Decimal('20'), Decimal('-2000'), 0, 0), Decimal('86609.36267304300040536731624'), decimal=10, )
def future_value(n, iy, pv): future_value = pv * (1 + iy)**n print(future_value, " future value of inv") def discount_factor(iy, n): disc = 1 / (1 + iy)**n print(str(round(disc, 5)), ' discount factor') TVM.compound_int(n=2, iy=.05, pv=100) TVM.future_value(n=2, iy=.05, pv=100) TVM.discount_factor(n=2, iy=.05) inv = npf.pv(rate=.05, nper=10, pmt=0, fv=100000) investment_2 = npf.fv(rate=.08, nper=10, pmt=0, pv=-100000) print("Investment 2 will yield a total of $" + str(round(investment_2, 2)) + " in 10 years") print(inv) # Calculate investment_3 investment_3 = npf.fv(rate=.08, nper=10, pmt=0, pv=-100000) print("Investment 3 will yield a total of $" + str(round(investment_3, 2)) + " in 10 years") # Calculate investment_3 and adjsut for inflation of 3% investment_3_discounted = npf.pv(rate=.03, nper=10, pmt=0, fv=investment_3) print("After adjusting for inflation, investment 3 is worth $" + str(round(-investment_3_discounted, 2)) + " in today's dollars") #Discounting cashflows with NPV # NPV = sum of all discounted cashflows
def get_fv(self): return fin.fv(self.rate, self.n, self.pmt, self.pv, self.when)[0]
def update_plot( cash_r: float, property_r: float, securities_r: float, rental_income: int, rental_income_months: int, cash_allocation: int, securities_allocation: int, mortgage_idx: int, bills: int, housing_upkeep: int, rent_out: int, savable_income: int, allocation_scenarios: str, mortgage_data: str, ) -> Tuple[go.Figure, str]: """ Updates plot showing household balance sheet and income / expenditure over time. Args: cash_r: rate of return on cash (%) property_r: rate of return on property (%) securities_r: rate of return on securities (%) rental_income: expected rental income (£ /month) rental_income_months: number of months expected rental income cash_allocation: user initial allocation to cash (£ ,000) securities_allocation: user initial allocation to securities (£ ,000) mortgage_idx: index of selected mortgage bills: monthly bills (£) housing_upkeep: monthly housing upkeep (£) rent_out: monthly rent expenditure (£) savable_income: monthly savable income (£) allocation_scenarios: JSON str of saved scenarios mortgage_data: JSON str of saved mortgage data Returns: go.Figure object of household balance sheet and income / expenditure statement """ # Will only show plot if a mortgage has been selected if mortgage_idx is None: raise PreventUpdate data = json.loads(mortgage_data) mortgage = data[mortgage_idx] # Set date range to mortgage term term = mortgage.get("term", 20) * 12 x = pd.date_range(datetime.datetime.now(), periods=term, freq="M") fig = go.Figure() # 3. Liabilities if mortgage.get("mortgage_size", 0) == 0: mortgage_balance = np.array([0] * term) else: mortgage_balance = _get_mortgage_balance(mortgage) fig.add_trace( go.Scatter( x=x, y=mortgage_balance, fillcolor="rgba(0,176,246,0.2)", line={ "color": "red", "width": 1.5 }, name="Liabilities", hovertemplate="Date: %{x} \nTotal value: £%{y:,.3r}<extra></extra>", )) # 4. Assets cash_array = np.array([ npf.fv((cash_r / 100) / 12, i, 0, -(cash_allocation * 1000)) for i in range(term) ]) fig.add_trace( go.Scatter( x=x, y=cash_array, fillcolor="rgba(0,176,246,0.2)", line={ "color": "green", "width": 0.8 }, name="Cash", hovertemplate="Date: %{x} \nCash value: £%{y:,.3r}<extra></extra>", )) purchase_price = mortgage.get("purchase_price") property_array = np.array([ npf.fv((property_r / 100) / 12, i, 0, -(purchase_price * 1000)) for i in range(term) ]) fig.add_trace( go.Scatter( x=x, y=property_array, fillcolor="rgba(0,176,246,0.2)", line={ "color": "orange", "width": 0.8 }, name="Property", hovertemplate= "Date: %{x} \nProperty value: £%{y:,.3r}<extra></extra>", )) # TODO: Fix bug where not updated if rent isn't set to a number # Assumes that all net income is reinvested in securities if all(v is not None for v in [savable_income, rental_income, bills, housing_upkeep, rent_out]): # Get the net income during rent period net_income_rental_period = _get_net_savings(savable_income, rental_income, bills, housing_upkeep, rent_out) rental_income_months = min(term, rental_income_months) net_income_rental_period = np.array([net_income_rental_period] * rental_income_months) securities_array_rent = np.array([ npf.fv((securities_r / 100) / 12, i, -net_income, -(securities_allocation * 1000)) for i, net_income in enumerate(net_income_rental_period) ]) # Get the net income during post rent period post_rent_months = term - rental_income_months if post_rent_months > 0: net_income_post_rental_period = _get_net_savings( savable_income, 0, bills, housing_upkeep, rent_out) net_income_post_rental_period = np.array( [net_income_post_rental_period] * post_rent_months) start_balance = (securities_array_rent[-1] if len(securities_array_rent) > 0 else securities_allocation * 1000) securities_array_post_rent = np.array([ npf.fv((securities_r / 100) / 12, i, -net_income, -start_balance) for i, net_income in enumerate(net_income_post_rental_period) ]) securities_array = np.append(securities_array_rent, securities_array_post_rent) else: securities_array = securities_array_rent else: securities_array = np.array([ npf.fv((securities_r / 100) / 12, i, -0, -(securities_allocation * 1000)) for i in range(term) ]) fig.add_trace( go.Scatter( x=x, y=securities_array, fillcolor="rgba(0,176,246,0.2)", line={ "color": "purple", "width": 0.8 }, name="Securities", hovertemplate= "Date: %{x} \nSecurities value: £%{y:,.3r}<extra></extra>", )) total_array = cash_array + property_array + securities_array fig.add_trace( go.Scatter( x=x, y=total_array, fillcolor="rgba(0,176,246,0.2)", line={ "color": "green", "width": 1.5 }, name="Total assets", hovertemplate="Date: %{x} \nTotal value: £%{y:,.3r}<extra></extra>", )) # 5. Wealth wealth = total_array - mortgage_balance fig.add_trace( go.Scatter( x=x, y=wealth, fillcolor="rgba(0,176,246,0.2)", line={ "color": "black", "width": 2 }, name="Wealth", hovertemplate="Date: %{x} \nTotal value: £%{y:,.3r}<extra></extra>", )) # Show other scenarios if allocation_scenarios is not None: allocation_scenarios = json.loads(allocation_scenarios) for scenario in allocation_scenarios: dates = [ datetime.datetime.strptime(i, "%Y-%m-%d") for i in scenario["x"] ] data = dict(zip(dates, scenario["wealth"])) scenario_data = [] for date in x: date = date.to_pydatetime().replace(hour=0, minute=0, second=0, microsecond=0) if date in data.keys(): scenario_data.append(data[date]) else: scenario_data.append(np.nan) fig.add_trace( go.Scatter( x=x, y=scenario_data, fillcolor="rgba(0,176,246,0.2)", line={ "color": "grey", "width": 2 }, name=scenario["name"], hovertemplate= "Date: %{x} \nTotal value: £%{y:,.3r}<extra></extra>", )) x_as_str = x.format(formatter=lambda x: x.strftime("%Y-%m-%d")) allocation_scenario = json.dumps({ "x": list(x_as_str), "wealth": list(wealth) }) return fig, allocation_scenario
def test_when_is_begin_float(self, when): assert_allclose( npf.fv(0.075, 20, -2000, 0, when), 93105.064874, # Computed using Google Sheet's FV rtol=1e-10, )