Ejemplo n.º 1
0
    def test_parse_realtime_data_single_quote(self):
        raw_data = {"Symbol": "ABC", "LastTradePriceOnly": 123.45}
        test_date = dates.get_database_timestamp().date()

        quotes = stocks._parse_realtime_data(raw_data, TEST_DB_NAME)
        self._check_quotes(quotes, "ABC", test_date, 123.45)
        self._check_database_quotes("ABC", 1, test_date, 123.45)
Ejemplo n.º 2
0
 def test_fetch_realtime_multiple_quotes(self):
     test_date = dates.get_database_timestamp().date()
     quotes = stocks.fetch_realtime(["SPX", "VIX", "AAPL"], TEST_DB_NAME)
     self.assertGreater(quotes["SPX"].close, 0)
     self.assertGreater(quotes["VIX"].close, 0)
     self.assertGreater(quotes["AAPL"].close, 0)
     self._check_database_quotes("SPX", 1, test_date, None)
     self._check_database_quotes("VIX", 1, test_date, None)
     self._check_database_quotes("AAPL", 1, test_date, None)
Ejemplo n.º 3
0
def get_db_date():
    """Get date from request parameters"""
    date = request.args.get("date", None, type=str)
    current_db_date = dates.get_database_timestamp().date()
    if date is not None:
        try:
            date = datetime.strptime(date, "%Y-%m-%d").date()
            date = min(date, current_db_date)
        except ValueError:
            date = current_db_date
    return date
Ejemplo n.º 4
0
    def test_parse_realtime_data(self):
        test_data = """<div class="component">
    <div class="left">
        <a name="VX"></a>
        <h3>VX&nbsp;- &nbsp;CBOE S&amp;P 500 Volatility Index (VIX) Futures</h3>
    </div>
    <div class="table-wrapper">
        <table class="table  oddeven  padvertical  padhorizontal inner-cellborders">
            <tbody>
                <tr>
                    <td><a href="ssfquote.aspx?ticker=VIX/F6" title="VIX/F6">VIX/F6</a></td>
                    <td style="text-align:right"><span>01/20/2016</span>
                    <td style="text-align:right"><span>24.15</span></td>
                    <td style="text-align:right"><span data-numericcolor="-0.575">-0.575</span></td>
                    <td style="text-align:right"><span>25.30</span></td>
                    <td style="text-align:right"><span>24.05</span></td>
                    <td style="text-align:right"><span>24.72</span></td>
                    <td style="text-align:right"><span>3344</span></td>
                    <td style="text-align:right"><span>72413</span></td>
                </tr>
                <tr>
                    <td><a href="ssfquote.aspx?ticker=04VX/F6" title="04VX/F6">04VX/F6</a></td>
                    <td style="text-align:right"><span>01/27/2016</span>
                    <td style="text-align:right"><span>23.875</span></td>
                    <td style="text-align:right"><span data-numericcolor="0.0">0.0</span></td>
                    <td style="text-align:right"><span>0.0</span></td>
                    <td style="text-align:right"><span>0.0</span></td>
                    <td style="text-align:right"><span>23.88</span></td>
                    <td style="text-align:right"><span>0</span></td>
                    <td style="text-align:right"><span>78</span></td>
                </tr>
                <tr>
                    <td><a href="ssfquote.aspx?ticker=VIX/G6" title="VIX/G6">VIX/G6</a></td>
                    <td style="text-align:right"><span>02/17/2016</span>
                    <td style="text-align:right"><span>22.56</span></td>
                    <td style="text-align:right"><span data-numericcolor="-0.565">-0.565</span></td>
                    <td style="text-align:right"><span>23.47</span></td>
                    <td style="text-align:right"><span>22.56</span></td>
                    <td style="text-align:right"><span>23.13</span></td>
                    <td style="text-align:right"><span>2860</span></td>
                    <td style="text-align:right"><span>112614</span></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
"""
        test_date = dates.get_database_timestamp().date()

        quotes = futures._parse_realtime_data('VX', test_data, TEST_DB_NAME)
        self._check_quotes(quotes, 'VX', test_date)
        self._check_database_quotes('VX', 2, test_date, 2)
