Begin implementing trade management

This commit is contained in:
Mark Veidemanis 2022-10-18 07:22:22 +01:00
parent e2a697dcc1
commit 5279217324
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
5 changed files with 126 additions and 4 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 4.1.2 on 2022-10-17 18:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0008_trade'),
]
operations = [
migrations.AddField(
model_name='trade',
name='exchange_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
]

View File

@ -0,0 +1,38 @@
# Generated by Django 4.1.2 on 2022-10-17 18:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0009_trade_exchange_id'),
]
operations = [
migrations.AddField(
model_name='account',
name='sandbox',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='trade',
name='direction',
field=models.CharField(blank=True, choices=[('buy', 'Buy'), ('sell', 'Sell')], max_length=255, null=True),
),
migrations.AddField(
model_name='trade',
name='status',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AlterField(
model_name='trade',
name='symbol',
field=models.CharField(choices=[('BTCUSD', 'Bitcoin/USD')], max_length=255),
),
migrations.AlterField(
model_name='trade',
name='type',
field=models.CharField(choices=[('market', 'Market'), ('limit', 'Limit')], max_length=255),
),
]

View File

@ -1,5 +1,6 @@
import logging
import ccxt
import stripe
from django.conf import settings
from django.contrib.auth.models import AbstractUser
@ -67,11 +68,16 @@ class User(AbstractUser):
class Account(models.Model):
EXCHANGE_CHOICES = (
("binance", "Binance"),
("alpaca", "Alpaca"),
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
exchange = models.CharField(max_length=255)
exchange = models.CharField(choices=EXCHANGE_CHOICES, max_length=255)
api_key = models.CharField(max_length=255)
api_secret = models.CharField(max_length=255)
sandbox = models.BooleanField(default=False)
class Session(models.Model):
@ -90,14 +96,71 @@ class Hook(models.Model):
class Trade(models.Model):
SYMBOL_CHOICES = (("BTCUSD", "Bitcoin/USD"),)
TYPE_CHOICES = (
("market", "Market"),
("limit", "Limit"),
)
DIRECTION_CHOICES = (
("buy", "Buy"),
("sell", "Sell"),
)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
hook = models.ForeignKey(Hook, on_delete=models.CASCADE, null=True, blank=True)
symbol = models.CharField(max_length=255)
type = models.CharField(max_length=255)
symbol = models.CharField(choices=SYMBOL_CHOICES, max_length=255)
type = models.CharField(choices=TYPE_CHOICES, max_length=255)
amount = models.FloatField()
price = models.FloatField()
stop_loss = models.FloatField(null=True, blank=True)
take_profit = models.FloatField(null=True, blank=True)
exchange_id = models.CharField(max_length=255, null=True, blank=True)
status = models.CharField(max_length=255, null=True, blank=True)
direction = models.CharField(
choices=DIRECTION_CHOICES, max_length=255, null=True, blank=True
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._original = self
def save(self, *args, **kwargs):
"""
Override the save function to place the trade.
"""
if self.exchange_id is None:
# the trade is not placed yet
if self.account.exchange == "alpaca":
account = ccxt.alpaca(
{"apiKey": self.account.api_key, "secret": self.account.api_secret}
)
if self.account.sandbox:
account.set_sandbox_mode(True)
if self.type == "market":
order = account.create_order(
self.symbol, self.type, self.direction, self.amount
)
elif self.type == "limit":
params = ""
order = account.create_limit_order(
self.symbol,
self.type,
self.direction,
self.amount,
self.price,
params,
)
self.status = "filled"
else:
# there is a trade open
# get trade
# update trade
pass
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
# close the trade
super().delete(*args, **kwargs)
class Callback(models.Model):

View File

@ -0,0 +1,3 @@
TRADE DETAILS
{{ items }}
{{ status }}

View File

@ -98,7 +98,7 @@ class AccountAction(LoginRequiredMixin, APIView):
if account_id:
try:
form = AccountForm(
request.data, instance=account.objects.get(id=account_id)
request.data, instance=Account.objects.get(id=account_id)
)
except account.DoesNotExist:
message = "Account does not exist"