How to calculate mortgage with a floating rate that compounds monthly - python

I am solving this problem where im given a floating rate of 5.1 that increases .1 every month. (5.1, 5.2 ... 5.9, 6%)
It also compounds monthly. Im given an initial loan of 200,000. Monthly payments of 1000 and im trying to solve how much they owe every month.
I am using Pandas Series to hold the increasing rate. Im having difficulty creating a function that will help. Any suggestions would be appreciated.
This is what I have.
`
df = pd.DataFrame(51*np.ones(100) + np.arange(100))
df = df.rename(columns={0:'monthly rate'})
df['monthly rate'] = df['monthly rate'] /10/100 /12
df['monthly payment'] = 1000
df['interest due'] = df['monthly rate'] * 200000
df['mortgage decreasing'] = df['interest due'] - df['monthly payment']
`
This is where I get confused. So we start with 200,000. And it decreases each month, and then that decrease we calculate the new interest due using that new amount. So its like one involved the other and im not sure how to put that into code.
I think where im going wrong is in the calculating interest due portion. Since in that code I am multiplying the rate by the initial loan value, instead of the values of each month. Im just unsure how to solve that.

Just in plain Python you can simulate it like this:
loan = 200000
interest = 0.051
payment = 1000
interest_change = 0.001
month = 1
while month < 37:
# In real life banks calculates interest per day, not 1/12 of year
month_interest = loan * interest/12
new_loan = loan+month_interest-payment
print ("%s: %.2f \t +%.2f (%.2f %%) \t-%s \t -> %.2f " % (month,loan,month_interest, interest*100, payment, new_loan))
loan = new_loan
interest += interest_change
month += 1
if loan < 0:
break

Related

Calculate average asset price when using netting instead of hedging

I'm trying to come up with a formula to calculate the average entry/position price to further update my stop loss and take profit.
For example opened BTC buy position with amount of 1 when price was 20000.
Later when price dropped down to 19000 we made another buy using the same amount of 1, "avereging" the position to the middle, so end up with position at 19500 with amount of 2.
Where I'm struggling is what if we want to increase the order size on each price.
Say 1 at 20000, 1.5 at 19500, 2 at 19000 and so on.
Or made new buys of the same amount but shorter distance between.
Inital buy at 20000. then 19000 then 19150
Or combine these two variants.
I use mainly Python and Pandas. Maybe the latter one has some built-in function which I'm not aware of. I checked the official Pandas docs, but found only regular mean function.
Thanks to Yuri's suggestion to look into VWAP, I came up with the following code, which is more advanced and allows you to use different contract/volume sizes and increase/decrease "distance" between orders.
As an example here I used avarage price of BTC 20000 and increased steps distance using 1.1 multiplier as well as increased volume. Operated in Binance futures terms, where you can buy minimum 1 contract for 10$.
The idea is to find sweet spot for orders distance, volume, stop loss and take profit while avereging down.
# initial entry price
initial_price = 20000
# bottom price
bottom_price = 0
# enter on every 5% price drop
step = int(initial_price*0.05)
# 1.1 to increase distance between orders, 0.9 to decrease
step_multiplier = 1.1
# initial volume size in contracts
initial_volume = 1
# volume_multiplier, can't be less than 1, in case of use float, will be rounded to decimal number
volume_multiplier = 1.1
# defining empty arrays
prices = []
volumes = []
# checking if we are going to use simple approach with 1 contract volume and no sep or volume multiplier
if step_multiplier == 1 and volume_multiplier == 1:
prices = range(initial_price,bottom_price,-step)
else:
# defining current price and volume vars
curr_price = initial_price
curr_volume = initial_volume
# Checking if current price is still bigger then defined bottom price
while curr_price > bottom_price:
# adding current price to the list
prices.append(curr_price)
# calulating next order price
curr_price = curr_price-step*step_multiplier
# checking if volume multiplier is bigger then 1
if volume_multiplier > 1:
# adding current volume to the list
volumes.append(int(curr_volume))
# calulating next order volume
curr_volume = curr_volume*volume_multiplier
print("Prices:")
for price in prices:
print(price)
print("Volumes:")
for volume in volumes:
print(volume)
print("Prices array length", len(prices))
print("Volumes array length", len(volumes))
a = [item1 * item2 for item1, item2 in zip(prices, volumes)]
b = volumes
print("Average position price when price will reach",prices[-1], "is", sum(a)/sum(b))

Pandas dataframe trading gain/loss

