Beispiel #1
0
def _parse_query(query):

    coin, interval_string = _split_query(query)

    coin = coin.upper()
    coin2 = None
    if '/' in coin:
        coin, coin2 = coin.split('/', 1)

    if coins_names.coin_name(coin) == '' and currencies_names.currency_name(coin) == '':
        raise SyntaxError("Invalid coin/currency name: %s" % coin)

    if coin2 and coins_names.coin_name(coin2) == '' and currencies_names.currency_name(coin2) == '':
        raise SyntaxError("Invalid coin/currency name: %s" % coin2)

    try:
        time_begin, time_end = interval.parse_interval(interval_string)
    except OverflowError:
        # to be fixed: ranges like yesterday, today, now and so on
        raise RuntimeError("Wrong range specification: %s" % interval_string)

    if time_begin is None or time_end is None:
        raise SyntaxError("Invalid time interval specification: %s" % interval_string)

    return coin, coin2, time_begin, time_end
Beispiel #2
0
def _parse_query(query):

    coin, interval_string = _split_query(query)

    coin = coin.upper()
    coin2 = None
    if '/' in coin:
        coin, coin2 = coin.split('/', 1)

    if coins_names.coin_name(coin) == '' and currencies_names.currency_name(
            coin) == '':
        raise SyntaxError("Invalid coin/currency name: %s" % coin)

    if coin2 and coins_names.coin_name(
            coin2) == '' and currencies_names.currency_name(coin2) == '':
        raise SyntaxError("Invalid coin/currency name: %s" % coin2)

    try:
        time_begin, time_end = interval.parse_interval(interval_string)
    except OverflowError:
        # to be fixed: ranges like yesterday, today, now and so on
        raise RuntimeError("Wrong range specification: %s" % interval_string)

    if time_begin is None or time_end is None:
        raise SyntaxError("Invalid time interval specification: %s" %
                          interval_string)

    return coin, coin2, time_begin, time_end
Beispiel #3
0
    def _make_header(self):
        coin_symbol = self.data['meta']['symbol']
        coin_name = coins_names.coin_name(coin_symbol)

        meta = self.data['meta']
        interval_name = interval.from_secs(self.interval)
        time_interval = "%s +%s" % (self._format_time(
            meta['time_begin']), interval_name)
        #self._format_time(meta['time_end'], show_date=True, show_time=True),

        output = "\n"
        if self.currency == 'USD':
            output += u"{-1▶ %s (%s) }{1▶}" % (coin_name, coin_symbol)
        else:
            currency_symbol = self.currency
            currency_name = currencies_names.currency_name(self.currency)
            if not currency_name:
                currency_name = coins_names.coin_name(self.currency)

            output += u"{-1▶ %s (%s) to %s (%s) }{1▶}" % \
                      (coin_name, coin_symbol, currency_name, currency_symbol)
        #output += u"{1%s (%s)}," % (coin_name, coin_symbol)
        output += " %s" % (time_interval)
        output += " %s\n" % self._show_change_percentage()[1]
        output += "\n\n"

        return output
Beispiel #4
0
    def _make_header(self):
        coin_symbol = self.data['meta']['symbol']
        coin_name = coins_names.coin_name(coin_symbol)

        meta = self.data['meta']
        interval_name = interval.from_secs(self.interval)
        time_interval = "%s +%s" % (
            self._format_time(meta['time_begin']),
            interval_name)
            #self._format_time(meta['time_end'], show_date=True, show_time=True),

        output = "\n"
        if self.currency == 'USD':
            output += u"{-1▶ %s (%s) }{1▶}" % (coin_name, coin_symbol)
        else:
            currency_symbol = self.currency
            currency_name = currencies_names.currency_name(self.currency)
            if not currency_name:
                currency_name = coins_names.coin_name(self.currency)

            output += u"{-1▶ %s (%s) to %s (%s) }{1▶}" % \
                      (coin_name, coin_symbol, currency_name, currency_symbol)
        #output += u"{1%s (%s)}," % (coin_name, coin_symbol)
        output += " %s" % (time_interval)
        output += " %s\n" % self._show_change_percentage()[1]
        output += "\n\n"

        return output