Ejemplo n.º 5
0
def _parse_realtime_data(symbol, data, db_name=None):
    """Parses realtime (delayed) futures quotes from CBOE website and saves
    them to database.

    Args:
        symbol (str): Symbol.
        data (str): Raw quotes for the symbol.
        db_name (str): Optional database name.

    Returns:
        list: List of FutureQuote objects.
    """
    assert symbol == 'VX'

    logger = logging.getLogger(__name__)
    timestamp = dates.get_database_timestamp()
    date = timestamp.date()
    time = timestamp.time()
    base_symbol = _future_to_base_symbol(symbol)

    quotes = []
    with database.connect_db(db_name) as db:
        try:
            soup = BeautifulSoup(data, 'html5lib')
            table = soup.find('a', {'name': symbol}).parent.parent.find('table')
            for row in table.find_all('tr'):
                cols = row.find_all('td')
                if len(cols) != 9:
                    continue
                row_symbol = cols[0].text.strip().split('/')[0]
                if row_symbol != base_symbol:
                    continue
                expiration = datetime.strptime(
                    cols[1].text.strip(), '%m/%d/%Y').date()
                last = utils.to_float(cols[2].text.strip())
                if last is None:
                    continue
                quote = FutureQuote(symbol, expiration, date, time, last)
                save_quote(db, quote)
                quotes.append(quote)
        except AttributeError:
            logger.error('Cannot parse futures quotes from CBOE for %s ...',
                         symbol)
    return quotes
Ejemplo n.º 6
0
 def test_fetch_realtime_vx(self):
     test_date = dates.get_database_timestamp().date()
     quotes = futures.fetch_realtime('VX', TEST_DB_NAME)
     self._check_quotes(quotes, 'VX', test_date)
     self._check_database_quotes('VX', len(quotes), test_date, len(quotes))
Ejemplo n.º 7
0
 def test_fetch_realtime_non_existing_quote(self):
     test_date = dates.get_database_timestamp().date()
     quotes = stocks.fetch_realtime([NON_EXISTING_SYMBOL], TEST_DB_NAME)
     self.assertIsNone(quotes[NON_EXISTING_SYMBOL].close)
     self._check_database_quotes(NON_EXISTING_SYMBOL, 0, test_date, None)
Ejemplo n.º 8
0
 def test_fetch_realtime_single_quote(self):
     test_date = dates.get_database_timestamp().date()
     quotes = stocks.fetch_realtime(["SPX"], TEST_DB_NAME)
     self._check_quotes(quotes, "SPX", test_date, None)
     self._check_database_quotes("SPX", 1, test_date, None)
Ejemplo n.º 9
0
 def test_fetch_realtime_non_existing(self):
     test_date = dates.get_database_timestamp().date()
     quotes = options.fetch_realtime(NON_EXISTING_SYMBOL, TEST_DB_NAME)
     self.assertEquals(len(quotes), 0)
     self._check_database_quotes(NON_EXISTING_SYMBOL, 0, test_date, 0, False, None)
Ejemplo n.º 10
0
 def test_get_database_timestamp_at_open(self):
     now = datetime(2015, 12, 8, 9, 30)
     self.assertEqual(
         dates.get_database_timestamp(now), datetime(2015, 12, 8, 9, 30))
Ejemplo n.º 11
0
 def test_get_database_timestamp_before_open(self):
     now = datetime(2015, 12, 8, 9, 29)
     self.assertEqual(
         dates.get_database_timestamp(now), datetime(2015, 12, 8, 9, 29))
Ejemplo n.º 12
0
 def test_parse_data_not_eod(self):
     test_date = dates.get_database_timestamp().date()
     quotes = options._parse_data("VIX", self.TEST_DATA, False, TEST_DB_NAME)
     self._check_quotes(quotes, "VIX", test_date, False, 25.22)
     self._check_database_quotes("VIX", 10, test_date, 10, False, 25.22)
Ejemplo n.º 13
0
 def test_query_historical_non_existing(self):
     test_date = dates.get_database_timestamp().date()
     quotes = options.query_historical(NON_EXISTING_SYMBOL, test_date, TEST_DB_NAME)
     self.assertEqual(len(quotes), 0)
