Skip to content

Commit

Permalink
Basic prototype for mortgage_gui
Browse files Browse the repository at this point in the history
  • Loading branch information
RmStorm committed Apr 17, 2019
0 parents commit 29aa81b
Show file tree
Hide file tree
Showing 10 changed files with 339 additions and 0 deletions.
126 changes: 126 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Secrets
secrets/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don’t work, or not
# install all needed dependencies.
#Pipfile.lock

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 Roald Storm

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include README.md LICENSE
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Mortgage calculation

This repo contains a small GUI for investigating the tradeoffs of various ways of getting a mortgage.

I started this calculation in excel but because of multiple mortgage offers and several options it seemed to make sense to make something a little more specific and powerful than an excel sheet.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pyside2==5.12.2
79 changes: 79 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# !/usr/bin/env python
# -*- coding: utf-8 -*-

import io
import os

from setuptools import find_packages, setup

# Package meta-data.
NAME = 'astrid-roald-mortgage-gui'
DESCRIPTION = 'A small gui for investigating various mortgages'
URL = 'https://github.com/RmStorm/mortgage_calculation'
EMAIL = '[email protected]'
AUTHOR = 'Roald Storm'
REQUIRES_PYTHON = '>=3.6.0'
VERSION = None

# What packages are required for this module to be executed?
REQUIRED = [
'pyside2'
]

# What packages are optional?
EXTRAS = {
# 'fancy feature': ['some_pakcage'],
}

TEST_REQUIRES = [
["pytest"]
]

here = os.path.abspath(os.path.dirname(__file__))

# Import the README and use it as the long-description.
# Note: this will only work if 'README.md' is present in your MANIFEST.in file!
try:
with io.open(os.path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = '\n' + f.read()
except FileNotFoundError:
long_description = DESCRIPTION

# Load the package's __version__.py module as a dictionary.
about = {}
if not VERSION:
project_slug = NAME.lower().replace("-", "_").replace(" ", "_")
with open(os.path.join(here, 'src', project_slug, '__version__.py')) as f:
exec(f.read(), about)
else:
about['__version__'] = VERSION

# Where the magic happens:
setup(
name=NAME,
version=about['__version__'],
description=DESCRIPTION,
long_description=long_description,
long_description_content_type='text/markdown',
author=AUTHOR,
author_email=EMAIL,
python_requires=REQUIRES_PYTHON,
url=URL,
packages=find_packages(where="src"),
package_dir={"": "src"},
install_requires=REQUIRED,
extras_require=EXTRAS,
tests_require=TEST_REQUIRES,
include_package_data=True,
license='MIT',
classifiers=[
# Trove classifiers
# Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy'
]
)
Empty file.
3 changes: 3 additions & 0 deletions src/astrid_roald_mortgage_gui/__version__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
VERSION = (0, 0, 1)

__version__ = '.'.join(map(str, VERSION))
45 changes: 45 additions & 0 deletions src/astrid_roald_mortgage_gui/mortgage_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import datetime


example_input = {'date of creation': datetime.datetime(2019, 3, 20),
'rent per month': 1000,
'housing money': 2000,
'deposit': 1000,
'total savings': 2000,
'mortgage goal': 400000,
'top loan interest percentage': 10,
'mortgage interest percentage': 1}


def get_monthly_interest_from_yearly(yearly_interest_percentage: float) -> float:
return (1+(yearly_interest_percentage/100))**(1/12)-1


def calculate_cost_with_top_loan(duration, housing_money, mortgage, top_loan,
mortgage_yearly_interest, top_loan_yearly_interest):
mortgage_monthly_interest = get_monthly_interest_from_yearly(mortgage_yearly_interest)
top_loan_monthly_interest = get_monthly_interest_from_yearly(top_loan_yearly_interest)
cumulative_cost = [0]
for i in range(duration):
month_cost = mortgage*mortgage_monthly_interest + top_loan*top_loan_monthly_interest
cumulative_cost.append(month_cost + cumulative_cost[-1])
pay_down = housing_money - month_cost
if top_loan > pay_down:
top_loan = top_loan - pay_down
elif top_loan == 0:
mortgage = mortgage - pay_down
else:
mortgage = mortgage - pay_down + top_loan
top_loan = 0
return cumulative_cost


def main():
print(calculate_cost_with_top_loan(100, example_input['housing money'],
example_input['mortgage goal'] * .85, example_input['mortgage goal'] * .15,
example_input['mortgage interest percentage'],
example_input['top loan interest percentage']))


if __name__ == '__main__':
main()
58 changes: 58 additions & 0 deletions src/astrid_roald_mortgage_gui/mortgage_gui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import sys

from PySide2 import QtWidgets, QtCharts
# from PySide2 import QtCore, QtGui

from astrid_roald_mortgage_gui.mortgage_functions import calculate_cost_with_top_loan, example_input
from astrid_roald_mortgage_gui.secrets.astrid_roald_input import astrid_roald_input


class Mortgage_plotter(QtWidgets.QDialog):
def __init__(self, input_dict, parent=None):
super(Mortgage_plotter, self).__init__(parent)
# Create widgets
self.button = QtWidgets.QPushButton("Plot Graph")
self.edit_widgets = {k: QtWidgets.QLineEdit(str(v)) for k, v in input_dict.items()}

self.chart_view = QtCharts.QtCharts.QChartView()
self.chart_view.chart().createDefaultAxes()

# Create layout and add widgets
layout = QtWidgets.QVBoxLayout()
input_layout = QtWidgets.QFormLayout()
for k, v in self.edit_widgets.items():
input_layout.addRow(k, v)
layout.addLayout(input_layout)
layout.addWidget(self.button)
layout.addWidget(self.chart_view)

# Set layout into widget
self.setLayout(layout)

self.button.clicked.connect(self.add_cost_line)
self.add_cost_line()

def add_cost_line(self):
cost_list = calculate_cost_with_top_loan(100, float(self.edit_widgets['housing money'].text()),
float(self.edit_widgets['mortgage goal'].text()) * .85,
float(self.edit_widgets['mortgage goal'].text()) * .15,
float(self.edit_widgets['mortgage interest percentage'].text()),
float(self.edit_widgets['top loan interest percentage'].text()))
series = QtCharts.QtCharts.QLineSeries()
for i, cost in enumerate(cost_list):
series.append(i, cost)
self.chart_view.chart().addSeries(series)
print("Hello something")


def run_app():
app = QtWidgets.QApplication([])
# widget = Mortgage_plotter(example_input)
widget = Mortgage_plotter(astrid_roald_input)
widget.resize(800, 700)
widget.show()
sys.exit(app.exec_())


if __name__ == '__main__':
run_app()

0 comments on commit 29aa81b

Please sign in to comment.