Beispiel #5
0
def view(query, use_currency=None):
    """
    Main rendering function, entry point for this module.
    Returns rendered view for the ``query``.
    If currency is specified in ``query``, it overrides ``currency``.
    If ``currency`` is not specified, USD is used.
    """

    try:
        coin, coin2, time_begin, time_end = _parse_query(query)
    except SyntaxError as e_msg:
        raise RuntimeError("%s" % e_msg)

    # if currency is specified in the domain name (use_currency)
    # but not in the query, then we use it as the output currency
    if use_currency \
        and not coin2 \
        and (coins_names.coin_name(use_currency) != '' \
            or currencies_names.currency_name(use_currency) != ''):
        coin2 = use_currency

    print(coin2)
    ticks = 80
    if coin2:
        data = aggregate.get_aggregated_pair(coin, coin2, time_begin, time_end,
                                             ticks)
    else:
        data = aggregate.get_aggregated_coin(coin, time_begin, time_end, ticks)

    if data['ticks'] == []:
        raise RuntimeError("No data found for your query. Wrong range?")

    #import json
    #print json.dumps(data['meta'], indent=True)

    warnings = []
    if data['meta']['time_begin'] - time_begin > 3600 * 24:
        warnings.append(
            "for the moment, rate.sx has historical data only starting from 2018-Jan-07"
        )

    options = dict(
        width=80,
        height=25,
        msg_interval='@' not in query,
        currency=coin2 or 'USD',
        warnings=warnings,
    )
    dia = Diagram(data, (time_begin, time_end), options=options)
    return dia.make_view()
Beispiel #6
0
def view(query, use_currency=None):
    """
    Main rendering function, entry point for this module.
    Returns rendered view for the ``query``.
    If currency is specified in ``query``, it overrides ``currency``.
    If ``currency`` is not specified, USD is used.
    """

    try:
        coin, coin2, time_begin, time_end = _parse_query(query)
    except SyntaxError as e_msg:
        raise RuntimeError("%s" % e_msg)

    # if currency is specified in the domain name (use_currency)
    # but not in the query, then we use it as the output currency
    if use_currency \
        and not coin2 \
        and (coins_names.coin_name(use_currency) != '' \
            or currencies_names.currency_name(use_currency) != ''):
        coin2 = use_currency

    print coin2
    ticks = 80
    if coin2:
        data = aggregate.get_aggregated_pair(coin, coin2, time_begin, time_end, ticks)
    else:
        data = aggregate.get_aggregated_coin(coin, time_begin, time_end, ticks)

    if data['ticks'] == []:
        raise RuntimeError("No data found for your query. Wrong range?")

    #import json
    #print json.dumps(data['meta'], indent=True)

    warnings = []
    if data['meta']['time_begin'] - time_begin > 3600*24:
        warnings.append(
            "for the moment, rate.sx has historical data only starting from 2018-Jan-07")

    options = dict(
        width=80,
        height=25,
        msg_interval='@' not in query,
        currency=coin2 or 'USD',
        warnings=warnings,
    )
    dia = Diagram(data, (time_begin, time_end), options=options)
    return dia.make_view()
Beispiel #7
0
def get_data(query, use_currency=None):

    try:
        coin, coin2, time_begin, time_end = _parse_query(query)
    except SyntaxError as e_msg:
        raise RuntimeError("%s" % e_msg)

    # if currency is specified in the domain name (use_currency)
    # but not in the query, then we use it as the output currency
    if use_currency \
        and not coin2 \
        and (coins_names.coin_name(use_currency) != '' \
            or currencies_names.currency_name(use_currency) != ''):
        coin2 = use_currency

    ticks = 80
    if coin2:
        data = aggregate.get_aggregated_pair(coin, coin2, time_begin, time_end,
                                             ticks)
    else:
        data = aggregate.get_aggregated_coin(coin, time_begin, time_end, ticks)

    return data
