diff --git a/accountant/api/models/operations.py b/accountant/api/models/operations.py index d1d3c58..a7a4a6f 100644 --- a/accountant/api/models/operations.py +++ b/accountant/api/models/operations.py @@ -16,7 +16,7 @@ """ import arrow -from sqlalchemy import func, case, desc +from sqlalchemy import func, case, desc, false from accountant import db @@ -136,3 +136,61 @@ class Operation(db.Model): ) return query + + @classmethod + def get_ohlc_per_day_for_range(cls, session, account, begin=None, end=None): + if isinstance(account, int) or isinstance(account, str): + account_id = account + else: + account_id = account.id + + sold = func.sum(cls.value).over( + order_by=[cls.operation_date, desc(cls.value), cls.label] + ) + + previous = sold - cls.value + + subquery = session.query( + cls.operation_date, + sold.label("sold"), + previous.label("previous") + ).filter( + cls.account_id == account_id, + cls.canceled == false() + ).subquery() + + query = session.query( + subquery.c.operation_date, + func.first_value(subquery.c.previous).over( + partition_by=subquery.c.operation_date + ).label("open"), + func.max( + func.greatest( + subquery.c.previous, subquery.c.sold + ) + ).over( + partition_by=subquery.c.operation_date + ).label('high'), + func.min( + func.least( + subquery.c.previous, subquery.c.sold + ) + ).over( + partition_by=subquery.c.operation_date + ).label('low'), + func.last_value(subquery.c.sold).over( + partition_by=subquery.c.operation_date + ).label('close') + ).distinct() + + if begin: + query = query.filter(subquery.c.operation_date >= str(begin)) + + if end: + query = query.filter(subquery.c.operation_date <= str(end)) + + query = query.order_by( + subquery.c.operation_date + ) + + return query