Пример #1
0
    def get_latest_price(self, ticker: str) -> Optional[source.SourcePrice]:
        """See contract in beanprice.source.Source."""

        url = "https://query1.finance.yahoo.com/v7/finance/quote"
        fields = ['symbol', 'regularMarketPrice', 'regularMarketTime']
        payload = {
            'symbols': ticker,
            'fields': ','.join(fields),
            'exchange': 'NYSE',
        }
        payload.update(_DEFAULT_PARAMS)
        response = requests.get(url, params=payload)
        result = parse_response(response)
        try:
            price = Decimal(result['regularMarketPrice'])

            tzone = timezone(
                timedelta(hours=result['gmtOffSetMilliseconds'] / 3600000),
                result['exchangeTimezoneName'])
            trade_time = datetime.fromtimestamp(result['regularMarketTime'],
                                                tz=tzone)
        except KeyError as exc:
            raise YahooError("Invalid response from Yahoo: {}".format(
                repr(result))) from exc

        currency = parse_currency(result)

        return source.SourcePrice(price, trade_time, currency)
Пример #2
0
def fetch_quote(ticker):
    """Fetch the latest price for the given ticker."""

    url = "https://api.iextrading.com/1.0/tops/last?symbols={}".format(
        ticker.upper())
    response = requests.get(url)
    if response.status_code != requests.codes.ok:
        raise IEXError("Invalid response ({}): {}".format(
            response.status_code, response.text))

    results = response.json()
    if len(results) != 1:
        raise IEXError("Invalid number of responses from IEX: {}".format(
            response.text))
    result = results[0]

    price = Decimal(result['price']).quantize(Decimal('0.01'))

    # IEX is American markets.
    us_timezone = tz.gettz("America/New_York")
    time = datetime.datetime.fromtimestamp(result['time'] / 1000)
    time = time.astimezone(us_timezone)

    # As far as can tell, all the instruments on IEX are priced in USD.
    return source.SourcePrice(price, time, 'USD')
Пример #3
0
 def _check_valid(self, query_date, out_time, out_price):
     candles = [
         (datetime.datetime(2017, 1, 21, 0, 0, 0,
                            tzinfo=UTC), Decimal('1.3100')),
         (datetime.datetime(2017, 1, 21, 8, 0, 0,
                            tzinfo=UTC), Decimal('1.3300')),
         (datetime.datetime(2017, 1, 21, 16, 0, 0,
                            tzinfo=UTC), Decimal('1.3500')),
         (datetime.datetime(2017, 1, 22, 0, 0, 0,
                            tzinfo=UTC), Decimal('1.3700')),
         (datetime.datetime(2017, 1, 22, 8, 0, 0,
                            tzinfo=UTC), Decimal('1.3900')),
         (datetime.datetime(2017, 1, 22, 16, 0, 0,
                            tzinfo=UTC), Decimal('1.4100')),
         (datetime.datetime(2017, 1, 23, 0, 0, 0,
                            tzinfo=UTC), Decimal('1.4300')),
         (datetime.datetime(2017, 1, 23, 8, 0, 0,
                            tzinfo=UTC), Decimal('1.4500')),
         (datetime.datetime(2017, 1, 23, 16, 0, 0,
                            tzinfo=UTC), Decimal('1.4700')),
     ]
     with mock.patch.object(oanda, '_fetch_candles', return_value=candles):
         query_time = datetime.datetime.combine(query_date,
                                                time=datetime.time(
                                                    16, 0, 0),
                                                tzinfo=UTC)
         srcprice = self.fetcher.get_historical_price('USD_CAD', query_time)
         if out_time is not None:
             self.assertEqual(
                 source.SourcePrice(out_price, out_time, 'CAD'), srcprice)
         else:
             self.assertEqual(None, srcprice)
Пример #4
0
    def get_latest_price(self, ticker):
        symbol, base = _parse_ticker(ticker)
        headers = {
            'X-CMC_PRO_API_KEY': environ['COINMARKETCAP_API_KEY'],
        }
        params = {
            'symbol': symbol,
            'convert': base,
        }

        resp = requests.get(
            url='https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest',
            params=params, headers=headers)
        if resp.status_code != requests.codes.ok:
            raise CoinmarketcapApiError(
                "Invalid response ({}): {}".format(resp.status_code, resp.text)
            )
        data = resp.json()
        if data['status']['error_code'] != 0:
            status = data['status']
            raise CoinmarketcapApiError(
                "Invalid response ({}): {}".format(
                    status['error_code'], status['error_message'])
            )

        quote = data['data'][symbol]['quote'][base]
        price = Decimal(str(quote['price']))
        date = parse(quote['last_updated'])

        return source.SourcePrice(price, date, base)
