Implement storing asset restriction callbacks
This commit is contained in:
parent
c283c6c192
commit
010aba7f81
|
@ -89,10 +89,10 @@ class AccountForm(RestrictedFormMixin, ModelForm):
|
||||||
"exchange",
|
"exchange",
|
||||||
"api_key",
|
"api_key",
|
||||||
"api_secret",
|
"api_secret",
|
||||||
"sandbox",
|
|
||||||
"enabled",
|
|
||||||
"risk_model",
|
"risk_model",
|
||||||
"initial_balance",
|
"initial_balance",
|
||||||
|
"sandbox",
|
||||||
|
"enabled",
|
||||||
)
|
)
|
||||||
help_texts = {
|
help_texts = {
|
||||||
"name": "Name of the account. Informational only.",
|
"name": "Name of the account. Informational only.",
|
||||||
|
@ -119,6 +119,7 @@ class StrategyForm(RestrictedFormMixin, ModelForm):
|
||||||
"name",
|
"name",
|
||||||
"description",
|
"description",
|
||||||
"account",
|
"account",
|
||||||
|
"asset_group",
|
||||||
"trading_times",
|
"trading_times",
|
||||||
"order_type",
|
"order_type",
|
||||||
"time_in_force",
|
"time_in_force",
|
||||||
|
@ -138,6 +139,7 @@ class StrategyForm(RestrictedFormMixin, ModelForm):
|
||||||
"name": "Name of the strategy. Informational only.",
|
"name": "Name of the strategy. Informational only.",
|
||||||
"description": "Description of the strategy. Informational only.",
|
"description": "Description of the strategy. Informational only.",
|
||||||
"account": "The account to use for this strategy.",
|
"account": "The account to use for this strategy.",
|
||||||
|
"asset_group": "Asset groups determine which pairs can be traded.",
|
||||||
"trading_times": "When the strategy will place new trades.",
|
"trading_times": "When the strategy will place new trades.",
|
||||||
"order_type": "Market: Buy/Sell at the current market price. Limit: Buy/Sell at a specified price. Limits protect you more against market slippage.",
|
"order_type": "Market: Buy/Sell at the current market price. Limit: Buy/Sell at a specified price. Limits protect you more against market slippage.",
|
||||||
"time_in_force": "The time in force controls how the order is executed.",
|
"time_in_force": "The time in force controls how the order is executed.",
|
||||||
|
@ -323,6 +325,7 @@ class AssetRestrictionForm(RestrictedFormMixin, ModelForm):
|
||||||
"name",
|
"name",
|
||||||
"description",
|
"description",
|
||||||
"pairs",
|
"pairs",
|
||||||
|
"pairs_parsed",
|
||||||
)
|
)
|
||||||
help_texts = {
|
help_texts = {
|
||||||
"name": "Name of the asset restriction group. Informational only.",
|
"name": "Name of the asset restriction group. Informational only.",
|
||||||
|
@ -330,6 +333,8 @@ class AssetRestrictionForm(RestrictedFormMixin, ModelForm):
|
||||||
"pairs": "Comma-separated list of pairs to restrict when a webhook is received. This does nothing on its own.",
|
"pairs": "Comma-separated list of pairs to restrict when a webhook is received. This does nothing on its own.",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pairs_parsed = forms.BooleanField(widget=forms.HiddenInput)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(AssetRestrictionForm, self).clean()
|
cleaned_data = super(AssetRestrictionForm, self).clean()
|
||||||
if "pairs" in cleaned_data and cleaned_data["pairs"]:
|
if "pairs" in cleaned_data and cleaned_data["pairs"]:
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 4.1.6 on 2023-02-10 22:57
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0054_assetrestriction_webhook_id_alter_assetgroup_allowed'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='strategy',
|
||||||
|
name='asset_group',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='core.assetgroup'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 4.1.6 on 2023-02-10 23:09
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0055_strategy_asset_group'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='assetrestriction',
|
||||||
|
name='pairs_parsed',
|
||||||
|
field=models.JSONField(blank=True, default=dict, null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -369,6 +369,10 @@ class Strategy(models.Model):
|
||||||
trade_size_percent = models.FloatField(default=0.5)
|
trade_size_percent = models.FloatField(default=0.5)
|
||||||
trends = models.JSONField(null=True, blank=True)
|
trends = models.JSONField(null=True, blank=True)
|
||||||
|
|
||||||
|
asset_group = models.ForeignKey(
|
||||||
|
"core.AssetGroup", on_delete=models.PROTECT, null=True, blank=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name_plural = "strategies"
|
verbose_name_plural = "strategies"
|
||||||
|
|
||||||
|
@ -414,7 +418,7 @@ class AssetGroup(models.Model):
|
||||||
allowed = models.JSONField(null=True, blank=True, default=dict)
|
allowed = models.JSONField(null=True, blank=True, default=dict)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return f"{self.name} ({self.restrictions})"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def matches(self):
|
def matches(self):
|
||||||
|
@ -438,7 +442,7 @@ class AssetRestriction(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
description = models.TextField(null=True, blank=True)
|
description = models.TextField(null=True, blank=True)
|
||||||
pairs = models.CharField(max_length=4096, null=True, blank=True)
|
pairs = models.CharField(max_length=4096, null=True, blank=True)
|
||||||
pairs_parsed = models.JSONField(null=True, blank=True)
|
pairs_parsed = models.JSONField(null=True, blank=True, default=dict)
|
||||||
|
|
||||||
webhook_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
webhook_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ from rest_framework.views import APIView
|
||||||
from core.forms import AssetGroupForm, AssetRestrictionForm
|
from core.forms import AssetGroupForm, AssetRestrictionForm
|
||||||
from core.models import AssetGroup, AssetRestriction
|
from core.models import AssetGroup, AssetRestriction
|
||||||
from core.util import logs
|
from core.util import logs
|
||||||
|
import json
|
||||||
|
|
||||||
log = logs.get_logger(__name__)
|
log = logs.get_logger(__name__)
|
||||||
|
|
||||||
|
@ -109,12 +110,35 @@ class AssetRestrictionAPI(APIView):
|
||||||
parser_classes = [JSONParser]
|
parser_classes = [JSONParser]
|
||||||
|
|
||||||
def post(self, request, webhook_id):
|
def post(self, request, webhook_id):
|
||||||
log.debug(f"AssetAPI POST {webhook_id}: {request.data}")
|
# log.debug(f"AssetAPI POST {webhook_id}: {request.data}")
|
||||||
|
print(json.dumps(request.data, indent=2))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
webhook = AssetRestriction.objects.get(webhook_id=webhook_id)
|
restriction = AssetRestriction.objects.get(webhook_id=webhook_id)
|
||||||
except AssetRestriction.DoesNotExist:
|
except AssetRestriction.DoesNotExist:
|
||||||
log.error(f"AssetRestriction {webhook_id} does not exist")
|
log.error(f"Asset restriction {webhook_id} does not exist")
|
||||||
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
|
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
|
if restriction.group is not None:
|
||||||
|
group = restriction.group
|
||||||
|
else:
|
||||||
|
log.error(f"Asset restriction {restriction} has no group")
|
||||||
|
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
|
||||||
|
|
||||||
|
# if group.strategy_set.exists() is not None:
|
||||||
|
# strategies = group.strategy_set.all()
|
||||||
|
# else:
|
||||||
|
# log.error(f"Asset group {group} has no strategy")
|
||||||
|
# return HttpResponse(status=status.HTTP_404_NOT_FOUND)
|
||||||
|
# log.debug(f"Asset API {webhook_id} matched to strategies {strategies}")
|
||||||
|
|
||||||
|
if "meta" in request.data:
|
||||||
|
if "is_match" in request.data["meta"]:
|
||||||
|
is_match = request.data["meta"]["is_match"]
|
||||||
|
if isinstance(restriction.pairs_parsed, list):
|
||||||
|
for pair in restriction.pairs_parsed:
|
||||||
|
group.allowed[pair] = is_match
|
||||||
|
group.save()
|
||||||
|
|
||||||
return HttpResponse(status=status.HTTP_200_OK)
|
return HttpResponse(status=status.HTTP_200_OK)
|
||||||
|
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
Loading…
Reference in New Issue