Ejemplo n.º 14
0
 def test_query_historical_existing(self):
     test_date = dates.get_database_timestamp().date()
     options.fetch_historical("VIX", TEST_DB_NAME)
     quotes = options.query_historical("VIX", test_date, TEST_DB_NAME)
     self._check_quotes(quotes, "VIX", test_date, True, None)
Ejemplo n.º 15
0
 def test_fetch_historical_non_existing(self):
     test_date = dates.get_database_timestamp().date()
     lines = options.fetch_historical(NON_EXISTING_SYMBOL, TEST_DB_NAME)
     self.assertEquals(lines, 0)
     self._check_database_quotes(NON_EXISTING_SYMBOL, 0, test_date, 0, True, None)
Ejemplo n.º 16
0
 def test_fetch_historical_existing(self):
     test_date = dates.get_database_timestamp().date()
     lines = options.fetch_historical("VIX", TEST_DB_NAME)
     self.assertGreater(lines, 0)
     self._check_database_quotes("VIX", lines, test_date, lines, True, None)
Ejemplo n.º 17
0
def _parse_data(symbol, data, is_eod, db_name=None, timestamp=None):
    """Parses realtime (delayed) options quotes from CBOE and saves to
    database.

    Args:
        symbol (str): Symbol.
        data (str): Raw quotes for the symbol.
        is_eod (bool): If True: mark received quotes as EOD (time=None),
            if False: store actual time.
        db_name (str): Optional database name.
        timestamp (datetime): Optional datetime for the data.

    Returns:
        list: List of OptionQuote objects.
    """
    logger = logging.getLogger(__name__)
    if timestamp is None:
        timestamp = dates.get_database_timestamp()
    date = timestamp.date()
    time = None if is_eod else timestamp.time()

    quotes = []
    stock_price = None
    expirations = dates.get_expirations(symbol)
    with database.connect_db(db_name) as db:
        for line in data.splitlines():
            values = line.strip().split(',')
            if (len(values) == 4) and (stock_price is None):
                stock_price = utils.to_float(values[1])
                continue
            if len(values) != 15:
                continue
            if values[0] == 'Calls' or values[0].find('-') >= 0:
                continue

            code_values = values[0].split(' ')
            if len(code_values) != 4:
                continue
            position = code_values[3].find(code_values[0])
            if code_values[3][1:position] in SKIP_SYMBOLS:
                continue
            expiration_year = 2000 + int(code_values[0])
            expiration_month = MONTHS[code_values[1]]
            expiration_day = int(code_values[3][position + 2:position + 4])
            expiration = datetime(expiration_year, expiration_month,
                                  expiration_day).date()
            if expiration not in expirations:
                continue
            strike = utils.to_float(code_values[2])

            for type_, bid, ask in [
                (consts.CALL, values[3], values[4]),
                (consts.PUT, values[10], values[11]),
            ]:
                bid = utils.to_float(bid)
                ask = utils.to_float(ask)
                quote = OptionQuote(
                    symbol, type_, expiration, strike, date, time,
                    bid, ask, stock_price, None, None)
                iv_bid = math.calc_iv(quote, bid) * 100
                iv_ask = math.calc_iv(quote, ask) * 100
                quote = OptionQuote(
                    symbol, type_, expiration, strike, date, time,
                    bid, ask, stock_price, iv_bid, iv_ask)
                save_quote(db, quote)
                quotes.append(quote)
    logger.info('... quotes parsed: %d', len(quotes))
    return quotes
Ejemplo n.º 18
0
 def test_get_database_timestamp_before_close(self):
     now = datetime(2015, 12, 8, 15, 59)
     self.assertEqual(
         dates.get_database_timestamp(now), datetime(2015, 12, 8, 15, 59))
Ejemplo n.º 19
0
 def test_get_database_timestamp_after_close(self):
     now = datetime(2015, 12, 8, 16, 1)
     self.assertEqual(
         dates.get_database_timestamp(now), datetime(2015, 12, 9, 16, 1))
Ejemplo n.º 20
0
 def test_fetch_realtime_existing(self):
     test_date = dates.get_database_timestamp().date()
     quotes = options.fetch_realtime("VIX", TEST_DB_NAME)
     self._check_quotes(quotes, "VIX", test_date, False, None)
     self._check_database_quotes("VIX", len(quotes), test_date, len(quotes), False, None)