示例#1
0
    def start_trading(self, Tmode=False):
        global ml

        now = datetime.datetime.now(TZ)
        Notify.info("Trading has begun")
        self.logger.info("Trading has begun")
        count = 1
        if not Tmode:
            while now.time() < self.pack_up or self.is_dev_mode:
                try:
                    for trader in self.traders:
                        trader.run()
                    self.logger.info(f"Completed round {count}")
                    sleep(self.period)
                except Exception as e:
                    Notify.fatal("Trading has been aborted")
                    self.logger.critical(
                        "Trade abort due to unexpected error : ", e)
                    quit(0)
                finally:
                    now = datetime.datetime.now(TZ)
                    count += 1
        else:
            Notify.info("Confirming access to live stock price...")
            self.logger.info("Confirming access to live stock price...")
            for trader in self.traders:
                try:
                    get_live_price(trader.ticker)
                except Exception as e:
                    Notify.fatal(
                        "Error in fetching live stock price. Aborting")
                    self.logger.critical(
                        "Error in fetching live stock price : ", e)
示例#2
0
    def start_trading(self, Tmode=False):
        global ml

        now = datetime.datetime.now(TZ)
        Notify.info("Trading has begun")
        ml.info("Trading has begun")
        count = 1
        if not Tmode:
            while now.time() < PACK_UP or DEV_MODE:
                try:
                    for trader in self.traders:
                        trader.run()
                    ml.info("Completed round #", count)
                    sleep(PERIOD_INTERVAL)
                except Exception as e:
                    Notify.fatal("Trading has been aborted")
                    ml.critical("Trade abort due to unexpected error : ", e)
                    quit(0)
                finally:
                    now = datetime.datetime.now(TZ)
                    count += 1
        else:
            Notify.info("Confirming access to live stock price...")
            ml.info("Confirming access to live stock price...")
            for trader in self.traders:
                try:
                    get_live_price(trader.ticker)
                except Exception as e:
                    Notify.fatal(
                        "Error in fetching live stock price. Aborting")
                    ml.critical("Error in fetching live stock price : ", e)
示例#3
0
def get_stocks(stocks_temp, prev_data, key):
    if (not key in prev_data):
        raise Exception(f"Missing key '{key}' in prev_data")

    for ticker in prev_data[key]:

        stock_name, stock_ex = ticker.split(".")
        if stock_name in stocks_temp:
            Notify.fatal("Cannot buy and sell the same stock.")
            quit(0)

        stocks_temp[stock_name] = stock_ex
