Exemplo n.º 1
0
def update_index_value(symbol):
    value = get_index_value(symbol)
    if during_trading_day():
        add_row("indexes", symbol=symbol, value=value, timestamp=time.time())
        return True

    # a bit of logic to get the close of day price
    with engine.connect() as conn:
        max_time = conn.execute(
            "SELECT MAX(timestamp) FROM indexes WHERE symbol = %s;",
            symbol).fetchone()[0]
        if max_time is None:
            max_time = 0

    ref_day = time.time()
    eod = get_end_of_last_trading_day(ref_day)
    while eod > ref_day:
        ref_day -= SECONDS_IN_A_DAY
        eod = get_end_of_last_trading_day(ref_day)

    if max_time < eod <= time.time():
        add_row("indexes", symbol=symbol, value=value, timestamp=eod)
        return True

    return False
Exemplo n.º 2
0
    def test_index_scrapers(self):
        """This test make sure that our external integration with yahoo finance via the celery workers is running
        properly, as well as that new indexes that get added to our inventory will be properly intitialized, as well as
        that close of day index values will be stored
        """

        with self.engine.connect() as conn:
            conn.execute("TRUNCATE indexes;")
            async_update_all_index_values.delay()
            df = pd.read_sql("SELECT * FROM indexes;", conn)

        iteration = 0
        while df.shape != (3, 4) and iteration < 120:
            time.sleep(1)
            with self.engine.connect() as conn:
                df = pd.read_sql("SELECT * FROM indexes;", conn)
            iteration += 1

        self.assertEqual(df.shape, (3, 4))
        if not during_trading_day():
            ref_day = time.time()
            eod = get_end_of_last_trading_day(ref_day)
            while eod > ref_day:
                ref_day -= SECONDS_IN_A_DAY
                eod = get_end_of_last_trading_day(ref_day)
            [self.assertEqual(eod, x) for x in df["timestamp"].to_list()]
Exemplo n.º 3
0
def async_cache_price(self, symbol: str, price: float, last_updated: float):
    cache_price, cache_time = get_cache_price(symbol)
    if cache_price is not None and cache_time == last_updated:
        return

    if during_trading_day():
        add_row("prices", symbol=symbol, price=price, timestamp=last_updated)
        set_cache_price(symbol, price, last_updated)
Exemplo n.º 4
0
def process_order(order_id: int):
    timestamp = time.time()
    if get_order_expiration_status(order_id):
        add_row("order_status",
                order_id=order_id,
                timestamp=timestamp,
                status="expired",
                clear_price=None)
        return

    order_ticket = query_to_dict("SELECT * FROM orders WHERE id = %s",
                                 order_id)[0]
    symbol = order_ticket["symbol"]
    game_id = order_ticket["game_id"]
    user_id = order_ticket["user_id"]
    buy_or_sell = order_ticket["buy_or_sell"]
    quantity = order_ticket["quantity"]
    order_type = order_ticket["order_type"]

    market_price, _ = fetch_price(symbol)

    # Only process active outstanding orders during trading day
    cash_balance = get_current_game_cash_balance(user_id, game_id)
    current_holding = get_current_stock_holding(user_id, game_id, symbol)
    if during_trading_day():
        if execute_order(buy_or_sell, order_type, market_price,
                         order_ticket["price"], cash_balance, current_holding,
                         quantity):
            order_status_id = add_row("order_status",
                                      order_id=order_id,
                                      timestamp=timestamp,
                                      status="fulfilled",
                                      clear_price=market_price)
            update_balances(user_id, game_id, order_status_id, timestamp,
                            buy_or_sell, cash_balance, current_holding,
                            market_price, quantity, symbol)
            serialize_and_pack_pending_orders(
                game_id, user_id)  # refresh the pending orders table
            add_fulfilled_order_entry(
                game_id, user_id,
                order_id)  # add the new fulfilled orders entry to the table
            serialize_and_pack_portfolio_details(game_id, user_id)
        else:
            # if a market order was placed after hours, there may not be enough cash on hand to clear it at the new
            # market price. If this happens, cancel the order and recalculate the purchase quantity with the new price
            if order_type == "market":
                cancel_order(order_id)
                updated_quantity = cash_balance // market_price
                if updated_quantity <= 0:
                    return

                place_order(user_id, game_id, symbol, buy_or_sell,
                            cash_balance, current_holding, order_type,
                            "Shares", market_price, updated_quantity,
                            order_ticket["time_in_force"])
                serialize_and_pack_portfolio_details(game_id, user_id)
Exemplo n.º 5
0
def place_order(user_id: int,
                game_id: int,
                symbol: str,
                buy_or_sell: str,
                cash_balance: float,
                current_holding: int,
                order_type: str,
                quantity_type: str,
                market_price: float,
                amount: float,
                time_in_force: str,
                stop_limit_price: float = None):
    timestamp = time.time()
    order_price = get_order_price(order_type, market_price, stop_limit_price)
    order_quantity = get_order_quantity(order_price, amount, quantity_type)
    if order_quantity <= 0:
        raise NoNegativeOrders

    if buy_or_sell == "buy":
        qc_buy_order(order_type, quantity_type, order_price, market_price,
                     amount, cash_balance)
    elif buy_or_sell == "sell":
        qc_sell_order(order_type, quantity_type, order_price, market_price,
                      amount, current_holding)
    else:
        raise Exception(f"Invalid buy or sell option {buy_or_sell}")

    # having validated the order, now we'll go ahead and book it
    order_id = add_row("orders",
                       user_id=user_id,
                       game_id=game_id,
                       symbol=symbol,
                       buy_or_sell=buy_or_sell,
                       quantity=order_quantity,
                       price=order_price,
                       order_type=order_type,
                       time_in_force=time_in_force)

    add_row("order_status",
            order_id=order_id,
            timestamp=timestamp,
            status="pending",
            clear_price=None)

    # If this is a market order and we're inside a trading day we'll execute this order at the current price
    if order_type == "market" and during_trading_day():
        os_id = add_row("order_status",
                        order_id=order_id,
                        timestamp=timestamp,
                        status="fulfilled",
                        clear_price=order_price)
        update_balances(user_id, game_id, os_id, timestamp, buy_or_sell,
                        cash_balance, current_holding, order_price,
                        order_quantity, symbol)
    return order_id
    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())
Exemplo n.º 7
0
def check_if_payout_time(current_time: float, payout_time: float) -> bool:
    if current_time >= payout_time:
        return True

    if during_trading_day() and current_time < payout_time:
        return False

    next_day_schedule = get_next_trading_day_schedule(posix_to_datetime(current_time) + timedelta(days=1))
    next_trade_day_start, _ = get_schedule_start_and_end(next_day_schedule)
    if next_trade_day_start > payout_time:
        return True

    return False