Beispiel #8
0
def get_aggregated_pair(coin1,
                        coin2,
                        time_start,
                        time_end,
                        number_of_ticks,
                        key=None):  # pylint: disable=too-many-locals,too-many-arguments,too-many-branches,too-many-statements
    """
    Aggregate coin pairs (or coin and currency pairs).
    It works this way: find data for ``coin1`` and find data for ``coin2``,
    after that divide ``coin1`` data by ``coin2`` pairwise.
    This method is approximate for aggregated values.
    ``coin2`` can be a currency.
    """

    coin2_is_currency = bool(currency_name(coin2))
    desired_interval = (time_end - time_start) / number_of_ticks

    chosen_interval = None
    for interval_name, interval_size in sorted(INTERVAL.items(),
                                               key=lambda x: -x[1]):
        if interval_size < desired_interval:
            chosen_interval = interval_name

    # if interval is so small, we need to use the raw and not the aggregated data
    collection_name = None
    if chosen_interval:
        collection_name = 'coins_%s' % chosen_interval

    if key is None:
        key = "price_usd"

    entries1 = MONGO_READER.get_raw_data(coin1,
                                         time_start,
                                         time_end,
                                         collection_name=collection_name)
    if entries1 == []:
        return {'meta': {}, 'ticks': []}

    # depeding on (1) that we have a currency in coin2 or not
    # and (2) if data is aggregated, we have to read entries2 from different collections
    # and in one case postprocess them
    if coin2_is_currency:
        if collection_name is None:
            currencies_collection = 'currencies'
        else:
            currencies_collection = collection_name.replace(
                'coins_', 'currencies_')

        fields = {'timestamp': 1, coin2: 1}
        entries2 = MONGO_READER.get_raw_data(
            None,
            time_start,
            time_end,
            collection_name=currencies_collection,
            fields=fields)

        new_entries2 = []
        for entry in entries2:
            entry.update({key: entry[coin2]})
            new_entries2.append(entry)
        entries2 = new_entries2

    else:
        entries2 = MONGO_READER.get_raw_data(coin2,
                                             time_start,
                                             time_end,
                                             collection_name=collection_name)

    meta = {}
    ticks = []
    sum_ = 0

    if collection_name is None:
        # not aggregated data
        meta = {
            'symbol': entries1[0]['symbol'],
            'begin': entries1[0][key] / entries2[0][key],
            'end': entries1[-1][key] / entries2[-1][key],
            'time_begin': entries1[0]['timestamp'],
            'time_end': entries1[-1]['timestamp'],
            'min': entries1[0][key] / entries2[0][key],
            'max': entries1[0][key] / entries2[0][key],
            'time_min': entries1[0]['timestamp'],
            'time_max': entries1[0]['timestamp'],
        }

        for entry1, entry2 in zip(entries1, entries2):
            this_value = entry1[key] / entry2[key]
            ticks.append(this_value)
            sum_ += this_value

            if this_value > meta['max']:
                meta['max'] = this_value
                meta['time_max'] = entry1['timestamp']

            if this_value < meta['min']:
                meta['min'] = this_value
                meta['time_min'] = entry1['timestamp']
    else:
        # aggregated data

        # this parameter should be taken to the ticks
        take_this = 'avg'

        meta = {
            'symbol': entries1[0]['symbol'],
            'begin': entries1[0][key]['begin'] / entries2[0][key]['begin'],
            'end': entries1[-1][key]['end'] / entries2[-1][key]['end'],
            'time_begin': entries1[0]['timestamp'],
            'time_end': entries1[-1]['time_end'],
            'min': entries1[0][key]['min'] / entries2[0][key]['max'],
            'max': entries1[0][key]['max'] / entries2[0][key]['min'],
            'time_min': entries1[0][key]['time_min'],
            'time_max': entries1[0][key]['time_max'],
        }

        for entry1, entry2 in zip(entries1, entries2):
            this_value = entry1[key][take_this] / entry2[key][take_this]
            ticks.append(this_value)
            sum_ += this_value

            if this_value > meta['max']:
                meta['max'] = this_value
                meta['time_max'] = entry1[key]['time_max']

            if this_value < meta['min']:
                meta['min'] = this_value
                meta['time_min'] = entry1[key]['time_min']

    meta['avg'] = sum_ / len(ticks)

    return {
        'ticks': ticks,
        'meta': meta,
    }
