def getPreMarketChange( symbol, list_GapDate, folder_30min='/Users/yutaasano/Documents/PyCharm/StockData/HistStkPrice_30min_Russell3000_Kibot_20150912' ):
    """
    Return pre-market change for a given stock symbol for given dates
    list_GapDate is a nx3 numpy array, each row: year, month, day. It has to be sorted from old to new dates for faster process
    Pre-market change [%] is defined as (O(k_30-1) - C(k_day-1)) / C(k_day-1) * 100
    O(k_30-1): open price at 9:00
    C(k_day-1): close price at previous day's 15:30
    """

    # Check if list_GapDate is sorted
    list_GapDate_sorted = m.sortrowsByMultiCol(list_GapDate, [0,1,2], isAscending=1)
    if np.sum(np.abs(list_GapDate_sorted-list_GapDate)) != 0:
        raise ValueError('list_GapDate has to be sorted from old to new dates!')

    n_date = list_GapDate.shape[0]
    data_30min = fi.getHistStkPrice30min(symbol, folder_30min)

    t_row_GapDateInit = 0
    change_PreMarket = np.zeros((n_date))
    for k_date in range(0,n_date):
        t_GapDate = list_GapDate[k_date,:]

        # Look for a row where t_GapDate first occurs
        while t_row_GapDateInit<data_30min.shape[0]:
            t_30minDate = np.int64(data_30min[t_row_GapDateInit,0:3])
            if sum(np.abs(t_30minDate - t_GapDate)) == 0:
                break
            else:
                t_row_GapDateInit += 1

        if t_row_GapDateInit!=data_30min.shape[0]:
            t_row_ub = t_row_GapDateInit # upper bound row (open price 30 min before market open, typically row for 9:00)
            if np.int64(data_30min[t_row_ub,3]) >= 900:
                pass
            else:
                while np.int64(data_30min[t_row_ub,3]) < 900:
                    t_row_ub += 1

            t_row_lb = t_row_GapDateInit-1 # lower bound row (previous day's market close, typically row for 15:30)
            if np.int64(data_30min[t_row_lb,3]) < 1600:
                pass
            else:
                while np.int64(data_30min[t_row_lb,3]) >= 1600:
                    t_row_lb -= 1

            # Record only if the upper bound is at 9:00
            if int(data_30min[t_row_ub,3]) == 900:
                change_PreMarket[k_date] = ( data_30min[t_row_ub,4]-data_30min[t_row_lb,7] ) / data_30min[t_row_lb,7] * 100
            else:
                change_PreMarket[k_date] = np.nan

        else:
            change_PreMarket[k_date] = np.nan # no gap date found for this stock
            t_row_GapDateInit = 0 # re-initialize the gap date location

    return change_PreMarket
def getPreMarketVol( symbol, list_GapDate, folder_input='/Users/yutaasano/Documents/PyCharm/Stock/HistStkPrice_30min' ):
    """
    Return pre-market volume for a given stock symbol for given dates
    list_GapDate is a nx3 numpy array, each row: year, month, day
    """

    n_date = list_GapDate.shape[0]
    data_30min = fi.getHistStkPrice30min(symbol, folder_input)

    # For each rebound date, calculate pre-market volume from the time slot with largest open-close price difference
    vol_PreMarket = np.int64(np.zeros((n_date)))
    for k_date in range(0,n_date):
        t_GapDate = list_GapDate[k_date,:]

        # Look for a row where t_GapDate first occurs
        t_row_GapDateInit = 0
        while t_row_GapDateInit<data_30min.shape[0]:
            t_30minDate = np.int64(data_30min[t_row_GapDateInit,0:3])
            if sum(np.abs(t_30minDate - t_GapDate)) == 0:
                break
            else:
                t_row_GapDateInit += 1

        if t_row_GapDateInit!=data_30min.shape[0]:
            t_row_ub = t_row_GapDateInit # upper bound row (just before market open, typically row for 9:00)
            if np.int64(data_30min[t_row_ub,3]) >= 930:
                pass
            else:
                while np.int64(data_30min[t_row_ub,3]) < 930:
                    t_row_ub += 1
            t_row_ub -= 1 # back 1 row to get a row just before market open

            t_row_lb = t_row_GapDateInit-1 # lower bound row (just after previous day's market close, typically row for 16:00)
            if np.int64(data_30min[t_row_lb,3]) <= 1600:
                pass
            else:
                while np.int64(data_30min[t_row_lb,3]) > 1600:
                    t_row_lb -= 1

            # Find a row (time slot) that produced largest open-close price difference
            t_gapIntra = 0
            t_row_GapIntraLargest = t_row_lb
            for k_row in range(t_row_lb, t_row_ub+1):
                t_gapIntra_k = abs(data_30min[k_row,7] - data_30min[k_row,4])
                if t_gapIntra_k > t_gapIntra:
                    t_gapIntra = t_gapIntra_k
                    t_row_GapIntraLargest = k_row

            # Sum Volume from the row with largest open-close price difference to the upper bound row
            vol_PreMarket[k_date] = int(sum(data_30min[t_row_GapIntraLargest:t_row_ub+1,8]))

        else:
            vol_PreMarket[k_date] = np.nan # no gap date found for this stock

    return vol_PreMarket