def get_beginning_of_next_trading_day(ref_time):
    ref_day = posix_to_datetime(ref_time).date()
    schedule = get_trading_calendar(ref_day, ref_day)
    while schedule.empty:
        ref_day += timedelta(days=1)
        schedule = get_trading_calendar(ref_day, ref_day)
    start_day, _ = get_schedule_start_and_end(schedule)
    return start_day
    def test_time_handlers(self):
        posix_time = 1590165714.1528566
        actual_date = dt(2020, 5, 22, 12, 41, 54, 152857)
        localizer = pytz.timezone(TIMEZONE)
        localized_date = localizer.localize(actual_date)
        self.assertEqual(posix_to_datetime(posix_time), localized_date)
        self.assertAlmostEqual(posix_time, datetime_to_posix(localized_date),
                               0)

        mexico_date = actual_date.replace(hour=11)
        localizer = pytz.timezone("America/Mexico_City")
        localized_date = localizer.localize(mexico_date)
        self.assertAlmostEqual(posix_time, datetime_to_posix(localized_date),
                               0)

        # Pre-stage all of the mocked current time values that will be called sequentially in the tests below.
        # ----------------------------------------------------------------------------------------------------
        with patch('backend.logic.base.time') as current_time_mock:
            # Check during trading day just one second before and after open/close
            schedule = get_trading_calendar(actual_date, actual_date)
            start_day, end_day = [
                datetime_to_posix(x)
                for x in schedule.iloc[0][["market_open", "market_close"]]
            ]

            current_time_mock.time.side_effect = [
                posix_time,  # during trading day
                posix_time + 8 * 60 * 60,  # 8 hours later--after trading day
                1608908400,  # Christmas 2020, Friday, 11am in NYC. We want to verify that we're accounting for holidays
                start_day - 1,  # one second before trading day
                (start_day + end_day) /
                2,  # right in the middle of trading day
                end_day + 1  # one second after trading day
            ]

            self.assertTrue(during_trading_day())
            self.assertFalse(during_trading_day())
            self.assertFalse(during_trading_day())
            self.assertFalse(during_trading_day())
            self.assertTrue(during_trading_day())
            self.assertFalse(during_trading_day())

        # Finally, just double-check that the real-time, default invocation works as expected
        posix_now = time.time()
        nyc_now = posix_to_datetime(posix_now)
        schedule = get_trading_calendar(nyc_now, nyc_now)
        during_trading = False
        if not schedule.empty:
            start_day, end_day = [
                datetime_to_posix(x)
                for x in schedule.iloc[0][["market_open", "market_close"]]
            ]
            during_trading = start_day <= posix_now <= end_day

        # FYI: there is a non-zero chance that this test will fail at exactly the beginning or end of a trading day
        self.assertEqual(during_trading, during_trading_day())
Exemple #3
0
    def test_task_caching(self):
        rds.flushall()
        test_time = posix_to_datetime(time.time()).date()
        start = time.time()
        _ = get_trading_calendar(test_time, test_time)
        time1 = time.time() - start

        start = time.time()
        _ = get_trading_calendar(test_time, test_time)
        time2 = time.time() - start

        self.assertLess(time2, time1 / 2)  # "2" is a hueristic for 'substantial performance improvement'
        self.assertIn("rc:get_trading_calendar", rds.keys()[0])
