Source code for tickers.models

# -*- coding: UTF-8 -*-
# models.py
#
# Copyright (C) 2014 HES-SO//HEG Arc
#
# Author(s): Cédric Gaspoz <cedric.gaspoz@he-arc.ch>
#
# This file is part of MarMix.
#
# MarMix is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# MarMix is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MarMix. If not, see <http://www.gnu.org/licenses/>.

# Stdlib imports
import datetime

# Core Django imports
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.cache import cache
from django.utils import timezone

# Third-party app imports
from django_extensions.db.models import TimeStampedModel

# MarMix imports
from simulations.models import Simulation


[docs]class Ticker(TimeStampedModel): simulation = models.OneToOneField(Simulation, verbose_name=_("simulation"), help_text=_("Related simulation")) nb_companies = models.IntegerField(verbose_name=_("number of companies"), null=True, blank=True, help_text=_("Number of real/simulated companies")) initial_value = models.IntegerField(verbose_name=_("initial value of companies"), default="100", help_text=_("Initial value of the companies (discounted cash flow). The exact value is randomized.")) state = models.IntegerField(verbose_name=_("state of the ticker"), choices=Simulation.SIMULATION_STATE_CHOICES, default=Simulation.CONFIGURING, help_text=_("Current state of this ticker")) with_drift = models.BooleanField(verbose_name=_("display the drift"), default=False, help_text=_("Advanced simulations display the drift")) nb_rounds = models.IntegerField(verbose_name=_("number of rounds"), default="4", help_text=_("Number of simulation rounds")) nb_days = models.IntegerField(verbose_name=_("number of days per round"), default="10", help_text=_("Number of days in a simulation round")) day_duration = models.IntegerField(verbose_name=_("duration of a day"), default="60", help_text=_("Duration of each simulation day in seconds")) dividend_payoff_rate = models.DecimalField(verbose_name=_("dividend payoff rate"), max_digits=14, decimal_places=4, default='30.0000', help_text=_("Payoff rate in percent. To disable dividend payoff, set to 0.00")) transaction_costs = models.DecimalField(verbose_name=_("transaction cost"), max_digits=14, decimal_places=4, default='5.5000', help_text=_("Amount to be paid for one transaction. To disable transaction costs, set to 0.00")) interest_rate = models.DecimalField(verbose_name=_("interest rate"), max_digits=14, decimal_places=4, default='3.0000', help_text=_("Interest rate retributing portfolios. To disable retribution of cash, set to 0.00")) fixed_interest_rate = models.BooleanField(verbose_name=_("fixed interest rate"), default=False, help_text=_("If fixed, the interest rate will not vary accross time")) # TODO: Add fields needed for the live simulation class Meta: verbose_name = _('ticker') verbose_name_plural = _('tickers') ordering = ['simulation'] def _last_tick(self): tick = cache.get('tick-%s' % self.simulation_id) if tick: last_tick = tick else: try: last_tick = self.ticks.all()[0] except IndexError: last_tick = None return last_tick last_tick = property(_last_tick) def save(self, *args, **kwargs): if self.simulation_id: cache.delete('ticker-%s' % self.simulation_id) super(Ticker, self).save(*args, **kwargs) def __str__(self): return self.simulation.__str__()
[docs]class TickerStock(TimeStampedModel): """ Stocks are shares of a company that are automatically generated during the simulation setup. """ ticker = models.ForeignKey('Ticker', verbose_name=_("ticker"), related_name="stocks", help_text=_("Related ticker")) symbol = models.CharField(verbose_name=_("symbol"), max_length=4, help_text=_("Symbol of the stock (4 chars)")) name = models.CharField(verbose_name=_("name"), max_length=100, help_text=_("Full name of the stock")) description = models.TextField(verbose_name=_("description"), blank=True, help_text=_("Description of the stock (HTML)")) quantity = models.IntegerField(verbose_name=_("quantity"), default=1, help_text=_("Total quantity of stocks in circulation")) #next_price = models.DecimalField(verbose_name=_("next stock price"), max_digits=14, decimal_places=4, # default='0.0000', help_text=_("Next stock price")) #drift = models.IntegerField(verbose_name=_("next stock price"), # default='0.0000', help_text=_("Next stock price")) class Meta: verbose_name = _('stock') verbose_name_plural = _('stocks') ordering = ['symbol'] def _last_quote(self): try: last_quote = self.quotes.all()[0] except IndexError: last_quote = None return last_quote last_quote = property(_last_quote) def __str__(self): return self.symbol
[docs]class TickerQuote(models.Model): """ Quotes are the price of a given stock at a certain time. """ stock = models.ForeignKey('TickerStock', verbose_name=_("stock"), related_name="quotes", help_text=_("Related stock")) price = models.DecimalField(verbose_name=_("stock price"), max_digits=14, decimal_places=4, default='0.0000', help_text=_("Current stock price")) timestamp = models.DateTimeField(verbose_name=_("timestamp"), auto_now_add=True, help_text=_("Timestamp of the quote")) class Meta: verbose_name = _('quote') verbose_name_plural = _('quotes') ordering = ['-timestamp'] def __str__(self): return "%s - %s (%s)" % (self.stock, self.price, self.timestamp)
[docs]class TickerTick(models.Model): """ Stocks are shares of a company that are automatically generated during the simulation setup. """ ticker = models.ForeignKey('Ticker', verbose_name=_("ticker"), related_name="ticks", help_text=_("Related ticker")) timestamp = models.DateTimeField(verbose_name=_("timestamp"), auto_now_add=True, help_text=_("Timestamp of the tick")) sim_round = models.IntegerField(verbose_name=_("round"), default=0, help_text=_("Current round")) sim_day = models.IntegerField(verbose_name=_("day"), default=0, help_text=_("Current day")) class Meta: verbose_name = _('tick') verbose_name_plural = _('ticks') ordering = ['-timestamp'] def __str__(self): return "R%s/D%s" % (self.sim_round, self.sim_day) def save(self, *args, **kwargs): tick = {'ticker': self.ticker_id, 'timestamp': self.timestamp, 'sim_round': self.sim_round, 'sim_day': self.sim_day} cache.set('tick-%s' % self.ticker_id, tick)