Ejemplo n.º 1
0
def add(code, user):
    # Get current stock info from Finnhub API
    code = code.upper()
    api = Api()
    messages = {}
    try:
        stockinfo = api.search(code)
    except Exception as e:
        messages['error'] = str(e)
        return messages

    price = stockinfo['c']
    timestamp = stockinfo['t']

    # cache stock info if this is the first time app has encountered stock
    stocks = Stock.objects.filter(code=code)
    if (stocks.count() != 1):
        Stock.objects.create(name=stockinfo["name"], code=code)

    stock_to_add_in_wl = Stock.objects.get(code=code)
    wl = WatchListItem.objects.filter(user_id=user, stock=stock_to_add_in_wl)
    if (wl.count() != 0):
        messages['error'] = "Stock {} is already in your watchlist".format(
            code)
        return messages

    WatchListItem.objects.create(user_id=user,
                                 stock=stock_to_add_in_wl,
                                 timestamp=datetime.utcnow().timestamp())
    messages['success'] = "Stock {} added to your watchlist".format(code)

    return messages
Ejemplo n.º 2
0
def sell(code, units, user):
    code = code.upper()
    api = Api()
    messages = {}
    try:
        tgt = api.search(code)
    except Exception as e:
        messages['error'] = str(e)
        return messages
    stocks = Stock.objects.filter(code=code)
    if (stocks.count() != 1):
        Stock.objects.create(name=tgt["name"], code=code)
    st = Stock.objects.get(code=code)

    price = tgt['c']
    money = price * units

    current_units = purchases.get_total_owned_units(user, code)
    balance = user.profile.balance
    remaining_sell_units = units
    if current_units >= units:
        ps = purchases.get_unsold_purhases(user, code)
        for p in ps:
            if (remaining_sell_units == 0):
                break
            unsold_purchased_units = p.orignialUnitBought - p.unitSold
            if (unsold_purchased_units <= remaining_sell_units):
                remaining_sell_units = remaining_sell_units - unsold_purchased_units
                p.unitSold = p.orignialUnitBought
                p.save()
            else:
                p.unitSold = p.unitSold + remaining_sell_units
                p.save()
                remaining_sell_units = 0

        newBalance = balance + decimal.Decimal(float(money))
        user.profile.balance = newBalance
        user.save()
        messages[
            'success'] = "Successfully sold {} shares of Stock {} costing {}".format(
                units, code, round(money, 2))
        Transaction.objects.create(user_id=user,
                                   stock=st,
                                   units=units,
                                   price=price,
                                   action="sell")
    else:
        messages[
            'error'] = "Insufficient number of shares in Stock {} to sell {} units".format(
                code, units)
    return messages
Ejemplo n.º 3
0
class test_search(TestCase):
    def setUp(self):
        self.api = Api()

    def test_upper(self):
        assert self.api.search("AAPL") != {}

    def test_lower(self):
        assert self.api.search("aapl") != {}

    def test_invalid(self):
        assert self.api.search(
            "abcd") == "The stock code you searched was invalid"
        assert self.api.search(
            "goog") == "The stock code you searched was invalid"
Ejemplo n.º 4
0
def list_watchlist(user, messages):
    api = Api()
    result = WatchListItem.objects.filter(user_id=user)

    wlist = []

    for row in result:
        wlist_entry = {}
        code = row.stock.code
        wlist_entry['code'] = code
        wlist_entry['name'] = row.stock.name
        wlist_entry['date'] = row.date
        wlist_entry['timestamp'] = row.timestamp

        # Get current stock info from Finnhub API
        try:
            stockinfo = api.search(code)
            wlist_entry['current'] = stockinfo['c']
            wlist_entry['change'] = stockinfo['change']
        except Exception as e:
            wlist_entry['current'] = "N/A"
            wlist_entry['change'] = "N/A"
            messages['error'] = str(e)

        wlist.append(wlist_entry)

        # Get all alerts related to stock
        stock = Stock.objects.get(code=code)
        alerts_to_show = WatchListAlert.objects.filter(user_id=user,
                                                       stock=stock,
                                                       triggered=True,
                                                       shown=False)
        print(len(alerts_to_show))
        for alert in alerts_to_show:
            messages[
                f'alert at {alert.dateTriggered} for {alert.stock.code}'] = f"Stock {alert.stock.name} hit {alert.watchprice} at {alert.dateTriggered}"
            alert.shown = True
            alert.save()

        # Column for watch prices not triggered yet
        alerts_not_triggered_yet = WatchListAlert.objects.filter(
            user_id=user, stock=stock, triggered=False)
        wlist_entry['alerts'] = []
        for alert in alerts_not_triggered_yet:
            wlist_entry['alerts'].append(alert)

    return wlist, messages