Exemple #4
0
def scrape_dividends(date: dt = None, timeout: int = 120) -> pd.DataFrame:
    if date is None:
        date = dt.now().replace(hour=0, minute=0, second=0, microsecond=0)

    if get_trading_calendar(date, date).empty:
        return pd.DataFrame()
    day_of_month = str(date.day)
    month = date.strftime('%B %Y')
    driver = get_web_driver()
    driver.get('https://www.thestreet.com/dividends/index.html')
    table_x_path = '//*[@id="listed_divdates"]/table/tbody[2]'
    if day_of_month != str(dt.now().day):
        click_calendar(day_of_month, month, driver, timeout)
    next_page = True
    first_page = True
    dividends_table = []
    while next_page:
        table = WebDriverWait(driver, timeout).until(
            EC.visibility_of_element_located((By.XPATH, table_x_path)))
        dividends_table += get_table_values(table)
        next_page = click_next_page(table, first_page)
        first_page = False
    df = pd.DataFrame(
        dividends_table,
        columns=['symbol', 'company', 'amount', 'yield', 'exec_date'])
    del df['yield']
    df["amount"] = df['amount'].replace('[\$,]', '', regex=True).astype(float)
    dividend_exdate = pd.to_datetime(df['exec_date'].iloc[0])
    posix_dividend_exdate = datetime_to_posix(dividend_exdate)
    df['exec_date'] = posix_dividend_exdate
    df.drop_duplicates(inplace=True)
    with engine.connect() as conn:
        df.to_sql("dividends", conn, if_exists="append", index=False)
Exemple #5
0
def get_order_expiration_status(order_id):
    """Before processing an order, we'll use logic to determine whether that order is still active. This function
    return True if an order is expired, or false otherwise.
    """
    with engine.connect() as conn:
        time_in_force = conn.execute(
            "SELECT time_in_force FROM orders WHERE id = %s;",
            order_id).fetchone()[0]
        if time_in_force == "until_cancelled":
            return False

    # posix_to_datetime
    current_time = time.time()
    with engine.connect() as conn:
        time_placed = conn.execute(
            """SELECT timestamp 
                                      FROM order_status 
                                      WHERE order_id = %s 
                                      ORDER BY id LIMIT 0, 1;""",
            order_id).fetchone()[0]

    time_placed_nyc = posix_to_datetime(time_placed)

    cal_ref_time = time_placed_nyc.date()
    schedule = get_trading_calendar(cal_ref_time, cal_ref_time)
    if schedule.empty:
        next_day_schedule = get_next_trading_day_schedule(time_placed_nyc)
        _, cutoff_time = get_schedule_start_and_end(next_day_schedule)
    else:
        if time_placed_nyc.hour >= END_OF_TRADE_HOUR:
            next_day_schedule = get_next_trading_day_schedule(time_placed_nyc +
                                                              timedelta(
                                                                  days=1))
            _, cutoff_time = get_schedule_start_and_end(next_day_schedule)
        else:
            _, cutoff_time = get_schedule_start_and_end(schedule)

    if current_time > cutoff_time:
        return True
    return False
Exemple #6
0
def trade_time_index(timestamp_sr: pd.Series) -> List:
    """this function solves the problem of how to create a continuous, linear index across a bunch of purchases and
    sales happening at different times across trade days. Simply trying to get the timestamp for a fixed number of bins
    results in the algorithm creating bins for "non-event" times on weekend and between trading hours. This algorithm
    create a "trade time index" that maps scalar time index values dependably to corresponding datetimes.

    Note that the passed-in timestamp series must be sorted, meaning that the dataframe from the outer environment must
    be sorted in orders for this to work.
    """
    ls = timestamp_sr.to_list()
    assert all(ls[i] <= ls[i + 1] for i in range(len(ls) - 1))  # enforces that timestamps are strictly sorted

    start_time = timestamp_sr.min().date()
    end_time = timestamp_sr.max().date()
    trade_times_df = get_trading_calendar(start_time, end_time)
    # when this happens it means that the game is young enough that we don't yet have any observations that occured
    # during trading hours. In this case we won't worry about filtering our trading hours -- we'll just assign  an index
    # on the times available
    if trade_times_df.empty or trade_times_df.iloc[-1]["market_close"] <= start_time:
        return pd.cut(timestamp_sr, N_PLOT_POINTS, right=True, labels=False, include_lowest=False).to_list()

    df = timestamp_sr.to_frame()
    df["anchor_time"] = timestamp_sr.min()
    df["time_diff"] = (df["timestamp"] - df["anchor_time"]).dt.total_seconds()
    df.set_index("timestamp", inplace=True)
    df.index = df.index.to_period("D")
    del df["anchor_time"]

    trade_times_df["last_close"] = trade_times_df["market_close"].shift(1)
    trade_times_df["non_trading_seconds"] = (
            trade_times_df["market_open"] - trade_times_df["last_close"]).dt.total_seconds().fillna(0)
    trade_times_df["adjustment"] = trade_times_df["non_trading_seconds"].cumsum()
    trade_times_df.set_index("market_open", inplace=True)
    trade_times_df.index = trade_times_df.index.to_period("D")
    adjustment_df = trade_times_df["adjustment"]

    tt_df = df.join(adjustment_df)
    tt_df["trade_time"] = tt_df["time_diff"] - tt_df["adjustment"]
    return downsample_time_series(tt_df["trade_time"], N_PLOT_POINTS)