Пример #5
0
 def get_daily_prices(
         self, ticker: str, time_begin: datetime,
         time_end: datetime) -> Optional[List[source.SourcePrice]]:
     """See contract in beanprice.source.Source."""
     series, currency = get_price_series(ticker, time_begin, time_end)
     return [
         source.SourcePrice(price, time, currency) for time, price in series
     ]
Пример #6
0
def fetch_time_series(ticker, time=None):
    """Fetch"""
    # Create request payload.
    ticker_spec = parse_ticker(ticker)
    url = "https://www.quandl.com/api/v3/datasets/{}/{}.json".format(
        ticker_spec.database, ticker_spec.dataset)
    payload = {"limit": 1}
    if time is not None:
        date = time.date()
        payload["start_date"] = (date -
                                 datetime.timedelta(days=10)).isoformat()
        payload["end_date"] = date.isoformat()

    # Add API key, if it is set in the environment.
    if 'QUANDL_API_KEY' in os.environ:
        payload['api_key'] = os.environ['QUANDL_API_KEY']

    # Fetch and process errors.
    response = requests.get(url, params=payload)
    if response.status_code != requests.codes.ok:
        raise QuandlError("Invalid response ({}): {}".format(
            response.status_code, response.text))
    result = response.json()
    if 'quandl_error' in result:
        raise QuandlError(result['quandl_error']['message'])

    # Parse result container.
    dataset = result['dataset']
    column_names = dataset['column_names']
    date_index = column_names.index('Date')
    if ticker_spec.column is not None:
        data_index = column_names.index(ticker_spec.column)
    else:
        try:
            data_index = column_names.index('Adj. Close')
        except ValueError:
            data_index = column_names.index('Close')
    data = dataset['data'][0]

    # Gather time and assume it's in UTC timezone (Quandl does not provide the
    # market's timezone).
    time = datetime.datetime.strptime(data[date_index], '%Y-%m-%d')
    time = time.replace(tzinfo=tz.tzutc())

    # Gather price.
    # Quantize with the same precision default rendering of floats occur.
    price_float = data[data_index]
    price = Decimal(price_float)
    match = re.search(r'(\..*)', str(price_float))
    if match:
        price = price.quantize(Decimal(match.group(1)))

    # Note: There is no currency information in the response (surprising).
    return source.SourcePrice(price, time, None)
Пример #7
0
 def _test_valid(self):
     candles = [
         (datetime.datetime(2017, 1, 21, 0, 45, 15, tzinfo=UTC), Decimal('1.330115')),
         (datetime.datetime(2017, 1, 21, 0, 45, 20, tzinfo=UTC), Decimal('1.330065')),
     ]
     with mock.patch.object(oanda, '_fetch_candles', return_value=candles):
         srcprice = self.fetcher.get_latest_price('USD_CAD')
         # Latest price, with current time as time.
         self.assertEqual(source.SourcePrice(
             Decimal('1.330065'),
             datetime.datetime(2017, 1, 21, 0, 45, 20, tzinfo=UTC),
             'CAD'), srcprice)
Пример #8
0
    def get_historical_price(self, ticker: str,
                             time: datetime) -> Optional[source.SourcePrice]:
        """See contract in beanprice.source.Source."""

        # Get the latest data returned over the last 5 days.
        series, currency = get_price_series(ticker, time - timedelta(days=5), time)
        latest = None
        for data_dt, price in sorted(series):
            if data_dt >= time:
                break
            latest = data_dt, price
        if latest is None:
            raise YahooError("Could not find price before {} in {}".format(time, series))

        return source.SourcePrice(price, data_dt, currency)
Пример #9
0
def _get_quote(ticker, date):
    """Fetch a exchangerate from ratesapi."""
    base, symbol = _parse_ticker(ticker)
    params = {
        'base': base,
        'symbol': symbol,
    }
    response = requests.get(url='https://api.exchangerate.host/' + date, params=params)

    if response.status_code != requests.codes.ok:
        raise RatesApiError("Invalid response ({}): {}".format(response.status_code,
                                                            response.text))

    result = response.json()

    price = Decimal(str(result['rates'][symbol]))
    time = parse(result['date']).replace(tzinfo=tz.tzutc())

    return source.SourcePrice(price, time, symbol)
Пример #10
0
def fetch_quote(ticker, time=None):
    """Fetch a quote from Coinbase."""
    url = "https://api.coinbase.com/v2/prices/{}/spot".format(ticker.lower())
    options = {}
    if time is not None:
        options['date'] = time.astimezone(tz.tzutc()).date().isoformat()

    response = requests.get(url, options)
    if response.status_code != requests.codes.ok:
        raise CoinbaseError("Invalid response ({}): {}".format(
            response.status_code, response.text))
    result = response.json()

    price = Decimal(result['data']['amount'])
    if time is None:
        time = datetime.datetime.now(tz.tzutc())
    currency = result['data']['currency']

    return source.SourcePrice(price, time, currency)
