From cafe2da4845dca174ba47fc5337004d52a24b28b Mon Sep 17 00:00:00 2001 From: Roland W-H Date: Tue, 28 Jan 2025 15:25:41 +0000 Subject: [PATCH] initial commit --- .gitignore | 1 + .idea/SIPPCompare.iml | 10 + .../inspectionProfiles/profiles_settings.xml | 7 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 118 ++++++++++++ gui/main_gui.ui | 174 ++++++++++++++++++ gui/output_window.ui | 71 +++++++ gui/platform_edit.ui | 70 +++++++ src/main.py | 9 + src/main_window.py | 88 +++++++++ src/output_window.py | 28 +++ src/platform_edit.py | 7 + 13 files changed, 597 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/SIPPCompare.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 gui/main_gui.ui create mode 100644 gui/output_window.ui create mode 100644 gui/platform_edit.ui create mode 100644 src/main.py create mode 100644 src/main_window.py create mode 100644 src/output_window.py create mode 100644 src/platform_edit.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b25f85e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/designer.exe - Shortcut.lnk diff --git a/.idea/SIPPCompare.iml b/.idea/SIPPCompare.iml new file mode 100644 index 0000000..cbfcce6 --- /dev/null +++ b/.idea/SIPPCompare.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..dd4c951 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e316109 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..4e4c334 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + { + "associatedIndex": 4 +} + + + + + + + + + + + + + + + + + + + + + + + + + + 1737895685673 + + + + + + + \ No newline at end of file diff --git a/gui/main_gui.ui b/gui/main_gui.ui new file mode 100644 index 0000000..13203cf --- /dev/null +++ b/gui/main_gui.ui @@ -0,0 +1,174 @@ + + + MainWindow + + + + 0 + 0 + 420 + 250 + + + + + 420 + 250 + + + + + 420 + 250 + + + + SIPPCompare + + + QTabWidget::TabShape::Rounded + + + + + + 10 + 0 + 401 + 191 + + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + Pension value + + + + + + + £0000000000 + + + £ + + + 11 + + + true + + + 1 + + + + + + + Investment mix (funds 50% / shares 50%) + + + Qt::AlignmentFlag::AlignCenter + + + + + + + 100 + + + 50 + + + Qt::Orientation::Horizontal + + + QSlider::TickPosition::NoTicks + + + + + + + Annual share trades + + + + + + + true + + + + + + + Annual fund trades + + + + + + + true + + + + + + + Calculate + + + + + + + + + true + + + + + + 0 + 0 + 420 + 33 + + + + + File + + + + + + + + Edit Platforms + + + + + + diff --git a/gui/output_window.ui b/gui/output_window.ui new file mode 100644 index 0000000..60a66d4 --- /dev/null +++ b/gui/output_window.ui @@ -0,0 +1,71 @@ + + + ResultsWindow + + + + 0 + 0 + 400 + 300 + + + + + 400 + 300 + + + + + 400 + 300 + + + + Results + + + + + 10 + 10 + 380 + 250 + + + + + + + 320 + 270 + 75 + 24 + + + + OK + + + + + + + res_ok_but + clicked(bool) + ResultsWindow + close() + + + 357 + 281 + + + 199 + 149 + + + + + diff --git a/gui/platform_edit.ui b/gui/platform_edit.ui new file mode 100644 index 0000000..9f04d99 --- /dev/null +++ b/gui/platform_edit.ui @@ -0,0 +1,70 @@ + + + PlatformEdit + + + + 0 + 0 + 771 + 502 + + + + Platform Editor + + + + + 180 + 130 + 331 + 191 + + + + true + + + + + 0 + 0 + 329 + 189 + + + + + + 10 + 10 + 311 + 141 + + + + + up to + + + + + + + 210 + 160 + 111 + 24 + + + + PushButton + + + + + + + + diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..1dbe58c --- /dev/null +++ b/src/main.py @@ -0,0 +1,9 @@ +import sys + +from PyQt6.QtWidgets import QApplication +import main_window + +app = QApplication(sys.argv) +window = main_window.SIPPCompare() +window.show() +app.exec() diff --git a/src/main_window.py b/src/main_window.py new file mode 100644 index 0000000..6ce7546 --- /dev/null +++ b/src/main_window.py @@ -0,0 +1,88 @@ +from PyQt6.QtWidgets import QMainWindow +from PyQt6 import uic +import platform_edit +import output_window + + +class SIPPCompare(QMainWindow): + def __init__(self): + super().__init__() + uic.loadUi("gui/main_gui.ui", self) + + # Define class variables + self.tiered_fees = [ + [0, 250000, 1000000, 2000000], + [0, 0.25, 0.1, 0.05] + ] + self.fund_deal_fee = 1.5 + self.share_plat_fee = 0.0025 + self.share_plat_max_fee = 3.5 + self.share_deal_fee = 5 + self.share_deal_reduce_trades = 10 + self.share_deal_reduce_amount = 3.5 + + self.result = None + self.platform_win = None + self.output_win = None + + # Handle events + self.calc_but.clicked.connect(self.calculate_fee) + self.actionEdit_Platforms.triggered.connect(self.show_platform_edit) + self.mix_slider.valueChanged.connect(self.update_slider_lab) + + # Display slider position as mix between two nums (funds/shares) + def update_slider_lab(self): + slider_val = self.mix_slider.value() + self.mix_lab.setText(f"Investment mix (funds {slider_val}% / shares {100 - slider_val}%)") + #mix_percent_lab_str = f"{slider_val}% / {100 - slider_val}%" + #self.mix_percent_lab.setText(mix_percent_lab_str) + + # Calculate fees + def calculate_fee(self): + value_num = float(self.value_input.text()[1:]) + slider_val = self.mix_slider.value() + funds_value = (slider_val / 100) * value_num + fund_trades_num = int(self.fund_trades_combo.currentText()) + fund_deal_fees = fund_trades_num * self.fund_deal_fee + fund_plat_fees = 0 + remaining = funds_value + + for i in range(1, len(self.tiered_fees[0])): + band = self.tiered_fees[0][i] + prev_band = self.tiered_fees[0][i - 1] + fee = self.tiered_fees[1][i] + gap = (band - prev_band) + + if remaining > gap: + fund_plat_fees += gap * (fee / 100) + remaining -= gap + else: + fund_plat_fees += remaining * (fee / 100) + break + + shares_value = (1 - (slider_val / 100)) * value_num + share_plat_fees = self.share_plat_fee * shares_value + if (share_plat_fees / 12) > self.share_plat_max_fee: + share_plat_fees = self.share_plat_max_fee * 12 + share_trades_num = int(self.share_trades_combo.currentText()) + share_deal_fees = self.share_deal_fee * share_trades_num + if (share_trades_num / 12) > self.share_deal_reduce_trades: + share_deal_fees = self.share_deal_reduce_amount * share_trades_num + + self.show_output_win(fund_plat_fees, fund_deal_fees, share_plat_fees, share_deal_fees) + + # Show the output window - this func is called from calculate_fee() + def show_output_win(self, fund_plat_fees, fund_deal_fees, share_plat_fees, share_deal_fees): + # Check window isn't already open + if self.output_win is None: + self.output_win = output_window.OutputWindow() + # Refresh the results when new fees are calculated + self.output_win.display_output(fund_plat_fees, fund_deal_fees, share_plat_fees, share_deal_fees) + self.output_win.show() + + # Show the platform editor window (currently useless) + def show_platform_edit(self): + # Check window isn't already open + if self.platform_win is None: + self.platform_win = platform_edit.PlatformEdit() + self.platform_win.show() diff --git a/src/output_window.py b/src/output_window.py new file mode 100644 index 0000000..e618f8a --- /dev/null +++ b/src/output_window.py @@ -0,0 +1,28 @@ +from PyQt6.QtWidgets import QWidget +from PyQt6 import uic + +class OutputWindow(QWidget): + def __init__(self): + super().__init__() + uic.loadUi("gui/output_window.ui", self) + + def display_output(self, fund_plat_fees: float, fund_deal_fees: float, + share_plat_fees: float, share_deal_fees: float): + results_str = "Fees breakdown:" + + results_str += "\n\nPlatform fees:" + results_str += f"\n\tFund platform fees: £{round(fund_plat_fees, 2):.2f}" + results_str += f"\n\tShare platform fees: £{round(share_plat_fees, 2):.2f}" + total_plat_fees = fund_plat_fees + share_plat_fees + results_str += f"\n\tTotal platform fees: £{round(total_plat_fees, 2):.2f}" + + results_str += "\n\nDealing fees:" + results_str += f"\n\tFund dealing fees: £{round(fund_deal_fees, 2):.2f}" + results_str += f"\n\tShare dealing fees: £{round(share_deal_fees, 2):.2f}" + total_deal_fees = fund_deal_fees + share_deal_fees + results_str += f"\n\tTotal dealing fees: £{round(total_deal_fees, 2):.2f}" + + total_fees = total_plat_fees + total_deal_fees + results_str += f"\n\nTotal fees: £{round(total_fees, 2):.2f}" + + self.output.setText(results_str) diff --git a/src/platform_edit.py b/src/platform_edit.py new file mode 100644 index 0000000..1e17db2 --- /dev/null +++ b/src/platform_edit.py @@ -0,0 +1,7 @@ +from PyQt6.QtWidgets import QWidget +from PyQt6 import uic + +class PlatformEdit(QWidget): + def __init__(self): + super().__init__() + uic.loadUi("gui/platform_edit.ui", self)