def position_list(): search = request.args.get('search', '') sort = request.args.get('sort', 'total_increase') order = request.args.get('order', 'desc') user = current_user._id position = Position.user_position(user) if search: position = list(filter( lambda x: search in x['exchange'] or search in x['name'] or search in x['symbol'], position)) position = sorted(position, key=lambda x: x[sort] or 0, reverse=order == 'desc') for p in position: p['name'] = (p['name'] or '')[:5] p['increase'] = '{:.1f}%'.format((p['increase'] or 0) * 100) p['total_increase'] = '{:.1f}%'.format((p['total_increase'] or 0) * 100) p['unrealized_profit'] = '{:.1f}'.format(p['unrealized_profit'] or 0) p['avg_buy_price'] = '{:.2f}'.format(p['avg_buy_price']) if p['latest_price']: p['latest_price'] = '{:.2f}'.format(p['latest_price']) position = [p for p in position if p['quantity'] > 0] return jsonify(total=len(position), rows=position)
def position(): nav = 'position' today = (datetime.utcnow() + timedelta(hours=8)).strftime('%Y-%m-%d') user = current_user._id num_collections = Position.num_collections(user) average_increase = Position.average_increase(user) market_value = Position.market_value(user) realized_profit = Position.realized_profit(user) unrealized_profit = Position.unrealized_profit(user) annual_profit = Position.annual_profit(user) position = Position.user_position(user) # charts pfs = ProfitLog.profits(user) pldates = [pf['date'].strftime('%Y-%m-%d') for pf in pfs] plvalues = [int(pf['profit']) for pf in pfs] exchanges = [{'value': n, 'text': n} for n in sorted(ABBRS)] total_transactions = Transaction.user_total_transactions(user) transactions = Transaction.user_recent_transactions( user) for t in transactions: t.typecn = '买入' if t.type_ == 'buy' else '卖出' return render_template('user/position.html', **locals())
def accounting(user): """ 对账号进行自动记账(如果用户已配置) """ operated_at = datetime.utcnow() + timedelta(hours=8) def add_transaction(type_, exchange, symbol, price, quantity): t = Transaction({ 'user': user._id, 'type_': type_, 'operated_at': operated_at, 'exchange': exchange, 'symbol': symbol, 'price': price, 'quantity': quantity, }) t.save() if not Position.do_op(t): t.remove() if user.auto_accounting: op = Position.user_position(user._id) p2pairs = {} for ta in TradeAccount.query({'user': user._id}): for p in ta.position or []: pair = (ta.exchange, p.symbol) if pair not in p2pairs: p2pairs[pair] = p else: pp = p2pairs[pair] amount = p.average_price * p.quantity + \ pp.average_price * pp.quantity p.quantity += pp.quantity if p.quantity > 0: p.average_price = amount / p.quantity p2pairs[pair] = p p1pairs = {(p1['exchange'], p1['symbol']): p1 for p1 in op} # 检查更改项 for p1 in op: pair = p1['exchange'], p1['symbol'] if pair[0] in ['湖南文交所', '海西文交所', '上海邮币卡', '上海文交所', '中俄邮币卡']: continue if pair in p2pairs: p2 = p2pairs[pair] quantity = p2.quantity - p1['quantity'] if quantity != 0: type_ = 'buy' if quantity > 0 else 'sell' if type_ == 'buy': price = (p2.average_price * p2.quantity - p1['avg_buy_price'] * p1['quantity']) / quantity else: price = p2.price if price < 0.01: price = Quote.latest_price(p1['exchange'], p1['symbol']) price = int(price * 100) / 100. add_transaction( type_, pair[0], pair[1], price, abs(quantity)) else: # 按现价计算已卖出 if p1['quantity'] > 0: price = Quote.latest_price(p1['exchange'], p1['symbol']) price = int(price * 100) / 100. add_transaction( 'sell', pair[0], pair[1], price, p1['quantity']) # 检查新增项 for pair, p2 in p2pairs.items(): if pair[0] in ['湖南文交所', '海西文交所', '上海邮币卡', '上海文交所', '中俄邮币卡']: continue if pair not in p1pairs and p2.quantity > 0: price = int(p2.average_price * 100) / 100. add_transaction('buy', pair[0], pair[1], price, p2.quantity)
def trade_quote_realtime(): """ 实时数据/列表 """ # 全部 -> all # 指数 -> index # 持仓 -> position # 自选 -> diy category = request.args.get('category', '').strip() search = request.args.get('search', '').strip() sort = request.args.get('sort', '').strip() order = request.args.get('order', 'asc').strip() today = Quote.cached(3600).query_one({'quote_type': '1d'}, sort=[('quote_at', -1)]).quote_at cond = {'quote_type': '1d', 'quote_at': today} colls = set() symbols = [] if search: pairs = Collection.search(search) symbols = [p[1] for p in pairs] colls = set(pairs) cond['symbol'] = {'$in': symbols} elif category == 'all': pass elif category == 'index': cs = list(Collection.cached(3600).query({'name': {'$regex': '指数$'}})) colls = set((c.exchange, c.symbol) for c in cs) symbols = [c.symbol for c in cs] cond['symbol'] = {'$in': symbols} elif category == 'position': position = Position.user_position(current_user._id) colls = set((p['exchange'], p['symbol']) for p in position) symbols = [p['symbol'] for p in position] cond['symbol'] = {'$in': symbols} elif category == 'diy': raise NotImplementedError qs = [q for q in Quote.query(cond) if (not colls) or ((q.exchange, q.symbol) in colls)] qs = [{ 'open_': q.open_, 'high': q.high, 'low': q.low, 'close': q.close, 'lclose': q.lclose, 'volume': q.volume, 'amount': q.amount, 'increase': 0 if not q.lclose else q.close / q.lclose - 1, 'exchange': q.exchange, 'symbol': q.symbol, 'name': Collection.get_name(q.exchange, q.symbol), } for q in qs] # sort if sort: qs = sorted(qs, key=lambda x: x[sort], reverse=order == 'desc') # format for q in qs: if q['lclose']: q['lclose'] = '{:.2f}'.format(q['lclose']) q['open_'] = '{:.2f}'.format(q['open_']) q['high'] = '{:.2f}'.format(q['high']) q['low'] = '{:.2f}'.format(q['low']) q['close'] = '{:.2f}'.format(q['close']) q['amount'] = '{:.1f}万'.format(q['amount'] / 10000) q['increase'] = '{:.1f}%'.format(q['increase'] * 100) # add no result symbols exist_pairs = set((q['exchange'], q['symbol']) for q in qs) for exchange, symbol in (colls - exist_pairs): qs.append({ 'open_': '-', 'high': '-', 'low': '-', 'close': '-', 'lclose': '-', 'volume': '-', 'amount': '-', 'increase': '-', 'exchange': exchange, 'symbol': symbol, 'name': Collection.get_name(exchange, symbol), }) return jsonify(status=200, total=len(qs), rows=qs)
def accounting(user): """ 对账号进行自动记账(如果用户已配置) """ operated_at = datetime.utcnow() + timedelta(hours=8) def add_transaction(type_, exchange, symbol, price, quantity): t = Transaction({ 'user': user._id, 'type_': type_, 'operated_at': operated_at, 'exchange': exchange, 'symbol': symbol, 'price': price, 'quantity': quantity, }) t.save() if not Position.do_op(t): t.remove() if user.auto_accounting: op = Position.user_position(user._id) p2pairs = {} for ta in TradeAccount.query({'user': user._id}): for p in ta.position or []: pair = (ta.exchange, p.symbol) if pair not in p2pairs: p2pairs[pair] = p else: pp = p2pairs[pair] amount = p.average_price * p.quantity + \ pp.average_price * pp.quantity p.quantity += pp.quantity if p.quantity > 0: p.average_price = amount / p.quantity p2pairs[pair] = p p1pairs = {(p1['exchange'], p1['symbol']): p1 for p1 in op} # 检查更改项 for p1 in op: pair = p1['exchange'], p1['symbol'] if pair[0] in ['湖南文交所', '海西文交所', '上海邮币卡', '上海文交所', '中俄邮币卡']: continue if pair in p2pairs: p2 = p2pairs[pair] quantity = p2.quantity - p1['quantity'] if quantity != 0: type_ = 'buy' if quantity > 0 else 'sell' if type_ == 'buy': price = ( p2.average_price * p2.quantity - p1['avg_buy_price'] * p1['quantity']) / quantity else: price = p2.price if price < 0.01: price = Quote.latest_price(p1['exchange'], p1['symbol']) price = int(price * 100) / 100. add_transaction(type_, pair[0], pair[1], price, abs(quantity)) else: # 按现价计算已卖出 if p1['quantity'] > 0: price = Quote.latest_price(p1['exchange'], p1['symbol']) price = int(price * 100) / 100. add_transaction('sell', pair[0], pair[1], price, p1['quantity']) # 检查新增项 for pair, p2 in p2pairs.items(): if pair[0] in ['湖南文交所', '海西文交所', '上海邮币卡', '上海文交所', '中俄邮币卡']: continue if pair not in p1pairs and p2.quantity > 0: price = int(p2.average_price * 100) / 100. add_transaction('buy', pair[0], pair[1], price, p2.quantity)
def trade_quote_realtime(): """ 实时数据/列表 """ # 全部 -> all # 指数 -> index # 持仓 -> position # 自选 -> diy category = request.args.get('category', '').strip() search = request.args.get('search', '').strip() sort = request.args.get('sort', '').strip() order = request.args.get('order', 'asc').strip() today = Quote.cached(3600).query_one({ 'quote_type': '1d' }, sort=[('quote_at', -1)]).quote_at cond = {'quote_type': '1d', 'quote_at': today} colls = set() symbols = [] if search: pairs = Collection.search(search) symbols = [p[1] for p in pairs] colls = set(pairs) cond['symbol'] = {'$in': symbols} elif category == 'all': pass elif category == 'index': cs = list(Collection.cached(3600).query({'name': {'$regex': '指数$'}})) colls = set((c.exchange, c.symbol) for c in cs) symbols = [c.symbol for c in cs] cond['symbol'] = {'$in': symbols} elif category == 'position': position = Position.user_position(current_user._id) colls = set((p['exchange'], p['symbol']) for p in position) symbols = [p['symbol'] for p in position] cond['symbol'] = {'$in': symbols} elif category == 'diy': raise NotImplementedError qs = [ q for q in Quote.query(cond) if (not colls) or ((q.exchange, q.symbol) in colls) ] qs = [{ 'open_': q.open_, 'high': q.high, 'low': q.low, 'close': q.close, 'lclose': q.lclose, 'volume': q.volume, 'amount': q.amount, 'increase': 0 if not q.lclose else q.close / q.lclose - 1, 'exchange': q.exchange, 'symbol': q.symbol, 'name': Collection.get_name(q.exchange, q.symbol), } for q in qs] # sort if sort: qs = sorted(qs, key=lambda x: x[sort], reverse=order == 'desc') # format for q in qs: if q['lclose']: q['lclose'] = '{:.2f}'.format(q['lclose']) q['open_'] = '{:.2f}'.format(q['open_']) q['high'] = '{:.2f}'.format(q['high']) q['low'] = '{:.2f}'.format(q['low']) q['close'] = '{:.2f}'.format(q['close']) q['amount'] = '{:.1f}万'.format(q['amount'] / 10000) q['increase'] = '{:.1f}%'.format(q['increase'] * 100) # add no result symbols exist_pairs = set((q['exchange'], q['symbol']) for q in qs) for exchange, symbol in (colls - exist_pairs): qs.append({ 'open_': '-', 'high': '-', 'low': '-', 'close': '-', 'lclose': '-', 'volume': '-', 'amount': '-', 'increase': '-', 'exchange': exchange, 'symbol': symbol, 'name': Collection.get_name(exchange, symbol), }) return jsonify(status=200, total=len(qs), rows=qs)