Functions

using PortfolioAnalytics
using Dates
using TSFrames

dates = Date(2020, 12, 31):Month(1):Date(2021, 12, 31)
TSLA = [235.22,264.51,225.16,222.64,236.48,208.40,226.56,229.06,245.24,258.49,371.33,381.58,352.26]
NFLX = [540.73,532.39,538.85,521.66,513.47,502.81,528.21,517.57,569.19,610.34,690.31,641.90,602.44]
MSFT = [222.42,231.96,232.38,235.77,252.18,249.68,270.90,284.91,301.88,281.92,331.62,330.59,336.32]

prices_ts = TSFrame([TSLA NFLX MSFT], dates, colnames=[:TSLA, :NFLX, :MSFT])

13×3 TSFrame with Date Index
 Index       TSLA     NFLX     MSFT    
 Date        Float64  Float64  Float64 
───────────────────────────────────────
 2020-12-31   235.22   540.73   222.42 
 2021-01-31   264.51   532.39   231.96 
 2021-02-28   225.16   538.85   232.38 
 2021-03-31   222.64   521.66   235.77 
 2021-04-30   236.48   513.47   252.18 
 2021-05-31   208.4    502.81   249.68 
 2021-06-30   226.56   528.21   270.9  
 2021-07-31   229.06   517.57   284.91 
 2021-08-31   245.24   569.19   301.88 
 2021-09-30   258.49   610.34   281.92 
 2021-10-31   371.33   690.31   331.62
 2021-11-30   381.58   641.9    330.59
 2021-12-31   352.26   602.44   336.32

weights = [0.4, 0.4, 0.2]
3-element Vector{Float64}:
 0.4
 0.4
 0.2
PortfolioAnalytics.asset_returnFunction
asset_return(price::TSFrame, period::Int=1; method::String="simple")

Calculates returns form asset prices.

Arguments:

  • price::TSFrame: column(s) of TSFrame object of asset prices
  • period::Int=1: return period
  • method::String="simple": return method, available methods; "simple" and "log"

Example

julia> returns = asset_return(prices_ts)
12×3 TSFrame with Date Index
 Index       TSLA        NFLX        MSFT        
 Date        Float64?    Float64?    Float64?    
─────────────────────────────────────────────────
 2021-01-31   0.124522   -0.0154236   0.0428918
 2021-02-28  -0.148766    0.012134    0.00181066
 2021-03-31  -0.011192   -0.0319013   0.0145882
 2021-04-30   0.0621631  -0.0156999   0.0696017
 2021-05-31  -0.118742   -0.0207607  -0.00991355
 2021-06-30   0.0871401   0.0505161   0.0849888
 2021-07-31   0.0110346  -0.0201435   0.0517165
 2021-08-31   0.0706365   0.0997353   0.0595627
 2021-09-30   0.0540287   0.0722957  -0.066119
 2021-10-31   0.436535    0.131025    0.176291
 2021-11-30   0.0276035  -0.0701279  -0.00310596
 2021-12-31  -0.0768384  -0.0614737   0.0173326


 julia> log_returns = asset_return(prices_ts, method = "log")
12×3 TSFrame with Date Index
 Index       TSLA        NFLX        MSFT        
 Date        Float64?    Float64?    Float64?    
─────────────────────────────────────────────────
 2021-01-31   0.117358   -0.0155438   0.0419975
 2021-02-28  -0.161068    0.0120609   0.00180902
 2021-03-31  -0.0112551  -0.0324212   0.0144828
 2021-04-30   0.0603075  -0.0158244   0.0672864
 2021-05-31  -0.126404   -0.0209792  -0.00996302
 2021-06-30   0.0835505   0.0492816   0.0815697
 2021-07-31   0.0109742  -0.0203492   0.0504236
 2021-08-31   0.0682533   0.0950695   0.0578562
 2021-09-30   0.0526197   0.0698019  -0.0684062
 2021-10-31   0.362234    0.123125    0.162366
 2021-11-30   0.0272294  -0.0727082  -0.0031108
 2021-12-31  -0.079951   -0.0634445   0.0171842

