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 django.urls import include, path
from two_factor.urls import urlpatterns as tf_urls 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 # from core.views.stripe_callbacks import Callback
@ -185,4 +185,9 @@ urlpatterns = [
ads.AdRedist.as_view(), ads.AdRedist.as_view(),
name="ad_redist", name="ad_redist",
), ),
path(
"profit/<str:type>/",
profit.Profit.as_view(),
name="profit",
),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -1,10 +1,13 @@
# Twisted imports # Twisted imports
import logging import logging
from datetime import datetime from datetime import datetime
import asyncio
import urllib3 import urllib3
# Other library imports # Other library imports
from core.models import Aggregator, Platform
from aiocoingecko import AsyncCoinGeckoAPISession from aiocoingecko import AsyncCoinGeckoAPISession
from django.conf import settings from django.conf import settings
from elasticsearch import AsyncElasticsearch from elasticsearch import AsyncElasticsearch
@ -38,28 +41,46 @@ class Money(object):
) )
self.es = client 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. Run all the balance checks that output into ES in another thread.
""" """
total = await self.get_total() if not all([user, nordigen, agora]):
remaining = await self.get_remaining() raise Exception
profit = await self.get_profit()
profit_with_trades = await self.get_profit(True) # I hate circular dependencies
open_trades = await self.get_open_trades_usd() self.nordigen = nordigen
total_remaining = await self.get_total_remaining() self.agora = agora
total_with_trades = await self.get_total_with_trades()
# This will make them all run concurrently, hopefully not hitting rate limits aggregators = Aggregator.objects.filter(user=user, enabled=True)
for x in ( platforms = Platform.objects.filter(user=user, enabled=True)
total,
remaining, order = [
profit, "total",
profit_with_trades, # "remaining",
open_trades, # "profit",
total_remaining, # "profit_with_trades",
total_with_trades, # "open_trades",
): # "total_remaining",
yield x # "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): # def setup_loops(self):
# """ # """
@ -255,9 +276,43 @@ class Money(object):
await self.write_to_es("get_total_usd", cast_es) await self.write_to_es("get_total_usd", cast_es)
return total_usd 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 # 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 # 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. Get all the values corresponding to the amount of money we hold.
:return: ((total SEK, total USD, total GBP), :return: ((total SEK, total USD, total GBP),
@ -267,30 +322,20 @@ class Money(object):
tuple(float, float), tuple(float, float),
tuple(float, float)) tuple(float, float))
""" """
total_sinks_usd = await self.sinks.get_total_usd() total_sinks_usd = await self.gather_total_map(aggregators)
agora_wallet_xmr = await self.agora.api.wallet_balance_xmr() agora_wallet_xmr = await self.gather_wallet_balance_xmr(platforms)
agora_wallet_btc = await self.agora.api.wallet_balance() agora_wallet_btc = await self.gather_wallet_balance(platforms)
# lbtc_wallet_btc = await self.lbtc.api.wallet_balance() # lbtc_wallet_btc = await self.lbtc.api.wallet_balance()
if not agora_wallet_xmr["success"]:
return False total_xmr_agora = agora_wallet_xmr
if not agora_wallet_btc["success"]: total_btc_agora = agora_wallet_btc
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"] # total_btc_lbtc = lbtc_wallet_btc["response"]["data"]["total"]["balance"]
# Get the XMR -> USD exchange rate # 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 # 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 # Convert the Agora XMR total to USD
total_usd_agora_xmr = float(total_xmr_agora) * xmr_usd["monero"]["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_usd = total_usd
price_gbp = rates["GBP"] * total_usd price_gbp = rates["GBP"] * total_usd
cast = ( # cast = (
( # (
price_sek, # price_sek,
price_usd, # price_usd,
price_gbp, # price_gbp,
), # Total prices in our 3 favourite currencies # ), # Total prices in our 3 favourite currencies
( # (
total_xmr_usd, # total_xmr_usd,
total_btc_usd, # total_btc_usd,
), # Total USD balance in only Agora # ), # Total USD balance in only Agora
(total_xmr, total_btc), # (total_xmr, total_btc),
) # Total XMR and BTC balance in Agora # ) # Total XMR and BTC balance in Agora
# TODO
cast_es = { cast_es = {
"price_sek": price_sek, "price_sek": price_sek,
"price_usd": price_usd, "price_usd": price_usd,
@ -348,8 +394,8 @@ class Money(object):
"total_sinks_usd": total_sinks_usd, "total_sinks_usd": total_sinks_usd,
"total_usd_agora": total_usd_agora, "total_usd_agora": total_usd_agora,
} }
await self.write_to_es("get_total", cast_es) # await self.write_to_es("get_total", cast_es)
return cast return cast_es
async def get_remaining(self): async def get_remaining(self):
""" """

View File

@ -219,7 +219,7 @@
Home Home
</a> </a>
{% if user.is_authenticated %} {% if user.is_authenticated %}
<a class="navbar-item" href="#"> <a class="navbar-item" href="{% url 'profit' type='page' %}">
Profit Profit
</a> </a>
<div class="navbar-item has-dropdown is-hoverable"> <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 two_factor.views.mixins import OTPRequiredMixin
from core.clients.aggregators.nordigen import NordigenClient from core.clients.aggregators.nordigen import NordigenClient
from core.forms import AggregatorForm from core.forms import AggregatorForm
from core.models import Aggregator from core.models import Aggregator
from core.util import logs 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_xmr = yield self.agora.api.wallet_balance_xmr()
agora_wallet_btc = yield self.agora.api.wallet_balance() agora_wallet_btc = yield self.agora.api.wallet_balance()
lbtc_wallet_btc = yield self.lbtc.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_xmr_agora = agora_wallet_xmr["response"]["data"]["total"]["balance"]
total_btc_agora = agora_wallet_btc["response"]["data"]["total"]["balance"] total_btc_agora = agora_wallet_btc["response"]["data"]["total"]["balance"]
total_btc_lbtc = lbtc_wallet_btc["response"]["data"]["total"]["balance"] total_btc_lbtc = lbtc_wallet_btc["response"]["data"]["total"]["balance"]