Exemplo n.º 1
0
def equal_weight(stocks: List[str], other_args: List[str]):
    """
    Equally weighted portfolio, where weight = 1/# of stocks

    Parameters
    ----------
    stocks: List[str]
        List of tickers to be included in optimization

    Returns
    -------
    weights : dict
        Dictionary of weights where keys are the tickers

    """
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="equal",
        description="Returns an equally weighted portfolio",
    )

    parser.add_argument(
        "-v",
        "--value",
        default=1,
        type=float,
        dest="value",
        help="Amount to allocate to portfolio",
    )
    parser.add_argument(
        "--pie",
        action="store_true",
        dest="pie",
        default=False,
        help="Display a pie chart for weights",
    )
    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return

        if len(stocks) < 2:
            print(
                "Please have at least 2 loaded tickers to calculate weights.\n"
            )
            return

        values = {}
        for stock in stocks:
            values[stock] = ns_parser.value * round(1 / len(stocks), 5)
        if ns_parser.pie:
            pie_chart_weights(values, "Equally Weighted Portfolio")
        else:
            display_weights(values)
            print("")

    except Exception as e:
        print(e)
        print("")
Exemplo n.º 2
0
def efficient_return(stocks: List[str], other_args: List[str]):
    """Displays a portfolio that minimises volatility for a given target return ('Markowitz portfolio')

    Parameters
    ----------
    stocks : List[str]
        List of the stocks to be included in the weights
    other_args : List[str]
        argparse other args
    """

    parser = argparse.ArgumentParser(
        add_help=False,
        prog="effret",
        description="Calculate the 'Markowitz portfolio', minimising volatility for a given target return",
    )
    parser.add_argument(
        "-p",
        "--period",
        default="3mo",
        dest="period",
        help="period to get yfinance data from",
        choices=period_choices,
    )
    parser.add_argument(
        "-v",
        "--value",
        dest="value",
        help="Amount to allocate to portfolio",
        type=float,
        default=1.0,
    )
    parser.add_argument(
        "-n",
        "--market-neutral",
        action="store_true",
        default=False,
        dest="market_neutral",
        help="""whether the portfolio should be market neutral (weights sum to zero), defaults to False.
        Requires negative lower weight bound.""",
    )
    if "-n" not in other_args:
        parser.add_argument(
            "--pie",
            action="store_true",
            dest="pie",
            default=False,
            help="Display a pie chart for weights. Only if neutral flag is left False.",
        )

    if other_args:
        if "-" not in other_args[0]:
            other_args.insert(0, "-t")
    parser.add_argument(
        "-t",
        "--target-return",
        type=float,
        dest="target_return",
        default=0.1,
        help="the desired return of the resulting portfolio",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return

        if len(stocks) < 2:
            print("Please have at least 2 loaded tickers to calculate weights.\n")
            return

        period = ns_parser.period
        stock_prices = process_stocks(stocks, period)
        ef = prepare_efficient_frontier(stock_prices)

        sp = d_period[ns_parser.period]

        ef_opt = dict(
            ef.efficient_return(ns_parser.target_return, ns_parser.market_neutral)
        )
        s_title = f"{sp} Weights that minimise volatility for a given target return of {ns_parser.target_return}"

        weights = {
            key: ns_parser.value * round(value, 5) for key, value in ef_opt.items()
        }

        if not ns_parser.market_neutral:
            if ns_parser.pie:
                pie_chart_weights(weights, s_title)
                ef.portfolio_performance(verbose=True)
                print("")
                return

        print(s_title)
        display_weights(weights)
        print("")
        ef.portfolio_performance(verbose=True)
        print("")

    except Exception as e:
        print(e)
        print("")
        return
Exemplo n.º 3
0
def min_volatility(stocks: List[str], other_args: List[str]):
    """Return a portfolio that optimizes for minimum volatility

    Parameters
    ----------
    stocks : List[str]
        List of the stocks to be included in the weights
    other_args : List[str]
        argparse other args
    """

    parser = argparse.ArgumentParser(
        add_help=False,
        prog="min_volatility",
        description="Optimizes for minimum volatility",
    )
    parser.add_argument(
        "-p",
        "--period",
        default="3mo",
        dest="period",
        help="period to get yfinance data from",
        choices=period_choices,
    )
    parser.add_argument(
        "-v",
        "--value",
        dest="value",
        help="Amount to allocate to portfolio",
        type=float,
        default=1.0,
    )
    parser.add_argument(
        "--pie",
        action="store_true",
        dest="pie",
        default=False,
        help="Display a pie chart for weights",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return

        if len(stocks) < 2:
            print("Please have at least 2 loaded tickers to calculate weights.\n")
            return

        period = ns_parser.period
        stock_prices = process_stocks(stocks, period)
        ef = prepare_efficient_frontier(stock_prices)

        sp = d_period[ns_parser.period]

        ef_opt = dict(ef.min_volatility())
        s_title = f"{sp} Weights that minimize volatility"

        weights = {
            key: ns_parser.value * round(value, 5) for key, value in ef_opt.items()
        }

        if ns_parser.pie:
            pie_chart_weights(weights, s_title)
        else:
            print(s_title)
            display_weights(weights)
            print("")

        ef.portfolio_performance(verbose=True)
        print("")

    except Exception as e:
        print(e)
        print("")
        return
Exemplo n.º 4
0
def max_sharpe(stocks: List[str], other_args: List[str]):
    """Return a portfolio that maximises the Sharpe Ratio

    Parameters
    ----------
    stocks : List[str]
        List of the stocks to be included in the weights
    other_args : List[str]
        argparse other args
    """

    parser = argparse.ArgumentParser(
        add_help=False, prog="maxsharpe", description="Maximise the Sharpe Ratio"
    )
    parser.add_argument(
        "-p",
        "--period",
        default="3mo",
        dest="period",
        help="period to get yfinance data from",
        choices=period_choices,
    )
    parser.add_argument(
        "-v",
        "--value",
        dest="value",
        help="Amount to allocate to portfolio",
        type=float,
        default=1.0,
    )
    parser.add_argument(
        "--pie",
        action="store_true",
        dest="pie",
        default=False,
        help="Display a pie chart for weights",
    )

    if other_args:
        if "-" not in other_args[0]:
            other_args.insert(0, "-r")
    parser.add_argument(
        "-r",
        "--risk-free-rate",
        type=float,
        dest="risk_free_rate",
        default=0.02,
        help="""Risk-free rate of borrowing/lending. The period of the risk-free rate
                should correspond to the frequency of expected returns.""",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return

        if len(stocks) < 2:
            print("Please have at least 2 loaded tickers to calculate weights.\n")
            return

        period = ns_parser.period
        stock_prices = process_stocks(stocks, period)
        ef = prepare_efficient_frontier(stock_prices)

        sp = d_period[ns_parser.period]

        ef_opt = dict(ef.max_sharpe(ns_parser.risk_free_rate))
        s_title = f"{sp} Weights that maximize Sharpe ratio with risk free level of {ns_parser.risk_free_rate}"

        weights = {
            key: ns_parser.value * round(value, 5) for key, value in ef_opt.items()
        }

        if ns_parser.pie:
            pie_chart_weights(weights, s_title)
        else:
            print(s_title)
            display_weights(weights)
            print("")

        ef.portfolio_performance(verbose=True)
        print("")

    except Exception as e:
        print(e)
        print("")
        return
Exemplo n.º 5
0
def property_weighting(stocks: List[str], other_args: List[str]):
    """Weighted portfolio where each weight is the relative fraction of a specified info property.

    Parameters
    ----------
    stocks: List[str]
        List of tickers to be included in optimization
    other_args : List[str]
        Command line arguments to be processed with argparse
    """

    parser = argparse.ArgumentParser(
        add_help=False,
        prog="property",
        description="Returns a portfolio that is weighted based on a selected property info",
    )
    parser.add_argument(
        "-p",
        "--property",
        required=bool("-h" not in other_args),
        type=check_valid_property_type,
        dest="property",
        help="""Property info to weigh. Use one of:
        previousClose, regularMarketOpen, twoHundredDayAverage, trailingAnnualDividendYield,
        payoutRatio, volume24Hr, regularMarketDayHigh, navPrice, averageDailyVolume10Day, totalAssets,
        regularMarketPreviousClose, fiftyDayAverage, trailingAnnualDividendRate, open, toCurrency, averageVolume10days,
        expireDate, yield, algorithm, dividendRate, exDividendDate, beta, circulatingSupply, regularMarketDayLow,
        priceHint, currency, trailingPE, regularMarketVolume, lastMarket, maxSupply, openInterest, marketCap,
        volumeAllCurrencies, strikePrice, averageVolume, priceToSalesTrailing12Months, dayLow, ask, ytdReturn, askSize,
        volume, fiftyTwoWeekHigh, forwardPE, fromCurrency, fiveYearAvgDividendYield, fiftyTwoWeekLow, bid, dividendYield,
        bidSize, dayHigh, annualHoldingsTurnover, enterpriseToRevenue, beta3Year, profitMargins, enterpriseToEbitda,
        52WeekChange, morningStarRiskRating, forwardEps, revenueQuarterlyGrowth, sharesOutstanding, fundInceptionDate,
        annualReportExpenseRatio, bookValue, sharesShort, sharesPercentSharesOut, fundFamily, lastFiscalYearEnd,
        heldPercentInstitutions, netIncomeToCommon, trailingEps, lastDividendValue, SandP52WeekChange, priceToBook,
        heldPercentInsiders, shortRatio, sharesShortPreviousMonthDate, floatShares, enterpriseValue,
        threeYearAverageReturn, lastSplitFactor, legalType, lastDividendDate, morningStarOverallRating,
        earningsQuarterlyGrowth, pegRatio, lastCapGain, shortPercentOfFloat, sharesShortPriorMonth,
        impliedSharesOutstanding, fiveYearAverageReturn, and regularMarketPrice.""",
    )
    parser.add_argument(
        "-v",
        "--value",
        default=1,
        type=float,
        dest="value",
        help="Amount to allocate to portfolio",
    )
    parser.add_argument(
        "--pie",
        action="store_true",
        dest="pie",
        default=False,
        help="Display a pie chart for weights",
    )

    try:
        if other_args:
            if "-" not in other_args[0]:
                other_args.insert(0, "-p")

        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return
        if len(stocks) < 2:
            print("Please have at least 2 loaded tickers to calculate weights.\n")
            return

        weights = {}
        prop = {}
        prop_sum = 0
        for stock in stocks:
            stock_prop = yf.Ticker(stock).info[ns_parser.property]
            if stock_prop is None:
                stock_prop = 0
            prop[stock] = stock_prop
            prop_sum += stock_prop

        if prop_sum == 0:
            print(f"No {ns_parser.property} was found on list of tickers provided")
            print("")
            return

        for k, v in prop.items():
            weights[k] = round(v / prop_sum, 5) * ns_parser.value

        if ns_parser.pie:
            pie_chart_weights(
                weights, "Weighted Portfolio based on " + ns_parser.property
            )
        else:
            display_weights(weights)
            print("")

    except Exception as e:
        print(e)
        print("")
        return
Exemplo n.º 6
0
def property_weighting(stocks: List[str], property_type: str, other_args: List[str]):
    """
    Property weighted portfolio where each weight is the relative fraction.
    Parameters
    ----------
    stocks: List[str]
        List of tickers to be included in optimization
    property_type: str
        Property to weight by.  Can be anything in yfinance.Ticker().info.  Examples:
            "marketCap", "dividendYield", etc

    Returns
    -------
    weights: dict
        Dictionary of weights where keys are the tickers
    """
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="market_cap_weighted",
        description="Return portfolio weights/values that are weighted by marketcap",
    )

    parser.add_argument(
        "-v",
        "--value",
        default=1,
        type=float,
        dest="value",
        help="Amount to allocate to portfolio",
    )
    parser.add_argument(
        "--pie",
        action="store_true",
        dest="pie",
        default=False,
        help="Display a pie chart for weights",
    )
    weights = {}
    prop = {}
    prop_sum = 0

    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return
        for stock in stocks:
            stock_prop = yf.Ticker(stock).info[property_type]
            if stock_prop is None:
                stock_prop = 0
            prop[stock] = stock_prop
            prop_sum += stock_prop
        for k, v in prop.items():
            weights[k] = round(v / prop_sum, 5) * ns_parser.value

        if ns_parser.pie:
            pie_chart_weights(weights, property_type, 0)

        if property_type == "marketCap":
            print("Market Cap Weighted Portfolio: ")

        elif property_type == "dividendYield":
            print("Dividend Yield Weighted Portfolio: ")

        if len(stocks) >= 1:
            display_weights(weights)
            print("")

    except Exception as e:
        print(e)
        print("")
        return
Exemplo n.º 7
0
def ef_portfolio(stocks: List[str], port_type: str, other_args: List[str]):
    """
    Return a portfolio based on condition in port_type  Defaults to 3m of historical data
    Parameters
    ----------
    stocks: List[str]
        List of the stocks to be included in the weights
    port_type: str
        Method to be used on ef object (example: max_sharpe, min_volatility)
    Returns
    -------
    weights: dict
        Dictionary of weights where keys are the tickers.
    """

    parser = argparse.ArgumentParser(add_help=False, prog=port_type)

    parser.add_argument(
        "-p",
        "--period",
        default="3mo",
        dest="period",
        help="period to get yfinance data from",
        choices=period_choices,
    )

    parser.add_argument(
        "-v",
        "--value",
        dest="value",
        help="Amount to allocate to portfolio",
        type=float,
        default=1.0,
    )
    parser.add_argument(
        "--pie",
        action="store_true",
        dest="pie",
        default=False,
        help="Display a pie chart for weights",
    )

    try:
        ns_parser = parse_from_port_type(parser, port_type, other_args)
        if not ns_parser:
            return
        if len(stocks) < 2:
            print("Please have at least 2 loaded tickers to calculate weights.\n")
            return
        period = ns_parser.period
        stock_prices = process_stocks(stocks, period)
        ef = prepare_efficient_frontier(stock_prices)

        if port_type == "max_sharpe":

            ef_sharpe = dict(ef.max_sharpe())
            weights = {
                key: ns_parser.value * round(value, 5)
                for key, value in ef_sharpe.items()
            }
            val = 0
            print("Weights that maximize Sharpe Ratio:")

        elif port_type == "min_volatility":

            ef_min_vol = dict(ef.min_volatility())
            weights = {
                key: ns_parser.value * round(value, 5)
                for key, value in ef_min_vol.items()
            }
            val = 0
            print("Weights that minimize volatility")

        elif port_type == "eff_risk":

            ef_eff_risk = dict(ef.efficient_risk(ns_parser.risk_level))
            weights = {
                key: ns_parser.value * round(value, 5)
                for key, value in ef_eff_risk.items()
            }
            val = ns_parser.risk_level
            print(f"Weights for maximizing returns at risk = {100*val:.1f} %")

        elif port_type == "eff_ret":

            ef_eff_risk = dict(ef.efficient_return(ns_parser.target_return))
            weights = {
                key: ns_parser.value * round(value, 5)
                for key, value in ef_eff_risk.items()
            }
            val = ns_parser.target_return
            print(f"Weights for minimizing risk at target return = {100*val:.1f} %")

        else:
            raise ValueError("EF Method not found")

        if ns_parser.pie:
            pie_chart_weights(weights, port_type, val)

        print("")
        ef.portfolio_performance(verbose=True)
        print("")
        display_weights(weights)
        print("")

    except Exception as e:
        print(e)
        print("")
        return
Exemplo n.º 8
0
def max_quadratic_utility(stocks: List[str], other_args: List[str]):
    """
    Return a portfolio that maximises the quadratic utility, given some risk aversion

    Parameters
    ----------
    stocks: List[str]
        List of the stocks to be included in the weights

    Returns
    -------
    weights: dict
        Dictionary of weights where keys are the tickers.
    """
    parser = argparse.ArgumentParser(
        add_help=False,
        prog="max_quadratic_utility",
        description="Maximises the quadratic utility, given some risk aversion",
    )
    parser.add_argument(
        "-p",
        "--period",
        default="3mo",
        dest="period",
        help="period to get yfinance data from",
        choices=period_choices,
    )
    parser.add_argument(
        "-v",
        "--value",
        dest="value",
        help="Amount to allocate to portfolio",
        type=float,
        default=1.0,
    )
    parser.add_argument(
        "-n",
        "--market-neutral",
        action="store_true",
        default=False,
        dest="market_neutral",
        help=
        """whether the portfolio should be market neutral (weights sum to zero), defaults to False.
        Requires negative lower weight bound.""",
    )
    if "-n" not in other_args:
        parser.add_argument(
            "--pie",
            action="store_true",
            dest="pie",
            default=False,
            help=
            "Display a pie chart for weights. Only if neutral flag is left False.",
        )

    if other_args:
        if "-" not in other_args[0]:
            other_args.insert(0, "-r")

    parser.add_argument(
        "-r",
        "--risk-aversion",
        type=float,
        dest="risk_aversion",
        default=1,
        help="risk aversion parameter",
    )

    try:
        ns_parser = parse_known_args_and_warn(parser, other_args)
        if not ns_parser:
            return None

        if len(stocks) < 2:
            print(
                "Please have at least 2 loaded tickers to calculate weights.\n"
            )
            return

        period = ns_parser.period
        stock_prices = process_stocks(stocks, period)
        ef = prepare_efficient_frontier(stock_prices)

        sp = d_period[ns_parser.period]

        ef_opt = dict(
            ef.max_quadratic_utility(ns_parser.risk_aversion,
                                     ns_parser.market_neutral))
        s_title = f"{sp} Weights that maximise the quadratic utility with risk aversion of {ns_parser.risk_aversion}"

        weights = {
            key: ns_parser.value * round(value, 5)
            for key, value in ef_opt.items()
        }

        if not ns_parser.market_neutral:
            if ns_parser.pie:
                pie_chart_weights(weights, s_title)
                ef.portfolio_performance(verbose=True)
                print("")
                return

        print(s_title)
        display_weights(weights)
        print("")
        ef.portfolio_performance(verbose=True)
        print("")

    except Exception as e:
        print(e)
        print("")
        return