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. 67
      views.py

23
forms.py

@ -30,7 +30,7 @@ class TradeFilterForm(forms.Form): @@ -30,7 +30,7 @@ class TradeFilterForm(forms.Form):
def __init__(self, *args, show_unbalanced_checkbox=False, **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()
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): @@ -42,3 +42,24 @@ class TradeFilterForm(forms.Form):
self.fields['unbalanced_only'] = forms.BooleanField(required=False)
except KeyError:
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 @@ @@ -5,11 +5,27 @@
{% load humanize %}
{% 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">
<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 == 'monthly' %} class="active"{% endif %}><a href="{% url 'performance' %}?timeframe=monthly">Monthly</a></li>
</ul>
-->
<script src="http://code.highcharts.com/highcharts.js"></script>
<div id="profits-container" style="width:100%; height:400px;">
</div>
@ -37,6 +53,34 @@ @@ -37,6 +53,34 @@
</tr>
</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>
$(function () {
$('#profits-container').highcharts({

67
views.py

@ -11,12 +11,15 @@ from django.contrib.auth import authenticate, login, logout @@ -11,12 +11,15 @@ from django.contrib.auth import authenticate, login, logout
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import RobotInstance, Trade, ClosedTrade
from .forms import NewTradeForm, TradeFilterForm, LoginForm
from .forms import NewTradeForm, TradeFilterForm, PerformanceFilterForm, LoginForm
import redis
import json
import datetime
import calendar
import numpy as np
import scipy.stats as stats
def login_view(request):
if request.method == 'POST':
form = LoginForm(request.POST)
@ -328,22 +331,45 @@ def rebalance_closed_trades(request): @@ -328,22 +331,45 @@ def rebalance_closed_trades(request):
@login_required
def performance(request):
aggregate_unbalanced_trades()
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():
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')
dates = []
columns = {}
for account in all_accounts:
columns[account] = []
timeframe = request.GET.get('timeframe')
if timeframe is None:
timeframe = 'daily'
if timeframe == 'daily':
prev_day = None
for trade in closed_trades:
@ -396,15 +422,36 @@ def performance(request): @@ -396,15 +422,36 @@ def performance(request):
results['total']['loss'] -= trade.profit
results[trade.account]['loss'] -= trade.profit
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['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')
context = {
'user' : request.user,
'dates' : dates,
'columns' : columns,
'results' : results,
'timeframe' : timeframe
'trades_filter_form' : form
}
return HttpResponse(template.render(context, request))

Loading…
Cancel
Save