{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7a0be8d0",
   "metadata": {},
   "source": [
    "<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
   ]
  },
  {
   "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": [
    "<a href=\"https://pyquantnews.com/\">PyQuant News</a> 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 <a href=\"https://gettingstartedwithpythonforquantfinance.com/\">get started with Python for quant finance</a>. 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
}