Beispiel #9
0
def get_aggregated_pair(coin1, coin2, time_start, time_end, number_of_ticks, key=None): # pylint: disable=too-many-locals,too-many-arguments,too-many-branches,too-many-statements
    """
    Aggregate coin pairs (or coin and currency pairs).
    It works this way: find data for ``coin1`` and find data for ``coin2``,
    after that divide ``coin1`` data by ``coin2`` pairwise.
    This method is approximate for aggregated values.
    ``coin2`` can be a currency.
    """

    coin2_is_currency = bool(currency_name(coin2))
    desired_interval = (time_end-time_start)/number_of_ticks

    chosen_interval = None
    for interval_name, interval_size in sorted(INTERVAL.items(), key=lambda x: -x[1]):
        if interval_size < desired_interval:
            chosen_interval = interval_name

    # if interval is so small, we need to use the raw and not the aggregated data
    collection_name = None
    if chosen_interval:
        collection_name = 'coins_%s' % chosen_interval

    if key is None:
        key = "price_usd"

    entries1 = MONGO_READER.get_raw_data(
        coin1, time_start, time_end, collection_name=collection_name)
    if entries1 == []:
        return {'meta':{}, 'ticks':[]}

    # depeding on (1) that we have a currency in coin2 or not
    # and (2) if data is aggregated, we have to read entries2 from different collections
    # and in one case postprocess them
    if coin2_is_currency:
        if collection_name is None:
            currencies_collection = 'currencies'
        else:
            currencies_collection = collection_name.replace('coins_', 'currencies_')

        fields = {'timestamp': 1, coin2: 1}
        entries2 = MONGO_READER.get_raw_data(
            None, time_start, time_end,
            collection_name=currencies_collection,
            fields=fields)

        new_entries2 = []
        for entry in entries2:
            entry.update({key: entry[coin2]})
            new_entries2.append(entry)
        entries2 = new_entries2

    else:
        entries2 = MONGO_READER.get_raw_data(
            coin2, time_start, time_end, collection_name=collection_name)

    meta = {}
    ticks = []
    sum_ = 0

    if collection_name is None:
        # not aggregated data
        meta = {
            'symbol': entries1[0]['symbol'],
            'begin': entries1[0][key]/entries2[0][key],
            'end': entries1[-1][key]/entries2[-1][key],
            'time_begin': entries1[0]['timestamp'],
            'time_end': entries1[-1]['timestamp'],

            'min': entries1[0][key]/entries2[0][key],
            'max': entries1[0][key]/entries2[0][key],
            'time_min': entries1[0]['timestamp'],
            'time_max': entries1[0]['timestamp'],
            }

        for entry1, entry2 in zip(entries1, entries2):
            this_value = entry1[key]/entry2[key]
            ticks.append(this_value)
            sum_ += this_value

            if this_value > meta['max']:
                meta['max'] = this_value
                meta['time_max'] = entry1['timestamp']

            if this_value < meta['min']:
                meta['min'] = this_value
                meta['time_min'] = entry1['timestamp']
    else:
        # aggregated data

        # this parameter should be taken to the ticks
        take_this = 'avg'

        meta = {
            'symbol': entries1[0]['symbol'],
            'begin': entries1[0][key]['begin']/entries2[0][key]['begin'],
            'end': entries1[-1][key]['end']/entries2[-1][key]['end'],
            'time_begin': entries1[0]['timestamp'],
            'time_end': entries1[-1]['time_end'],

            'min': entries1[0][key]['min']/entries2[0][key]['max'],
            'max': entries1[0][key]['max']/entries2[0][key]['min'],
            'time_min': entries1[0][key]['time_min'],
            'time_max': entries1[0][key]['time_max'],
            }

        for entry1, entry2 in zip(entries1, entries2):
            this_value = entry1[key][take_this]/entry2[key][take_this]
            ticks.append(this_value)
            sum_ += this_value

            if this_value > meta['max']:
                meta['max'] = this_value
                meta['time_max'] = entry1[key]['time_max']

            if this_value < meta['min']:
                meta['min'] = this_value
                meta['time_min'] = entry1[key]['time_min']

    meta['avg'] = sum_/len(ticks)

    return {
        'ticks': ticks,
        'meta': meta,
    }