Allow viewing profit

This commit is contained in:
Mark Veidemanis 2023-03-11 00:21:58 +00:00
parent 1e201e3f26
commit 77dcd4dd8f
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
7 changed files with 172 additions and 68 deletions

View File

@ -20,7 +20,7 @@ from django.contrib.auth.views import LogoutView
from django.urls import include, path
from two_factor.urls import urlpatterns as tf_urls
from core.views import ads, aggregators, banks, base, notifications, platforms
from core.views import ads, aggregators, banks, base, notifications, platforms, profit
# from core.views.stripe_callbacks import Callback
@ -185,4 +185,9 @@ urlpatterns = [
ads.AdRedist.as_view(),
name="ad_redist",
),
path(
"profit/<str:type>/",
profit.Profit.as_view(),
name="profit",
),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -1,10 +1,13 @@
# Twisted imports
import logging
from datetime import datetime
import asyncio
import urllib3
# Other library imports
from core.models import Aggregator, Platform
from aiocoingecko import AsyncCoinGeckoAPISession
from django.conf import settings
from elasticsearch import AsyncElasticsearch
@ -38,28 +41,46 @@ class Money(object):
)
self.es = client
async def run_checks_in_thread(self):
async def check_all(self, user=None, nordigen=None, agora=None):
"""
Run all the balance checks that output into ES in another thread.
"""
total = await self.get_total()
remaining = await self.get_remaining()
profit = await self.get_profit()
profit_with_trades = await self.get_profit(True)
open_trades = await self.get_open_trades_usd()
total_remaining = await self.get_total_remaining()
total_with_trades = await self.get_total_with_trades()
# This will make them all run concurrently, hopefully not hitting rate limits
for x in (
total,
remaining,
profit,
profit_with_trades,
open_trades,
total_remaining,
total_with_trades,
):
yield x
if not all([user, nordigen, agora]):
raise Exception
# I hate circular dependencies
self.nordigen = nordigen
self.agora = agora
aggregators = Aggregator.objects.filter(user=user, enabled=True)
platforms = Platform.objects.filter(user=user, enabled=True)
order = [
"total",
# "remaining",
# "profit",
# "profit_with_trades",
# "open_trades",
# "total_remaining",
# "total_with_trades",
]
tasks = [
self.get_total(aggregators, platforms),
# self.get_remaining(),
# self.get_profit(),
# self.get_profit(True),
# self.get_open_trades_usd(),
# self.get_total_remaining(),
# self.get_total_with_trades(),
]
task_output = await asyncio.gather(*tasks)
print("TASK OUTPUT", task_output)
results = dict(zip(order, task_output))
print("RESULTS", results)
return results
# def setup_loops(self):
# """
@ -255,9 +276,43 @@ class Money(object):
await self.write_to_es("get_total_usd", cast_es)
return total_usd
async def gather_total_map(self, aggregators):
total = 0
for aggregator in aggregators:
run = await self.nordigen(aggregator)
total_map = await run.get_total_map()
total_usd = await self.multiple_to_usd(total_map)
print("gather_total_map total_usd", total_usd)
total += total_usd
return total
async def gather_wallet_balance_xmr(self, platforms):
# TODO: check success
total = 0
for platform in platforms:
run = await self.agora(platform)
xmr = await run.api.wallet_balance_xmr()
xmr = float(xmr["response"]["data"]["total"]["balance"])
print("gather waller xmr", xmr)
total += xmr
return total
async def gather_wallet_balance(self, platforms):
# TODO: check success
total = 0
for platform in platforms:
run = await self.agora(platform)
btc = await run.api.wallet_balance()
btc = float(btc["response"]["data"]["total"]["balance"])
total += btc
return total
# TODO: possibly refactor this into smaller functions which don't return as much
# check if this is all really needed in the corresponding withdraw function
async def get_total(self):
async def get_total(self, aggregators, platforms):
"""
Get all the values corresponding to the amount of money we hold.
:return: ((total SEK, total USD, total GBP),
@ -267,30 +322,20 @@ class Money(object):
tuple(float, float),
tuple(float, float))
"""
total_sinks_usd = await self.sinks.get_total_usd()
agora_wallet_xmr = await self.agora.api.wallet_balance_xmr()
agora_wallet_btc = await self.agora.api.wallet_balance()
total_sinks_usd = await self.gather_total_map(aggregators)
agora_wallet_xmr = await self.gather_wallet_balance_xmr(platforms)
agora_wallet_btc = await self.gather_wallet_balance(platforms)
# lbtc_wallet_btc = await self.lbtc.api.wallet_balance()
if not agora_wallet_xmr["success"]:
return False
if not agora_wallet_btc["success"]:
return False
# if not lbtc_wallet_btc["success"]:
# return False
if not agora_wallet_xmr["response"]:
return False
if not agora_wallet_btc["response"]:
return False
# if not lbtc_wallet_btc["response"]:
# return False
total_xmr_agora = agora_wallet_xmr["response"]["data"]["total"]["balance"]
total_btc_agora = agora_wallet_btc["response"]["data"]["total"]["balance"]
total_xmr_agora = agora_wallet_xmr
total_btc_agora = agora_wallet_btc
# total_btc_lbtc = lbtc_wallet_btc["response"]["data"]["total"]["balance"]
# Get the XMR -> USD exchange rate
xmr_usd = self.cg.get_price(ids="monero", vs_currencies=["USD"])
async with AsyncCoinGeckoAPISession() as cg:
xmr_usd = await cg.get_price(ids="monero", vs_currencies="USD")
# Get the BTC -> USD exchange rate
btc_usd = self.cg.get_price(ids="bitcoin", vs_currencies=["USD"])
btc_usd = await cg.get_price(ids="bitcoin", vs_currencies="USD")
# Convert the Agora XMR total to USD
total_usd_agora_xmr = float(total_xmr_agora) * xmr_usd["monero"]["usd"]
@ -320,19 +365,20 @@ class Money(object):
price_usd = total_usd
price_gbp = rates["GBP"] * total_usd
cast = (
(
price_sek,
price_usd,
price_gbp,
), # Total prices in our 3 favourite currencies
(
total_xmr_usd,
total_btc_usd,
), # Total USD balance in only Agora
(total_xmr, total_btc),
) # Total XMR and BTC balance in Agora
# cast = (
# (
# price_sek,
# price_usd,
# price_gbp,
# ), # Total prices in our 3 favourite currencies
# (
# total_xmr_usd,
# total_btc_usd,
# ), # Total USD balance in only Agora
# (total_xmr, total_btc),
# ) # Total XMR and BTC balance in Agora
# TODO
cast_es = {
"price_sek": price_sek,
"price_usd": price_usd,
@ -348,8 +394,8 @@ class Money(object):
"total_sinks_usd": total_sinks_usd,
"total_usd_agora": total_usd_agora,
}
await self.write_to_es("get_total", cast_es)
return cast
# await self.write_to_es("get_total", cast_es)
return cast_es
async def get_remaining(self):
"""

View File

@ -219,7 +219,7 @@
Home
</a>
{% if user.is_authenticated %}
<a class="navbar-item" href="#">
<a class="navbar-item" href="{% url 'profit' type='page' %}">
Profit
</a>
<div class="navbar-item has-dropdown is-hoverable">

View File

@ -0,0 +1,27 @@
{% load cache %}
{% load cachalot cache %}
{% get_last_invalidation 'core.Platform' as last %}
{% include 'mixins/partials/notify.html' %}
{# cache 600 objects_platform_profit request.user.id object_list type last #}
{% for platform_name, profit_map in object_list.items %}
<h2 class="title is-4">{{ platform_name }}</h2>
<table
class="table is-fullwidth is-hoverable"
hx-target="#{{ context_object_name }}-table"
id="{{ context_object_name }}-table"
hx-swap="outerHTML"
hx-trigger="{{ context_object_name_singular }}Event from:body"
hx-get="{{ list_url }}">
<thead>
<th>id</th>
</thead>
{% for item in profit_map.values %}
<tr>
<td> {{ item }}
</td>
</tr>
{% endfor %}
</table>
{% endfor %}
{# endcache #}

View File

@ -13,6 +13,7 @@ from mixins.views import (
from two_factor.views.mixins import OTPRequiredMixin
from core.clients.aggregators.nordigen import NordigenClient
from core.forms import AggregatorForm
from core.models import Aggregator
from core.util import logs

36
core/views/profit.py Normal file
View File

@ -0,0 +1,36 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse
from django.shortcuts import render
from django.urls import reverse
from django.views import View
from mixins.views import (
ObjectCreate,
ObjectDelete,
ObjectList,
ObjectRead,
ObjectUpdate,
)
from two_factor.views.mixins import OTPRequiredMixin
from core.clients.aggregators.nordigen import NordigenClient
from core.clients.platforms.agora import AgoraClient
from core.util import logs
from core.models import Platform
from core.lib.money import money
from core.views.helpers import synchronize_async_helper
log = logs.get_logger(__name__)
class Profit(LoginRequiredMixin, OTPRequiredMixin, ObjectRead):
context_object_name_singular = "profit"
context_object_name = "profit"
# detail_template = "partials/profit-info.html"
def get_object(self, **kwargs):
res = synchronize_async_helper(money.check_all(user=self.request.user, nordigen=NordigenClient, agora=AgoraClient))
results = {
"Bank balance total (USD)": res["total"]["total_sinks_usd"],
"Platform balance total (USD)": res["total"]["total_usd_agora"],
"Sum of above": res["total"]["total_sinks_usd"] + res["total"]["total_usd_agora"],
}
return results

View File

@ -239,18 +239,7 @@ class Money(util.Base):
agora_wallet_xmr = yield self.agora.api.wallet_balance_xmr()
agora_wallet_btc = yield self.agora.api.wallet_balance()
lbtc_wallet_btc = yield self.lbtc.api.wallet_balance()
if not agora_wallet_xmr["success"]:
return False
if not agora_wallet_btc["success"]:
return False
if not lbtc_wallet_btc["success"]:
return False
if not agora_wallet_xmr["response"]:
return False
if not agora_wallet_btc["response"]:
return False
if not lbtc_wallet_btc["response"]:
return False
total_xmr_agora = agora_wallet_xmr["response"]["data"]["total"]["balance"]
total_btc_agora = agora_wallet_btc["response"]["data"]["total"]["balance"]
total_btc_lbtc = lbtc_wallet_btc["response"]["data"]["total"]["balance"]