Exemple #7
0
def make_stock_data_records():
    with open("./database/fixtures/stock_data.json") as json_file:
        stock_data = json.load(json_file)

    timezone = pytz.timezone(TIMEZONE)
    sample_days = list(set([x["date"] for x in stock_data["AMZN"]]))
    sample_days.sort()
    schedule = get_trading_calendar(start_date=dt.utcnow() -
                                    timedelta(days=15),
                                    end_date=dt.utcnow() + timedelta(days=15))
    trading_days = []
    for i in range(5):
        trading_days.append(schedule.iloc[i]["market_open"])

    ixic_value = ixic_value_0 = 10_473.83
    gspc_value = gspc_value_0 = 3_215.57
    dji_value = dji_value_0 = 27_734.71
    price_records = []
    index_records = []
    for sample_day, simulated_day in zip(sample_days, trading_days):
        for stock_symbol in stock_data.keys():
            sample_day_subset = [
                entry for entry in stock_data[stock_symbol]
                if entry["date"] == sample_day
            ]
            for record in sample_day_subset:
                simulated_date = simulated_day.strftime("%Y-%m-%d")
                str_time = f"{simulated_date} {record['minute']}"
                base_date = pd.to_datetime(str_time, format="%Y-%m-%d %H:%M")
                localized_date = timezone.localize(base_date)
                posix_time = datetime_to_posix(localized_date)
                price_records.append(
                    dict(symbol=stock_symbol,
                         price=record["average"],
                         timestamp=posix_time))

                # add synthetic index data as well
                ixic_value += np.random.normal(0, 0.0005 * ixic_value_0)
                gspc_value += np.random.normal(0, 0.0005 * gspc_value_0)
                dji_value += np.random.normal(0, 0.0005 * dji_value_0)
                index_records.append(
                    dict(symbol="^IXIC",
                         value=ixic_value,
                         timestamp=posix_time))
                index_records.append(
                    dict(symbol="^GSPC",
                         value=gspc_value,
                         timestamp=posix_time))
                index_records.append(
                    dict(symbol="^DJI", value=dji_value, timestamp=posix_time))

    # our simulation requires a full two weeks worth of data. append new entries for indexes and prices adding 7 days
    # worth of time to each.
    extended_price_records = deepcopy(price_records)
    extended_index_records = deepcopy(index_records)
    for price_record, index_record in zip(price_records, index_records):
        pr_copy = deepcopy(price_record)
        pr_copy["timestamp"] += SECONDS_IN_A_DAY * 7
        extended_price_records.append(pr_copy)
        ir_copy = deepcopy(index_record)
        ir_copy["timestamp"] += SECONDS_IN_A_DAY * 7
        extended_index_records.append(ir_copy)

    return extended_price_records, extended_index_records
Exemple #8
0
def get_day_start(start_time_dt: dt):
    start_time = datetime_to_posix(start_time_dt)
    schedule = get_trading_calendar(start_time_dt, start_time_dt)
    if not schedule.empty:
        start_time, _ = get_schedule_start_and_end(schedule)
    return start_time