Пример #1
0
 def render_to_response(self, context):
     qs = context['paginator'].object_list.all(
     )  # all() to get a fresh queryset instance
     qs = list(qs.values_list('asx_code', flat=True))
     if len(qs) == 0:
         warning(self.request, "No stocks to report")
         sentiment_data, df, top10, bottom10, n_stocks = (None, None, None,
                                                          None, 0)
     else:
         sentiment_data, df, top10, bottom10, n_stocks = plot_heatmap(
             qs, n_top_bottom=self.n_top_bottom)
     context.update({
         'most_recent_date':
         self.as_at_date,
         'sentiment_heatmap':
         sentiment_data,
         'watched':
         user_watchlist(
             self.request.user),  # to ensure bookmarks are correct
         'n_top_bottom':
         self.n_top_bottom,
         'best_ten':
         top10,
         'worst_ten':
         bottom10,
         'title':
         'Find by dividend yield or P/E',
         'sentiment_heatmap_title':
         "Recent sentiment: {} total stocks".format(n_stocks),
     })
     add_messages(self.request, context)
     return super().render_to_response(context)
Пример #2
0
 def render_to_response(self, context):
     context.update(self.template_values_dict)
     context.update({ # NB: we use update() to not destroy page_obj
         'watched': user_watchlist(self.request.user), # to highlight top10/bottom10 bookmarks correctly
         'title': 'Find by company sector',
     })
     assert context['sector_id'] is not None and isinstance(
         context['sector_id'], int)
     context['sentiment_heatmap_title'] = "{}: past {} days".format(
         context['sector_name'], context['n_days'])
     add_messages(self.request, context)
     return super().render_to_response(context)
Пример #3
0
def show_matching_companies(matching_companies,
                            title,
                            heatmap_title,
                            user_purchases,
                            request,
                            extra_context=None):
    """
    Support function to public-facing views to eliminate code redundancy
    """
    assert len(matching_companies) > 0
    assert isinstance(title, str) and isinstance(heatmap_title, str)

    stocks_queryset, date = latest_quote(matching_companies)
    stocks_queryset = stocks_queryset.order_by('asx_code')
    print("Found {} quotes for {} stocks".format(stocks_queryset.count(),
                                                 len(matching_companies)))

    # paginate results for 50 stocks per page
    paginator = Paginator(stocks_queryset, 50)
    page_number = request.GET.get('page', 1)
    page_obj = paginator.page(page_number)

    # add sentiment heatmap amongst watched stocks
    n_days = 30
    n_top_bottom = 20
    sentiment_heatmap_data, df, top10, bottom10, n = \
        plot_heatmap(matching_companies, all_dates=desired_dates(start_date=n_days), n_top_bottom=n_top_bottom)

    context = {
        "most_recent_date": latest_quotation_date('ANZ'),
        "page_obj": page_obj,
        "title": title,
        "watched": user_watchlist(request.user),
        'n_top_bottom': n_top_bottom,
        "best_ten": top10,
        "worst_ten": bottom10,
        "virtual_purchases": user_purchases,
        "sentiment_heatmap": sentiment_heatmap_data,
        "sentiment_heatmap_title":
        "{}: past {} days".format(heatmap_title, n_days)
    }
    if extra_context:
        context.update(extra_context)
    add_messages(request, context)
    return render(request, 'all_stocks.html', context=context)
Пример #4
0
def show_companies(
        matching_companies, # may be QuerySet or iterable of stock codes (str)
        request,
        sentiment_timeframe: Timeframe,
        extra_context=None,
        template_name="all_stocks.html",
):
    """
    Support function to public-facing views to eliminate code redundancy
    """
    virtual_purchases_by_user = user_purchases(request.user)

    if isinstance(matching_companies, QuerySet):
        stocks_queryset = matching_companies  # we assume QuerySet is already sorted by desired criteria
    elif matching_companies is None or len(matching_companies) > 0:
        stocks_queryset, _ = latest_quote(matching_companies)
        # FALLTHRU

    # sort queryset as this will often be requested by the USER
    sort_by = tuple(request.GET.get("sort_by", "asx_code").split(","))
    info(request, "Sorting by {}".format(sort_by))
    stocks_queryset = stocks_queryset.order_by(*sort_by)

    # keep track of stock codes for template convenience
    asx_codes = [quote.asx_code for quote in stocks_queryset.all()]
    n_top_bottom = extra_context['n_top_bottom'] if 'n_top_bottom' in extra_context else 20
    print("show_companies: found {} stocks".format(len(asx_codes)))
    
    # setup context dict for the render
    context = {
        # NB: title and heatmap_title are expected to be supplied by caller via extra_context
        "timeframe": sentiment_timeframe,
        "title": "Caller must override",
        "watched": user_watchlist(request.user),
        "n_stocks": len(asx_codes),
        "n_top_bottom": n_top_bottom,
        "virtual_purchases": virtual_purchases_by_user,
    }

    # since we sort above, we must setup the pagination also...
    assert isinstance(stocks_queryset, QuerySet)
    paginator = Paginator(stocks_queryset, 50)
    page_number = request.GET.get("page", 1)
    page_obj = paginator.page(page_number)
    context['page_obj'] = page_obj
    context['object_list'] = paginator

    if len(asx_codes) <= 0:
        warning(request, "No matching companies found.")
    else:
        df = selected_cached_stocks_cip(asx_codes, sentiment_timeframe)
        sentiment_heatmap_data, top10, bottom10 = plot_heatmap(df, sentiment_timeframe, n_top_bottom=n_top_bottom)
        sector_breakdown_plot = plot_breakdown(df)
        context.update({
            "best_ten": top10,
            "worst_ten": bottom10,
            "sentiment_heatmap": sentiment_heatmap_data,
            "sentiment_heatmap_title": "{}: {}".format(context['title'], sentiment_timeframe.description),
            "sector_breakdown_plot": sector_breakdown_plot,
        })

    if extra_context:
        context.update(extra_context)
    add_messages(request, context)
    #print(context)
    return render(request, template_name, context=context)
