Browse Source

Performance: added various stats

master
Denis Tereshkin 6 years ago
parent
commit
eb5f0b6755
  1. 23
      forms.py
  2. 44
      templates/dashboard/performance.html
  3. 71
      views.py

23
forms.py

@ -30,7 +30,7 @@ class TradeFilterForm(forms.Form):
def __init__(self, *args, show_unbalanced_checkbox=False, **kwargs): def __init__(self, *args, show_unbalanced_checkbox=False, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
now = datetime.date.today() now = datetime.date.today() + datetime.timedelta(days=1)
all_accounts, all_strategies = get_all_accounts_and_strategies() all_accounts, all_strategies = get_all_accounts_and_strategies()
self.fields['accounts'] = forms.MultipleChoiceField(choices=zip(sorted(list(all_accounts)), sorted(list(all_accounts))), required=False) self.fields['accounts'] = forms.MultipleChoiceField(choices=zip(sorted(list(all_accounts)), sorted(list(all_accounts))), required=False)
@ -42,3 +42,24 @@ class TradeFilterForm(forms.Form):
self.fields['unbalanced_only'] = forms.BooleanField(required=False) self.fields['unbalanced_only'] = forms.BooleanField(required=False)
except KeyError: except KeyError:
pass pass
# Can't subclass it from TradeFilterForm, field 'timestamp' will not show. Go figure.
class PerformanceFilterForm(forms.Form):
def __init__(self, *args, show_unbalanced_checkbox=False, **kwargs):
super().__init__(*args, **kwargs)
now = datetime.date.today() + datetime.timedelta(days=1)
all_accounts, all_strategies = get_all_accounts_and_strategies()
self.fields['accounts'] = forms.MultipleChoiceField(choices=zip(sorted(list(all_accounts)), sorted(list(all_accounts))), required=False)
self.fields['strategies'] = forms.MultipleChoiceField(choices=zip(sorted(list(all_strategies)), sorted(list(all_strategies))), required=False)
self.fields['startdate'] = forms.DateField(initial=(now - datetime.timedelta(weeks=4)))
self.fields['enddate'] = forms.DateField(initial=now)
try:
if show_unbalanced_checkbox:
self.fields['unbalanced_only'] = forms.BooleanField(required=False)
except KeyError:
pass
self.fields['timeframe'] = forms.ChoiceField(choices=[('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly')])

44
templates/dashboard/performance.html

@ -5,11 +5,27 @@
{% load humanize %} {% load humanize %}
{% block content %} {% block content %}
<div class="panel panel-default">
<div class="panel-header">
<a href="#trades_filter_form" role="button" data-toggle="collapse">Apply filter...</a>
</div>
<div class="panel-body panel-collapse collapse" id="trades_filter_form">
<form action="{% url 'performance' %}" method="GET">
{% csrf_token %}
{% bootstrap_form trades_filter_form %}
{% bootstrap_button button_type='submit' content='Submit' %}
</form>
</div>
</div>
<!--
<ul class="nav nav-pills"> <ul class="nav nav-pills">
<li role="presentation"{% if timeframe|length == 0 or timeframe == 'daily' %} class="active"{% endif %}><a href="{% url 'performance' %}?timeframe=daily">Daily</a></li> <li role="presentation"{% if timeframe|length == 0 or timeframe == 'daily' %} class="active"{% endif %}><a href="{% url 'performance' %}?timeframe=daily">Daily</a></li>
<li role="presentation"{% if timeframe == 'weekly' %} class="active"{% endif %}><a href="{% url 'performance' %}?timeframe=weekly">Weekly</a></li> <li role="presentation"{% if timeframe == 'weekly' %} class="active"{% endif %}><a href="{% url 'performance' %}?timeframe=weekly">Weekly</a></li>
<li role="presentation"{% if timeframe == 'monthly' %} class="active"{% endif %}><a href="{% url 'performance' %}?timeframe=monthly">Monthly</a></li> <li role="presentation"{% if timeframe == 'monthly' %} class="active"{% endif %}><a href="{% url 'performance' %}?timeframe=monthly">Monthly</a></li>
</ul> </ul>
-->
<script src="http://code.highcharts.com/highcharts.js"></script> <script src="http://code.highcharts.com/highcharts.js"></script>
<div id="profits-container" style="width:100%; height:400px;"> <div id="profits-container" style="width:100%; height:400px;">
</div> </div>
@ -37,6 +53,34 @@
</tr> </tr>
</table> </table>
<table class="table">
<tr>
<td>Parameter</td>
<td>Trade</td>
<td>Period</td>
</tr>
<tr>
<td>Mean</td>
<td> {{ results.stats.mean }} </td>
<td> {{ results.stats_period.mean }} </td>
</tr>
<tr>
<td>Std. dev.</td>
<td> {{ results.stats.stddev }} </td>
<td> {{ results.stats_period.stddev }} </td>
</tr>
<tr>
<td>Skew</td>
<td> {{ results.stats.skew }} </td>
<td> {{ results.stats_period.skew }} </td>
</tr>
<tr>
<td>Kurtosis</td>
<td> {{ results.stats.kurtosis }} </td>
<td> {{ results.stats_period.kurtosis }} </td>
</tr>
</table>
<script> <script>
$(function () { $(function () {
$('#profits-container').highcharts({ $('#profits-container').highcharts({

71
views.py

@ -11,12 +11,15 @@ from django.contrib.auth import authenticate, login, logout
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import RobotInstance, Trade, ClosedTrade from .models import RobotInstance, Trade, ClosedTrade
from .forms import NewTradeForm, TradeFilterForm, LoginForm from .forms import NewTradeForm, TradeFilterForm, PerformanceFilterForm, LoginForm
import redis import redis
import json import json
import datetime import datetime
import calendar import calendar
import numpy as np
import scipy.stats as stats
def login_view(request): def login_view(request):
if request.method == 'POST': if request.method == 'POST':
form = LoginForm(request.POST) form = LoginForm(request.POST)
@ -328,22 +331,45 @@ def rebalance_closed_trades(request):
@login_required @login_required
def performance(request): def performance(request):
aggregate_unbalanced_trades() aggregate_unbalanced_trades()
all_accounts = set()
for trade in ClosedTrade.objects.all():
if trade.account != 'demo':
all_accounts.add(trade.account)
closed_trades = ClosedTrade.objects.exclude(account='demo').order_by('exitTime')
trades = Trade.objects.exclude(account='demo').order_by('timestamp')
trades = Trade.objects.exclude(account='demo').order_by('timestamp') trades = Trade.objects.exclude(account='demo').order_by('timestamp')
form = PerformanceFilterForm(request.GET)
if form.is_valid():
d = form.cleaned_data
closed_trades = ClosedTrade.objects.all()
trades = Trade.objects.order_by('timestamp')
if len(d['strategies']) > 0:
closed_trades = closed_trades.filter(strategyId__in=list(d['strategies']))
trades = trades.filter(strategyId__in=list(d['strategies']))
if len(d['accounts']) > 0:
closed_trades = closed_trades.filter(account__in=list(d['accounts']))
trades = trades.filter(account__in=list(d['accounts']))
all_accounts = set(d['accounts'])
if d['startdate'] is not None:
closed_trades = closed_trades.filter(exitTime__gte=d['startdate'])
trades = trades.filter(timestamp__gte=d['startdate'])
if d['enddate'] is not None:
closed_trades = closed_trades.filter(exitTime__lte=d['enddate'])
trades = trades.filter(timestamp__lte=d['enddate'])
timeframe = d['timeframe']
else:
now = datetime.date.today()
closed_trades = ClosedTrade.objects.all().filter(exitTime__gte=(now - datetime.timedelta(weeks=4)))
trades = Trade.objects.order_by('timestamp').filter(timestamp__gte=(now - datetime.timedelta(weeks=4)))
form = PerformanceFilterForm()
timeframe = 'daily'
all_accounts = set()
for trade in ClosedTrade.objects.all():
all_accounts.add(trade.account)
dates = [] dates = []
columns = {} columns = {}
for account in all_accounts: for account in all_accounts:
columns[account] = [] columns[account] = []
timeframe = request.GET.get('timeframe')
if timeframe is None:
timeframe = 'daily'
if timeframe == 'daily': if timeframe == 'daily':
prev_day = None prev_day = None
for trade in closed_trades: for trade in closed_trades:
@ -396,15 +422,36 @@ def performance(request):
results['total']['loss'] -= trade.profit results['total']['loss'] -= trade.profit
results[trade.account]['loss'] -= trade.profit results[trade.account]['loss'] -= trade.profit
results['total']['pf'] = results['total']['profit'] / results['total']['loss'] if results['total']['loss'] > 0:
results['total']['pf'] = results['total']['profit'] / results['total']['loss']
else:
results['total']['pf'] = '+inf'
results['total']['commission'] = trades.aggregate(Sum('commission'))['commission__sum'] results['total']['commission'] = trades.aggregate(Sum('commission'))['commission__sum']
results['stats'] = {}
results['stats_period'] = {}
pnls = list(map(lambda x: float(x.profit), closed_trades))
results['stats']['mean'] = "{:.3f}".format(np.mean(pnls))
results['stats']['stddev'] = "{:.3f}".format(np.std(pnls))
results['stats']['skew'] = "{:.3f}".format(stats.skew(pnls))
results['stats']['kurtosis'] = "{:.3f}".format(stats.kurtosis(pnls))
all_columns = []
for v in columns.values():
all_columns += list(map(float, v))
results['stats_period']['mean'] = "{:.3f}".format(np.mean(all_columns))
results['stats_period']['stddev'] = "{:.3f}".format(np.std(all_columns))
results['stats_period']['skew'] = "{:.3f}".format(stats.skew(all_columns))
results['stats_period']['kurtosis'] = "{:.3f}".format(stats.kurtosis(all_columns))
template = loader.get_template('dashboard/performance.html') template = loader.get_template('dashboard/performance.html')
context = { context = {
'user' : request.user, 'user' : request.user,
'dates' : dates, 'dates' : dates,
'columns' : columns, 'columns' : columns,
'results' : results, 'results' : results,
'timeframe' : timeframe 'trades_filter_form' : form
} }
return HttpResponse(template.render(context, request)) return HttpResponse(template.render(context, request))

Loading…
Cancel
Save