Skip to content

Commit

Permalink
Merge pull request #354 from napse-invest/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Xenepix authored Mar 20, 2024
2 parents ed56c99 + 0e86a09 commit 5da9846
Show file tree
Hide file tree
Showing 32 changed files with 471 additions and 133 deletions.
4 changes: 1 addition & 3 deletions django_napse/api/api_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ def build_main_router() -> DefaultRouter:
for module_name in api_modules_folders_names:
try:
module: ModuleType = import_module(f"django_napse.api.{module_name}.views")
except (ImportError, ModuleNotFoundError) as error:
print(f"Could not import module {module_name} ({type(error)})")
print(error)
except (ImportError, ModuleNotFoundError):
continue
for obj in vars(module).values():
if isinstance(obj, type) and issubclass(obj, GenericViewSet):
Expand Down
1 change: 0 additions & 1 deletion django_napse/api/bots/serializers/bot_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ def get_space(self, instance: Bot) -> UUID | None: # noqa: ARG002
"""Return the space used for the space containerization."""
if self.space is None:
return None
print("UUID", type(self.space.uuid))
return self.space.uuid

def get_exchange_account(self, instance: Bot) -> UUID | None:
Expand Down
2 changes: 1 addition & 1 deletion django_napse/api/fleets/serializers/fleet_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def get_wallet(self, instance: Fleet) -> list[dict[str, float | str]] | None:
def _search_ticker(ticker: str, merged_wallet: list[dict[str, str | float]]) -> int | None:
"""Return the index of the currency in the list if found, None otherwise."""
for i, currency in enumerate(merged_wallet):
if currency.get("ticker").ticker == ticker:
if currency.get("ticker") == ticker:
return i
return None

Expand Down
2 changes: 1 addition & 1 deletion django_napse/api/wallets/serializers/wallet_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Meta: # noqa: D106
]

def get_value(self, instance) -> float:
return instance.value_market()
return instance.value()

def get_operations(self, instance) -> dict:
transactions = Transaction.objects.filter(Q(from_wallet=instance) | Q(to_wallet=instance)).order_by("created_at")
Expand Down
15 changes: 10 additions & 5 deletions django_napse/auth/db_essentials.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import contextlib
import json
from pathlib import Path

from django.apps import apps
from django.apps import AppConfig, apps
from django.db.models.signals import post_migrate
from django.dispatch import receiver

Expand All @@ -10,13 +11,17 @@


@receiver(post_migrate)
def create_master_key(sender, **kwargs):
def create_master_key(sender: AppConfig, **kwargs: dict) -> None: # noqa: ARG001
"""Create a master key for the Napse API."""
NapseAPIKey = apps.get_model("django_napse_auth", "NapseAPIKey")
with contextlib.suppress(NapseKeyError.DuplicateMasterkey):
_, key = NapseAPIKey.objects.create_key(name="", is_master_key=True)
print(f"Master key created: {key}")
with open(napse_settings.NAPSE_SECRETS_FILE_PATH, "r") as f:

Path.mkdir(Path(Path.home() / ".napse-dev"), exist_ok=True)
with Path(Path.home() / ".napse-dev" / "api-keys.json").open("w") as f:
json.dump({"Django Napse Dev": {"url": "http://localhost:8000", "token": key}}, f, indent=4)
with Path(napse_settings.NAPSE_SECRETS_FILE_PATH).open("r") as f:
secrets = json.load(f)
secrets["master_key"] = key
with open(napse_settings.NAPSE_SECRETS_FILE_PATH, "w") as f:
with Path(napse_settings.NAPSE_SECRETS_FILE_PATH).open("w") as f:
json.dump(secrets, f, indent=4)
10 changes: 5 additions & 5 deletions django_napse/core/management/commands/create_dca.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ def add_arguments(self, parser): # noqa
def handle(self, *args, **options): # noqa
exchange_account = ExchangeAccount.objects.first()
space = Space.objects.first()
config = DCABotConfig.objects.create(space=space, settings={"timeframe": timedelta(hours=1)})
config = DCABotConfig.objects.create(space=space, settings={"timeframe": timedelta(minutes=1)})
controller = Controller.get(
exchange_account=exchange_account,
base="BTC",
base="ETH",
quote="USDT",
interval="15m",
interval="1m",
)
architecture = SinglePairArchitecture.objects.create(constants={"controller": controller})
strategy = DCAStrategy.objects.create(config=config, architecture=architecture)
Bot.objects.create(name="Test Bot", strategy=strategy)
Bot.objects.create(name="Test Bot ETH/BTC", strategy=strategy)

self.stdout.write(self.style.SUCCESS("DCABot have been created successfully!"))
self.stdout.write(self.style.SUCCESS("DCABot has been created successfully!"))
134 changes: 134 additions & 0 deletions django_napse/core/management/commands/default_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
from datetime import timedelta

import environ
from django.core.exceptions import ImproperlyConfigured
from django.core.management.base import BaseCommand
from django.db.transaction import atomic

