From c20e1e9d09b8bfcf4e2ba299048c3921dd245658 Mon Sep 17 00:00:00 2001 From: Roland W-H Date: Wed, 29 Jan 2025 18:24:24 +0000 Subject: [PATCH] User-defined fee structure (except tiered) and file saving --- gui/output_window.ui | 13 ++++ gui/platform_edit.ui | 168 +++++++++++++++++++++++++++++++------------ src/main.py | 5 +- src/main_window.py | 70 ++++++++++-------- src/output_window.py | 41 ++++++++--- src/platform_edit.py | 43 +++++++++++ 6 files changed, 252 insertions(+), 88 deletions(-) diff --git a/gui/output_window.ui b/gui/output_window.ui index 60a66d4..698e910 100644 --- a/gui/output_window.ui +++ b/gui/output_window.ui @@ -48,6 +48,19 @@ OK + + + + 240 + 270 + 75 + 24 + + + + Save + + diff --git a/gui/platform_edit.ui b/gui/platform_edit.ui index 9f04d99..b24bfe5 100644 --- a/gui/platform_edit.ui +++ b/gui/platform_edit.ui @@ -6,65 +6,143 @@ 0 0 - 771 - 502 + 484 + 290 Platform Editor - + - 180 - 130 - 331 + 10 + 10 + 461 191 - - true - - - - - 0 - 0 - 329 - 189 - + + + 6 - - - - 10 - 10 - 311 - 141 - - - + + 6 + + + 6 + + + 6 + + + 15 + + + 10 + + + - up to + Share platform fee - - - - - - 210 - 160 - 111 - 24 - - - - PushButton - - - + + + + + + + + + + + + Fund dealing fee + + + + + + + + + + + + + Share platform fee cap + + + + + + + + + + Share dealing fee + + + + + + + Share dealing fee discount + + + + + + + + + + Share dealing discount # of trades + + + + + + + + + 290 + 260 + 191 + 24 + + + + Save + + + fund_deal_fee_box + share_plat_fee_box + share_plat_max_fee_box + share_deal_fee_box + share_deal_reduce_trades_box + share_deal_reduce_amount_box + save_but + - + + + save_but + clicked() + PlatformEdit + close() + + + 445 + 211 + + + 275 + 117 + + + + diff --git a/src/main.py b/src/main.py index 1dbe58c..8247e20 100644 --- a/src/main.py +++ b/src/main.py @@ -1,9 +1,12 @@ +from PyQt6.QtWidgets import QApplication + import sys -from PyQt6.QtWidgets import QApplication import main_window + app = QApplication(sys.argv) window = main_window.SIPPCompare() window.show() +window.show_platform_edit() app.exec() diff --git a/src/main_window.py b/src/main_window.py index c53a773..62c117e 100644 --- a/src/main_window.py +++ b/src/main_window.py @@ -1,5 +1,6 @@ from PyQt6.QtWidgets import QMainWindow from PyQt6 import uic + import platform_edit import output_window @@ -10,41 +11,50 @@ class SIPPCompare(QMainWindow): 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.fund_plat_fee = 0.0 + self.fund_deal_fee = 0.0 + self.share_plat_fee = 0.0 + self.share_plat_max_fee = 0.0 + self.share_deal_fee = 0.0 + self.share_deal_reduce_trades = 0.0 + self.share_deal_reduce_amount = 0.0 + + self.fund_plat_fees = 0.0 + self.fund_deal_fees = 0.0 + self.share_plat_fees = 0.0 + self.share_deal_fees = 0.0 - self.result = None self.platform_win = None - self.output_win = None + self.output_win = output_window.OutputWindow() # Handle events - self.calc_but.clicked.connect(self.calculate_fee) + self.calc_but.clicked.connect(self.calculate_fees) 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) + mix_lab_str = f"Investment mix (funds {slider_val}% / shares {100 - slider_val}%)" + self.mix_lab.setText(mix_lab_str) + + def init_variables(self): + self.fund_plat_fee = self.platform_win.get_fund_plat_fee() + self.fund_deal_fee = self.platform_win.get_fund_deal_fee() + self.share_plat_fee = self.platform_win.get_share_plat_fee() + self.share_plat_max_fee = self.platform_win.get_share_plat_max_fee() + self.share_deal_fee = self.platform_win.get_share_deal_fee() + self.share_deal_reduce_trades = self.platform_win.get_share_deal_reduce_trades() + self.share_deal_reduce_amount = self.platform_win.get_share_deal_reduce_amount() # Calculate fees - def calculate_fee(self): + def calculate_fees(self): + self.init_variables() 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 + self.fund_deal_fees = fund_trades_num * self.fund_deal_fee remaining = funds_value for i in range(1, len(self.tiered_fees[0])): @@ -54,33 +64,31 @@ class SIPPCompare(QMainWindow): gap = (band - prev_band) if remaining > gap: - fund_plat_fees += gap * (fee / 100) + self.fund_plat_fees += gap * (fee / 100) remaining -= gap else: - fund_plat_fees += remaining * (fee / 100) + self.fund_plat_fees += remaining * (fee / 100) break shares_value = (1 - (slider_val / 100)) * value_num if (self.share_plat_fee * shares_value / 12) > self.share_plat_max_fee: - share_plat_fees = self.share_plat_max_fee * 12 + self.share_plat_fees = self.share_plat_max_fee * 12 else: - share_plat_fees = self.share_plat_fee * shares_value + self.share_plat_fees = self.share_plat_fee * shares_value share_trades_num = int(self.share_trades_combo.currentText()) if (share_trades_num / 12) >= self.share_deal_reduce_trades: - share_deal_fees = self.share_deal_reduce_amount * share_trades_num + self.share_deal_fees = self.share_deal_reduce_amount * share_trades_num else: - share_deal_fees = self.share_deal_fee * share_trades_num + self.share_deal_fees = self.share_deal_fee * share_trades_num - self.show_output_win(fund_plat_fees, fund_deal_fees, share_plat_fees, share_deal_fees) + self.show_output_win() # 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() + def show_output_win(self): # 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.display_output(self.fund_plat_fees, self.fund_deal_fees, + self.share_plat_fees, self.share_deal_fees) self.output_win.show() # Show the platform editor window (currently useless) diff --git a/src/output_window.py b/src/output_window.py index e618f8a..dc7b435 100644 --- a/src/output_window.py +++ b/src/output_window.py @@ -1,28 +1,47 @@ from PyQt6.QtWidgets import QWidget from PyQt6 import uic +import datetime +import os + +import platform_edit + + class OutputWindow(QWidget): def __init__(self): super().__init__() uic.loadUi("gui/output_window.ui", self) + self.res_save_but.clicked.connect(self.save_results) + self.results_str = "" + + def save_results(self): + cur_time = datetime.datetime.now() + if not os.path.exists("output"): + os.makedirs("output") + filename_str = (f"output/{cur_time.year}-{cur_time.month}-{cur_time.day}" + f".{cur_time.hour}-{cur_time.minute}-{cur_time.second}.txt") + output_file = open(filename_str, "wt") + output_file.write(self.results_str) + + def display_output(self, fund_plat_fees: float, fund_deal_fees: float, share_plat_fees: float, share_deal_fees: float): - results_str = "Fees breakdown:" + self.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}" + self.results_str += "\n\nPlatform fees:" + self.results_str += f"\n\tFund platform fees: £{round(fund_plat_fees, 2):.2f}" + self.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}" + self.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}" + self.results_str += "\n\nDealing fees:" + self.results_str += f"\n\tFund dealing fees: £{round(fund_deal_fees, 2):.2f}" + self.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}" + self.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.results_str += f"\n\nTotal fees: £{round(total_fees, 2):.2f}" - self.output.setText(results_str) + self.output.setText(self.results_str) diff --git a/src/platform_edit.py b/src/platform_edit.py index 1e17db2..e56962a 100644 --- a/src/platform_edit.py +++ b/src/platform_edit.py @@ -1,7 +1,50 @@ from PyQt6.QtWidgets import QWidget from PyQt6 import uic + class PlatformEdit(QWidget): def __init__(self): super().__init__() uic.loadUi("gui/platform_edit.ui", self) + + self.fund_plat_fee = [ + [0, 250000, 1000000, 2000000], + [0, 0.25, 0.1, 0.05] + ] + self.fund_deal_fee = 0.0 + self.share_plat_fee = 0.0 + self.share_plat_max_fee = 0.0 + self.share_deal_fee = 0.0 + self.share_deal_reduce_trades = 0.0 + self.share_deal_reduce_amount = 0.0 + + self.save_but.clicked.connect(self.init_variables) + + def init_variables(self): + self.fund_deal_fee = float(self.fund_deal_fee_box.text()) + self.share_plat_fee = float(self.share_plat_fee_box.text()) / 100 + self.share_plat_max_fee = float(self.share_plat_max_fee_box.text()) + self.share_deal_fee = float(self.share_deal_fee_box.text()) + self.share_deal_reduce_trades = float(self.share_deal_reduce_trades_box.text()) + self.share_deal_reduce_amount = float(self.share_deal_reduce_amount_box.text()) + + def get_fund_plat_fee(self): + return self.fund_plat_fee + + def get_fund_deal_fee(self): + return self.fund_deal_fee + + def get_share_plat_fee(self): + return self.share_plat_fee + + def get_share_plat_max_fee(self): + return self.share_plat_max_fee + + def get_share_deal_fee(self): + return self.share_deal_fee + + def get_share_deal_reduce_trades(self): + return self.share_deal_reduce_trades + + def get_share_deal_reduce_amount(self): + return self.share_deal_reduce_amount