Portfolio Management¶
As mentioned above, FinQuant is a program for financial portfolio management, among others. The module finquant.portfolio
does exactly that.
Note
The impatient reader who simply wants to jump in and start using FinQuant is advised to jump to build_portfolio and have a look at and play around with the Examples.
This module is the core of FinQuant. It provides
- a public class
Stock
that holds and calculates quantities of a single stock, - a public class
Portfolio
that holds and calculates quantities of a financial portfolio, which is a collection of Stock instances. - a public function
build_portfolio()
that automatically constructs and returns an instance ofPortfolio
and instances ofStock
. The relevant stock data is either retrieved through quandl/yfinance or provided by the user as apandas.DataFrame
(after loading it manually from disk/reading from file). For an example on how to use it, please read the corresponding docstring, or have a look at the examples in the sub-directoryexample
.
The classes Stock
and Portfolio
are designed to easily manage your
financial portfolio, and make the most common quantitative calculations, such as:
- cumulative returns of the portfolio’s stocks
- daily returns of the portfolio’s stocks (daily percentage change),
- daily log returns of the portfolio’s stocks,
- Expected (annualised) Return,
- Volatility,
- Sharpe Ratio,
- skewness of the portfolio’s stocks,
- Kurtosis of the portfolio’s stocks,
- the portfolio’s covariance matrix.
Furthermore, the constructed portfolio can be optimised for
- minimum Volatility,
- maximum Sharpe Ratio
- minimum Volatility for a given Expected Return
- maximum Sharpe Ratio for a given target Volatility
by either performing a numerical computation to solve a minimisation problem, or by performing a Monte Carlo simulation of n trials. The former should be the preferred method for reasons of computational effort and accuracy. The latter is only included for the sake of completeness.
Finally, functions are implemented to generated the following plots:
- Monte Carlo run to find optimal portfolio(s)
- Efficient Frontier
- Portfolio with the minimum Volatility based a numerical optimisation
- Portfolio with the maximum Sharpe Ratio based on a numerical optimisation
- Portfolio with the minimum Volatility for a given Expected Return based on a numerical optimisation
- Portfolio with the maximum Sharpe Ratio for a given target Volatility based on a numerical optimisation
- Individual stocks of the portfolio (Expected Return over Volatility)
Stock¶
-
class
finquant.portfolio.
Stock
(investmentinfo, data)¶ Object that contains information about a stock/fund. To initialise the object, it requires a name, information about the stock/fund given as one of the following data structures:
pandas.Series
pandas.DataFrame
The investment information can contain as little information as its name, and the amount invested in it, the column labels must be
Name
andAllocation
respectively, but it can also contain more information, such as- Year
- Strategy
- CCY
- etc.
It also requires either data, e.g. daily closing prices as a
pandas.DataFrame
orpandas.Series
.data
must be given as apandas.DataFrame
, and at least one data column is required to containing the closing price, hence it is required to contain one column label<stock_name> - Adj. Close
which is used to compute the return of investment. However,data
can contain more data in additional columns.-
__init__
(investmentinfo, data)¶ Input: investmentinfo: pandas.DataFrame
of investment informationdata: pandas.DataFrame
of stock price
-
comp_daily_returns
()¶ Computes the daily returns (percentage change). See
finquant.returns.daily_returns
.
-
comp_expected_return
(freq=252)¶ Computes the Expected Return of the stock.
Input: freq: int
(default:252
), number of trading days, default value corresponds to trading days in a yearOutput: expected_return: Expected Return of stock.
-
comp_volatility
(freq=252)¶ Computes the Volatility of the stock.
Input: freq: int
(default:252
), number of trading days, default value corresponds to trading days in a yearOutput: volatility: Volatility of stock.
-
properties
()¶ Nicely prints out the properties of the stock: Expected Return, Volatility, Skewness, Kurtosis as well as the
Allocation
(and other information provided in investmentinfo.)
Portfolio¶
-
class
finquant.portfolio.
Portfolio
¶ Object that contains information about a investment portfolio. To initialise the object, it does not require any input. To fill the portfolio with investment information, the function
add_stock(stock)
should be used, in whichstock
is an object ofStock
.-
__init__
()¶ Initiates
Portfolio
.
-
add_stock
(stock)¶ Adds a stock of type
Stock
to the portfolio. Each timeadd_stock
is called, the following instance variables are updated:portfolio
:pandas.DataFrame
, adds a column with information fromstock
stocks
:dictionary
, adds an entry forstock
data
:pandas.DataFrame
, adds a column of stock prices fromstock
Also, the following instance variables are (re-)computed:
expected_return
: Expected Return of the portfoliovolatility
: Volatility of the portfoliosharpe
: Sharpe Ratio of the portfolioskew
: Skewness of the portfolio’s stockskurtosis
: Kurtosis of the portfolio’s stocks
Input: stock: an object of Stock
-
comp_cov
()¶ Compute and return a
pandas.DataFrame
of the covariance matrix of the portfolio.Output: cov: a pandas.DataFrame
of the covariance matrix of the portfolio.
-
comp_cumulative_returns
()¶ Computes the cumulative returns of all stocks in the portfolio. See
finquant.returns.cumulative_returns
.Output: ret: a pandas.DataFrame
of cumulative returns of given stock prices.
-
comp_daily_log_returns
()¶ Computes the daily log returns of all stocks in the portfolio. See
finquant.returns.daily_log_returns
.Output: ret: a pandas.DataFrame
of log Returns
-
comp_daily_returns
()¶ Computes the daily returns (percentage change) of all stocks in the portfolio. See
finquant.returns.daily_returns
.Output: ret: a pandas.DataFrame
of daily percentage change of Returns of given stock prices.
-
comp_expected_return
(freq=252)¶ Computes the Expected Return of the portfolio.
Input: freq: int
(default:252
), number of trading days, default value corresponds to trading days in a year.Output: expected_return: float
the Expected Return of the portfolio.
-
comp_mean_returns
(freq=252)¶ Computes the mean returns based on historical stock price data. See
finquant.returns.historical_mean_return
.Input: freq: int
(default:252
), number of trading days, default value corresponds to trading days in a year.Output: ret: a pandas.DataFrame
of historical mean Returns.
-
comp_sharpe
()¶ Compute and return the Sharpe Ratio of the portfolio.
Output: sharpe: float
, the Sharpe Ratio of the portfolio
-
comp_stock_volatility
(freq=252)¶ Computes the Volatilities of all the stocks individually
Input: freq: int
(default:252
), number of trading days, default value corresponds to trading days in a year.Output: volatilies: pandas.DataFrame
with the individual Volatilities of all stocks of the portfolio.
-
comp_volatility
(freq=252)¶ Computes the Volatility of the given portfolio.
Input: freq: int
(default:252
), number of trading days, default value corresponds to trading days in a year.Output: volatility: float
the Volatility of the portfolio.
-
comp_weights
()¶ Computes and returns a
pandas.Series
of the weights/allocation of the stocks of the portfolio.Output: weights: a pandas.Series
with weights/allocation of all stocks within the portfolio.
-
ef_efficient_frontier
(targets=None)¶ Interface to
finquant.efficient_frontier.EfficientFrontier.efficient_frontier
.Gets portfolios for a range of given target Returns. If no targets were provided, the algorithm will find the minimum and maximum Returns of the portfolio’s individual stocks, and set the target range according to those values. Results in the Efficient Frontier.
Input: targets: list
/numpy.ndarray
(default:None
) offloats
, range of target Returns.Output: efrontier: numpy.ndarray
of (Volatility, Return) values.
-
ef_efficient_return
(target, verbose=False)¶ Interface to
finquant.efficient_frontier.EfficientFrontier.efficient_return
.Finds the portfolio with the minimum Volatility for a given target return.
Input: target: float
, the target return of the optimised portfolio.verbose: boolean
(default=False
), whether to print out properties or not.Output: df_weights: a pandas.DataFrame
of weights/allocation of stocks within the optimised portfolio.
-
ef_efficient_volatility
(target, verbose=False)¶ Interface to
finquant.efficient_frontier.EfficientFrontier.efficient_volatility
.Finds the portfolio with the maximum Sharpe Ratio for a given target Volatility.
Input: target: float
, the target Volatility of the optimised portfolio.verbose: boolean
(default=False
), whether to print out properties or not.Output: df_weights: a pandas.DataFrame
of weights/allocation of stocks within the optimised portfolio.
-
ef_maximum_sharpe_ratio
(verbose=False)¶ Interface to
finquant.efficient_frontier.EfficientFrontier.maximum_sharpe_ratio
.Finds the portfolio with the maximum Sharpe Ratio, also called the tangency portfolio.
Input: verbose: boolean
(default=False
), whether to print out properties or not.Output: df_weights: a pandas.DataFrame
of weights/allocation of stocks within the optimised portfolio.
-
ef_minimum_volatility
(verbose=False)¶ Interface to
finquant.efficient_frontier.EfficientFrontier.minimum_volatility
.Finds the portfolio with the minimum Volatility.
Input: verbose: boolean
(default=False
), whether to print out properties or not.Output: df_weights: a pandas.DataFrame
of weights/allocation of stocks within the optimised portfolio.
-
ef_plot_efrontier
()¶ Interface to
finquant.efficient_frontier.EfficientFrontier.plot_efrontier
.Plots the Efficient Frontier.
-
ef_plot_optimal_portfolios
()¶ Interface to
finquant.efficient_frontier.EfficientFrontier.plot_optimal_portfolios
.Plots markers of the optimised portfolios for
- minimum Volatility, and
- maximum Sharpe Ratio.
-
get_stock
(name)¶ Returns the instance of
Stock
with namename
.Input: name: string
of the name of the stock that is returned. Must match one of the labels in the dictionaryself.stocks
.Output: stock: instance of Stock
.
-
mc_optimisation
(num_trials=1000)¶ Interface to
finquant.monte_carlo.MonteCarloOpt.optimisation
.Optimisation of the portfolio by performing a Monte Carlo simulation.
Input: num_trials: int
(default:1000
), number of portfolios to be computed, each with a random distribution of weights/allocation in each stock.Output: opt_w: pandas.DataFrame
with optimised investment strategies for maximum Sharpe Ratio and minimum Volatility.opt_res: pandas.DataFrame
with Expected Return, Volatility and Sharpe Ratio for portfolios with minimum Volatility and maximum Sharpe Ratio.
-
mc_plot_results
()¶ Plots the results of the Monte Carlo run, with all of the randomly generated weights/portfolios, as well as markers for the portfolios with the
- minimum Volatility, and
- maximum Sharpe Ratio.
-
mc_properties
()¶ Calculates and prints out Expected annualised Return, Volatility and Sharpe Ratio of optimised portfolio.
-
plot_stocks
(freq=252)¶ Plots the Expected annual Returns over annual Volatility of the stocks of the portfolio.
Input: freq: int
(default:252
), number of trading days, default value corresponds to trading days in a year.
-
properties
()¶ Nicely prints out the properties of the portfolio:
- Expected Return,
- Volatility,
- Sharpe Ratio,
- skewness,
- Kurtosis
as well as the allocation of the stocks across the portfolio.
-
build_portfolio¶
-
portfolio.
build_portfolio
()¶ This function builds and returns an instance of
Portfolio
given a set of input arguments.Input: pf_allocation: (optional)
pandas.DataFrame
with the required data column labelsName
andAllocation
of the stocks. If not given, it is automatically generated with an equal weights for all stocks in the resulting portfolio.names: (optional) A
string
orlist
ofstrings
, containing the names of the stocks, e.g. “GOOG” for Google.start_date: (optional)
string
/datetime
start date of stock data to be requested through quandl/yfinance (default:None
).end_date: (optional)
string
/datetime
end date of stock data to be requested through quandl/yfinance (default:None
).data: (optional) A
pandas.DataFrame
which contains quantities of the stocks listed inpf_allocation
.data_api: (optional) A
string
(default:quandl
) which determines how to obtain stock prices, if data is not provided by the user. Valid values:quandl
(Python package/API to Quandl)yfinance
(Python package formerly known asfix-yahoo-finance
)
Output: pf: Instance of Portfolio
which contains all the information requested by the user.Note
Only the following combinations of inputs are allowed:
names
,pf_allocation
(optional),start_date
(optional),end_date
(optional), data_api (optional)data
,pf_allocation
(optional)
The two different ways this function can be used are useful for:
- building a portfolio by pulling data from quandl/yfinance,
- building a portfolio by providing stock data which was obtained otherwise, e.g. from data files.
If used in an unsupported way, the function (or subsequently called function) raises appropriate Exceptions with useful information what went wrong.