From b467466d7d25733f2198ad97fb53d3094bdfb390 Mon Sep 17 00:00:00 2001 From: Denis Tereshkin Date: Tue, 7 Mar 2017 21:09:34 +0700 Subject: [PATCH] Closed trades index --- static/images/down-arrow-2.png | Bin 0 -> 9743 bytes static/images/up-arrow-7.png | Bin 0 -> 10121 bytes templates/dashboard/base.html | 1 + templates/dashboard/closed_trades.html | 10 +++++ urls.py | 1 + views.py | 59 ++++++++++++++++++++++++- 6 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 static/images/down-arrow-2.png create mode 100644 static/images/up-arrow-7.png diff --git a/static/images/down-arrow-2.png b/static/images/down-arrow-2.png new file mode 100644 index 0000000000000000000000000000000000000000..33a16f27c93806c7551ce0cd6a1e1e898fe468fd GIT binary patch literal 9743 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
D2B)QWEoF{A0%nt%7#SGP&EMak#SZ&8*8yKNPy zw4akRs0ji?UaUjCD0PX{7tj-vCOC^Limi-UwAf6_w5tG4>M{603xaRjesjt6Mb(2f`H;VHf}J{{OvbuG8`?N59=Tm)0fEjOOGSX$XiFKz>X*&0MdyoXr-A;HLG5zhIeX9Y%Y})KXdZF6D<5rQe;PtF$ca2-)T~Y;Y2QDNW$Hn8Yf{ z{FApj@=CFr((CFYz)U~F_~W1X+q&28$ePN%>GMI&)UmJUebqH`v;)6Ndi%{AOcT2ZwxS)( zE-DB4pE&(_LHz2OPPRR3c4tLU81=&98z0-PsFOPI3lNKdIJTc}Xkg^2Z&iQ{jr;~c z7QD}KDLhZ9lHS8F0}E0t{FpCZKa}uv;H}?Lg_qtBUc8RdG6_bMuIG{T{pD_N`MD}B;irl6@GkOKT;)P$ePXkI_J`$}CUCgs zSto1^MlQs8i9EfO;7#g!g^BKd{ZY9EV>QDGqzHak)~`_N$huzA68G@8_<}oa*Ae-t zXv4Ho>6c3I*xOsIk}NzQ)Z|cYtp-LXph|8tu_1|$ESp5c_Z|KVy+6Ibvj1?i0@RCe zqIbf}O+(z*KiTigA}zv?Kc14|TZ%uWjlT13iB2$2G+m6a)M-2s^6VU4wtz`+0q|$b M#%&vl)_eT+U%N=if&c&j literal 0 HcmV?d00001 diff --git a/templates/dashboard/base.html b/templates/dashboard/base.html index 6418644..c044548 100644 --- a/templates/dashboard/base.html +++ b/templates/dashboard/base.html @@ -17,6 +17,7 @@ diff --git a/templates/dashboard/closed_trades.html b/templates/dashboard/closed_trades.html index 3a839dd..4d91306 100644 --- a/templates/dashboard/closed_trades.html +++ b/templates/dashboard/closed_trades.html @@ -1,4 +1,5 @@ {% extends "dashboard/base.html" %} +{% load static %} {% load bootstrap3 %} {% load mathfilters %} @@ -14,6 +15,15 @@ Strategy ID {% for closed_trade in closed_trades %} + + {% if closed_trade.direction == "long" %} {% else %} {% endif %} + {{ closed_trade.account }} + {{ closed_trade.security }} + {{ closed_trade.entryTime }} + {{ closed_trade.exitTime }} + {{ closed_trade.profit }} {{ closed_trade.profitCurrency}} + {{ closed_trade.strategyId }} + {% endfor %} {% endblock %} diff --git a/urls.py b/urls.py index 858005e..e9b8610 100644 --- a/urls.py +++ b/urls.py @@ -10,4 +10,5 @@ urlpatterns = [ url(r'^trades/$', views.trades_index, name='trades_index'), url(r'^add_trade/$', views.add_trade, name='add_trade'), url(r'^delete_trade/(?P[^/]+)$', views.delete_trade, name='delete_trade'), + url(r'^closed_trades/$', views.closed_trades_index, name='closed_trades_index'), ] diff --git a/views.py b/views.py index 0306ead..a76b5c4 100644 --- a/views.py +++ b/views.py @@ -4,8 +4,9 @@ from django.template import loader from django.shortcuts import render, get_object_or_404 from django.urls import reverse from django.contrib import messages +from django.db import transaction -from .models import RobotInstance, Trade +from .models import RobotInstance, Trade, ClosedTrade from .forms import NewTradeForm import redis import json @@ -109,3 +110,59 @@ def add_trade(request): return HttpResponse(template.render(context, request)) raise Http404("Invalid method") +@transaction.atomic +def aggregate_unbalanced_trades(): + unbalanced_trades = Trade.objects.filter(balanced=False).order_by('timestamp') + balanced_trades = [] + balances = {} + for trade in unbalanced_trades: + balance_key = '/'.join([trade.account, trade.security, trade.strategyId]) + try: + balance_entry = balances[balance_key] + except KeyError: + balance_entry = { 'balance' : 0} + + print('ts:', trade.timestamp) + if balance_entry['balance'] == 0: + print('new entry: ', balance_key) + balance_entry['balance'] = trade.quantity + direction = '' + if trade.quantity > 0: + direction='long' + else: + direction='short' + balance_entry['trade'] = ClosedTrade(account=trade.account, security=trade.security, entryTime=trade.timestamp, profitCurrency=trade.volumeCurrency, + profit=(-trade.price * trade.quantity), strategyId=trade.strategyId, direction=direction) + balance_entry['ks'] = trade.volume / (trade.price * abs(trade.quantity)) + balance_entry['trade_ids'] = [trade.pk] + else: + print('update entry: ', balance_key) + balance_entry['balance'] += trade.quantity + balance_entry['trade'].profit += -trade.price * trade.quantity + balance_entry['ks'] += trade.volume / (trade.price * abs(trade.quantity)) + balance_entry['ks'] /= 2 + balance_entry['trade_ids'].append(trade.pk) + + print('updated: ', balance_entry['balance']) + if balance_entry['balance'] == 0: + balance_entry['trade'].profit *= balance_entry['ks'] + balance_entry['trade'].exitTime = trade.timestamp + balanced_trades.append((balance_entry['trade'], balance_entry['trade_ids'])) + balances[balance_key] = balance_entry + + for trade, trade_ids in balanced_trades: + trade.save() + for trade_id in trade_ids: + tr = Trade.objects.get(pk=trade_id) + tr.balanced = True + tr.save() + + +def closed_trades_index(request): + aggregate_unbalanced_trades() + closed_trades = ClosedTrade.objects.all() + template = loader.get_template('dashboard/closed_trades.html') + context = { + 'closed_trades' : closed_trades + } + return HttpResponse(template.render(context, request))