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)}
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, })