Dataframe
(Disregard the two index columns)
level_0
index
Year
Month
Day
Open
High
Low
Close
Volume
Length
Polarity
Sentiment_Negative
Sentiment_Neutral
Sentiment_Positive
Target_variable
Predicted
0
0
0
2020
1
19
8941.45
9164.36
8620.08
8706.25
3.42173e+10
937.167
0.0884653
0
0
1
0
0
1
1
1
2020
1
18
8927.21
9012.2
8827.33
8942.81
3.23378e+10
1177.5
0.176394
0
0
1
1
1
2
2
2
2020
1
17
8725.21
8958.12
8677.32
8929.04
3.63721e+10
1580
0.216762
0
0
1
0
0
3
3
3
2020
1
16
8812.48
8846.46
8612.1
8723.79
3.1314e+10
1336.33
0.182707
0
0
1
0
0
Description
The value of the target_variable is 1 if todays closing price is greater than yesterdays closing price
The value of the target_variable is 0 if todays closing price is less than yesterdays closing price
The predicted value is the output of my classifier.
Problem
I need to run some code that tracks how much money is gained if I invest when the classifier tells me to invest
I have started to code this
credit = 10000
for index, row in df.iterrows():
if row["Predicted"] == 1:
#print(row["Percentage_diff"])
credit = credit - 100
credit = credit + (100 * row["Percentage_diff"])
print(credit)
The idea is that I start off with a balance of 10,000 and invest 100 every time the classifier signals to. The only problem is that when I lose 8000 credits. Is the code correct and the classifier is very poor?
Or have I made an error in the code?
I am not a trading expert, so I assume that every day the classifier tells you to trade, you will buy with the opening price and sell with the close price.
You can start by calculating the percentage of profit or loss when the classifier tells you to trade. You can do that by subtracting the closing price from the opening and dividing it by the opening price.
df["perc_diff"] = (df["Close"] - df["Open"])/df["open"]
Of course, this will be negative when the classifier is wrong. To compute the cumulative profits/losses, all you want to do is to iteratively add/subtract your profit/loss to your capital. This means at a day with a profit/loss percentage of r, if you invest x dollars, your new credit is (1+r)*x. So a simple for loop can do it like that:
credit = 1 # your capital
for label, row in df.iterrows():
credit = (1 + row["Predicted"] * r) * row["perc_diff"]
print(credit)
Edit to address your updated problem:
If you want to specify an amount to invest rather than all your capital, then you can use this:
credit = 1 # your capital
to_invest = 0.1 # money to invest
for label, row in df.iterrows():
# update invest
invest_update = (1 + row["Predicted"] * row["perc_diff"]) * to_invest
credit = credit - to_invest + invest_update
print(credit)
The last two lines can be combined into one line:
credit = credit + row["Predicted"] * row["perc_diff"] * to_invest
I think the code is correct, and if you lose, then it is probably due to poor performance from your classifier, but this should be evident from your evaluation of the model (like accuracy and precision metrics). Also, if it is a classifier that is not made for time series (e.g. logistic regression), then it is very reasonable that it performs poorly.
Solution
df["Percentage_diff"] = (df["Close"] - df["Open"])/df["Open"]
credit = 10000
for index, row in df.iterrows():
if row["Predicted"] == 1:
#print(row["Percentage_diff"])
credit = credit - 100
credit = credit + ((100 * row["Percentage_diff"]) + 100)
print(credit)
This was the solution thanks to Ahmed.
If I start with an original balance of 10000 every time the classifier signals to invest I invest 100 dollars at opening and withdraw at close this calculates the balance.

Compound Interest Calculator - Variable Frequency of Deposits, Deposit Amounts and Daily Variable Interest Rate

