예제 #1
0
    def minutes_till_trading():
        ''' Time till NZX is open for trading '''

        now = util.get_nz_time()
        open_dt = datetime.strptime(config.open_time, '%I:%M%p')
        close_dt = datetime.strptime(config.close_time, '%I:%M%p')

        # market is open today
        if now.strftime('%A').lower() not in config.days_closed:

            # open now
            if now.time() >= open_dt.time() and now.time() <= close_dt.time():
                return 0

            # hasn't open yet
            if now.time() < open_dt.time():
                open_time = datetime.combine(now, open_dt.time()) - now
                return open_time.total_seconds() / 60

        # market has closed
        for i in range(7):
            future = now + timedelta(days=(i + 1))
            if future.strftime('%A').lower() not in config.days_closed:
                next_open = datetime.combine(future, open_dt.time()) - now
                return next_open.total_seconds() / 60

        util.log("market is never open according to config", error=True)
예제 #2
0
    def should_buy(market_price, history, margin_percent):
        ''' Decides if the bot should buy or not '''

        # ignore zero divide errors
        np.seterr(divide='ignore', invalid='ignore')

        try:
            # calculate vwap
            history = history.groupby(history.index.date, group_keys=False)
            history = history.apply(Market.vwap).fillna(
                0)  ## Fill NaN's in df with 0's

            # calculate direction
            moves = np.gradient(history['vwap'])
            median = np.median(moves)
            average = np.average(moves)

            # calculate margin price
            margin_price = history['vwap'][-1]
            margin_price -= (margin_price * (margin_percent / 100))

            print(f'median:\t {median:.4g}')
            print(f'averag:\t {average:.4g}')
            print(f'market:\t {market_price:.4g}')
            print(f'margin:\t {margin_price:.4g}')

            # agree if going up and below margin
            if median > 0 and average > 0 and market_price <= margin_price:  # might like to consider changing the 0's?
                return True

        except Exception as e:
            util.log(f'Warning: {e}')

        return False
예제 #3
0
    def should_buy(market_price, history, margin_percent):
        ''' Decides if the bot should buy or not '''

        # ignore zero divide errors
        np.seterr(divide='ignore', invalid='ignore')

        try:
            # calculate vwap
            history = history.groupby(history.index.date, group_keys=False)
            history = history.apply(Market.vwap)

            # calculate direction
            moves = np.gradient(history['vwap'])
            median = np.median(moves)
            average = np.average(moves)

            # calculate margin price
            margin_price = history['vwap'][-1]
            margin_price -= (margin_price * (margin_percent/100))

            # agree if going up and below margin
            if median > 0 and average > 0 and market_price <= margin_price:
                return True

        except Exception as e:
            util.log(f'Warning: {e}')

        return False
예제 #4
0
def perform_buying(client, investments, companies, balance):
    ''' Find new stocks to buy from the companies '''

    for company in companies:

        # don't double invest
        if company['id'] in investments:
            continue

        # ignore penny stocks
        price = float(company['market_price'])
        if price < config.minimum_stock_price:
            continue

        c = company['code']
        sleep(2)
        print()
        print(f'Considering buying {c}')

        symbol = company['code'] + '.NZ'
        stock = yfinance.Ticker(symbol)
        try:
            history = stock.history(period='1mo', interval='15m')
        except RuntimeError:
            print('Probably not enough data at this resolution. Skipping')
            continue

        # buy if it is a bargain
        should_buy = Market.should_buy(price, history, 0.4) # 0.4 is margin %, i.e. 0.4%
        print(should_buy)
        if should_buy:
            buy_amount = config.buy_amount

            # value shares more as dividends are upcoming
            if company['dividends']:
                dividends_soon = util.dividends_soon(company['dividends'])
                if dividends_soon and config.dividends_bonus > 1:
                    buy_amount *= config.dividends_bonus

            # check we have balance
            if balance < buy_amount:
                util.log(f'Want to buy {symbol} but not enough $$$')
                break

            # submit the buy order
            util.log(f'Buying ${buy_amount} of {symbol}')
            client.buy(company, buy_amount)
            balance -= buy_amount
예제 #5
0
def perform_selling(client, portfolio, companies, dividends):
    ''' Look to sell stocks from the portfolio '''

    for company in portfolio:
        fund_id = company['fund_id']

        contribution = float(company['contribution'])
        current_value = float(company['value'])

        # does company give dividends?
        if fund_id in dividends:
            util.log(f'Not selling {fund_id}:{code} due to dividends')
            continue

        # sell if we're making a profit
        if Market.should_sell(contribution, current_value):
            code = util.get_code_from_id(fund_id, companies)
            util.log(f'Selling ${current_value} of {code}')
            client.sell(company, float(company['shares']))
예제 #6
0
def perform_buying(client, investments, companies, balance):
    ''' Find new stocks to buy from the companies '''

    for company in companies:

        # don't double invest
        if company['id'] in investments:
            continue

        # ignore penny stocks
        price = float(company['market_price'])
        if price < config.minimum_stock_price:
            continue

        symbol = company['code'] + '.NZ'
        stock = yfinance.Ticker(symbol)
        history = stock.history(period='1mo', interval='15m')

        # buy if it is a bargain
        if Market.should_buy(price, history, 0.4):

            buy_amount = config.buy_amount

            # value shares more as dividends are upcoming
            if company['dividends']:
                dividends_soon = util.dividends_soon(company['dividends'])
                if dividends_soon and config.dividends_bonus > 1:
                    buy_amount *= config.dividends_bonus

            # check we have balance
            if balance < buy_amount:
                util.log(f'Want to buy {symbol} but not enough $$$')
                break

            # submit the buy order
            util.log(f'Buying ${buy_amount} of {symbol}')
            client.buy(company, buy_amount)
            balance -= buy_amount
예제 #7
0
    balance = float(profile['user']['wallet_balance'])
    portfolio = profile['portfolio']
    dividends = profile['upcoming_dividends']

    investments = util.get_fund_ids(portfolio)
    companies = client.get_companies()

    # it's show time
    perform_selling(client, portfolio, companies, dividends)
    perform_buying(client, investments, companies, balance)


if __name__ == '__main__':

    # config
    util.log('Loaded config')

    # init client
    client = sharesies.Client()
    if client.login(config.username, config.password):
        util.log('Connected to Sharesies')
    else:
        util.log('Failed to login', error=True)

    # trade loop
    while True:
        minutes_till_open = Market.minutes_till_trading()

        if minutes_till_open == 0:
            util.log('Market is currently open!')
            scan_market(client)