Ejemplo n.º 1
0
def parse_mnb_result(mnb_result, ticker):
    """Válasz XML feldolgozása, átalakítása a beancount által elvárt beancount.prices.source.SourcePrice() formátumra

    <MNBCurrentExchangeRates>
        <Day date="2019-02-22">
            <Rate unit="1" curr="AUD">199,16000</Rate>
            <Rate unit="1" curr="BGN">162,51000</Rate>
        </Day>
    </MNBCurrentExchangeRates>
    """
    # kézi XML feldolgozás, mert az MNB lusta volt XSD sémát mellékelni a servicehez
    root = etree.fromstring(mnb_result)
    if len(root) > 0:
        # ha a fa gyökerének van eleme (<Day>), dátum feldolgozása
        datum = datetime.strptime(root[0].attrib['date'], '%Y-%m-%d').replace(tzinfo=pytz.timezone('CET'))
        # végigmegyünk a <Rate> elemeken
        for currency in root[0]:
            if currency.attrib['curr'] == ticker:
                # ha a kért árfolyam devizaneme megfelel, árfolyam konvertálása 1 egységre
                arfolyam = Decimal(currency.text.replace(',', '.'))
                egyseg = int(currency.attrib['unit'])
                return source.SourcePrice(price=Decimal(arfolyam / egyseg), time=datum, quote_currency='HUF')
    else:
        # ha az xml fa gyökerének nincs eleme, akkor aznapra nincs érvényes árfolyam
        return source.SourcePrice(price=None, time=datetime.now(tz=pytz.timezone('CET')), quote_currency='HUF')