Пример #5
0
def show_companies(
    matching_companies,  # may be QuerySet or iterable of stock codes (str)
    request,
    sentiment_timeframe: Timeframe,
    extra_context=None,
    template_name="all_stocks.html",
):
    """
    Support function to public-facing views to eliminate code redundancy
    """
    if isinstance(matching_companies, QuerySet):
        stocks_queryset = matching_companies  # we assume QuerySet is already sorted by desired criteria
    elif matching_companies is None or len(matching_companies) > 0:
        stocks_queryset, _ = latest_quote(matching_companies)
        # FALLTHRU
    else:
        # no companies to report?
        warning(request, "No matching companies.")
        return render(request,
                      template_name,
                      context={"timeframe": sentiment_timeframe})

    # prune companies without a latest price, makes no sense to report them
    stocks_queryset = stocks_queryset.exclude(last_price__isnull=True)

    # sort queryset as this will often be requested by the USER
    arg = request.GET.get("sort_by", "asx_code")
    #info(request, "Sorting by {}".format(arg))

    if arg == "sector" or arg == "sector,-eps":
        ss = {
            s["asx_code"]: s["sector_name"]
            for s in stocks_by_sector().to_dict("records")
        }
        if arg == "sector":
            stocks_queryset = sorted(stocks_queryset,
                                     key=lambda s: ss.get(s.asx_code, "Z")
                                     )  # companies without sector sort last
        else:
            eps_dict = {
                s.asx_code: s.eps if s.eps is not None else 0.0
                for s in stocks_queryset
            }
            stocks_queryset = sorted(
                stocks_queryset,
                key=lambda s:
                (ss.get(s.asx_code, "Z"), -eps_dict.get(s.asx_code, 0.0)),
            )
    else:
        sort_by = tuple(arg.split(","))
        stocks_queryset = stocks_queryset.order_by(*sort_by)

    # keep track of stock codes for template convenience
    asx_codes = [quote.asx_code for quote in stocks_queryset]
    n_top_bottom = (extra_context["n_top_bottom"]
                    if "n_top_bottom" in extra_context else 20)
    print("show_companies: found {} stocks".format(len(asx_codes)))

    # setup context dict for the render
    context = {
        # NB: title and heatmap_title are expected to be supplied by caller via extra_context
        "timeframe": sentiment_timeframe,
        "title": "Caller must override",
        "watched": user_watchlist(request.user),
        "n_stocks": len(asx_codes),
        "n_top_bottom": n_top_bottom,
        "virtual_purchases": user_purchases(request.user),
    }

    # since we sort above, we must setup the pagination also...
    # assert isinstance(stocks_queryset, QuerySet)
    paginator = Paginator(stocks_queryset, 50)
    page_number = request.GET.get("page", 1)
    page_obj = paginator.page(page_number)
    context["page_obj"] = page_obj
    context["object_list"] = paginator

    # compute totals across all dates for the specified companies to look at top10/bottom10 in the timeframe
    ld = LazyDictionary()
    ld["cip_df"] = lambda ld: selected_cached_stocks_cip(
        asx_codes, sentiment_timeframe)
    ld["sum_by_company"] = lambda ld: ld["cip_df"].sum(axis=1,
                                                       numeric_only=True)
    ld["top10"] = lambda ld: ld["sum_by_company"].nlargest(n_top_bottom)
    ld["bottom10"] = lambda ld: ld["sum_by_company"].nsmallest(n_top_bottom)
    ld["stocks_by_sector"] = lambda ld: stocks_by_sector()

    if len(asx_codes) <= 0 or len(ld["top10"]) <= 0:
        warning(request, "No matching companies found.")
    else:
        sorted_codes = "-".join(sorted(asx_codes))
        sentiment_heatmap_uri = cache_plot(
            f"{sorted_codes}-{sentiment_timeframe.description}-stocks-sentiment-plot",
            lambda ld: plot_heatmap(sentiment_timeframe, ld),
            datasets=ld,
        )

        key = f"{sorted_codes}-{sentiment_timeframe.description}-breakdown-plot"
        sector_breakdown_uri = cache_plot(key, plot_breakdown, datasets=ld)

        top10_plot_uri = cache_plot(
            f"top10-plot-{'-'.join(ld['top10'].index)}",
            lambda ld: plot_cumulative_returns(ld["top10"].index, ld),
            datasets=ld,
        )
        bottom10_plot_uri = cache_plot(
            f"bottom10-plot-{'-'.join(ld['bottom10'].index)}",
            lambda ld: plot_cumulative_returns(ld["bottom10"].index, ld),
            datasets=ld,
        )

        context.update({
            "best_ten":
            ld["top10"],
            "worst_ten":
            ld["bottom10"],
            "sentiment_heatmap_uri":
            sentiment_heatmap_uri,
            "sentiment_heatmap_title":
            "{}: {}".format(context["title"], sentiment_timeframe.description),
            "sector_breakdown_uri":
            sector_breakdown_uri,
            "top10_plot_uri":
            top10_plot_uri,
            "bottom10_plot_uri":
            bottom10_plot_uri,
            "timeframe_end_performance":
            timeframe_end_performance(ld),
        })

    if extra_context:
        context.update(extra_context)
    add_messages(request, context)
    # print(context)
    return render(request, template_name, context=context)