def trade(request): try: # Check if user is a supervisor if request.user.groups.filter(name='supervisor').exists(): # Collect all viewable groups preview_groups = AuthorizedUser.objects.order_by( 'account').values_list('account', flat=True).distinct() # Collect the specific preview request (if available) preview_group = request.GET.get('preview-group') if preview_group: group = get_group(request) return render( request, 'trade/trade.html', { 'title': 'AI Trading - Trade - Preview Group', 'group': group, 'preview_groups': preview_groups }) # When first loading the page, no preview group has been selected yet else: return render( request, 'preview_landing.html', { 'title': 'AI Trading - Preview Group', 'preview_groups': preview_groups }) else: group = get_group(request) if isinstance(group, HttpResponseForbidden): return group if DEBUG != 'True': keen.add_event( 'visits', { 'group': group.get('group_account'), 'email': request.user.email }) return render(request, 'trade/trade.html', { 'title': 'AI Trading - Trade', 'group': group }) except AuthorizedUser.DoesNotExist: return render(request, 'unauthorized.html', {'title': 'AI Trading - Unauthorized'}, status=401)
def get_snapshots(request): group = get_group(request) if isinstance(group, HttpResponseForbidden): return group portfolio_snapshots = db_client.get_snapshots(group.get('group_account')) if portfolio_snapshots is None: return HttpResponseNotFound('No data available on server') return JsonResponse({'snapshots': portfolio_snapshots})
def get_portfolio(request): group = get_group(request) if isinstance(group, HttpResponseForbidden): return group portfolio = db_client.get_snapshots(group.get('group_account'), latest=True) if portfolio is None: return HttpResponseNotFound('No data available on server') return JsonResponse(portfolio)
def download_portfolio_all(request): group = get_group(request) if isinstance(group, HttpResponseForbidden): return group portfolio_snapshots = db_client.get_snapshots(group.get('group_account')) if portfolio_snapshots is None: return HttpResponseNotFound('No data available on server') rows = [] for snapshot in portfolio_snapshots: date = snapshot['as_of_date'].strftime("%Y-%m-%d") fx_rate = snapshot['fx_rate'] rows.append( {'as_of_date': date, 'sec_name': 'CAD Cash', 'asset_category': 'CASH & CASH EQUIVALENTS', 'sector_name': 'CASH', 'currency': 'CAD', 'fx_rate': 1.0, 'local_total': snapshot['CAD_cash'], 'base_total': snapshot['CAD_cash']}) rows.append( {'as_of_date': date, 'sec_name': 'USD Cash', 'asset_category': 'CASH & CASH EQUIVALENTS', 'sector_name': 'CASH', 'currency': 'USD', 'fx_rate': fx_rate, 'local_total': snapshot['USD_cash'], 'base_total': snapshot['USD_cash'] * fx_rate}) for security in snapshot['securities']: security_fx_rate = fx_rate if security['currency'] == 'USD' else 1.0 security.update( {'as_of_date': date, 'fx_rate': security_fx_rate, 'local_price': security['price'], 'local_total': security['total'], 'base_price': security['price'] * security_fx_rate, 'base_total': security['total'] * security_fx_rate}) rows.append(security) response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="%s_All_Portfolio_Details_as_of_%s.csv"' % ( group.get('group_account'), datetime.datetime.now().strftime('%Y-%m-%d')) headers = ['as_of_date', 'ticker', 'isin', 'sec_name', 'asset_category', 'sector_name', 'shares', 'currency', 'fx_rate', 'local_price', 'local_total', 'base_price', 'base_total'] writer = csv.DictWriter(response, headers, extrasaction='ignore') writer.writeheader() writer.writerows(rows) if DEBUG != 'True': keen.add_event('download_portfolio', {'group': group.get('group_account'), 'email': request.user.email}) return response
def download_transactions(request): try: group = get_group(request) if isinstance(group, HttpResponseForbidden): return group transaction_list = db_client.get_transactions( group.get('group_account')) if len(transaction_list) == 0: return HttpResponseNotFound('No transactions available') # Convert posted_date datetime objects to properly formatted strings for transaction in transaction_list: transaction["posted_date"] = transaction["posted_date"].strftime( '%Y-%m-%d') response = HttpResponse(content_type='text/csv') response[ 'Content-Disposition'] = 'attachment; filename="%s_Transactions_as_of_%s.csv"' % ( group.get('group_account'), datetime.datetime.now().strftime('%Y-%m-%d')) header = transaction_list[0].keys() # Get all column names writer = csv.DictWriter(response, header, extrasaction='ignore') writer.writeheader() writer.writerows(transaction_list) if DEBUG != 'True': keen.add_event('download_transactions', { 'group': group.get('group_account'), 'email': request.user.email }) return response except AuthorizedUser.DoesNotExist: return render(request, 'unauthorized.html', {'title': 'AI Trading - Unauthorized'}, status=401)
def submit_order(request): json_request = json.loads(request.body) trades = json_request.get('trades') cash = json_request.get('cash') reasoning = json_request.get('reasoning') notes = json_request.get('notes') if trades is None or cash is None: return HttpResponseBadRequest('Error: missing trade information') group = get_group(request) if isinstance(group, HttpResponseForbidden): return group if DEBUG != 'True': keen.add_events({ 'trades': trades, 'orders': [{ 'group': group.get('group_account'), 'email': request.user.email }] }) try: sender = '%s %s <%s>' % (request.user.first_name, request.user.last_name, request.user.email) other_members = group.get('members').exclude(email=request.user.email) other_members_emails = [ '%s %s <%s>' % (member.first_name, member.last_name, member.email) for member in other_members ] supervisors = [ '%s %s <%s>' % (supervisor.first_name, supervisor.last_name, supervisor.email) for supervisor in group.get('supervisors') ] trader_content = render_to_string( 'trade/email_template.html', { 'trades': trades, 'cash': cash, 'notes': notes, 'group_account': group.get('group_account'), 'group_number': group.get('group_number') }, request) supervisor_content = render_to_string( 'trade/email_template.html', { 'trades': trades, 'cash': cash, 'reasoning': reasoning, 'notes': notes, 'group_account': group.get('group_account'), 'group_number': group.get('group_number') }, request) from aitrading.templatetags.template_tags import remove_extra_0 trader_msg = EmailMessage( from_email=sender, to=supervisors, bcc=[sender], cc=other_members_emails, subject='Applied Investments Trade Request - Group %s (%s)' % (group.get('group_number'), remove_extra_0(group.get('group_account'))), body=str(trader_content)) trader_msg.content_subtype = 'html' trader_msg.send() supervisor_msg = EmailMessage( from_email=sender, to=supervisors, bcc=[sender], cc=other_members_emails, subject= 'Reasoning for Applied Investments Trade Request - Group %s (%s)' % (group.get('group_number'), remove_extra_0(group.get('group_account'))), body=str(supervisor_content)) supervisor_msg.content_subtype = 'html' supervisor_msg.send() return JsonResponse(data={}) except Exception as e: return HttpResponse('Error: ' + str(e), status=500)
def download_portfolio_timeseries(request): group = get_group(request) if isinstance(group, HttpResponseForbidden): return group account_snapshots = db_client.get_snapshots(group.get('group_account')) if account_snapshots is None: return HttpResponseNotFound('No data available on server') identifier = request.GET.get('identifier') headers = ['as_of_date', 'fx_rate', 'CAD_cash', 'USD_cash'] rows = [] for snapshot in account_snapshots: # Get fx_rate for conversion in base modes if 'base' in request.GET.get('value'): fx_rate = snapshot['fx_rate'] value = request.GET.get('value')[:-5] else: fx_rate = 1 value = request.GET.get('value') row = { 'as_of_date': snapshot['as_of_date'].strftime("%Y-%m-%d"), 'fx_rate': snapshot['fx_rate'], 'CAD_cash': snapshot['CAD_cash'], 'USD_cash': snapshot['USD_cash'] * fx_rate } for security in snapshot['securities']: # Cash corrections if security['sec_name'] == 'RECEIVABLE FOR INVESTMENTS SOLD ': row[security['currency'] + '_cash'] += security['total'] * fx_rate elif security['sec_name'] == 'PAYABLE FOR INVESTMENTS PURCHASED ': row[security['currency'] + '_cash'] -= security['total'] * fx_rate else: # Convert price or total (but not shares) to base for USD securities security_value = security[value] * fx_rate if security['currency'] == 'USD' and value != 'shares' else security[value] if security_value != 0: # Correction for extra spaces at the end of certain security names if security[identifier][-1:] == ' ': security[identifier] = security[identifier][:-1] # Need to include currency since there is a possibility of having USD and CAD security with same ticker security_id = security[identifier]+" ("+security['currency']+")" # Add to headers if doesn't exist already if security_id not in headers: headers.append(security_id) row[security_id] = security_value rows.append(row) response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="%s_Portfolio_Time_Series_as_of_%s.csv"' % ( group.get('group_account'), datetime.datetime.now().strftime('%Y-%m-%d')) writer = csv.DictWriter(response, headers, extrasaction='ignore') writer.writeheader() writer.writerows(rows) if DEBUG != 'True': keen.add_event('download_timeseries', {'group': group.get('group_account'), 'email': request.user.email, 'identifier': identifier, 'value': request.GET.get('value')}) return response