%%This is a very basic article template. %%There is just one section and two subsections. %-------------------------------------------------- \documentclass[letterpaper]{report} %-------------------------------------------------- %Packeges %-------------------------------------------------- \usepackage[english]{babel} \usepackage{amsmath,amssymb,amsfonts} % Typical maths resource packages \usepackage[dvips]{graphicx} \usepackage{color} % For creating coloured text and background \usepackage{fancyhdr} % For inclusion of title at the top of the page \usepackage[left=3cm,right=1.5 cm,top=2cm,bottom=2cm,bindingoffset=0cm]{geometry} \usepackage[explicit]{titlesec} \usepackage{setspace} \usepackage{pdfpages} \usepackage{cite} \usepackage{float} \usepackage{newclude} \usepackage{bookmark} \usepackage{listings} \usepackage{tikz} \usepackage{type1cm} \usepackage{hyperref} % For creating hyperlinks in cross \usetikzlibrary{fit} \definecolor{grey}{rgb}{0.97,0.97,0.97} \definecolor{rred}{rgb}{0.6,0,0} % for strings \definecolor{rgreen}{rgb}{0.25,0.5,0.35} % comments \definecolor{rpurple}{rgb}{0.5,0,0.35} % keywords \definecolor{rblue}{rgb}{0.25,0.35,0.75} % docs \newcommand*\chapterlabel{} \makeatletter \def\@makechapterhead#1{% \vspace*{10\p@}% {\parindent \z@ \centering \reset@font \par\nobreak \vspace*{2\p@}% {\Huge \bfseries \thechapter\quad #1\par\nobreak} \par\nobreak \vspace*{2\p@}% \vskip 40\p@ %\vskip 100\p@ }} \def\@makeschapterhead#1{% \vspace*{10\p@}% {\parindent \z@ \centering \reset@font \par\nobreak \vspace*{2\p@}% {\Huge \bfseries #1\par\nobreak} \par\nobreak \vspace*{2\p@}% \vskip 100\p@ %\vskip 100\p@ }} \makeatother \newcounter{N} \setlength{\parindent}{0ex} \setlength{\parskip}{1em} \lstset{language=R, basicstyle=\footnotesize\ttfamily, basewidth=0.5em, keywordstyle=\color{rpurple}\bfseries, stringstyle=\color{rred}, commentstyle=\color{rgreen}, morecomment=[s][\color{rblue}]{/**}{*/}, numbers=none, numberstyle=\tiny\color{black}, stepnumber=2, numbersep=10pt, tabsize=4, aboveskip=3mm, belowskip=3mm, backgroundcolor=\color{grey}, frame=none, showspaces=false, showstringspaces=false, breaklines=true} \begin{document} \begin{titlepage} \begin{center} \vspace{5cm} {\href{https://www.portfolioeffect.com}{www.portfolioeffect.com} \\ High Frequency Portfolio Analytics\\} \vspace{8cm} {\Large \bfseries User Manual \\} \vspace{0.3cm} {\Huge\bfseries PortfolioEffectHFT Package \\ for R Software\\ } % ---------------------------------------------------------------- \vspace{1.5cm} {Andrey Kostin \\ andrey.kostin@portfolioeffect.com} \\[14pt] % ---------------------------------------------------------------- \vfill \emph{{Released Under GPL-3 License\\ by Snowfall Systems, Inc.}}\\[2cm] {August 20, 2015} \end{center} \end{titlepage} \bookmarksetup{startatroot} \cleardoublepage \phantomsection \addcontentsline{toc}{chapter}{Contents} \bibliographystyle{amsplain}%} \renewcommand{\bibname}{Contents} \tableofcontents %\VignetteIndexEntry{PorfolioEffectHFT package} \SweaveOpts{concordance=TRUE} \chapter{Package Installation} PortfolioEffectHFT package for R relies on the rJava package, which assumes that Java runtime is installed and configured on your system. To install Java runtime and to configure your R engine to work with it, follow these steps: \section{Install Latest JDK/JRE Runtime} Download and install latest Java distribution (JDK or JRE) for your platform from \href{http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html}{Oracle's website} \section{Configure Java Environment (Optional)} If you are using Windows, installation wizard from the previous step should have done everything for you. If you are on Linux or Mac and you used a tarball file, you will need to manually append the following lines to /etc/environment using your favorite text editor: \begin{lstlisting} export JAVA_HOME=/path/to/java/folder export PATH=$PATH:$JAVA_HOME/bin \end{lstlisting} Apply environment changes: \begin{lstlisting} source /etc/environment \end{lstlisting} To complete with the set-up of Java environment inside R, run the following line: \begin{lstlisting} sudo R CMD javareconf \end{lstlisting} \section{Install Required Packages (Optional)} If you are manually installing PortfolioEffectHFT package (you don't want to use CRAN repositories for some reason), you would need to install all required package dependencies first. Start R from the command line or in your GUI editor and type \begin{lstlisting} install.packages(c("rJava", "ggplot2")) \end{lstlisting} You are now ready to install the PortfolioEffectHFT package directly from \href{https://www.portfolioeffect.com}{www.portfolioeffect.com} downloads section. \chapter{API Credentials} All portfolio computations are performed on PortfolioEffect cloud servers. To obtain a free non-professional account, you need to follow a quick sign-up process on our website: \href{https://www.portfolioeffect.com/registration}{www.portfolioeffect.com/registration}.\par Please use a valid sign-up address - it will be used to email your account activation link. \section{Locate API Credentials} Log in to you account and locate your API credentials on the main page \section{Set API Credentials in R} Run the following commands to set your account API credentials for the PortfolioEffectHFT R Package installed. You will need to do it only once as your credentials are stored between sessions on your local machine to speed up future logons. \par You would need to repeat this procedure if you change your account password or install PortfolioEffectHFT package on another computer. \begin{lstlisting} require(PortfolioEffectHFT) util_setCredentials("API Username", "API Password", "API Key") \end{lstlisting} You are now ready to call PortfolioEffectHFT methods. \chapter{Portfolio Construction} \section{User Data} Users may supply their own historical datasets for index and position entries. This external data could be one a OHLC bar column element (e.g. 1-second close prices) or a vector of actual transaction prices that contains non-equidistant data points. You might want to prepend at least N =(4 x windowLength) data points to the beginning of the interval of interest which would be used for initial calibration of portfolio metrics. \subsection{Create Portfolio} Method \href{https://www.portfolioeffect.com/docs/platform/quant/functions/general-functions/portfolio-create}{portfolio\_create()}. takes a vector of index prices in the format (UTC timestamp, price) with UTC timestamp expressed in milliseconds from 1970-01-01 00:00:00 EST. \begin{lstlisting} Time Value [1,] 1412256601000 99.30 [2,] 1412256602000 99.33 [3,] 1412256603000 99.30 [4,] 1412256604000 99.26 [5,] 1412256605000 99.36 [6,] 1412256606000 99.36 [7,] 1412256607000 99.36 [8,] 1412256608000 99.38 [9,] 1412256609000 99.40 [10,] 1412256610000 99.37 \end{lstlisting} If index symbol is specified, it is silently ignored. \begin{lstlisting} data(spy.data) # Create portfolio portfolio=portfolio_create(priceDataIx=spy.data) \end{lstlisting} \subsection {Add Positions} Positions are added using \href{https://www.portfolioeffect.com/docs/platform/quant/functions/general-functions/portfolio-add-position}{portfolio\_addPosition()} with 'priceData' in the same format as index price. \begin{lstlisting} data(goog.data) data(aapl.data) # Single position without rebalancing positionGOOG=position_add(portfolio, symbol='GOOG', quantity=100, priceData=goog.data) # Single position with rebalancing positionAAPL=position_add(portfolio, symbol='AAPL', quantity=c(300,150), time=c("2014-09-01 09:00:00","2014-09-07 14:30:00"), priceData=aapl.data) \end{lstlisting} \section{Server Data} At PortfolioEffect we are capturing and storing 1-second intraday bar history for a \href{https://www.portfolioeffect.com/docs/symbology}{all NASDAQ traded equites}. This server-side dataset spans from January 2013 to the latest trading time minus five minutes. It could be used to construct asset portfolios and compute intraday portfolio metrics. \subsection {Create Portfolio} Method \href{https://www.portfolioeffect.com/docs/platform/quant/functions/general-functions/portfolio-create}{portfolio\_create()} creates new asset portfolio or overwrites an existing portfolio object with the same name. \par When using server-side data, it only requires a time interval that would be treated as a default position holding period unless positions are added with rebalancing. Index symbol could be specified as well with a default value of ``SPY'' - SPDR S\&P 500 ETF Trust. \par Interval boundaries are passed in the following format: \begin{itemize} \item ``yyyy-MM-dd HH:MM:SS'' (e.g. ``2014-10-01 09:30:00'') \item ``yyyy-MM-dd'' (e.g. ``2014-10-01'') \item ``t-N'' (e.g. ``t-5'' is latest trading time minus 5 days) \item UTC timestamp in milliseconds (mills from ``1970-01-01 00:00:00'') in EST time zone \end{itemize} \begin{lstlisting} # Timestamp in "yyyy-MM-dd HH:MM:SS" format portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") # Timestamp in "yyyy-MM-dd" format portfolio=portfolio_create(fromTime="2014-10-01", toTime="2014-10-02") # Timestamp in "t-N" format portfolio=portfolio_create(fromTime="t-5", toTime="t") \end{lstlisting} \subsection {Get Symbols List} Once portfolio is created, \href{https://www.portfolioeffect.com/docs/platform/quant/functions/general-functions/portfolio-available-symbols}{portfolio\_availableSymbols()} method could be called to receive the list of all available symbols for position creation. Each symbol is accompanied by a full company/instrument description and listing exchange name. \begin{lstlisting} portfolio_availableSymbols(portfolio) id description exchange [1,] "BBC" "BioShares Biotechnology Clinical Trials Fund" "NASDAQ" [2,] "SCS" "Steelcase Inc. Common Stock" "NYSE" [3,] "BBD" "Banco Bradesco Sa American Depositary Shares" "NYSE" [4,] "BBG" "Bill Barrett Corporation Common Stock" "NYSE" [5,] "STPP" "Barclays PLC - iPath US Treasury Steepener ETN" "NASDAQ" [6,] "BBF" "BlackRock Municipal Income Investment Trust" "NYSE" [8,] "BBH" "Market Vectors Biotech ETF" "NYSEARCA" [9,] "SCON" "Superconductor Technologies Inc. - Common Stock" "NASDAQ" [10,] "SCX" "L.S. Starrett Company (The) Common Stock" "NYSE" [11,] "BBK" "Blackrock Municipal Bond Trust" "NYSE" \end{lstlisting} \subsection {Add Positions} Positions are added by calling \href{https://www.portfolioeffect.com/docs/platform/quant/functions/general-functions/portfolio-add-position}{position\_add()} method on a portfolio object with a list of symbols and quantities. For positions that were rebalanced or had non-default holding periods a 'time' argument could be used to specify rebalancing timestamps. \begin{lstlisting} # Single position without rebalancing positionGOOG=position_add(portfolio, symbol='GOOG', quantity=100) # Single position with rebalancing positionAAPL=position_add(portfolio, symbol='AAPL', quantity=c(300,150), time=c("2014-09-01 09:00:00","2014-09-07 14:30:00")) \end{lstlisting} \chapter{Portfolio Settings} \section{Portfolio Metrics} These settings regulate how portfolio returns and return moments are computed \subsection {Portfolio Metrics Mode} One of the two modes for collecting portfolio metrics that could be used: \begin{itemize} \item ``portfolio''- portfolio metrics are computed using previous history of position rebalancing. Portfolio risk and performance metrics account for the periods with no market exposure (i.e. when no positions are held) depending on the holding periods accounting settings (see holding periods mode below). \item ``price'' - at any given point of time, both position and portfolio metrics are computed for a buy-and-hold strategy. This mode is a common for classic portfolio theory and is often used in academic literature for portfolio optimization or when computing price statistics. \end{itemize} By default, mode is set to "portfolio". \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionAAPL=position_add(portfolio, symbol='AAPL', quantity=c(300,150), time=c("2014-10-01 09:30:00","2014-10-02 09:30:00")) positionGOOG=position_add(portfolio, symbol='GOOG', quantity=c(100,150), time=c("2014-10-01 09:30:00","2014-10-02 09:30:00")) # "price" mode portfolio_settings(portfolio, portfolioMetricsMode="price") variance_price=variance(portfolio); # "portfolio" mode portfolio_settings(portfolio, portfolioMetricsMode="portfolio") variance_portfolio=variance(portfolio); plot(variance_portfolio,variance_price,title="Variance, portfolioMetricsMode",legend=c("portfolio","price")) \end{lstlisting} \subsection {Holding Periods Only} This setting should only be used when portfolio metrics mode is set to "portfolio". When holdingPeriodsOnly is set to FALSE, trading strategy risk and performance metrics will be annualized to include time intervals when strategy had no market exposure at certain points (i.e. when position quantity were zero). When set to TRUE, trading strategy metrics are annualized only based on actual holding intervals. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionAAPL=position_add(portfolio,'AAPL', c(0,300,0,150), time=c("2014-09-30 09:30:00", "2014-10-01 09:30:00", "2014-10-01 15:30:00", "2014-10-02 11:30:00")) # enable holdingPeriodsOnly portfolio_settings(portfolio, holdingPeriodsOnly=TRUE) variance_holdingPeriodsOnly_TRUE=variance(portfolio); # disable holdingPeriodsOnly portfolio_settings(portfolio, holdingPeriodsOnly=FALSE) variance_holdingPeriodsOnly_FALSE=variance(portfolio); plot(variance_holdingPeriodsOnly_TRUE,variance_holdingPeriodsOnly_FALSE,title="Variance,holdingPeriodsOnly",legend=c("TRUE","FALSE")) \end{lstlisting} \subsection {Short Sales Mode} This setting is used to specify how position weights are computed. Available modes are: \begin{itemize} \item ``lintner'' - the sum of absolute weights is equal to 1 (Lintner assumption) \item ``markowitz'' - the sum of weights must equal to 1 (Markowitz assumption) \end{itemize} Defaults to "lintner", which implies that the sum of absolute weights is used to normalize investment weights. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',-500,) positionGOOG=position_add(portfolio,'GOOG',600) # weights are normalized based on a simple sum (Markowitz) portfolio_settings(portfolio, shortSalesMode="markowitz") variance_markowitz=variance(portfolio); # weights are normalized based on a sum of absolute values (Lintner) portfolio_settings(portfolio, shortSalesMode="lintner") variance_lintner=variance(portfolio); plot(variance_markowitz,variance_lintner,title="Variance,shortSalesMode",legend=c("markowitz","lintner")) \end{lstlisting} \section{Data Sampling} These settings regulate how results of portfolio computations are returned. Depending on your usage scenario, some of them might bring significantly improvement to speed of your portfolio computations \subsection{Results Sampling Interval} Interval to be used for sampling computed results before returning them to the caller. Available interval values are: \begin{itemize} \item ``Xs'' - seconds \item ``Xm'' - minutes \item ``Xh'' - hours \item ``Xd'' - trading days (6.5 hours in a trading day) \item ``Xw'' - weeks (5 trading days in 1 week) \item ``Xmo'' - month (21 trading day in 1 month) \item ``Xy'' - years (256 trading days in 1 year) \item ``none'' - no sampling. \item ``last'' - only the very last data point is returned \end{itemize} Large sampling interval would produce smaller vector of results and would require less time spent on data transfer. Default value of ``1s'' indicates that data is returned for every second during trading hours. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-01 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # sample results every 30 seconds portfolio_settings(portfolio, resultsSamplingInterval="30s") variance_30s=variance(portfolio); # sample results every 5 minutes portfolio_settings(portfolio, resultsSamplingInterval="15m") variance_15m=variance(portfolio); plot(variance_30s,variance_15m,title="Variance,resultsSamplingInterval",legend=c("30s","15m")) \end{lstlisting} \subsection{Input Sampling Interval} Interval to be used as a minimum step for sampling input prices. Available interval values are: \begin{itemize} \item ``Xs'' - seconds \item ``Xm'' - minutes \item ``Xh'' - hours \item ``Xd'' - trading days (6.5 hours in a trading day) \item ``Xw'' - weeks (5 trading days in 1 week) \item ``Xmo'' - month (21 trading day in 1 month) \item ``Xy'' - years (256 trading days in 1 year) \item ``none'' - no sampling \end{itemize} Default value is ``none'', which indicates that no sampling is applied. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # sample input prices every 30 seconds portfolio_settings(portfolio, inputSamplingInterval="30s") variance_30s=variance(portfolio); # sample input prices every 5 min portfolio_settings(portfolio, inputSamplingInterval="5m") variance_5m=variance(portfolio); plot(variance_30s,variance_5m,title="Variance,inputSamplingInterval",legend=c("30s","5m")) \end{lstlisting} \section{Model Pipeline} \subsection{Window Length} Specifies rolling window length that should be used for computing portfolio and position metrics. When portfolio mode is set to ``portfolio'', it is also the length of rebalancing history window to be used. Available interval values are: \begin{itemize} \item ``Xs'' - seconds \item ``Xm'' - minutes \item ``Xh'' - hours \item ``Xd'' - trading days (6.5 calendar hours in a trading day) \item ``Xw'' - weeks (5 trading days in 1 week) \item ``Xmo'' - month (21 trading day in 1 month) \item ``Xy'' - years (256 trading days in 1 year) \item ``all'' - all observations are used \end{itemize} Default value is ``1d'' - one trading day. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # 1 hour rolling window portfolio_settings(portfolio, windowLength="1h") variance_1h=variance(portfolio); # 1 week rolling window portfolio_settings(portfolio, windowLength="1d") variance_1d=variance(portfolio); plot(variance_1h,variance_1d,title="Variance,windowLength",legend=c("1h","1d")) \end{lstlisting} \subsection{Time Scale} Interval to be used for scaling return distribution statistics and producing metrics forecasts at different horizons. Available interval values are: \begin{itemize} \item ``Xs'' - seconds \item ``Xm'' - minutes \item ``Xh'' - hours \item ``Xd'' - trading days (6.5 hours in a trading day) \item ``Xw'' - weeks (5 trading days in 1 week) \item ``Xmo'' - month (21 trading day in 1 month) \item ``Xy'' - years (256 trading days in 1 year) \item ``all'' - actual interval specified during portfolio creation. \end{itemize} Default value is "1d" - one trading day. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # 1 hour time scale portfolio_settings(portfolio, timeScale="1h") variance_1h=variance(portfolio); # 1 week time scale portfolio_settings(portfolio, timeScale="1d") variance_1d=variance(portfolio); plot(variance_1h,variance_1d,title="Variance,timeScale",legend=c("1h","1d")) \end{lstlisting} \subsection{Microstructure Noise Model} Enables market microstructure noise model of distribution returns.\\ Defaults to TRUE, which means that microstructure effects are modeled and resulting HF noise is removed from metric calculations. When FALSE, HF microstructure noise is not separated from asset returns, which at high trading frequencies could yield noise-contaminated results. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # HF noise model is enabled portfolio_settings(portfolio, noiseModel=TRUE) variance_noiseModel_TRUE=variance(portfolio); # HF noise model is disabled portfolio_settings(portfolio, noiseModel=FALSE) variance_noiseModel_FALSE=variance(portfolio); plot(variance_noiseModel_TRUE,variance_noiseModel_FALSE,title="Variance,noiseModel",legend=c("TRUE","FALSE")) \end{lstlisting} \subsection{Jumps/Outliers Model} Used to select jump filtering mode when computing return statistics. Available modes are: \begin{itemize} \item ``none'' - price jumps are not filtered anywhere \item ``moments'' - price jumps are filtered only when computing return moments (i.e. for expected return, variance, skewness, kurtosis and derived metrics) \item ``all'' - price jumps are filtered from computed returns, prices and all return metrics. \end{itemize} \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # Price jumps detection is enabled for returns and moments portfolio_settings(portfolio, jumpsModel="all") variance_all=variance(portfolio); # Price jumps detection is disabled portfolio_settings(portfolio, jumpsModel="none") variance_none=variance(portfolio); plot(variance_all,variance_none,title="Variance,jumpsModel",legend=c("all","none")) \end{lstlisting} \subsection {Density Model} Used to select density approximation model of return distribution. Available models are: \begin{itemize} \item ``GLD'' - Generalized Lambda Distribution \item ``CORNER\_FISHER'' - Corner-Fisher approximation \item ``NORMAL'' - Gaussian distribution \end{itemize} Defaults to ``GLD'', which would fit a very broad range of distribution shapes. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # Using normal density portfolio_settings(portfolio, densityModel="NORMAL") util_plotDensity(dist_density(portfolio,pValueLeft=0.6,pValueRight=1,nPoints=100,addNormalDensity=TRUE)) # Using Generalized Lambda density portfolio_settings(portfolio, densityModel="GLD") util_plotDensity(dist_density(portfolio,pValueLeft=0.6,pValueRight=1,nPoints=100,addNormalDensity=TRUE)) \end{lstlisting} \subsection {Factor Model} Factor model to be used when computing portfolio metrics. Available models are: \begin{itemize} \item ``sim'' - portfolio metrics are computed using the Single Index Model \item ``direct'' - portfolio metrics are computed using portfolio value itself (experimental) \end{itemize} Defaults to "sim", which implies that the Single Index Model is used to compute portfolio metrics. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # Single Index Model is used portfolio_settings(portfolio, factorModel="sim") variance_sim=variance(portfolio); # Direct model is used portfolio_settings(portfolio, factorModel="direct") variance_direct=variance(portfolio); plot(variance_sim,variance_direct,title="Variance,factorModel",legend=c("sim","direct")) \end{lstlisting} \subsection {Fractal Price Model} Used to enable mono-fractal price assumptions (fGBM) when time scaling return moments. Defaults to TRUE, which implies that computed Hurst exponent is used to scale return moments. When FALSE, price is assumed to follow regular GBM with Hurst exponent = 0.5. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # Fractal price model is enabled portfolio_settings(portfolio, fractalPriceModel=TRUE) variance_fractal=variance(portfolio); # Fractal price model is disabled portfolio_settings(portfolio, fractalPriceModel=FALSE) variance_nonfractal=variance(portfolio); plot(variance_fractal,variance_nonfractal,title="Variance,fractalPriceModel",legend=c("enabled","disabled")) \end{lstlisting} \subsection{Drift Term} Used to enable drift term (expected return) when computing probability density approximation and related metrics (e.g. CVaR, Omega Ratio, etc.). Defaults to FALSE, which implies that distribution is centered around expected return. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # Drift term is enabled portfolio_settings(portfolio, driftTerm=TRUE) ES_driftTerm_TRUE=expected_shortfall(portfolio,0.95); # Drift term is disabled portfolio_settings(portfolio, driftTerm=FALSE) ES_driftTerm_FALSE=expected_shortfall(portfolio,0.95); plot(ES_driftTerm_TRUE,ES_driftTerm_FALSE,title="Expected Shortfall,driftTerm",legend=c("TRUE","FALSE")) \end{lstlisting} \section{Transactional Costs} These settings provide a framework for adding variable and fixed transactional costs into return, expected return and profit calculations. All metrics based on expected return like Sharpe Ratio, VaR (with drift term enabled) would reflect transactional costs in their computations. \subsection{Cost Per Share} Amount of transaction costs per share. Default value is 0. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionAAPL=position_add(portfolio,'AAPL', c(100,300,500,150), time=c("2014-10-01 09:30:00", "2014-10-01 11:30:00", "2014-10-01 15:30:00", "2014-10-02 11:30:00")) # Transactional costs per share are 0.5 cent portfolio_settings(portfolio, txnCostPerShare=0.005) return_5=log_return(portfolio) txn_costs_5=txn_costs(portfolio) # Transactional costs per share are 0.1 cent portfolio_settings(portfolio, txnCostPerShare=0.001) return_1=log_return(portfolio) txn_costs_1=txn_costs(portfolio) plot(return_5,return_1,title="Return,txnCostPerShare",legend=c("0.005","0.001")) plot(txn_costs_5,txn_costs_1,title="Txn Costs,txnCostPerShare",legend=c("0.005","0.001")) \end{lstlisting} \subsection {Cost Per Transaction} Amount of fixed costs per transaction. Defaults to 0. \begin{lstlisting} require(PortfolioEffectHFT) portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionAAPL=position_add(portfolio,'AAPL', c(100,300,500,150), time=c("2014-10-01 09:30:00", "2014-10-01 11:30:00", "2014-10-01 15:30:00", "2014-10-02 11:30:00")) # Fixed costs per transaction are 9 dollars portfolio_settings(portfolio, txnCostFixed=19.0) return_19=log_return(portfolio) txn_costs_19=txn_costs(portfolio) # Fixed costs per transaction are 1 dollar portfolio_settings(portfolio, txnCostFixed=1.0) return_1=log_return(portfolio) txn_costs_1=txn_costs(portfolio) plot(return_19,return_1,title="Return,txnCostFixed",legend=c("19.0","1.0")) plot(txn_costs_19,txn_costs_1,title="Txn Costs,txnCostFixed",legend=c("19.0","1.0")) \end{lstlisting} \chapter{Portfolio Optimization} \section{Optimization Goals \& Constraints} A classic problem of constructing a portfolio that meets certain maximization/minimization goals and constraints is addressed in our version of a multi-start portfolio optimization algorithm. At every time step optimization algorithm tries to find position weights that best meet optimization goals and constraints. \subsection{Key Features} \begin{itemize} \item A multi-start approach is used to compare local optima with each other and select a global optimum. Local optima are computed using a modified method of parallel tangents (PARTAN). \item When optimization algorithm is supplied with mutually exclusive constraints, it would try to produce result that is equally close (in absolute terms) to all constraint boundaries. For instance, constraints ``x > 6'' and ``x < 4'' are mutually exclusive, so the optimization algorithm would choose ``x = 5'', which is a value that has the smallest distance to both constraints. \item Portfolio metrics change over time, but optimization uses only the latest value in the time series. Therefore, the faster metric series would change, the more likely current optimal weights would deviate from the optimal weights at the next time step. \item Optimization results depend on provided portfolio settings. For example, short windowLength would produce "spot" versions of portfolio metrics and computed optimal weights would change faster to reflect shortened metric horizon. \end{itemize} \subsection{Optimization Goals} Optimization algorithm requires a single maximization/minimization goal to be set using \href{https://www.portfolioeffect.com/docs/platform/quant/functions/optimization-functions/optimization-goal}{optimization\_goal()} method that operates on a portfolio (see \href{https://www.portfolioeffect.com/docs/platform/quant/manuals/portfolio-construction}{portfolio construction}). Returned optimizer object could be used to add optional optimization costraints and then passed to the \href{https://www.portfolioeffect.com/docs/platform/quant/functions/optimization-functions/optimization-run}{optimization\_run} method to launch portfolio optimization. \begin{lstlisting} portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) portfolio_settings(portfolio, portfolioMetricsMode='price', resultsSamplingInterval='30m') # set optimization goal optimizer=optimization_goal(log_return(portfolio),"max") # launch optimization and obtain optimal portfolio optimalPortfolio=optimization_run(optimizer) plot(log_return(portfolio),log_return(optimalPortfolio),title="Portfolio Return",legend=c("Simple Portfolio","Optimal Portfolio")) \end{lstlisting} The following portfolio metrics could currently be used as optimization goals: \begin{description} \item[``variance(portfolio)''] \hfill \\ portfolio returns variance \item[``value\_at\_risk(portfolio)''] \hfill \\ portfolio Value-at-Risk \item[``expected\_shortfall(portfolio)''] \hfill \\ portfolio Conditional Value-at-Risk (Expected Tail Loss) \item[``expected\_return(portfolio)''] \hfill \\ portfolio expected return \item[``log\_return(portfolio)''] \hfill \\ portfolio return \item[``sharpe\_ratio(portfolio)''] \hfill \\ portfolio Sharpe Ratio \item[``mod\_sharpe\_ratio(portfolio)''] \hfill \\ portfolio modified Sharpe Ratio \item[``starr\_ratio(portfolio)''] \hfill \\ portfolio STARR Ratio \item[``weight\_transform(portfolio,"equiweight")''] \hfill \\ no optimization is performed and constraints are not processes. Portfolio positions are returned with equal weights \end{description} \subsection{Adding Constraints} Optimization constraints cover both metric-based and weight-based constraints. Metric-based constraints limit portfolio-level metrics to a certain range of values. For example, zero beta constraint would produce market-neutral optimal portfolio. Weight-based constraints operate on optimal position weights or sum of weights to give control over position concentration risks or short-sales assumptions. \par Constraint methods could be chained to produce complex optimization rules: \par Since position quantities are integer numbers and weights are decimals, a discretization error is introduced while converting optimal position weights to corresponding quantities. By default, optimal portfolio starts with a value of the initial portfolio. Portfolio value could be fixed to a constant level at every optimization step (see corresponding constraint below). Higher portfolio value could be used to keep difference between computed optimal weights and effective weights based on position quantities small. Lower portfolio value or higher asset price would normally increase discretization error. \begin{lstlisting} # create portfolio and add positions portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) positionAAPL=position_add(portfolio,'AAPL',300) portfolio_settings(portfolio, portfolioMetricsMode='price', resultsSamplingInterval='30m') # set optimization goal optimizer=optimization_goal(sharpe_ratio(portfolio),"max") # add constraints optimizer=optimization_constraint(optimizer,beta(portfolio),"=",0) optimizer=optimization_constraint(optimizer,weight(positionGOOG),">=",0.5) optimizer=optimization_constraint(optimizer,variance(portfolio),"<=",0.02) optimizer=optimization_constraint(optimizer,value(portfolio),"=",10^6) # launch optimization and obtain optimal portfolio optimalPortfolio=optimization_run(optimizer) plot(sharpe_ratio(portfolio),sharpe_ratio(optimalPortfolio),title="Sharpe Ratio",legend=c("Simple Portfolio","Optimal Portfolio")) plot(beta(portfolio),beta(optimalPortfolio),title="Beta",legend=c("Simple Portfolio","Optimal Portfolio")) plot(variance(portfolio),variance(optimalPortfolio),title="Variance",legend=c("Simple Portfolio","Optimal Portfolio")) plot(weight(portfolio_getPosition(portfolio,'GOOG')),weight(portfolio_getPosition(optimalPortfolio,'GOOG')),title="Weight GOOG",legend=c("Simple Portfolio","Optimal Portfolio")) \end{lstlisting} \subsection{Scalar Constraints} Scalar constraints are the simplest type of optimization boundaries. They require a single constant that is applied over a full time span of portfolio optimization. An example below sets portfolio beta constraint to be greater or equal to 0.1. \begin{lstlisting} # create portfolio and add positions portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionC=position_add(portfolio,'C',500) positionGOOG=position_add(portfolio,'GOOG',600) # rebalancing every minute, static portfolio ignores rebalancing history portfolio_settings(portfolio, portfolioMetricsMode='price', resultsSamplingInterval='30m') # set optimization goal and define constraints optimizer=optimization_goal(sharpe_ratio(portfolio),"max") optimizer=optimization_constraint(optimizer,beta(portfolio), "<=", constraintValue = 0.1) # run optimization optimalPortfolio=optimization_run(optimizer) # plot results plot(beta(optimalPortfolio),beta(portfolio), title="Beta", legend=c("Optimal Beta","Original Beta")) \end{lstlisting} \subsection{Vector Constraints} Instead of using a single scalar, one could specify an vector of constraint values with corresponding timestamps. Optimization algorithm would then automatically determine when certain constraint value should be applied based on the current rebalancing time. \begin{lstlisting} # create portfolio and add positions portfolio=portfolio_create(fromTime="2014-10-01 09:30:00", toTime="2014-10-02 16:00:00") positionAAPL=position_add(portfolio,'AAPL',500) positionGOOG=position_add(portfolio,'GOOG',600) # rebalancing every minute, static portfolio ignores rebalancing history portfolio_settings(portfolio, portfolioMetricsMode='price', resultsSamplingInterval='30m') betaVector = cbind(c("2014-10-01 09:30:00","2014-10-01 12:30:00"), c(0.1,0.5)) # set optimization goal and define constraints optimizer=optimization_goal(sharpe_ratio(portfolio),"max") optimizer=optimization_constraint(optimizer,beta(portfolio), "<=", constraintValue = betaVector) # run optimization optimalPortfolio=optimization_run(optimizer) # plot results plot(beta(optimalPortfolio),beta(portfolio), title="Beta", legend=c("Optimal Beta","Original Beta")) \end{lstlisting} \end{document}