Skip to content

Commit

Permalink
Merge pull request #242 from napse-invest/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Xenepix authored Dec 21, 2023
2 parents 5b1df65 + afeeaf3 commit fc13a3a
Show file tree
Hide file tree
Showing 23 changed files with 329 additions and 181 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/django.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ jobs:
label: Coverage
message: ${{ env.COVERAGE }} %
valColorRange: ${{ env.COVERAGE }}
minColorRange: 50
maxColorRange: 95
minColorRange: 70
maxColorRange: 100

stop-runner:
name: Stop self-hosted EC2 runner
Expand Down
97 changes: 71 additions & 26 deletions .github/workflows/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,92 @@ permissions:
contents: write

jobs:
api-schema:
name: API schema
runs-on: ubuntu-latest

start-runner:
name: Start self-hosted EC2 runner
runs-on: ubuntu-latest
outputs:
label: ${{ steps.start-ec2-runner.outputs.label }}
ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }}
steps:
- uses: actions/checkout@v4
with:
python-version: 3.11

- name: Set up python
uses: actions/setup-python@v4
with:
python-version: "3.11"
architecture: "x64"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pip-tools
pip-compile ./requirements/development.txt --output-file ./full-requirements.txt --resolver=backtracking
pip install -r ./full-requirements.txt
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Start EC2 runner
id: start-ec2-runner
uses: machulav/ec2-github-runner@v2
with:
mode: start
github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
ec2-image-id: ${{ secrets.AWS_EC2_IMAGE_ID }}
ec2-instance-type: t3.micro
subnet-id: ${{ secrets.AWS_SUBNET_ID }}
security-group-id: ${{ secrets.AWS_SECURITY_GROUP_ID }}

- name: Write open-api schema
run: python tests/test_app/manage.py spectacular --file docs/schema.yml


deploy:
needs: api-schema
needs: start-runner
name: Deploy documentation
runs-on: ubuntu-latest
runs-on: ${{ needs.start-runner.outputs.label }}
timeout-minutes: 10
environment: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && 'external' || 'internal' }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
- uses: actions/setup-python@v4
with:
python-version: 3.x
python-version: 3.11
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v3
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
- run: |
pip install -r requirements/development.txt
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pip-tools
pip-compile ./requirements/development.txt --output-file ./full-requirements.txt --resolver=backtracking
pip install -r ./full-requirements.txt
- name: Tests with coverage
run: |
export PYTHONPATH="$PYTHONPATH:./django-napse/"
export NAPSE_IS_IN_PIPELINE=True
cd tests/test_app
bash setup_secrets.sh
cd ../..
python3 tests/test_app/manage.py makemigrations && python3 tests/test_app/manage.py migrate
coverage run ./tests/test_app/manage.py test -v2 --keepdb && coverage html
- name: Write open-api schema
run: python tests/test_app/manage.py spectacular --file docs/schema.yml
- name: Deploy documentation
run: |
mkdocs gh-deploy --force
stop-runner:
name: Stop self-hosted EC2 runner
needs:
- start-runner # required to get output from the start-runner job
- deploy # required to wait when the main job is done
runs-on: ubuntu-latest
if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Stop EC2 runner
uses: machulav/ec2-github-runner@v2
with:
mode: stop
github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
label: ${{ needs.start-runner.outputs.label }}
ec2-instance-id: ${{ needs.start-runner.outputs.ec2-instance-id }}
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ all: setup-testing-environment makemigrations migrate runserver

setup:
ifeq ($(OS),Darwin) # Mac OS X
./setup-osx.sh
./setup/setup-osx.sh
else ifeq ($(OS),Linux)
./setup-unix.sh
./setup/setup-unix.sh
else
./setup-windows.sh
./setup/setup-windows.sh
endif

setup-testing-environment:
Expand Down
42 changes: 12 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,47 +22,29 @@

<p align="center">
<a href="#django-napse"><strong>Django Napse</strong></a> ·
<a href="#usefull-commands"><strong>Usefull commands</strong></a> .
<a href="#documentation"><strong>Documentation</strong></a> .
<a href="#how-to-contribute"><strong>How to contribute</strong></a>
</p>
<br/>

## django-napse
....

## Useful commands
Unless otherwise specified, all commands are to be run at the root folder of the project.
Django napse is a portfolio management module using trading bots.
This directory can be used as a django module, which you can install as follows:

### Create a new project
- Unix \
```source setup-unix.sh```

- Windows \
```.\setup-windows.ps1```
```bash
pip install django-napse
```

