summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlxf <sng@luxagraf.net>2022-01-06 10:28:50 -0500
committerlxf <sng@luxagraf.net>2022-01-06 10:28:50 -0500
commit1b74c74fb154385d861d8a74feca75826d1c8a4b (patch)
tree09a7e8b5edf87815147625df521430df4602fea8
parent66b01525e454369aacaa5bd42c791aa261878562 (diff)
trad: added monthly and yearly options stats plus color to tables
-rw-r--r--app/trading/models.py186
-rw-r--r--app/trading/templates/trading/list.html29
-rw-r--r--app/trading/views.py6
3 files changed, 134 insertions, 87 deletions
diff --git a/app/trading/models.py b/app/trading/models.py
index d96970f..10aaaf4 100644
--- a/app/trading/models.py
+++ b/app/trading/models.py
@@ -205,90 +205,6 @@ class LuxOptionsTradeStatsManager(models.Manager):
return self.filter(close_date__range=(start_date, end_date)).aggregate(Sum('pl'))
-class LuxOptionPurchase(models.Model):
- symbol = models.CharField(max_length=256)
- open_date = models.DateTimeField(auto_now_add=True)
- close_date = models.DateTimeField(null=True, blank=True)
- pl = models.FloatField(null=True, blank=True)
- STATUS = (
- (0, 'Open'),
- (1, 'Closed'),
- )
- status = models.IntegerField(choices=STATUS, default=0)
-
- class Meta:
- ordering = ('-open_date',)
- get_latest_by = 'open_date'
-
- def __str__(self):
- return str(self.symbol)
-
- def get_absolute_url(self):
- return reverse('luxtrade:option-update', kwargs={"pk": self.pk})
-
- def get_contract_count(self):
- return self.luxoptioncontract_set.count()
-
- def profit_loss(self):
- total = 0
- for option in self.luxoptioncontract_set.all():
- if option.contract_close_price:
- pl = option.contract_close_price - option.contract_open_price
- else:
- pl = 0
- total = total + pl
- return total*100
-
- @property
- def stop_price(self):
- return (self.contract_price*.75)
-
- @property
- def total_invested(self):
- return round(self.get_contract_count()*(self.luxoptioncontract_set.first().contract_open_price*100))
-
- @property
- def trade_risk(self):
- return round(self.total_invested*.25)
-
- @property
- def portfolio_risk(self):
- return (self.trade_risk/10000)*100
-
- @property
- def sell_half_at(self):
- return self.luxoptioncontract_set.first().contract_open_price*1.25
-
- @property
- def contract_price(self):
- return self.luxoptioncontract_set.first().contract_open_price
-
- def save(self, *args, **kwargs):
- if self.status == 1 and not self.close_date:
- self.close_date = timezone.now()
- if self.status == 1 and not self.pl:
- pass
- #self.pl = round((self.close_price*self.shares)-(self.entry_price*self.shares), 2)
- super(LuxOptionPurchase, self).save()
-
-
-class LuxOptionContract(models.Model):
- symbol = models.CharField(max_length=256)
- strike_price = models.FloatField()
- expiration_date = models.DateField()
- contract_open_price = models.FloatField()
- contract_close_price = models.FloatField(null=True, blank=True)
- CALL_PUT = (
- (0, 'Calls'),
- (1, 'Puts'),
- )
- call_put = models.IntegerField(choices=CALL_PUT, default=0)
- options_purchase = models.ForeignKey(LuxOptionPurchase, null=True, on_delete=models.SET_NULL)
-
- def __str__(self):
- return "%s - %s %s" %(self.symbol, round(self.strike_price), self.get_call_put_display())
-
-
class LuxOptionsTrade(models.Model):
symbol = models.CharField(max_length=256)
date = models.DateTimeField(auto_now_add=True)
@@ -432,3 +348,105 @@ class TradeJrnl(models.Model):
md = render_images(self.body_markdown)
self.body_html = markdown_to_html(md)
super(TradeJrnl, self).save()
+
+
+class LuxOptionsPurchaseStatsManager(models.Manager):
+
+ def get_month_pl(self, month=timezone.now().month):
+ last_day = calendar.monthrange(timezone.now().year, month)[1]
+ start_date = datetime.date(timezone.now().year, month, 1)
+ end_date = datetime.date(timezone.now().year, month, last_day)
+ return self.filter(close_date__range=(start_date, end_date)).aggregate(Sum('pl'))
+
+ def get_year_pl(self, year=timezone.now().year):
+ start_date = datetime.date(year, 1, 1)
+ end_date = datetime.date(year, 12, 31)
+ return self.filter(close_date__range=(start_date, end_date)).aggregate(Sum('pl'))
+
+
+class LuxOptionPurchase(models.Model):
+ symbol = models.CharField(max_length=256)
+ open_date = models.DateTimeField(auto_now_add=True)
+ close_date = models.DateTimeField(null=True, blank=True)
+ pl = models.FloatField(null=True, blank=True)
+ STATUS = (
+ (0, 'Open'),
+ (1, 'Closed'),
+ )
+ status = models.IntegerField(choices=STATUS, default=0)
+
+ class Meta:
+ ordering = ('-open_date',)
+ get_latest_by = 'open_date'
+
+ objects = models.Manager() # The default manager.
+ stats = LuxOptionsPurchaseStatsManager()
+
+ def __str__(self):
+ return str(self.symbol)
+
+ def get_absolute_url(self):
+ return reverse('luxtrade:option-update', kwargs={"pk": self.pk})
+
+ def get_contract_count(self):
+ return self.luxoptioncontract_set.count()
+
+ def profit_loss(self):
+ total = 0
+ for option in self.luxoptioncontract_set.all():
+ if option.contract_close_price:
+ pl = option.contract_close_price - option.contract_open_price
+ else:
+ pl = 0
+ total = total + pl
+ return total*100
+
+ @property
+ def stop_price(self):
+ return (self.contract_price*.75)
+
+ @property
+ def total_invested(self):
+ return round(self.get_contract_count()*(self.luxoptioncontract_set.first().contract_open_price*100))
+
+ @property
+ def trade_risk(self):
+ return round(self.total_invested*.25)
+
+ @property
+ def portfolio_risk(self):
+ return (self.trade_risk/10000)*100
+
+ @property
+ def sell_half_at(self):
+ return self.luxoptioncontract_set.first().contract_open_price*1.25
+
+ @property
+ def contract_price(self):
+ return self.luxoptioncontract_set.first().contract_open_price
+
+ def save(self, *args, **kwargs):
+ if self.status == 1 and not self.close_date:
+ self.close_date = timezone.now()
+ if self.status == 1 and not self.pl:
+ self.pl = self.profit_loss
+ super(LuxOptionPurchase, self).save()
+
+
+class LuxOptionContract(models.Model):
+ symbol = models.CharField(max_length=256)
+ strike_price = models.FloatField()
+ expiration_date = models.DateField()
+ contract_open_price = models.FloatField()
+ contract_close_price = models.FloatField(null=True, blank=True)
+ CALL_PUT = (
+ (0, 'Calls'),
+ (1, 'Puts'),
+ )
+ call_put = models.IntegerField(choices=CALL_PUT, default=0)
+ options_purchase = models.ForeignKey(LuxOptionPurchase, null=True, on_delete=models.SET_NULL)
+
+ def __str__(self):
+ return "%s - %s %s" %(self.symbol, round(self.strike_price), self.get_call_put_display())
+
+
diff --git a/app/trading/templates/trading/list.html b/app/trading/templates/trading/list.html
index a8a0a01..d89504a 100644
--- a/app/trading/templates/trading/list.html
+++ b/app/trading/templates/trading/list.html
@@ -37,7 +37,7 @@
<td>{{object.portfolio_risk|floatformat:2}}%</td>
<td>${{object.sell_half_at|floatformat:2}}</td>
<td>${{object.stop_price|floatformat:2}}</td>
- <td>${{object.profit_loss|floatformat:2}}</td>
+ <td {%if object.profit_loss > 0 %}class="money"{%elif object.profit_loss < 0 %}class="nomoney"{%endif%}>${{object.profit_loss|floatformat:2}}</td>
<td class="notes">
{% if object.notes %}
<div class="wrapper">
@@ -50,6 +50,33 @@
</td>{% endif %}
</tr>
{% endfor %}
+ <tr>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td>{{month}} P/L:</td>
+ <td>{{monthly_pl.pl__sum}}</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td>YTD P/L:</td>
+ <td>{{year_pl.pl__sum}}</td>
+ <td></td>
+ </tr>
</table>
{% comment %}
<h3>Options Trades</h3>
diff --git a/app/trading/views.py b/app/trading/views.py
index 69e1ace..982fb8f 100644
--- a/app/trading/views.py
+++ b/app/trading/views.py
@@ -20,8 +20,10 @@ class LuxTradeListView(PaginatedListView):
context['options_trades_closed'] = LuxOptionsTrade.objects.filter(status=1)
context['monthly_pl'] = LuxTrade.stats.get_month_pl()
context['year_pl'] = LuxTrade.stats.get_year_pl()
- context['options_monthly_pl'] = LuxOptionsTrade.stats.get_month_pl()
- context['options_year_pl'] = LuxOptionsTrade.stats.get_year_pl()
+ #context['options_monthly_pl'] = LuxOptionsTrade.stats.get_month_pl()
+ #context['options_year_pl'] = LuxOptionsTrade.stats.get_year_pl()
+ context['options_monthly_pl'] = LuxOptionPurchase.stats.get_month_pl()
+ context['options_year_pl'] = LuxOptionPurchase.stats.get_year_pl()
context['month'] = datetime.now().strftime('%h')
context['luxoptions_purchases'] = LuxOptionPurchase.objects.filter(status=0)
return context