Begin implementing trade management
This commit is contained in:
parent
e2a697dcc1
commit
5279217324
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,5 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
import ccxt
|
||||||
import stripe
|
import stripe
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
|
@ -67,11 +68,16 @@ class User(AbstractUser):
|
||||||
|
|
||||||
|
|
||||||
class Account(models.Model):
|
class Account(models.Model):
|
||||||
|
EXCHANGE_CHOICES = (
|
||||||
|
("binance", "Binance"),
|
||||||
|
("alpaca", "Alpaca"),
|
||||||
|
)
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
name = models.CharField(max_length=255)
|
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_key = models.CharField(max_length=255)
|
||||||
api_secret = models.CharField(max_length=255)
|
api_secret = models.CharField(max_length=255)
|
||||||
|
sandbox = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
|
||||||
class Session(models.Model):
|
class Session(models.Model):
|
||||||
|
@ -90,14 +96,71 @@ class Hook(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Trade(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)
|
account = models.ForeignKey(Account, on_delete=models.CASCADE)
|
||||||
hook = models.ForeignKey(Hook, on_delete=models.CASCADE, null=True, blank=True)
|
hook = models.ForeignKey(Hook, on_delete=models.CASCADE, null=True, blank=True)
|
||||||
symbol = models.CharField(max_length=255)
|
symbol = models.CharField(choices=SYMBOL_CHOICES, max_length=255)
|
||||||
type = models.CharField(max_length=255)
|
type = models.CharField(choices=TYPE_CHOICES, max_length=255)
|
||||||
amount = models.FloatField()
|
amount = models.FloatField()
|
||||||
price = models.FloatField()
|
price = models.FloatField()
|
||||||
stop_loss = models.FloatField(null=True, blank=True)
|
stop_loss = models.FloatField(null=True, blank=True)
|
||||||
take_profit = 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):
|
class Callback(models.Model):
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
TRADE DETAILS
|
||||||
|
{{ items }}
|
||||||
|
{{ status }}
|
|
@ -98,7 +98,7 @@ class AccountAction(LoginRequiredMixin, APIView):
|
||||||
if account_id:
|
if account_id:
|
||||||
try:
|
try:
|
||||||
form = AccountForm(
|
form = AccountForm(
|
||||||
request.data, instance=account.objects.get(id=account_id)
|
request.data, instance=Account.objects.get(id=account_id)
|
||||||
)
|
)
|
||||||
except account.DoesNotExist:
|
except account.DoesNotExist:
|
||||||
message = "Account does not exist"
|
message = "Account does not exist"
|
||||||
|
|
Loading…
Reference in New Issue