def form_valid(self, form): exclude = form.cleaned_data["excluded_stocks"] n_days = form.cleaned_data["n_days"] algo = form.cleaned_data["method"] portfolio_cost = form.cleaned_data["portfolio_cost"] exclude_price = form.cleaned_data.get("exclude_price", None) max_stocks = form.cleaned_data.get("max_stocks", 80) stocks = self.stocks() if exclude is not None: if isinstance(exclude, str): exclude = exclude.split(",") stocks = set(stocks).difference(exclude) if form.cleaned_data["exclude_etfs"]: stocks = set(stocks).difference(all_etfs()) print(f"After excluding ETFs: {len(stocks)} stocks remain") self.timeframe = Timeframe(past_n_days=n_days) self.results = optimise_portfolio( stocks, self.timeframe, algo=algo, max_stocks=max_stocks, total_portfolio_value=portfolio_cost, exclude_price=exclude_price, warning_cb=lambda msg: warning(self.request, msg), returns_by=form.cleaned_data.get("returns_by", None), ) return render(self.request, self.template_name, self.get_context_data())
def get_dataset(dataset_wanted, request, timeframe=None): assert (dataset_wanted in set(["market_sentiment", "eps-per-sector"]) or dataset_wanted.startswith("kmeans-") or dataset_wanted.startswith("financial-metrics-") or dataset_wanted.startswith("stock-quotes-")) if timeframe is None: timeframe = Timeframe(past_n_days=300) if dataset_wanted == "market_sentiment": df = cached_all_stocks_cip(timeframe) return df elif dataset_wanted == "kmeans-watchlist": _, _, _, _, df = make_kmeans_cluster_dataframe( timeframe, 7, user_watchlist(request.user)) return df elif dataset_wanted == "kmeans-etfs": _, _, _, _, df = make_kmeans_cluster_dataframe(timeframe, 7, all_etfs()) return df elif dataset_wanted.startswith("stock-quotes-"): stock = dataset_wanted[len("stock-quotes-"):] validate_stock(stock) df = company_prices([stock], timeframe=timeframe, fields=all_stock_fundamental_fields, missing_cb=None) df['stock_code'] = stock return df elif dataset_wanted.startswith("kmeans-sector-"): sector_id = int(dataset_wanted[14:]) sector = Sector.objects.get(sector_id=sector_id) if sector is None or sector.sector_name is None: raise Http404("No stocks associated with sector") asx_codes = all_sector_stocks(sector.sector_name) _, _, _, _, df = make_kmeans_cluster_dataframe(timeframe, 7, asx_codes) return df elif dataset_wanted.startswith("financial-metrics-"): stock = dataset_wanted[len("financial-metrics-"):] validate_stock(stock) df = financial_metrics(stock) if df is not None: # excel doesnt support timezones, so we remove it first colnames = [d.strftime("%Y-%m-%d") for d in df.columns] df.columns = colnames # FALLTHRU return df elif dataset_wanted == "eps-per-sector": df, _ = pe_trends_df(Timeframe(past_n_days=180)) df = make_pe_trends_eps_df(df, stocks_by_sector()) df = df.set_index("asx_code", drop=True) return df else: raise ValueError("Unsupported dataset {}".format(dataset_wanted))
def show_etfs(request): validate_user(request.user) matching_codes = all_etfs() extra_context = { "title": "Exchange Traded funds over past 300 days", "sentiment_heatmap_title": "Sentiment for ETFs", } return show_companies( matching_codes, request, Timeframe(), extra_context, )
def stocks(self): return sorted(all_etfs())
def cluster_stocks_view(request, stocks: str): """ ref: https://pythonforfinance.net/2018/02/08/stock-clusters-using-k-means-algorithm-in-python/ """ validate_user(request.user) timeframe = Timeframe(past_n_days=300) if stocks == "watchlist": asx_codes = user_watchlist(request.user) elif stocks == "etfs": asx_codes = all_etfs() elif stocks.startswith("sector-"): sector_id = int(stocks[7:]) sector = Sector.objects.get(sector_id=sector_id) if sector is None or sector.sector_name is None: raise Http404("No stocks associated with sector") asx_codes = all_sector_stocks(sector.sector_name) else: raise Http404("Unknown stock list {}".format(stocks)) chosen_k = 7 # often a reasonable tradeoff def elbow_curve_plot(ld: LazyDictionary): distortion, _, _, _, _ = make_kmeans_cluster_dataframe( timeframe, chosen_k, asx_codes ) fig = plt.figure(figsize=(15, 5)) plt.plot(range(2, 20), distortion) plt.grid(True) plt.title("Elbow curve") return fig def cluster_plot(ld: LazyDictionary): _, _, centroids, idx, data_df = make_kmeans_cluster_dataframe( timeframe, chosen_k, asx_codes ) centroids_df = pd.DataFrame.from_records( centroids, columns=["return", "volatility"] ) plot = ( p9.ggplot( data_df, p9.aes("return", "volatility", colour="factor(cluster_id)") ) + p9.geom_point(size=3) + p9.facet_wrap("~cluster_id", ncol=3, scales="free") ) return user_theme( plot, x_axis_label="Returns (%)", y_axis_label="Volatility (%)", figure_size=(15, 15), subplots_adjust={"hspace": 0.15, "wspace": 0.15}, ) stocks_as_str = "-".join(sorted(asx_codes)) elbow_curve_uri = cache_plot( f"{request.user.username}-cluster-{stocks_as_str}-elbow-curve-plot", elbow_curve_plot, ) cluster_uri = cache_plot( f"{request.user.username}-cluster-{stocks_as_str}-kmeans-cluster-plot", cluster_plot, ) context = { "elbow_curve_plot_uri": elbow_curve_uri, "k": chosen_k, "dataset": stocks, "n_stocks": len(asx_codes), "cluster_plot_uri": cluster_uri, "timeframe": timeframe, } return render(request, "cluster_stocks.html", context=context)