{ "cells": [ { "cell_type": "markdown", "id": "7a0be8d0", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "9159b91e", "metadata": {}, "source": [ "This code uses the OpenBB Terminal and Riskfolio libraries to create and optimize a financial portfolio based on historical stock data. It first screens for stocks hitting new highs, filters them, and retrieves their historical prices. It calculates the returns, uses them to create a portfolio, and applies mean-variance optimization to determine the optimal asset allocation. The results are then visualized and detailed with the number of shares to purchase based on a specified investment amount." ] }, { "cell_type": "code", "execution_count": null, "id": "ef4428e3", "metadata": {}, "outputs": [], "source": [ "from openbb_terminal.sdk import openbb, TerminalStyle\n", "theme = TerminalStyle(\"light\", \"light\", \"light\")" ] }, { "cell_type": "code", "execution_count": null, "id": "08c0afb0", "metadata": {}, "outputs": [], "source": [ "import riskfolio as rp" ] }, { "cell_type": "markdown", "id": "4f3bdc68", "metadata": {}, "source": [ "Screen for stocks hitting new highs using OpenBB Terminal." ] }, { "cell_type": "code", "execution_count": null, "id": "106cb79a", "metadata": {}, "outputs": [], "source": [ "new_highs = openbb.stocks.screener.screener_data(\"new_high\")" ] }, { "cell_type": "markdown", "id": "6a71c50c", "metadata": {}, "source": [ "Filter stocks with a price above $15 and located in the USA." ] }, { "cell_type": "code", "execution_count": null, "id": "d2f32e31", "metadata": {}, "outputs": [], "source": [ "port_data = new_highs[\n", " (new_highs.Price > 15) & (new_highs.Country == \"USA\")\n", "]" ] }, { "cell_type": "markdown", "id": "0109063b", "metadata": {}, "source": [ "Retrieve the list of ticker symbols from the filtered data." ] }, { "cell_type": "code", "execution_count": null, "id": "aea54a4d", "metadata": {}, "outputs": [], "source": [ "tickers = port_data.Ticker.tolist()" ] }, { "cell_type": "markdown", "id": "2f647c98", "metadata": {}, "source": [ "Fetch historical price data for the selected tickers from 2016-01-01 to 2022-12-31." ] }, { "cell_type": "code", "execution_count": null, "id": "5adbca4a", "metadata": {}, "outputs": [], "source": [ "data = openbb.economy.index(\n", " tickers, \n", " start_date=\"2016-01-01\", \n", " end_date=\"2022-12-31\"\n", ")" ] }, { "cell_type": "markdown", "id": "76163388", "metadata": {}, "source": [ "Calculate the daily percentage returns of the stock prices and drop columns with any NaN values." ] }, { "cell_type": "code", "execution_count": null, "id": "785d23f5", "metadata": {}, "outputs": [], "source": [ "returns = data.pct_change()[1:]\n", "returns.dropna(how=\"any\", axis=1, inplace=True)" ] }, { "cell_type": "markdown", "id": "35afdcfe", "metadata": {}, "source": [ "Create a portfolio object using the calculated returns." ] }, { "cell_type": "code", "execution_count": null, "id": "c92245e0", "metadata": {}, "outputs": [], "source": [ "port = rp.Portfolio(returns=returns)" ] }, { "cell_type": "markdown", "id": "c06747d1", "metadata": {}, "source": [ "Compute asset statistics such as historical mean and covariance." ] }, { "cell_type": "code", "execution_count": null, "id": "3ecfd866", "metadata": {}, "outputs": [], "source": [ "port.assets_stats(method_mu='hist', method_cov='hist', d=0.94)" ] }, { "cell_type": "markdown", "id": "b7b7529f", "metadata": {}, "source": [ "Set the lower return constraint for the optimization problem." ] }, { "cell_type": "code", "execution_count": null, "id": "808168b2", "metadata": {}, "outputs": [], "source": [ "port.lowerret = 0.0008" ] }, { "cell_type": "markdown", "id": "a7fed1c3", "metadata": {}, "source": [ "Perform mean-variance optimization using historical data and no risk-free rate." ] }, { "cell_type": "code", "execution_count": null, "id": "85a8ec29", "metadata": {}, "outputs": [], "source": [ "w_rp_c = port.rp_optimization(\n", " model=\"Classic\", # use historical\n", " rm=\"MV\", # use mean-variance optimization\n", " hist=True, # use historical scenarios\n", " rf=0, # set risk-free rate to 0\n", " b=None # don't use constraints\n", ")" ] }, { "cell_type": "markdown", "id": "e7df27bc", "metadata": {}, "source": [ "Plot the optimized portfolio allocation as a pie chart." ] }, { "cell_type": "code", "execution_count": null, "id": "22d9a70c", "metadata": {}, "outputs": [], "source": [ "ax = rp.plot_pie(w=w_rp_c)" ] }, { "cell_type": "markdown", "id": "78e3c04c", "metadata": {}, "source": [ "Plot the risk contributions of each asset in the portfolio." ] }, { "cell_type": "code", "execution_count": null, "id": "e3d2307b", "metadata": {}, "outputs": [], "source": [ "ax = rp.plot_risk_con(\n", " w_rp_c,\n", " cov=port.cov,\n", " returns=port.returns,\n", " rm=\"MV\",\n", " rf=0,\n", ")" ] }, { "cell_type": "markdown", "id": "e077bdaf", "metadata": {}, "source": [ "Calculate the investment amount and number of shares to purchase for each asset." ] }, { "cell_type": "code", "execution_count": null, "id": "e23ce3c7", "metadata": {}, "outputs": [], "source": [ "port_val = 10_000\n", "w_rp_c[\"invest_amt\"] = w_rp_c * port_val\n", "w_rp_c[\"last_price\"] = data.iloc[-1]\n", "w_rp_c[\"shares\"] = (w_rp_c.invest_amt / w_rp_c.last_price).astype(int)" ] }, { "cell_type": "markdown", "id": "086649c5", "metadata": {}, "source": [ "Display the optimized portfolio with investment amounts and number of shares." ] }, { "cell_type": "code", "execution_count": null, "id": "0ce0af32", "metadata": {}, "outputs": [], "source": [ "w_rp_c" ] }, { "cell_type": "markdown", "id": "4c5e18cb", "metadata": {}, "source": [ "Sort the portfolio by asset weights in ascending order." ] }, { "cell_type": "code", "execution_count": null, "id": "707e8c1f", "metadata": {}, "outputs": [], "source": [ "w_rp_c.sort_values(by=\"weights\")" ] }, { "cell_type": "markdown", "id": "ed9a0034", "metadata": {}, "source": [ "PyQuant News is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to get started with Python for quant finance. For educational purposes. Not investment advise. Use at your own risk." ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "main_language": "python", "notebook_metadata_filter": "-all" } }, "nbformat": 4, "nbformat_minor": 5 }