Ejemplo n.º 5
0
class test_search(TestCase):
    def setUp(self):
        self.api = Api()

    def test_upper(self):
        assert self.api.search("AAPL") != {}

    def test_lower(self):
        assert self.api.search("aapl") != {}

    def test_invalid(self):
        try:
            info = self.api.search("abcd")
        except Exception as e:
            assert str(e) == "The stock code you searched was invalid"
        else:
            assert 1 == 2
Ejemplo n.º 6
0
def get_user_profit(user_id, cprice_cache):
    api = Api()
    purchases = Purchase.objects.filter(user_id=user_id,
                                        unitSold__lt=F('orignialUnitBought'))
    total_worth = 0
    for purchase in purchases:
        orignialUnitBought = purchase.orignialUnitBought
        unitSold = purchase.unitSold
        unitsOwned = orignialUnitBought - unitSold
        if purchase.stock.code not in cprice_cache.keys():
            stockinfo = api.search(purchase.stock.code)
            cprice_cache[purchase.stock.code] = stockinfo['c']
        current_price = cprice_cache[purchase.stock.code]
        purchase_worth = round(unitsOwned * current_price, 2)
        total_worth = total_worth + purchase_worth

    return round(total_worth, 2), cprice_cache
Ejemplo n.º 7
0
def buy(code, units, user):
    code = code.upper()
    api = Api()
    messages = {}
    try:
        tgt = api.search(code)
    except Exception as e:
        messages['error'] = str(e)
        return messages
    stocks = Stock.objects.filter(code=code)
    if (stocks.count() != 1):
        Stock.objects.create(name=tgt["name"], code=code)
    st = Stock.objects.get(code=code)
    price = tgt['c']
    price = decimal.Decimal(float(price))
    money = price * units

    balance = user.profile.balance
    if balance >= money:
        newBalance = balance - money
        user.profile.balance = newBalance
        user.save()
        Purchase.objects.create(user_id=user,
                                stock=st,
                                price=price,
                                orignialUnitBought=units,
                                unitSold=0)
        Transaction.objects.create(user_id=user,
                                   stock=st,
                                   units=units,
                                   price=price,
                                   action="buy")
        messages[
            'success'] = "Successfully bought {} shares of Stock {} costing {}".format(
                units, code, round(money, 2))
    else:
        messages[
            'error'] = "Insufficient funds in balance for buying {} units of Stock {} for ${}".format(
                units, code, round(money, 2))
    return messages
Ejemplo n.º 8
0
def get_purchases_info(user_id, include_sold):
    api = Api()
    if include_sold:
        purchases = Purchase.objects.filter(
            user_id=user_id).order_by('dateBought')
    else:
        purchases = Purchase.objects.filter(
            user_id=user_id,
            unitSold__lt=F('orignialUnitBought')).order_by('dateBought')
    cprice_cache = {}
    purchase_summary = []
    messages = {}
    for purchase in purchases:
        summary_entry = {}
        summary_entry['code'] = purchase.stock.code
        summary_entry['dateBought'] = purchase.dateBought
        summary_entry['price'] = purchase.price
        summary_entry['orignialUnitBought'] = purchase.orignialUnitBought
        summary_entry['unitsSold'] = purchase.unitSold
        summary_entry[
            'unitsOwned'] = purchase.orignialUnitBought - purchase.unitSold
        summary_entry[
            'paid'] = summary_entry['unitsOwned'] * summary_entry['price']
        if purchase.stock.code not in cprice_cache.keys():
            try:
                stockinfo = api.search(purchase.stock.code)
            except Exception as e:
                messages['error'] = str(e)
                return [], messages
            # Add api result to cache
            cprice_cache[purchase.stock.code] = stockinfo['c']
        summary_entry['c'] = cprice_cache[purchase.stock.code]
        summary_entry[
            'worth'] = summary_entry['unitsOwned'] * summary_entry['c']
        summary_entry['profit'] = round(
            float(summary_entry['worth']) - float(summary_entry['paid']), 2)
        summary_entry['timestamp'] = purchase.dateBought
        purchase_summary.append(summary_entry)

    return purchase_summary, messages