### Run a test version of the project
Or you can use it as a local backend for the [Napse desktop application](https://github.com/napse-invest/Napse), by cloning the repository.

- Build migrations \
```make makemigrations```
- Apply migrations \
```make migrate```
- Run server \
```make runserver```
Find more details for installation in the [documentation](https://napse-invest.github.io/django-napse/#installation).

### Run coverage tests
### Documentation

- Run tests \
```test-napse```
- Run tests with coverage \
```coverage```
- Run tests with coverage and open coverage report \
```coverage-open```
You can find the documentation [here](https://napse-invest.github.io/django-napse/).

## Documentation

[Docs](https://napse-invest.github.io/django-napse/)
## How to contribute

Run mkdocs server:
```
make mkdocs
```
If you want to contribute to the project, please read the [contributing guidelines](https://napse-invest.github.io/django-napse/contributing/) first. You will find the setup instructions and our standards.
1 change: 1 addition & 0 deletions django_napse/api/fleets/serializers/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .cluster_serialisers import ClusterSerializer
from .fleet_serializers import FleetDetailSerializer, FleetSerializer
17 changes: 17 additions & 0 deletions django_napse/api/fleets/serializers/cluster_serialisers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from rest_framework import serializers

from django_napse.api.bots.serializers import BotSerializer
from django_napse.core.models import Cluster


class ClusterSerializer(serializers.ModelSerializer):
template_bot = BotSerializer()

class Meta:
model = Cluster
fields = [
"template_bot",
"share",
"breakpoint",
"autoscale",
]
8 changes: 6 additions & 2 deletions django_napse/api/fleets/serializers/fleet_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
from rest_framework.fields import empty

from django_napse.api.bots.serializers import BotSerializer
from django_napse.api.fleets.serializers.cluster_serialisers import ClusterSerializer
from django_napse.core.models import ConnectionWallet, Fleet


class FleetSerializer(serializers.ModelSerializer):
value = serializers.SerializerMethodField(read_only=True)
bot_count = serializers.SerializerMethodField(read_only=True)
clusters = ClusterSerializer(
write_only=True,
many=True,
required=True,
)

class Meta:
model = Fleet
Expand All @@ -20,8 +26,6 @@ class Meta:
]
read_only_fields = [
"uuid",
"value",
"bot_count",
]

def __init__(self, instance=None, data=empty, space=None, **kwargs):
Expand Down
15 changes: 13 additions & 2 deletions django_napse/api/fleets/views/fleet_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
from django_napse.api.custom_permissions import HasSpace
from django_napse.api.custom_viewset import CustomViewSet
from django_napse.api.fleets.serializers import FleetDetailSerializer, FleetSerializer
from django_napse.core.models import NapseSpace
from django_napse.core.models import Fleet, NapseSpace


class FleetView(CustomViewSet):
permission_classes = [HasAPIKey, HasSpace]
serializer_class = FleetSerializer

def get_queryset(self):
self.space = NapseSpace.objects.get(uuid=self.request.query_params["space"])
space_uuid = self.request.query_params.get("space", None)
if space_uuid is None:
return Fleet.objects.all()
self.space = NapseSpace.objects.get(uuid=space_uuid)
return self.space.fleets

def get_serialiser_class(self, *args, **kwargs):
Expand All @@ -25,6 +28,13 @@ def get_serialiser_class(self, *args, **kwargs):
result = actions.get(self.action)
return result if result else super().get_serializer_class()

def get_permissions(self):
match self.action:
case "list" | "create":
return [HasAPIKey()]
case _:
return super().get_permissions()

def list(self, request):
serializer = self.serializer_class(self.get_queryset(), many=True, space=self.space)
return Response(serializer.data, status=status.HTTP_200_OK)
Expand All @@ -34,6 +44,7 @@ def retrieve(self, request, pk=None):

def create(self, request, *args, **kwargs):
return Response(status=status.HTTP_501_NOT_IMPLEMENTED)
# serializer = self.serializer_class(data=request.data, space=self.space)

def delete(self):
return Response(status=status.HTTP_501_NOT_IMPLEMENTED)
14 changes: 2 additions & 12 deletions django_napse/api/spaces/views/space_view.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework_api_key.permissions import HasAPIKey

from django_napse.api.custom_permissions import HasFullAccessPermission, HasMasterKey, HasReadPermission
from django_napse.api.custom_viewset import CustomViewSet
from django_napse.api.exchanges.serializers.exchange_account_serializer import ExchangeAccountSerializer
from django_napse.api.spaces.serializers import SpaceDetailSerializer, SpaceSerializer
from django_napse.core.models import ExchangeAccount, NapseSpace
from django_napse.core.models import NapseSpace
from django_napse.utils.errors import SpaceError


Expand Down Expand Up @@ -38,7 +36,7 @@ def get_permissions(self):
return [HasReadPermission()]
case "list":
return [HasAPIKey()]
case "possible_exchange_accounts" | "create":
case "create":
return [HasMasterKey()]

case _:
Expand Down Expand Up @@ -82,11 +80,3 @@ def delete(self, request, *args, **kwargs):
except SpaceError.DeleteError:
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
return Response(status=status.HTTP_204_NO_CONTENT)

@action(detail=False, methods=["GET"])
def possible_exchange_accounts(self, request):
serialized_exchange_account = ExchangeAccountSerializer(ExchangeAccount.objects.all(), many=True)
return Response(
serialized_exchange_account.data,
status=status.HTTP_200_OK,
)
12 changes: 10 additions & 2 deletions django_napse/core/models/fleets/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@


class Cluster(models.Model):
fleet = models.ForeignKey("Fleet", on_delete=models.CASCADE, related_name="clusters")
template_bot = models.OneToOneField("Bot", on_delete=models.CASCADE, related_name="cluster")
fleet = models.ForeignKey(
"Fleet",
on_delete=models.CASCADE,
related_name="clusters",
)
template_bot = models.OneToOneField(
"Bot",
on_delete=models.CASCADE,
related_name="cluster",
)
share = models.FloatField()
breakpoint = models.FloatField()
autoscale = models.BooleanField()
Expand Down
21 changes: 17 additions & 4 deletions django_napse/core/models/fleets/fleet.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,25 @@


class Fleet(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
name = models.CharField(max_length=100, default="Fleet")
exchange_account = models.ForeignKey("ExchangeAccount", on_delete=models.CASCADE)
uuid = models.UUIDField(
default=uuid.uuid4,
editable=False,
unique=True,
)
name = models.CharField(
max_length=100,
default="Fleet",
)
exchange_account = models.ForeignKey(
"ExchangeAccount",
on_delete=models.CASCADE,
)
running = models.BooleanField(default=False)
setup_finished = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
created_at = models.DateTimeField(
auto_now_add=True,
blank=True,
)

objects = FleetManager()

Expand Down
Loading

0 comments on commit fc13a3a

Please sign in to comment.