Notes:

  • missing resulting from the function is automatically removed
source
PortfolioAnalytics.portfolio_returnFunction
portfolio_return(price::TSFrame, weights::Vector{<:Number}; period::Int=1, method::String="simple", colname::String="PORT")

Calculates portfolio return from asset prices and given weights.

Arguments:

  • price::TSFrame: column(s) of TSFrame object of asset prices
  • weights::Vector{<:Number}: weights of assets
  • period::Int=1: return period
  • method::String="simple": return method, available methods; "simple" and "log"
  • colname::String="PORT": name of the column of portfolio return

Example

julia> preturns = portfolio_return(prices_ts, weights)
12×1 TSFrame with Date Index
 Index       PORT        
 Date        Float64?    
─────────────────────────
 2021-01-31   0.0522176
 2021-02-28  -0.0542905
 2021-03-31  -0.0143197
 2021-04-30   0.0325056
 2021-05-31  -0.0577836
 2021-06-30   0.0720602
 2021-07-31   0.00669974
 2021-08-31   0.0800613
 2021-09-30   0.037306
 2021-10-31   0.262282
 2021-11-30  -0.017631
 2021-12-31  -0.0518583


 julia> log_preturns = portfolio_return(prices_ts, weights, method = "log")
 12×1 TSFrame with Date Index
  Index       PORT        
  Date        Float64?    
 ─────────────────────────
  2021-01-31   0.0491251
  2021-02-28  -0.0592409
  2021-03-31  -0.014574
  2021-04-30   0.0312505
  2021-05-31  -0.060946
  2021-06-30   0.0694468
  2021-07-31   0.00633473
  2021-08-31   0.0769004
  2021-09-30   0.0352874
  2021-10-31   0.226617
  2021-11-30  -0.0188137
  2021-12-31  -0.0539213

Notes:

  • missing resulting from the function is automatically removed.
source
julia> all_returns = TSFrames.join(returns, preturns)
12×4 TSFrame with Date Index
 Index       TSLA        NFLX        MSFT         PORT        
 Date        Float64?    Float64?    Float64?     Float64?    
──────────────────────────────────────────────────────────────
 2021-01-31   0.124522   -0.0154236   0.0428918    0.0522176
 2021-02-28  -0.148766    0.012134    0.00181066  -0.0542905
 2021-03-31  -0.011192   -0.0319013   0.0145882   -0.0143197
 2021-04-30   0.0621631  -0.0156999   0.0696017    0.0325056
 2021-05-31  -0.118742   -0.0207607  -0.00991355  -0.0577836
 2021-06-30   0.0871401   0.0505161   0.0849888    0.0720602
 2021-07-31   0.0110346  -0.0201435   0.0517165    0.00669974
 2021-08-31   0.0706365   0.0997353   0.0595627    0.0800613
 2021-09-30   0.0540287   0.0722957  -0.066119     0.037306
 2021-10-31   0.436535    0.131025    0.176291     0.262282
 2021-11-30   0.0276035  -0.0701279  -0.00310596  -0.017631
 2021-12-31  -0.0768384  -0.0614737   0.0173326   -0.0518583
PortfolioAnalytics.sharpeFunction
sharpe(R::TSFrame, Rf::Number=0)

Calculates Sharpe Ratio from asset returns. Output is a NamedArray.

Arguments:

  • R::TSFrame: column(s) of TSFrame object of asset returns
  • Rf::Number=0: Risk-free rate

Example

julia> sharpe = sharpe(returns)
4-element Named Vector{Float64}
Sharpe Ratio (Rf=0)  │
─────────────────────┼─────────
TSLA                 │ 0.288602
NFLX                 │ 0.170242
MSFT                 │ 0.606824
source
PortfolioAnalytics.mean_returnFunction
mean_return(R::TSFrame; geometric::Bool=true)

Calculates the mean return from asset returns. Output is a NamedArray.

