Example #1
0
def check(request, symbols=''):
    """ Fetch symbol information """
    convert = lambda x: dict(symbol=x.symbol, name=x.name, price=x.last_price)
    symbols = set([s.upper() for s in symbols.split(',')])

    # check streamer first (allow fast updates)
    data = map(lambda k: price_consumer.get_symbol(k), symbols)
    if None not in data:
        convert = lambda x: dict(symbol=x.symbol, name=x.name, price=x.price)
        return {'data': map(convert, data)}
    else:
        pass

    # fetch item records, detect new and expired items
    items = list(FinancialInstrument.objects.filter(symbol__in=symbols))
    items_insert, items_update, items_map = set(), set(), set()
    for item in items:
        if datetime.now() - item.last_update >= timedelta(minutes=1):
            items_update.add(item)
        items_map.add(item.symbol)
    for symbol in symbols:
        if symbol not in items_map:
            items_insert.add(FinancialInstrument(symbol=symbol))

    # load content from yahoo API
    items_query = items_update.union(items_insert)
    if items_query:
        yapi = YahooFinance()
        yapi.query_multiple([x.symbol for x in items_query])
        for item in items_query:
            info = yapi[item.symbol]
            item.last_price = info.price
            if not info.price:
                break
            if item.symbol in items_insert:
                item.name = info.name
                items.append(item)
            item.save()

    # return values
    if not items:
        return {'error': 'NO_SYMBOL'}
    return {'data': map(convert, items)}
Example #2
0
def monitor_add(request):
    """ Add symbol (via html or ajax) """
    # fetch form data
    data = request.POST
    symbol = data.get('s').upper()
    lower_bound = data.get('l') or None
    upper_bound = data.get('h') or None
    error = lambda msg: json_or_redirect(request, {'error': msg})

    # verify user subscription
    try:
        profile = UserProfile.objects.get(user=request.user)
        if not profile.count_watches:
            return error("Plan limit reached")
    except UserProfile.DoesNotExist:
        profile = None  # admin account

    # load content from yahoo API
    yapi = YahooFinance()
    info = yapi.query_single(symbol)

    try:
        # validate input
        if not info.price:
            return error("Symbol %s not found" % symbol)
        if lower_bound is not None:
            lower_bound = float(lower_bound)
            if lower_bound >= info.price:
                return error("Low alert must be below current price")
        if upper_bound is not None:
            upper_bound = float(upper_bound)
            if upper_bound <= info.price:
                return error("High alert must be above current price")
    except ValueError:
        # output error
        return error("Invalid value")

    # create database record (instrument)
    try:
        item = FinancialInstrument.objects.get(symbol=symbol)
    except FinancialInstrument.DoesNotExist:
        item = FinancialInstrument(symbol=symbol,
            name=info.name, last_price=info.price)
        item.save()

    try:
        # get next position
        qs = PriceWatch.objects.filter(user=request.user)
        pos = 1 + (qs.aggregate(Max('position'))['position__max'] or 0)

        # create database record (watch)
        watch = PriceWatch(user=request.user, instrument=item,
            lower_bound=lower_bound, upper_bound=upper_bound, position=pos)
        watch.set_alert_flags(profile)
        watch.save()
    except IntegrityError:
        # output error
        return error("Symbol exists")

    # notify streamer
    if not price_consumer.get_symbol(symbol):
        price_consumer.add_symbol(item.symbol)

    # output result or redirect
    return json_or_redirect(request, {
        'id': watch.id,
        'symbol': symbol,
        'lower_bound': lower_bound,
        'upper_bound': upper_bound,
        'price': info.price,
        'alert_email': watch.alert_email,
        'alert_phone': watch.alert_phone,
    })