I am trying to build a calculator that computes compound interest but with a few quirks. Specifically:
a) I want the deposited amount to vary within a normal distribution for every month until the end of the investment
b) I want the rate of interest to vary within a normal distribution for every day until the end of the investment
I started off with the basics:
# -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
import numpy as np
from tabulate import tabulate
tabulate.PRESERVE_WHITESPACE = True
year = 1
Principal = 1050
Prev_Principal = 0
n = 365
Total_New = 0
FV_prev = 0
for year in range(1,5):
RoR = 0.01*np.random.normal(7.43,4.172,1)
PMT = np.random.normal(575,85.39,1)
FV = PMT*(12/n)*((1+(RoR/n))**(n*year)-1)/(RoR/n)
Total = FV + Principal*(1+(RoR/n))**(n*year)
Total_New = Total - Total_New
Net_Gain = Total - (year*12*PMT+Principal)
print(tabulate([["YEAR","FV","TOTAL","CI", "R%"],[year,np.round(FV,1),np.round(Total,1),np.round(Net_Gain,1),np.round(100*RoR,1)]], headers="firstrow", tablefmt='fancy_grid'))
This basic version just outputs the sum at the end of the year including the interest as well as the net interest by year. Unfortunately, although it varies the interest rate, it only does so once per year. I plan on doing the following however I am not sure if it's correct, both in terms of programming and mathematically. So I want to take these:
FV = PMT*(12/n)*((1+(RoR/n))-1)/(RoR/n)
Total = FV + Principal*(1+(RoR/n))**(n*year)
and use
RoR_Array = 0.01*np.random.normal(7.43,4.172, 365)
math.prod((1+RoR_Array/365))
With RoR_Array I am basically trying to create a 1D ray with 365 elements, one for each day of the year, which represents the daily interest rate.
With 'math prod' I am trying to overcome the following issue:
If n=365, that means that interest is fixed for the year and compounded daily so
Total = FV + Principal*(1+(RoR/365))**(365*1)
But since I want a variable daily RoR, what's the best way of doing it?
Hence why I am using math.prod.

Plotting (discrete sum over time period) vs. (time period) yields graph with discontinuities

