Beispiel #1
0
class Main:
    def __init__(self):
        """ METHOD INITIALIZES LOGGER, MONGO, GMAIL, EXCEPTION HOOK, ECT.
        """

        # INSTANTIATE LOGGER
        self.logger = Logger()

        # CONNECT TO MONGO
        self.mongo = MongoDB(self.logger)

        # CONNECT TO GMAIL API
        self.gmail = Gmail(self.mongo, self.logger)

        # SET GMAIL AND MONGO ATTRIBUTE FOR LOGGER
        self.logger.gmail = self.gmail

        self.logger.mongo = self.mongo

        self.traders = {}

        self.accounts = []

        self.sim_trader = SimTrader(self.mongo)

        self.not_connected = []

    def setupTraders(self):
        """ METHOD GETS ALL USERS ACCOUNTS FROM MONGO AND CREATES LIVE TRADER INSTANCES FOR THOSE ACCOUNTS.
            IF ACCOUNT INSTANCE ALREADY IN SELF.TRADERS DICT, THEN ACCOUNT INSTANCE WILL NOT BE CREATED AGAIN.
        """
        try:

            # GET ALL USERS ACCOUNTS
            users = self.mongo.users.find({})

            for user in users:

                for account_id, info in user["Accounts"].items():

                    if account_id not in self.traders and account_id not in self.not_connected:

                        tdameritrade = TDAmeritrade(self.mongo, user,
                                                    account_id, self.logger)

                        connected = tdameritrade.initialConnect()

                        if connected:

                            obj = LiveTrader(
                                user, self.mongo,
                                PushNotification(user["deviceID"], self.logger,
                                                 self.gmail), self.logger,
                                account_id, info["Asset_Type"], tdameritrade)

                            self.traders[account_id] = obj

                        else:

                            self.not_connected.append(account_id)

                    self.accounts.append(account_id)

        except Exception:

            self.logger.ERROR()

    def checkTradersAndAccounts(self):
        """ METHOD COMPARES THE CURRENT TOTAL TRADERS TO CURRENT TOTAL ACCOUNTS IN MONGO.
            IF CURRENT TRADERS > CURRENT ACCOUNTS, MEANING AN ACCOUNT WAS REMOVED, THEN REMOVE THAT INSTANCE FROM SELF.TRADERS DICT

        """
        try:

            if len(self.traders) > len(self.accounts):

                self.logger.INFO(
                    f"CURRENT TOTAL TRADERS: {len(self.traders)} - CURRENT TOTAL ACCOUNTS: {len(self.accounts)}"
                )

                accounts_to_remove = self.traders.keys() - set(self.accounts)

                for account in accounts_to_remove:

                    self.traders[account].isAlive = False

                    del self.traders[account]

                    self.logger.INFO(f"ACCOUNT ID {account} REMOVED")

            self.accounts.clear()

        except Exception:

            self.logger.ERROR()

    def terminateNeeded(self):
        """ METHOD ITERATES THROUGH INSTANCES AND FIND ATTRIBUTE NAMED TERMINATE AND CHECKS IF TRUE.
            IF TRUE, REMOVE FROM SELF.TRADERS AND STOP TASKS
        """

        try:

            traders = self.traders.copy()

            for account_id, info in traders.items():

                if info.tdameritrade.terminate:

                    info.isAlive = False

                    del self.traders[account_id]

                    self.logger.INFO(f"ACCOUNT ID {account_id} REMOVED")

        except Exception:

            self.logger.ERROR()

    def run(self):
        """ METHOD RUNS THE TWO METHODS ABOVE AND THEN RUNS LIVE TRADER METHOD RUNTRADER FOR EACH INSTANCE.
        """
        try:

            sim_went = False

            self.setupTraders()

            self.checkTradersAndAccounts()

            self.terminateNeeded()

            trade_data = self.gmail.getEmails()

            for live_trader in self.traders.values():

                live_trader.runTrader(trade_data)

                if not sim_went:  # ONLY RUN ONCE DESPITE NUMBER OF INSTANCES

                    self.sim_trader.runTrader(trade_data,
                                              live_trader.tdameritrade)

                    sim_went = True

        except Exception:

            self.logger.ERROR()

    def updateSystemInfo(self):

        system = list(self.mongo.system.find({}))[0]

        self.mongo.system.update_one({"_id": ObjectId(system["_id"])}, {
            "$set": {
                "Threads_Running": threading.active_count(),
                "Last_Updated": getDatetime()
            }
        })