示例#4
0
    def make_decision(self):
        # global ACCOUNT
        # update tenkan data
        self.tenkan_data = []
        for i in range(DATA_LIMIT - 9):
            tenkan_src = self.price[i:i + 9]
            self.tenkan_data.append((max(tenkan_src) + min(tenkan_src)) / 2)
        # update kijun data
        self.kijun_data = []
        for i in range(DATA_LIMIT - 26):
            kijun_src = self.price[i:i + 26]
            self.kijun_data.append((max(kijun_src) + min(kijun_src)) / 2)
        # update x values for senkou A and senkou B
        self.x5 = self.time[78:78 + DATA_LIMIT - 26]
        self.x6 = self.time[104:104 + DATA_LIMIT - 52]
        # update senkou A data
        self.senkou_A_data = [
            (self.tenkan_data[i + 17] + self.kijun_data[i]) / 2
            for i in range(DATA_LIMIT - 26)
        ]
        # update senkou B data
        self.senkou_B_data = []
        for i in range(DATA_LIMIT - 52):
            senkou_B_src = self.price[i:i + 52]
            self.senkou_B_data.append(
                (max(senkou_B_src) + min(senkou_B_src)) / 2)

        # get Ichimoku params for comparison
        x = self.time[26:26 + DATA_LIMIT][-1]
        curr_price = self.price[-1]
        tenkan = self.tenkan_data[-1]
        kijun = self.kijun_data[-1]
        sen_A = self.get_value(self.senkou_A_data, self.x5, x)
        sen_B = self.get_value(self.senkou_B_data, self.x6, x)
        self.logger.info(
            f"Current status - Price : {curr_price}, Tenkan : {tenkan}, Kijun : {kijun}, Senkou A : {sen_A}, Senkou B : {sen_B}"
        )

        # conditions for long trade entry
        # If Kumo cloud is green and current price is above kumo, strong bullish signal
        cond1 = (sen_A > sen_B) and (curr_price >= sen_A)
        if cond1:
            self.logger.debug("Sensing strong bullish signal")
        # conditions for short trade entry
        # If Kumo cloud is red and current price is below kumo, strong bearish signal
        cond2 = (sen_A < sen_B) and (curr_price <= sen_A)
        if cond2:
            self.logger.debug("Sensing strong bearish signal")
        # check allocated money
        cond3 = curr_price < self.account

        # IF all conditions are right, long trade entry
        if cond1 and not self.IN_LONG_TRADE and cond3:
            self.buy(curr_price, "LONG")
            self.price_for_buffer = curr_price
            self.IN_LONG_TRADE = True
            self.STOCKS_TO_SELL += 1
        if not cond3:
            Notify.fatal(
                f"[Trader #{self.number} {self.ticker}] : Oops! Out of cash!")
            self.logger.critical("Trader out of cash to buy stocks!")
        # If all conditions are right, short trade entry
        if cond2 and not self.IN_SHORT_TRADE:
            self.sell(curr_price, "SHORT")
            self.price_for_buffer = curr_price
            self.IN_SHORT_TRADE = True
            self.STOCKS_TO_BUY_BACK += 1

        # setup buffer for stop loss and trade exit
        buffer = self.price_for_buffer * BUFFER_PERCENT
        cond4 = abs(curr_price - kijun) >= buffer

        # Get stopped out as the price moves through the buffer area beyond the Kijun
        if self.IN_LONG_TRADE:
            if cond4:
                self.sell(curr_price, "LONG")
                self.IN_LONG_TRADE = False
                self.STOCKS_TO_SELL -= 1
        if self.IN_SHORT_TRADE:
            if cond4 and cond3:
                self.buy(curr_price, "SHORT")
                self.IN_SHORT_TRADE = False
                self.STOCKS_TO_BUY_BACK -= 1
            if not cond3:
                Notify.fatal(
                    f"[Trader #{self.number} {self.ticker}] : Oops! Out of cash!"
                )
                self.logger.critical("Trader out of cash to buy back stock !")
示例#5
0
def main():
    """
        Main Function
    """
    # make sure that market is open
    if not DEV_MODE and CHECK_MARKET:
        if args.t:
            Notify.for_input("Check Market? (y/n) : ")
            confirm = input().strip().lower()
            print("")
        else:
            confirm = "y"
        if is_open() or confirm == "n":
            pass
        else:
            Notify.fatal("Market is closed at the moment, aborting.")
            print("")
            quit(0)
    # else:
    #     Notify.warn("You are in developer mode, if not intended, please quit.")
    #     Notify.info("Press ENTER to continue, Ctrl+C to quit")
    #     input()

    # allow market to settle to launch Ichimoku strategy
    if IDLE_DELAY == 0:
        Notify.info("Skipped Idle phase")
    else:
        Notify.info(
            f"Entered Idle phase at {datetime.datetime.now(TZ).strftime('%H:%M:%S')}"
        )
        master_logger.info(f"Entered Idle phase")
        Notify.info(f"\tExpected release : after {IDLE_DELAY // 60} minutes")
        print("")
        sleep(IDLE_DELAY)

    master_logger.info("Idle phase complete")
    # find relevant stocks to focus on
    Notify.info("Finding stocks to focus on .....")
    try:
        stocks_to_focus = fetch_stocks()
    except Exception as ex:
        print(f'Exception was {ex}')
        stocks_to_focus = []
        Notify.fatal(
            "Could not fetch relevant stocks. Verify Network connection and check logs for details."
        )
        master_logger.critical(
            "Could not fetch relevant stocks, Most possibly due to network error"
        )
        quit(0)
    Notify.info("\tStatus : Complete")
    master_logger.info("Successfully found relevant stocks")
    print("")

    # setup traders and begin trade
    master = Master(PERIOD_INTERVAL, master_logger, FEASIBLE_PERCENT, ACCOUNT,
                    PACK_UP, DEV_MODE)
    master.validate_repo()
    master.lineup_traders(stocks_to_focus)
    master.init_traders(args.t)
    master.start_trading(args.t)

    # trading in over by this point
    Notify.info("Trading complete")
    master_logger.info("Trading complete")

    # initiate packup
    del master
    quit(0)