Arguments:

  • R::TSFrame: column(s) of TSFrame object of asset returns
  • geometric::Bool=true: if true, calculates geometric mean

Example

julia> mean_return(returns)
4-element Named Vector{Float64}
μ    │
─────┼───────────
TSLA │  0.0342267
NFLX │ 0.00904634
MSFT │  0.0350585


julia> mean_return(returns, geometric=false)
4-element Named Vector{Float64}
μ    │
─────┼──────────
TSLA │ 0.0431772
NFLX │  0.010848
MSFT │ 0.0366371
source
using Plots
# plotting mean return of stocks and portfolio
bar(names(mreturn), mreturn, labels = false)
PortfolioAnalytics.stddevFunction
stddev(R::TSFrame)

Calculates the standard deviation of asset returns. Output is a NamedArray.

Example

julia> stddev(returns)
4-element Named Vector{Float64}
σ    │
─────┼──────────
TSLA │  0.149608
NFLX │ 0.0637211
MSFT │ 0.0603753
source
PortfolioAnalytics.momentsFunction
moments(R::TSFrame)

Calculates the (statistical) moments of asset returns. Output is a NamedArray.

Example

julia> pmoments = moments(returns)
4×4 Named Matrix{Float64}
Tickers ╲ Moments │      Mean        Std   Skewness   Kurtosis
──────────────────┼───────────────────────────────────────────
TSLA              │ 0.0431772   0.149608    1.36882    2.19682
NFLX              │  0.010848  0.0637211   0.604374  -0.808401
MSFT              │ 0.0366371  0.0603753   0.681468   0.790701

Output:

  • NamedArray; rows: tickers, columns: moments

Notes:

  • Kurtosis: excess kurtosis
source
PortfolioAnalytics.value_at_riskFunction
value_at_risk(R::TSFrame, p::Number=0.95; method::String="historical")

Calculates Value-at-Risk(VaR) from asset returns. Output is a NamedArray.

Arguments:

  • R::TSFrame: column(s) of TSFrame object of asset returns
  • p::Number=0.95: confidence level
  • method::String="historical": method of VaR calculation, available methods; "historical" and "parametric"

Example

julia> var_historical = value_at_risk(returns)
4-element Named Vector{Float64}
95% historical VaR  │
────────────────────┼───────────
TSLA                │  -0.132252
NFLX                │ -0.0653681
MSFT                │  -0.035206

julia> var_parametric = value_at_risk(returns, 0.90, method = "parametric")
4-element Named Vector{Float64}
90% parametric VaR  │
────────────────────┼───────────
TSLA                │  -0.148553
NFLX                │ -0.0708139
MSFT                │ -0.0407369
source
PortfolioAnalytics.esFunction
es(R::TSFrame, p::Number=0.95; method::String="historical")

Calculates Expected Shortfall (Conditional Value at Risk) from asset returns. Output is a NamedArray.

Arguments:

  • R::TSFrame: column(s) of TSFrame object of asset returns
  • p::Number=0.95: confidence level
  • method::String="historical": method of Expected Shortfall calculation

Example

julia> ES = es(returns)
4-element Named Vector{Any}
95% historical ES  │
───────────────────┼───────────
TSLA               │  -0.148766
NFLX               │ -0.0701279
MSFT               │  -0.066119

Notes:

  • Available methods: "historical" and "parametric"
  • Monte Carlo method will be implemented as part of the next release
source
PortfolioAnalytics.portfolio_optimizeFunction
portfolio_optimize(R::TSFrame, objective::String = "minumum variance"; target = Nothing, Rf::Number = 0)

Calculates the optimal Portfolio weights for a given objective and target return.

Arguments:

  • R::TSFrame: columns of TSFrame object of asset returns
  • objective::String = "minumum variance": portfolio objective, minimizes the standard deviation for the portfolio. Available objecives; "minumum variance" and "maximum sharpe"
  • target = Nothing: target portfolio mean return for a chosen objective. It allows to move accross the efficient frontier
  • Rf::Number = 0: risk-free rate, used with maximum sharpe

