cvar/0000755000176200001440000000000015120450157011205 5ustar liggesuserscvar/tests/0000755000176200001440000000000015105335521012347 5ustar liggesuserscvar/tests/testthat/0000755000176200001440000000000015120450157014207 5ustar liggesuserscvar/tests/testthat/test-VaR.R0000644000176200001440000001721715105335521016007 0ustar liggesuserslibrary(cvar) context("VaR") test_that("VaR works ok", { muA <- 0.006408553 sigma2A <- 0.0004018977 ## with quantile function res1 <- cvar::VaR(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A)) res2 <- cvar::VaR(qnorm, p_loss = 0.05, intercept = muA, slope = sqrt(sigma2A)) abs((res2 - res1)) # 0, intercept/slope equivalent to mean/sd expect_error(cvar::VaR(dnorm, dist.type = "pdf", p_loss = 0.05, intercept = muA, slope = sqrt(sigma2A)), "Not ready") cvar::VaR_qf(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A)) ## with cdf the precision depends on solving an equation res1a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A)) res2a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A)) abs((res1a - res2)) # 3.287939e-09 abs((res2a - res2)) # 5.331195e-11, intercept/slope better numerically expect_equal(res1, VaR_qf(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A))) expect_equal(res2a, VaR_cdf(pnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A))) set.seed(1236) a.num <- rnorm(100) VaR(a.num) ## test the fix for issue #2 expect_true(ES(a.num) == ES(a.num, p_loss = 0.05)) expect_true(ES(a.num) != ES(a.num, p_loss = 0.01)) ## as above, but increase the precision, this is probably excessive res1b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75) res2b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75) expect_lt( abs((res1b - res2)), 1e-12) # 6.938894e-18 # both within machine precision expect_lt( abs((res2b - res2)), 1e-12) # 1.040834e-16 ## relative precision is also good abs((res1b - res2)/res2) # 2.6119e-16 # both within machine precision abs((res2b - res2)/res2) # 3.91785e-15 ## an extended example with vector args, if "PerformanceAnalytics" is present if(require("PerformanceAnalytics")){ data(edhec, package = "PerformanceAnalytics") mu <- apply(edhec, 2, mean) sigma2 <- apply(edhec, 2, var) musigma2 <- cbind(mu, sigma2) ## compute in 2 ways with cvar::VaR vAz1 <- cvar::VaR(qnorm, p_loss = 0.05, mean = mu, sd = sqrt(sigma2)) vAz2 <- cvar::VaR(qnorm, p_loss = 0.05, intercept = mu, slope = sqrt(sigma2)) vAz1a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2)) vAz2a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2)) vAz1b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2), tol = .Machine$double.eps^0.75) vAz2b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2), tol = .Machine$double.eps^0.75) ## analogous calc. with PerformanceAnalytics::VaR vPA <- apply(musigma2, 1, function(x) PerformanceAnalytics::VaR(p = .95, method = "gaussian", invert = FALSE, mu = x[1], sigma = x[2], weights = 1)) ## the results are numerically the same max(abs((vPA - vAz1))) # 5.551115e-17 max(abs((vPA - vAz2))) # "" max(abs((vPA - vAz1a))) # 3.287941e-09 max(abs((vPA - vAz2a))) # 1.465251e-10, intercept/slope better max(abs((vPA - vAz1b))) # 4.374869e-13 max(abs((vPA - vAz2b))) # 3.330669e-16 ## compute in 2 ways with cvar::VaR; this time with transf = TRUE ## TODO: need more meaningful example(s) for this vAz1tr <- cvar::VaR(qnorm, p_loss = 0.05, mean = mu, sd = sqrt(sigma2), transf = TRUE) vAz2tr <- cvar::VaR(qnorm, p_loss = 0.05, intercept = mu, slope = sqrt(sigma2), transf = TRUE) vAz1atr <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2), transf = TRUE) vAz2atr <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2), transf = TRUE) vAz1btr <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2), tol = .Machine$double.eps^0.75, transf = TRUE) vAz2btr <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2), tol = .Machine$double.eps^0.75, transf = TRUE) } ## the matrix method m20 <- matrix(rnorm(40), ncol = 2) colnames(m20) <- c("A", "B") expect_equal(VaR(m20), VaR(m20, 0.05)) VaR(m20) VaR(m20, c(0.01, 0.05)) ## ES ## use 500 values to mamke 1% and 5% quantiles more likely to be different m500 <- matrix(rnorm(250), ncol = 2) ES(m500) ES(m500, 0.01) ES(m500, 0.05) ES(m500, c(0.01, 0.05)) ## transf = TRUE ES(m500, transf = TRUE) ES(m500, 0.01, transf = TRUE) ES(m500, 0.05, transf = TRUE) ES(m500, c(0.01, 0.05), transf = TRUE) VaR(m500, transf = TRUE) VaR(m500, 0.01, transf = TRUE) VaR(m500, 0.05, transf = TRUE) VaR(m500, c(0.01, 0.05), transf = TRUE) }) test_that("ES works ok", { expect_equal(ES(qnorm, dist.type = "qf"), ES(qnorm) ) ## Gaussian expect_equal(ES(qnorm, dist.type = "qf"), ES(pnorm, dist.type = "cdf") ) ## t-dist expect_equal(ES(qt, dist.type = "qf", df = 4), ES(pt, dist.type = "cdf", df = 4) ) expect_equal(ES(pnorm, p_loss = 0.95, dist.type = "cdf"), ES(qnorm, p_loss = 0.95, dist.type = "qf") ) ## - VaRES::esnormal(0.95, 0, 1) ## - PerformanceAnalytics::ETL(p=0.05, method = "gaussian", mu = 0, ## sigma = 1, weights = 1) # same ## this uses "pdf" expect_equal(ES(dnorm, p_loss = 0.05, dist.type = "pdf", qf = qnorm), ES(pnorm, p_loss = 0.05, dist.type = "cdf") ) ## several in one call ES(pnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "cdf") ES(dnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "pdf", qf = qnorm) ES(dnorm, p_loss = 0.05, dist.type = "pdf", qf = qnorm) ES(dnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "pdf", qf = qnorm) ES(dnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "pdf", qf = list(qnorm, qnorm, qnorm)) ES(dnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "pdf", qf = c(qnorm, qnorm, qnorm)) #### the above with transf = TRUE; TODO: need more meaningful examples #### expect_equal(ES(qnorm, dist.type = "qf", transf = TRUE), ES(qnorm, transf = TRUE) ) ## Gaussian expect_equal(ES(qnorm, dist.type = "qf", transf = TRUE), ES(pnorm, dist.type = "cdf", transf = TRUE) ) ## t-dist expect_lt(abs(ES(qt, dist.type = "qf", df = 4, transf = TRUE) - ES(pt, dist.type = "cdf", df = 4, transf = TRUE)), 1e-7 ) expect_equal(ES(pnorm, p_loss = 0.95, dist.type = "cdf", transf = TRUE), ES(qnorm, p_loss = 0.95, dist.type = "qf", transf = TRUE) ) ## - VaRES::esnormal(0.95, 0, 1) ## - PerformanceAnalytics::ETL(p=0.05, method = "gaussian", mu = 0, ## sigma = 1, weights = 1) # same ## this uses "pdf" expect_lt(abs(ES(dnorm, p_loss = 0.05, dist.type = "pdf", qf = qnorm, transf = TRUE) - ES(pnorm, p_loss = 0.05, dist.type = "cdf", transf = TRUE)), 1e-7 ) ## several in one call expect_lt(max(abs( ES(pnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "cdf", transf = TRUE) - ES(dnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "pdf", qf = qnorm, transf = TRUE) )), 1e-7) ES(dnorm, p_loss = 0.05, dist.type = "pdf", qf = qnorm, transf = TRUE) ES(dnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "pdf", qf = qnorm, transf = TRUE) expect_equal( ES(dnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "pdf", qf = list(qnorm, qnorm, qnorm), transf = TRUE), ES(dnorm, p_loss = c(0.1, 0.05, 0.01), dist.type = "pdf", qf = c(qnorm, qnorm, qnorm), transf = TRUE)) }) cvar/tests/testthat/a.RDS0000644000176200001440000000522615105335521015006 0ustar liggesusers}V 8cR\WEةdmWAer-ZR[,QtKtHf,3hdWy}{=<8p8N@#|6?B}twfWJ{xֺPZoWc@S+7\]iKbg&wGҋluMFh8A~n尊١r#}!t-qd\_.>hA"rA6 9hdmu tϼ8ِLG'dQJNH`Qb9\.1Ts1܅6iw Sv4:L`τAM>MIuД ;nǟ_C- 0)y= hx3k)|W[4Pơ:ND.UR7J$GF⸻˓M?x;ddZ'+ BR6heܐ/X Ш7@[mVCqbHJ]щCMh ?U@2 Wſ|4 ꆧe> Rhn֖E`zw ^ }15 s$)߯wi+1ME 4JE#zCCDiv&s?޿?Qsm"2nUXT vd=0K>] vLfB? P^VP _w-{]&;WzSEj镝R*DݘU)&k\q]h)0ds;TkdTufXuD ^6Fn[;U" &zt}1I!M.84v,@a+1;Pʖ"bF1łsͫR{ ~ߡC[6_tm_--C[W]#"py-e&J|*7A/瓟=e' ֳI o0ؼCmٮpJo3:> ݅ _6Q\uZAO$%;uk/Tw>͂IzfFl^LC|dÉ߹uƌm΅^*"F65;%I =$.ta "ݼ K?4[U0;9 X7zi_.Bp^]#T@r;ƣ- aJ">p=p]GɞAD& ֹ[>>U FW:ӧ oPwv Y C'_O&x <Zv/0Dg|1L=S p ƶ4\:sP.G8V]j5"K+c\$A>lX]7CCghoK}CߝMM󚖸ᭉEzx-8y-sKk59m_|쫍O$|q>{iCKA/*ō<=:D'߬-D9=վv R}՝էm8%Y BxzPc{:8;_"B\ 9t,mوˬN ɍO_ aOo&η::SBVّD a`_Z+4L3ܤiq3Vr cvar/tests/testthat/a_pred_before_6.0.RDS0000644000176200001440000001717615105335521017734 0ustar liggesusersZ 8۟.{*CsTlPQ*!B Y+i(˾ی11}+^}u=ν}!n p~^ñp-l7rm{Yr,~T>Z ƫ.ҶYo'Ja5 c5%->vݵ*C0\wusZh)7;N;;GŶ6I߄]m~=yI^c=pL[ASv.lmN fh[m(*v{9-b,#߿dĮ9?er>fu'.O(74\#Kȝ%\& Lh"r.%h<2D.|k O?q'oϒ_s{-87W_3PNCiTjG6]8Mz8p}"&=cY %@fSrQgJ<M{g) jW[ u~ OXEO牭*Iv#PX91:*6]U[{EBLYKX,RxiXV<G;$R6ٳ4[(|Ogvζn,yO&K/TqWεo$c#EVA!+Ãwh*h 59CfZӕOC^Ր_!:5:T#:G'w߰sۜ؈Se2_jMZ8:rs]3lZP0*q*pth196`x1- ݺ nht3?BM}uȓ( @#oʧ!j\_P{RMl,4reD4}A5Х0+?xnGÀ<oϡ;.=37 .^s8zdϱo*=;, P'URw~ԓWuj' FC9ODC\s {4~WuQ{ ຽvتꚂ͓7v$_c"VrնVa"Uϓ}.T2]543m/"W 0q|u+I.#]y}rׄB ]=h>P0 0i&b-Į 2Th-/CcߧWP'*̣:҄DZb P|hk?=b8/ZnzZ?`Qm3/48d@| h{-`:Bms0|n5(mҮPWI^[A)tSDycuC+:DߴCb*PY~ǰ Q9 A w !~ּ2.MlAEwoϽݣ^ie5hZwyȓDG+1?QGl[O΍1ULL!D3Ȱ~ƂL_1OĆ y G7<@IzXMOŖ|E-~&^,AB:rƩ!G0zҩLTr̲|/7XUFI=].{ ^ ʒ{bQ'/š rt<)ۄ77YyiP(QZw!ީxڞHb,D+|2QчBJ&0(Cda$jJ`(Hձ}k̊bfh& ;ٹt@K׽U.טή1~`KJ"ĬB~(}rvǎ5`tj X#k@WMI9l0%ܼE <u]\|ax5Cxn#ui# xy[H@˺&q#u$!2hsgĊi48PuPnWԵNĕ5WgT÷وBO MH.hhDtnn%bK̼r1Ȼ~E=<^[5i1978T/Nc9g\]{0SKΌ 'YΣ55PMJC%W#tr1-[PU}. '8U~yT+zltdmM&1o$q2G<^a""=^@@ҩ9h.;bi"w\0eGıu.a~ǾFLuC6hQwEõ~7CE蠁D[A1>e0밷ׂKMb{&hp s 4դIoLOzxx3vgT*Д2\%A>Zj_q \^] :xXq9>iTZlE=Tm!?;DoM w}̼vM=@[UI(yEk`v 4? FiFЧoS_ @C>EAߗ `^j4K~-`aI8 d'`c}Nj$hQXxTf}ˎy+v(ZቑIN6RNuR+ɑ0~i80靅GZucԬ&mf'֢:/ےLh}pPAtm^G rᗉASB l.79@.ru`mfxF}HEMحwc];(v@F~x0׀6Ã_ 8S`vF"d6(89D4kҲO)͆l ;RXEUҮ[wqFq[g:%9X"zu#'R R kL%KxɄ@8Sz 3Oޞ>|z_ - uyu{TRmVm>j!u U"[uOgQч"DRjX*ܴ. &-V"Jf3^` g¹:8wY/" #?ަf:ɛ1bg{]Wgk+W[7 F "k64iC䲹tR$^: UO;Ah&l=ۘU03^F؇ |z7$%I@k`Qvr>dGm2 csX]Ȧ*8+1fHGqBMv͡]Dq bE<|vTLsE &N+^d2ӒC+XҮ.ⰲk\YG}yE@- / ?&5BRW2~3Kz4OchOC~o_B6vak̜Led 8z/>Yɋ8G#PuwY(!\T~*"Eb72ZzL53=xk1/dEhꂛI[}NB|nҀwb Xx8+ĚE'˅ ol{Ty(r'1d a/_}9j2t"S[o ;=[,W`v8`"-]5 c?W7}C,Ձ.[0#h/ &[y]>[dM8k}wY̓L,vg?g ({fY|ƅ/+A\L}`ab8n%`?vyo^X{ub Ꮅmv׶߱rɨ Hfw-G*ΞE/흏etG5fijE$P~h-d:9R@NU'!u?^wn׬ isFL-l!ܶcEf0|Mڬ&),ܩ).:`ŭ 5O!օ+h}`²\!YL[ >Z n_y87`,|ڗ!8yHпJZԪquBPë (t5U? _N 9mqln7$+^,qau|s5'12k7;_aA@0mg:̭$ChP+k Szs#,&4,;] Øf%C.71GL/gV~>+]ܿ qmS gQW~K!F^+%_۞X0>0|觐MPmZ.[\d # eigCί>-⸄>B2d-C'Iz gۋ8΄D)޾R02t})F&rW vjJtV"9G>sw4*튀j"*5F= / |"bF CҲ{mH8}f5*@o}+c?kÒoۦ "?N4.++z2-lShvHZև%Lx}|J8u$`M$U#vt_zh;,9qf @$+&䛱,Rzbp^NVp,۶%wE`ŭxXOsczn]OQzb / ;d@P6FdrҖ'5aur4xpL;]$4i|OS+Yz6:-JM*t&[Kr"=4 (:tSrι-;>qw aFDrׯX%2'H9JTݏ-Foα}g9"\`z8@i+*q_7OTPe53h6eC01ӺY03V@E |y7"p7c:?֭mIHn0B˖/`Rq(4+OZ e4_({*|H2ݳg$C'[O1n *A1A,;O .4Llu9|).p}t!wX8:0/{Fdt ˻i̊)vJ}0s!1<|0Bd_j{aq i>!& 捿//EjK@z }@}"l Kξ b{Q!0kj|z{Pj>.ߊE,`fK5E̪$sD BX nӍsi SI6:XSG0]3UO//2yv-⤄9A!G}9,Al FK p$o> f;:Am\~f:-=h0,ubUi ^n6. ktV#l͸f_Դ̝^8 _9h?̀C~?7[PiuY|=443*w<^[ie I8"g*~$?6ƴW@jxJ:oCNC?nډ& םҗCMoV-'-_%REg0nV/'oW~r'ꕭ [H}NaַDMr9")aT2%Y %_K\~ wwD% L3 P0WwJ;W<>Tk0l-ɲs]0r6(Yof5Uey F&Y^`?9t8y5PxHO,~XqR"*jVLtvw֝rrtwwT\&> SR ,g=bƯ۽m<2픃om]:$cvar/tests/testthat/a_pred.RDS0000644000176200001440000001721115105335521016015 0ustar liggesusersZ 8۟.{*CsTlPQ*!B Y+i(˾ی11}+^}u=w~y>č`p<;/ ? 7͆_!׶!GŐmʬ )mk=|ү_㰠1+n^k>X".)bt뮵EW1:BAofO9]up]!9z/=qN&ljFN >OGg{o5Oٹ8{Bq;/ooF춈~oWg'FD?pc ^,%"wp6<2u]4N `𭙮6"g2k?qnĵŸ8ҿw>K~po2g<<[ŝ)4Վl"'&q05$q"EL+r{ƞJmYʹ8(74Ϭ=y7$)?K/R4֯c'Jy(ß[U詻/fG±l3rctTlf< ;a*Y*Dwӂ̭y$Z&%vHFmD=Vg i &Pz'#/mEXV*M4y돀s {eayy:kk ^Mg1Fc^qnFJnq7@o@qe]aҽ("SE3R4}^$⮌kH$TFBV2T~`ksNAU+U+X9٫!Btjtn1&) 3٧e,p":qtz[fQkEٴ`UTP+blK#rlbkb7[ug~') w >QjX:GޔOC$F5 z]wlX'*ۃiZ :ˈhkK[37a0V<&ݎy0W@ICUw\z g o\ p c1TzZ?wxYNO9#^'B>$Ohr.d8 :, 0-,hh 9u{U5C7'ox h}I(k1fDmDϫ'~-]2Ao3dk })igx!_o=DFһa(V6\Fໂii!P/> @{<}*`t'8aMZx\.xD[@䩣26O:7iQ ?`d,5oGWb.lmAh:0_rWs!IEᶇ,/Dp6{2^,]9Ƌ N{(ʮ`NAMH} LT$Tig*l_n@F9csh^:. us qJegA_YM}]iiA<d6[^ֿOOTG-u''ҥ {µ v.~1={,q0^,.0<5O)&У0$w#,/g ^h5qȌJ|+ev[ta0ܦkQ۶ۥ]սSl>W0udϝǽiKTDybCmm/7PJPd,_a"zDy+T"1zμH:q3;:~ %_5&5\pA{0}v<y3MɟBG~ƠѨeTƝvhor`tZ~[) *jVff/mxC{ |i eۼҏjM DmC; fEQ.۸@Oe&ⳊwǠj䄦6"1*YD+o*'ir,Ԧi} gsv_4JSxԺr;){ vQ"q TE-( tfOn9jƒ<ӕrkAk8V:9D!F-&hPY/TvU`z?JЫ@᥯Foَ `dZ <$qkW*MG@WY [l[ee1 r*bW%51n@ `PU@qG oM*s=Qʣ-~z=qf#I0M" 9Ƽ:}6asDl#Bn>PQye]T 0؂ߞ{YG]1F ʒk\)T'%*Wb~4%b$==P11Cfa-LJ'b @BEo_#S+ =y\rNd--5܋[3LlXVFuSC*6o;aSṙ-e_n >Jz0쯻\41=ýb"9%fN^CA(xR on/BӆQ$0u#¾{i{"A7z1F=GB)W.ɓt)" VB|"3+"拙@4+ gjzE*-y^Ts\c:JPO-) MIk;B`{Щ]&` 䏴6~x:^E4%AÔțs}3?u%sO@f?y&]1@ץY$lm]#6-čLK%?N[8s~ϝ+fP"CAΧ!^Q6nh:W_Q f#z =5`6!a 5)AAo.q0SA"xmiפAvƄbSE;t]DsvAՂb"^Le.y;3.fd9@94zpg* Yr]2oi[&^ /6q烢uv$OHϥ:G<3DfW"D&Ѯ}0^>a i `Z؝Q@Sse |k=D|ŝOG,փ4syw%`hcuVtQ-jYPke@h`N;Pp5%hpN1 >xE7mI2WM&][P+$+wCMUv^c{W~&LEU}_F4ћv{Q,",%ာA; foF!b RE-;zNڡfj'F&9 K9QK$GD\ glw3jɏQQ#ڟD?[ToK^3} _cuaAEѷy1q_&M -7(SrۻP˳Ձ!3#35bn`߉Z^:vcӗX~  e;?\l~5 :DL΃=PPѬK˂B$>IH4-Ha UJ>oEu;[,o%o9xccMПJ3|J1T/qի'ycL-0W̄>U`nz{h~%Ԫ'48Q9HYz4j1BWel򄬚 0{WXtj>jQ?hx}%ƔvK> iG]rܤ]GghpCbEMT#ShM}==e.EE6IyapӺ`&ȶgbX(*'<@Wz*D PVtdP`be@"7x9&ozlYf.nQw] \m݀gVg'ZФ>J ^I{IH&T=jz͛:?ۢlc6WA̔c za{6,<& =Gݻ3ůo, aw!İ}#UIX 5%7fBvR1 dR1q7䳛8 {m NKzozbIʪrf5e,,/ I],M;ֶ"N]۾j!'6 :{w>uVꚥ:yCS KH"9yWuUxŲ߹]>$v(ϩ*~rdZ3 ^p֎e'7ƛkOp.L<[?A ~Fsfm0m*ph $}܀T?9k]Nx:P!M@*iPƝCE ɏC &uWl(:q'sޓZıuސҮ`{`o f㛛X~<Я\YKuFމ0|pKe i;өgdn%HbF3ְpeN_YCLr/՛eA09׈`ٙb4+?u9b v8;MY͔^nӞZ8e[ 1J"^)ǂ)[?E?Eo2orْX~j$&'ȦP0/K;r~`l%Er!kY5DPS9z V L]oWTQIlc)4(-/m|mc3ڔwc[hC6Wz ]Y;o|6XAv¥q]_ Ȟ=hfFe<@Ҳ>D(egZu ~S‘ kr&q@)g ȉ3ۤr Y1!ߌf)rKdٶ-+ /ngzƟC#w zWe@YY$Z6 ? ȭ Ydăc $ᇍM~]ңi90uTjR)6/,.g,{JLӬCn08!ےCwGmD$wZ_U"sbO J5h)D,ğx9 nȶl}0⇤[f]r>BTu݈h!R!sDgFIsv0Pioܤ'B/Z3[\ͤ}I+NWKa/}NzEf*=w:V +'@<B 8ˡG!v\vi)|o\9^ؐ6-C`Gr)jUV;j5NzvCћslYLyf.0nwLT8i䯛'*~s4懲!i,@ϙWXi Jmi,OYc\f=#i24sf ;cpȾzL\K~Q!/Fڀ0o8{4mc_X|ŗ"5x%PL>>%Kgn~(}5 >=]c=(q5|oOT0^"fU}gcY BX nӍsi SI6:XSG0]3UO//2yv-⤄9A!G}9,Al FK p$o> f;:Am\~f:-=h0,ubUi ^n6. ktV#l͸f_Դ̝^8 _9h?̀C~?7[PiuY|=443*w<^[ie I8"g*~$?6ƴW@jxJ:oCNC?nډ& םҗCMoV-'-_%REg0nV/'oW~r'ꕭ [H}NaDMr9"S xdK4K :;z!JZ7Ng*,`r9w$T pޫupZ ovF4s,zs}nm1ey a1Bޥld|LuJ[8.~ (i`&Jhޒe]/4aov*`zh$<}y6ͯ؜{-`h`z`~ɘ9Y v}c;V&z1`X"]']XZHMuܝ\r ~Xe$; 98[I0 r*RÒ/|p.jґX8o1D*U3̘8O~Nv9zz9;uvW?;,J:+G(+9bv/o[o0㿌cs;[%{[e.g3',4IJwo^8-+ ?$cvar/tests/testthat/test-garch.R0000644000176200001440000000511615105335521016376 0ustar liggesuserslibrary(cvar) context("garch") test_that("GarchModel works ok", { mo1a <- GarchModel(omega = 1, alpha = 0.3, beta = 0.5) expect_equal(class(mo1a), "garch1c1") mo1b <- GarchModel(omega = 1, alpha = 0.3, beta = 0.5, cond.dist = "norm") identical(GarchModel(mo1a, omega = 0.4), GarchModel( omega = 0.4, alpha = 0.3, beta = 0.5) ) ## GARCH(1,1) with standardised-t_5 mo_t <- GarchModel(omega = 1, alpha = 0.3, beta = 0.5, cond.dist = list("std", nu = 5)) expect_identical(mo_t, GarchModel(mo1a, cond.dist = list("std", nu = 5))) }) test_that("garch1c1 related functions work ok", { ## try to deal with the misterious error on TravisCI and devtools::test() ## set.seed(123) a_mo <- GarchModel(omega = 0.4, alpha = 0.3, beta = 0.5) a <- sim_garch1c1(a_mo, n = 100, n.start = 100, seed = 1234) a_pred <- predict(a_mo, n.ahead = 5, Nsim = 100, eps = a$eps, sigmasq = a$h, seed = 1235) ## 2019-03-13 deal with change in RNG in R-devel (for 3.6.0), see email from Kurt Hornik in Org/ ## I couldn't make his suggestion work. ## TODO: maybe it would be better to just load 'a' from a saved version. if(getRversion() < "3.6.0"){ a_saved <- "a_before_6.0.RDS" a_pred_saved <- "a_pred_before_6.0.RDS" }else{ a_saved <- "a.RDS" a_pred_saved <- "a_pred.RDS" } expect_equal_to_reference(a, a_saved) expect_equal_to_reference(a_pred, a_pred_saved) ## as above but without 'seed' sim_garch1c1(a_mo, n = 100, n.start = 100) predict(a_mo, n.ahead = 5, Nsim = 100, eps = a$eps, sigmasq = a$h) expect_equal(.get_dist_elem(NULL, "r"), .dist$norm$r) ## for now expect_error(.get_dist_elem("unknowndist", "r")) expect_error(.get_dist_elem(list("unknowndist"), "r")) expect_error(.get_dist_elem(5, "r")) .get_dist_elem(list("norm"), "r") .get_dist_elem(list("norm", mean = 5, sd = 3), "r") .get_dist_elem(list("norm", mean = 5, sd = 3, n = 10), "r") .get_dist_elem("std", "r") .get_dist_elem(list("std", df = 5), "r") .get_dist_elem(list("std", df = 5, n = 10), "r") .get_dist_elem(list("ged"), "r") expect_equal(.get_dist_elem(NULL, "p"), .dist$norm[["p"]]) .get_dist_elem("norm", "d") .get_dist_elem("norm", "p") .get_dist_elem("norm", "q") .get_dist_elem("norm", "r") .get_dist_elem(list("norm"), "p") .get_dist_elem(list("norm", mean = 4, sd = 2), "p") ## for now expect_error(.get_dist_elem("unknowndist")) expect_error(.get_dist_elem(list("unknowndist"))) expect_error(.get_dist_elem(5)) }) cvar/tests/testthat/a_before_6.0.RDS0000644000176200001440000000522615105335521016713 0ustar liggesusers}V 8cR\WEةdmWAer-ZR[,QtKtHf,3hdWy}{=<8p8N@#|6?B}twfWJ{xֺPZoWc@S+7\]iKbg&wGҋluMFh8A~n尊١r#}!t-qd\_.>hA"rA6 9hdmu tϼ8ِLG'dQJNH`Qb9\.1Ts1܅6iw Sv4:L`τAM>MIuД ;nǟ_C- 0)y= hx3k)|W[4Pơ:ND.UR7J$GF⸻˓M?x;ddZ'+ BR6heܐ/X Ш7@[mVCqbHJ]щCMh ?U@2 Wſ|4 ꆧe> Rhn֖E`zw ^ }15 s$)߯wi+1ME 4JE#zCCDiv&s?޿?Qsm"2nUXT vd=0K>] vLfB? P^VP _w-{]&;WzSEj镝R*DݘU)&k\q]h)0ds;TkdTufXuD ^6Fn[;U" &zt}1I!M.84v,@a+1;Pʖ"bF1łsͫR{ ~ߡC[6_tm_--C[W]#"py-e&J|*7A/瓟=e' ֳI o0ؼCmٮpJo3:> ݅ _6Q\uZAO$%;uk/Tw>͂IzfFl^LC|dÉ߹uƌm΅^*"F65;%I =$.ta "ݼ K?4[U0;9 X7zi_.Bp^]#T@r;ƣ- aJ">p=p]GɞAD& ֹ[>>U FW:ӧ oPwv Y C'_O&x <Zv/0Dg|1L=S p ƶ4\:sP.G8V]j5"K+c\$A>lX]7CCghoK}CߝMM󚖸ᭉEzx-8y-sKk59m_|쫍O$|q>{iCKA/*ō<=:D'߬-D9=վv R}՝էm8%Y BxzPc{:8;_"B\ 9t,mوˬN ɍO_ aOo&η::SBVّD a`_Z+4L3ܤiq38r cvar/tests/testthat.R0000644000176200001440000000006415105335521014332 0ustar liggesuserslibrary(testthat) library(cvar) test_check("cvar") cvar/MD50000644000176200001440000000301115120450157011510 0ustar liggesusers5d7f216da0075345f6f1433dc3ee1e6e *DESCRIPTION b85c3a439dcd9b16fff8ff649ae9e2c8 *NAMESPACE faabd45f502b917a7a7ae2200fc556f0 *NEWS.md 0242ae98e5c6dc2d450e8aa32447dea2 *R/VaR.R 802cd8124080e646e8a2c7ff7a4f13a5 *R/cvar-package.R efee4c21b22b3163ce3854f35904c753 *R/garch.R b63911fe58587200ee402d4c36f9422b *README.md 7d96ac1618fa59b9fd2c8054d0a12253 *build/partial.rdb a6ed210b33d927a495c2d1fbf2b00918 *build/vignette.rds 2a87d8dae0626a5d81eeee24dd1f9a72 *inst/REFERENCES.bib c06deb911fae19138395ca4f79cc026b *inst/doc/Guide_cvar.R 53492f8f1b03ecf1e3af93c7135bc9e3 *inst/doc/Guide_cvar.Rnw 10364e8593806f7101d95dd4a2b308e4 *inst/doc/Guide_cvar.pdf e4dafaeeae24235d07405728a3e35d2a *inst/pkgdown.yml 87b0745b2ba3fbc0cf70eeb607676f28 *man/ES.Rd 78aba2fb83715ba99ef50381b282342c *man/GarchModel.Rd c39b234962a3168fd3697caf8015d7fa *man/VaR.Rd 3356a7a7e885ad9616a837761d6c09af *man/cvar-package.Rd da01e698e5747d552b74980d83351d5b *man/predict.garch1c1.Rd cce9502065e5ccc46e867f033ecde953 *man/sim_garch1c1.Rd 32e67ae25ca51c0a429ccd166a1bfef7 *tests/testthat.R 58140e1d8933e014abc7ab5d481b9111 *tests/testthat/a.RDS 17bfcf5140c800a7cf57b6bc07e96019 *tests/testthat/a_before_6.0.RDS cf640ab785180cfce3d4ea1524be4494 *tests/testthat/a_pred.RDS 6c50b97c3d91d256f30aa902eb813362 *tests/testthat/a_pred_before_6.0.RDS bb9d45b2ffa4379c22b08f32bb057f3d *tests/testthat/test-VaR.R 2d588c9ad8807c0bf8954c6e98cbc8ed *tests/testthat/test-garch.R 53492f8f1b03ecf1e3af93c7135bc9e3 *vignettes/Guide_cvar.Rnw 7f515121f8177cec1dcd78ad0670bfde *vignettes/REFERENCES.bib cvar/R/0000755000176200001440000000000015120272321011401 5ustar liggesuserscvar/R/VaR.R0000644000176200001440000005276215105335521012235 0ustar liggesusers#' Compute Value-at-Risk (VaR) #' #' @description #' #' \code{VaR} is a generic function for computation of Value-at-Risk. The default method #' computes VaR corresponding to a distribution, usually fitted or implied by a fitted #' model. There are also methods for data (numeric or matrix). #' #' @note We use the traditional definition of VaR as the negated lower quantile. For example, #' if \eqn{X} are returns on an asset, VAR\eqn{{}_\alpha}{_a} = \eqn{-q_\alpha}{-q_a}, #' where \eqn{q_\alpha}{-q_a} is the lower \eqn{\alpha}{a} quantile of \eqn{X}. #' Equivalently, VAR\eqn{{}_\alpha}{_a} is equal to the lower \eqn{1-\alpha}{1-a} #' quantile of \eqn{-X}. #' #' @inheritParams ES #' #' @param intercept,slope compute VaR for the linear transformation \code{intercept + #' slope*X}, where \code{X} has distribution specified by \code{dist}, see Details. #' #' #' @details #' #' \code{VaR} is S3 generic. The meaning of the parameters for the methods defined in #' \pkg{cvar} and described here are the same as in \code{\link{ES}}, including the #' recycling rules. #' #' \code{VaR_qf} and \code{VaR_cdf} are streamlined, non-generic, variants for the common #' case when the \code{"..."} parameters are scalar. The parameters \code{p_loss}, #' \code{intercept}, and \code{slope} can be vectors, as for \code{VaR}. #' #' Argument \code{dist} can also be a numeric vector. In that case the ES is computed, #' effectively, for the empirical cumulative distribution function (ecdf) of the #' vector. The ecdf is not created explicitly and the \code{\link[stats]{quantile}} #' function is used instead for the computation of VaR. Arguments in \code{"..."} are #' passed eventually to \code{quantile()} and can be used, for example, to select a #' non-defult method for the computation of quantiles. #' #' If \code{dist} is of class \code{"matrix"}, then the numeric method is applied to each #' column. #' #' In practice, we may need to compute VaR associated with data. The distribution comes #' from fitting a model. In the simplest case, we fit a distribution to the data, #' assuming that the sample is i.i.d. For example, a normal distribution \eqn{N(\mu, #' \sigma^2)} can be fitted using the sample mean and sample variance as estimates of the #' unknown parameters \eqn{\mu} and \eqn{\sigma^2}, see section \sQuote{Examples}. For #' other common distributions there are specialised functions to fit their parameters and #' if not, general optimisation routines can be used. More soffisticated models may be #' used, even time series models such as GARCH and mixture autoregressive models. #' #' When argument \code{dist} represents log-returns, VaR is for the log-returns. Use #' \code{transf = TRUE} to return its value for the returns. #' #' #' @param tol tollerance #' #' @seealso \code{\link{ES}} for ES, #' #' \code{\link[=predict.garch1c1]{predict}} for examples with fitted models #' #' @concept Value at Risk #' #' @examples #' cvar::VaR(qnorm, c(0.01, 0.05), dist.type = "qf") #' #' ## the following examples use these values, obtained by fitting a normal distribution to #' ## some data: #' muA <- 0.006408553 #' sigma2A <- 0.0004018977 #' #' ## with quantile function, giving the parameters directly in the call: #' res1 <- cvar::VaR(qnorm, 0.05, mean = muA, sd = sqrt(sigma2A)) #' res2 <- cvar::VaR(qnorm, 0.05, intercept = muA, slope = sqrt(sigma2A)) #' abs((res2 - res1)) # 0, intercept/slope equivalent to mean/sd #' #' ## with quantile function, which already knows the parameters: #' my_qnorm <- function(p) qnorm(p, mean = muA, sd = sqrt(sigma2A)) #' res1_alt <- cvar::VaR(my_qnorm, 0.05) #' abs((res1_alt - res1)) #' #' ## with cdf the precision depends on solving an equation #' res1a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A)) #' res2a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A)) #' abs((res1a - res2)) # 3.287939e-09 #' abs((res2a - res2)) # 5.331195e-11, intercept/slope better numerically #' #' ## as above, but increase the precision, this is probably excessive #' res1b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", #' mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75) #' res2b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", #' intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75) #' abs((res1b - res2)) # 6.938894e-18 # both within machine precision #' abs((res2b - res2)) # 1.040834e-16 #' #' ## relative precision is also good #' abs((res1b - res2)/res2) # 2.6119e-16 # both within machine precision #' abs((res2b - res2)/res2) # 3.91785e-15 #' #' #' ## an extended example with vector args, if "PerformanceAnalytics" is present #' if (requireNamespace("PerformanceAnalytics", quietly = TRUE)) withAutoprint({ #' data(edhec, package = "PerformanceAnalytics") #' mu <- apply(edhec, 2, mean) #' sigma2 <- apply(edhec, 2, var) #' musigma2 <- cbind(mu, sigma2) #' #' ## compute in 2 ways with cvar::VaR #' vAz1 <- cvar::VaR(qnorm, 0.05, mean = mu, sd = sqrt(sigma2)) #' vAz2 <- cvar::VaR(qnorm, 0.05, intercept = mu, slope = sqrt(sigma2)) #' #' vAz1a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", #' mean = mu, sd = sqrt(sigma2)) #' vAz2a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", #' intercept = mu, slope = sqrt(sigma2)) #' #' vAz1b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", #' mean = mu, sd = sqrt(sigma2), #' tol = .Machine$double.eps^0.75) #' vAz2b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", #' intercept = mu, slope = sqrt(sigma2), #' tol = .Machine$double.eps^0.75) #' #' ## analogous calc. with PerformanceAnalytics::VaR #' vPA <- apply(musigma2, 1, function(x) #' PerformanceAnalytics::VaR(p = .95, method = "gaussian", invert = FALSE, #' mu = x[1], sigma = x[2], weights = 1)) #' ## the results are numerically the same #' max(abs((vPA - vAz1))) # 5.551115e-17 #' max(abs((vPA - vAz2))) # "" #' #' max(abs((vPA - vAz1a))) # 3.287941e-09 #' max(abs((vPA - vAz2a))) # 1.465251e-10, intercept/slope better #' #' max(abs((vPA - vAz1b))) # 4.374869e-13 #' max(abs((vPA - vAz2b))) # 3.330669e-16 #' }) #' #' @export VaR <- function(dist, p_loss = 0.05, ...){ UseMethod("VaR") } warn_about_x <- function(s){ warning("argument 'x' has been renamed to 'p_loss'. 'x' still works with this version of 'cvar' but will stop doing so in the next release.\n Please change your scripts suitably.\n It most cases there is no need to name this argument when calling ", s) } #' @name VaR #' #' @export VaR_qf <- function(dist, p_loss = 0.05, ..., intercept = 0, slope = 1, tol = .Machine$double.eps^0.5, x){ if(!missing(x)){ p_loss <- x warn_about_x("VaR_qf") } dist <- match.fun(dist) ## assumes "..." are scalar res <- if(length(p_loss) > 1) - sapply(p_loss, dist, ...) else - dist(p_loss, ...) - intercept + slope * res } #' @name VaR #' #' @export VaR_cdf <- function(dist, p_loss = 0.05, ..., intercept = 0, slope = 1, tol = .Machine$double.eps^0.5, x){ if(!missing(x)){ p_loss <- x warn_about_x("VaR_cdf") } dist <- match.fun(dist) ## assumes "..." are scalar res <- if(length(p_loss) > 1) - sapply(p_loss, cdf2quantile, ..., MoreArgs = list(cdf = dist, tol = tol)) else - cdf2quantile(p_loss, dist, tol = tol, ...) # TODO: interval? - intercept + slope * res } #' @name VaR #' #' @export VaR.default <- function(dist, p_loss = 0.05, dist.type = "qf", ..., intercept = 0, slope = 1, tol = .Machine$double.eps^0.5, transf = FALSE, x){ if(!missing(x)){ p_loss <- x warn_about_x("VaR") } dist <- match.fun(dist) ## TODO: add "rand" to dist.type ## TODO: include 'dist' in the condition and mapply? # fu <- switch(dist.type, # qf = function(y) - dist(y, ...), # cdf = function(y) - cdf2quantile(y, dist, tol = tol, ...), # pdf = { # stop("Not ready yet. Please supply quantile function or cdf") # }, # stop('argument dist.type should be one of "qf", "cdf" or "pdf"') # ) # sapply(p_loss, fu) res <- switch(dist.type, qf = - mapply(dist, p_loss, ...), cdf = - mapply(cdf2quantile, p_loss, ..., MoreArgs = list(cdf = dist, tol = tol)), pdf = { stop("Not ready yet. Please supply quantile function or cdf") }, stop('argument dist.type should be one of "qf", "cdf" or "pdf"') ) res <- - intercept + slope * res if(transf) - (exp(-res) - 1) else res } #' @name VaR #' #' @export VaR.numeric <- function(dist, p_loss = 0.05, ..., intercept = 0, slope = 1, transf = FALSE, x){ if(!missing(x)){ p_loss <- x warn_about_x("VaR") } ## dist is raw data here res <- - quantile(dist, p_loss, ...) res <- - intercept + slope * res if(transf) - (exp(-res) - 1) else res } #' @name VaR #' #' @export VaR.matrix <- function(dist, p_loss = 0.05, ..., intercept = 0, slope = 1, transf = FALSE, x){ if(!missing(x)){ p_loss <- x warn_about_x("VaR") } lst <- apply(dist, 2, identity, simplify = FALSE) # to use in 'mapply' res <- mapply(VaR.numeric, lst, intercept = intercept, slope = slope, transf = transf, MoreArgs = list(p_loss = p_loss, ...)) res } #' @title Compute expected shortfall (ES) #' #' @description #' Compute expected shortfall (ES). #' #' @details #' #' \code{ES} is a generic function for computation of expected shortfall. The default #' method computes ES corresponding to a distribution, usually fitted or implied by a #' fitted model. There are also methods for data (numeric or matrix). #' #' Alternative terms for ES include CVaR (conditional value at risk), AVaR (average value #' at risk), and ETL (expected tail loss). #' #' The default method of \code{ES} computes the expected shortfall for distributions #' specified by the arguments. \code{dist} is typically a function (or the name of #' one). What \code{dist} computes is determined by \code{dist.type}, whose default #' setting is \code{"qf"} (the quantile function). Other possible settings of #' \code{dist.type} include \code{"cdf"} and \code{"pdf"}. Additional arguments for #' \code{dist} can be given with the \code{"..."} arguments. #' #' Argument \code{dist} can also be a numeric vector. In that case the ES is computed, #' effectively, for the empirical cumulative distribution function (ecdf) of the #' vector. The ecdf is not created explicitly and the \code{\link[stats]{quantile}} #' function is used instead for the computation of VaR. Arguments in \code{"..."} are #' passed eventually to \code{quantile()} and can be used, for example, to select a #' non-defult method for the computation of quantiles. #' #' If \code{dist} is a matrix, the numeric method is applied to each of its columns. #' #' Except for the exceptions discussed below, a function computing VaR for the specified #' distribution is constructed and the expected shortfall is computed by numerically #' integrating it. The numerical integration can be fine-tuned with argument #' \code{control}, which should be a named list, see \code{\link{integrate}} for the #' available options. #' #' If \code{dist.type} is \code{"pdf"}, VaR is not computed, Instead, the partial #' expectation of the lower tail is computed by numerical integration of \code{x * #' pdf(x)}. Currently the quantile function is required anyway, via argument \code{qf}, #' to compute the upper limit of the integral. So, this case is mainly for testing and #' comparison purposes. #' #' #' A bunch of expected shortfalls is computed if argument \code{p_loss} or any of the #' arguments in \code{"..."} are of length greater than one. They are recycled to equal #' length, if necessary, using the normal \R recycling rules. #' #' \code{intercept} and \code{slope} can be used to compute the expected shortfall for #' the location-scale transformation \code{Y = intercept + slope * X}, where the #' distribution of \code{X} is as specified by the other parameters and \code{Y} is the #' variable of interest. The expected shortfall of \code{X} is calculated and then #' transformed to that of \code{Y}. Note that the distribution of \code{X} doesn't need #' to be standardised, although it typically will. #' #' The \code{intercept} and the \code{slope} can be vectors. Using them may be #' particularly useful for cheap calculations in, for example, forecasting, where the #' predictive distributions are often from the same family, but with different location #' and scale parameters. Conceptually, the described treatment of \code{intercept} and #' \code{slope} is equivalent to recycling them along with the other arguments, but more #' efficiently. #' #' The names, \code{intercept} and \code{slope}, for the location and scale parameters #' were chosen for their expressiveness and to minimise the possibility for a clash with #' parameters of \code{dist} (e.g., the Gamma distribution has parameter \code{scale}). #' #' When argument \code{dist} represents log-returns, ES is for the log-returns. Use #' \code{transf = TRUE} to return its value for the returns. Note that the ES of the #' returns cannot be obtained by exponentiating the ES for the log-returns. #' #' @param dist specifies the distribution whose ES is computed, usually a function or a name #' of a function computing quantiles, cdf, pdf, or a random number generator. Can also be #' a numeric vector or matrix, representing data, see section \sQuote{Details}. #' #' @param p_loss level, default is 0.05. #' #' @param dist.type a character string specifying what is computed by \code{dist}, such as #' "qf" or "cdf". #' #' @param qf quantile function, only used if \code{dist.type = "pdf"}. #' #' @param intercept,slope compute ES for the linear transformation \code{intercept + #' slope*X}, where \code{X} has distribution specified by \code{dist}, see Details. #' #' @param control additional control parameters for the numerical integration routine. #' #' @param transf use only if \code{"dist"} represents log-returns. If \code{TRUE}, give the #' result for the returns (not log-returns), see section \sQuote{Details}. #' #' @param ... passed on to \code{dist}. #' #' @param x deprecated and will soon be removed. \code{x} was renamed to \code{p_loss}, #' please use the latter. #' #' #' @return a numeric vector or matrix #' #' @seealso \code{\link{VaR}} for VaR, #' #' \code{\link[=predict.garch1c1]{predict}} for examples with fitted models #' #' @concept CVaR #' @concept AVaR #' @concept ETL #' @concept expected shortfall #' @concept conditional value at risk #' @concept average value at risk #' @concept expected tail loss #' #' @examples #' ES(qnorm) #' #' ## Gaussian #' ES(qnorm, dist.type = "qf") #' ES(pnorm, dist.type = "cdf") #' #' ## t-dist #' ES(qt, dist.type = "qf", df = 4) #' ES(pt, dist.type = "cdf", df = 4) #' #' ES(pnorm, 0.95, dist.type = "cdf") #' ES(qnorm, 0.95, dist.type = "qf") #' ## - VaRES::esnormal(0.95, 0, 1) #' ## - PerformanceAnalytics::ETL(p=0.05, method = "gaussian", mu = 0, #' ## sigma = 1, weights = 1) # same #' #' cvar::ES(pnorm, dist.type = "cdf") #' cvar::ES(qnorm, dist.type = "qf") #' cvar::ES(pnorm, 0.05, dist.type = "cdf") #' cvar::ES(qnorm, 0.05, dist.type = "qf") #' #' ## this uses "pdf" #' cvar::ES(dnorm, 0.05, dist.type = "pdf", qf = qnorm) #' #' #' ## this gives warning (it does more than simply computing ES): #' ## PerformanceAnalytics::ETL(p=0.95, method = "gaussian", mu = 0, sigma = 1, weights = 1) #' #' ## run this if VaRRES is present #' \dontrun{ #' x <- seq(0.01, 0.99, length = 100) #' y <- sapply(x, function(p) cvar::ES(qnorm, p, dist.type = "qf")) #' yS <- sapply(x, function(p) - VaRES::esnormal(p)) #' plot(x, y) #' lines(x, yS, col = "blue") #' } #' #' @export ES <- function(dist, p_loss = 0.05, ...){ UseMethod("ES") } CVaR <- AVaR <- ES # synonyms for ES, currently not exported #' @name ES #' #' @export ES.default <- function(dist, p_loss = 0.05, dist.type = "qf", qf, ..., intercept = 0, slope = 1, control = list(), transf = FALSE, x){ if(!missing(x)){ p_loss <- x warn_about_x("ES") } ## TODO: this method needs consolidation; it became repetitive when features were added. dist <- match.fun(dist) stopifnot(length(transf) == 1) # only scalar transf for this method if(transf){ ## can't apply intercept and slope at the end here; ## so pass them in each call to VaR or (recursively) ES if(length(p_loss) == 1 && all(sapply(list(..., intercept, slope), length) < 2)){ if(dist.type == "pdf"){ fu <- function(p) - (exp(-intercept + slope * p) - 1) * dist(p, ...) / p_loss iargs <- list(f = fu, lower = -Inf, upper = qf(p_loss)) # stop.on.error = FALSE,? }else{ ## TODO: check the theoretical justification here fu <- function(p){ v <- VaR(dist = dist, p_loss = p, dist.type = dist.type, intercept = intercept, slope = slope, ...) - (exp(-v) - 1) / p_loss } iargs <- list(f = fu, lower = 0, upper = p_loss) # stop.on.error = FALSE,? } iargs[names(control)] <- control res <- do.call("integrate", iargs)$value }else{ if(dist.type == "pdf"){ if(is.list(qf)) res <- mapply(ES, MoreArgs = list(dist = dist, dist.type = dist.type, control = control, transf = transf, intercept = intercept, slope = slope), p_loss = p_loss, qf = qf, ...) else res <- mapply(ES, MoreArgs = list(dist = dist, dist.type = dist.type, control = control, transf = transf, intercept = intercept, slope = slope, qf = qf), p_loss = p_loss, ...) }else{ res <- mapply(ES, MoreArgs = list(dist = dist, dist.type = dist.type, control = control), intercept = intercept, slope = slope, transf = transf, p_loss = p_loss, ...) } } res }else{ if(length(p_loss) == 1 && all(sapply(list(...), length) < 2)){ if(dist.type == "pdf"){ fu <- function(p) - p * dist(p, ...) / p_loss iargs <- list(f = fu, lower = -Inf, upper = qf(p_loss)) # stop.on.error = FALSE,? }else{ fu <- function(p) VaR(dist = dist, p_loss = p, dist.type = dist.type, ...) / p_loss iargs <- list(f = fu, lower = 0, upper = p_loss) # stop.on.error = FALSE,? } iargs[names(control)] <- control res <- do.call("integrate", iargs)$value }else{ if(dist.type == "pdf"){ if(is.list(qf)) res <- mapply(ES, MoreArgs = list(dist = dist, dist.type = dist.type, control = control), p_loss = p_loss, qf = qf, ...) else res <- mapply(ES, MoreArgs = list(dist = dist, dist.type = dist.type, control = control, qf = qf), p_loss = p_loss, ...) }else{ res <- mapply(ES, MoreArgs = list(dist = dist, dist.type = dist.type, control = control), p_loss = p_loss, ...) } } -intercept + slope * res } } #' @name ES #' #' @export ES.numeric <- function(dist, p_loss = 0.05, ..., intercept = 0, slope = 1, transf = FALSE, x){ if(!missing(x)){ p_loss <- x warn_about_x("ES") } v <- VaR.numeric(dist, p_loss = p_loss, ..., intercept = intercept, slope = slope) f <- if(transf){ function(x){ logret <- dist[dist <= -x] - mean(exp(logret) - 1) } }else # direct code doesn't work if length(v) > 1): # bad <- dist[dist <= - v] # res <- - mean(bad) function(x) - mean(dist[dist <= -x]) #browser() res <- sapply(v, f) res } #' @name ES #' #' @export ES.matrix <- function(dist, p_loss = 0.05, ..., intercept = 0, slope = 1, transf = FALSE, x){ if(!missing(x)){ p_loss <- x warn_about_x("ES") } ## v <- VaR.matrix(dist, p_loss = p_loss, ..., intercept = intercept, slope = slope) lst <- apply(dist, 2, identity, simplify = FALSE) # to use in 'mapply' res <- mapply(ES.numeric, lst, intercept = intercept, slope = slope, transf = transf, MoreArgs = list(p_loss = p_loss, ...)) res } cvar/R/cvar-package.R0000644000176200001440000001230015120272321014044 0ustar liggesusers#' @author Georgi N. Boshnakov #' #' @importFrom stats quantile runif #' @importFrom gbutils cdf2quantile #' @importFrom Rdpack reprompt #' #' #' #' @name cvar-package #' @aliases cvar #' #' @title Compute Expected shortfall (ES) and Value-at-Risk (VaR) #' #' @description Compute expected shortfall (ES) and Value at Risk (VaR) from a #' quantile function, distribution function, random number generator, #' probability density function, or data. ES is also known as Conditional #' Value at Risk (CVaR). Virtually any continuous distribution can be #' specified. \code{VaR()} and \code{ES()} are vectorised over the #' arguments. Some support for GARCH models is provided, as well. #' #' @details #' #' The name, \pkg{cvar}, of this package comes from \emph{Conditional Value #' at Risk} (CVaR), which is an alternative term for expected shortfall. #' #' There is a huge number of functions for computations with #' distributions in core \R and in contributed packages. Pdf's, #' cdf's, quantile functions and random number generators are #' covered comprehensively. The coverage of expected shortfall is #' more patchy but a large collection of distributions, including #' functions for expected shortfall, is provided by #' \insertCite{VaRES2013;textual}{cvar}. #' \insertCite{PerformanceAnalytics2018;textual}{cvar} and #' \insertCite{actuarJSS2008;textual}{cvar} provide packages #' covering comprehensively various aspects of risk measurement, #' including some functions for expected shortfall. #' #' Package \pkg{cvar} is a small package with, essentially, two main #' functions --- \code{ES} for computing the expected shortfall and #' \code{VaR} for Value at Risk. The user specifies the distribution by #' supplying one of the functions that define a continuous #' distribution---currently this can be a quantile function (qf), cumulative #' distribution function (cdf) or probability density function #' (pdf). Virtually any continuous distribution can be specified. The #' distributions are usually obtained by fitting distributions or #' specialised models to data. Instead of distributions, data for returns or #' log-returns can be supplied, as well. #' #' The functions \code{VaR} and \code{ES} are vectorised over the parameters #' of the distributions, making bulk computations more convenient, for #' example for forecasting or model evaluation. #' #' We chose to use the standard names \code{ES} and \code{VaR}, #' despite the possibility for name clashes with same named #' functions in other packages, rather than invent possibly #' difficult to remember alternatives. Just call the functions as #' \code{cvar::ES} and \code{cvar::VaR} if necessary. #' #' Locations-scale transformations can be specified separately #' from the other distribution parameters. This is useful when #' such parameters are not provided directly by the distribution #' at hand. The use of these parameters often leads to more #' efficient computations and better numerical accuracy even if #' the distribution has its own parameters for this purpose. Some #' of the examples for \code{VaR} and \code{ES} illustrate this #' for the Gaussian distribution. #' #' Since VaR is a quantile, functions computing it for a given #' distribution are convenience functions. \code{VaR} exported by #' \pkg{cvar} could be attractive in certain workflows because of #' its vectorised distribution parameters, the location-scale #' transformation, and the possibility to compute it from cdf's #' when quantile functions are not available. #' #' Some support for GARCH models is provided, as well. It is #' currently under development, see \code{\link{predict.garch1c1}} #' for current functionality. #' #' In practice, we may need to compute VaR associated with data. The #' distribution comes from fitting a model. In the simplest case, we fit a #' distribution to the data, assuming that the sample is i.i.d. For example, #' a normal distribution \eqn{N(\mu, \sigma^2)} can be fitted using the #' sample mean and sample variance as estimates of the unknown parameters #' \eqn{\mu} and \eqn{\sigma^2}, see section \sQuote{Examples}. For other #' common distributions there are specialised functions to fit their #' parameters and if not, general optimisation routines can be used. More #' soffisticated models may be used, even time series models such as GARCH #' and mixture autoregressive models. #' #' The functions \code{VaR} and \code{ES} are generic (S3). Further methods #' for them may be defined in other packages. #' #' @references \insertAllCited{} #' #' @seealso #' \code{\link{ES}}, #' \code{\link{VaR}} #' #' @concept VaR #' @concept CVaR #' @concept AVaR #' @concept ETL #' @concept Value at Risk #' @concept expected shortfall #' @concept conditional value at risk #' @concept average value at risk #' @concept expected tail loss #' #' @examples #' ## see the examples for ES(), VaR(), predict.garch1c1() #' "_PACKAGE" .onLoad <- function(lib, pkg){ Rdpack::Rdpack_bibstyles(package = pkg, authors = "LongNames") invisible(NULL) } cvar/R/garch.R0000644000176200001440000004320715120272005012615 0ustar liggesusers#' Specify a GARCH model #' #' Specify a GARCH model. #' #' Argument \code{model} can be the result of a previous call to \code{GarchModel}. #' Arguments in \code{"..."} overwrite current components of \code{model}. #' #' \code{GarchModel} guarantees that code using it will continue to work #' transparently for the user even if the internal represedtation of GARCH #' models in this package is changed or additional functionality is added. #' #' @param model a GARCH model or a list. #' @param ... named arguments specifying the GARCH model. #' @param model.class a class for the result. By default \code{GarchModel()} #' decides the class of the result. #' @return an object from suitable GARCH-type class #' #' @examples #' ## GARCH(1,1) with Gaussian innovations #' mo1a <- GarchModel(omega = 1, alpha = 0.3, beta = 0.5) #' mo1b <- GarchModel(omega = 1, alpha = 0.3, beta = 0.5, cond.dist = "norm") #' #' ## equivalently, the parameters can be given as a list #' p1 <- list(omega = 1, alpha = 0.3, beta = 0.5) #' mo1a_alt <- GarchModel(p1) #' mo1b_alt <- GarchModel(p1, cond.dist = "norm") #' stopifnot(identical(mo1a, mo1a_alt), identical(mo1b, mo1b_alt)) #' #' ## additional arguments modify values already in 'model' #' mo_alt <- GarchModel(p1, beta = 0.4) #' #' ## set also initial values #' mo2 <- GarchModel(omega = 1, alpha = 0.3, beta = 0.5, esp0 = - 1.5, h0 = 4.96) #' #' ## GARCH(1,1) with standardised-t_5 #' mot <- GarchModel(omega = 1, alpha = 0.3, beta = 0.5, cond.dist = list("std", nu = 5)) #' #' @concept GARCH model #' #' @export GarchModel <- function(model = list(), ..., model.class = NULL){ ## TODO: check the correctness of the parameters ## alpha, beta, cond.dist, 2nd order stationary, initial value for eps_t^2, h_t ## 2019-03-15 TODO: handle fGARCH models ## if(inherits(model, "fGARCH")){ ## ## }else{ dots <- list(...) if(length(dots) > 0) model[names(dots)] <- dots class(model) <- "GarchModel0" if(is.null(model.class) && length(model$alpha) == 1 && length(model$beta) == 1) class(model) <- "garch1c1" # GARCH(1,1), 'c' stands for 'comma' ## } model } ## 2022-11-01 change .dist from 'list' to 'env', was: # .dist <- list( # norm = list(d = call("dnorm", x = NA, mean = 0, sd = 1), # p = call("pnorm", q = NA, mean = 0, sd = 1), # q = call("qnorm", p = NA, mean = 0, sd = 1), # r = call("rnorm", n = NA, mean = 0, sd = 1)), # std = list(d = call("dstd", x = NA, mean = 0, sd = 1, nu = NA), # p = call("pstd", q = NA, mean = 0, sd = 1, nu = NA), # q = call("qstd", p = NA, mean = 0, sd = 1, nu = NA), # r = call("rstd", n = NA, mean = 0, sd = 1, nu = NA)), # ged = list(d = call("dged", x = NA, mean = 0, sd = 1, nu = NA), # p = call("pged", q = NA, mean = 0, sd = 1, nu = NA), # q = call("qged", p = NA, mean = 0, sd = 1, nu = NA), # r = call("rged", n = NA, mean = 0, sd = 1, nu = NA)) # ) .dist <- new.env() ## N(0,1) is built-in .dist$norm <- list(d = call("dnorm", x = NA, mean = 0, sd = 1), p = call("pnorm", q = NA, mean = 0, sd = 1), q = call("qnorm", p = NA, mean = 0, sd = 1), r = call("rnorm", n = NA, mean = 0, sd = 1)) # generalise and prepare to make fGarch suggested; was: # # .dist$std <- list(d = call("dstd", x = NA, mean = 0, sd = 1, nu = NA), # p = call("pstd", q = NA, mean = 0, sd = 1, nu = NA), # q = call("qstd", p = NA, mean = 0, sd = 1, nu = NA), # r = call("rstd", n = NA, mean = 0, sd = 1, nu = NA)) # # .dist$ged <- list(d = call("dged", x = NA, mean = 0, sd = 1, nu = NA), # p = call("pged", q = NA, mean = 0, sd = 1, nu = NA), # q = call("qged", p = NA, mean = 0, sd = 1, nu = NA), # r = call("rged", n = NA, mean = 0, sd = 1, nu = NA)) .dist_list <- list( ## TODO: allow different packages here by letting 'package be vector or completely ## refactor all this. Only '.get_dist_elem()' should know the implementation. std = list(package = "fGarch", d = list(str2lang("fGarch::dstd"), x = NA, mean = 0, sd = 1, nu = NA), p = list(str2lang("fGarch::pstd"), q = NA, mean = 0, sd = 1, nu = NA), q = list(str2lang("fGarch::qstd"), p = NA, mean = 0, sd = 1, nu = NA), r = list(str2lang("fGarch::rstd"), n = NA, mean = 0, sd = 1, nu = NA)), ged = list(package = "fGarch", d = list(str2lang("fGarch::dged"), x = NA, mean = 0, sd = 1, nu = NA), p = list(str2lang("fGarch::pged"), q = NA, mean = 0, sd = 1, nu = NA), q = list(str2lang("fGarch::qged"), p = NA, mean = 0, sd = 1, nu = NA), r = list(str2lang("fGarch::rged"), n = NA, mean = 0, sd = 1, nu = NA)) ) .get_dist_elem <- function(dist, what){ if(is.list(dist)){ params <- dist[-1] dist <- dist[[1]] }else params <- list() if(is.null(dist)){ ## TODO: this probably should be handled by the caller ## normal distribution is default res <- .dist$norm[[what]] }else{ stopifnot(is.character(dist), length(dist) == 1) gen <- .dist[[dist]] if(!is.null(gen)) # already prepared res <- gen[[what]] else{ # not prepared yet gen_list <- .dist_list[[dist]] if(is.null(gen_list)) stop("unknown distribution specified.") if(!requireNamespace(gen_list$package)) stop("requested distribution property needs package ", gen_list$package, "\nplease install package '", gen_list$package, "' and try again") ## prepare ## .dist is env, so assignment is persistent .dist[[dist]] <- lapply(gen_list[-1], as.call) # dropping $package res <- .dist[[dist]][[what]] if(is.null(res)) stop("property '", what, "' not available for '", dist, "'") } } if(length(params) > 0) # set parameters if specified res[names(params)] <- params res } #' Simulate GARCH(1,1) time series #' #' Simulate GARCH(1,1) time series. #' #' The simulated time series is in component \code{eps} of the returned value. #' For exploration of algorithms and eestimation procedures, the volatilities #' and the standardised innovations are also returned. #' #' The random seed at the start of the simulations is saved in the returned #' object. A speficific seed can be requested with argument \code{seed}. In #' that case the simulations are done with the specified seed and the old state #' of the random number generator is restored before the function returns. #' #' @param model a GARCH(1,1) model, an object obtained from \code{GarchModel}. #' @param n the length of the generated time series. #' @param n.start number of warm-up values, which are then dropped. #' @param seed an integer to use for setting the random number generator. #' #' @return a list with components: #' \item{eps}{the time series,} #' \item{h}{the (squared) volatilities,} #' \item{eta}{the standardised innovations,} #' \item{model}{the GARCH(1,1) model,} #' \item{.sim}{a list containing the parameters of the simulation,} #' \item{call}{the call.} #' #' @note This function is under development and may be changed. #' #' @concept GARCH model #' @concept simulate GARCH time series #' #' @export sim_garch1c1 <- function(model, n, n.start = 0, seed = NULL){ ## TODO: seed is not used currently garch1c1_fields <- c("omega", "alpha", "beta", "cond.dist", "eps0", "h0", "eps0sq") stopifnot(all(names(model) %in% garch1c1_fields)) omega <- model$omega alpha <- model$alpha beta <- model$beta rgen <- .get_dist_elem(model$cond.dist, "r") eps0 <- model$eps0 h0 <- model$h0 eps0sq <- model$eps0sq ## see Francq & Zakoian, p. 142, for alternative initialisations if(is.null(eps0sq)){ model$eps0sq <- eps0sq <- if(is.null(eps0)) omega / (1 - alpha - beta) else eps0^2 } if(is.null(h0)){ model$h0 <- h0 <- omega / (1 - alpha - beta) } N <- n + n.start h <- eps <- numeric(N) RNGstate <- .RNGstate(seed) ## 2020-03-04 was: if(!is.null(RNGstate$oldRNGstate)) # or !is.null(seed) ## (see comment at a similar command) if(!is.null(seed)) on.exit( if(is.null(RNGstate$RNGstate)){ ## TRUE id seed is NULL but also if .Random.seed was not set. "nothing to do" }else if(is.null(RNGstate$oldRNGstate)){ rm(".Random.seed", envir = .GlobalEnv) }else{ assign(".Random.seed", RNGstate$oldRNGstate, envir = .GlobalEnv) } ) rgen$n <- N # or: rgen[[2]] <- N eta <- eval(rgen) h[1] <- omega + alpha * eps0sq + beta * h0 for(i in 1:(N - 1)){ eps[i] <- sqrt(h[i]) * eta[i] h[i + 1] <- omega + alpha * eps[i]^2 + beta * h[i] } eps[N] <- sqrt(h[N]) * eta[N] ## TODO: return eta only conditionally? ## TODO: include the model in the returned value? ## TODO: return also the initialisation values (in a separate component)? list(eps = eps[(n.start + 1):N], h = h[(n.start + 1):N], eta = eta[(n.start + 1):N], model = model, .sim = list(seed = seed, rand.gen = rgen, n = n, n.start = n.start), call = match.call() ) } ## modelled after the beginning of `stats:::simulate.lm()` .RNGstate <- function(seed = NULL){ ## 2020-03-04 - changing the logic below ## ## if(!exists(".Random.seed", envir = .GlobalEnv, inherits = FALSE)) ## runif(1) oldRNGstate <- if(exists(".Random.seed", envir = .GlobalEnv)) get(".Random.seed", envir = .GlobalEnv) else NULL if (is.null(seed)) list(RNGstate = oldRNGstate) else{ ## This doesn't resolve the problem ## suppressWarnings(RNGversion("3.5.0")) # 2019-03-13 temporary, RNG changed in R-devel. ## # see email from Kurt Hornik in Org/ set.seed(seed) RNGstate <- structure(seed, kind = as.list(RNGkind())) ## on.exit(assign(".Random.seed", oldRNGstate, envir = .GlobalEnv)) list(RNGstate = RNGstate, oldRNGstate = oldRNGstate) } } #' Prediction for GARCH(1,1) time series #' #' Predict GARCH(1,1) time series. #' #' Plug-in prediction intervals and predictive distributions are obtained by #' inserting the predicted volatility in the conditional densities. For #' predictions more than one lag ahead these are not the real predictive #' distributions but the prediction intervals are usually adequate. #' #' For simulation prediction intervals we generate a (large) number of #' continuations of the given time series. Prediction intervals can be based on #' sample quantiles. The generated samples are stored in the returned object and #' can be used for further exploration of the predictive #' distributions. \code{dist_sim$eps} contains the simulated future values of #' the time series and \code{dist_sim$h} the corresponding (squared) #' volatilities. Both are matrices whose \code{i}-th rows contain the predicted #' quantities for horizon \code{i}. #' #' The random seed at the start of the simulations is saved in the returned #' object. A speficific seed can be requested with argument \code{seed}. In #' that case the simulations are done with the specified seed and the old state #' of the random number generator is restored before the function returns. #' This setup is similar to \code{\link{sim_garch1c1}}. #' #' @param object an object from class \code{"garch1c1"}. #' @param n.ahead maximum horizon (lead time) for prediction. #' @param Nsim number of Monte Carlo simulations for simulation based quantities. #' @param eps the time series to predict, only the last value is used. #' @param sigmasq the (squared) volatilities, only the last value is used. #' @param seed an integer, seed for the random number generator. #' @param ... currently not used. #' #' @return an object from S3 class \code{"predict_garch1c1"} containing #' the following components: #' \item{eps}{point predictions (conditional expectations) of the time series (equal #' to zero for pure GARCH).} #' \item{h}{point predictions (conditional expectations)of the squared volatilities.} #' \item{model}{the model.} #' \item{call}{the call.} #' \item{pi_plugin}{Prediction intervals for the time series, based on plug-in #' distributions, see Details.} #' \item{pi_sim}{Simulation based prediction intervals for the time series, see Details.} #' \item{dist_sim}{simulation samples from the predictive distributions of the time #' series and the volatilties. } #' #' @examples #' op <- options(digits = 4) #' #' ## set up a model and simulate a time series #' mo <- GarchModel(omega = 0.4, alpha = 0.3, beta = 0.5) #' a1 <- sim_garch1c1(mo, n = 1000, n.start = 100, seed = 20220305) #' #' ## predictions for T+1,...,T+5 (T = time of last value) #' ## Nsim is small to reduce the load on CRAN, usually Nsim is larger. #' a.pred <- predict(mo, n.ahead = 5, Nsim = 1000, eps = a1$eps, #' sigmasq = a1$h, seed = 1234) #' #' ## preditions for the time series #' a.pred$eps #' #' ## PI's for eps - plug-in and simulated #' a.pred$pi_plugin #' a.pred$pi_sim #' #' ## a DIY calculation of PI's using the simulated sample paths #' t(apply(a.pred$dist_sim$eps, 1, function(x) quantile(x, c(0.025, 0.975)))) #' #' ## further investigate the predictive distributions #' t(apply(a.pred$dist_sim$eps, 1, function(x) summary(x))) #' #' ## compare predictive densities for horizons 2 and 5: #' h2 <- a.pred$dist_sim$eps[2, ] #' h5 <- a.pred$dist_sim$eps[5, ] #' main <- "Predictive densities: horizons 2 (blue) and 5 (black)" #' plot(density(h5), main = main) #' lines(density(h2), col = "blue") #' #' ## predictions of sigma_t^2 #' a.pred$h #' #' ## plug-in predictions of sigma_t #' sqrt(a.pred$h) #' #' ## simulation predictive densities (PD's) of sigma_t for horizons 2 and 5: #' h2 <- sqrt(a.pred$dist_sim$h[2, ]) #' h5 <- sqrt(a.pred$dist_sim$h[5, ]) #' main <- "PD's of sigma_t for horizons 2 (blue) and 5 (black)" #' plot(density(h2), col = "blue", main = main) #' lines(density(h5)) #' #' ## VaR and ES for different horizons #' cbind(h = 1:5, #' VaR = apply(a.pred$dist_sim$eps, 1, function(x) VaR(x, c(0.05))), #' ES = apply(a.pred$dist_sim$eps, 1, function(x) ES(x, c(0.05))) ) #' #' ## fit a GARCH(1,1) model to exchange rate data and predict #' gmo1 <- fGarch::garchFit(formula = ~garch(1, 1), data = fGarch::dem2gbp, #' include.mean = FALSE, cond.dist = "norm", trace = FALSE) #' mocoef <- gmo1@fit$par #' mofitted <- GarchModel(omega = mocoef["omega"], alpha = mocoef["alpha1"], #' beta = mocoef["beta1"]) #' gmo1.pred <- predict(mofitted, n.ahead = 5, Nsim = 1000, eps = gmo1@data, #' sigmasq = gmo1@h.t, seed = 1234) #' gmo1.pred$pi_plugin #' gmo1.pred$pi_sim #' #' op <- options(op) # restore options(digits) #' #' @note This function is under development and may be changed. #' #' @concept predict GARCH time series #' #' @export predict.garch1c1 <- function(object, n.ahead = 1, Nsim = 1000, eps, sigmasq, seed = NULL, ...){ model <- object omega <- model$omega alpha <- model$alpha beta <- model$beta model$eps0 <- eps0 <- eps[length(eps)] model$h0 <- h0 <- sigmasq[length(sigmasq)] # TODO: compute if not present? ## TODO: add non-zero mean and possibly ARMA conditional mean pred_eps <- numeric(n.ahead) ## tsff slides, p. II.7.4/y1718 pred_h <- numeric(n.ahead) pred_h[1] <- omega + alpha * eps0^2 + beta * h0 if(n.ahead > 1) for(i in 2:n.ahead){ pred_h[i] <- omega + (alpha + beta) * pred_h[i - 1] } fq <- .get_dist_elem(model$cond.dist, "q") fq$sd <- sqrt(pred_h) fq[[2]] <- 0.025 lwr <- eval(fq) fq[[2]] <- 0.975 upr <- eval(fq) eps_pi <- cbind(lwr, upr) ## need local variants of withr::with_seed() withr::with_preserve_seed() ## but such are not available (as of 2018-09-28), so do it DIY: ## ## Memorise the state in any case but restore the old state only if 'seed' is not NULL. RNGstate <- .RNGstate(seed) ## 2020-03-04 was: ## ## if(!is.null(RNGstate$oldRNGstate)) # or !is.null(seed) ## ## But the check is not equivalent to is.null(seed)! ## Moreover, if RNGstate$oldRNGstate is NULL, .Random.seed should be removed, ## (so doing it now) if(!is.null(seed)) on.exit( if(is.null(RNGstate$RNGstate)){ ## TRUE id seed is NULL but also if .Random.seed was not set. "nothing to do" }else if(is.null(RNGstate$oldRNGstate)){ rm(".Random.seed", envir = .GlobalEnv) }else{ assign(".Random.seed", RNGstate$oldRNGstate, envir = .GlobalEnv) } ) h_sim <- eps_sim <- matrix(NA_real_, nrow = n.ahead, ncol = Nsim) for(i in 1:Nsim){ wrk <- sim_garch1c1(model = model, n = n.ahead, n.start = 0) eps_sim[ , i] <- wrk$eps h_sim[ , i] <- wrk$h } sim_pi <- t(apply(eps_sim, 1, function(x) quantile(x, c(0.025, 0.975)))) structure(list( eps = pred_eps, h = pred_h, model = model, call = match.call(), pi_plugin = eps_pi, pi_sim = sim_pi, dist_sim = list(eps = eps_sim, h = h_sim, RNGstate = RNGstate$RNGstate) ), class = "predict_garch1c1") } cvar/vignettes/0000755000176200001440000000000015120300537013211 5ustar liggesuserscvar/vignettes/REFERENCES.bib0000644000176200001440000000233215120276571015322 0ustar liggesusers@article{acerbi2002expected, title={Expected shortfall: a natural coherent alternative to value at risk}, author={Acerbi, Carlo and Tasche, Dirk}, journal={Economic notes}, volume={31}, number={2}, pages={379--388}, year={2002}, doi = {10.1111/1468-0300.00091}, url = {https://arxiv.org/pdf/cond-mat/0105191.pdf}, } @Manual{PerformanceAnalytics2018, title = {PerformanceAnalytics: Econometric Tools for Performance and Risk Analysis}, author = {Brian G. Peterson and Peter Carl}, year = {2018}, note = {R package version 1.5.2}, url = {https://CRAN.R-project.org/package=PerformanceAnalytics}, } @Manual{VaRES2013, title = {VaRES: Computes value at risk and expected shortfall for over 100 parametric distributions}, author = {Saralees Nadarajah and Stephen Chan and Emmanuel Afuecheta}, year = {2013}, note = {R package version 1.0}, url = {https://CRAN.R-project.org/package=VaRES}, } @Article{actuarJSS2008, title = {actuar: An R Package for Actuarial Science}, author = {Christophe Dutang and Vincent Goulet and Mathieu Pigeon}, journal = {Journal of Statistical Software}, year = {2008}, volume = {25}, number = {7}, pages = {38}, url = {https://www.jstatsoft.org/v25/i07}, } cvar/vignettes/Guide_cvar.Rnw0000644000176200001440000003275615120300526015764 0ustar liggesusers% preamble taken from the vignette in package strucchange % \documentclass[nojss,article]{jss} \usepackage[T1]{fontenc} %\usepackage{a4wide} \usepackage[left=2cm,right=2cm,bottom=15mm]{geometry} \usepackage{graphicx,color,alltt} \usepackage[authoryear,round,longnamesfirst]{natbib} \usepackage{hyperref} \usepackage{amsmath, amsfonts} % \usepackage{Sweave} %\definecolor{Red}{rgb}{0.7,0,0} %\definecolor{Blue}{rgb}{0,0,0.8} %\definecolor{hellgrau}{rgb}{0.55,0.55,0.55} %\newcommand{\E}{\mbox{$\mathsf{E}$}} %\newcommand{\VAR}{\mbox{$\mathsf{VAR}$}} %\newcommand{\COV}{\mbox{$\mathsf{COV}$}} %\newcommand{\p}{\mbox{$\mathsf{P}$}} %\newcommand{\email}[1]{\href{mailto:#1}{\normalfont\texttt{#1}}} %\newenvironment{smallexample}{\begin{alltt}\small}{\end{alltt}} %\setlength{\parskip}{0.5ex plus0.1ex minus0.1ex} %\setlength{\parindent}{0em} % %\bibpunct{(}{)}{;}{a}{}{,} % %\newcommand{\ui}{\underline{i}} %\newcommand{\oi}{\overline{\imath}} %\RequirePackage{color} %\definecolor{Red}{rgb}{0.5,0,0} %\definecolor{Blue}{rgb}{0,0,0.5} %\definecolor{hellgrau}{rgb}{0.55,0.55,0.55} % %\hypersetup{% %hyperindex,% %colorlinks,% %linktocpage,% %plainpages=false,% %linkcolor=Blue,% %citecolor=Blue,% %urlcolor=Red,% %pdfstartview=Fit,% %pdfview={XYZ null null null}% %} % SweaveOpts{engine=R,eps=FALSE} %\VignetteIndexEntry{Brief guide to R package cvar} %\VignetteDepends{cvar} %\VignetteKeywords{expected shortfall, ES, CVaR, VaR, value at risk} %\VignettePackage{cvar} <>= library(cvar) pd <- packageDescription("cvar") @ \newcommand{\VaR}[2][\alpha]{\text{VaR}_{#1}(#2)} \newcommand{\ES}[2][\alpha]{\text{ES}_{#1}(#2)} \title{Brief guide to R package \pkg{cvar}} \author{Georgi N. Boshnakov \\ University of Manchester } \Plainauthor{Georgi N. Boshnakov} \Address{ Georgi N. Boshnakov\\ School of Mathematics\\ The University of Manchester\\ Oxford Road, Manchester M13 9PL, UK\\ URL: \url{https://personalpages.manchester.ac.uk/staff/georgi.boshnakov/} } %\date{} %\maketitle \Abstract{ Package \pkg{cvar} is a small package with, essentially, two functions --- \code{ES()} for computing the expected shortfall and \code{VaR()} for Value at Risk. The user specifies the distribution by supplying one of the functions that define a continuous distribution---currently this can be a quantile function (qf), cumulative distribution function (cdf) or probability density function (pdf). Virtually any continuous distribution can be specified. This vignette is part of package \pkg{cvar}, version~\Sexpr{pd$Version}. %$ } \Keywords{expected shortfall, ES, CVaR, VaR, value at risk} \Plainkeywords{expected shortfall, ES, CVaR, VaR, value at risk} \begin{document} \section{Introduction} \label{sec:introduction} There is a huge number of functions for computations with distributions in core R and in contributed packages. Pdf's, cdf's, quantile functions and random number generators are covered comprehensively. The coverage of expected shortfall is more patchy but a large collection of distributions, including functions for expected shortfall, is provided by \citet{VaRES2013}. \citet{PerformanceAnalytics2018} and \citet{actuarJSS2008} provide packages covering comprehensively various aspects of risk measurement, including some functions for expected shortfall. Package \pkg{cvar} is a small package with, essentially two functions --- \code{ES} for computing the expected shortfall and \code{VaR} for Value at Risk. The user specifies the distribution by supplying one of the functions that define a continuous distribution---currently this can be a quantile function (qf), cumulative distribution function (cdf) or probability density function (pdf). Virtually any continuous distribution can be specified. The computations are done directly from the definitions, see e.g. \citet{acerbi2002expected}. The functions are vectorised over the parameters of the distributions, making bulk computations more convenient, for example for forecasting or model evaluation. The name of this package, "cvar", comes from \emph{Conditional Value at Risk} (CVaR), which is an alternative term for expected shortfall. We chose to use the standard names \code{ES} and \code{VaR}, despite the possibility for name clashes with same named functions in other packages, rather than invent possibly difficult to remember alternatives. Just call the functions as \code{cvar::ES} and \code{cvar::VaR} if necessary. Locations-scale transformations can be specified separately from the other distribution parameters. This is useful when such parameters are not provided directly by the distribution at hand. The use of these parameters often leads to more efficient computations and better numerical accuracy even if the distribution has its own parameters for this purpose. Some of the examples for \code{VaR} and \code{ES} illustrate this for the Gaussian distribution. Since VaR is a quantile, functions computing it for a given distribution are convenience functions. \code{VaR} exported by \pkg{cvar} could be attractive in certain workflows because of its vectorised distribution parameters, the location-scale transformation and the possibility to compute it from cdf's when quantile functions are not available. \section{Value at Risk and Expected Shortfall} %To avoid confusion, we give the mathematical definitions here. We use the traditional definition of VaR as the negated lower quantile. More specifically, let $Y$ be the variable of interes, such as return on a financial asset. Suppose that it is modelled as a random variable with distribution function $F^{Y}(y)$. Then VaR is defined as% \footnote{Beware that a definition without negation is also used in both the literature and in the R packages.} \begin{equation*} \VaR{Y} = - q_{\alpha}^{Y} . \end{equation*} where $q_{\alpha}^{Y}$ is the lower $\alpha$-quantile of $Y$, i.e. we have \begin{equation*} \alpha = F(q_{\alpha}^{Y}) = P(Y \le q_{\alpha}^{Y}) . \end{equation*} Typical values for $\alpha$ are $0.05$ and $0.01$. Equivalently, we could write\footnote{This equation shows why some authors use the ``big numbers'', e.g. 0.95 and 0.99, in the notation for the VaR.} \begin{equation*} \VaR{Y} = q_{1-\alpha}^{-Y} . \end{equation*} The expected shortfall is the (partial) expectation of $\VaR{Y}$: \begin{equation*} \ES{Y} = \frac{1}{\alpha}\int_{0}^{\alpha}\VaR[\gamma]{Y} d\gamma . \end{equation*} Suppose now that $Y$ is obtained from another random variable, $X$, by a linear transformation: \begin{equation*} Y = a + bX \end{equation*} When this is the case, there is a simple relation between the VaR's and ES's of $Y$ and $X$: \begin{align*} \VaR{Y} &= -a + b \VaR{X} \\ \ES{Y} &= -a + b \ES{X} \end{align*} In practice, $X$ is often chosen to be standardised but this is not necessary. Note also that if a bunch of VaR's and ES's are needed, say for normally distributed variables, this can be computed very efficiently using this property. \section{VaR} \label{sec:var} Here we compute the VaR associated with a standard normal r.v. The three variants are equivalent since 0.05 and \code{"qf"} are default for the last two arguments. <<>>= cvar::VaR(qnorm, p_loss = 0.05, dist.type = "qf") cvar::VaR(qnorm, p_loss = 0.05) cvar::VaR(qnorm) @ \code{x} can be a vector: <<>>= cvar::VaR(qnorm, p_loss = c(0.01, 0.05)) @ Let's set some more realistic values for the parameters of the normal distribution. Suppose that the daily returns on some stock have sample mean $0.006408553$ and sample variance $0.0004018977$. Then $N(0.006408553, 0.0004018977)$ can be taken as normal distribution fitted to the data. <<>>= muA <- 0.006408553 sigma2A <- 0.0004018977 @ This computes VaR using the fitted normal distribution: <<>>= res1 <- cvar::VaR(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A)) @ For the normal disribution we could also use the intercept-slope arguments, since the parameters are precisely the intercept and the slope: <<>>= res2 <- cvar::VaR(qnorm, p_loss = 0.05, intercept = muA, slope = sqrt(sigma2A)) abs((res2 - res1)) # 0, intercept/slope equivalent to mean/sd @ If we compute VaR using the cdf, the intercept-slope method has some numerical advantage: <<>>= ## with cdf the precision depends on solving an equation res1a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A)) res2a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A)) abs((res1a - res2)) # 3.287939e-09 abs((res2a - res2)) # 5.331195e-11, intercept/slope better numerically @ Of course, it is almost always better to use the quantile function when it is available. We can use smaller tollerance to improve the precision (the value \verb+.Machine$double.eps^0.75+ = \Sexpr{.Machine$double.eps^0.75} is probably excessive): <<>>= ## as above, but increase the precision, this is probably excessive res1b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75) res2b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75) abs((res1b - res2)) # 6.938894e-18 # both within machine precision abs((res2b - res2)) # 1.040834e-16 @ The relative precision is also good. <<>>= abs((res1b - res2)/res2) # 2.6119e-16 # both within machine precision abs((res2b - res2)/res2) # 3.91785e-15 @ For examples with vectorised distribution parameters we use data from \pkg{PerformanceAnalytics}. Compute means and variances of the variables in a data frame and store them in vectors: <<>>= ## if(require("PerformanceAnalytics")){ data(edhec, package = "PerformanceAnalytics") mu <- apply(edhec, 2, mean) sigma2 <- apply(edhec, 2, var) musigma2 <- cbind(mu, sigma2) @ We compute VaR using \code{PerformanceAnalytics::VaR}: <<>>= ## analogous calc. with PerformanceAnalytics::VaR vPA <- apply(musigma2, 1, function(x) PerformanceAnalytics::VaR(p = .95, method = "gaussian", invert = FALSE, mu = x[1], sigma = x[2], weights = 1)) @ The results below compare to the value, \code{vPA}, obtained here. The computations below are similar to the previous example but the distribution parameters are vectors. The first pair of results are numerically the same: <<>>= vAz1 <- cvar::VaR(qnorm, p_loss = 0.05, mean = mu, sd = sqrt(sigma2)) vAz2 <- cvar::VaR(qnorm, p_loss = 0.05, intercept = mu, slope = sqrt(sigma2)) max(abs((vPA - vAz1))) # 5.551115e-17 max(abs((vPA - vAz2))) # "" @ Computing VaR from cdf shows some advantage for the location-scale method: <<>>= vAz1a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2)) vAz2a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2)) max(abs((vPA - vAz1a))) # 3.287941e-09 max(abs((vPA - vAz2a))) # 1.465251e-10, intercept/slope better @ The advantage remains for smaller tolerance: <<>>= vAz1b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2), tol = .Machine$double.eps^0.75) vAz2b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2), tol = .Machine$double.eps^0.75) max(abs((vPA - vAz1b))) # 4.374869e-13 max(abs((vPA - vAz2b))) # 3.330669e-16 @ \section{Expected shortfall} \label{sec:expected-shortfall} \code{ES} has essentially the same arguments as \code{VaR}. The examples below are obtained almost literally by replacing the calls to \code{VaR} with \code{ES()} ones. Here we compute the VaR associated with a standard normal r.v. The three variants are equivalent since 0.5 and \code{"qf"} are default for the last two arguments. <<>>= cvar::ES(qnorm, p_loss = 0.05, dist.type = "qf") cvar::ES(qnorm, p_loss = 0.05) cvar::ES(qnorm) @ \code{x} can be a vector: <<>>= cvar::ES(qnorm, p_loss = c(0.01, 0.05)) @ Let's set some more realistic values for the parameters of the normal distribution: <<>>= muA <- 0.006408553 sigma2A <- 0.0004018977 @ This demonstrates the use of \code{intercept} and \code{slope}. These arguments use the linear transformation property discussed in the theoretical section. For the normal disribution the parameters are precisely the intercept and the slope: <<>>= res1 <- cvar::ES(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A)) res2 <- cvar::ES(qnorm, p_loss = 0.05, intercept = muA, slope = sqrt(sigma2A)) abs((res2 - res1)) @ If we compute ES using the cdf, the intercept slope method has some numerical advantage: <<>>= ## with cdf the precision depends on solving an equation res1a <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A)) res2a <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A)) abs((res1a - res2)) # abs((res2a - res2)) # intercept/slope better numerically @ We can use smaller tollerance to improve the precision (the value \verb+.Machine$double.eps^0.75+ = \Sexpr{.Machine$double.eps^0.75} is probably excessive): <<>>= ## as above, but increase the precision, this is probably excessive res1b <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75) res2b <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75) abs((res1b - res2)) abs((res2b - res2)) @ The relative precision is also good. <<>>= abs((res1b - res2)/res2) abs((res2b - res2)/res2) @ \newpage{} \bibliography{REFERENCES} \end{document} cvar/NAMESPACE0000644000176200001440000000062615105335521012430 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(ES,default) S3method(ES,matrix) S3method(ES,numeric) S3method(VaR,default) S3method(VaR,matrix) S3method(VaR,numeric) S3method(predict,garch1c1) export(ES) export(GarchModel) export(VaR) export(VaR_cdf) export(VaR_qf) export(sim_garch1c1) importFrom(Rdpack,reprompt) importFrom(gbutils,cdf2quantile) importFrom(stats,quantile) importFrom(stats,runif) cvar/NEWS.md0000644000176200001440000000523615120273345012313 0ustar liggesusers# cvar 0.6 * `ES.numeric` was giving wrong results when `length(p_loss) > 1`. * VaR and ES now have methods for class `"matrix"`. * documented that now ES and VaR can be computed from data, as well. * new argument `transf` of `Var()` and `ES()` can be used to request the values corresponding to the returns (when `dist` represents log-returns). # cvar 0.5 (CRAN) * made `ES` generic (`VaR` was already generic). * moved `fGarch` from Imports to Suggests. * renamed argument `x` of `VaR` and `ES` to `p_loss`. `p_loss` seems more expressive and suggests that it relates to the losses, usually small numbers like `0.05`. Other suitable names like `alpha`, `p`, and `prob`, are commonly used as arguments to other functions that might be used as argument `dist` and make them more difficult to pass via the `...` arguments. For now, an warning is issued if `x` is used as a named argument in a call (e.g. `VaR(dist, x = 0.05)`) with the intend to turn that in an error in the next release of the package. This change should not be noticed by most users since it is much more natural not to name this argument and use something like `VaR(dist, 0.05)`. * moved `fGarch` from Imports to Suggests. # cvar 0.4.1 (CRAN) * when the input was numeric, `ES()` was not handling the level `x` properly (fixes issue #2, reported by Marius Bommert). * changed the JSS reference to use the new-style doi. * fixed a bug in the tests, in v0.4-0, that was causing failure of the tests on travis, despite all checks on CRAN passing with OK. `devtools::test()` was failing too, but only on the first run in a session, details in the git commit. * set up GHA. # cvar 0.4-0 (CRAN) * fix tests to pass with the changed R random generator. * some new examples and minor documentation changes. # cvar 0.3-0 (CRAN) * now `\VignetteIndexEntry` in `Guide_cvar.Rnw` is plain text. * added experimental support for GARCH models - currently GARCH(1,1) (the API may change). * now the first argument of `VaR()` and `ES()` can be a numeric vector. This is useful, e.g., for computing VaR by simulation. * bugfix: in `VaR_cdf()` and `VaR_qf()`, the code for the `if/else` clauses had been wrongly swappped. # cvar 0.2-0 (CRAN) * suggest 'covr'. * setup for travisCI and Coveralls. * more tests. * corrected \VignetteIndexEntry in the vignette --- I used the vignette for Rdpack as a template but didn't change this entry, which resulted in the vignette appearing with a puzzling title on CRAN and other sites.! * added author@R in DESCRIPTION. * added experimental web site (docs/) # cvar 0.1-1 (CRAN) * added a doi to DESCRIPTION. # cvar 0.1-0 * first public release. cvar/inst/0000755000176200001440000000000015120300537012156 5ustar liggesuserscvar/inst/REFERENCES.bib0000644000176200001440000000231615105335521014263 0ustar liggesusers@article{acerbi2002expected, title={Expected shortfall: a natural coherent alternative to value at risk}, author={Acerbi, Carlo and Tasche, Dirk}, journal={Economic notes}, volume={31}, number={2}, pages={379--388}, year={2002}, doi = {10.1111/1468-0300.00091}, url = {https://arxiv.org/pdf/cond-mat/0105191.pdf}, } @Manual{PerformanceAnalytics2018, title = {PerformanceAnalytics: Econometric Tools for Performance and Risk Analysis}, author = {Brian G. Peterson and Peter Carl}, year = {2018}, note = {R package version 1.5.2}, url = {https://CRAN.R-project.org/package=PerformanceAnalytics}, } @Manual{VaRES2013, title = {VaRES: Computes value at risk and expected shortfall for over 100 parametric distributions}, author = {Saralees Nadarajah and Stephen Chan and Emmanuel Afuecheta}, year = {2013}, note = {R package version 1.0}, url = {https://CRAN.R-project.org/package=VaRES}, } @Article{actuarJSS2008, title = {actuar: An R Package for Actuarial Science}, author = {Christophe Dutang and Vincent Goulet and Mathieu Pigeon}, journal = {Journal of Statistical Software}, year = {2008}, volume = {25}, number = {7}, pages = {38}, doi = {10.18637/jss.v025.i07}, } cvar/inst/pkgdown.yml0000644000176200001440000000030615120273361014355 0ustar liggesuserspandoc: 3.1.3 pkgdown: 2.2.0 pkgdown_sha: ~ articles: {} last_built: 2025-12-16T15:12Z urls: reference: https://geobosh.github.io/cvar/reference article: https://geobosh.github.io/cvar/articles cvar/inst/doc/0000755000176200001440000000000015120300537012723 5ustar liggesuserscvar/inst/doc/Guide_cvar.R0000644000176200001440000001607315120300537015125 0ustar liggesusers### R code from vignette source 'Guide_cvar.Rnw' ################################################### ### code chunk number 1: Guide_cvar.Rnw:57-59 ################################################### library(cvar) pd <- packageDescription("cvar") ################################################### ### code chunk number 2: Guide_cvar.Rnw:205-208 ################################################### cvar::VaR(qnorm, p_loss = 0.05, dist.type = "qf") cvar::VaR(qnorm, p_loss = 0.05) cvar::VaR(qnorm) ################################################### ### code chunk number 3: Guide_cvar.Rnw:212-213 ################################################### cvar::VaR(qnorm, p_loss = c(0.01, 0.05)) ################################################### ### code chunk number 4: Guide_cvar.Rnw:220-222 ################################################### muA <- 0.006408553 sigma2A <- 0.0004018977 ################################################### ### code chunk number 5: Guide_cvar.Rnw:225-226 ################################################### res1 <- cvar::VaR(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A)) ################################################### ### code chunk number 6: Guide_cvar.Rnw:231-233 ################################################### res2 <- cvar::VaR(qnorm, p_loss = 0.05, intercept = muA, slope = sqrt(sigma2A)) abs((res2 - res1)) # 0, intercept/slope equivalent to mean/sd ################################################### ### code chunk number 7: Guide_cvar.Rnw:237-244 ################################################### ## with cdf the precision depends on solving an equation res1a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A)) res2a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A)) abs((res1a - res2)) # 3.287939e-09 abs((res2a - res2)) # 5.331195e-11, intercept/slope better numerically ################################################### ### code chunk number 8: Guide_cvar.Rnw:250-257 ################################################### ## as above, but increase the precision, this is probably excessive res1b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75) res2b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75) abs((res1b - res2)) # 6.938894e-18 # both within machine precision abs((res2b - res2)) # 1.040834e-16 ################################################### ### code chunk number 9: Guide_cvar.Rnw:261-263 ################################################### abs((res1b - res2)/res2) # 2.6119e-16 # both within machine precision abs((res2b - res2)/res2) # 3.91785e-15 ################################################### ### code chunk number 10: Guide_cvar.Rnw:272-277 ################################################### ## if(require("PerformanceAnalytics")){ data(edhec, package = "PerformanceAnalytics") mu <- apply(edhec, 2, mean) sigma2 <- apply(edhec, 2, var) musigma2 <- cbind(mu, sigma2) ################################################### ### code chunk number 11: Guide_cvar.Rnw:281-285 ################################################### ## analogous calc. with PerformanceAnalytics::VaR vPA <- apply(musigma2, 1, function(x) PerformanceAnalytics::VaR(p = .95, method = "gaussian", invert = FALSE, mu = x[1], sigma = x[2], weights = 1)) ################################################### ### code chunk number 12: Guide_cvar.Rnw:291-295 ################################################### vAz1 <- cvar::VaR(qnorm, p_loss = 0.05, mean = mu, sd = sqrt(sigma2)) vAz2 <- cvar::VaR(qnorm, p_loss = 0.05, intercept = mu, slope = sqrt(sigma2)) max(abs((vPA - vAz1))) # 5.551115e-17 max(abs((vPA - vAz2))) # "" ################################################### ### code chunk number 13: Guide_cvar.Rnw:299-305 ################################################### vAz1a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2)) vAz2a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2)) max(abs((vPA - vAz1a))) # 3.287941e-09 max(abs((vPA - vAz2a))) # 1.465251e-10, intercept/slope better ################################################### ### code chunk number 14: Guide_cvar.Rnw:309-317 ################################################### vAz1b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2), tol = .Machine$double.eps^0.75) vAz2b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2), tol = .Machine$double.eps^0.75) max(abs((vPA - vAz1b))) # 4.374869e-13 max(abs((vPA - vAz2b))) # 3.330669e-16 ################################################### ### code chunk number 15: Guide_cvar.Rnw:329-332 ################################################### cvar::ES(qnorm, p_loss = 0.05, dist.type = "qf") cvar::ES(qnorm, p_loss = 0.05) cvar::ES(qnorm) ################################################### ### code chunk number 16: Guide_cvar.Rnw:336-337 ################################################### cvar::ES(qnorm, p_loss = c(0.01, 0.05)) ################################################### ### code chunk number 17: Guide_cvar.Rnw:341-343 ################################################### muA <- 0.006408553 sigma2A <- 0.0004018977 ################################################### ### code chunk number 18: Guide_cvar.Rnw:349-352 ################################################### res1 <- cvar::ES(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A)) res2 <- cvar::ES(qnorm, p_loss = 0.05, intercept = muA, slope = sqrt(sigma2A)) abs((res2 - res1)) ################################################### ### code chunk number 19: Guide_cvar.Rnw:356-363 ################################################### ## with cdf the precision depends on solving an equation res1a <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A)) res2a <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A)) abs((res1a - res2)) # abs((res2a - res2)) # intercept/slope better numerically ################################################### ### code chunk number 20: Guide_cvar.Rnw:368-375 ################################################### ## as above, but increase the precision, this is probably excessive res1b <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75) res2b <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75) abs((res1b - res2)) abs((res2b - res2)) ################################################### ### code chunk number 21: Guide_cvar.Rnw:379-381 ################################################### abs((res1b - res2)/res2) abs((res2b - res2)/res2) cvar/inst/doc/Guide_cvar.Rnw0000644000176200001440000003275615120300526015476 0ustar liggesusers% preamble taken from the vignette in package strucchange % \documentclass[nojss,article]{jss} \usepackage[T1]{fontenc} %\usepackage{a4wide} \usepackage[left=2cm,right=2cm,bottom=15mm]{geometry} \usepackage{graphicx,color,alltt} \usepackage[authoryear,round,longnamesfirst]{natbib} \usepackage{hyperref} \usepackage{amsmath, amsfonts} % \usepackage{Sweave} %\definecolor{Red}{rgb}{0.7,0,0} %\definecolor{Blue}{rgb}{0,0,0.8} %\definecolor{hellgrau}{rgb}{0.55,0.55,0.55} %\newcommand{\E}{\mbox{$\mathsf{E}$}} %\newcommand{\VAR}{\mbox{$\mathsf{VAR}$}} %\newcommand{\COV}{\mbox{$\mathsf{COV}$}} %\newcommand{\p}{\mbox{$\mathsf{P}$}} %\newcommand{\email}[1]{\href{mailto:#1}{\normalfont\texttt{#1}}} %\newenvironment{smallexample}{\begin{alltt}\small}{\end{alltt}} %\setlength{\parskip}{0.5ex plus0.1ex minus0.1ex} %\setlength{\parindent}{0em} % %\bibpunct{(}{)}{;}{a}{}{,} % %\newcommand{\ui}{\underline{i}} %\newcommand{\oi}{\overline{\imath}} %\RequirePackage{color} %\definecolor{Red}{rgb}{0.5,0,0} %\definecolor{Blue}{rgb}{0,0,0.5} %\definecolor{hellgrau}{rgb}{0.55,0.55,0.55} % %\hypersetup{% %hyperindex,% %colorlinks,% %linktocpage,% %plainpages=false,% %linkcolor=Blue,% %citecolor=Blue,% %urlcolor=Red,% %pdfstartview=Fit,% %pdfview={XYZ null null null}% %} % SweaveOpts{engine=R,eps=FALSE} %\VignetteIndexEntry{Brief guide to R package cvar} %\VignetteDepends{cvar} %\VignetteKeywords{expected shortfall, ES, CVaR, VaR, value at risk} %\VignettePackage{cvar} <>= library(cvar) pd <- packageDescription("cvar") @ \newcommand{\VaR}[2][\alpha]{\text{VaR}_{#1}(#2)} \newcommand{\ES}[2][\alpha]{\text{ES}_{#1}(#2)} \title{Brief guide to R package \pkg{cvar}} \author{Georgi N. Boshnakov \\ University of Manchester } \Plainauthor{Georgi N. Boshnakov} \Address{ Georgi N. Boshnakov\\ School of Mathematics\\ The University of Manchester\\ Oxford Road, Manchester M13 9PL, UK\\ URL: \url{https://personalpages.manchester.ac.uk/staff/georgi.boshnakov/} } %\date{} %\maketitle \Abstract{ Package \pkg{cvar} is a small package with, essentially, two functions --- \code{ES()} for computing the expected shortfall and \code{VaR()} for Value at Risk. The user specifies the distribution by supplying one of the functions that define a continuous distribution---currently this can be a quantile function (qf), cumulative distribution function (cdf) or probability density function (pdf). Virtually any continuous distribution can be specified. This vignette is part of package \pkg{cvar}, version~\Sexpr{pd$Version}. %$ } \Keywords{expected shortfall, ES, CVaR, VaR, value at risk} \Plainkeywords{expected shortfall, ES, CVaR, VaR, value at risk} \begin{document} \section{Introduction} \label{sec:introduction} There is a huge number of functions for computations with distributions in core R and in contributed packages. Pdf's, cdf's, quantile functions and random number generators are covered comprehensively. The coverage of expected shortfall is more patchy but a large collection of distributions, including functions for expected shortfall, is provided by \citet{VaRES2013}. \citet{PerformanceAnalytics2018} and \citet{actuarJSS2008} provide packages covering comprehensively various aspects of risk measurement, including some functions for expected shortfall. Package \pkg{cvar} is a small package with, essentially two functions --- \code{ES} for computing the expected shortfall and \code{VaR} for Value at Risk. The user specifies the distribution by supplying one of the functions that define a continuous distribution---currently this can be a quantile function (qf), cumulative distribution function (cdf) or probability density function (pdf). Virtually any continuous distribution can be specified. The computations are done directly from the definitions, see e.g. \citet{acerbi2002expected}. The functions are vectorised over the parameters of the distributions, making bulk computations more convenient, for example for forecasting or model evaluation. The name of this package, "cvar", comes from \emph{Conditional Value at Risk} (CVaR), which is an alternative term for expected shortfall. We chose to use the standard names \code{ES} and \code{VaR}, despite the possibility for name clashes with same named functions in other packages, rather than invent possibly difficult to remember alternatives. Just call the functions as \code{cvar::ES} and \code{cvar::VaR} if necessary. Locations-scale transformations can be specified separately from the other distribution parameters. This is useful when such parameters are not provided directly by the distribution at hand. The use of these parameters often leads to more efficient computations and better numerical accuracy even if the distribution has its own parameters for this purpose. Some of the examples for \code{VaR} and \code{ES} illustrate this for the Gaussian distribution. Since VaR is a quantile, functions computing it for a given distribution are convenience functions. \code{VaR} exported by \pkg{cvar} could be attractive in certain workflows because of its vectorised distribution parameters, the location-scale transformation and the possibility to compute it from cdf's when quantile functions are not available. \section{Value at Risk and Expected Shortfall} %To avoid confusion, we give the mathematical definitions here. We use the traditional definition of VaR as the negated lower quantile. More specifically, let $Y$ be the variable of interes, such as return on a financial asset. Suppose that it is modelled as a random variable with distribution function $F^{Y}(y)$. Then VaR is defined as% \footnote{Beware that a definition without negation is also used in both the literature and in the R packages.} \begin{equation*} \VaR{Y} = - q_{\alpha}^{Y} . \end{equation*} where $q_{\alpha}^{Y}$ is the lower $\alpha$-quantile of $Y$, i.e. we have \begin{equation*} \alpha = F(q_{\alpha}^{Y}) = P(Y \le q_{\alpha}^{Y}) . \end{equation*} Typical values for $\alpha$ are $0.05$ and $0.01$. Equivalently, we could write\footnote{This equation shows why some authors use the ``big numbers'', e.g. 0.95 and 0.99, in the notation for the VaR.} \begin{equation*} \VaR{Y} = q_{1-\alpha}^{-Y} . \end{equation*} The expected shortfall is the (partial) expectation of $\VaR{Y}$: \begin{equation*} \ES{Y} = \frac{1}{\alpha}\int_{0}^{\alpha}\VaR[\gamma]{Y} d\gamma . \end{equation*} Suppose now that $Y$ is obtained from another random variable, $X$, by a linear transformation: \begin{equation*} Y = a + bX \end{equation*} When this is the case, there is a simple relation between the VaR's and ES's of $Y$ and $X$: \begin{align*} \VaR{Y} &= -a + b \VaR{X} \\ \ES{Y} &= -a + b \ES{X} \end{align*} In practice, $X$ is often chosen to be standardised but this is not necessary. Note also that if a bunch of VaR's and ES's are needed, say for normally distributed variables, this can be computed very efficiently using this property. \section{VaR} \label{sec:var} Here we compute the VaR associated with a standard normal r.v. The three variants are equivalent since 0.05 and \code{"qf"} are default for the last two arguments. <<>>= cvar::VaR(qnorm, p_loss = 0.05, dist.type = "qf") cvar::VaR(qnorm, p_loss = 0.05) cvar::VaR(qnorm) @ \code{x} can be a vector: <<>>= cvar::VaR(qnorm, p_loss = c(0.01, 0.05)) @ Let's set some more realistic values for the parameters of the normal distribution. Suppose that the daily returns on some stock have sample mean $0.006408553$ and sample variance $0.0004018977$. Then $N(0.006408553, 0.0004018977)$ can be taken as normal distribution fitted to the data. <<>>= muA <- 0.006408553 sigma2A <- 0.0004018977 @ This computes VaR using the fitted normal distribution: <<>>= res1 <- cvar::VaR(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A)) @ For the normal disribution we could also use the intercept-slope arguments, since the parameters are precisely the intercept and the slope: <<>>= res2 <- cvar::VaR(qnorm, p_loss = 0.05, intercept = muA, slope = sqrt(sigma2A)) abs((res2 - res1)) # 0, intercept/slope equivalent to mean/sd @ If we compute VaR using the cdf, the intercept-slope method has some numerical advantage: <<>>= ## with cdf the precision depends on solving an equation res1a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A)) res2a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A)) abs((res1a - res2)) # 3.287939e-09 abs((res2a - res2)) # 5.331195e-11, intercept/slope better numerically @ Of course, it is almost always better to use the quantile function when it is available. We can use smaller tollerance to improve the precision (the value \verb+.Machine$double.eps^0.75+ = \Sexpr{.Machine$double.eps^0.75} is probably excessive): <<>>= ## as above, but increase the precision, this is probably excessive res1b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75) res2b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75) abs((res1b - res2)) # 6.938894e-18 # both within machine precision abs((res2b - res2)) # 1.040834e-16 @ The relative precision is also good. <<>>= abs((res1b - res2)/res2) # 2.6119e-16 # both within machine precision abs((res2b - res2)/res2) # 3.91785e-15 @ For examples with vectorised distribution parameters we use data from \pkg{PerformanceAnalytics}. Compute means and variances of the variables in a data frame and store them in vectors: <<>>= ## if(require("PerformanceAnalytics")){ data(edhec, package = "PerformanceAnalytics") mu <- apply(edhec, 2, mean) sigma2 <- apply(edhec, 2, var) musigma2 <- cbind(mu, sigma2) @ We compute VaR using \code{PerformanceAnalytics::VaR}: <<>>= ## analogous calc. with PerformanceAnalytics::VaR vPA <- apply(musigma2, 1, function(x) PerformanceAnalytics::VaR(p = .95, method = "gaussian", invert = FALSE, mu = x[1], sigma = x[2], weights = 1)) @ The results below compare to the value, \code{vPA}, obtained here. The computations below are similar to the previous example but the distribution parameters are vectors. The first pair of results are numerically the same: <<>>= vAz1 <- cvar::VaR(qnorm, p_loss = 0.05, mean = mu, sd = sqrt(sigma2)) vAz2 <- cvar::VaR(qnorm, p_loss = 0.05, intercept = mu, slope = sqrt(sigma2)) max(abs((vPA - vAz1))) # 5.551115e-17 max(abs((vPA - vAz2))) # "" @ Computing VaR from cdf shows some advantage for the location-scale method: <<>>= vAz1a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2)) vAz2a <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2)) max(abs((vPA - vAz1a))) # 3.287941e-09 max(abs((vPA - vAz2a))) # 1.465251e-10, intercept/slope better @ The advantage remains for smaller tolerance: <<>>= vAz1b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2), tol = .Machine$double.eps^0.75) vAz2b <- cvar::VaR(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2), tol = .Machine$double.eps^0.75) max(abs((vPA - vAz1b))) # 4.374869e-13 max(abs((vPA - vAz2b))) # 3.330669e-16 @ \section{Expected shortfall} \label{sec:expected-shortfall} \code{ES} has essentially the same arguments as \code{VaR}. The examples below are obtained almost literally by replacing the calls to \code{VaR} with \code{ES()} ones. Here we compute the VaR associated with a standard normal r.v. The three variants are equivalent since 0.5 and \code{"qf"} are default for the last two arguments. <<>>= cvar::ES(qnorm, p_loss = 0.05, dist.type = "qf") cvar::ES(qnorm, p_loss = 0.05) cvar::ES(qnorm) @ \code{x} can be a vector: <<>>= cvar::ES(qnorm, p_loss = c(0.01, 0.05)) @ Let's set some more realistic values for the parameters of the normal distribution: <<>>= muA <- 0.006408553 sigma2A <- 0.0004018977 @ This demonstrates the use of \code{intercept} and \code{slope}. These arguments use the linear transformation property discussed in the theoretical section. For the normal disribution the parameters are precisely the intercept and the slope: <<>>= res1 <- cvar::ES(qnorm, p_loss = 0.05, mean = muA, sd = sqrt(sigma2A)) res2 <- cvar::ES(qnorm, p_loss = 0.05, intercept = muA, slope = sqrt(sigma2A)) abs((res2 - res1)) @ If we compute ES using the cdf, the intercept slope method has some numerical advantage: <<>>= ## with cdf the precision depends on solving an equation res1a <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A)) res2a <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A)) abs((res1a - res2)) # abs((res2a - res2)) # intercept/slope better numerically @ We can use smaller tollerance to improve the precision (the value \verb+.Machine$double.eps^0.75+ = \Sexpr{.Machine$double.eps^0.75} is probably excessive): <<>>= ## as above, but increase the precision, this is probably excessive res1b <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75) res2b <- cvar::ES(pnorm, p_loss = 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75) abs((res1b - res2)) abs((res2b - res2)) @ The relative precision is also good. <<>>= abs((res1b - res2)/res2) abs((res2b - res2)/res2) @ \newpage{} \bibliography{REFERENCES} \end{document} cvar/inst/doc/Guide_cvar.pdf0000644000176200001440000020772315120300537015501 0ustar liggesusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 4562 /Filter /FlateDecode /N 89 /First 745 >> stream x\[s8~?o'S[!q5*_$8sq ˔,z$9I"ɴF-"Ɉs2Ȧ"2gE'k#qUF\"n$.xĭƵs##4nH(J:V%Ifp?TS8G8G4"R*T_T&2Z⹍q6.2.uH1YdDVh][j_bN> c&r\H "'?t SQQ*AVH)aJ@#T>m0>@Іj3*߄q14cP|)z>AZ4XUUn b,kuQWUlM tْxi:_ Xr8ox zvl|LuoȆ'$(z([Fz挊A^1#  rV<)ѴL01Voj%D|AЂ- O!(?p ȗl}'.)KC=xGԎNu1t32CRy~34ųIRZRl=,NI}M)ٜ88E]}+.~KplRpE4ff2&^qt7}&XB .kiq?{ґ e|HUc`z;;#ZlgR` FA77jin3xVQK.by{b uP@<- %b-j^1RMeyɨ`&O߼{}tWG`|ra~>^Q;B OQZ_89"^r*ta|$-NY\AGFqp+_}\}.븪g]rG+R<$P%*:PugdIAIߟ+6fmⲼ; yd;y͒~8?OfXD5KKG_XWtt& G5| Vd zdƀЕQG+ XH Լ2,Vc&XTaq˷>TH]W-Jȸ{CFaIGal0!9pĎzJh5jPs}[֖+VnԀgkk O ˖b C׎{-"gbd*<~Pt_"QޣRtIvat`v'/ (  (Yedl]I6 ?oXPncEzMyxN7#1L"f¸y/IU5ˋP_"iΤkh ׇbmW0(nP[~2 aNnu`s>Q3u-`6O$'{o*wvBbH{FԢWw=XMuz\~wXW]w0 ?\|8dz~6 d omrK< YֿixzZwqTKkR%T;k]W U2۸5f3K20~´sVfYU(=A^%%W^E'L ySMPсIǑɭH˖T:MSXK֫ڢ5:w3Ӏ+uk{z'lVĥ/x(BHEڇDS`nBz)x5pi,1 ]؋s 闒`SXm~lؠ6,l̆w.>,g;9WF UV:NJӦuіXQ7ЦekoAֱ2Mcf?Jg&fFVqYWg66d ԇ $J$N g*,sfR:36) F,q0"AX; FV@mm_A&<W/Gv5euPvR%m9)ʚZ[W﷎d0]y3,BfeM[ MQZb+SЬntݑN?gTFej55]%ɱg궧Tb)݂_>r+~s6y v z~C z;&pY=kJP Es=i S}j^}V|@uOx5OHA?w5 i;!BJ'Ypgu+P?~z~1#nPY!Iך-3Kb)>!*"Y4O>8!d3(6q2R_@k9v==UFaHu6Z訩iᲒ*2HHk\˦@Y>v6JT*n{;Jhd#.+qM}=ySt"lqm+&Lwߘx.fx~=4=Q[`{MY;2kSɭ+u8^>}H/"Ǭ~gpYud0Yfi7ڔu9r# }Adz6r4,ӛl6_L{妽wYmVfE ,iwqYn^fcAu9m#d/v{`0)o."Fqgt#Ϸ}x[ʐĦ}Jg'v?nޣ0hS}k G.r7f JWSA-J,^q^hEQ)WM bGzvK]؆o1(wc>'z炅ݻ;dׄWxy}X8NXuqiElS^c4ւsҴMגFY{AԘ֤NU,ydm)zZ']YbeYGc#UneWłHӺ,H\eKKet(Nf Sܦ)sqΩ:wvGjTF.Qeb/>r~[(ywRr3;EY Ϗ'\Q1-y7vǣQ׽GqT͌}Zr}u5W773[yQ^2QDޗ{ Qi*kЍ?LsoJ:@[hR£p}lP*endstream endobj 91 0 obj << /Subtype /XML /Type /Metadata /Length 1474 >> stream GPL Ghostscript 10.02.1 expected shortfall, ES, CVaR, VaR, value at risk 2025-12-16T15:57:19Z 2025-12-16T15:57:19Z LaTeX with hyperref Brief guide to R package cvarGeorgi N. Boshnakov endstream endobj 92 0 obj << /Filter /FlateDecode /Length 5304 >> stream x\KsFˠ7D,*l13=X{IQ7[ZO>Im&P|~ ^.n?ׇwWRhk)\)jJeS7J7ʴU}Tnn_^Tcmԍջz|*VUuw RcSj$6n`kcZVf8"joɗH-\jY[/cظBTni^Z;[L4F}HW!4p9 $8o/o.v){ZxxR>lnuU?NR~WG乒@BM4[s8[~.AF ػG/궩.rvӓϫB%Jʔֶrc(Rշ >m̛f]N\]#w?OqUޢZ%iZL5pB\O$'E"H)!R֭" K 4'o~o<\;/!4݊&8Ia?- Ҫgi[>lhhZHY)ڑɦ,NVY%–>9*pLcZV̱ꇟ_U 7,MLO[du<[!KIN8e,R~ j(ϤdwK?E:ꔽ-uE5(_@3 ZhDmm Zk%sGBpc -;JyN<nx ҂z<<]eӇ:_ l zP"0 mȏw`hv7HyZ!,Հz߭?2H&FD ,(6HYkZK h ޹8‰T 26(U_،si:ݢQe ˆ*OJE.+Lp:9UF@:3a 6nf7cC sVvd{J@gHk)Y2QF9տZ~͚&C~B;$6nfߝ0XV EY˴DOtBaS]wZ!"K4<| {LkcJpckЉQvZEM'^UXȌKgV™:/IF $QX,*-ZJw<ҦrAӌR IՋaC`In$&hticw‡m8;)[y>϶ -j'hb Ѷ#ƹ/fE x!E9ԶѠIKZ:Mt m! }`+GPQ#0vͰ]ʨ4ČI0 r0^\W71R1^@?k'hϋ$9ɹ^D[ł^Ш*<[H&bD D(Y$8#41 Y3哬->9akeA46ZF4a <1 zo_b/"tRr)zUcHoZ5#֣cf~~C *<[ta̱+Q>lwLu^Li}|+0ٞ4"c4Gq;Ǽ;J0y#5u4(5%Y᧒ytAnEEPL Q3(-~Gßwՠjf6)7d5D^-ܔ'hO` ݪ6Va Y=[/I<њ%>]"2ѝ}Ju`Z Q2g 5=U}E e,]1A!>C21i k' =^*ZJ2S!2Bs%sEe OOF_2s>@Wu Csg~J o^T`ڤ +7#+Z]\~]\LBtIm[Ul # (8&#Ҳl;5]1!Y峅'fEd7 5 ٙq %8*C y:fU&W:Z?R~}wȢC sBI~4vOgrd2 w̺D-~FEl hb,)r\׿+ސ292ˋBJ^"겣c6fbʒp[m8,3rS::7yD)^ť$ ~Z/USYOL¬,yêT`c,8D8 SDg4SI960јnpKJ];c}oun&˖5w9xZ[[nĦqWcVqw^cG '6!܆ ڟR dv*`ؿ黁;sR6F0waF4WيLS&0ߩѹ&j0-7a]])Kh=?ZK1ok3<nDF]`Cjv?teJqv-Ҥ5ɡi.V+QըM 0d=4Ր_3}yuNÊuR~2&@?T'M/ԽFEj"VK&l(]k Sk)vVYjтY5]SAaٟ"i=ME+ PYo*T̬r&=/v,Q$5#3( _Y@3Y|ኵ¶&,Quffi_kL.f&+ rbVrtCӜVDHC.Dn/ڂ!X\H2ilm`n@%EO.46. L=Fq>o}Lx\MdÔY|pfz-{lzncy#*r ބV<6yep:X$5opd Wo R |reoچPRf>ָt9H,jkDY s,OV ytK7ޑ>2b)}69k7oհg}]! RN= %0 J5~ba8/|qȽ.+aT 7륭|CXZW"L<:@LSTxd)ДXjˡ#MmQ8}-=/int]>:F9֨֓IVʩ$l猦 L%Do,G3 F_ qO$ ;]%r{Α'%SD C8ew؍oժBghpSWnNR^`!)+*x:}@ >g D}bϻDls sU1n:vu/>1걁OsX1/"S4ɖo27kgv:E2ZkeYBwpP\~P6YY?ZyBOnrC_PLo):ϑLb?aVZ-FWsꦁ:[*㋏㽏Z]<2=OïvfæhO~{xvSdYV> + !E*=FxJ[(.ӴBN`(X> stream x[[oXj >c },$M%Yf~g..)K%z.ΙeSeC߳E\^0v]/??]|z,ԮqlyjҵvbivEŏN퍪pszxQ}[_QYmWG+!x.0q:Wf۳#nj'}{fӍ~wgZ(yK;H) dBg&LBjNWZJjJ5U_9kS;چX:ӳomƊjNH9O=tKluyuq_I\j_y0l. ъZ:%6>$gHPUAGrLХFWU!Ǻ]krݯ76i|_enC,Sj*>K_U{FҢXelZV8'u[/Ty)׹7jTկ7EVү]U{$خZÛAj_`GV*muq9TME*S+&8 $z֪˥+iZ\ džcCy4ˬfh ma0 [ *5;&^]nހ];]A7!lDItAk<2u(hMVXGWNf 6$d%*SG)?!9[ml$'ylƮC3y:/Z0qW!w{ s,NCA:oR]W1fruֹQr 0#&jMa:7UL/Ȯ3YBO mD%VeJhjpVi5]O/]ɷGSnqS^͙E*@ M'QaC)!Tڛŗ@r7O HGQFb>MqrrJ^AlxS{hZ/>&mYs~VUa5iȟM eAebױIW17X+_t,kyoST7x䠮ٔ1cCfbD4&l(6y26GԂ{9tD`xܯ[i^pdOmꑑ  2p"L&57"jrEA'kYM =R["&hlp Zc%%s,oxf@]jodH\(#ܷ1&d*T4Ċ>g93@|w٭9$dh6ߧH1k-eP,_J^@PtT bI3x}a,34)\:Sa $:eGi԰PQ!#bp6d&͔T-jFB+GgNӨɥ _$8l#z"OX$'jX@P4cH.6#F&z)F:M2oV9+{[c+51@PzVhTVSXY eĹER0,qHY# ejFȯT"'o~5,6WhC$ʳ8j&F2UF*cAAВ8x#Q݅@+Q~(S$t%4LaF s0 {c#DhX8 tj87m *~o3?2)ш>)y(Eed2kNDw q(d`˷?,mhK *HDӛ,x%'Ҙ #+`Ext\'+88bmd9$bbXM%L[<؎SK[[ b r7u#uhZUaα?ð ?YH w%&%\6+%$AFjGLWBW{Jut,N "6 hRR6y]o C9*K?:4ɲ<"t65eze~`h6Y3RbIiFFǔ:O#}{#\uc}֓yUm&v)GS#'tvtlr/+Z9y%93v6W5梠mk֫-exgý$14jUuv+ϢN.ӱce| fr^穳W_fCs׵ʌtLm?*6-RM1_SA6Ц}7%ȯJ'ZpD5YHK 70b|'GEԤ̉9 @{c4|%]!x-!AyZi1>t>H;9}pwo@ Qg6=)i~P-cXl8_kÃ!Nio kt뉋Pڥsuz\= 3 ~T/+Ð+#ʑk^~_kTD˺ص~6D1`=cHdWy@jOhy^Ҡ?86b>)Aሷ{QtW႙:0$u^`_m  8E84pRNuWW/ח{J]rw.v/cshFi/~bi^°Lg\v8[|T[P T=!)h%eyr/(AVendstream endobj 94 0 obj << /Filter /FlateDecode /Length 1564 >> stream xXmo6_adJmwV C7l/q7(~IY#)i_#EڤVl?آ;fJ0ߋzBW uS/flz2,S&.4j%Vf:'* &*P^UY9DŽ2#~BM>Ġw{ Lɘڠ{p+P?l̐&Ls.qxgdTsT^vs4Gw?D|?V3<,D( eU]nlW~A^0JJj2]waC x0bn_Q0sQ ai" :ks%)˫0[z< L!ZUT4hmִvYPWM 9.cˋU2?{ 3\z x=o=|}mzM[x$i.0AoZ7„eP&,S.X Â{_[HBPS6ַ{2稫ͳa:x1Cx_]\6^m_dHm@ΐBDC/G4'(0עPԀ?,%BJ &S Y419(uxKE) \!R 0Auv5v~tC.B[V~)r9|@_GϠ]aktCP~ 'e P.P,ɥUς;B Dse >U o OJum*kc/֘mѠ?-Su/m4-- (Ɍo~2ߧl 7FKo@@uM8TApQEL>8,;iۨ*oEL󕯭υ>ρ>&vp )ǘpL}c880PZ$plF߀dvmRI 7&!TKVbX]N|E]7}H87&xomLqy6s`~yj@Ʀ*SY)CP T@.!iwm$ |-r l5F'=ᴞIή]' W^R 9-&\L?R.KRyt,1W,/\p$'7O`pbt'$ZǨFm}o6 n +,핊KR2%$Tb zv ) f56o - |5B}W?>y3F>{rDxD'5k@B&biEV;;N1No_L\-x:IaSo@}*QIEK_wMnHk|pjGݗ1ARmTA';F[~Xq4VqT*i4 bL,*RcÍlOC3h&?OрDendstream endobj 95 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3716 >> stream xWy|Sն>!9({L+P(8P'"sLB֖Nt";C %MKZZär 2<>pa]ޝUeN>{}R1}J5pe[1c=;36:(ȺݡTǡ' ) 6#ff9 s)_޸isIJQѫ&Lyn" e0ØPf)3Yά`F2+Uh&ɬaf3s1L3g3 "f132@ƛU zHƃf6:LPv0: eGG\ 7N?]zY#?Ñn/> \S*gU .\lزvu3$XmuA+4wPk9Ւ,vWn]'NoT ףW(Q|n"}f-)Z+|M \"8B0.#YCi";ܷU8; kd@ [?#Ğ)=]:e5F"sYHFۧkES'E6%z>2 ==Jj1`2L0[Xgvh`}2-[ a#dTx9M_!z 1As7H@ ;EfH 6H߀?~#$CZP>-b'<~Pge[C;3钱R .t WCgdԦd&$]oJ $6YP`VhghyYho5ϪM7@y_a2Ma׾AfdqWנ7pHgǾLSgZmsoHw98anVFq}• ˖ `GuxhM/rP䪠h{yMBFs\g.8}8K`\+VooDp\ *lP_ky53$ϑd1( ~O+:ۥ /J uM˓Cޅ(*~8H۩o^"6cLp\;rd>:k xʑSWDV7tnMR<8IB~ܴ/OW{RNYSc~d:R&tQ2~jG&JzfS)luE鳴4*erNu2f5%,%D͚2h[!B}gxr_ Ŷ8+U| oͭu`w=Zgq*c4wk$p9;QߔZPoo2K+%5P GƿF'_-בzW`P-0}vbj+"(i>Q^pd*G%ş̍1ǀbm:N6 F\XIg9 &(=dt׶z҃fEb.jPM4z[c;O:KɧmQR>J=sy&dmX2rESyc(вxi+ois.Xfy}sZu+\IBPȓS8_`sJ7{S@W) Wz.2xM ?zu/Wo s٫[S GR*<dq%縺z/Uy*"$::AM~}I|\P%!bMeG< IK\^9ْ |u?eDn+! f ռ䔝=_eX- rj}}XT-%[F܂['J퐳͒#-o\K0܂$||R KzK݊pM|OGƠdvkj~i]CwV= &8Uwy2EI۾5;7^>Cw< L;W,Y̅40RTT4Yׄn]m´f}Q\J&I3SKVqKsK H)-%56αɾLY"ŻW>\\[C<V]QF+-bkEqx:bZ2Jʚ]{mp=)쩲dh: x\+Y'Q~XJDav&|e/&=ZGJo-nQ7lv1[s0Nk0W[ڽ; S,t& t~筜N81y ,{4b\s!긆HNa䅎w[+G"Ms ĂɡTQUy ]Ǘ'=_|Ӝyɝӿ3=g(?h#7^74G79Beza1ꃛzuSW?oU-7:;z#X u|KV{%޾m4aռW ;s/nRڸ;>V:c<pNѲ qZR*쮭}t >w :p&Er6HL뎂=CKJ. Μ W^3/'Y@Fh'X'aA #H=UWއH0h'BfV2պ5+2;`{x{/ݘг6 nO[|)7vUz96< vR0j83sw}OV4_liDHsnrXSK[KĎ w*KzWn.Am|vɣ\eW|ggFKTnߡo;PG& ?< S0 5(ף gt[]$zG.y/V ;PV-L Q⌅DnStUYxx7SM$lGEYu 1W+6-A=ki*l"0AG:7cG4>JhlsEۣwuYSW2$$geSJOS&q8܆"z>j>y۰E)d*e8W o&cQS3D"CivͪcWDW(lْ. Eƙ73,ɖ O+ =`H浒\R |{LAL111wWVs l[qP3woPWy#3r5’<tV_Hn Mu ͢p!yzr#^XRY T񉆌$OKp\=[3TecH]6SDr%__ZP_"ֳo}j]d!vendstream endobj 96 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1625 >> stream x}{PTﲻ^  nDMұD 3锠!AH 1\Xygw)1V{D'ʤicH2ش2?f]H~{> J@)_64nٛ:Cq~fDMUCTK5Ȇ}: ㍦"sIfΜ]{)*JR+TzzH%RX*JPa%uEO/Z) ߨ^UNu4C'a_%JpYU!j잻PiMfV`VX6Asj4"R?'^0^+KD,ג-4V~+QL#qHDfekY)Fv/-jl=(0qF6NkC=Gxr2I:!'q^[SpRCMD,9}ɢv-66{ X{~}d0 c[^HlC{c 7!:.UZ.o,U1oCs%˛f[4Ս[PVar:񲾭b[ᙼ?59kR`U*9v̓/8x{('qh+WZsM+\ɂj;o:eԌʌxo\VDZiA-긿 1io6f,`*0u&B?n#r&g%O}<&H+D䐖jEh+<ᨲ˥sghjկ!%+ѩPIj2 :z ;Zzp ~lY_A*c >R2ZG]pB_${)vPAwV oJt>w7oj>^ßv =IBZ6ؘe>=9> EQqRnwBap%RKqQRuI)`Zh7ڻ[u;DX-d\~&iD 8'w'4`R@*lU7J_+-ˀ {;=|M0vr%~$bj8y ܒATu;9ŋ\GqIIWo4T45T5E[^* ,Q]ңwߺe@hcd߬E.>mgXKRhnoNdnFYfW0v&DU|ǨQJҬ g%"yó{0->-w8}ONksFWF`qóTEź/OyBsb:n/aʊ I bcz寅dṛ4Ö5 y jƒt\?ғ !yOK&HSE\9oy9;3 yrId=͌_heF1U_(;=/*!9e778 ^2~F11!5Rjfw~_zq6vk'(?tendstream endobj 97 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 7179 >> stream xyw\ ;cCe\Y{n+bEEQz[XʲeKD1%Ē3x^7?̞9>>YeщD֋;n;S)t;6RYB71t75B8ד27Vσ  lno^eVm˽Vx;]5abI !=7QcQ@ʑD-S˨)'#j95ZA aJj8AfR#5,jM>Ps\ʞGͧS Bj"D-&SK)CQ6T_ʎ(FuPTwʏT/ʚR,[ԕZ@RCYPKQaW[,,,XޑHўy&.H9ݪO^d5L={{|;l6Y҆>lsF-/37m;~ wh?xn5S2`ցQU[h /mÇӎ>mmZ$DFvc|_ X CRf^~X"ǣzm}CC.n`po! @7,`+֨%qɆj*N->Q^`&/f~Kx҇VK JGނ, ´yJ/Gh+.rvp;O}ڙ]4F[љ'3۰hOO.]ocn>\{'2uS^F{jq>B? l>Dw NbtZ}AןMZ)/í٫p/6V*Rx 4䃡DbHSϭqRŎx"];4)#FQcG#-Unoa{ GϰŴMaE}z%MQ޾m, UΠS"u)ʧ?QE@3(f{>\}Ҵx!(mz ENp' qh(Z*xڰeQG%ݴ%K3&4S{ }xhW+ʿ$JP cltOHqGܴ(sɀ%pEptw 03<@4z[V6 x4Z[FmQ4HG3m_!${I&*}s(5v4 *Wc9S.G )yo%V#Roy{6lzIk|]gzsP'gİ-J;hh4}4=Fcayv GMj1zGu=ppAP9Tn6f%l45#0::9ݣ|ɱ^#(UHE7 1G*RJHPd]{ 9dNAٜ)}yּ8U4CR}\R\09R$̢D-DsulZQ;Hi<-ߚ_VbثFY}Wou6&G L4$˱"N}aѾMu%􁯾!| u􆬛\)OI\SsdM4O@Ӯo=7׻&"*EEBXHht!0 tY!jC.FP4䫷C* HOdFr&A7d{/&^)RY8# Q孛Bd 5G[tM0<tUBY|%T\<ðeﬨ/ۢ6Yp׫eqI頇]nʅ\G$<^T n[nUABUhS:c8 cql(Qgb[$A_),ߴql$*N&oL~,hd{#k,%oʈ>5%T/7$+Mls`RgSGD,1Gk#KW ySAeA*z \hhFφ͍k3u|∊IʺY5>y| ZfmA`#*?~t=8v{r妃v%gsOJ٤mXVwds+JR(B!4wD?<䐞~I<bc`A!Gq/c2thĠNh>.Iˈ[FM]6 udjev3Cq_ ۹{ )`C/G'mKё}ƣUɦIj yyI C*MiB%)ː; Ke.uqZl6Jz>~g( 9y}X]{ҕ9uqq;t !=2TBnmF_іf~"=1X_aϰdKx$.,-?B| oTh6xx9ne SAn4ARV~㩓e<* NXYT ^dTOpl<F;OŽ0M;]WKءϱf0{_]X䵝d,Fa#o]t?ˏ CNɰՙd¼(=:D݊dAK+,[z"I+ӍTl SDnhq^Y'wӨ|! , (.p1=qgC v֠n&ReoHտ Uůkx$@[dW8gԐHlVHC`l@Mz0 I4RN))Y`HOB+7Dk0|MB#| S<:Igji$EmXMG~w`}hz .e0,ӡHrar|}$p*#q`E&ih}K~w B8cS%L"Kt&}.4~)e뒶|S-Ƀb]TL{ѿNKV #۟2btiBZ\8LW[1.k㴪x-u=p{.B=j$FJq$ S nCemSMfn qz,Exx݈Ǣ9hƣ \).L3l׭Ѡ8ô}ד8p'(B҆-+?rO}nۯ! ;#С}& 2&\^PfVCBS{W5>s {&ߞؾy/X&FHOF~;E=b,w\ѱRsQ[TȊVB\Sk!hԏѷd֮(zRv,`~ƒ;xz <y{TDm >0{l:iwv+9(l!S_ F+0$]|@ηN m8!؜GORڲF*(i<Ҕ&7M\9\^rq.T2aNv#6})"~I(ZɋQ^.nsVK{$َ\41BLml+ DpN]I[$|=+O|k MJhbˋ.6ZtR-Ese:}b*qEWZ2m֗졟&]2"]!,*J&ly%2Noypn=B3[jUs)wvEmw9d R8⨻xb0YDP AWZorߤ'bdJKiMGnOhqa{34D"L_1cOCut1FiLgE}*`j\Lj\7q3=_[l^5:[uUhٴ~Կ*h>,gHSpF륨ZՓCh)Q&ءjRlg %jֆ#M\J j{h,Ga:sd.+p קoo&.n+8o ޼%p=/v ˲-(/+(ښ^Ζ&^,ψKZdD3b&ܓwXP_J^O"[};a֢br5LB:%;ԅC+7_3gRXhOuC .GdR3ݲz]WF>ڳhYj|vwf4l<4vĸbQΞDdr{2=5/U^AEF5ve4G,2~;n6U N9n=oTW^X5+iJf:qֹ35PiUӜh6sӪ!.*-ŊfѸj,OWqh79.'aFс߀#/753dJӁڌ7ͽW$A=y'Ӟ*5z[\7b>X|ۮ?ݳfH)=9**.N @ei3ψPU#G\&4>Kj!'^0G*R*#t'ќ᭏wxdþ"a4H蛰1vGB|bYx)@w(Ġ/EhcǦ3] TreOht/jX}ąbN=0M'1eit`mt(Ӡ'0w7o댂/y#f6q>!G~q}\k!LC͚5S/ 9}G8Rx 0pgG줛q*# D/+9+QUR˥\:&O gu Lendstream endobj 98 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1438 >> stream x={Pw/BN9B-bNS_X!jB@ aCU$H (SG::Uju۱j};Ξ9cδ sP(F.^"u{BJG!ےG`zw]<3[#>G΄͉ J*ZEER (ʏRSKyҔ'0(Y9=<ت%Ei^8!e9S0/?1ʜe vơvSYP!:#XG_%:m ’{!ilQ>(W)zoTE,JD']G% O:rmA %Mz =)fg]/_d4کvƜZ a:m['5'Ϋe9Psםe m 2 `H+&MM#tluew ƥt lw D huO,K^2wWo։8Lr$5zk.♘pf9+uLѤ&O\ct௻n?>kKO`K} bZN'o4ڠXLfD SVUa6ñgݙjK1i;ݶp[&B@X4 3o=O繈m/,]{ :mqG|b[R8]?2$_.̗Eori+Р 6EcC+>RUr7[d4NyғR67%C4$]wX^`QdD cd}}*'}siTfþ"O_,'b̽ݹyD/e';8ݮ~B q,X-GH zS[u~M6>oM-i&˫ m|-l_h'VkQAѾ">0) 97E hBֲ&8r䖍 [C_-E R37Ae*ᆺ8 0ϸTvV\bs8N^endstream endobj 99 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 5082 >> stream xXTW۞̎؀qhbb-F*5(AK_EY"FbA, EMhib41y'|wEȟ/gv{}yH(=J"89;5oODnW2px7GC4N38e)M`D1XF;+f6mt z{S,}}71yo_@QS Fu=ʅFm\͔JQۨU;KޤwrަQN3ZOqeNYP>eEM )CQ˨j%52L(S&QKH@%v7J- 80 c4fƘ&#+8oڍ{gܱM001|IwL֘.5-dIƓ> u\!wlffG~7w6&Hj6< bZҋr#bE@P7?XgQZVRZZ2J`Q ]݈ڣCXD7fQ ]Ռr؂>1ZU*6gOEm\ z|ZhUw='#5r$t9] khgϗlq^и͸9Cr $Ф} ϰ6;`٠z?<S 7Γ]q=P'w\QM:8%Kl?z|]}*bzw1jq-D uF5ݽ8/'vC"k0'chy(G3テDf,FQA_6gqX6b\RЌX~C\`B)sªS_[2ƛ*V鋞`¡`. RwKLsG_9bu4R(,#^{yh;K||8^Mܘ}TrOƧWg"F0SdmE9]|,%!/OJ|>If0Qvd,\)`-QC[?_fڪk">ęO}n?4[Shj{kŢv-Go-M Xu "z:Vwwgwԡɷ&Ԯ *R4RIaئ/fknjJIc %pPI5 F?)EuȲ5C -ڴ\&d|gUJ=lũ\[᱔ #4ކf cddLgD18kثp- ?^Gsǐ1[TjzS[[jTPne^eh0 5đR+ 2$ߝC뻦" eQW srj甡"|v.pd,MKW ?}t,#7ab}]-K^z`H6C4 F~aL ɡi0̷2YĂ&Hgaʔ/1 &53ZGlݜl͙o8Kՠ.YD~Xb ?i# #: a¨JCE{;k*VICeE:\>R]'ADe?2wb.텏.AM[/F]԰Vz1CEs֘ D !}s{N5J|kvNfѮ*hPIq)AVȷ\VH*dz^ͳB]1g$]bЩ(4XΰSʳ;PWu41o6-5VYWژWSAQVͻ{ 'Nn5.a_|Ufl5+;JjPG^"v[!GTP;+%m,sxo otM%}MnsQ6x(bSzNQRT+_BL]sTAP{_3g@Xʡ>$ypyjݥޝ9{U ,s#JjO#>2=6(\AKf٢ @ߐP}Ֆ]wd|]]]k)POY_PQ R]%v|8 h}~ hɉZ|Y`68F;ww i(Q\tdU<' S<;)G| if,}SߦL@n0z#t"<^h8z#q7ࡐ|9y,l?a* x̍LeZ N5p4=TxOcFr~SuSX/%ETtU)]3EK vW'YX8f!T*DȲՠ.-C>7g{Ų!!]Z䕰7G((>,ahˊB1~Oj'n(uq4zXa? R%}4Sa>(C0) ( E1Ev1Vo<``g䧯`1.|/ίլ_)^TIN/ y)_i1(1~("Z-՞kY&`ᏼ5\=xɾs}?wa;lYk>_pZa|=Qr=~ dY=-r乑JԄsl y6%Eң{o/Hrqճ4k;p>;W}OgB)''2/?U11ؠդ BefnFJe:Er }'p]A޲}mGy|O'/^=Hj y0Wz(L|Dnk,z]Cdq%[lQX`Y RzقB(êR|2vZ_\LOm?* 5gA9b#,:}X1+9cǺ$'@[5 ÖKXєGq߇|}R~Kij :Q"ɽ.>˻=9Tȋ)_KQʒy)L ƻ.cOչ?owg94MsD/`Ggn!F*/Qg `%x!s>w}+7-YOTUP,M/K9Wi8ݝ ָ*P>%5-[6!RfiT*0P6F=d ZݼC[!s,lo,XV˷мGw*rɐ#hŸgg׾~Ӽ=+JzBE, ]+ =P_?~OH*WZes Gɯ+7๧endstream endobj 100 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 4358 >> stream xXyXSw>1KJSI9Z˸EkVwk} K@|! } Dp;EkZNgq~sO/v\?<<}~{x1Ǜa֔E MO4.$>L̓WWa ϳSVKgHeEdEFElm8qg  bIl!fۈb'B%voPb5x&~K!k%:b)HHMid CV {=,?Π2HƔ?riRU hLk7Z +iAH&pp/d S,.:VhcZC%ͽB.ZF7p}*w x&Z0x `)4=WhZQbCYW3x] I5Uѹ17KFuHݫXbfK!\xDӱ;>UCF!%g;*`PYD mPnk?B*my WR0ETmQXl%[S2A! m r?doΕ{O?XhsW΢.(^ViSR UQ G[ 垁T@=޵ߓTZKb$g,ni-䏗ͷ|mbmHzbx|n7/Zۡ]cwȄƗGs@Uzy1tB:M b`?d6 롌tIʴ4iB#MT֣*"bи}k=:^*')6j&ר2L*#fa@:E/\!ƣNKvж:0Uh'%KpN_ش?]R&69rf_]WRBEs/ ; 67@9Y#wdQ(ݶG:nؽ;|o}Ej jl w>ұ^,iPچ:gѰ=3k?GO|;)螟'zFzqh[8e[-#I[R&HPkL)% cA7cĉV.#}?n:ESGnxȾ3ggq,f!a.5$PRAZ>dW$n?tnzen4zv\ DFI㞌RRnLZւL܌2:H 5XUYIgV<--3no~7iaVpEX74M*ev6١P"O+C&Q.n?;\肛{s/^sQq0b*sA)}ohzh4æXjٻ3,<2ںV.w^MB3Տ/Ja(.$pZ!gsrv]{'<ȻC]:36-;X_CxY3!G-HGuC} UZzq\g2Է C#-/a J6;N<FXKr2vykJ SLL$T<ı @Nr̜f e&}90BLJouvzQ*{įbT ݷ/\ `wB_Ȏӗ]9m!^Ǖ+/jXJx)7=J tkR I ٮws .WPʼn噍-n{te8}A؋.{%h>!INzNڽ [ DhuD]++HqX[Б֫t ے֯ ϔL}X?4%d Vgܶ M~>]W9k3ɌޏlEAQka0kԯH3#(e>}!J6]@Ns©ԄS&wXhogEu$dendstream endobj 101 0 obj << /Filter /FlateDecode /Length 1907 >> stream xXMsI4{n[a{0`[Ȓ-l=Jr`U^e_cXw~;_#˟l4=3OxQgQDq꿳ߐ TTS>#E4\(b|^D[w,%MA2M.1av/6OM;QBsTn=*8 /H!l4J&ӣ|e*,+Vor"{mBn}ﮭo(L!쪕^w"u4V-2) p9Y;`ֶknJ*xPY0趙c5 o"x0`DjnMT+UyeYnnWMn:GjM`ݸKaB"}YI˴!菑6Q}Z!> 2vApBVfuXSd'X:$Z樬M ][WUG_ Eo k3>mgovuwn?8oJhXW @Ttެ/hkmMTGBGDIscRz1*_RIB4g|/@/R"(AN%YI$@Q3 hv]S*i.@$B:Ǿ5*w{5hdaEQEfP2cR-kuJF!F{d4^r較8nU%!IѪ-*d,;oݧ͂MY'@V)&2e&'mX]D֐1Q$+;-fO>g$>?(;]4ObF# w|]_d(:cS}E; `#dZeorm?ٷ;rDPyRYI{Vk';?&Pb}S@~|}oHROQ!onLS½U%vx8ksEΈ㩴VZ.\f NfEzAkR1$9iEzo){zvm{*,]|\3{jii&zNk[-y(N=v5ސޥ!+`:2tvC1Vg/&iW7>+K*S> 500j=9ͪ&<>h2Pt<{9Eb[' ]?YlXg漇6q=mJsW-`ث0h8<]vl4~:&Sٟ!$BleH#K>'71=6޼jJy3FM{Q5[ӔsT׉Xɤ8QIjɎ! huSD?shm`T$;tÉW zﯧrAu}> stream x}ViTS8s6XֱVNC:!0J %'sA0$BSji8txg]>zZ{oYG޳slC JZ%>eℷVEe[?Ixkϕ0!~M@!uasw-Lnڶ,:&v(jZM0*ZKͥS j!J-&S *(]}SrI~eBP% UקO_/3>o)pB]&W 뇙k!Lul=Z]eq'70"}7 sRjd_U݌JV#C"#PPCKL$UpiLBN atwjz?0降K\ł__*-u42~wJuuV9]"&t[\tD:hm 1㝼pZoM"g6jj Z!bAxe(=U7b: x>Xȱޛ/@ =&VoX"!ʑ~4Ȟ &kK)ƣ'ܕh38܍9y֝]uy%Б[`Gf)N 32A7 7w-~F$|NeV{BnOط `VL;, 6mD+.'j8:9 @B:.ȼj#R6#G„%!SO`I >-kv SE̸9Ej4^Ro 08\I&r>){(`Ghӱ|!hdr]nqb}m-hqɞO-]| wVFv反zt K*4NV<ևVo/Njԗw+%j DgʅЩ 9HL̠W ޼U~Q5;QM.%132=eH# . ށFV-֋A]"I~xh^,x@(sh|;Q:Lot_=r R-*he霤SeWI;r!OFT9W(D `3Es%s6\uRVi(ߍ/UuT d'h0YĴQ̉6~0!(ɚ`-'mµx&`+E_TaPt&-8{!!ӌǾT<ɚb\`AtC@eMb9&q㮖ϲ&JHA=.>7dV_Ab; NTF֬plA(hl,F0I[}Dئ3"6{#S^Sl X {2tMR\YuSt83ݨ1gk ϐ]& Vك6J,-;[6m0{r&<\0WIil/о-kY-Ʊ3vXL3?%_v5m4AWMꀋ7h<](e!]m' OfXO*[hέ_ {r<ജ:b|"aj4Յ?t 3]m,VNWIڛj,7LE!-郩T<8h@@o!qNrK2)/EUȔ)|X,Ki#'ũDp ꕋ$\ 'fP#qu'ig-Zk܇=dUF2ˠ䁻G.^ys&Dv~Ηutdw5ՊBTWu\^D1>7" k.ܤj]}hUuV`KAo5K5nxIR%I|ˏn+4Ѩ^#叢zy K -4.!_ތX1%{Am޲4йSѹ.ȬAbK 鸏="]^h0϶̡NB$z:D '{̱#a/ri9dmJIZ ¾ ~JʲJʀF\#cU$ "L_(!9ifR,ڑkzFfv-͌TGk͝x "@~%,.I6edUzi\7*+*rv _.Ҝ,> stream xM]HSqG9LVg%}HB7BQ`7h`dhip:On{w8e.tKMS]U& :x{(B\~Zk-om,*,QQp+? hAKV^קAh>!HBJEhC( t{*&A%svL#5T( m L6]ؑ0ݖa鎚bJY |y)$3i,c 9WlxMvN$ҒF_%JL)icH{>;Fp.o}^x>5Kup(2ؐ=*--L!10MaBj'I$tű~巈Ob ]YChf%|<,vC4¨o3Qv> stream xipSǟ%? @"{PPZCCia a)8%x[hyi_! +6{ Lcm&0LIf̕{+&:o{w]6ds^έ.T[RE֔V~CTLréٳѬYgޙIMɔrKʋr sKKs)+bCC[V,E-SۨZjZOZB=Fe\2$4BvsVZ~/R@qGL_Oҋ>3|Ą,!е"1d*4iݝ]:FhMZJ8(hy6'P&?ת^wF>фt܁78e*![$7RdQƅXpéٽsO.ԑ  r@" `Br% QO7l6ΘҘy+FfK:w 43NRUU8(gP$z]9{]ZcuS%G3HjA,Lcln-Mʣ8B֦9 mrZ[;L_1 1V=|҆,H:-RoƖɹkosϯju*F[ā)&V~+6%ws7N{U+6^&Pꭓ7;V?גg<8| BVnmq_JaNS{ZoAH647yEjKܑhoD :>ĩhؙR40.e Ģm<a[>9ΔJt+'w!N* |WHRUJc;T60gf~|&:7A7vW5Bյ7ehS\ Uke届H 1( dd k6kH7|6Lewю˪JJ-i'a8;Drt |qP eASS%^Ѿg =,|> stream x[HSqqkti}$^"z#D°K3E6͹97wΙ9Z ] HV' ?Q>$yI%[ZXKw5\:zܕ.&emf6O\۞<4nc u"c$GX#(]7-ܟ4e;l xC 7 6wD&)H.R6s/И1\_T$'8ap(;sD`ryeST7:qȟNqh$~[P('GXA3VE!jx)0BEJD {USU|:Ӥ7G^bt6̒Wkx{x;p03J@4="rC^q(1F@ ذ. އ~!33S|PO nϘ[jL~y<\YO!u9r&8Vo^/ >\ > stream xUTiPTW~Mofi_@^W dBJqČ 6ڀ B,dk8#kzh@ *ƘF ʨCT#!5?_瞪s+$.H$u4-.]a]TBRVj\/n>a&^-}ԃZ<+^|e`5k7()jK+r<)/j%P_!ӒzBWot(xgDx喘bc& KX2"MEʢ06;U]W@۳aݪp;C 24RoityvY{GGOg[9_y̏ʕ;apyBE%'G-efGi9\cxTt PnНܯ҅: @{$OE.PRkjƶ24uDc7_D sdr똜y90l蔷r`,ʍD-qoc zt_tXڙomуLV?ČtO*>@Ѱ/7)-RS~" mUxדξ{a?-@Kp+|F}R!# l0#&77֌C3xXF$d!*b9>i`/ahwaO}B?e:2x|XW?w޺}cVֲ0a{^݃O\Hz{nuֻ̠e =\@M0h%/6ޯeŜPx%WVN}^+Gsug홭Yyi'TjԪ^a6*@=0a.Xz>m> C+iI[U*vpU}:N@TkQ񳲖ŚWQg=]Rv^ZpK/nAwl^k+b6|K\ 6Ap#Y1Dޟj; 10^+v4?/&g$HDN<׻P a TХ p^Rag6NKut ]萵I!sQdc6EvɗXEObݤ )f6-"aCoß ZWoî÷&Ba[ю?F@:[nB/}̜-87Q9Ve巶czcUf_vs9Lxh䮺Qo-endstream endobj 107 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 462 >> stream xcd`ab`dd M̳ JM/I, JtòG@ЈAAAl C#9Ơk3 ;0-ɵq˓0~Y[ÙtխOwSmjŁg}rߓ3FE ˔j3f}i8{-xsLvvX޽5b,&]cٗu%%tsd/>}tǟi:rYl[vG[:`5B]앸Es:ʛ#+Z9~}7{5gJ> stream xcd`ab`ddM,M)64 JM/I,IvSewo$rRS KsD13032?3 Uz}_]+g+[mEwy?͜=_,H -},#cީgHNk YmMuSۦ{ĴniSLFfrtnShl6sq1p.8wjľ%<< ]Yuendstream endobj 109 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 160 >> stream xcd`ab`ddM,M) JM/I,IItw,ew. gO 0#/c`bdd?U@ }Jk\f-.)Y=Se 5N> stream xLMMathExtension10-RegularRC  integraldisplayZ+RꥡIC.UT?S`T"q-n;jyB]P:grrtsr|hXa,~հi\xjzurj{$  To 8|&endstream endobj 111 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 6142 >> stream xY\׺NJ0Y&&Ѩ7Bb( v)lc. HD!E$ͪĨihr3;;9_7omebĬڶ'W'FmfdD0=89^(y{}(%,xuOEqmIۗ&X34lex]k"E2m/9{y-xL yirSR j%ZMPc@j- S~5j"ZHMEbuej OMW2jS(o|(wi/%D3Գ?5K S!ʃR&ʋb(_bm[|}osW#!эVLӀ,1z!<{93#kxjS߈q9g83wӞV=}A"In mqo>j(֔B-Yhs4.2@of1ȄЇǐX+1aMfc qd{A"`ޡYQHA4.rٽ]Z$b:tLr1+B~c]1D:}lwE+p_.R)'P.*zX>Ux6^/_G^+p"@>Y KvtQP#qСq<+x}<Cp(E՛(􏪲jú?Ֆa5Th,a*Cy[ | ѷecINт &HOؔrj$)N+ @L$Co#&[k1p)H٣uQPBdCC D~XzYĄ.U|&0l4_tLS@D]\|XNȔe9\AB"MkS[LUHF@Vf;f"BY4ۡZOLl0U+]̍]yKQfnɿ [цجCJ#rJL5Z^2ρYԗ~N8Z ۺ{2l7X芎q>53P]V:@SȧyG]]$tt:e󻑗XfݠSVf$|706Į3i)p$2l2%z۾5}ٻwX:lUw*%HH^h9MfEbsC,(Bn:ww^Ls;hߣxؚ:xrv;ekc%P&J*5 ”Jvцh;C3@t]T"da*qZ i|߲*A䋾rhGS v/!ՏN"r`:1@C]}ΐ$.:RF,tLٍW d6&|Ky[j{펱(ɦ3p5 ,%yUAw"yqlb򕂇HnYc<;>ã`+~j~55'/;"(G/cnCxU.VI r72oTQ!Iqr$X)ݖLj2hvkE/Wڈf8ћg ,";hƊQ]OͭyOn]+b#g}45w7]1E@t ʿkv$"ա`i,Oh2- sMĿlgc; )7 OΚO^ SeR`m^!:E|oMN=8ɾy`{:W^~;6& */YG IPIa(!u ICQ >EPمKuư^T'a'wcAsFJ\h`Xk)$H՘eq,93VmNxgG|0c8]ߍ84 u{@KRi{7 aťv~HB20TRE5I}zHf2<RWϲrJ) Uu)DqLWWPĎ[pb[P*n WB/r }=:n\6m܄sL &I)B(/2Y,'H50k'6NZ_(I.PWPguEXciNtֱnP՛9}m  Vk9C2^U%Kރg1VE!㼮8~q!1/4?xJL}hVn T$){yiw$J~*|ݬ/t$*YZ=x d{0l+"l4Kg"P tՋ]p:N=ȓ:Gchv~?Rl`90}:nؽG5 mto{348:+BC ~x;Qx Cqg T@M%R;ݜ7QW\rWq|_H[h-!O1p(.t;ҋ~Ūuz>@ >t#ձ0pzCz\9iq-(a!h^ؙ,,3|5[ v'%ꢵY[g)Ӿ]wsKMeΪYD! 49r"U ܨlbcY9 {—)+ u ME{46ҡʁ;-B`-갞`ؿ}v㒓мhzc&d10^+mcYqSKE]Cw ~|!dqsimDGY5ݼBЎ%#$]%r_ln'hZ1wD0lrtIWZE_,[jD{uߠIL)f&jK)tE 2&YrZ{~7 k'=h^kёu[Y =0~$9)<8J꒫b-b3ct1euPU]yvxpySU[6Qْa=ˀabv!Ѧp+U㌮~ET@PΕOW.i$k?n\"H)b?V7SSS]1j^\֢ө灤wچj6ULr?w PrGS _m(3hztWh&<ٻ4^'At<7tFFԅqSQ:2'#T9^xO6E]*>~IfP]oՀG2=fnHE. Px5)?1s78k? BK 'ۼNĝ)|K\@C5Z\wr'[Q _(8w .o/,Ўti;Uqe ׈T$2 %#΅X:.– u[.)ʀX%,'@]r6F>;zj)#'A\5&ac9#IXRd S2?/uD .K:bݼ2S)#h^ѥଳ GӍ ďCqҎuL:7S'aԇ0JGƎDd'T-% )$s#-  <LbUglvZїN]:@VӒPRf\B/27m[Z" M4Zt. C_~kM>QڣOQ|:$6B\Ѥ)9Ѯ%-uߌvr2;yjM>MP(OomW0c9 2Za,H{53>ShFT(s!*1 ϴT'-oej6+f3JmWH5!yE%@ۦyv[Z_yΧlQe_ʼ\lC r>})@!U2r>)+͢j1r V}NS]}ɍHP MV@w'E "NM"Z(a`nqWΈs \| rV}izf>)_m %쟮L(M/+R&<.̿tQfb0U_Bٗ6_ZEno7]Hx*T9€XY"2+JDVti!) dsUW"k6{1hBk∣!7;/'vنL>Ie RJ 261b~C7r=hݜH˽UB{mb<Q^8748M=$?p VWȯ}1g+ɆsvnDbAo^h‡A< (Y/c`lAjj4.wˍ$6Ǒ堹q?ƙjLT0-&͔W}n*-j!0aAȩYZ]eNo0x]tD5kٜ.Zcϡ|;;BOGk)dKj$:]4}RŰT4KW+&M˱C &?L^yz!HǷM_H0XE_<]9›L!qf)kjBA/5dsh|,\ro 6Rgi96ڽ.;96mw;IK3l}zڲ @Z/RT85eˤ1p]4":1,6.+;o`̠J,d4yʀendstream endobj 112 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 318 >> stream xcd`ab`dd M3 JM/I, JtwXSeBgO`&C#!afFFgJbcߗ>d+)]{Wwyzvws/>}|9ǟ^:C7CPÞ~&Ocw4FϚVnlE>]+Wn}o+~Flkd V-wbn/m\b\7mlΑWS'/`u[%$suOoO_O爛yx$endstream endobj 113 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 3858 >> stream xW TS׺>!s1jO|s[} GjUh La I 9 EQ VYNjmm݇{w{{9YZ}%WN-3k]HXLgq }E.z4x nFPK1q I);BBEG6Fs1v)j 5ZKCSj#@-|RjZAVQs)?jzOMTM (wjr |CP$|1y#,y1?uW5\3ynnG|κކ Vtۚn@}(ϓUҬā B@BcH& ۖ" OR8E%ޢUUk1(+JGE~qep8׺3jz "zL'[y Ka_Nn7؋{EuP::TX%"6] vG V.PEWɡQ"҃7Hx9% THPzfsxh䧛MB>E TG7H NV-IRRSX:zMmT^hj@ʐV4ӄn5ZS=T~?ǴMC4OW1oimm< #OɼQXbA!\F 蠚A14Qۘ+^”=cNN$$~bGuT|}1E*ߊ7nG j]Q8xcg,=1Td/ Uhv8 O%-MūCNpW%dS“<ٵs5R[ 汈ʴ݀X5^*it[ DVk2!Mh\&(&$2!set y)Iac A/vQ8m&SՒ^(T!3S:1$ <>Q";۝ݝWUZcJfdH{D&*3I IBvQ ƒ4ҭ9!ՎI֊V'y'o<=t7Ћeaa+*5IV< Ӛ8t77 =p 6&TWdvIx=gӛ(Opۡ.jOMImG8t7bnw/X!D`"!!XvMy $A:O{MFeAm̜ޢi e_j4%E`P)ӽ|pLTWAlj Tdy[FȩK#UϪ 0B~ YExWPLrū6Cb) 39&wk}I6J҄-Am߫e7efKu=$&`{CJ" EʕQB0*|~9wr]"-h kc:]/9.fMEo ޿YF(jB6 Di@&ܧ>.+c9tT=H~bx] b] !5vIJC5hK*[:*A;7Ktk!R+5ryMށFdri:ҧ5A>(s&l/*]-PkoPuަP.As^qk7\qZ1==-ɕ q)i1A㟵tCJUmgtބ|JXnjzW/Dĥ P)@%,_̛>TםNZ%a'[d6~\&֙M-vqPǥkH0+P>X0D#owmP.&`!V,Ufnx>Z<>!{COv$SAp.nG+^h-Q"*,) {_8zuh$rr[ LBQiLWTҬ;wW]rɑP JUREar}yeq-0%N/ql15Yt-{$5F`n >eX?Ŵŝ'+^CnW%|blVpzFrx%ĺM*8܀7F(Mπ \-)jrfe;i9,U5^cB\苰/Đ a)o뱐SP̷7$8#u5a+6A-0 x}>>ĩQ75Ԅ~%f{D{z>Q]}$$R1zGqs|Ctt||ttC|ssC1Gy W|8 %:%DFQ9iBӉ6PWkI{sY'ҽT2JDҤ~V~hHH|3WOaWeJiv񏬇I'GO7`G{]:? yt`4wC%ABr<Ҿ䗇#~/n}n%iXPvzwv||LCg0ۓsp4F2[î-c|aT15-恈m? U; .TF$x0*zׄ=AA5*f<3/_@B ag?gڀ(ZcB&! 築ڤ1111 E%NӒh@*dk_ l{V;ߚA1&~ws"o{Ĩ} ӓfۏ:wf KGzګDpۺX b^G}xϑ<9%zU϶[HL./$f/0+m3|ű+Aױv-=} rCVym g,І$>䚌\㐫'9 ׉-ɖl9w5,Ƣ͟;*z(` s96EMvb:NvU~K&A/_8{A8}I@Qi=5 vE?ov nHV7}m v0N Sglͣ;%O.Ixuc[w0q*=YsLU IճK X͸&{c|k/wyA# ?rqwendstream endobj 114 0 obj << /Filter /FlateDecode /Length 2142 >> stream xY[o~oȃ-Q*ΝmS Ң6E7B`%^6(7{FHY$؇ș3f1^]Qvf_^`M4n:cB~Y&Сn/pDߣ9CžjjJ1 d >ۀI-䤠& jSh8A)N8x.9i8T߸Gňdk1QP샛(EܦD/箪c1X3qJ&n{T"ҹ%C1Xfr,'! "gdT Q}9F?ڰ*% &u3BC9nmarȳ *Pba ojA=IJtH."I}3SP!% u@7~I"C)D K%@ɰ"KN@8UxlƆ\eJ3O.a8:F-uBˡ 6iVꭸLYḧ-MJKķczjH!q{5V:'ŁNf?cpddޔJLQBd$a A؞ WRhjUQ[u @Zt6 ֮L.lkyfz, ̍*+og} K>[|`^4WCria$`_ |o_Bjrq(\t5 0c[88iح"~H[mw[40.֩{2|[M K[q}{li`q" $ٓ=I`z4uE ".KE]ӭCE4<7iY0YqR8}2Km u Io!j q;Kmd_%F5D"HPsFYbte= /]ڤLh ].3V)n%RX{5 6f9ʲztJ E`!R=Md*T\`>!TǮlz4"U尵_G'@,ґQŦ] l5Zh>^׽rFWTWž ߖѿLvwBSf13u$zx'wdY=Y7h-1jY.i|]:x6% x(M=01/ ϛ6 ?k,eYzsh~~3ܝ }aohl_fȓ?1:ο)VJa' ]Peσv-_ۖ(zK"lN(s[/6OHx@sloM aS S ny<,m6 w+:>K,b:}S39vEB /͒8D[AK p> stream xXKo67`d/tkŧĠ--v[c{"+Zr$HNEEX<țiio^Mzr3ztjjf1y0Xjb)t%BNgؓOxD9ib68))%$ Z8Mp,Qr^ %ĢavBQJs|FH2x3[DK?/~VQ>B"qo_w7cff&o$br:F:v}6>Iaq ˴,5U7}rL0ACVdxf2J;L@= lR>lr/ʶkKgEΦ7U Ý"Į%b$}Qv\1+yN5<_nlHtMg&x=S$YR 6#wJА̑ƨ?lZJ&qfgi$ڲQ d, У[.XwS-k sI>؏ @=YZʣ~&,Y7xNlT`8ӽ@t*7p4jA̜]Y,EB'6쑞h(?n IVG1m,X.O=g`*Ӽk,qv&=f,+&Cx, Tqu$E[m9c51óјu=>AD{g>aچ vo e9VAoon9PpRnɋ]7}t?zW:oieos?ljp>DcNpvOK a%ɇ妓'7w+5㩓h[^9`Lֽrzu۔i B[WA9bu50"j] !+y l\й m^dB]JG@'vz zfuR $_]躢1nDwm?'pAg#?y$M$> stream xX[D~ϯ(c=(R+ xh r!'{\l$^P}X{.}v`2MNvB[mo'9ί& 9fYO Jp|&0c9ܙ'*8D]E1c4CׇH$9Kqp]z*9@%N3G $<'!չ  uDΥD;j;gG2:8Mt.RϸM;S#iJ;AhXuf[mR pBL<{/MbY:Mk='݁ϥ'U ZE 8O9XOR}Tf:<2Jmd jtj2VP $G?E|C|Ot:rAv~qq⣦ZFCd43b xkOvÚϸ\Bm 2̑r:u2y̘sWHJ<4) %H?#[wځ#JpJ ?¡, lVqK &E9!vπcѼx nצVD}ىcH+2v(@X j6lu'm.}XB[藳evwYcAj\ĐbhagT!1{aP8\2&(?w4 M ]>m[?@μ9L_]2צʃ.SR2r2SRC;EN2uӲ-G'X+RRJA?Q(+X3vXT€e M"-6e`Z +gφXi d)}S*e[ZrVC PPX,o[C X Q)Tۻ}9 ߀}D$&x.fNDCȥFNg(BFo2^HKP^ٻy0epewؖuDYD1t6enS!dqf/@C mꁡ,4ACuڎk3AX#0'#zPT?={m\fщҋJSCx6$̳oڕ߮rSrLp&ƦG)LݐRy0Ot蹊`<'Lp!ܘЎc ;C POGpP4FnUձZ(P>Vݪ) #@it7g@=Xj/tORX>ƖGL|6\oF <>@/~vȘ ( <_5n&@tN-6МO<0X.sdb5փmBDv@um ĢT~N>2'`¨JM&/jsq"}O~=ǔendstream endobj 117 0 obj << /Type /XRef /Length 125 /Filter /FlateDecode /DecodeParms << /Columns 5 /Predictor 12 >> /W [ 1 3 1 ] /Info 3 0 R /Root 2 0 R /Size 118 /ID [<4f06449ce071d1d4436a4427f9794716><1ea037cf50cc2db055b4dcb64794b045>] >> stream xcb&F~0 $8JP? M6DA$Lɞ "H R,DHDɱD|̻"`q`sA$d" R"̞+H2r'/A endstream endobj startxref 69188 %%EOF cvar/README.md0000644000176200001440000000652615105335521012475 0ustar liggesusers[![CRANStatusBadge](https://www.r-pkg.org/badges/version/cvar)](https://cran.r-project.org/package=cvar) [![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/cvar)](https://www.r-pkg.org/pkg/cvar) [![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/grand-total/cvar?color=blue)](https://r-pkg.org/pkg/cvar) [![R-CMD-check](https://github.com/GeoBosh/cvar/workflows/R-CMD-check/badge.svg)](https://github.com/GeoBosh/cvar/actions) [![codecov](https://codecov.io/gh/GeoBosh/cvar/branch/master/graph/badge.svg?token=2SW9HKG71Y)](https://app.codecov.io/gh/GeoBosh/cvar) ## Overview Compute expected shortfall (ES) and Value at Risk (VaR) from a quantile function, distribution function, random number generator or probability density function. ES is also known as Conditional Value at Risk (CVaR). Virtually any continuous distribution can be specified. The functions are vectorised over the arguments. The computations are done directly from the definitions, see e.g. Acerbi and Tasche (2002). Some support for GARCH models is provided, as well. ## Installing cvar The [latest stable version](https://cran.r-project.org/package=cvar) is on CRAN. install.packages("cvar") The vignette [Guide_cvar]( https://CRAN.R-project.org/package=cvar/vignettes/Guide_cvar.pdf) shipping with the package gives illustrative examples (can also be opened from R with `vignette("Guide_cvar", package = "cvar")`). You can install the [development version](https://github.com/GeoBosh/cvar) of `cvar` from Github: library(devtools) install_github("GeoBosh/cvar") ## Overview Package `cvar` is a small `R` package with, essentially two functions — `ES` for computing the expected shortfall and `VaR` for Value at Risk. The user specifies the distribution by supplying one of the functions that define a continuous distribution—currently this can be a quantile function (qf), cumulative distribution function (cdf) or probability density function (pdf). Virtually any continuous distribution can be specified. The functions are vectorised over the parameters of the distributions, making bulk computations more convenient, for example for forecasting or model evaluation. The name of this package, "cvar", comes from *Conditional Value at Risk* (CVaR), which is an alternative term for expected shortfall. We chose to use the standard names `ES` and `VaR`, despite the possibility for name clashes with same named functions in other packages, rather than invent possibly difficult to remember alternatives. Just call the functions as `cvar::ES` and `cvar::VaR` if necessary. Locations-scale transformations can be specified separately from the other distribution parameters. This is useful when such parameters are not provided directly by the distribution at hand. The use of these parameters often leads to more efficient computations and better numerical accuracy even if the distribution has its own parameters for this purpose. Some of the examples for `VaR` and `ES` illustrate this for the Gaussian distribution. Since VaR is a quantile, functions computing it for a given distribution are convenience functions. `VaR` exported by `cvar` could be attractive in certain workflows because of its vectorised distribution parameters, the location-scale transformation and the possibility to compute it from cdf's when quantile functions are not available. cvar/build/0000755000176200001440000000000015120300537012300 5ustar liggesuserscvar/build/vignette.rds0000644000176200001440000000041215120300537014634 0ustar liggesusers}PN0 Mv!H~q Bܐո#Zh4[Ɨ3Idlj2aqxFnDvA>[+LW]6 Ktak,Q#T,~#5 1Ɏ5{i96XIp=?,,JѾƖu᷏3} 5 ¨vm k`F49{EFy8`cSwԍEnK'\\ 7`!+ ;?<#cvar/build/partial.rdb0000644000176200001440000001730715120300536014434 0ustar liggesusers=rȑ-(Q4*3VS&%Qh8DMj lhR\x7b={>la?`OD P,jk+d7ʬ*r]\Q@OrGݹSV\b[ow6y,bZ.5r.᷽emU6&>o˫[i1$5.lUUU7(Cs?n9h!z^> OMts#$ț{LNcO)Wg?pzQt _y~j(N䮀͗/V^n +L?h Eɭ7Je77W܍[7oKbɑn*Xkk[ =>PQޮ:ChJá Ry})%DU',΁LU{؛T=S@@4qm}a6ozuj ?7,3'?I3`a[ʺnѨeJ;D1lֶI,X& ٍ!rϲQOȆkv=fk;vj1 9SSYfz3+zUS$U#HH}Ě=_.t/dժ@x]V\Bx+P+ɔGuF) R+13^@>^ ֨~|/,:X\>=s )}V/bڃ0x^VpnTWT >TagM7JP"+ Ĥdfڈ뒎D:!~@z){ yIm늩y츺0˪]6ⷓt7^R8l(bA qd;>'00)Tپ#rw.bwN+*!6Lga.b'X@\zv8I9% a,@@T( ´f#sD#> } Y ӿl ,eD6,թx6yp,5M S\مS*f32 |S`z1OTj46 gRkfڟrh0U qXam@mݔ',Lj?$SSSVu-Je"8#Z\'v9#ͳE7 ͝DxD -_Fe1y"W_xh5xQt& vχr KLAx eaw ur It?<鋮t: ;rrApП 0Q~qXz>kڷ!~/v#O$cn4[S86&Ȧ!={"x YZUpš/rZ"y9.KJ #4H בx%Io`[5;w gR9w 6Hي2%C!rs3\M.er7yJxcqu3vJOBoe#_ jVj:K`|}-_6⏲>V X0u}RT&,!y ֭7u2J:3DQUV2,#OzmA0 mcP;,vQYF z $8,IH@S.2+'i?H@xBKL@syӹf&N0XJ5޲șA8xz4Gl˟}x,UdA覤4aZ\t& BYi+Rœ_d,,uFF+dґ}\VNm\'U!.I C'kJn E<r3iS>L(l7- 6f&D0(D8xvUVq՟ZcfY_ WlQNqKm( ۖY5mݢ*~Z kL@( Q^Be`̲L1~[cyҚxHvfɖǤ83,ˆ4f #7)cBl)T:PҒE.fwe[6hO+2xu[?0^ԋZ<ҫ?F>.#'~" 'I'9mבrR uqT_ %=1iތiiħS|"yMAd \B|)5y?8~S.Uq: ҩl{mhA[$BO&юGY@ aZeہc\3Js/#(̑VIqZ=Ds "T K~q-UG pP^o xAummx,{.%22Hc{ǪVbt 8 \b۰ol1]lA/u}y.M8X)VH t 6lVcS/V%vp34wo.!;<\6cAsی5.uWnL׳yj&!|Ԅʄz-Z{廴c|%K)QWэI־ΥpG!mT/FHUs]+ao<_rb;Os~}zJilsR,l&H PeeOS7(5O*x_$Ɔ<6!&)7k6Ͽ`,YQyWf!X^awbJV'LYVfaܡRV1>yauu}c2c H7;ƽo߹e8w)kkݚfy8w`ۙܭKo5}}ON:|f*r00B$Ob{}rƈ/ktpW&` q&W0h~hu}P`}/_,V@OwWVV殺i8?jɭ7Je77W2fn޺9}~~^dE))t["a:$!B=_sOV[1(Kp(6tX+G 2_Zow8d7w![Hk܌8"k~tm-H,XlvQBrhd.fӇ,\)Tö0+ZF)8i1 ֢+mtLs#:ݚ<)-(_rƘW!,pX+½|\AkmӞ³٢B=/pb;Y/+h|Lz:? DǁTї.CքQ9؞~ˡbmLSyc?*y]rjMKj%?-9;s />L{"r"rmD_3pm]Cms13e=O1zgl zo~x#. Some support for GARCH models is provided, as well. URL: https://geobosh.github.io/cvar/ (doc), https://github.com/GeoBosh/cvar (devel) BugReports: https://github.com/GeoBosh/cvar/issues Imports: gbutils, Rdpack (>= 0.8) Suggests: testthat, fGarch, PerformanceAnalytics RdMacros: Rdpack License: GPL (>= 2) Collate: VaR.R cvar-package.R garch.R Encoding: UTF-8 RoxygenNote: 7.3.3 NeedsCompilation: no Packaged: 2025-12-16 15:57:19 UTC; georgi Author: Georgi N. Boshnakov [aut, cre] (ORCID: ) Maintainer: Georgi N. Boshnakov Repository: CRAN Date/Publication: 2025-12-17 06:40:47 UTC