import os
import sys
import inspect
import logging
import datetime as dt
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from Model.DatabaseHandler import DatabaseHandler
from Utils.Utils import Callbacks
from UI.View import View
from Model.Portfolio import Portfolio
from Utils.ConfigurationManager import ConfigurationManager
from Utils.Utils import Utils
[docs]class TradingMate:
"""
Main class that handles the interaction between the User Interface and the
underlying business logic of the whole application
"""
LOG_FILEPATH = os.path.join(
Utils.get_install_path(), "log", "trading_mate_{timestamp}.log"
)
CONFIG_FILEPATH = os.path.join(Utils.get_install_path(), "config", "config.json")
def __init__(self):
self._setup_logging()
# Read TradingMate configuration
self.configurationManager = ConfigurationManager(self.CONFIG_FILEPATH)
# Create the portfolios
self._create_portfolios()
logging.info("TradingMate initialised")
def _setup_logging(self):
"""
Setup the global logging settings
"""
time_str = dt.datetime.now().isoformat()
time_suffix = time_str.replace(":", "_").replace(".", "_")
log_filename = self.LOG_FILEPATH.replace("{timestamp}", time_suffix)
os.makedirs(os.path.dirname(log_filename), exist_ok=True)
logging.basicConfig(
filename=log_filename,
level=logging.INFO,
format="[%(asctime)s] %(levelname)s: %(message)s",
)
def _create_portfolios(self):
"""Create the portfolios from the configured trading logs"""
self.portfolios = []
for log_path in self.configurationManager.get_trading_database_path():
self.portfolios.append(Portfolio(self.configurationManager, log_path))
# Public API
[docs] def get_portfolios(self):
"""Return the list of active portfolios"""
return self.portfolios
[docs] def close_view_event(self):
"""
Callback function to handle close event of the user interface
"""
for pf in self.portfolios:
pf.stop()
logging.info("TradingMate stop")
[docs] def manual_refresh_event(self, portfolio_id):
"""
Callback function to handle refresh data request
"""
for pf in self.portfolios:
if pf.get_id() == portfolio_id:
pf.on_manual_refresh_live_data()
[docs] def set_auto_refresh(self, enabled, portfolio_id):
"""
Callback function to handle set/unset of auto refresh data
"""
for pf in self.portfolios:
if pf.get_id() == portfolio_id:
pf.set_auto_refresh(enabled)
[docs] def new_trade_event(self, new_trade, portfolio_id):
"""
Callback function to handle new trade event
"""
logging.info(
"TradingMate - new trade {} for portfolio {}".format(
new_trade, portfolio_id
)
)
for pf in self.portfolios:
if pf.get_id() == portfolio_id:
pf.add_trade(new_trade)
[docs] def delete_last_trade_event(self, portfolio_id):
"""
Callback function to handle delete of last trade request
"""
logging.info(
"TradingMate - delete last trade for portfolio {}".format(portfolio_id)
)
for pf in self.portfolios:
if pf.get_id() == portfolio_id:
pf.remove_last_trade()
[docs] def open_portfolio_event(self, filepath):
"""
Callback function to handle request to open a new portfolio file
"""
logging.info("TradingMate - open portfolio: {}".format(filepath))
# Create a new Portfolio from the filepath
pf = Portfolio(self.configurationManager, filepath)
self.portfolios.append(pf)
[docs] def save_portfolio_event(self, portfolio_id, filepath):
"""
Callback function to handle request to save/export the portfolio
"""
logging.info(
"TradingMate - save portfolio {} to {}".format(portfolio_id, filepath)
)
for pf in self.portfolios:
if pf.get_id() == portfolio_id:
pf.save_portfolio(filepath)
[docs] def get_settings_event(self):
"""
Callback to handle request to show the settings panel
"""
return self.configurationManager.get_editable_config()
[docs] def save_settings_event(self, config):
"""
Callback to save edited settings
"""
self.configurationManager.save_settings(config)
self._create_portfolios()
logging.info("TradingMate - portfolios reloaded after settings update")
def main():
# Initialise the business logic
tm = TradingMate()
# Initialise the user interface
View(tm).start()
if __name__ == "__main__":
main()