def search_view(request):

    if ("code" in request.GET):
        messages = {}
        api = Api()
        code = request.GET.get('code')

        try:
            result = api.search(code)
        except Exception as e:
            messages['error'] = str(e)
            search_info = {'messages': messages}
        else:
            search_info = result
        finally:
            return render(request, 'simulator/search.html', search_info)

    return render(request, 'simulator/search.html')
Ejemplo n.º 10
0
def stock_detail(request, code):
    stockObj = Stock.objects.get(code=code)
    api = Api()
    stockinfo = api.search(code)
    stock = {}
    stock['code'] = stockObj.code
    stock['name'] = stockObj.name
    stock['current'] = stockinfo['c']
    stock['change'] = stockinfo['change']
    stock['alerts'] = []
    alerts_not_triggered_yet = WatchListAlert.objects.filter(user_id=request.user, stock=stockObj, triggered=False)
    if alerts_not_triggered_yet.count() == 0:
        stock['alert'] = "No alerts to display"
    else:
        stock['alert'] = ""
        for alert in alerts_not_triggered_yet:
            stock['alerts'].append(alert)

    return render(request, 'simulator/stock_detail.html', {'stock': stock})
Ejemplo n.º 11
0
 def setUp(self):
     self.api = Api()
Ejemplo n.º 12
0
 def __init__(self):
     self.api = Api()
Ejemplo n.º 13
0
class Watchprice:
    def __init__(self):
        self.api = Api()

    '''
    Method used to check if a given watch price alert has been trigged.

    parameters
        alertId : WatchListAlert model ID field
    '''

    def check(self, alertId):
        while True:
            time.sleep(10)
            try:
                alert = WatchListAlert.objects.get(id=alertId)
                if alert.triggered:
                    return
                code = alert.stock.code
                action = alert.action
                current_price = self.api.search(code)['c']
                if action == "sell":
                    # current price is greater than or equal to watchprice
                    if current_price >= alert.watchprice:
                        # frontend - add new notification
                        alert.dateTriggered = datetime.now().isoformat(
                            ' ', 'seconds')
                        # db - set flag to true
                        alert.triggered = True
                        alert.save()
                        return
                elif action == "buy":
                    # current price is less than or equal to watchprice
                    if current_price <= alert.watchprice:
                        # frontend - add new notification
                        alert.dateTriggered = datetime.now().isoformat(
                            ' ', 'seconds')
                        # db - set flag to true
                        alert.triggered = True
                        alert.save()
                        return
            except:
                # ID cant be found exception because watch price was deleted. End thread
                return

    '''
    Method used to set a watchprice of a given stock. Watchprices with a "buy" action are triggered 
    when the current price is below the watch price (buy low), whereas watchprices with a "sell" action 
    are triggered when the current price is above the watch price (sell high).

    parameters
        code : string
        price : float
        user : User model
        action : string ("buy" or "sell")
    returns
        messages : {string : string}
    '''

    def set(self, code, price, user, action):
        stock = Stock.objects.get(code=code)
        alert = WatchListAlert.objects.create(user_id=user,
                                              stock=stock,
                                              watchprice=price,
                                              action=action)
        messages = {}
        messages[
            'watchprice_set'] = f"Successfully set trigger to {action} stock {code} at watch price {price}"

        alertId = alert.pk

        th = threading.Thread(target=self.check, args=(alertId, ))
        th.start()

        print("Returning messages")

        return messages

    '''
    Starts the threads which will monitor the watchprices by with the check method
    '''

    def start_up(self):
        alerts = WatchListAlert.objects.filter(triggered=False)
        for alert in alerts:
            th = threading.Thread(target=self.check, args=(alert.id, ))
            th.start()

    '''
    Removes a given watch price

    parameters
        user : User model
        alert : WatchListAlert model
    returns
        messages : {string : string}
    '''

    def remove(self, user, alert):
        alert_obj = WatchListAlert.objects.get(user_id=user, id=alert)

        code = alert_obj.stock.code
        price = alert_obj.watchprice
        messages = {}
        messages[
            'removed_wp'] = "Watchprice {} of stock {} has been removed from your watchlist".format(
                price, code)
        alert_obj.delete()

        return messages