Skip to content
Browse files

Ability to graph "historical average"


* We're trying to do generators all the way down, so passing a `length` to some things
* Yielding `(dt.timestamp(), price)` since `svg_graph` currently needs a "numeral" for both X and Y
* Catching `RuntimeError` in `` to avoid configuring django ORM twice. Is there a better way?
* Actually graphing historical average. Needs work but works!
* `to_xml` instead of relying on `__str__` in `LineGraph`. It's easy to accidentally exhaust the generator when debugging (e.g. `print("the graph looks like "+str(graph))`. Hard to diagnose. Instead we use an explicit method.
  • Loading branch information
stnbu committed Sep 8, 2018
1 parent 92def93 commit 28bbb372af5f682184793c3d4e0974ba7fb6835e
Showing with 38 additions and 29 deletions.
  1. +16 −4 coincharts/
  2. +7 −3 coincharts/
  3. +1 −1 coincharts/
  4. +14 −21 coincharts/
@@ -2,6 +2,7 @@

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'coincharts.settings'
from dateutil.parser import parse as parse_dt

from mutils.memoize import memoize

@@ -10,12 +11,12 @@
from coincharts import config
config = config.get_config()

symbols = config['history_symbols']

class SymbolInfo(object):

def __init__(self, symbol):
def __init__(self, symbol, length):
self.symbol = symbol
self.length = length # this is set below when we access the "history". Being as lazy as possible.

@@ -30,20 +31,30 @@ def max(self):
def history(self):
return Prices.objects.filter(symbol=self.symbol)
history = Prices.objects.filter(symbol=self.symbol)
self.length = len(history)
return history

def normalized_history(self):
price_delta = self.max - self.min
for record in self.history:
yield record.dt, (record.price - self.min) / price_delta
yield parse_dt(record.dt).timestamp(), (record.price - self.min) / price_delta

class SymbolComparison(dict):

def __init__(self, *args, **kwargs):
self.update(*args, **kwargs)

def length(self):
# `self.length` has to be a calculated value, we may be truncating other symbol histories
# so we're only dealing with time periods where they all overlap (are present).
# So it's up to me* to set self.length as soon as practical.
# For now we'll just grab an arbitrary symbol and use its lenght attribute
return list(self.values())[0].length # <-- only a few symbols. not expensive.

def normalized_history_averages(self):
normalized_history_generators = []
for symbol, data in self.items():
@@ -67,6 +78,7 @@ def normalized_history_averages(self):

if __name__ == '__main__':

symbols = config['history_symbols']
comparison = SymbolComparison()
for symbol in symbols:
comparison[symbol] = SymbolInfo(symbol)
@@ -35,9 +35,13 @@
from django.db import connections
import atexit

# HACK -- note that the rhs "DATABASES" here comes from mysite.settings, above
# HACK -- This is doubly a hack: "DATABASES" pops into existence (from .settings) and also we're using a kludgy try/except
# to test if the database is already configured.
except RuntimeError:

from coincharts.models import *

@@ -3,5 +3,5 @@
from . import views

urlpatterns = [
path('<str:symbol>/', views.index, name='index'),
path('', views.index, name='index'),
@@ -6,37 +6,30 @@

from dateutil.parser import parse as parse_dt
import time
from coincharts import config
from import SymbolComparison, SymbolInfo

import svg_graph

def index(request, symbol):
prices = Prices.objects.filter(symbol=symbol)[:1000]
config = config.get_config()

def string_to_epoch(string):
return time.mktime(parse_dt(string).timetuple())
import svg_graph

def prices_gen(prices):
x = []
for p in prices:
x.append((p.dt, int(p.price)))
return x
def index(request):

title = '{} from {} to {}'.format(
prices[len(prices)-1].dt, # "negative indexing is not supported"
symbols = config['history_symbols']
comparison = SymbolComparison()
for symbol in symbols:
comparison[symbol] = SymbolInfo(symbol, length=967)
history_generator = comparison.normalized_history_averages()

graph = svg_graph.LineGraph(
title='Price history averages',

context = {
'graph': graph,
'prices': prices,
'graph': graph.to_xml(),
return render(request, 'coincharts/index.html', context)

0 comments on commit 28bbb37

Please sign in to comment.