diff options
Diffstat (limited to 'app/trading/models.py')
-rw-r--r-- | app/trading/models.py | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/app/trading/models.py b/app/trading/models.py new file mode 100644 index 0000000..f9c9881 --- /dev/null +++ b/app/trading/models.py @@ -0,0 +1,174 @@ +import os +from PIL import Image +from django.db import models +from django.db.models.signals import post_save +from django.contrib.sitemaps import Sitemap +from django.dispatch import receiver +from django.urls import reverse +from django.apps import apps +from django.utils.html import format_html +from django.utils import timezone +from django.conf import settings +from django.template.defaultfilters import slugify + +from media.models import LuxImage, LuxImageSize +from media.utils import resize_image +from utils.util import render_images, render_products, parse_video, markdown_to_html + + +def get_upload_path(self, filename): + return "images/products/%s" % (filename) + + +class Ticker(models.Model): + symbol = models.CharField(max_length=9) + name = models.CharField(max_length=243, blank=True, null=True) + + def __str__(self): + return str(self.symbol) + + +class OptionsTrade(models.Model): + date = models.DateTimeField() + symbol = models.ForeignKey(Ticker, null=True, on_delete=models.SET_NULL) + TRANSACTION_CODE = ( + ('Trade', 'Trade'), + ) + transaction_code = models.CharField(choices=TRANSACTION_CODE, max_length=25) + TRANSACTION_SUBCODE = ( + ('Buy to Open', 'Buy to Open'), + ('Sell to Open', 'Sell to Open'), + ('Sell to Close', 'Sell to Close'), + ) + transaction_subcode = models.CharField(choices=TRANSACTION_SUBCODE, max_length=25) + BUY_SELL = ( + ('Buy', 'Buy'), + ('Sell', 'Sell'), + ) + buy_sell = models.CharField(choices=BUY_SELL, max_length=4) + OPEN_CLOSE = ( + ('Open', 'Open'), + ('Close', 'Close'), + ) + open_close = models.CharField(choices=OPEN_CLOSE, max_length=5) + quantity = models.FloatField() + expiration_date = models.DateTimeField() + strike = models.FloatField() + CALL_PUT = ( + ('C', 'Call'), + ('P', 'Put'), + ) + call_put = models.CharField(choices=CALL_PUT, max_length=4) + price = models.FloatField() + fees = models.FloatField() + amount = models.FloatField() + description = models.TextField(blank=True) + + def __str__(self): + return str(self.symbol) + + def get_profit_by_symbol(self,t): + buy_amount = 0 + sell_amount = 0 + for o in OptionsTrade.objects.filter(symbol__symbol=t).filter(buy_sell="Sell"): + sell_amount+=o.amount+o.fees + for o in OptionsTrade.objects.filter(symbol__symbol=t).filter(buy_sell="Buy"): + buy_amount+=o.amount+o.fees + return buy_amount+sell_amount + + def get_profit(self): + buy_amount = 0 + sell_amount = 0 + for o in OptionsTrade.objects.filter(buy_sell="Sell"): + sell_amount+=o.amount+o.fees + for o in OptionsTrade.objects.filter(buy_sell="Buy"): + buy_amount+=o.amount+o.fees + return buy_amount+sell_amount + +class LuxTrade(models.Model): + symbol = models.CharField(max_length=256) + date = models.DateTimeField(auto_now_add=True) + close_date = models.DateTimeField(null=True, blank=True) + open_date = models.DateTimeField(null=True, blank=True) + entry_price = models.FloatField() + stop_price = models.FloatField() + target_price = models.FloatField() + close_price = models.FloatField(null=True, blank=True) + shares = models.FloatField() + STATUS = ( + (0, 'Open'), + (1, 'Closed'), + (2, 'Watching'), + ) + status = models.IntegerField(choices=STATUS, default=2) + + def __str__(self): + return str(self.symbol) + + def get_absolute_url(self): + return reverse('luxtrade:detail', kwargs={"pk": self.pk}) + + @property + def risk_reward(self): + if self.stop_price > self.entry_price: + return "No risk" + else: + return (self.entry_price - self.stop_price)/(self.target_price-self.entry_price) + + @property + def goal_dollars(self): + return (self.target_price*self.shares)-(self.entry_price*self.shares) + + @property + def goal_percent(self): + return round((((self.target_price*self.shares)-(self.entry_price*self.shares))/self.amount_invested)*100, 2) + + @property + def risk_dollars(self): + if self.stop_price > self.entry_price: + return 0 + else: + return round((self.entry_price-self.stop_price)*self.shares, 2) + + @property + def amount_invested(self): + return round(self.entry_price * self.shares, 2) + + @property + def realized_dollars(self): + return (self.close_price*self.shares)-(self.entry_price*self.shares) + + @property + def realized_percent(self): + return (self.realized_dollars/self.amount_invested)*100 + + def save(self, *args, **kwargs): + if self.status == 0 and not self.open_date: + self.open_date = timezone.now() + super(LuxTrade, self).save() + +class TradeJrnl(models.Model): + date = models.DateTimeField(auto_now_add=True) + body_markdown = models.TextField(blank=True) + body_html = models.TextField(null=True, blank=True) + + def __str__(self): + return str(self.date) + + @property + def get_previous_admin_url(self): + n = self.get_previous_by_read_date() + return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=[n.id]) + + @property + def get_next_admin_url(self): + model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name) + try: + return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=[self.get_next_by_read_date().pk]) + except model.DoesNotExist: + return '' + + def save(self, *args, **kwargs): + md = render_images(self.body_markdown) + self.body_html = markdown_to_html(md) + super(TradeJrnl, self).save() |