Example

julia> opt1 = portfolio_optimize(returns, "minumum variance")
julia> opt_weights = opt1.pweights
3-element Named Vector{Float64}
Optimal Weights  │
─────────────────┼───────
TSLA             │   -0.0
NFLX             │ 0.4438
MSFT             │ 0.5562


# plotting efficient frontier and decision space
julia> opt1.plt

Optimize minumum-variance portfolio with a minumum return target of 4%

julia> opt2 = portfolio_optimize(returns, "minumum variance", target = 0.04)

# optimal portfolio weights for a chosen objective and target return
julia> opt2.pweights
3-element Named Vector{Float64}
Optimal Weights  │
─────────────────┼───────
TSLA             │ 0.5142
NFLX             │    0.0
MSFT             │ 0.4858

Optimization of maximum sharpe portfolio

julia> opt3 = portfolio_optimize(returns, "maximum sharpe")
julia> opt3.pweights
3-element Named Vector{Float64}
Optimal Weights  │
─────────────────┼─────
TSLA             │ -0.0
NFLX             │  0.0
MSFT             │  1.0

julia> opt3.plt

Optimization of maximum sharpe portfolio with target return of at least 4%

julia> opt4 = portfolio_optimize(returns, "maximum sharpe", target = 0.04)
julia> opt4.pweights
3-element Named Vector{Float64}
Optimal Weights  │
─────────────────┼───────
TSLA             │ 0.5142
NFLX             │   -0.0
MSFT             │ 0.4858

Output:

Named Tuple

  • 1, preturn : portfolio mean return
  • 2, prisk: portfolio standard deviation
  • 3, psharpe: portfolio sharpe ratio
  • 4, pweights: optimal portfolio weights for chosen objective and defined target
  • 5, plt: plot of the efficient frontier and decision space
  • 6, pm: list of expected returns per each solution
  • 7, po: list of objective values per portfolio. If the objective is minimum-variance, then standard deviations of each optimal portfolio. If the objective is set to the maximum-sharpe, then the Sharpe Ratios of each portfolio.
  • 8, pw: list of weights per each solution
source
Example
bond = [0.06276629, 0.03958098, 0.08456482,0.02759821,0.09584956,0.06363253,0.02874502,0.02707264,0.08776449,0.02950032]
stock = [0.1759782,0.20386651,0.21993588,0.3090001,0.17365969,0.10465274,0.07888138,0.13220847,0.28409742,0.14343067]

R = TSFrame([bond stock], colnames  = [:bond, :stock])

Minumum variance portfolio.

opt = portfolio_optimize(R, "minumum variance")
opt.pweights
2-element Named Vector{Float64}
Optimal Weights  │ 
─────────────────┼───────
bond             │ 0.9463
stock            │ 0.0537

Minumum variance portfolio with 10% target return.

opt1 = portfolio_optimize(R, "minumum variance", target = 0.1)
opt1.plt

Maximum Sharpe portfolio with 15% target return.

opt2 = portfolio_optimize(R, "maximum sharpe", target = 0.15)
opt2.plt
using Plots
# plotting optimal weights for maximum sharpe portfolio with 15% return target
bar(names(opt2.pweights), opt2.pweights, labels = false)
PortfolioAnalytics.cumulative_returnFunction
cumulative_return(R::TSFrame; geometric::Bool=true, verbose=false)

Calculates the cumulative asset returns.

Arguments:

  • R::TSFrame: column(s) of TSFrame object of asset returns
  • geometric::Bool=true: if true, calculates geometric returns
  • verbose=false: if true, returns a TSFrame object of cumulaitve asset returns for data history

Example

julia> cumulative_return(returns)
3-element Named Vector{Float64}
Cumulative Return  │
───────────────────┼─────────
TSLA               │ 0.497577
NFLX               │ 0.114123
MSFT               │ 0.512094