Ejemplo n.º 2
0
 def _check_valid(self, query_date, out_time, out_price):
     candles = [
         (datetime.datetime(2017, 1, 21, 0, 0, 0,
                            tzinfo=tz.tzutc()), D('1.3100')),
         (datetime.datetime(2017, 1, 21, 8, 0, 0,
                            tzinfo=tz.tzutc()), D('1.3300')),
         (datetime.datetime(2017, 1, 21, 16, 0, 0,
                            tzinfo=tz.tzutc()), D('1.3500')),
         (datetime.datetime(2017, 1, 22, 0, 0, 0,
                            tzinfo=tz.tzutc()), D('1.3700')),
         (datetime.datetime(2017, 1, 22, 8, 0, 0,
                            tzinfo=tz.tzutc()), D('1.3900')),
         (datetime.datetime(2017, 1, 22, 16, 0, 0,
                            tzinfo=tz.tzutc()), D('1.4100')),
         (datetime.datetime(2017, 1, 23, 0, 0, 0,
                            tzinfo=tz.tzutc()), D('1.4300')),
         (datetime.datetime(2017, 1, 23, 8, 0, 0,
                            tzinfo=tz.tzutc()), D('1.4500')),
         (datetime.datetime(2017, 1, 23, 16, 0, 0,
                            tzinfo=tz.tzutc()), D('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=tz.tzutc())
         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)
Ejemplo n.º 3
0
    def _get_price_for_date(self, ticker, date=None):
        paramater = ticker.split("--")
        currency = paramater[1].upper()

        if date == None:
            timestamp = int(datetime.today().timestamp())
        else:
            timestamp = int(date.timestamp())

        url = BASE_URL_TEMPLATE.substitute(date_start=timestamp,
                                           date_end=timestamp + 1,
                                           ticker=paramater[0],
                                           currency=currency)

        try:
            content = requests.get(url).content
            ret = json.loads(content)
            quote = ret['data']['quotes'][0]['quote'][currency]
            price = D(quote['close'])
            return source.SourcePrice(price, date, CURRENCY)

        except KeyError:
            raise CoinmarketcapError(
                "Invalid response from Coinmarketcap: {}".format(
                    repr(content)))
        except AttributeError:
            raise CoinmarketcapError(
                "Invalid response from Coinmarketcap: {}".format(
                    repr(content)))
Ejemplo n.º 4
0
    def _get_price(self, ticker, time=None):
        match = TICKER_REGEXP.match(ticker)
        base_currency, quote_currency = match.groups()
        data = get_data(base_currency)

        if time is None:
            price_str = data['rebalancing_set']['price_usd']
            price = to_decimal(price_str, 6)
            price_time = datetime.datetime.now(tz=datetime.timezone.utc)
        else:
            time_utc = time.astimezone(datetime.timezone.utc)
            sorted_prices = sorted(zip(
                data['rebalancing_set']['historicals']['dates'],
                data['rebalancing_set']['historicals']['prices'],
            ),
                                   key=lambda item: item[0])
            for price_time_str, price_str in sorted_prices:
                price_time = datetime.datetime.strptime(
                    price_time_str,
                    '%Y-%m-%dT%H:%M:%SZ',
                ).replace(tzinfo=datetime.timezone.utc)
                if price_time.date() == time_utc.date() \
                        and price_time > time_utc:
                    price = to_decimal(price_str, 6)
                    break
            else:
                return None

        return source.SourcePrice(price, price_time, base_currency)
Ejemplo n.º 5
0
    def get_latest_price(self, ticker):
        """Fetch the current latest price. The date may differ.

        This routine attempts to fetch the most recent available price, and
        returns the actual date of the quoted price, which may differ from the
        date this call is made at. {1cfa25e37fc1}

        Args:
          ticker: A string, the ticker to be fetched by the source. This ticker
            may include structure, such as the exchange code. Also note that
            this ticker is source-specified, and is not necessarily the same
            value as the commodity symbol used in the Beancount file.
        Returns:
          A SourcePrice instance. If the price could not be fetched, None is
          returned and another source should be consulted. There is never any
          guarantee that a price source will be able to fetch its value; client
          code must be able to handle this. Also note that the price's returned
          time must be timezone-aware.
        """
        try:
            theStock = Stock(ticker)
            theQuote = theStock.get_book()["quote"]

            # IEX is American markets.
            us_timezone = tz.gettz("America/New_York")
            theDate = datetime.datetime.fromtimestamp(
                theQuote["latestUpdate"] / 1000)
            theDate = theDate.astimezone(us_timezone)

            thePrice = D(theQuote["latestPrice"]).quantize(D("0.01"))
            return source.SourcePrice(thePrice, theDate, "USD")
        except Exception:
            raise IEXError("Erreur lors de l'execution de la requete")
            return None
Ejemplo n.º 6
0
    def get_latest_price(self, ticker):
        token = environ['IBKR_TOKEN']
        queryId = environ['IBKR_QUERY_ID']

        try:
            response = client.download(token, queryId)
        except client.ResponseCodeError as e:
            if e.code == '1018':
                sleep(10)
                response = client.download(token, queryId)
            else:
                raise e

        statement = parser.parse(response)
        for position in statement.FlexStatements[0].OpenPositions:
            if position.symbol.rstrip('z') == ticker:
                price = D(position.markPrice)
                timezone = tz.gettz("Europe/Zurich")
                time = datetime.combine(
                    position.reportDate,
                    datetime.min.time()).astimezone(timezone)

                return source.SourcePrice(price, time, position.currency)

        return None
    def _get_price_for_date(self, ticker, date=None):
        time.sleep(TIME_DELAY)

        if date == None:
            url = BASE_URL_TEMPLATE_WITHOUT_TIME.substitute(ticker=ticker)
        else:
            # Somehow it expects a 3 day timespan in the query
            time_start = int((date - timedelta(days=1)).timestamp())
            time_end = int((date + timedelta(days=2)).timestamp())
            url = BASE_URL_TEMPLATE_WITH_TIME.substitute(time_start=time_start, time_end=time_end, ticker=ticker)


        try:
            content = requests.get(url).content
            parsed_content = json.loads(content)            
            quotes = parsed_content['data']['quotes']

            if date == None:
                # If no date, pick the latest
                quote = max(quotes, key = lambda x: parser.isoparse(x['time_open']))
            else:
                quote = list(filter(lambda x: parser.isoparse(x['time_open']) == date, quotes))
                assert len(quote) == 1
                quote = quote[0]

            date = parser.isoparse(quote['quote'][CURRENCY]['timestamp'])
            price = D(quote['quote'][CURRENCY]['close']).quantize(D('0.0000'))

            return source.SourcePrice(price, date, CURRENCY)
        except KeyError as e:
            raise CoinmarketcapError("Exception {}, Invalid response from Coinmarketcap: {}".format(e, repr(content)))
        except AttributeError as e:
            raise CoinmarketcapError("Exception {}, Invalid response from Coinmarketcap: {}".format(e, repr(content)))
Ejemplo n.º 8
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 = D(result['price']).quantize(D('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')
Ejemplo n.º 9
0
    def _get_price_for_date(self, ticker, date=None):
        time.sleep(TIME_DELAY)

        if date == None:
            date_string = ""
        else:
            date_string = date.strftime("%Y%m%d")

        url = BASE_URL_TEMPLATE.substitute(date=date_string, ticker=ticker)

        try:
            content = requests.get(url).content
            soup = BeautifulSoup(content, 'html.parser')
            table = soup.find('table', {'class': 'table'})
            tr = table.findChildren('tr')[1]
            data = [td.text.strip() for td in tr.findChildren('td')]

            parsed_date = parse_date_liberally(data[0])
            date = datetime(parsed_date.year,
                            parsed_date.month,
                            parsed_date.day,
                            tzinfo=utc)

            price = D(data[4])

            return source.SourcePrice(price, date, CURRENCY)

        except KeyError:
            raise CoinmarketcapError(
                "Invalid response from Coinmarketcap: {}".format(
                    repr(content)))
        except AttributeError:
            raise CoinmarketcapError(
                "Invalid response from Coinmarketcap: {}".format(
                    repr(content)))
Ejemplo n.º 10
0
    def get_latest_price(self, ticker):
        """See contract in beancount.prices.source.Source."""

        _, quote_currency = _get_currencies(ticker)
        if quote_currency is None:
            logging.error(
                "Invalid price source ticker '%s'; must be like 'EUR_USD'",
                ticker)
            return

        # Query at the current (latest) time.
        params_dict = {
            'instrument': ticker,
            'granularity': 'S5',  # Every two hours.
            'count': '10',
            'candleFormat': 'midpoint',
        }
        time_prices = _fetch_candles(params_dict)
        if time_prices is None:
            return

        # Get the latest price point available.
        time, price = sorted(time_prices)[-1]

        # Use current local date as the date.
        current_date = datetime.datetime.now()

        return source.SourcePrice(price, current_date, quote_currency)
    def get_latest_price(self, ticker):
        """See contract in beancount.prices.source.Source."""

        path_to_script = os.path.abspath(os.path.dirname(__file__)) + "/financequote.pl"
        params = [path_to_script]

        if ':' in ticker:
            exchange, symbol = ticker.split(':')
        else:
            # exchange and symbol were not both supplied
            return None

        params = [path_to_script, exchange, symbol]
        # output is a json object with keys in the form "$symbol\u001$variable"
        output = subprocess.check_output(params).decode()
        info = json.loads(output)
        # remove the `symbol` prefix from the keys (+1 for control character)
        info = {x[len(symbol) + 1:]: info[x] for x in info.keys()}

        if 'price' not in info:
            return None  # data was not able to be fetched

        currency = info['currency']
        # Finance::Quote returns date in mm/dd/YY format
        trade_date = datetime.datetime.strptime(info['date'], "%m/%d/%Y")
        price = D(info['price'])
        return source.SourcePrice(price, trade_date, currency)
Ejemplo n.º 12
0
    def _get_price_for_date(self, ticker, date=None):
        paramater = ticker.split("--")
        currency = paramater[1].upper()

        if date == None:
            date = datetime.today().replace(hour=0, minute=0,
                                            second=0) + timedelta(days=-1)
        end_date = date + timedelta(days=1)

        url = BASE_URL_TEMPLATE.substitute(date_start=int(date.timestamp()),
                                           date_end=int(end_date.timestamp()),
                                           ticker=paramater[0],
                                           currency=currency)

        try:
            content = requests.get(url).content
            ret = json.loads(content)
            quote = ret['data']['quotes'][0]['quote'][currency]
            price = D(quote['close'])
            return source.SourcePrice(price, date, CURRENCY)

        except:
            raise CoinmarketcapError(
                "Invalid response from Coinmarketcap: {}".format(
                    repr(content)))
Ejemplo n.º 13
0
 def test_get_latest_price(self):
     self.response.read.return_value = textwrap.dedent("""\
         {
                 "instrument" : "USD_CAD",
                 "granularity" : "S5",
                 "candles" : [
                         {
                                 "time" : "2016-04-04T21:19:17.000000Z",
                                 "openMid" : 1.308475,
                                 "highMid" : 1.308475,
                                 "lowMid" : 1.308475,
                                 "closeMid" : 1.308475,
                                 "volume" : 1,
                                 "complete" : true
                         }
                 ]
         }
     """).encode('utf-8')
     srcprice = self.fetcher.get_latest_price('USD_CAD')
     self.assertIsNotNone(srcprice)
     self.assertTrue(isinstance(srcprice.price, Decimal))
     expected = source.SourcePrice(
         D('1.308475'),
         datetime.datetime(2016,
                           4,
                           4,
                           21,
                           19,
                           17,
                           tzinfo=dateutil.tz.tzutc()), 'CAD')
     self.assertEqual(expected, srcprice)
Ejemplo n.º 14
0
    def get_latest_price(self, ticker):
        """See contract in beancount.prices.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 = D(result['regularMarketPrice'])

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

        currency = parse_currency(result)

        return source.SourcePrice(price, trade_time, currency)
Ejemplo n.º 15
0
    def _get_daily_price(self, fund, date=None):
        assert fund[0] == "F"
        params = {
            "callback": "thecallback",
            "fundCode": fund[1:],
            "pageIndex": 1,
            "pageSize": 1,

        }
        if date is not None:
            dt_str = date.strftime("%Y-%m-%d")
            params.update({
                "startDate": dt_str,
                "endDate": dt_str,
            })
        resp = self.http.get(
            "https://api.fund.eastmoney.com/f10/lsjz",
            params=params,
            headers={
                "Referer": "http://fundf10.eastmoney.com/jjjz_{fund}.html"
            }
        )
        assert resp.status_code == 200, resp.text
        result_str = next(re.finditer("thecallback\((.*)\)", resp.text)).groups()[0]
        result = json.loads(result_str)
        records = result["Data"]["LSJZList"]
        if len(records) == 0:
            return

        trade_date = records[0]["FSRQ"]
        nav = D(records[0]["DWJZ"]).quantize(D('1.000000000000000000'))
        trade_date = datetime.strptime(trade_date, "%Y-%m-%d")
        trade_date = utils.default_tzinfo(trade_date, CN_TZ)

        return source.SourcePrice(nav, trade_date, 'CNY')
Ejemplo n.º 16
0
 def setUp(self):
     fetch_cached = mock.patch(
         'beancount.prices.price.fetch_cached_price').start()
     fetch_cached.return_value = source.SourcePrice(
         D('125.00'), datetime.datetime(2015, 11, 22, 16, 0, 0), 'JPY')
     self.dprice = find_prices.DatedPrice('JPY', 'USD',
                                          datetime.date(2015, 11, 22), None)
     self.addCleanup(mock.patch.stopall)
Ejemplo n.º 17
0
 def get_latest_price(self, ticker):
     resp = self.cached_request("CURRENCY_EXCHANGE_RATE", ticker)
     base = resp['Realtime Currency Exchange Rate']
     last_refreshed = base["6. Last Refreshed"]
     last_refreshed_tz = base['7. Time Zone']
     return source.SourcePrice(
         D(base['5. Exchange Rate']),
         datetime.fromisoformat(last_refreshed).replace(
             tzinfo=self.get_timezone(last_refreshed_tz)), self.currency)
Ejemplo n.º 18
0
    def get_latest_price(self, ticker):
        resp = requests.get(url='https://www.bitstamp.net/api/v2/ticker/' + ticker.lower() + 'eur/')
        data = resp.json()

        price = D(data['last'])
        date = datetime.datetime.fromtimestamp(int(data['timestamp']))

        us_timezone = tz.gettz("Europe/Zurich")
        time = date.astimezone(us_timezone)
        return source.SourcePrice(price, time, 'EUR')
Ejemplo n.º 19
0
    def get_historical_price(self, compound_ticker, date):
        """See contract in beancount.prices.source.Source."""

        # security_type, exchange, ticker = compound_ticker.lower().split(':')
        # symbol = self.get_ft_symbol(security_type, exchange, ticker)
        symbol = compound_ticker

        if not symbol:
            logging.info("Could not find secId for %s" % compound_ticker)
            return None

        # Look back some number of days in the past in order to make sure we hop
        # over national holidays.
        begin_date = date - datetime.timedelta(days=5)
        end_date = date

        # template = 'http://mschart.morningstar.com/chartweb/defaultChart?type=getcc&secids={}&dataid={}&startdate={}&enddate={}&currency=&format=1'
        template = 'https://markets.ft.com/data/equities/ajax/get-historical-prices?startDate={}&endDate={}&symbol={}'

        def fmt(d):
            return d.strftime('%Y/%m/%d')

        # symbol = 19753923
        url = template.format(fmt(begin_date), fmt(end_date), symbol)
        logging.info("Fetching %s", url)

        try:
            response = net_utils.retrying_urlopen(url)
            if response is None:
                return None
            response = response.read().decode('utf-8').strip()
            response = json.loads(response)
            if 'status' in response:
                status = response['status']
                if status['code'] != 200:
                    logging.info("HTTP Status: [%s] %s" %
                                 (status['code'], status['message']))
                    return None
            soup = BeautifulSoup(response['html'], 'html.parser')
        except error.HTTPError:
            return None

        try:
            entries = soup.find_all('td')
            trade_date = entries[0].find_all('span')[0].contents[0]
            trade_date = datetime.datetime.strptime(trade_date,
                                                    '%A, %B %d, %Y')
            trade_date = trade_date.replace(tzinfo=pytz.UTC)
            price = D(entries[4].contents[0])

            return source.SourcePrice(price, trade_date, None)
        except:
            import sys
            logging.error("Error parsing data.", sys.exc_info()[0])
            return None
Ejemplo n.º 20
0
    def get_historical_price(self, ticker, date):
        """See contract in beancount.prices.source.Source."""

        _, quote_currency = _get_currencies(ticker)
        if quote_currency is None:
            logging.error(
                "Invalid price source ticker '%s'; must be like 'EUR_USD'",
                ticker)
            return

        # Find the boundary dates to query in UTC timezone.
        start_utc = datetime.datetime(date.year,
                                      date.month,
                                      date.day,
                                      0,
                                      0,
                                      0,
                                      tzinfo=tz.tzlocal()).astimezone(
                                          tz.tzutc())
        end_utc = start_utc + datetime.timedelta(days=1)

        interval_begin_utc = (start_utc - datetime.timedelta(days=5))
        interval_end_utc = (end_utc + datetime.timedelta(days=5))

        # Build the query.
        params_dict = {
            'instrument': ticker,
            'granularity': 'H2',  # Every two hours.
            'candleFormat': 'midpoint',
            'start': interval_begin_utc.isoformat('T'),
            'end': interval_end_utc.isoformat('T'),
        }
        time_prices = _fetch_candles(params_dict)

        # Get all the prices with the same date.
        same_date = [
            item for item in time_prices if start_utc <= item[0] < end_utc
        ]
        if same_date:
            # Find the min/max and return the median of all prices.
            sorted_prices = sorted(same_date, key=lambda item: item[1])
            time, price = sorted_prices[len(sorted_prices) // 2]
        else:
            # No price matching the date were found; use the midpoint of the
            # last price before the day interval and the first price after the
            # day interval.
            before_time, before_price = min(item for item in time_prices
                                            if item[0] < start_utc)
            after_time, after_price = max(item for item in time_prices
                                          if item[0] >= end_utc)
            price = (after_price + before_price) / 2
            time = before_time + (after_time - before_time) / 2

        return source.SourcePrice(price, time, quote_currency)
    def get_latest_price(self, ticker):
        resp = requests.get(url='https://api.ratesapi.io/latest?base=' +
                            ticker + '&symbols=CHF')
        data = resp.json()

        price = D(str(data['rates']['CHF']))
        date = parse(data['date'])

        us_timezone = tz.gettz("Europe/Zurich")
        time = date.astimezone(us_timezone)
        return source.SourcePrice(price, time, 'CHF')
Ejemplo n.º 22
0
    def _get_price(self, ticker, time=None):
        match = TICKER_REGEXP.match(ticker)
        api_key, base_currency, quote_currency = match.groups()
        data = get_latest_quote(api_key, base_currency, quote_currency)

        price = to_decimal(data['price'], 8)
        price_time = datetime.datetime.strptime(
            data['last_updated'],
            '%Y-%m-%dT%H:%M:%S.%fZ',
        ).replace(tzinfo=datetime.timezone.utc)
        return source.SourcePrice(price, price_time, base_currency)
Ejemplo n.º 23
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 = D(price_float)
    match = re.search(r'(\..*)', str(price_float))
    if match:
        price = price.quantize(D(match.group(1)))

    # Note: There is no currency information in the response (surprising).
    return source.SourcePrice(price, time, None)
Ejemplo n.º 24
0
 def _get_price(self, ticker, time=None):
     match = TICKER_REGEXP.match(ticker)
     api_key, token_address, quote_currency = match.groups()
     token_price, symbol = get_exchange_rate(api_key, token_address)
     underlying_price, timestamp = cryptonator.get_latest_price(
         symbol[1:],  # iDAI -> DAI
         quote_currency,
     )
     price = to_decimal(token_price * float(underlying_price), 8)
     price_time = datetime.datetime.fromtimestamp(timestamp).\
         replace(tzinfo=datetime.timezone.utc)
     return source.SourcePrice(price, price_time, symbol)
Ejemplo n.º 25
0
    def get_historical_price(self, ticker, time):
        us_timezone = tz.gettz("Europe/Zurich")
        reqdate = time.astimezone(us_timezone).date()

        resp = requests.get(url='https://api.exchangeratesapi.io/' +
                            str(reqdate) + '?base=' + ticker + '&symbols=CHF')
        data = resp.json()

        price = D(str(data['rates']['CHF']))
        date = parse(data['date'])

        time = date.astimezone(us_timezone)
        return source.SourcePrice(price, time, 'CHF')
Ejemplo n.º 26
0
    def get_historical_price(self, ticker, date):
        """See contract in beancount.prices.source.Source."""

        # Look back some number of days in the past in order to make sure we hop
        # over national holidays.
        begin_date = date - datetime.timedelta(days=5)
        end_date = date

        # Make the query.
        params = parse.urlencode(
            sorted({
                'q': ticker,
                'startdate': begin_date.strftime('%b+%d,%Y'),
                'enddate': end_date.strftime('%b+%d,%Y'),
                'num': 5,
                'output': 'csv',
            }.items()))
        url = 'http://www.google.com/finance/historical?{}'.format(params)
        try:
            response = net_utils.retrying_urlopen(url)
            if response is None:
                return None
            data = response.read()
        except socket.timeout:
            logging.error("Connection timed out")
            return None
        except error.HTTPError:
            # When the instrument is incorrect, you will get a 404.
            return None

        # Note: utf-8-sig automatically skips the BOM here.
        data = data.decode('utf-8-sig').strip()

        lines = data.splitlines()
        assert len(lines) >= 2, "Too few lines in returned data: {}".format(
            len(lines))

        # Parse the header, find the column for the adjusted close.
        columns = lines[0].split(',')
        index_price = columns.index('Close')
        assert index_price >= 0, "Could not find 'Adj Close' data column."
        index_date = columns.index('Date')
        assert index_date >= 0, "Could not find 'Date' data column."

        # Get the latest data returned.
        most_recent_data = lines[1].split(',')
        close_price = D(most_recent_data[index_price])
        date = datetime.datetime.strptime(most_recent_data[index_date],
                                          '%d-%b-%y')

        return source.SourcePrice(close_price, date, None)
Ejemplo n.º 27
0
    def get_latest_price(self, ticker):
        """Fetch the current latest price. The date may differ.

        This routine attempts to fetch the most recent available price, and
        returns the actual date of the quoted price, which may differ from the
        date this call is made at. {1cfa25e37fc1}

        Args:
          ticker: A string, the ticker to be fetched by the source. This ticker
            may include structure, such as the exchange code. Also note that
            this ticker is source-specified, and is not necessarily the same
            value as the commodity symbol used in the Beancount file.
        Returns:
          A SourcePrice instance. If the price could not be fetched, None is
          returned and another source should be consulted. There is never any
          guarantee that a price source will be able to fetch its value; client
          code must be able to handle this. Also note that the price's returned
          time must be timezone-aware.
        """

        s = requests.Session()
        url = (
            BASEURL
            + "/Bio/rech_part.aspx?varvalidform=on&CodeISIN="
            + ticker
            + "&CLASSPROD=0&NumAgr=&selectNRJ=0&NomProd=&NomSOc=&action=new&valid_form=Lancer+la+recherche"
        )
        r = s.get(url)
        soup = BeautifulSoup(r.text, "html.parser")
        try:
            soup.find("input", {"name": "NumProd"})["value"]
        except Exception:
            raise AMFGecoError("ISIN introuvable sur AMFGeco")
            return None

        theDate = soup.find("td", text="Date VL :").next_sibling.get_text(
            strip=True
        )
        theDate = parse_datetime(theDate, dayfirst=True)
        fr_timezone = tz.gettz("Europe/Paris")
        theDate = theDate.astimezone(fr_timezone)

        thePrice = soup.find("td", text="Valeur (€) :").next_sibling.get_text(
            strip=True
        )
        thePrice = D(thePrice.replace(" ", "").replace(",", ".")).quantize(
            D("0.01")
        )

        return source.SourcePrice(thePrice, theDate, "EUR")
Ejemplo n.º 28
0
def fetch_quote(ticker):
    """Fetch a quote from Coinbase."""
    url = "https://api.coinbase.com/v2/prices/{}/spot".format(ticker.lower())
    response = requests.get(url)
    if response.status_code != requests.codes.ok:
        raise CoinbaseError("Invalid response ({}): {}".format(response.status_code,
                                                               response.text))
    result = response.json()

    price = D(result['data']['amount']).quantize(D('0.01'))
    time = datetime.datetime.now(tz.tzutc())
    currency = result['data']['currency']

    return source.SourcePrice(price, time, currency)
Ejemplo n.º 29
0
    def get_historical_price(self, ticker, date):
        """See contract in beancount.prices.source.Source."""

        # Look back some number of days in the past in order to make sure we hop
        # over national holidays.
        begin_date = date - datetime.timedelta(days=5)
        end_date = date

        # Make the query.
        params = parse.urlencode(
            sorted({
                's': ticker,
                'a': begin_date.month - 1,
                'b': begin_date.day,
                'c': begin_date.year,
                'd': end_date.month - 1,
                'e': end_date.day,
                'f': end_date.year,
                'g': 'd',
                'ignore': '.csv',
            }.items()))
        url = 'http://ichart.yahoo.com/table.csv?{}'.format(params)
        try:
            response = net_utils.retrying_urlopen(url)
            if response is None:
                return None
            data = response.read().decode('utf-8').strip()
        except error.HTTPError:
            return None
        if response is None:
            return None

        lines = data.splitlines()
        assert len(lines) >= 2, "Too few lines in returned data: {}".format(
            len(lines))

        # Parse the header, find the column for the adjusted close.
        columns = lines[0].split(',')
        index_price = columns.index('Adj Close')
        assert index_price >= 0, "Could not find 'Adj Close' data column."
        index_date = columns.index('Date')
        assert index_date >= 0, "Could not find 'Date' data column."

        # Get the latest data returned.
        most_recent_data = lines[1].split(',')
        close_price = D(most_recent_data[index_price])
        date = datetime.datetime.strptime(most_recent_data[index_date],
                                          '%Y-%m-%d')

        return source.SourcePrice(close_price, date, None)
Ejemplo n.º 30
0
 def get_historical_price(self, ticker, time):
     date = time.strftime('%Y-%m-%d')
     resp = self.cached_request("FX_DAILY", ticker)
     walk_back = 0
     while date not in resp['Time Series FX (Daily)']:
         if walk_back > self.walk_back_days:
             return None
         time -= timedelta(1)
         walk_back += 1
         date = time.strftime('%Y-%m-%d')
     return source.SourcePrice(
         D(resp['Time Series FX (Daily)'][date]['4. close']),
         datetime.fromisoformat(date).replace(
             tzinfo=self.get_timezone(resp['Meta Data']['6. Time Zone'])),
         self.currency)