from django_napse.core.models import Bot, Controller, DCABotConfig, DCAStrategy, SinglePairArchitecture
from django_napse.core.models.accounts.exchange import BinanceAccount
from django_napse.core.models.accounts.space import Space
from django_napse.core.models.fleets.fleet import Fleet
from django_napse.core.models.transactions.credit import Credit


class Command(BaseCommand): # noqa
help = "Create a prebuilt space with a fleet and a DCABot"

def add_arguments(self, parser): # noqa
pass

def handle(self, *args, **options): # noqa
env = environ.Env()
with atomic():
try:
public_key = env.str("BINANCE_PUBLIC_KEY")
private_key = env.str("BINANCE_PRIVATE_KEY")
except ImproperlyConfigured:
self.stdout.write(self.style.ERROR("Please set up BINANCE_PUBLIC_KEY and BINANCE_PRIVATE_KEY in .env file"))
exchange_account = BinanceAccount.objects.get(
public_key=public_key,
private_key=private_key,
)
space = Space.objects.create(
name="Prebuilt Space",
description="We've created a space for you with all the necessary data to try out the app.",
exchange_account=exchange_account,
)
Credit.objects.create(wallet=space.wallet, ticker="USDT", amount=100000)
config = DCABotConfig.objects.create(space=space, settings={"timeframe": timedelta(minutes=1)})
config5 = DCABotConfig.objects.create(space=space, settings={"timeframe": timedelta(minutes=5)})
fleet = Fleet.objects.create(
name="Prebuilt Fleet",
exchange_account=exchange_account,
clusters=[
{
"template_bot": Bot.objects.create(
name="Prebuilt DCABot",
strategy=DCAStrategy.objects.create(
config=config,
architecture=SinglePairArchitecture.objects.create(
constants={
"controller": Controller.get(
exchange_account=exchange_account,
base="BTC",
quote="USDT",
interval="1m",
),
},
),
),
),
"share": 0.3,
"breakpoint": 0,
"autoscale": False,
},
{
"template_bot": Bot.objects.create(
name="Prebuilt DCABot",
strategy=DCAStrategy.objects.create(
config=config,
architecture=SinglePairArchitecture.objects.create(
constants={
"controller": Controller.get(
exchange_account=exchange_account,
base="ETH",
quote="USDT",
interval="1m",
),
},
),
),
),
"share": 0.3,
"breakpoint": 0,
"autoscale": False,
},
{
"template_bot": Bot.objects.create(
name="Prebuilt DCABot",
strategy=DCAStrategy.objects.create(
config=config5,
architecture=SinglePairArchitecture.objects.create(
constants={
"controller": Controller.get(
exchange_account=exchange_account,
base="MATIC",
quote="USDT",
interval="1m",
),
},
),
),
),
"share": 0.2,
"breakpoint": 0,
"autoscale": False,
},
{
"template_bot": Bot.objects.create(
name="Prebuilt DCABot",
strategy=DCAStrategy.objects.create(
config=config5,
architecture=SinglePairArchitecture.objects.create(
constants={
"controller": Controller.get(
exchange_account=exchange_account,
base="MATIC",
quote="USDT",
interval="5m",
),
},
),
),
),
"share": 0.2,
"breakpoint": 0,
"autoscale": False,
},
],
)
fleet.invest(space=space, amount=10000, ticker="USDT")
fleet.running = True
fleet.save()
self.stdout.write(self.style.SUCCESS("DCABot has been created successfully!"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.2.7 on 2024-03-15 16:17

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):
dependencies = [
("django_napse_core", "0010_rename_napsespace_space"),
]

operations = [
migrations.AlterField(
model_name="strategy",
name="architecture",
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name="strategy", to="django_napse_core.architecture"),
),
migrations.AlterField(
model_name="strategy",
name="config",
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name="strategy", to="django_napse_core.botconfig"),
),
]
18 changes: 18 additions & 0 deletions django_napse/core/migrations/0012_alter_strategy_architecture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.7 on 2024-03-15 16:21

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):
dependencies = [
("django_napse_core", "0011_alter_strategy_architecture_alter_strategy_config"),
]

operations = [
migrations.AlterField(
model_name="strategy",
name="architecture",
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name="strategy", to="django_napse_core.architecture"),
),
]
19 changes: 15 additions & 4 deletions django_napse/core/models/accounts/managers/exchange.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from django.apps import apps
from django.db import models

if TYPE_CHECKING:
from django_napse.core.models.accounts.exchange import Exchange, ExchangeAccount


class ExchangeAccountManager(models.Manager):
"""Manager for the ExchangeAccount model."""

def create(
self,
exchange,
testing: bool,
exchange: Exchange,
name: str,
description: str = "",
**kwargs,
):
*,
testing: bool,
**kwargs: dict[str, any],
) -> ExchangeAccount:
"""Create a new exchange account."""
Space = apps.get_model("django_napse_core", "Space")
exchange_account = self.model(
exchange=exchange,
Expand Down
Loading

0 comments on commit 5da9846

Please sign in to comment.