julia> cumulative_return(returns, verbose=true)
12×3 TSFrame with Date Index
 Index       TSLA      NFLX      MSFT    
 Date        Float64   Float64   Float64 
─────────────────────────────────────────
 2021-01-31  1.12452   0.984576  1.04289
 2021-02-28  0.957232  0.996523  1.04478
 2021-03-31  0.946518  0.964733  1.06002
 2021-04-30  1.00536   0.949587  1.1338
 2021-05-31  0.885979  0.929873  1.12256
 2021-06-30  0.963183  0.976846  1.21797
 2021-07-31  0.973812  0.957169  1.28095
 2021-08-31  1.0426    1.05263   1.35725
 2021-09-30  1.09893   1.12873   1.26751
 2021-10-31  1.57865   1.27663   1.49096
 2021-11-30  1.62223   1.1871    1.48633
 2021-12-31  1.49758   1.11412   1.51209

 julia> cumulative_return(returns, geometric=false)
3-element Named Vector{Float64}
Cumulative Return  │
───────────────────┼─────────
TSLA               │ 0.518126
NFLX               │ 0.130176
MSFT               │ 0.439646
source
PortfolioAnalytics.drawdownsFunction
drawdowns(R::TSFrame; geometric::Bool=true, max_drawdown::Bool=false)

Calculates the drawdowns of asset or portfolio returns. Output is a TSFrame object of drawdowns.

Arguments:

  • R::TSFrame: column(s) of TSFrame object of asset returns
  • geometric::Bool=true: if true, calculates drawdowns from the geometric returns
  • max_drawdown::Bool=false: if true, returns maximum drawdown for asset(s) or a portfolio

Example

julia> drawdowns(returns)
12×3 TSFrame with Date Index
 Index       TSLA        NFLX        MSFT        
 Date        Float64     Float64     Float64     
─────────────────────────────────────────────────
 2021-01-31   0.0         0.0         0.0
 2021-02-28  -0.148766    0.0         0.0
 2021-03-31  -0.158293   -0.0319013   0.0
 2021-04-30  -0.10597    -0.0471003   0.0
 2021-05-31  -0.212128   -0.0668832  -0.00991355
 2021-06-30  -0.143473   -0.0197458   0.0
 2021-07-31  -0.134021   -0.0394915   0.0
 2021-08-31  -0.0728517   0.0         0.0
 2021-09-30  -0.0227591   0.0        -0.066119
 2021-10-31   0.0         0.0         0.0
 2021-11-30   0.0        -0.0701279  -0.00310596
 2021-12-31  -0.0768384  -0.127291    0.0

julia> drawdowns(returns, geometric=false)
12×3 TSFrame with Date Index
 Index       TSLA        NFLX         MSFT        
 Date        Float64     Float64      Float64     
──────────────────────────────────────────────────
 2021-01-31   0.0        -0.0154236    0.0
 2021-02-28  -0.132292   -0.00328963   0.0
 2021-03-31  -0.142245   -0.0351909    0.0
 2021-04-30  -0.0869655  -0.0508908    0.0
 2021-05-31  -0.192558   -0.0716515   -0.00878166
 2021-06-30  -0.115068   -0.0211354    0.0
 2021-07-31  -0.105255   -0.0412789    0.0
 2021-08-31  -0.0424401   0.0          0.0
 2021-09-30   0.0         0.0         -0.0502712
 2021-10-31   0.0         0.0          0.0
 2021-11-30   0.0        -0.0555787   -0.00217898
 2021-12-31  -0.0481756  -0.104299     0.0

julia> drawdowns(returns,  max_drawdown=true)
3-element Named Vector{Float64}
Maximum Drawdown  │
──────────────────┼──────────
TSLA              │ -0.212128
NFLX              │ -0.127291
MSFT              │ -0.066119


julia> drawdowns(returns, geometric=false, max_drawdown=true)
3-element Named Vector{Float64}
Maximum Drawdown  │
──────────────────┼───────────
TSLA              │  -0.192558
NFLX              │  -0.104299
MSFT              │ -0.0502712
source