display graphs for exchange rates

This commit is contained in:
2021-01-24 21:56:14 +01:00
parent d0f3c18eec
commit 6cfffd99c5
8 changed files with 215 additions and 1 deletions
+29
View File
@@ -0,0 +1,29 @@
/* https://github.com/nathancahill/skeleton-tabs */
ul.tab-nav {
list-style: none;
border-bottom: 1px solid #bbb;
padding-left: 5px;
}
ul.tab-nav li {
display: inline;
}
ul.tab-nav li a.button {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
margin-bottom: -1px;
border-bottom: none;
}
ul.tab-nav li a.active.button {
border-bottom: 0.175em solid #fff;
}
.tab-content .tab-pane {
display: none;
}
.tab-content .tab-pane.active {
display: block;
}
+22
View File
@@ -0,0 +1,22 @@
/* https://github.com/nathancahill/skeleton-tabs */
(function() {
function main() {
var tabButtons = [].slice.call(document.querySelectorAll('ul.tab-nav li a.button'));
tabButtons.map(function(button) {
button.addEventListener('click', function() {
document.querySelector('li a.active.button').classList.remove('active');
button.classList.add('active');
document.querySelector('.tab-pane.active').classList.remove('active');
document.querySelector(button.getAttribute('href')).classList.add('active');
})
})
}
if (document.readyState !== 'loading') {
main();
} else {
document.addEventListener('DOMContentLoaded', main);
}
})();
+2
View File
@@ -8,6 +8,8 @@
<link rel="stylesheet" href="{% static 'css/style.css' %}"> <link rel="stylesheet" href="{% static 'css/style.css' %}">
<link rel="stylesheet" href="{% static 'css/topnav.css' %}"> <link rel="stylesheet" href="{% static 'css/topnav.css' %}">
<link rel="stylesheet" href="{% static 'css/accordion.css' %}"> <link rel="stylesheet" href="{% static 'css/accordion.css' %}">
<link rel="stylesheet" href="{% static 'css/skeleton-tabs.css' %}">
<script src="{% static 'js/skeleton-tabs.js' %}"></script>
</head> </head>
<body> <body>
{% if user.is_authenticated %} {% if user.is_authenticated %}
+96
View File
@@ -0,0 +1,96 @@
from django.db import connection
import datetime
import matplotlib.pyplot as plt
from io import StringIO
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.figure import Figure
import matplotlib.ticker as plticker
from django.http import HttpResponse
class Graph:
def graph_days(self, Crypto, Fiat, DayDiff):
x = []
y = []
with connection.cursor() as cursor:
sql = """SELECT date(datetime_valid), rate FROM
(select date(datetime_valid) as day, max(datetime_valid) as last
from exchangerate WHERE crypto_currency = %s AND fiat_currency = %s
AND datetime_valid >= %s
GROUP BY day
ORDER BY datetime_valid DESC) AS a
JOIN exchangerate AS b ON a.last = b.datetime_valid
AND crypto_currency = %s AND fiat_currency = %s
ORDER BY datetime_valid ASC"""
startDate = datetime.datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) - datetime.timedelta(days=int(DayDiff))
cursor.execute(sql, [Crypto, Fiat, startDate, Crypto, Fiat])
rows = cursor.fetchall()
for row in rows:
x.append(datetime.datetime.strptime(row[0], '%Y-%m-%d'))
y.append(row[1])
if len(x) == 0:
raise Exception("no data for this time range in the database")
fig_size = plt.rcParams["figure.figsize"]
fig_size[0] = 5
fig_size[1] = 4
plt.rcParams["figure.figsize"] = fig_size
fig = Figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, y, color='green', linestyle='dashed', linewidth = 2,
marker='o', markerfacecolor='blue', markersize=2)
loc = plticker.MultipleLocator(base=(len(x)/4.0))
ax.xaxis.set_major_locator(loc)
ax.set_xlabel("time")
ax.set_ylabel(Fiat)
ax.set_title(('%s in %s' % (Crypto, Fiat)))
response = HttpResponse(content_type = 'image/png')
canvas = FigureCanvasAgg(fig)
canvas.print_png(response)
return response
def graph_hours(self, Crypto, Fiat, HourDiff):
x = []
y = []
with connection.cursor() as cursor:
sql = """SELECT datetime_valid, rate FROM exchangerate
WHERE crypto_currency = %s AND fiat_currency = %s
AND datetime_valid >= %s
ORDER BY datetime_valid ASC"""
startDate = datetime.datetime.today() - datetime.timedelta(hours=int(HourDiff))
cursor.execute(sql, [Crypto, Fiat, startDate])
rows = cursor.fetchall()
for row in rows:
x.append(row[0])
y.append(row[1])
if len(x) == 0:
raise Exception("no data for this time range in the database")
fig = Figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, y, color='green', linestyle='dashed', linewidth = 2,
marker='o', markerfacecolor='blue', markersize=2)
loc = plticker.MultipleLocator(base=(len(x)/5.0))
ax.xaxis.set_major_locator(loc)
ax.set_xlabel("time")
ax.set_ylabel(Fiat)
ax.set_title(('%s in %s' % (Crypto, Fiat)))
response = HttpResponse(content_type = 'image/png')
canvas = FigureCanvasAgg(fig)
canvas.print_png(response)
return response
+49 -1
View File
@@ -3,6 +3,7 @@
{% block content %} {% block content %}
<div class="form-box"> <div class="form-box">
<h2>Monitor</h2> <h2>Monitor</h2>
<a href="/monitor" class="button button-primary">Refresh</a><br/>
<p>Hint: these numbers are not very accurate.</p> <p>Hint: these numbers are not very accurate.</p>
{% for c in cryptos %} {% for c in cryptos %}
@@ -29,6 +30,7 @@
{% if c.bought_tax_free %} {% if c.bought_tax_free %}
We can sell without paying taxes: {{ c.bought_tax_free|floatformat:3 }} {{ c.crypto }} for {{ c.value_tax_free|floatformat:2 }} EUR<br/> We can sell without paying taxes: {{ c.bought_tax_free|floatformat:3 }} {{ c.crypto }} for {{ c.value_tax_free|floatformat:2 }} EUR<br/>
{% endif %} {% endif %}
<br/><a href="/transactions/show?crypto={{ c.crypto }}">My transactions</a><br/>
{% if c.rates %} {% if c.rates %}
<table> <table>
@@ -44,9 +46,55 @@
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
<ul class="tab-nav">
<li>
<a class="button active" href="#h48{{ c.crypto }}">48 hours</a>
</li>
<li>
<a class="button" href="#d3{{ c.crypto }}">3 days</a>
</li>
<li>
<a class="button" href="#w1{{ c.crypto }}">1 week</a>
</li>
<li>
<a class="button" href="#m1{{ c.crypto }}">1 month</a>
</li>
<li>
<a class="button" href="#m6{{ c.crypto }}">6 months</a>
</li>
<li>
<a class="button" href="#y1{{ c.crypto }}">1 year</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="h48{{ c.crypto }}">
48 hours
<img src="/graph?crypto={{ c.crypto }}&fiat=EUR&number_of_hours=48" loading="lazy">
</div>
<div class="tab-pane" id="d3{{ c.crypto }}">
3 days
<img src="/graph?crypto={{ c.crypto }}&fiat=EUR&number_of_days=3" loading="lazy">
</div>
<div class="tab-pane" id="w1{{ c.crypto }}">
1 week
<img src="/graph?crypto={{ c.crypto }}&fiat=EUR&number_of_days=7" loading="lazy">
</div>
<div class="tab-pane" id="m1{{ c.crypto }}">
1 month
<img src="/graph?crypto={{ c.crypto }}&fiat=EUR&number_of_days=30" loading="lazy">
</div>
<div class="tab-pane" id="m6{{ c.crypto }}">
6 months
<img src="/graph?crypto={{ c.crypto }}&fiat=EUR&number_of_days=180" loading="lazy">
</div>
<div class="tab-pane" id="y1{{ c.crypto }}">
1 year
<img src="/graph?crypto={{ c.crypto }}&fiat=EUR&number_of_days=360" loading="lazy">
</div>
</div>
{% endif %} {% endif %}
<br/><a href="/transactions/show?crypto={{ c.crypto }}">My transactions</a><br/>
<br/> <br/>
Google: <br/> Google: <br/>
<a href='https://www.google.com/search?channel=crow2&client=firefox-b-d&q={{ c.crypto }}+in+eur%3D' target='_blank'>{{ c.crypto }} in EUR</a><br/> <a href='https://www.google.com/search?channel=crow2&client=firefox-b-d&q={{ c.crypto }}+in+eur%3D' target='_blank'>{{ c.crypto }} in EUR</a><br/>
+15
View File
@@ -3,6 +3,7 @@ from django.contrib.auth.decorators import login_required
from apps.transactions.models import Transaction from apps.transactions.models import Transaction
from apps.rates.models import ExchangeRate from apps.rates.models import ExchangeRate
from apps.monitor.calc import Calc from apps.monitor.calc import Calc
from apps.monitor.graph import Graph
@login_required @login_required
def monitor(request): def monitor(request):
@@ -20,3 +21,17 @@ def monitor(request):
cryptos.append({"crypto": crypto, "rateEUR": rateEUR, "rateUSD": rateUSD, **out2}) cryptos.append({"crypto": crypto, "rateEUR": rateEUR, "rateUSD": rateUSD, **out2})
return render(request,"monitor.html",{'cryptos':cryptos, 'total_tax_free': total_tax_free, 'total_investment': total_investment, 'current_value': current_value}) return render(request,"monitor.html",{'cryptos':cryptos, 'total_tax_free': total_tax_free, 'total_investment': total_investment, 'current_value': current_value})
@login_required
def graph(request):
if not 'crypto' in request.GET:
return
if not 'fiat' in request.GET:
return
Crypto = request.GET['crypto']
Fiat = request.GET['fiat']
if 'number_of_days' in request.GET:
return Graph().graph_days(Crypto, Fiat, request.GET['number_of_days'])
if 'number_of_hours' in request.GET:
return Graph().graph_hours(Crypto, Fiat, request.GET['number_of_hours'])
+1
View File
@@ -1,3 +1,4 @@
django django
django-registration django-registration
matplotlib
+1
View File
@@ -27,6 +27,7 @@ urlpatterns = [
path('', core_views.home), path('', core_views.home),
path('home/', core_views.home), path('home/', core_views.home),
path('monitor/', monitor_views.monitor), path('monitor/', monitor_views.monitor),
path('graph/', monitor_views.graph),
path('transactions/add', tr_views.add), path('transactions/add', tr_views.add),
path('transactions/show', tr_views.show), path('transactions/show', tr_views.show),
path('transactions/edit/<int:id>', tr_views.edit), path('transactions/edit/<int:id>', tr_views.edit),