Пример #11
0
    def _get_price(self, ticker, time=None):
        base, symbol = ticker.split(':')
        url_params = {
            'base': base,
            'symbols': symbol,
        }
        if time is None:
            date_str = 'latest'
        else:
            date_str = time.strftime('%Y-%m-%d')

        url = urljoin(API_BASE_URL, date_str) + '?' + urlencode(url_params)
        response = urlopen(url)
        result = json.loads(response.read().decode())

        price = to_decimal(result['rates'][symbol], 4)
        price_time = datetime.datetime.\
            strptime(result['date'], '%Y-%m-%d').\
            replace(tzinfo=datetime.timezone.utc)
        return source.SourcePrice(price, price_time, base)
Пример #12
0
    def _get_price(ticker, time=None):
        dataset, data_id, quote_currency = ticker.split(':')
        if time is None:
            date = datetime.utcnow().replace(tzinfo=pytz.utc)
        else:
            date = time
        # https://finmind.github.io/quickstart/#api_1
        parameter = {
            "dataset": dataset,
            "data_id": data_id,
            "start_date": (date.strftime(Source.DATE_FORMAT)),
        }
        resp = requests.get(Source.API_ENDPOINT, params=parameter)
        data = resp.json()["data"]
        if len(data) == 0:
            # No data today
            return None

        close_price = data[0]["close"]
        price = D(close_price).quantize(D('0.00'))
        return source.SourcePrice(price, date, quote_currency)
Пример #13
0
    def _get_price(self, ticker, time=None):
        base, symbol = ticker.split(':')
        url_params = {'base': base, 'symbols': symbol, 'source': SOURCE}
        if time is None:
            date_str = 'latest'
        else:
            date_str = time.strftime('%Y-%m-%d')

        url = urljoin(EXCHANGERATE_API_URL,
                      date_str) + '?' + urlencode(url_params)
        request = Request(url)
        # Requests without User-Agent header can be blocked
        request.add_header('User-Agent', 'price-fetcher')
        response = urlopen(request)
        result = json.loads(response.read().decode())

        price = to_decimal(result['rates'][symbol], 4)
        price_time = datetime.datetime.\
            strptime(result['date'], '%Y-%m-%d').\
            replace(tzinfo=datetime.timezone.utc)
        return source.SourcePrice(price, price_time, base)
Пример #14
0
def _fetch_price(params_dict, time):
    """Fetch a price from OANDA using the given parameters."""
    ticker = params_dict['instrument']
    _, quote_currency = _get_currencies(ticker)
    if quote_currency is None:
        logging.error("Invalid price source ticker '%s'; must be like 'EUR_USD'",
                      ticker)
        return

    time_prices = _fetch_candles(params_dict)
    if not time_prices:
        logging.error("No prices returned.")
        return

    # Get all the prices before and on the same date and find the latest.
    sorted_prices = [item for item in time_prices if item[0] <= time]
    if not sorted_prices:
        logging.error("No prices matched.")
        return

    time, price = sorted_prices[-1]
    return source.SourcePrice(price, time, quote_currency)
Пример #15
0
    def get_historical_price(self, fund, time):
        """See contract in beanprice.source.Source."""
        if requests is None:
            raise TSPError("You must install the 'requests' library.")

        if fund not in TSP_FUND_NAMES:
            raise TSPError(
                "Invalid TSP Fund Name '{}'. Valid Funds are:\n\t{}".format(
                    fund, "\n\t".join(TSP_FUND_NAMES)))

        url = "https://secure.tsp.gov/components/CORS/getSharePricesRaw.html"
        fields = ['startdate', 'enddate', 'download', 'Lfunds', 'InvFunds']
        payload = {
            # Grabbing the last fourteen days of data in event the markets were closed.
            'startdate':
            (time - datetime.timedelta(days=14)).strftime("%Y%m%d"),
            'enddate': time.strftime("%Y%m%d"),
            'download': '0',
            'Lfunds': '1',
            'InvFunds': '1'
        }

        response = requests.get(url, params=payload)
        result = parse_response(response)
        trade_day = list(result.items())[0]
        prices = trade_day[1]

        try:
            price = prices[TSP_FUND_NAMES.index(fund)]

            trade_time = trade_day[0]
        except KeyError as exc:
            raise TSPError("Invalid response from TSP: {}".format(
                repr(result))) from exc

        return source.SourcePrice(price, trade_time, CURRENCY)