示例#6
0
def fetch_stocks():
    """
        Find relevant stocks to focus on for trading
    Returns:
        Deque of tickers of relevant stocks

    """

    global ml

    # url to grab data from
    url = f'https://finance.yahoo.com/gainers?count={NUM_OF_STOCKS_TO_SEARCH}'
    # request header
    headers = {
        'user-agent':
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
    }
    try:
        src = requests.get(url=url, headers=headers).content
    except Exception as e:
        src = None
        Notify.fatal(
            "Trade abort due to unexpected error. Check activity log for details"
        )
        master_logger.critical("Encountered error : ", e)
        quit(0)
    # soup object of source code
    soup = BeautifulSoup(src, "html.parser")
    rows = soup.find('table').tbody.find_all('tr')
    # initialisations
    stocks_temp = dict()
    # check previous day's closing status
    prev_data = json.loads(open("database/user_info.json").read())
    get_sells(stocks_temp, prev_data, "stocks_to_sell")
    get_buys(stocks_temp, prev_data, "stocks_to_buy_back")

    # set counter
    count = len(stocks_temp)
    stocks = deque()
    # iterate over rows in web page
    for tr in rows:
        # exit if
        if count == NUM_OF_STOCKS_TO_FOCUS:
            break
        else:
            row_data = tr.find_all('td')
            ticker = row_data[0].text.strip()
            price = get_live_price(ticker)

            # split ticker for checking if same stock of different stock exchange is selected or not
            stock_name = ""
            stock_ex = "US"
            stock_name = ticker  #ticker.split(".")
            if price >= PENNY_STOCK_THRESHOLD and stock_name not in stocks_temp:
                stocks_temp[stock_name] = stock_ex
                count += 1
    # get back ticker
    for stock in stocks_temp:
        stocks.append(f"{stock}")
        # stocks.append(f"{stock}.{stocks_temp[stock]}")

    # return deque of stocks to focus on
    return stocks
示例#7
0
##############################################################
TODAY = datetime.date.today().strftime("%d-%m-%Y")
if not os.path.exists(f"database/{TODAY}"):
    os.mkdir(f"database/{TODAY}")
master_logger = master_logger(f'database/{TODAY}/master.log')
master_logger.info("-" * 76)
master_logger.info("-" * 27 + " NEW SESSION DETECTED " + "-" * 27)
sys.stderr = open(f"database/{TODAY}/errorStream.txt", "a")

##############################################################

try:
    ACCOUNT = json.loads(open("database/user_info.json").read()
                         )["account_balance"] * FEASIBLE_PERCENT
except FileNotFoundError:
    Notify.fatal('User info not found, Aborting.')
    master_logger.critical("User info not found")
    quit(0)
master_logger.info("Successfully loaded user_info.json")
master_logger.info("-" * 76)

##############################################################

HEADERS = {
    "user-agent":
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"
}

##############################################################

parser = argparse.ArgumentParser(