I have some lists related to buying and selling bitcoin.
One is the price (of a buy or sell) and the other is an associated date.
When I plot the total money made (or lost) from my buying/selling over different lengths of time vs. those different lengths of time, the result is 'choppy' - not what I expected. And I think my logic might be wrong
My raw input lists look like:
dates=['2013-05-12 00:00:00', '2013-05-13 00:00:00', '2013-05-14 00:00:00', ....]
prices=[114.713, 117.18, 114.5, 114.156,...]
#simple moving average of prices calced over a short period
sma_short_list = [None, None, None, None, 115.2098, 116.8872, 118.2272, 119.42739999999999, 121.11219999999999, 122.59219999999998....]
#simple moving average of prices calced over a longer period
sma_long_list = [...None, None, None, None, 115.2098, 116.8872, 118.2272, 119.42739999999999, 121.11219999999999, 122.59219999999998....]
Based on the moving average cross-overs (which were calculated based on https://stackoverflow.com/a/14884058/2089889) I will either buy or sell the bitcoin at the date/price where crossover occurred.
I wanted to plot how (much money this approach would have made me as of today) vs. (days ago that I started this approach)
BUT
I am having trouble in that the resulting graph is really choppy. First I thought this was because I have one more buy than sell (or vis-versa) so I tried to account for that. But it was still choppy. NOTE the following code is called in a loop for days_ago in reversed(range(0,approach_started_days_ago)): so each time the following code executes it should spit out how much money that approach would have made had I started it days_ago (I call this bank), and the choppy plot is the days_ago vs. bank
dates = data_dict[file]['dates']
prices = data_dict[file]['prices']
sma_short_list = data_dict[file]['sma'][str(sma_short)]
sma_long_list = data_dict[file]['sma'][str(sma_long)]
prev_diff=0
bank = 0.0
buy_amt, sell_amt = 0.0,0.0
buys,sells, amt, first_tx_amt, last_tx_amt=0,0,0, 0, 0
start, finish = len(dates)-days_ago,len(dates)
for j in range(start, finish):
diff = sma_short_list[j]-sma_long_list[j]
amt=prices[j]
#If a crossover of the moving averages occured
if diff*prev_diff<0:
if first_tx_amt==0:
first_tx_amt = amt
#BUY
if diff>=0 and prev_diff<=0:
buys+=1
bank = bank - amt
#buy_amt = buy_amt+amt
#print('BUY ON %s (PRICE %s)'%(dates[j], prices[j]))
#SELL
elif diff<=0 and prev_diff>=0:
sells+=1
bank = bank + amt
#sell_amt = sell_amt + amt
#print('SELL ON %s (PRICE %s)'%(dates[j], prices[j]))
prev_diff=diff
last_tx_amt=amt
#if buys > sells, subtract last
if buys > sells:
bank = bank + amt
elif sells < buys:
bank = bank - amt
#THIS IS RELATED TO SOME OTHER APPROACH I TRIED
#a = (buy_amt) / buys if buys else 0
#b = (sell_amt) / sells if sells else 0
#diff_of_sum_of_avg_tx_amts = a - b
start_date = datetime.now()-timedelta(days=days_ago)
return bank, start_date
I reasoned that my amount in the 'bank' would be the amount I have sold - the amount I have bought
But, if the first crossover was a sell I don't want to count that (I am going to assume that the first tx I make will be a buy.
Then if the last tx I make is a buy (negative to my bank), I will count today's price into my 'bank'
if last_tx_type=='buy':
sell_amt=sell_amt+prices[len(prices)-1] #add the current amount to the sell amount if the last purchase you made is a buy
if sell_first==True:
sell_amt = sell_amt - first_tx_amt #if the first thing you did was sell, you do not want to add this to money made b/c it was with apriori money
bank = sell_amt-buy_amt

python compounding interest

I'm trying to figure out how to get the interest and principal to display correctly over the years. Here is the part of my code I am having trouble with:
print ('Luke\n-----')
print ('Year\tPrincipal\tInterest\t Total')
LU_RATE = .05
YEAR = 1
Principal = 100
for YEAR in range (1,28):
# Calculating Luke's total using formula for compounding interest
Lu_Total = (Principal * ((1 + LU_RATE) ** YEAR))
# I realize it's a logical error occurring somewhere here
Lu_Interest = #I'm not sure what to code here
Lu_Principal = #And here
# Displaying the Principal, Interest, and Total over the 27
print (YEAR,'\t%.02f\t\t %.02f\t\t %.02f' %(Lu_Principal, Lu_Interest, Lu_Total))
This is what gets displayed (minus the comment symbols of course):
Luke
-----
Year Principal Interest Total
1 # # 105.00
2 # # 110.25
3 # # 115.76
4 # # 121.55
5 # # 127.63
6 # # 134.01
#etc etc....
Every equation I've tried to code had the correct Interest for year one but ends up putting the Principal as the Total. Every year past that calculates out to the wrong numbers.
It should look like:
Luke
-----
Year Principal Interest Total
1 100.00 5.00 105.00
2 105.00 5.25 110.25
3 110.25 5.51 115.76
#etc etc....
I've been working at it on and off throughout the day and just can't seem to figure it out. Thank you in advance for any help or suggestions.
This sounds like homework, so I'll be a little vague:
You have a loop. Your program executes from the top of the loop to the bottom of the loop, and then goes back and starts over at the top of the loop again.
You can change things by setting values in the bottom of the loop that will be used in the top of the loop next time.
For example, you can compute the interest based on this year's principal. You're doing that in the top of the loop.
At the bottom of the loop, after you print everything out for this year, you could change the (next year's) principal by adding (this year's) interest to it. Then 100 would become 105, etc.
And another contestant ;-)
print ('Luke\n-----')
print ('Year\tPrincipal\tInterest\t Total')
rate = .05
principal = 100.
for year in range (1, 28):
# calculate interest and total
interest = principal * rate
total = principal + interest
# displaying this year's values
print(year,'\t%.02f\t\t %.02f\t\t %.02f' %(principal, interest, total))
# next year's principal == this year's total
principal = total
produces
Luke
-----
Year Principal Interest Total
1 100.00 5.00 105.00
2 105.00 5.25 110.25
3 110.25 5.51 115.76
4 115.76 5.79 121.55
# ... etc ...
Here is what I did:
print ('Luke\n-----')
print ('Year\tPrincipal\tInterest\t Total')
LU_RATE = .05
YEAR = 1
Principal = 100
Prev_Principal = 100 #added to store previous year principal
for YEAR in range (1,28):
# Calculating Luke's total using formula for compounding interest
Lu_Total = (Principal * ((1 + LU_RATE) ** YEAR))
Lu_Interest = Lu_Total - Prev_Principal
Lu_Principal = Lu_Total - Lu_Interest
Prev_Principal = Lu_Total
# Displaying the Principal, Interest, and Total over the 27
print (YEAR,'\t%.02f\t\t %.02f\t\t %.02f' %(Lu_Principal, Lu_Interest, Lu_Total))
There may be another way to do this, but I think you have a few issues. One is that you need to base your "total" calculation (where you're multiplying the principal by the 1+rate ** year) on the original principal value, and you need to keep this value separate from the rest of the calculations.
So you can work with two names like p0 and pN, where p0 represents the initial principal at year 0, and pN represents the original principal PLUS accrued interest at year N, then we reassign pN at the end of the loop.
r = .05
p0, pN = 100, p0
for y in range(1,5):
total = p0 * ((1+r)**y)
i = total - pN
print (y,'\t%.02f\t\t %.02f\t\t %.02f' %(pN, i, total))
pN = total
The output is as you expect:

Categories

Resources