scrilla: A Financial Optimization Application
Table of Contents
This is a financial application that calculates asset correlations, statistics and optimal portfolio allocations using data it retrieves from external services (currently: AlphaVantage, IEX and Quandl). Statistics are calculated using Ito Calculus and should be consistent with the results demanded by Modern Portfolio Theory and Financial Engineering. The portfolios are optimized by minimizing the portfolio's variance/volatility, i.e. by finding the optimal spot on the portfolio's efficient frontier as defined by the CAPM model. Alternatively, portfolios can be optimized by maximizing the portfolio's Sharpe ratio or by minimizing the portfolio's Conditional Value at Risk.
The program's functions are wrapped in PyQt5 widgets which provide a user interface (this feature is still in development and may explode). In addition, visualizations are created by matplotlib for easier presentation.
The links below will take you to the registration pages for each API service Key,
AlphaVantage API Key Registration
Quandl API Key Registration
IEX API Key Registration
Note this application optimizes across asset classes, i.e. the theoretical portfolio being constructed can be composed of equities, cryptocurrencies or both. In a future release, I would like to include fixed income assets, volatility assets (VIX futures, options, etc.) and other derivatives, but for now, only those two asset types are supported. I am looking for a good API that provides historical data on the other types of financial instruments before I bring them into the optimization algorithm, so if you know of one, contact me.
Setup
Installation
Install the package with the Python package manager,
pip install scrilla
If you prefer, you can build from source. git clone
the repository and then from the root directory build the library,
python3 -m build
cd
into the generated /dist/ to manually install the packaged code,
pip install scrilla-
Dependencies
You will need Python3.8 or greater. This application depends on the following Python libraries:
- python-dotenv>=0.17.0
- requests>=2.25.0
- numpy>=1.19.3
- scipy>=1.5.4
- matplotlib>=3.3.3
- holidays>=0.10.4
- PyQt5>=5.14
This libraries will be installed during the pip install
command. If you wish to use the GUI, you will also need to ensure your operating system has a Qt5 library,
sudo apt-get install qt5-default
The GUI will not function without a Qt library.
Configuration
In order to use this application, you will need to register for API keys. The program will need to be made aware of these keys somehow. The best option is storing these credentials in environment variables. See Required Configuration for more information. You can also invoke the CLI function store
to store the credentials in the local installation /data/common/ directory. To do so,
scrilla -store
where key
is one of the values: ALPHA_VANTAGE_KEY
, QUANDL_KEY
or IEX_KEY
. value
is the corresponding key itself given to you after registration. The key
is case-sensitive and there should be no spaces in the expression key=value
Environment
A sample environment file is located here, along with comments describing the purpose of each variable. The application sets sensible defaults for most of the environment variable configurations, but there are several required environment variables you will need to set yourself.
Required Configuration
As mentioned, you will need to register for API keys at AlphaVantage, IEX and Quandl. One way of passing API keys to the program is by storing these in your session's environment. scrilla will search for environment variables named ALPHA_VANTAGE_KEY, QUANDL_KEY and IEX_KEY. You can add the following lines to your .bashrc profile or corresponding configuration file for whatever shell you are using,
export ALPHA_VANTAGE_KEY=
export QUANDL_KEY=
export IEX_KEY=
If no API keys are found in these variables, the application will not function properly; be sure to load these variables into your shell session before using scrilla.
Optional Configuration
scrilla can be configured with the following optional environment variables. Each variable in this list has a suitable default set and so does not need changed unless the user prefers a different setting.
- RISK_FREE
Determines which annualized US-Treasury yield is used as stand-in for the risk free rate. This variable will default to a value of 10-Year
, but can be modified to any of the following: 3-Month
, 5-Year
, 10-Year
, or 30-Year
.
- MARKET_PROXY
Determines which ticker symbol is used as a proxy for the overall market return. This variable will default to a value of SPY
, but can be set to any ticker on the stock market. Recommended values: SPY
, QQQ
, DJI
or VTI
.
- FRONTIER_STEPS
Determines the number of data points in a portfolio's efficient frontier. This variable will default to a value of 5
, but can be set equal to any integer.
- MA_1, MA_2, MA_3
Determines the number of days used in the sample for moving average series and plots. These variables default to the values of 20
, 60
and 100
. In other words, by default, moving average plots will display the 20-day moving average, the 60-day moving average and the 100-day moving average. These variables can be set equal to any integer, as long as MA_1 < MA_2 < MA_3.
- FILE_EXT
Determines the type of files that are output by scrilla. This variable is currently only defined for an argument of json
. A future release will include csv
.
- LOG_LEVEL
Determines the amount of output. Defaults to info
. Allowable values: none
, info
, debug
or verbose
. Be warned, verbose
is extremely verbose.
Usage
Command Line
Most functions have been wired into command line arguments. For a full list of scrilla's functionality,
scrilla -help
The main usage of scrilla is detailed below.
Optimization
- Volatility Minimization & Sharpe-Ratio Maximization
A portfolio of consisting of the equities ALLY, BX and SONY can be optimized with the following command,
scrilla -opt ALLY BX SONY
By default, scrilla will optimize over the last 100 trading days. If you wish to optimize over a different time period, you may use the -start
and -end
argument flags to provide starting and ending dates in the YYYY-MM-DD
format.
Also by default, the optimization function will minimize the portfolio variance. You can also specify the portfolio should be maximized with respect to the Sharpe ratio,
scrilla -opt -sh ALLY BX SONY
There are several other arguments you may use to configure your optimization program. The full list of arguments is shown below,
scrilla -opt -sh -start
-target
will optimize the portfolio with the additional constraint that its rate of return must equal target
. Note the target return must be between the minimum rate of return and maximum rate of return in a basket of equities. For example, if ALLY had a rate of return of 10%, BX 15%, SONY 20%, the frontier of possible rates of returns resides in the range [10%, 20%]. It is impossible to combine the equities in such a way to get a rate of return less than 10% or one greater than 20%. Note, this assumes shorting is not possible. A future release will relax this assumption and allow portfolio weights to be negative.
-invest
represents the total amount of money invested in a portfolio.
For example, the following command,
scrilla -opt -sh -save
Will optimize a portfolio consisting of ALLY, BX and SONY using historical data between the dates of January 1st, 2020 and May 15th, 2021. The portfolio will be constrained to return a rate of 25%. A total $10,000 will be invested into this portfolio (to the nearest whole share). The output of this command will look like this,
---------------------------------------------- Results ----------------------------------------------
----------------------------------------------------------------------------------------------------
----------------------------------- Optimal Percentage Allocation -----------------------------------
ALLY = 22.83 %
BX = 19.26 %
SONY = 57.91 %
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
-------------------------------------- Optimal Share Allocation --------------------------------------
ALLY = 42
BX = 15
SONY = 56
-------------------------------------- Optimal Portfolio Value --------------------------------------
>> Total = $ 9893.98
---------------------------------------- Risk-Return Profile ----------------------------------------
>> Return = 0.25
>> Volatility = 0.201
----------------------------------------------------------------------------------------------------
Note the optimal share allocation does not allow fractional shares. scrilla will attempt to get as close to the total investment inputted without going over using only whole shares. Also note the return of this portfolio is 25%, as this was inputted into the target return constraint.
- Conditional Value at Risk Minimization
The portfolio optimization can also be done by minimizing its conditional value at risk. Because the underlying calculations are a bit different, this function is accessed through a different command and requires different arguments.
The two new arguments are prob
and expiry
. prob
, in essence, represents the percentile of the portfolio's distribution on which the value at risk will be conditioned. In other words, if the portfolio value is represented by a random variable P, for a given value of P=p, the prob
is the probability such that,
With these two new arguments, a portfolio's conditional value at risk can be optimized using the following, The command given above will optimize the portfolio consisting of ALLY, BX and SONY over the next half year ( scrilla will pull an equity's dividend payment history, regress the payment amount against its date and infer a linear regression from this time series. It will use this model to project future dividend payments and then calculate the current cost of equity and use that to discount the sum of dividend payments back to the present, Alternatively, you can visualize the dividend payments against the regression model, Financial Statistics Stock Watchlist and Screening Stocks can be added to your watchlist with, You can then screen stocks according to some criteria. For example, the following command will search your watchlist for stock prices that are less than their Discount Dividend Model (very rare this happens...), This package is made up of several top-level modules and various submodules, grouped according to the following name space: In general, you should not need to interact with any of the top level modules. main is the entrypoint for the CLI application, files is used to format and parse files and manage the local cache, settings parses environment variables to configure the application; these modules function entirely under the hood. On occasion, however, you may need to access services, as this is where raw data from the external services is requested and parsed. The four functions of interest in this module are: Returns:Probability(P
expiry
represents the time horizon over which the value at risk will be calculated, i.e. the point in time in which the hypothetical loss occurs.scrilla -opt-cvar -prob 0.05 -expiry 0.5 ALLY BX SONY
expiry
= 0.5) subject to the value at risk in the 5th percentile.
Other Notable Features
scrilla -ddm ALLY
scrilla -plot-div ALLY
scrilla -capm-beta [TICKERS]
scrilla -cor [TICKERS]
scrilla -capm-equity [TICKERS]
scrilla -rr [TICKERS]
scrilla -sharpe [TICKERS]
scrilla -watch [TICKERS]
scrilla -screen -model DDM
scrilla -plot-div [TICKER]
scrilla -plot-ef [TICKERS]
scrilla -plot-mov [TICKERS]
scrilla -plot-rr [TICKERS]
scrilla -plot-yield
(not implemented yet)
Programmatic
scrilla.services
scrilla.services.get_daily_price_history(ticker, start_date=None, end_date=None)
Description:
This function will retrieve the price history for the equity specified by the ticker
argument. ticker
must be the symbol associated with the equity on the stock exchange, e.g. MSFT = Microsft, TSLA = Tesla, etc. If no start_date
or end_date
are provided, the function returns the last 100 trading days worth of information.
Arguments:
ticker : str
: Required. Ticker symbol of the equity.start_date: datetime.date
: Optional. Start date of analysis range. Defaults to None
end_date: datetime.date
: Optional. End date of analysis range. Defaults to None
a dictionary of prices with the YYYY-MM-DD
formatted date as key. The dictionary is sorted latest price to earliest price.scrilla.services.get_daily_stat_history(statistic, start_date=None, end_date=None)
Description:
This function will retrieve the price history for the financial statistic specifed by the statistic
argument.
Arguments:
statistic : str
: Required. Statistic symbol for quantity of interest. A list of allowable values can be found herestart_date: datetime.date
: Optional. Start date of analysis range. Defaults to None
end_date: datetime.date
: Optional. End date of analysis range. Defaults to None
scrilla.services.get_dividend_history(ticker)
Description:
This function will retrieve the dividend payment history (i.e. the date on which the payment was made, not the date the payment was declared) for the equity specified by the ticker
arugment. ticker
must be the symobl assoccaited with the equity on the stock exchange.
Arguments:
ticker : str
: Required. Ticker symbol of the equity.scrilla.services.get_risk_free_rate()
Description:
This function will retrieve the current value of the risk free rate (annualized yield on a US Treasury). The risk free rate can be configured through the RISK_FREE environment variable. See optional configuration for more details.
scrilla.analysis.markets
scrilla.analysis.markets.sharpe_ratio
scrilla.analysis.markets.market_premium
scrilla.analysis.markets.market_beta
scrilla.analysis.markets.cost_of_equity
scrilla.analysis.optimizer
scrilla.analysis.optimizer.optimize_portfolio_variance
scrilla.analysis.optimizer.maximize_sharpe_ratio
scrilla.analysis.optimizer.maximize_portfolio_return
Description:
description goes here
Note:
The rate of return of a portfolio of assets is a linear function with respect to the asset weights. IAs a result, this function should always allocate 100% of any given portfolio to the asset with the highest expected rate of return, i.e. if you have two assets where one asset has a 10% rate of return and a second asset has a 20% rate of return, the maximum rate of return for a portfolio composed of both assets is produced when 100% of the portfolio is invested in the asset with a 20% rate of return.
scrilla.analysis.statistics
scrilla.analysis.statistics.sample_correlation
scrilla.analysis.statistics.recursive_rolling_correlation
scrilla.analysis.statistics.sample_mean
scrilla.anaylsis.statistics.recursive_rolling_mean
scrilla.anaylsis.statistics.sample_variance
scrilla.analysis.statistics.recursive_rolling_variance
scrilla.anaylsis.statistics.sample_covariance
scrilla.anaylsis.statistics.recursive_rolling_covariance
scrilla.analysis.statistics.regression_beta
scrilla.analysis.statistics.regression_alpha
scrilla.analysis.statistics.calculate_moving_averages
scrilla.analysis.statistics.calculate_risk_return
scrilla.analysis.statistics.calculate_return_covariance
scrilla.analysis.statistics.calculate_ito_correlation
scrilla.anaylsis.statistics.ito_correlation_matrix
scrilla.objects.cashflow.Cashflow
scrilla.objects.portfolio.Portfolio