horoskopet - Astrologihuset

Effektiv risikoberegning af aktieporteføljer ved
hjælp af principal-aktiver
Nikola Schou
3. november 2014
Resumé
Der indføres et nyt begreb kaldet principal-aktiver for at muliggøre mere effektive risikoberegninger af aktiemarkeder. Begrebet bygger
på principal-komponent analyse og der argumenteres for at principalaktiverne udgør en optimal måde at repræsentere positioner i et aktiemarked - optimal i forhold til at udregne forskellige risikomål mest
effektivt og optimal i forhold til at analysere markedets korrelationer,
korrektioner, afkast, regimer med mere. For at underbygge teorien gennemføres en række empiriske undersøgelser af amerikanske aktiemarkeder og det vises at beregningstiden for eksempelvis varians, value-at-risk
og expected shortfall kan reduceres med op til 99%.
Vejleder: Kristian Sørensen
1
Indhold
1 Introduktion
4
1.1
Motivation og emnekreds . . . . . . . . . . . . . . . . . . . . .
4
1.2
Problemformulering . . . . . . . . . . . . . . . . . . . . . . . .
7
1.3
Opgavens disposition . . . . . . . . . . . . . . . . . . . . . . .
9
1.4
Tak til . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
2 Matematisk baggrund
10
3 Markedet
13
3.1
Kildedata . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
3.2
Datasæt og perioder . . . . . . . . . . . . . . . . . . . . . . .
14
4 Principal komponent analyse
14
4.1
Introduktion . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
4.2
Matematisk udledning . . . . . . . . . . . . . . . . . . . . . .
16
4.3
Udregning af efficient rand vha. principal-aktiver . . . . . . . .
20
4.4
Empiriske resultater . . . . . . . . . . . . . . . . . . . . . . .
22
5 Effektive beregningsmetoder
24
6 Approximation af varians
24
6.1
Bestemmelse af reduktionsfaktor . . . . . . . . . . . . . . . . .
28
6.2
Empiriske resultater . . . . . . . . . . . . . . . . . . . . . . .
29
6.2.1
Historisk std.afv. for en portefølje . . . . . . . . . . . .
29
6.2.2
Valg af porteføljer . . . . . . . . . . . . . . . . . . . . .
32
6.2.3
Resultat af empiriske undersøgelser . . . . . . . . . . .
33
7 Definition af value-at-risk og expected shortfall
34
7.1
Historisk VaR og ESF . . . . . . . . . . . . . . . . . . . . . .
37
7.2
Empiriske resultater . . . . . . . . . . . . . . . . . . . . . . .
37
8 Approximation af value-at-risk
8.1
40
Bestemmelse af VaR i halen . . . . . . . . . . . . . . . . . . .
2
43
8.2
Empiriske resultater . . . . . . . . . . . . . . . . . . . . . . .
9 Approximation af expected shortfall
9.1
Empiriske resultater . . . . . . . . . . . . . . . . . . . . . . .
44
47
47
10 Bestemmelse af cut-off faktor vha. af random matrix teori (RMT)
52
11 Forecasting
57
11.1 Forecasting i Danske Capital - et resume . . . . . . . . . . . .
57
11.2 Forecasting med principal-aktiver . . . . . . . . . . . . . . . .
59
12 Konklusioner og resultater
62
13 Perspektivering
62
Litteratur
64
Appendices
65
A Programkode
65
3
1 Introduktion
1.1 Motivation og emnekreds
Prisudviklingen for Citigroup Inc. i perioden 1977-2014 ligner en bjergformation skabt med dynamit hvilket kan ses på figuren herunder. Fra starten af oktober 2007 sker et dramatisk fald i værdiansættelsen fra godt 500$ i sommeren
2007 til 10$ i marts 2009. Det svarer til en reduktion på ca. 98% af værdien på
blot 18 måneder, hvilket igen svarer til en halvering af værdien ca. hver 3. måned.
I juli måned 2007 var der stadig gang i festen hos Citigroup, hvilket følgende
udtalelse fra Citigroups administrerende direktør illustrerer:
When the music stops, in terms of liquidity, things will be complicated. But as long as the music is playing, you’ve got to get up
and dance. We’re still dancing. Citigroup Inc. CEO Chuck Prince,
July 2007
På dette tidspunkt vidste hverken ledelsen i Citigroup eller resten af verden at
der var noget så fundamentalt galt med virksomhedens dispositioner, at man
blot 3 måneder senere skulle være vidne til starten på et af de bratteste fald
fra de øverste tinder til fallitens rand i Wall Streets historie.
Før den finansielle nedsmeltning i 2007-2009 var Citigroup en af de største
banker i USA med 357.000 ansatte1 . Da Citigroup i perioden op til oktober
2007 havde status som ledende børsnoteret selskab i USA, må man antage at
adskillige kloge hoveder i og udenfor virksomheden har lavet daglige analyser
af Citigroup med henblik på at værdiansætte virksomhedens aktier, herunder
at vurdere risikoen i de aktiver, banken lå inde med. Hvordan kan man tage
1
Se http://en.wikipedia.org/wiki/Citigroup
4
så gruelig fejl, at alle - inklusiv den øverste administrerende direktør - i sidste
ende fremstår som glade amatører, der blot danser så længe musikken spiller
uden en klar idé om, hvornår den stopper eller hvor mange stole der vil være
tilbage at sidde på?
Vurdering af risiko er en videnskab men også - som eksemplet med Citigroup
illustrerer - konsensuspræget gætværk på kanten til kollektivt bedrag. Ikke
desto mindre er risikovurdering en grundpille i alle moderne samfund, hvilket
er motivationen for at denne opgave først og fremmest skal handle om risiko.
Ud af stor risiko kommer stor fortjeneste men også store tab. I et samfundsperspektiv er store fortjenester til enkelte individers fordel, risikotagerne, mens
store tab potentielt kan føre til andre endnu større tab og i sidste ende destabilisere økonomien med negative konsekvenser for langt flere personer, herunder
personer som ingen involvering i øvrigt har i den risiko, der blev taget, ej heller med udsigt til deling af den potentielle fortjeneste. Denne asymmetri giver
anledning til det velkendte begreb moral hazards, hvor risikotagerne fristes til
at tage en for høj risiko, ganske simpelt fordi de ved, at en potentiel optur er
til egen vinding mens en potentiel nedtur deles med offentligheden.
Af disse årsager er risikostyring et vigtigt nationalt og internationalt samfundsanliggende, som har udmøntet sig i en række finansmyndigheder, tilsyn og regulativer. Konsekvensen heraf er, at der stilles stadig større krav til
risikostyringen i alle større virksomheder, herunder i særlig grad finansielle
virksomheder såsom banker, investeringsforeninger og pensionskasser. Sådanne virksomheder er i dag nødt til at besidde folk med særlige kompetencer og
specialiseret software, der tilsammen giver virksomheden en effektiv forståelse
og kvantificering af den risiko, de står med, herunder skal de beherske effektive metoder til at lave fremskrivninger af volatilitet, afkast og andre størrelser
med relevans for risikostyring og/eller porteføljestyring.
Forskellige virksomheder er udsat for forskellige former for risici. Eksempelvis
er produktionsvirksomheder især udsat for operationel risiko mens finansielle
virksomheder især er udsat for markedsrisiko, equity risk, kreditrisiko et.al.
Forskellige former for risiko kræver forskellige modeller, både konceptuelt og
beregningsmæssigt.
For at analysere risiko er der i de seneste 5-10 år opstået interesse for et begreb
kaldet risikofaktorer, se [13] og [8]. En risiko-faktor er basalt set en makrostørrelse i markedet såsom markedsværdi, momentum, volumen og volatilitet.
På Figur 1 ses eksempler på risiko-faktorer samt korrelationer imellem dem.
Disse makro-størrelser kan kvantificeres og der kan laves lineær regression
af de enkelte aktiver i markedet mod disse makro-størrelser. Hermed ender
man med at kunne opskrive ethvert aktiv eller portefølje i markedet som en
linearkombination af risiko-faktorerne. Ifølge forfatterne til [8] får man hermed
en forbedret model til vurdering af risiko og allokering af efficiente porteføljer.
5
Figur 1: Tabel kopieret fra [8]. Viser eksempler på risikofaktorer samt
deres interne korrelationer.
I denne opgave tager vi skridtet videre ved at indføre begrebet principalaktiver. Principal-aktiver kan opfattes som en slags risikofaktorer der dog adskiller sig fra andre faktor-modeller på følgende punkter:
• Principal-aktiverne fremkommer via en matematisk velfunderet model
og ikke ud fra et gæt om hvad de vigtige makro-økonomiske størrelser
er.
• Principal-aktiverne udgør en såkaldt fuldstændig basis til at beskrive
positioner (dvs. porteføljer) i markedet. Hermed menes at alle positioner kan repræsenteres eksakt og entydigt som en linear-kombination af
principal-aktiverne. Samtidig har principal-aktiverne en orden, hvor det
første principal-aktiv er det vigtigste, det andet er det næstvigtigste og
så fremdeles. Det betyder, at man kan lave graduerede repræsentationer
af en given position, der spænder lige fra anvendelse af blot det første
principal-aktiv - som giver den højeste beregnings-effektivitet men den
dårligste approximation - til anvendelse af alle principal-aktiver, der giver den laveste beregnings-effektivitet men til gengæld opretholder fuld
præcision.
• Principal-aktiverne er ukorrelerede. Dette er i modsætning til normale
risiko-faktorer der har korrelationer, jævnfør Figur 1.
• Principal-aktiverne gør det muligt at approximere forskellige risikomål
såsom varians, value-at-risk og expected shortfall på en overraskende
effektiv måde.
Disse egenskaber gør det yderst attraktivt at beskæftige sig med principalaktiver og dermed er der redegjort for, at dette begreb udgør fundamentet i
denne opgave.
6
Et berømt udsagn lyder:
Time is money. - Benjamin Franklin
Sagt med andre ord:
Time is money says the proverb, but turn it around and you get
a precious truth. Money is time. - George Gissing
Time is money. Wasted time means wasted money means trouble.
- Shirley Temple
Tid og penge er yin og yan indenfor økonomisk virke. Og samtidig er penge
og dermed tid altid den vigtigste knappe ressource.
Risikovurderinger for finansielle virksomheder og især risikovurderinger, der
skal produceres til finansmyndighederne, handler i sidste ende om at lave nogle
udregninger, der ender med kvantitative udsagn formuleret med tal eller grafer. Fælles for alle disse risikoberegninger er, at de næsten altid baserer sig på
tidsserier for historisk udvikling af forskellige størrelser. Dette giver meget ofte
anledning til ekstreme datamængder, som skal indsamles, lagres og behandles. Og eftersom risikovurderingerne skal laves hver dag eller hver uge, ender
mange risikoberegninger med at være meget tidskrævende. Af denne grund
er effektive beregningsmetoder - eller algoritmer om man vil - værdifulde for
store virksomheder. En effektiv approximation, der giver en reduktion i en given risikoberegning med 99% kan eksempelvis gøre forskellen på, om man kan
producere risikoberegninger i real-tid eller ej. Eller på om ledelsen kan nå at
reagere i rette tid på en given hændelse. Derfor er effektive beregningsmetoder
for risiko guld værd for store finansielle virksomheder.
For at skabe en overkommelig ramme for opgaven, vil vi begrænse os til risiko
på aktiemarkeder og hermed har vi redegjort for det nøjagtige ordvalg i opgavens titel: Effektiv risikoberegning af aktieporteføljer ved hjælp af principalaktiver
1.2 Problemformulering
Hvordan analyseres et aktiemarked mest effektivt?
Hvordan ser vi klarest, hvornår der sker korrektioner i markedet?
Hvordan slipper vi ud over den vilkårlighed der ligger i at udvælge markedsindekser eller risiko-faktorer baseret på makro-økonomiske størrelser?
7
Kan man forestille sig et analyse-apparat der reducerer kompleksitet og beregningstid for risikoberegninger radikalt?
Denne opgave vil forsøge at give svar på disse spørgsmål. Som nævnt flere
gange begrænser vi os til aktiemarkeder. De resultater og metoder der udvikles
kan i en vis udstrækning anvendes på alle aktiver, der handles på et marked
med tilstrækkelig høj likviditet og efficiens, men i visse sammenhænge gøres
der antagelser, som holder bedst for diversificerede aktieporteføljer.
I traditionelle faktor-modeller laves der som allerede nævnt lineær regression
imod forudbestemte makro-størrelser. Vi vil i stedet tage udgangspunkt i en
stringent matematisk metode, som ligger i grænselandet mellem statistik og
lineær algebra (eller teori om mange-dimensionelle vektorrum om man vil).
Metoden hedder principal-komponent analyse og er vidt og bredt beskrevet
og endvidere anvendt indenfor finansiering igennem mange år, se fx. [1] afsnit
4.5 "Interpreting principal components - Stock Market Prices"eller [2] afsnit
3.4.4 eller [3] side 208.
Denne metode giver den fundamentale indsigt, at der i et marked med n
aktiver entydigt må findes n kombinationer af aktiver som har den egenskab
at de (i) er fuldstændig ukorrelerede, (ii) hver især maksimerer variansen og
(iii) udspænder markedet. Disse tre egenskaber kræver naturligvis en del mere
forklaring, og det vil blive givet i afsnit 4. Selv uden yderligere forklaring vil
nysgerrigheden hos mange læsere nok være vakt i forhold til hvordan disse
kombinationer af aktiver findes, hvordan de ser ud og hvad de kan bruges
til. I opgaven vil vi kalde dem for principal-aktiver. Hermed understreger vi
tilhørsforholdet til principal-komponent analysen samt det faktum, at vi kan
betragte dem som et nyt aktiv på linie med både de oprindelige aktiver og
alle andre mulige porteføljer i markedet.
Den overordnede tese for opgaven er, at principal-aktiverne giver et optimalt
eller tæt-på-optimalt udgangspunkt for at analysere risiko i markedet, herunder at lave effektive approximationer og beregningsmodeller for diversificerede
aktieporteføljer.
Som centralt resultat skal nævnes approximationer og beregningsmetoder for
historisk standard-afvigelse, historisk value-at-risk og historisk expected shortfall, med reduktioner på op til 99% af beregningstiden. Opgaven vil både udlede teorien bag og gennemføre en empirisk efterprøvning af approximationernes
validitet.
Herudover vil opgaven give en introduktion til principal-komponent analyse
uden den traditionelle brug af Lagrange multipliers. Derimod tager vi udgangspunkt i et centralt resultat fra lineær algebra, den såkaldte spektralsætning.2
Alle relevante egenskaber ved principal-aktiverne udledes fra denne læresæt2
Spektralsætningen for n-dimensionelle vektorrum følger af egenskaber ved determinanter og n’te-grads polynomier. Et kortfattet bevis kan findes her: http://tinyurl.com/ljvvypq
8
ning med relativt få matematiske forudsætninger. Denne fremgangsmåde er
valgt istedet for Lagrange multipliers, dels fordi bevisførelsen efter min mening er lettere og mere elegant, dels for at tilbyde et alternativ til traditionelle
lærebøger i finansiering eller principal komponent-analyser. Hvis læseren ønsker at se en traditionel fremstilling via Lagrange multipliers henvises til [1],
afsnit 1.1.
For yderligere at underbygge de approximationer der gøres, inddrages udvalgte resultater fra random matrix-teori. Ved hjælp af den såkaldte MarcenkoPastur fordeling argumenteres der for, hvor mange principal-aktiver der har
statistisk signifikans.
Slutteligt vil opgaven i forbindelse med forecasting introducere nogle nye værktøjer til analyse af markedskorrektioner baseret på principal-aktiverne og afledte begreber. Vi vil argumentere for, at principal-aktiverne og relaterede
teknikker giver en god forståelse for markedsdynamikkerne. Særligt vil det
blive forklaret hvorledes korrektioner i markedet kan afkodes forholdsvis klart,
hvilket i sidste ende gør det muligt at lave bedre modeller for forecast af risiko.
1.3 Opgavens disposition
• Den nødvendige og tilstrækkelige matematiske baggrund for opgaven
gennemgås i afsnit 2.
• Markedet og kildedata beskrives i afsnit 3. Dvs. der redegøres for hvilket
marked vi befinder os på, hvilke datasæt der arbejdes med, hvor data
hentes fra og hvordan det er blevet bearbejdet.
• Afsnit 4 giver en introduktion til principal-komponent analysen med
en udledning af relevante resultater. Samtidig introduceres principalaktiver som begreb.
• Afsnit 5 formaliserer idéen om effektive beregningsmetoder. Herunder
gives en simpel måde at måle hvor stor reduktion i beregningstid en
given approximation giver.
• I afsnit 6 udledes en effektiv approximation af historisk varians/std.afvigelse
med udgangspunkt i principal-aktiverne. Herunder vises det at man kan
opnå en reduktion i beregningstiden af historisk varians/std.afvigelse på
90-99%.
• Value-at-risk og expected shortfall defineres som risikomål i afsnit 7.
Samtidig beskrives hvorledes de kan bestemmes historisk ud fra en given
tidsserie.
9
• I afsnit 8 udledes en effektiv approximation af historisk value-at-risk og
expected shortfall. Igen vises det at beregningstiden kan reduceres med
90-99%.
• I afsnit 9 gentages øvelsen fra afsnit 8, nu blot for expected shortfall.
• Afsnit 10 inddrager nogle centrale resultater fra random matrix theory
til bestemmelse af signifikante og ikke-signifikante principal-aktiver.
• Afsnit 11 vil med udgangspunkt i nogle modeller fra Danske Capital
introducere forecasting som emne og forklare hvorledes principal-aktiver
kan anvendes indenfor dette felt.
• Afsnit 12 vil opridse de vigtigste konklusioner mens afsnit og 13 giver
en yderligere perspektivering af principal-aktiver og deres anvendelsesmuligheder.
Der er til denne opgave anvendt en række artikler, som findes på internettet. For at gøre det nemt for læseren kan de hentes samlet i denne
zip-fil:
http://nikolaschou.dk/principalaktiver/artikler.zip
1.4 Tak til
Tak til Kristian Sørensen, CBS, for omhyggeligt vejlederskab, til Peter Dalgaard, CBS, for at give vejledning vedr. statistisk teori, til Rasmus Majborn
og Jacob Hannover fra Danske Capital for at stille op til interview og udlåne
materialer, til Erik Gadeberg og Anders Haaning fra Jyske Bank for at perspektivere emnet og til Scott Ehlers og Else Braathen fra SimCorp for at stille
op til et interview tidligt i opgavens forløb.
2 Matematisk baggrund
Til denne opgave anvendes følgende notationer, konventioner og relevante regneregler indenfor matrixregning og statistik.
• Vektorer angives med små bogstaver i fed skrift, fx. w, hvor elementerne
i vektoren angives w1 , w2 , . . . , wn .
• Vektorer kan indekseres hvis der er m af slagsen, fx w1 , w2 , . . . wm . I
dette tilfælde angives elementerne af hver enkelt vektor med et ekstra
index, fx w1 = (w11 , w12 , . . . , w1n )
• Matricer angives med store bogstaver i fed skrift, fx. C, hvor de enkelte
elementer i C angives som Cij .
10
• Matricer og vektorer kan som bekendt transponeres og dette angives
med et 0-symbol, dvs.
a b
A= c d
a
⇐⇒ A0 = b
c
d
og

w=
w1 w2

w1
 w2 

. . . wn ⇐⇒ w0 = 
 ... 
wn
• Vektorer er som udgangspunkt rækkevektorer. Ved at transponere en
vektor w får man en søjlevektor w0.
• Matrix-transponering opfylder følgende vigtige regneregler: (A0 )0 = A
og (AB)0 = B 0 A0
• Matrix-multiplikation - herunder multiplikation mellem vektorer og matricer - er associativ, dvs. A(BC) = (AB)C. Det understreges at matrixmultiplikation ikke er kommutativ, dvs. AB er generelt set ikke det
samme som BA.
• Sporet af en matrix (på engelsk trace) defineres som summen af diagonalelementerne:
X
Tr(A) =
Aii
i
˙ herunder at Tr(AB) =
• Der gælder forskellige praktiske regneregler for Tr(),
Tr(BA).
• For en vektor w betegner diag(w) den matrix som har w1 , . . . , wn langs
diagonalen og 0 for resten. For en matrix C betegner diag(C) den vektor
som består af diagonalelementerne (C11 , . . . , Cnn ). Man kan sige at diag()˙
afbilder frem og tilbage mellem vektorer og matricer.
• I n defineres som enhedsmatricen i Rn , dvs. I n = diag(1, 1, . . . , 1).
• Stokastiske variable angives med ’krøllede’ bogstaver, fx A, B, C, P, Q
osv. Flere stokastiske variable indekseres som A1 , . . . , An og dette kan
knyttes sammen i en vektor angivet med en overstregning, fx A =
(A1 , . . . , An ).
11
• For en stokastisk variabel A og en fraktil α mellem 0 og 1 gælder det,
at E(A) og µA angiver middelværdien„ Var(A) angiver variansen, σ(A)
angiver std.afvigelsen (spredningen), ESFα (A) angiver expected shortfall
ved α og VaRα (A) angiver value-at-risk ved α. Bemærk at der gives en
detaljeret introduktion og definition af value-at-risk og expected shortfall
i afsnit 7.
• I klassisk vektorregning definerer man skalar-produktet mellem a og b
(også kaldet det indre produkt) som summen af produktet af elementerne. I denne opgave anvendes udelukkende matrix-multiplikation for at
holde en simpel notation, dvs. hvis vi ønsker at finde skalar-produktet
mellem to række-vektorer gøres det via matrix-operationen: ab0 som
alternativt skrives a · b0 .
• Hvis man multiplicerer a med b0 får man som nævnt skalar-produktet.
Hvis man derimod multiplicerer b0 med a får man en n × n matrix,
hvilkes ses her:
( a
 
 1
b 1 b 1 a1

 b 2 a1
b
2
 .
b0 a ≡ b0 · a = . 
 .. 
 ..
bn
b n a1
a2
b1 a2
b2 a2
..
.
...
...
...
...
an )

b1 an
b2 an 
.. 
. 
b n a2
...
b n an
• Længden af en vektor defineres som
v
!
u n
u X
a2i
kak = t
i=1
• Vinklen θ mellem to vektorer a og b findes fra formlen:
cos(θ) = kakkbka · b0
• En enhedsvektor er en vektor som har længden 1.
• De enhedsvektorer som

1
 0


i1 =  0
 ..
 .
0
peger langs akserne betegnes

 

0
0

 1 
 0

 


 0 
 .
 , i2 =   , . . . , in =  ..

 .. 

 . 
 0

0
1







• To vektorer a og b er ortogonale eller vinkelrette hvis a · b0 = 0 hvilket
let ses ved θ = cos−1 (0) = π/2 = 90◦ .
12
3 Markedet
Vi betragter et marked bestående af n aktier og lader A1 , . . . , An betegne
stokastiske variable, som angiver den daglige relative prisændring for de n
aktier.
Vi antager at den gennemsnitlige prisændring henover tid (den langsigtede
vækst) er meget mindre end de daglige udsving eller vi kan fratrække den
langsigtede vækst fra de daglige udsving, dvs. vi antager E(Ai ) ≡ µAi = 0 for
alle i.
I dette marked betragter vi en portefølje P karakteriseret ved en vægtet sammensætning af de n aktier, hvor vægtene betegnes w = (w1 , . . . , wn ). Dvs. vi
kan tænke på P som en stokastisk variabel defineret som følger:
P=
n
X
0
wi Ai = wA hvor
X
wi = 1
(1)
i
i=1
For en nemheds skyld forestiller vi os, at alle aktier kan
Phandles i enheder, der
hver koster 1kr hvormed også P koster 1kr, eftersom i wi = 1.
Det bemærkes at (1) implicit antager, at porteføljen løbende rebalanceres.
Hvis fx den absolutte pris på Ai stiger mens alle øvrige er uændrede, da vil
man være nødt til at sælge ud af Ai og købe op i de øvrige for at fastholde en
given sammensætning af vægte.
3.1 Kildedata
Som datakilde er anvendt Yahoo Finance, et gratis web-API udstillet af Yahoo.
Data hentes og analyseres vha. Matlab.
I princippet er det simpelt at hente data fra Matlab via funktionen buildUniverse()3 . Problemet er blot at de simple metoder ikke virker idet at priserne
ikke er korrigeret i forhold til dividender og aktiesplit. Det betyder at man reelt
ikke kan bruge disse data til at finde daglige afkast. Istedet er man nødt til at
bruge funktionen fetch(), som giver mulighed for at hente såkaldte ’Adjusted
Close’ priser.
Næste udfordring er at finde de sæt af aktiver, man ønsker at analysere. På
den ene side vil man gerne dække så mange aktiver som muligt. Samtidig vil
man gerne dække så lang en periode som muligt. Det leder en til spørgsmålet
om, hvorledes man kombinerer lange tidsserier med korte, dvs. hvorledes laves
analysen når nogle aktiver har eksisteret siden 60’erne, andre først er kommet
til senere. Til denne opgave er valgt følgende konventioner for en analyse, der
3
Dokumentation af denne funktion kan læses her:
http://www.mathworks.se/help/datafeed/yahoo.builduniverse.html?refresh=true
13
løber over en given periode: (i) Når et aktiv introduceres på børsen med en
pris P på en dato D efter periodens start, vil prisen i intervallet [start, D] blive
sat til P. (ii) Når et aktiv fjernes fra børsen sker det samme, dvs. den sidste
pris får lov at fortsætte uændret.
Sidste udfordring bunder i, at forskellige aktiver handles på forskellige handelsdage. Det kan enten skyldes at aktiverne handles på forskellige børser,
eller det kan skyldes at Yahoo har ufuldstændige data - hvilket desværre er et
faktum4 . Det gør det en smule kompliceret at opstille en samlet tidsserie, da
det kræver en form for sammenfletning. Tænk blot på en tidsserie A som har
priser for 2, 3 og 6. januar (i et givet år) og en anden tidsserie B som har priser
for 2, 4, og 5. januar. For denne analyse er det valgt at tage udgangspunkt i
de handelsdage, der er registreret for IBM. Alle andre tidsserier er flettet ind
således at priserne listes på IBM’s handelsdage vha. en slags best-fit algoritme.
Koden kan ses i appendix og er markeret med teksten ’MERGING TRADING
DAYS’.
3.2 Datasæt og perioder
Alle empiriske undersøgelser er baseret på et eller flere af de datasæt der
vises i Tabel 1. For alle tre datasæt har det været nødvendigt at rense ud i
de anvendte aktiver af forskellige årsager. Den primære årsag har været, at
Yahoo Finance ikke kunne levere valide data for en del af aktiverne. Således
var det for datasættet NYSE77 nødvendigt at fjerne ca. 177 aktiver for at få
et rent datasæt. Metoden til at rense ud i datasættene har været, at finde
de aktiver med særlig usædvanlige spring i prisudviklingen (fx. en stigning
på 5000% på en dag). Dernæst har det været en manuel opgave at gå dem
igennem og be- eller afkræfte, hvorvidt de leverede data er korrekte eller ej.
Vurderingen af om de er korrekte er taget ved at sammenligne priskurven med
den officielle priskurve fra de grafer man kan finde online via Yahoo Finance
web-grænsefladen.
4 Principal komponent analyse
4.1 Introduktion
Principal komponent-analyser (forkortet PCA) som metode blev opfundet af
Karl Pearson i 1901 og har siden fundet anvendelser indenfor mange viden4
For en diskussion af fejl og mangler i Yahoo Finance data se her:
http://quant.stackexchange.com/questions/942/any-known-bugs-with-yahoo-financeadjusted-close-data
og her:
http://quant.stackexchange.com/questions/7216/daily-returns-using-adjusted-close
14
Tabel 1: Oversigt over datasæt anvendt til de empiriske undersøgelser
ID
Beskrivelse
SP2000 Indeholder de aktier fra S&P500
indekset som har været i markedet siden år 2000
SP1984 Indeholder de aktier fra S&P500
indekset som har været i markedet siden år 1984
NYSE77 Indeholder de aktier fra New York
Stock exchange som har været i
markedet siden år 1977
# aktiver
n
463
Periode
2000-2014
#dage
T
3521
98
1984-2014
7565
1594
1977-2014
13090
skabelige discipliner, hvor metoden har fået forskellige navne, fx egenværdi
dekomposition indenfor lineær algebra, spektralanalyse indenfor akustik og fysik med mere, jf. [14].
For at få den rigtige intuition omkring PCA indenfor rammerne af denne opgave, kan det være en god ide at starte med at diskutere markedsindekser [12].
Markedsindekser dannes som bekendt ved at lave en fiktiv portefølje bestående af bestemte aktier med nogle bestemte vægte, hvormed man løbende kan
udregne en indeks-pris ud fra vægtene og de underliggende aktiepriser. Hermed får man en simpel én-dimensionel størrelse som er nemmere at forholde
sig til end markedet som helhed.
Der findes en lang række forskellige markedsindekser med forskellige kriterier
for udvælgelse af aktier og forskellige metoder til bestemmelse af vægtene.
Nogle indekser forsøger at samle aktier fra alle de største virksomheder på
tværs af hele markedet, globalt eller nationalt. Fx samler S&P Global 100indekset 100 multinationale aktier. Andre indekser samler aktier indenfor et
bestemt land, en bestemt sektor, en bestemt børs osv. osv.
Med hensyn til valg af vægte er der primært to metoder i anvendelse. For
prisvægtede indekser vælges vægten ud fra prisen. Hvis en aktie er dobbelt
så dyr som en anden aktie, vejer den også dobbelt så meget i indekset. For
kapitalvægtede indekser er det virksomhedens samlede markedsværdi, der bestemmer vægten. Hvis én aktie har dobbelt så stor markedsværdi som en anden
aktie, da er vægten også dobbelt så stor [14].
Markedsindekser bruges til mange forskellige slags formål, men nok primært
til markedsanalyser. Hvis et indeks stiger ses det som et udtryk for en generel
stigning i markedet. Hvis et indeks har kraftige udsving ses det som udtryk
for, at markedet generelt har høj volatilitet. Hvis udviklingsmønstrene i indekset ændrer sig, ses det måske som et udtryk for et regimeskifte i markedet.
Indekserne anses altså for at være gode aggregerede størrelser, hvorudfra vi
15
kan aflæse og forstå markedet.
Man kan i denne sammenhæng undre sig lidt over den vilkårlighed der er i
konstruktionen af indekserne. Og det kan virke uoverskueligt eller overflødigt
at der er så mange indekser at vælge imellem. Principal komponent-analysen
kan motiveres ud fra et ønske om at frembringe et mindre antal indekser som
kan bygges på et teoretisk grundlag, både matematisk og finansielt. Med dette
som indgangsbøn udleder vi nu principal komponent analysens grundsætninger og en række afledte værktøjer.
4.2 Matematisk udledning
Vi starter med at minde om at vi betragter et marked med n aktier betegnet
A1 , . . . , An og herudfra kan konstrueres porteføljer som en vægtet kombination
af aktierne, hvor vægtene betegnes med en vektor w. Vi minder også om at
vi i vores model tænker på både aktier og porteføljer som stokastiske variable
der angiver det daglige relative afkast, og at en portefølje kan skrives som
0
matrixprodukt: P = wA .
Vi starter nu med at udregne variansen for P.
0
0 0
2
Var(P) = E((P) ) = E wA wA
0
0
= E(wA Aw0 ) = wE(A A)w0
Her er det udnyttet at middelværdien E(·) som funktion er lineær. Nu indfører
man kovarians-matricen C defineret ved:
0
C ≡ Cov(A) ≡ E(A A) eller alternativt Cij = E(Ai Aj ) for alle i, j
og vi kan opsummere følgende vigtige sammenhæng:
Var(P) = wCw0 hvor Cij = E(Ai Aj ) for alle i, j
(2)
Det ses at kovarians-matricen er symmetrisk, dvs. Cij = Cji . Vi vil nu udnytte
det såkaldte spektral teorem, der er en hovedsætning indenfor lineær algebra og
matrixregning.5 Spektral-teoremet siger, at enhver symmetrisk matrix C
kan diagonaliseres, dvs. vi kan omskrive C som et produkt af tre matricer
som følger:
5
Spektral teoremet kan også formuleres mere generelt og indenfor mere avancerede grene
af matematikken, men til denne opgave er vi kun interesseret i en mere snæver anvendelse.
16
C = QΛQ−1
(3)
hvor Q er en ortonormal matrix (se nedenfor) og hvor Λ er en diagonalmatrix

λ1 0 0 0
 0 λ2 0 0

Λ=
 0 0 ... 0
0 0 0 λn





med faldende værdier langs diagonalen. Dvs. λ1 er den største værdi, λ2 er den
næststørste værdi osv. Der gælder endvidere at denne opsplitning eller dekomposition er entydig. Diagonalværdierne i Λ kaldes traditionelt for egenværdier
mens søjlevektorerne i Q kaldes for egenvektorer eller principal komponenter.
6
NB: Bemærk at ’egenværdi’ og ’egenvektor’ på engelsk kaldes for ’eigenvalue’
og ’eigenvector’ respektivt. Da visse figurer i denne opgave har engelske
figur-tekster, vil disse betegnelser indimellem blive brugt.
En ortonormal matrix består pr. definition af n enhedsvektorer, der alle er
ortogonale (dvs. vinkelrette) på hinanden, jævnfør afsnit 2.
Lad os i det følgende bruge lidt tid på at opbygge lidt intuition omkring C,
Q og Λ og deres indbyrdes sammenhænge.
Det er praktisk at benævne søjlerne i Q med q01 , . . . , q0n , dvs. vi kan skrive
således:
 


   
 


 





0
0
0
≡
q1
q2
qn
...
Q≡

 





 
q11 
 
 q21
..
.
.   ..
q   q
1n
2n





 qn1
..
...
.



 q
nn
hvor de krøllede parenteser kun er medtaget for at markere søjlestrukturen.
At Q er ortonormal betyder per definition at:
qi q0j
=
hvis i 6= j
hvis i = j
0
1
6
Dette udsagn er bevidst forsimplet og bygger på en række antagelser, nemlig at
det(C) 6= 0 og at alle diagonalværdierne er forskellige. For typiske finansielle tidsserier
med flere målepunkter end aktiver vil disse antagelser dog holde.
17
 






hvilket alternativt kan skrives:
QQ0 = Q0 Q = I n hvor I n er enhedsmatricen
Bemærk især fra disse ligninger at transponeringen af Q er sin egen inverse,
dvs.
Q−1 = Q0
(4)
Herfra konkluderes at Q er længdebevarende, hvilket demonstreres af følgende
udregning:
kQa0 k2 = (Qa0 )0 (Qa0 ) = a(Q0 Q)a0 = aI n a0 = aa0 = kak2
Ydermere kan det ses at Q er vinkelbevarende, dvs. hvis θ1 betegner vinklen
mellem a og b og θ2 betegner vinklen mellem a og b efter multiplikation med
C, da finder man:
cos(θ2 ) =
aQ0 Qb0
ab0
(Qa0 )0 Qb0
=
=
= cos(θ1 )
kQakkQbk
kakkbk
kakkbk
En matrix der både er længdebevarende og vinkelbevarende ved multiplikation, kender man også som en rotation. Samtidig ser man at Λ ved multiplikation virker som ren skalering. Vi kan altså betragte produktet QΛQ0 som
en samlet operation der først laver en rotation Q0 , dernæst en skalering Λ og
slutteligt en modsatrettet rotation Q.
Hernæst kan vi indse at følgende gælder:
Cq0i = QΛQ0 q0i = QΛii = Qλi i1 = λi q0i
Med andre ord, C virker på qi som en skalering med skaleringsfaktor λi .
Generelt set vil en matrix udvirke både skalering og rotation når den ganges
på en vektor, men disse særlige vektorer udmærker sig altså ved kun at blive
skaleret og ikke roteret af C. I den forstand kan man sige, at der er et særligt
tilhørsforhold mellem C og qi , hvilket er årsagen til at man kalder q1 , . . . , qn
for egenvektorer for C og de tilhørende λ’er for egenværdier. Hvis vi tænker på
vektorerne som komponenter ledes man til betegnelsen principal komponenter,
heraf forkortelsen PCA for principal komponent analyse.
Den første egenvektor q1 og den første egenværdi λ1 har en endnu mere speciel egenskab. Der gælder nemlig at q1 angiver den enhedsvektor, der giver
maksimal varians efter formel (2). Det kan ses ved at betragte en vilkårlig
enhedsvektor e og finde variansen for den tilhørende portefølje:
18
Figur 2: Illustrerer enhedsvektorerne for n = 3 og ideen om at én bestemt
vektor markeret med tallet 1 udmærker sig ved at maksimere variansen.
Var(Pe ) = eCe0 = eQΛQ0 e0 = (eQ)Λ(eQ)0 = f Λf 0 =
X
fi2 λi
i
≤ λ1
X
fi2 = λ1 kf k2 = λ1 = Var(Pq1 )
i
I udregningen har vi defineret f ≡ eQ og udnyttet at Q er længdebevarende,
dvs. kf k = 1 fordi e har længden 1.
Vi har altså vist at uanset hvordan vi vælger enhedsvektoren e vil det gælde
at Var(Pe ) ≤ Var(Pq1 ). Ideen er illustreret på figur 2.
Ved at anvende en lignende teknik kan man også indse, at blandt alle enhedsvektorer som er vinkelret på q1 , da er q2 den som giver størst varians og mere
generelt, blandt alle enhedsvektorer som er vinkelrette på q1 , q2 , . . . , qk , da er
qk+1 den som giver størst varians.
Lad nu Qi betegne den portefølje som har qi som vægte, dvs.
Qi =
n
X
0
qij Aj eller Qi = qi · A eller Q = Q0 · A
j=1
Da finder man variansen:
Var(Qi ) = qi Cq0i = qi (λi qi0 ) = λi
og kovariansen for i 6= j:
0
Cov(Qi , Qj ) = E(Qi · Qj ) = E qi A Aq0j
0 = qi E A A q0j = qi Cq0j = qi λj q0j = λj (qi q0j ) = 0
19
(5)
(6)
Det vil altså sige at Q1 , . . . , Qn udgør n porteføljer som er gensidigt ukorrelerede og som har variansen givet ved egenværdierne λ1 , . . . , λn .
Herudover gælder det at enhver portefølje P med vægte w entydigt kan skrives
som en linearkombination af Q1 , . . . , Qn som det vises her:
0
0
0
P = wA = (wQ) Q A
0
=β·Q =
n
X
βi Qi hvor β ≡ w · Q
(7)
i=1
hvilket også kan skrives som:
P = β1 Q1 + · · · + βn Qn hvor βi ≡ w · q0i
I denne ligning fortolkes βi som projektionen af w på den i’te egenvektor qi .
Vi ser altså at Q1 , . . . , Qn udspænder markedet og ved at operere med βi ’erne
istedet for wi ’erne får vi åbenbart en alternativ måde at repræsentere og analysere porteføljer i markedet. Fx kan vi finde variansen således:
Var(P) = Var(β1 Q1 + · · · + βn Qn ) = β12 Var(Q1 ) + · · · + βn2 Var(Qn )
Her er det udnyttet at alle krydsledene går ud eftersom Q1 , . . . , Qn er ukorrelerede. Med andre ord:
σP2 = Var(P) = β12 λ1 + · · · + βn2 λn hvor βi ≡ w · q0i
(8)
Det er her udnyttet at Qi ’erne er ukorrelerede hvorved alle ’krydsleddene’ udgår. Samtidig er det udnyttet at variansen af Qi er λi som vist ovenfor. Den
vigtige observation er her, at når en portefølje udtrykkes som en vægtet
sum af de principale komponenter (eller egenvektorerne), da findes
variansen som den vægtede sum af variansen af principal komponenterne. Dette er praktisk og elegant. Vi skal simpelthen tænke på markedet
som om de primære aktiver er Q1 , . . . , Qn og enhver portefølje (herunder de
oprindelige enkelte aktier i markedet) udtrykkes som linearkombinationer af
Qi ’erne. Man kan også sige at Qi ’erne udgør en ny basis for markedet. Denne
ide er illustreret på figur 3.
4.3 Udregning af efficient rand vha. principal-aktiver
Som en anvendelse af de udledte formler for principal-aktiverne vil vi nu se,
hvorledes punkter på den efficiente rand kan udtrykkes ved hjælp af principal20
Figur 3: Illustrerer ideen om at finde en ny basis, som ’passer’ bedre
til det givne problemfelt, her illustreret som en række målepunkter i 2
dimensioner. I den nye basis bestående af y1 og y2 ses målepunkterne at
have en variation der følger akserne. I den gamle basis bestående af x1
og x2 ses målepunkter at ligge på skrå.
aktiver. Vi tager udgangspunkt i den velkendte formel for udledning af markedsporteføljen på den efficiente rand jævnfør [10] ligning (3.20):
0
w
ˆ market
= C −1 (µ0A − r0 )
hvor µA = (µA1 , . . . , µAn ) angiver det gennemsnitlige afkast af aktiverne
A1 , . . . , An , r angiver den risikofri rente som en konstant vektor (dvs. en vektor med samme værdi r på alle pladser) og w
ˆ market angiver den unormaliserede
markedsportefølje. Dvs. den reelle markedsportefølje findes ved normalisering:
0
0
wmarket
=w
ˆ market
1
|w
ˆ market |
hvor | · | betegner summen af elementerne
Ved at bruge (3) og (4) kan vi nu omskrive denne formel på følgende måde:
−1
0
w
ˆ market
= (QΛQ0 )
(µ0A − r0 )
= (Q0 )−1 Λ−1 Q−1 (µ0A − r0 )
= QΛ−1 Q0 (µ0A − r0 )
= QΛ−1 µ0Q − r0Q
hvor vi har indført
µ0Q ≡ Q0 µ0A , dvs. forventet afkast af Q1 , . . . , Qn


|q1 |
 |q2 | 


r0Q ≡ r  ..  fortolket som en normaliseret risikofri rente
 . 
|qn |
21
Ved at gange med Q0 fra venstre på begge sider af lighedstegnet og udnytte
definitionen af β fra (7) når man til konklusionen:
0
βˆmarket = Λ−1 µ0Q − r0Q eller alternativt
βˆmarket,i = λ−1
i (µQi − r|qi |) hvor
0
1
β 0market = βˆmarket
|βˆmarket |
(9)
Vi ser altså, at porteføljer på den efficiente rand kan konstrueres ud fra
principal-aktiverne hvor vægten βi for det i’te principal-aktiv Qi , er proportionel med det forventede afkast af Qi fratrukket den risikofri rente gange prisen
|qi | på Qi og dernæst divideret med variansen λi af Qi .
4.4 Empiriske resultater
For at få en første validering af PCA analysen vil vi finde de første tre
principal-komponenter Q1 , Q2 , Q3 for markedsdata hørende til datasættes SP84,
jævnfør afsnit 3.2. Dernæst vil vi finde prisudviklingen for de tre principalkomponenter. Det gøres ved dag for dag at finde prisen på det indeks som har
hhv. q1 , q2 og q3 som vægte. Slutteligt sammenlignes dette med prisudviklingen i S&P500-indekset. Resultatet ses på Figur 4. Det bemærkes at det første
principal-aktiv overordnet set følger markedets udvikling. Det 2. principalaktiv følger nogenlunde markedets svingninger, dog mere afdæmpet. Det 3.
principal-aktiv viser klare tegn på modsatrettede bevægelser i forhold til markedet. Fx ses en kraftig nedtur omkring år 2000 efterfulgt af en kraftig optur,
hvilket er den modsatte bevægelse i forhold til markedet.
Det skal her understreges, at S&P500 løbende justeres mht. aktiver og vægte,
mens principal-aktiverne dannes som faste indekser for hele perioden. Endvidere gælder det at SP84-datasættet kun indeholder virksomheder som har
været på børsen siden 1984, og altså ikke det fulde grundlag for S&P500indekset. Der er derfor ingen grund til at forvente, at vi skulle være i stand
til at matche S&P500 fuldstændig.
Til yderligere at underbygge fortolkningen af de første par principal-aktiver
viser Figur 5 en opgørelse for SP2000 datasættet, der viser hvilke positioner,
de første 3 egenaktiver har i forskellige sektorer.
22
Figur 4: Øverst vises udviklingen i S&P indekset holdt op imod udviklingen i de første tre principal-komponenter set hver for sig. I midten
og nederst vises en vægtet sum af de tre principal-aktiver holdt op imod
S&P500. Det ses at de første tre principal-aktiver i kombination i rimelig høj grad kan forklare markedsudviklingen pånår perioden omkring
dotcom-boblen i år 2000. Vægtene er dannet vha. formlerne for efficient
rand (9).
5 Effektive beregningsmetoder
Vi vil nu kigge nærmere på hvorledes principal-komponenterne kan bruges
til at lave effektive approximationer og beregningsmetoder af historisk varians for porteføljer. Med ’effektiv’ menes en reduktion i de påkrævede antal
beregningsoperationer med en eller flere størrelsesordener, dvs. vi ønsker at
reducere beregningstiden med 90%-99%.7
For at kunne diskutere effektivitet i beregningsmetoder har vi brug for lidt
simple konventioner. Vi antager metoden implementeres i et givet programmeringssprog, der afvikles på en computer/server, hvor de basale aritmetiske
operationer (multiplikation, addition osv. ) tager lige lang tid. Vi ser bort fra
detaljer omkring repræsentation af tallene (floating points vs. fixed decimals
osv.), nøjagtighed ved udregning (altså om der accepteres afrundingsfejl) osv.
Det eneste vi er interesserede i er antallet af basale aritmetiske operationer.
Vi antager også at n >> 1, hvilket medfører at vi automatisk laver afrundinger
såsom n + 1 ≈ n og n − 1 ≈ n.
Som eksempel kan vi betragte en projektion (vektorprodukt):
ab0 = a1 b1 + a2 b2 + · · · + an bn
Det ses umiddelbart at denne udregning kræver n multiplikationer efterfulgt
af n − 1 additioner, dvs. ialt ca. 2n operationer.
6 Approximation af varians
Vi betragter igen en portefølje P med tilhørende vægte w. Vi forestiller os også, at der foreligger en tidsserie med T målinger af relative prisændringer for de
underliggende aktier, således at kovariansmatricen C kan bestemmes, og herudfra er principal-komponenterne q1 , . . . , qn og egenværdierne λ1 , . . . , λn fundet. Slutteligt er β-koefficienterne for P fundet ved at projicere vægt-vektoren
på principal-komponenterne: βi = w · q0i .
Som det fremgår af (8) er det let at finde variancen for en portefølje, når man
først har fundet principal-komponenterne, egenværdierne og beta-koefficienterne.
Dog gælder det, at udover de fortolkningsmæssige og analytiske fordele det
kan give at arbejde med principal-komponenter, vil denne fremgangsmåde ikke
i sig selv give en væsentlig beregningsmæssig besparelse af følgende årsager:
7
Indenfor datalogien ville man formulere dette som et ønske om, at reducere den beregningsmæssige kompleksitet, fx at gå fra O(n2 ) til O(n) i køretid. Denne opgave forsøger
dog at holde fokus på indsigten i PCA og de finansielle fortolkninger heraf og derfor bliver
spørgsmålet om reduktion i beregningsmæssig kompleksitet behandlet en smule forsimplet.
24
Figur 5: Øverst vises en opgørelse over positionen af de tre første
principal-aktiver indenfor forskellige sektorer opgjort for SP2000 datasættet. Positionen er opgjort ved at tælle hvor mange aktier indenfor
hver sektor principal-aktivet har hhv. en kort, en lang eller ingen
position i. Eksempelvis ses det at principal-aktiv nr. 2 er lang i 54% af
alle Consumer Services aktier. Det ses tydeligt at den 1. principal-aktiv
stort set er lig med markedet som helhed, i den forstand at det er bygget
op af en lang position af alle aktiver i markedet. Tilsvarende ses at 2.
principal aktiv er lang i cykliske aktier og kort i defensive aktier (fx
Consumer Goods og Health Care). Dette aktiv vil altså udvise særlig
stor volatilitet i hhv. højkonjunktur og lavkunjunktur.
Nederst vises et udklip fra det bagvedliggende datamateriale. Som
eksempel ses at det 2. principal-aktiv (dvs. q2 fra formlerne i afsnit
4) har en vægt på -0.065758 - dvs. en kort position - i Allstate Corp.
indenfor industrien Financials. Tilsvarende har det 3. principal-aktiv
en position på 0.00013285 i Alcoa Inc. hvilket fortolkes som ’ingen
position’. Der er anvendt den konvention at hvis en vægt ligger i
intervallet [−0.005, 0.005], da fortolkes det som hverken kort eller lang,
også kaldet ’ingen’ position.
Figur 6: Viser et tænkt men illustrativt eksempel på varianserne (dvs.
egenværdierne) af principal-aktiverne i et marked med 20 aktiver. Fx har
principal-aktiv 1 en varians på 20, principal-aktiv 2 har en varians på
10 osv. Halen af principal-aktiver har en meget lav varians omkring 1
og desuden er variansen i halen næsten konstant set imod størrelsen af
de første egenværdier.
• For at finde principal-komponenterne skal PCA-analysen først gennemføres, dvs. givet C skal man finde Q og Λ så ligning (3) er opfyldt.
Denne analyse er i sig selv krævende og baserer sig på komplekse og
beregningstunge matematiske operationer, jævnfør [5] afsnit 11. Naturligvis findes der masser af standardiserede software-pakker, som udfører
PCA-analysen, men det ændrer ikke ved at det generelt set er en beregningskrævende operation der har en løbetid, der skalerer med n2 [11].
• For at finde βi ’erne skal der laves n projektioner af vektorer med hver n
elementer i. Det vil i sig selv kræve ca. 2n2 operationer.
• Metoden forudsætter at C skal bestemmes. Ydermere gælder det at en
nøjagtig bestemmelse af alle egenværdier og principal-komponenter kræver en nøjagtig bestemmelse af C. Hvilket igen betyder at der skal anvendes en forholdsvis lang tidsserie. Hvis tidsserien indeholder T punkter
kræver udregningen af kovariansmatricen ca. T · n2 beregninger.
For at få gavn af PCA-analysen til at lave effektive beregningsmetoder af
varians m.m. er det nødvendigt at kigge nærmere på de egenværdier, som
typisk findes for finansielle tidsserier.
I praksis vil man ofte finde at der er et kraftigt fald i egenværdierne afløst af
en flad hale, et typisk billede er illustreret på Figur 6. Dette giver mulighed
for en effektiv approximation eftersom værdierne i halen kan udskiftes med en
gennemsnitsværdi.
26
Lad os anvende ideen til at regne videre på formel (8)
σ(P)2 = Var(P) = β12 λ1 + β22 λ2 + · · · + βn2 λn
2
≈ β12 λ1 + · · · + βk2 λk + λtail (βk+1
+ · · · + βn2 )
2
= β12 λ1 + · · · + βk2 λk + λtail βtail
hvor k markerer punktet lige inden egenværdi-halen starter (på figuren er k
ca. 3), λtail er den gennemsnitlige egenværdi i "halen"(på figuren ca. 1) og vi
2
2
har indført βtail
≡ βk+1
+ · · · + βn2 . Vi antager at k << n.
Hernæst skal man indse at:
2
βtail
=
n
X
βi2
i=1
−
k
X
βj2
2
= kβk −
j=1
= kw · Qk2 −
k
X
βj2
j=1
k
X
βj2 = kwk2 −
k
X
j=1
βj2
j=1
hvor det er udnytttet at Q er længde-bevarende. Slutteligt skal man se at:
(n − k) · λtail =
n
X
λi =
n
X
λi −
k
X
i=1
i=k+1
= Tr(Λ) −
k
X
λj
j=1
λj = Tr(C) −
j=1
k
X
λj
j=1
hvor det er udnyttet at Tr(Λ) = Tr(Q0 CQ) = Tr(CQQ0 ) = Tr(C).
P
Hvis vi til slut bemærker at Tr(C) = i σ 2 (Ai ) kan vi opsummere følgende
centrale resultat:
σ 2 (P) = Var(P) ≈ β12 λ1 + · · · + βk2 λk
1
+
n−k
X
σ 2 (Ai ) −
i
hvor βi ≡ w ·
k
X
j=1
!
λj
kwk2 −
k
X
!
βj2
j=1
q0i
(10)
På trods af at formlen muligvis ser lidt kompliceret ud, indeholder den væsentlige beregningsmæssig reduktioner. Bemærk især følgende:
27
• Formlen involverer kun de første k egenvektorer og egenværdier.8 De
fleste egenværdi-algoritmer fungerer iterativt på en måde så egenvektorerne findes i faldende orden.9 Det betyder også, at der opnås en væsentlig beregningsmæssig besparelse, hvis kun de første k egenværdier
og egenvektorer skal findes (husk vi antager k << n).
• Formlen involverer udover de første k egenvektorer og egenværdier kun
vektor-længden af porteføljevægtene (kwk) - som er givet på forhånd og summen af varianserne af de oprindelige aktier i markedet.
• Det kan vises teoretisk og praktisk at de første egenvektorer og egenværdier findes med højere statistisk signifikans end de efterfølgende egenvektorer og egenværdier. Ligeledes kan det vises teoretisk og praktisk at
varianser for en given tidsserie kan bestemmes med en væsentlig højere
statistisk signifikans end kovarianser. Det betyder at man ofte kan reducere antallet af målepunkter i tidsserien og stadig fastholde den ønskede
nøjagtighed i de endelige resultater.
6.1 Bestemmelse af reduktionsfaktor
Lad os nu forsøge at bestemme et kvantitativt bud på, hvilken beregningsmæssig reduktion vi opnår med formel (10). Vi antager at kovarians-matricen
C er fundet.
Først betragter vi den traditionelle fremgangsmåde: Var(P) = wCw0 . Produktet C·w0 koster n2 multiplikationer og n2 additioner, dvs. ialt 2n2 operationer. Dernæst foretages den sidste vektor-multiplikation w · (Cw0 ) som
vi allerede har set koster 2n operationer. Dvs. samlet involverer udregningen
2n2 + 2n ≈ 2n2 operationer, hvor vi antager at n er stor, dvs. n2 >> n.
Dernæst betragter vi formel (10): Vi starter med at antage at de første k egenværdier og egenvektorer er fundet. De k β-værdier involverer hver en vektorprojektion som koster 2n projektioner hver, dvs. ialt 2kn operationer. DernæstP
multipliceres med λ1 , . . . , λk , hvilket er yderligere k operationer. Hernæst
skal i σ 2 (Ai ) findes, hvilket svarer til summen af diagonalen af kovariansmatricen, dvs. ialt n operationer. Summen af de første k egenværdier koster
k operationer. Længden af w koster nP
multiplikationer og n additioner, dvs.
ialt 2n operationer. Slutteligt koster j βj2 k multiplikationer og k additioner, dvs. ialt 2k operationer. Samlet set vil udregningen af variansen ud fra
formlen således koste 2kn + k + n + k + 2n + 2k = 2kn + 4k + 3n ≈ (2k + 3)n
operationer hvor det er antaget at k << n.
Hermed får vi altså en reduktion på (2k+3)n
= k+1.5
, dvs. hvis n er ca. 10 gange
2n2
n
større end k da er reduktionen på ca. 90%. Hvis n er ca. 100 gange større end
8
9
Egenvektorerne er implicit involverede gennem β-koefficienterne eftersom βi = w · q0i .
Hvis to egenværdier ligger tæt kan de dog godt findes i omvendt rækkefølge.
28
k, da er reduktionen på ca. 99%.
6.2 Empiriske resultater
Det skal nu undersøges hvor godt approximationen (10) virker i praksis. Der
er lavet en undersøgelse for de to datasæt, SP2000 og NYSE77 og resultatet
er vist på Figur 7 og Figur 8 respektivt.
Det er vigtigt at forstå at approximationen både skal undersøges mht. forskellige valg af cutoff k og forskellige valg af porteføljer. Det giver i sig selv to
dimensioner i analysen. Dimensionen for valg af k er simpel og en-strenget.
Dimensionen for valg af portefølje er derimod kompleks. Forskellige typer af
porteføljer virker nemlig meget forskelligt på formlen. Eksempelvis finder man
at diversificerede porteføljer hvor mange aktier indgår, egner sig langt bedre
til at blive approximeret end porteføljer som består af et lille antal aktier, fx.
4. Lad os vende tilbage til dette lidt senere i dette afsnit. Først gennemgås
fremgangsmåden i analysen:
• Der udvælges M porteføljer, hvor M er valgt til at være lig n, men det
kunne lige så godt have været et andet antal såsom 500 eller 1000. Se
nedenfor hvordan disse porteføljer er udvalgt.
• For hver af de M porteføljer og for hver cutoff-værdi k = 1, 2, . . . , n
udregnes den approximerede standardafvigelse via formel (10).
• Samtidig udregnes for hver portefølje den historiske - dvs. den sande standardafvigelse.
• Herefter findes for hvert k og hver portefølje den procentvise fejl mellem
den sande standardafvigelse og den approximerede, som herefter plottes
med k ud af x-aksen og den procentvise fejl på y-aksen. Disse plot ses
på Figur 7 for SP2000 og Figur 8 for NYSE77-datasættet. Bemærk at
for hver k-værdi haves et målepunkt for hver af de M porteføljer hvilket
giver anledning til et tykt ’bånd’ af grafer. Tætheden i grafen viser hvor
mange porteføljer, der havde en given approximationsfejl.
NB: Det skal bemærkes at vi forsøger at gennemføre en analyse med nogle
statistiske størrelser, som nemt kan forvirre, fordi vi så at sige forsøger at finde
en standardafvigelse af fejlen på en approximation af en standardafvigelse.
Derfor skal man holde tungen lige i munden.
6.2.1 Historisk std.afv. for en portefølje
Lad os kort redegøre for, hvorledes den historiske std.afv. findes for en konkret
portefølje. Husk på at en portefølje er repræsenteret ved en vektor w med
29
Figur 7: Viser den relative fejl på standardafvigelsen udregnet efter formel (10) som funktion af cutoff-faktor for datasættet SP2000.
Figur 8: Viser den relative fejl på standardafvigelsen udregnet efter formel (10) som funktion af cutoff-faktor for datasættet NYSE77.
vægte, der summer til 1, hvor wi angiver hvor stor en procentdel af porteføljens
værdi, som udgøres af den i’te aktie i markedet.
Husk også på at de grundlæggende markedsdata består af en tidsserie som vi
kan betegne med G (som står for ’gain’). Tidsserien angiver for hver dag det
relative afkast for hver enkelt aktie, og vi tænker på G som en matrix hvor
Gij angiver afkast på tidspunkt i for aktie j.
Nu kan vi projicere afkastene for aktierne i markedet ned på porteføljevægtene
ved at udregne matrixproduktet g0 ≡ G·w0 . Hermed finder man en ny tidsserie
i form af en søjlevektor, som repræsenterer de daglige relative afkast man ville
have haft, hvis man havde haft den pågældende portefølje. Slutteligt finder
man den historiske standardafvigelse på sædvanligvis fra denne tidsserie. Som
√
matrixprodukt ser det således ud: σ = g · g0.
6.2.2 Valg af porteføljer
Når porteføljerne skal vælges til analyse af (10) er det værd at have en overordnet ide om, hvilke typer af porteføljer der er interessante at betragte. Det
viser sig at den vigtigste ’parameter’ i forhold til om porteføljen egner sig til
approximation eller ej, er hvorvidt porteføljen er diversificeret eller ej.
Forklaringen er at diversificerede porteføljer naturligt har en stor vægt på de
første principal-aktiver og samtidig vægte spredt godt ud i halen, mens ikkediversificerede porteføljer kun har lille vægt på de første principal-aktiver og
til gengæld har stor vægt på enkelte principal-aktiver i halen. Det betyder at
approximationen bliver dårlig, jævnfør Figur 6. Hvis det ikke umiddelbart er
klart ud fra denne forklaring, kan vi gå lidt videre med nogle observationer
omkring Figur 6.
Læg først mærke til at de første egenværdier (og vi minder om at egenværdierne eksakt er lig variansen af principal-aktiverne) er flere størrelsesordener
større end dem i halen. Det betyder hvis blot man har en stor vægt på de første principal-akter, da vil bidraget fra halen være af mindre betydning. Læg
hernæst mærke til, at halen har en svag hældning. Faktisk er det oftest sådan
at halen falder nogenlunde linært ned til 0, eller i hvert fald meget tæt på
0. Husk nu på at kernen i approximationen går ud på at udskifte de eksakte
værdier i halen med en gennemsnitlig værdi for halen. Det betyder at hvis en
given portefølje har en stor vægt midt i halen, da vil approximationen gå godt
(fordi gennemsnitsværdien af halen er meget tæt på den midterste værdi af
halen). Men hvis en given portefølje har en stor vægt i en af siderne i halen, da
vil approximationen gå meget galt. Til sidst bemærkes at hvis en portefølje
har lige meget vægt i begge sider af halen, da vil approximationen igen gå
godt.
For at lave en undersøgelse af approximationens gyldighed for porteføljer med
forskellige grader af diversifikation, genererer vi et antal porteføljer med én
32
aktie i hver, et antal porteføljer med 4 aktier i hver, osv. med 8, 16, 32 og 64
aktier i hver portefølje. Til sidst laver vi et antal porteføljer hvor alle aktier
indgår med en tilfældig valgt vægt, hvorefter der normeres så summen bliver
1.
Tabel 2: Cutoff-værdier for approximation med fejl under 1% vist for
forskellige grader af aktie-diversifikation angivet med 1, 4, 8, ..., 64,
’Alle’ samt for forskellige datasæt: NYSE77, SP2000 og SP84. Øverste
tabel viser de absolutte cutoff-værdier, nederste tabel viser cutoff-værdien
relativt til det totale antal principal-aktiver/egenværdier.
Cutoff
NYSE77
SP2000
SP84
Cutoff %
NYSE77
SP2000
SP84
1
383
109
53
1
22%
29%
54%
4
307
63
38
4
18%
17%
39%
8
174
13
2
8
10%
3.4%
2.0%
16
32
64
Alle
29
1
1
1
1
1
1
1
1
1
1
1
16
32
64
Alle
1.7% 0-1% 0-1% 0-1%
0-1% 0-1% 0-1% 0-1%
0-1% 0-1% 0-1% 0-1%
6.2.3 Resultat af empiriske undersøgelser
Resultaterne af de empiriske undersøgelser af approximationsformlen (10) for
standard-afvigelsen er opsummeret i Figur 7, Figur 8 og Tabel 2.
Graferne på de to figurer viser hvilken procentvis fejl der findes for de valgte
porteføljer som funktion af cutoff-factor k. I den øverste graf på Figur 7 kan
man eksempelvis se at approximation af std.afv. for en portefølje med kun
én aktie vil give fejl på mellem 0 og 40%, hvis k = 1 (dvs. kun den første
egenværdi medregnes). Hvis k = 200 svinger fejlen mellem 0 og godt 10%.
Hvis alle egenværdier medregnes (dvs. k er lig n som er lig 381) er fejlen
eksakt 0, som forventet.
Hvis vi går til næste graf for porteføljer med 4 aktier i hver, ser man det
samme mønster, dog er approximationen væsentlig bedre allerede når k er
tæt på 1. Hvis man kan leve med en præcision på 5% kan man faktisk nøjes
med at sætte k = 5, hvilket i sig selv vil give en reduktion i beregningstiden
på 1 − 5/381 ≈ 98.7%.
For porteføljer med 16 aktier og opefter kommer fejlen under 1% allerede med
k = 1.
Som man kan se er der meget stor forskel på hvor godt den historiske varians for forskellige porteføljer egner sig til at blive approximeret, hvilket giver
anledning til et bredt bånd af grafer. Til gengæld ser man at diversificerede porteføljer generelt set danner et smallere bånd end ikke-diversificerede
33
porteføljer og at diversificerede porteføljer egner sig væsentlig bedre til approximationen.
På Tabel 2 ses øverst hvilken cutoff-værdi k man skal bruge for at få en
approximationsfejl på under 1% for porteføljer med forskellig grad af diversifikation. Fx. kan man se at for datasættet NYSE77 og en portefølje med 16
aktier, skal man bruge de første 29 principal-aktiver, dvs. k = 29, for at få en
approximationsfejl på under 1%. Tilsvarende kan man aflæse at med en fuldt
diversificeret portefølje kan man nøjes med det første principal-aktiv, dvs.
k = 1. Den nederste tabel viser det samme, blot er tallene omregnet til en reduktionsfaktor, dvs. man finder cutoff-faktoren divideret med det totale antal
principal-aktiver: k/n. Dette er samtidig et udtryk for den mulige reduktion
man kan opnå i beregningstiden, jævnfør afsnit 6.1. Eksempelvis kan man for
porteføljer med mindst 16 forskellige aktier i SP2000 (som er et marked med
384 aktier) få en reduktion på ca. 100% − 3.4% = 96.6% af beregningstiden
og stadig have en præcision på 1%.
Ved generelt at kigge på graferne for diversificerede porteføljer kan man se, at
approximationen virker med meget stor nøjagtighed.
7 Definition af value-at-risk og expected shortfall
Vi har nu vist, hvordan man kan finde en god approximation af den historiske
varians og standard-afvigelse for en givet portefølje. I praksis er man dog ofte
mere interesseret i andre risikomål end standard-afvigelsen. Typisk ønsker
man nemlig risikomål som kan bruges til at bestemme hvor meget risikovillig
kapital en given position i markedet kræver, hvilket fører til en betragtning
af risikomål som giver et bud på hvor store tab, man kan blive udsat for.
To sådanne risikomål er value-at-risk (VaR) og expected shortfall (ESF) som
behandles i dette afsnit.
VaR er løst sagt et mål for hvor stort et værditab vi højst kan udsættes for
indenfor en given tidshorisont og med en given sandsynlighed. For at definere
VaR mere formelt tager vi udgangspunkt i en given portefølje P, et givet
tidsinterval t - som i rammerne af denne analyse altid er 1 dag - og en given
sandsynlighed α ∈ [0, 1], typisk 95% eller 99%. Det er praktisk at indføre α
ˆ=
1 − α, dvs. α
ˆ vil typisk være 5% eller 1%. Nu minder vi om at α-fraktilen for
P angiver det punkt på x-aksen i et diagram over sandsynlighedsfordelingen
for P, hvor α-% af sandsynlighedsmassen ligger til venstre for punktet og
dermed ligger 1 − α-% til højre for punktet.
Hermed kan vi definere value-at-risk sådan her:
VaRα (P) = −1 · (ˆ
α-fraktilen af P)
(11)
Det negative fortegn er indført, fordi man ønsker at value-at-risk skal være et
34
Figur 9: Illustration af sandsynlighedsfordeling og fraktiler. Figuren viser et histogram over daglige relative afkast for Alcoa Inc. (med ticker
symbolet AA) målt over perioden 1984-2014, hvilket svarer til en tidsserie med ca. 7500 målepunkter. Nederste billede viser halerne i større
detalje. Middelværdien kan findes til at være 0.0004 og spredningen er
0.023. Ved hjælp af lidt databehandling kan man finde, at 5%-fraktilen
ligger omkring -0.033, dvs. med andre ord er VaR95% = 0.033. Dernæst
kan man finde at 1%-fraktilen ligger omkring -0.06, dvs. VaR99% = 0.06.
NB: Hvis det daglige afkast havde været normalfordelt, skulle 99.7% af
punkter ligge mellem -0.07 og +0.07, hvilket passer nogenlunde grafisk
set. Til gengæld burde et daglig relativt afkast på -0.24 (som er det yderste venstre punkt) kun ske en ud af ca. 8 · 1026 dage, hvilket er en klar
indikation af, at det daglige afkast ikke er normalfordelt.
Figur 10: Grafisk illustration af VaR og ESF. Her vises som eksempel
90%-VaR og som det fremgår ligger 90% af sandsynlighedsmassen til
højre for punktet mens 10% ligger til venstre. ESF kan man forstå som
middelværdi af den del af halen som ligger til venstre for VaR, dvs.
middelværdien af den gule hale.
positivt mål, dvs. det angiver det potentielle tab. Begreberne omkring fraktiler
og definitionen af VaR er illustreret på Figur 9 og Figur 10.
NB: Bemærk at value-at-risk traditionelt defineres som et absolut mål for det
potentielle tab og value-at-risk måles normalt i en konkret valuta. Fx kan
man have en 95% VaR på 200.000 kr for en portefølje med værdi 1mio.kr.
Som allerede nævnt tænker vi på P som en stokastisk variabel, der angiver
den daglige relative tilvækst. Hvis fx P en dag er lig -0,08, da svarer det til
at porteføljen har haft et relativt afkast på -8%, eller omvendt sagt, et tab på
+8%. Da vi benytter den konvention, at alle porteføljer koster 1 kr (og bliver
rebalanceret hver dag) kan vi lige så godt tænke på det som om, at vi har lidt
et tab på 0,08kr. Med andre ord kan vi tænke på vores stokastiske variabel P
som den daglige gevinst/tab i kroner, og dermed bliver ovenstående definition
af value-at-risk konsistent med den normale definition.
Expected shortfall (forkortet ESF) er løst sagt et mål for, hvor meget man
skal forvente at tabe, hvis det først går galt. Mere præcist defineres ESF i
lighed med VaR for en given sandsynlighed α% og en given tidshorisont, som
det forventede tab i de α-% værste scenarier der kan hænde indenfor den givne
tidshorisont. ESF er også illustreret på Figur 10.
Formelt kan vi definere ESF som følger:
ESFα = −E(P|P < −VaRα )
Igen er der indført et negativt fortegn, for at ESF bliver en positiv størrelse. I
ord vil man læse formlen som det forventede tab givet et tab større end VaRα .
36
7.1 Historisk VaR og ESF
Når man arbejder med tidsserier for daglige relative prisændringer er det let at
finde den historiske VaR og historiske ESF. Historisk VaR for en givet fraktil
α findes ved at sortere tidsserien i stigende orden efter daglig relativ tilvækst
(så de største tab kommer først) og dernæst finde det K’te element i rækken,
hvor K = α
ˆ T og T er det totale antal elementer i tidsserien. Vi minder om at
α
ˆ ≡ 1 − α.
Historisk ESF findes i forlængelse heraf, ved at tage middelværdien af de
elementer, som kommer før det K’te element.
Det skal her bemærkes at historisk VaR og ESF også kan bestemmes på andre
måder fra en given tidsserie. Fx kan der benyttes en form for interpolation,
hvis man forsøger at bestemme nogle fraktiler, hvor der er langt imellem punkterne. Dette behov opstår typisk hvis man har et lille antal datapunkter i sin
tidsserie, eller hvis man forsøger at bestemme de mest ekstreme fraktiler såsom 99.9999%-fraktilen. Til denne opgave vil vi nøjes med den simple metode
beskrevet herover.
7.2 Empiriske resultater
Vi kan starte med at undersøge VaR for enkelte aktier, hvor vi sammenligner
historisk VaR med 1.6449×σ som teoretisk skulle give det samme, hvis afkastet
var normalfordelt. Dette er vist for SP1984 på Figur 11. Det ses at der som
forventet er en klar sammenhæng mellem σ og VaR i den forstand at de
bevæger sig op og ned sammen (dvs. de er stærkt korrelerede), men det ses også
at de ikke ligger oven i hinanden (dvs. afkastet er ikke normalfordelt) og der
er heller ikke perfekt korrelation, dvs. der er lidt forskel på hvor tæt de ligger
på hinanden. Dette skal fortolkes således, at der er forskelle i haletykkelserne
på forskellige aktier. Til at illustrere dette kigger vi nærmere på to specifikke
aktier, WMB (Williams Companies, Inc.) og PNR (Pentair plc). Tabel 3 viser
VaR-værdier for forskellige α-værdier. Det ses tydeligt at WMB er tykkere i
halen end PNR idet alle fraktiler udover 99%-fraktilen ligger længere ude.
Derudover kunne det være interessant at sammenligne VaR og ESF for aktier
versus principal-aktiver. Dette er vist på Figur 12. Som det kan ses giver
principal-aktiverne en form for koncentration af volatiliteten således at de
første principal-aktiver har en høj VaR svarende til en høj volatilitet, mens
halen har en lav VaR. Det samme gør sig gældende for ESF.
37
Alpha
95%
98%
99%
99.7%
99.9%
99.99%
VaRα /σ
PNR Norm.ford.
1.5
1.6
2.1
2.1
2.6
2.3
3.8
2.8
5.1
3.1
11.6
3.7
WMB
1.1
1.8
2.5
4.1
5.8
19.8
Tabel 3: Viser value-at-risk målt i enheder af σ for to virksomheder PNR
(Pentair Plc) og WMB (Williams Companies Inc.) med forskellig haletykkelse sammenlignet med en normalfordeling. Eksempelvis er VaR-95%
for Pentair Plc ca. lig med 1.5 standardafvigelser.
Figur 11: Illustration af VaR fundet henholdsvis historisk og ud fra formlen 1.6449 × σ.
Figur 12: Illustration af VaR (øverst) og ESF (nederst) fundet for alle
aktierne i SP84 markedet sammenlignet med VaR fundet for principalaktiverne. Den ’glatte’ grønne kurve angiver VaR hhv. ESF for principalaktiverne. Den blå hakkede kurve angiver VaR hhv. ESF for aktierne i
markedet.
Figur 13: En normalfordeling er entydigt kendetegnet ved dens middelværdi og standardafvigelse.
8 Approximation af value-at-risk
Vi ønsker at finde en metode til udregning af VaR og ESF der ligger i forlængelse af den allerede udledte formel (10) for approximation af varians og
standardafvigelse. Samtidig ønsker vi at forstå de begrænsninger og antagelser, der skal gøres for at approximationen er god.
Først gøres den betragtning, at visse familier af stokastiske variable har et fast
forhold mellem standard-afvigelsen og en given fraktil. For disse stokastiske
variable vil der også være et fast forhold mellem standard-afvigelsen og VaR-α,
jævnfør definitionen af VaR (11). Som eksempel har man den velkendte 68-9599.7 regel for normalfordelingen, der siger, at ca. 68% af sandsynlighedsmassen
ligger inden for 1 σ, 95% ligger inden for 2σ og 99.7% ligger inden for 3σ.
Denne ide er illustreret på Figur 13. Således har man at VaR-95% for en
normalfordelt stokastisk variabel med varians σ altid vil være 1.6449 × σ.
Man kan nu opstille den hypotese, at de porteføljer P vi kan konstruere i markedet, vil have denne egenskab, altså at der givet α er et fast forhold mellem
σ(P) og VaRα (P), uanset hvilken portefølje P vi vælger. Teoretisk set er der
gode eksempler på multivariate fordelinger, som har denne egenskab, specielt
skal nævnes de elliptiske fordelinger, jf. [2] afsnit 3.3. En simpel måde at efterprøve denne tese empirisk er, at udregne den historiske value-at-risk samt den
historiske standard-afvigelse for en række forskellige porteføljer eller aktier
i markedet, og dernæst finde forholdet mellem VaR og standard-afvigelsen.
Dette er undersøgt for SP84 og resultatet kan ses på Figur 14 og Tabel 4.
Undersøgelsen viser (som forventet) at hypotesen ikke holder eksakt. Til gengæld kan vi se, at forholdet ligger i et fast bånd, der i værste fald svinger
med ±10% for aktierne og i bedste fald ca. ±4% for halen af egenvektorerne,
jævnfør Tabel 4.
Vi kan nu lave følgende approximation, som analytisk set er grov og klodset
men som til gengæld er nem at forstå. Betragt en portefølje P og en fast værdi
40
Figur 14: Viser en undersøgelse af forholdet mellem value-at-risk og
std.afv. for SP84-aktierne øverst og SP84-principalaktiverne (dvs. egenvektorerne) nederst. Først observeres at forholdet generelt er mindre for
aktierne (svinger mellem 1.2 og 1.5) end for egenvektorerne (svinger
mellem 1.4 og 1.6). Det kan fortolkes således at egenvektorerne repræsenterer de kombinationer af aktiver i markedet, som giver de tungeste
haler! Det er ønskværdigt set ud fra et risikostyringsperspektiv, idet vi
jo netop forsøger at få styr på den risiko, som gemmer sig i de tunge haler. Dernæst ses det, at grafen for egenvektorerne har den særlige
egenskab, at halen stabiliserer sig en smule ved at svinge mellem 1.5 og
1.6. Tabel 4 viser middelværdi og std.afv. for svingningerne for hhv. aktierne, egenvektorerne og halen af egenvektorer (hvor de første 10 hhv.
20 egenvektorer skæres fra).
Tabel 4: Middelværdi og std.afv. i forholdet value-at-risk / std.afv.
Middelværdi
Aktier
1.42
Egenvektorer
1.57
Egenvektor > 10
1.58
Egenvektor > 20
1.59
std.afv.
0.071
0.055
0.035
0.03
95% konfidensinterval
±10%
±7%
±4.4%
±3.8%
af α og sæt
γ ≡ VaR(P)/σ(P)
Vi har droppet α-fodtegnet for at holde notationen simpel, men det er underforstået at vi mener VaRα () når vi skriver VaR(). Vi tænker på γ som
det sande men ukendte forhold mellem value-at-risk og std.afv. for P. Definér
ligeledes:
γi ≡ VaR(Qi )/σ(Qi )
hvor vi husker at Qi er den i’te principal komponent. Vi tænker på γi som forholdet mellem VaR og std.afv. for det i’te principalaktiv. Med udgangspunkt
i undersøgelsen fra Figur 14 og Tabel 4 vil vi nu antage at γ ≈ γi for alle i.
Ved at anvende egenvektor-dekompositionen fra (8) ser vi følgende:
(VaR(P))2 = γ 2 · σ 2 (P)
= γ 2 β12 λ1 + · · · + βn2 λn
= β12 γ 2 λ1 + · · · + βn2 γ 2 λn
≈ β12 γ12 λ1 + · · · + βn2 γn2 λn
= β12 VaR(Q1 )2 + · · · + βn2 VaR(Qn )2
hvor det i sidste linie er udnyttet at γi2 λi = γi2 σ 2 (Qi ) = (γi σ(Qi ))2 = VaR2 (Qi ).
Hvis vi indsætter α-fodtegnet igen og tager kvadratroden på begge sider finder
vi den endelige formel:
q
VaRα (P) ≈ β12 VaR2α (Q1 ) + · · · + βn2 VaR2α (Qn ) hvor βi ≡ w · q0i
(12)
Selvom argumentet i udledningen ikke er specielt stærkt, skal vi senere se at
denne approximation empirisk set er overraskende god.
Som en sidste bemærkning vil vi sammenligne denne formel med en tilsvarende
formel for standard-afvigelsen. Formel (8) kan omskrives til:
q
σ(P) = β12 σ 2 (Q1 ) + · · · + βn2 σ 2 (Qn )
(13)
42
Det understreges at σ er et moment-baseret risikomål, og som sådan er det
fundamentalt anderledes end VaR, ESF og andre fraktil-baserede risikomål.
Ligeledes skal det understreges at (13) er et analytisk eksakt resultat og ikke en
approximation som formel (12). På trods af forskellene i σ og VaR og måden,
hvorpå de to formler er udledt, så giver det intuitivt mening at riskomål som i
en eller anden forstand "skalerer"med std.afvigelsen, kan dekomponeres vha.
principal-komponenterne på samme måde som std.afvigelsen.
Ovenstående approximation har stadig den ulempe, at den involverer alle egenvektorer, hvilket både er beregningstungt og udsat for stor statistisk støj. Derfor vil vi nu forbedre approximationen yderligere ved at indsætte en middelværdi for value-at-risk i halen af egenvektorer og samtidig udskifte de mange
βi -værdier for halen med en samlet projektion ned i underrummet udspændt
af hale-egenvektorerne - præcis som det blev gjort i forbindelse med udledning
af formel (10). Hermed ender vi med dette centrale resultat, som gør det muligt at approximere value-at-risk med de k første egenvektorer og egenværdier
til kovarians-matricen:
(VaR(P))2 ≈ β12 VaR2 (Q1 ) + · · · + βk2 VaR2 (Qk )
!
k
X
2
2
2
+ VaRtail · kwk −
βj
(14)
j=1
hvor βi ≡ w ·
q0i
8.1 Bestemmelse af VaR i halen
Approximationen (14) involverer kun de første k egenvektorer bortset fra den
gennemsnitlige value-at-risk for halen af egenvektorer. I tilfældet med approximationen (10) kunne man anvende et analytisk eksakt resultat om at
summen af egenværdierne er lig summen af varianserne for de oprindelige ak2
tier (matematisk Tr(C) = Tr(Λ)) til at omskrive σtail
yderligere uden tab af
nøjagtighed. Denne mulighed har vi ikke nu. Man kan istedet forestille sig en
af følgende metoder anvendt til at bestemme VaR2tail :
1. Man kan finde alle principal-aktiverne i halen og dernæst finde value-atrisk for hver af disse. Slutteligt kan man finde gennemsnittet af VaR2i .
2. Som det kan ses på Figur 12 er halen nogenlunde jævnt faldende. Dvs.
man kunne nøjes med at bestemme value-at-risk for et par udvalgte
principal-aktiver i halen, og dernæst lave en simpel lineær interpolation
for at finde den gennemsnitlige værdi af VaR2i for i > k.
43
Uanset hvilken model der vælges til at estimere den gennemsnitlige værdi af
VaR2i i halen skal det bemærkes, at det ligesom for approximation af standardafvigelsen/variansen jf. (10) gælder, at de første principal-aktiver vil veje
tungest for vel-diversificerede porteføljer, både fordi VaR er størst for de første
principal-aktiver jf. Figur 12 og fordi vel-diversificerede porteføljer vil have de
største βi -værdier for de første i’er. Derfor vil selv større unøjagtigheder ved
bestemmelse af Var2tail blive mindre betydende når vi bruger approximationen
(12).
Til de empiriske undersøgelser i denne opgave vil vil blot anvende metode 1.
Dette kan lade sig gøre fordi vi betragter et relativt lille marked og dermed
kan vi nemt finde alle principal-aktiverne i halen.
8.2 Empiriske resultater
For at efterprøve formel (14) er der i genereret 5000 diversificerede porteføljer.
For hver af disse er VaR udregnet historisk og ved hjælp af formel (14) for forskellige cutoff-værdier k. Dernæst er den procentvise fejl mellem den historiske
og den approximerede værdi fundet og slutteligt er der lavet et histogram, der
viser fordelingen af procentvise fejl. Derudover er den gennemsnitlige fejl og
spredningen på fejlen fundet.
Undersøgelsen er først lavet uden cutoff (dvs. alle principal-aktiverne bruges)
på tværs af datasættene SP84 og SP2000. Resultatet ses på Figur 15.
Det ses at approximationen er brugbar, hvis man kan leve med unøjagtigheder på VaR på op til ca. 4%. Bemærk at denne fejlmargin opstår pga. den
approximation der blev lavet ved udledning af formel (12) og ikke pga. haleapproximationen i formel (14), da den ikke er anvendt her.
For at se om hale-approximationen giver en yderligere forringelse af nøjagtigheden, laves en undersøgelse af SP2000, hvor der prøves med forskellige
cutoff-værdier, denne gang for VaR-99% istedet for VaR-95%. Resultatet ses
på Figur 16. Det bemærkes at alle 4 histogrammer har en forholdsvis høj grad
af overensstemmelse hvad angår spredning og form. Det skal fortolkes således,
at man ved at anvende et meget lille principal-aktiver i approximationen kan
bestemme VaR med nogenlunde samme præcision, som hvis man anvender
alle principal-aktiver.
Approximationen af VaR er måske ikke fuldt tilfredsstillende, idet en fejlmargin på 4-6% ikke nødvendigvis er acceptabel. Da udregning af risikomål typisk
handler om kapitalkrav, er det ikke ligegyldigt, om der skal bruges 4-6% mere
eller mindre. Vi skal nu se, at ESF som risikomål har nogle pænere egenskaber
i denne sammenhæng, da vores approximation virker væsentlig bedre for ESF
end for VaR.
44
Figur 15: Viser et histogram over den procentvise fejl mellem den historiske og den approximerede værdi af VaR-95% jf. formel (14) for hhv.
SP84 (øverst) og SP2000 (nederst) for 5000 tilfældigt genererede porteføljer.
Figur 16: Viser den procentvise fejl mellem den historiske og den approximerede værdi af VaR-99% for SP2000 med anvendelse af cutoffværdier på hhv. 1, 4 og 8 (de tre øverste) mens det nederste histogram
er lavet uden cutoff.
9 Approximation af expected shortfall
Vi vil nu gå skridtet videre og lave den samme approximation for expected
shortfall. Igen gør vi den observation at der for visse familier af stokastiske variable vil være et fast forhold mellem standardafvigelsen og expected shortfall
for en given fraktil. Dette vil eksempelvis gælde for de multivariate elliptiske
fordelinger.
Ved at bruge de samme argumenter som blev anvendt til udledning af (14),
finder man en approximation for ESF som følger:
ESFα (P) ≈
q
β12 ESF2α (Q1 ) + · · · + βn2 ESF2α (Qn ) hvor βi ≡ w · q0i
(15)
Lige som før kan vi også anvende argumentet med at bruge en gennemsnitsværdi for ESF2α (Qi ) i halen for i > k, dvs. vi finder formlen:
(ESF(P))2 ≈ β12 ESF2 (Q1 ) + · · · + βk2 ESF2 (Qk )
!
k
X
2
2
2
+ ESFtail · kwk −
βj
(16)
j=1
hvor βi ≡ w ·
q0i
Ligesom for approximationen af VaR skal vi overveje, hvordan vi kan finde
ESF2tail , dvs. den gennemsnitlige expected shortfall for principal-aktiverne i
halen. Og ligesom for VaR kan man forestille sig forskellige heuristiske metoder
til at finde dette, jævnfør diskussionen i afsnit 8.1. Til denne opgave bruger vi
samme fremgangsmåde for ESF som vi gjorde for VaR, dvs. vi finder ganske
simpelt expected shortfall for alle principal-aktiverne med index i>k og herfra
finder vi den gennemsnitlige værdi af expected shortfall.
9.1 Empiriske resultater
Efterprøvningen af approximationerne for ESF foregår efter samme metode
som for VaR og resultaterne ses på Figur 17, Figur 18 og Figur 19.
Overordnet set bemærker vi at approximationerne generelt er bedre for ESF
end for VaR. Fx. ses på Figur 17 at approximationen har en fejlmargin på
under 1% for både SP84 og SP2000.
47
Figur 17: Viser den procentvise fejl mellem den historiske og den approximerede værdi af ESF-95% for hhv. SP1984 (øverst) og SP2000 (nederst).
Figur 18: Viser den procentvise fejl mellem den historiske og den approximerede værdi af ESF for SP2000 for forskellige værdier af α lig
90%, 95%, 99% og 99.9% (øverst til nederst). Det ses at approximationen
er ret god for alle α-værdier op til og med 99%, hvorefter approximationen bliver forringet.
Figur 19: Viser den procentvise fejl mellem den historiske og den approximerede værdi af ESF for forskellige cutoff-værdier k = 1, 4, 8 for
SP2000. Den nederste figur er lavet uden cutoff.
Fra Figur 18 kan vi observere at fejlmarginen vokser når fraktilen α vokser.
Dvs. vores approximation bliver dårligere og dårligere jo længere vi kommer
ud i halerne. For at forstå dette fænomen, skal vi tænke lidt dybere over,
hvad der gør principal-aktiverne så velegnede til bestemmelse af variansen,
faktisk så velegnede at formel (8) gælder eksakt. Forklaringen er, at principalaktiverne udgør de aktiver i vores marked, som maksimerer variansen10 og
som samtidig er ukorrelerede. Hvis vi samtidig husker at variansen og korrelation pr. definition er 2. ordens momenter, kan vi omformulere og sige, at
principalaktiverne er den optimale basis til at beskrive og beregne 2. ordens
momenter i markedet. Samtidig skal man indse at det ikke nødvendigvis er
optimalt til at beskrive og beregne højere ordens momenter.
Da VaRα og ESFα er fraktil-bestemte mål og α desuden kan antage alle værdier
mellem 0 og 1, afhænger de ikke kun af ét moment, men derimod af alle
momenter.11 Den grundlæggende hypotese for denne opgave kan nu udtrykkes
således:
Principalaktiverne udgør en optimal basis til at beskrive og beregne varians og standard afvigelse. Samtidig udgør de et godt bud
på en tæt-på-optimal basis til at beskrive og beregne VaR og ESF.
10
Og her er det underforstået at vi mener, at den første egenvektor maksimerer variansen
globalt, den anden maksimerer variansen i underrummet vinkeltret på den første, den tredje
maksimerer variansen i underrummet vinkelret på de to første osv. osv.
11
Vi minder om at en sandsynlighedsfordeling (for ’pæne’ fordelinger) entydigt bestemmes
af sine momenter og omvendt, jævnfør Teorem 5.2 i [4] som vedrører moment-genererende
funktioner.
51
10 Bestemmelse af cut-off faktor vha. af random matrix
teori (RMT)
Random matrix teori har sit udspring i teoretisk fysisk hvor grundstenene
blev lagt af Eugene Wigner, som i øvrigt vandt Nobelprisen i fysik i 1963.
Random matrix-teori har fundet anvendelse indenfor en lang række forskellige
områder indenfor fysisk, matematik og statistik og i de senere år også indenfor
finansiering, jævnfør [6] og [7].
I random matrix-teori betragter man ganske simpelt en matrix, hvor de enkelte
elementer er stokastiske variable eller - om man vil - tilfældige tal udtrukket
efter en given sandsynlighedsfordeling. Herefter undersøger man forskellige
statistiske egenskaber ved matricen, som udgangspunkt relateret til fordelingen af egenværdier og egenvektorer.
Vi vil i det følgende betragte et marked med n aktiver, som antages at være
ukorrelerede og med identiske sandsynlighedsfordelinger. Bemærk at vi ikke
antager at de er normalfordelte, blot at de er identisk fordelte. For en nemheds
skyld antager vi også at de er normaliseret så standardafvigelsen er 1. Det
antages nu at vi har en tidsserie i dette marked der viser afkast (pr. minut,
pr. time, pr. dag eller andet) af længde T , som angiver antal målepunkter.
Følgende må gælde helt oplagt:
• Den ægte (dvs. teoretiske) korrelationsmatrix for markedet må være lig
identitetsmatricen:


1 0 ... 0
0 1
0
.

.

C teoretisk = I n = ..
. . ... 
0
0
...
1
• Identitetsmatricen I n ses at have n egenværdier alle med værdien 1 mens
egenvektorerne er givet ved enhedsvektorerne.
• Når T bliver meget stor for fastholdt n må den empiriske korrelationsmatrix nærme sig den teoretiske grænse, dvs. fordelingen af egenværdier
må konvergere mod en spike, som har meget stor tæthed omkring 1.
• Jo mindre T bliver (dvs. jo færre målepunkter der haves i tidsserien) jo
større usikkerhed må der være i bestemmelsen af den empiriske korrelationsmatrix, dvs. naivt set må man forvente at fordelingen af egenværdier spreder sig i en eller anden form omkring 1.
Et centralt resultat indenfor RMT er, at der kan findes en overraskende simpel
analytisk formel der beskriver fordelingen af egenværdier i grænsen hvor både
52
Figur 20: Viser den teoretiske grænse for distributionen af egenværdier for korrelationsmatricen for en random matrix for Q ≡ T /N =
1.5, 10, 100 respektivt, hvor Q = 1.5-værdier svarer til den brede fordeling med en peak i venstre side mens Q = 100 svarer til den højeste
og mest centrerede halv-cirkel. Det man skal lære af figuren er, at jo
kortere tidsserie man har relativt til markedets størrelse (dvs. jo mindre
Q-værdi), jo mere bredspektret bliver støjen. Omvendt, jo længere tidsserie man vælger, jo mere konvergerer formen mod en spike omkring 1,
der i den teoretiske grænse samler hele sandsynlighedsmassen præcis i
punktet 1.
n og T går mod uendelig på en sådan måde at forholdet Q ≡ T /n fastholdes.
Hvis vi lader ρ(λ) betegne tæthedsfunktionen for fordelingen af egenværdier
ser formlen således ud:
p
Q (λmax − λ)(λmin − λ)
ρ(λ) =
λ
2π
p
max
hvor λmin = 1 + 1/Q ± 2 1/Q og Q = T /n
(17)
Formlen er oprindelig udledt af Vladimir Marcenko og Leonid Pastur i 1967, og
fordelingsfunktionen kaldes derfor for en Marcenko-Pastur fordeling. Fordelingen kan opfattes som et støjbånd, dvs. egenværdier som falder indenfor båndet
har ingen statistisk signifikans. Marcenko-Pastur fordelingen er illustreret på
Figur 20 for tre forskellige Q-værdier.
For at efterprøve disse resultater, kan vi simulere en tidsserie af længde T
fra et fiktivt marked bestående af n ukorrelerede aktiver med daglige afkast
der følger fx en normalfordeling (men vi kunne have valgt en vilkårlig anden
fordeling med middelværdi 0 og spredning 1). Herudfra findes korrelationsmatricens egenværdier og der kan tegnes et histogram. Dette sammenlignes med
Marcenko-Pastur fordelingen. Resultatet ses på Figur 21 hvor sammenfaldet
mellem empiri og teori er tydeligt.
53
Figur 21: Empirisk egenværdi-fordeling af en korrelationsmatrix for et
fiktivt marked bestående af ukorrelerede og identisk fordelte aktiver hvor
markedet størrelse n og tidsseriens længde T er valgt til at matche hhv.
SP2000 (øverst) og SP84 (nederst). Til sammenligning er også indtegnet
den teoretiske Marcenko-Pastur fordeling (tynd kurve). Det ses at den
empiriske fordeling tilnærmes fint af den teoretiske. Det skal understreges at i grænsen hvor både n og T går mod uendelig i et fast forhold,
da vil den empiriske egenværdi-fordeling konvergere mod den teoretiske
fordeling.
Figur 22: Øverst vises tætheden af egenværdier for korrelationsmatricen
for NYSE77 (lodrette søjler) sammenholdt med Marcenko-Pastur fordelingen (støjbåndet) for Q = 9334/1594 = 5.9 (blå kurve), der ville være
den gældende fordeling hvis aktierne i NYSE77-markedet var ukorrelerede. Det lille indlejrede vindue viser histogrammet i fuld skala. Det ses at
den første egenværdi skiller sig markant ud fra støjbåndet med en værdi
på 340, dvs. ca. 170 gange større end støjbåndets maksimumværdi. Den
2. og 3. egenværdi følger efter med værdier omkring 40. I midten og nederst vises det tilsvarende for hhv. SP2000 og SP84. I alle tre tilfælde ses,
at den empiriske fordeling er væsentlig forskelligt fra Marcenko-Pastur,
hvilket fortolkes på den måde, at markedet indeholder signifikante korrelationer, i modsætning til et komplet ukorreleret marked som det ses på
Figur 21.
Vi kan nu gå skridtet videre og sammenligne Marcenko-Pastur fordelingen
med de empiriske fordelinger for de tre udvalgte markeder, NYSE77, SP84 og
SP2000. Dette er gjort på Figur 22, hvor man ser, at de empiriske egenværdifordelinger adskiller sig radikalt fra Marcenko-Pastur fordelingen. Det kan
dels ses på formen men også (som noteret på figurerne) på cut-off faktoren
k der angiver hvor mange egenværdier, der ligger til højre for λmax og på
korrelationsfaktoren, der til formålet er defineret som forholdet mellem den
højeste empiriske egenværdi λ1 og λmax fra formel 17. Eksempelvis er λ1 = 340
for p
NYSE77 mens λmax = 1.997 som det kan udregnes fra formlen 1 + 1/Q +
2 ∗ (1/Q) hvor Q = 9334/1594.
Vi kan altså konkludere, at NYSE77 har 65 principal-aktiver (svarende til
k = 65) der ligger uden for støj-båndet (Marcenko-Pastur fordelingen) og den
første af disse principal-aktiver har en varians, der er 170 gange højere (angivet på figuren med korrelationsfaktor=170) end man vil finde i et fuldstændig
ukorreleret marked. Med andre ord, der findes i markedet 65 porteføljer, svarende til de første 65 principal-aktiver, som indkapsler al signifikant korrelation
i markedet.
Hermed har vi argumenteret for, at RMT kan anvendes til at give et bud på
en fornuftig cut-off faktor k ud fra betragtningen om, at man kun vil operere
med de principal-aktiver som kan tillægges statistisk signifikans.
56
11 Forecasting
Livet forstås baglæns, men må leves forlæns. - Søren Kierkegaard
Søren Kierkegaards velkendte citat har stor sandhed i relation til risikovurdering. Den sande risiko, den risiko vi virkelig gerne vil kende til, er risikoen for
de hændelser som adskiller sig så meget fra tidligere hændelser, at vi ikke har
en chance for at forudse dem.
Risk managere i små og store virksomheder har ikke den luksus, at kunne
læne sig tilbage sammen med Kierkegaard og se det som et grundvilkår kun
at kunne forstå fortiden. Vurdering af risiko handler i sidste ende altid om
vurdering af fremtidig risiko.
Indtil nu har vi koncentreret os om historiske risikomål, eller udtrykt mere
præcist, om risikomål udregnet for en tidligere periode med kendte markedsdata. Forecasting handler om det modsatte, nemlig om beregning af risikomål
for en fremtidig periode.
For at sætte den rigtige ramme for den følgende diskussion, starter vi med at
tage et kort kig på de metoder og principper, der anvendes i Danske Capital til
at lave forecasting af risiko. Med udgangspunkt heri vil vi give nogle udvalgte
eksempler på hvordan principal-aktiver kan anvendes.
11.1 Forecasting i Danske Capital - et resume
Forecasting i Danske Capital foregår efter en model, der er beskrevet i et
internt notat som er venligt udlånt til denne opgave og endvidere opsummeret
i en artikel i Finans Invest, jf. [9].
Modellen tager som udgangspunkt følgende observationer:
• Afkastfordelinger er ikke normalfordelte. Der er tykke haler og skævhed.
• Ingen egenskaber ved markedet er stationære, alting er i bevægelse. Det
gælder i særdeleshed korrelationer.
• Markedet har regimer, dvs. perioder med forskellige karakteristika. I
det interne notat anvendes en model med fire regimer kaldet expansion,
slowdown, recession og recovery. I artiklen [9] anvendes to regimer kaldet
stresset og ustresset.
• Markedet udviser temporal korrelation, dvs. korrelation mellem afkastet
af et givet aktiv til et tidspunkt og afkastet af samme aktiv til et senere
tidspunkt. Endvidere observeres det, at den temporale korrelation kommer fra de ekstreme hændelser. Hvis man fjerner alle ekstreme hændelser
fra datasættet forsvinder den temporale korrelation næsten.
57
Figur 23: Illustrerer idéen om en regime-model alá den der arbejdes med
i Danske Capital. Man tænker på markedet som et tilstandsrum med et
antal tilstande kaldet regimer, her vises 4 regimer. For hver periode der
går (fx en måned eller et kvartal) er der en given sandsynlighed for at
der sker en overgang til et andet regime.
• De ekstreme hændelser findes med stor overvægt i perioder (dvs. regimer) med recession. Det medfører at regimer med recession vil udvise
temporal korrelation i større grad mens det modsatte vil gøre sig gældende i andre regimer.
• Mange har forsøgt at modellere og parametrisere de multivariate fordelinger i markedet, hvilket har givet anledning til såkaldte copula-teorier.
Da det dels baserer sig på avancerede matematiske koncepter og dermed
bliver svært tilgængeligt for mange investorer og dels giver modeller med
mange frihedsgrader (og dermed stor vilkårlighed i modellen) har Danske Capital valgt en tilgang hvor der i stedet trækkes stikprøver fra de
historiske data. Hermed trækker man altså stikprøver fra den multivariate fordeling som markedet reelt har udvist uden at man behøver en
underliggende matematisk model for fordelingen.
Regime-modellen arbejder med et antal forskellige regimer. I det interne notat
anvendes Recession, Recovery, Expansion og Slowdown. I artiklen [9] anvendes
to regimer kaldet Stresset og Ustresset. Dette kobles med en model for overgangssandsynligheder imellem de forskellige regimer. Denne idé er illustreret
på Figur 23.
For at udregne et givet risikomål for en given portefølje, en given tidshorisont
og en antagelse om et givet intielt regime, bruges regime-modellen først til
at bestemme hvilke regimer der skal betragtes med hvilke vægte over hvilke
58
perioder. Hernæst trækkes historiske hændelser (dvs. afkast) fra de pågældende regimer for den givne portefølje. Hermed får man et bud på en fremtidig
tidsserie for porteføljen, som den vil se ud givet regime-modellen og de historiske data. Slutteligt kan der udregnes alle ønskelige risikomål for porteføljen,
herunder naturligvis varians, VaR og ESF.
Modellen kan udnyttes videre til at lave modeller for optimal allokering af
porteføljer. Princippet er her at man for forskellige risiko-værdier (den ønskede
risiko-profil) laver en afsøgning af markedet som numerisk bestemmer den
portefølje der optimerer afkastet givet risikoen.
11.2 Forecasting med principal-aktiver
Modellen omkring principal-aktiver ændrer ikke ved de grundlæggende diskussioner og problemstillinger man har, når man skal opstille en model for
vurdering af (fremtidig) risiko. Den grundlæggende anke er, at historien ikke
gentager sig selv.
Til gengæld giver principal-aktiverne os en række nye værktøjer og teknikker
til at forstå og analysere markedsdynamikkerne. Dette afsnit vil give nogle
udvalgte eksempler på dette.
Hvis man genlæser afsnittet om forecasting i Danske Capital vil man finde
følgende vigtige analyser:
• Identifikation af regimer.
• Identifikation af hvilket regime man pt. befinder sig i.
• Bestemmelse af overgangssandsynligheder mellem regimer.
• Udregning af afkast for en given portefølje.
• Udregning af realiseret risiko (ex.ante) for en given portefølje for en
historisk periode.
• Estimering af forventet fremtidig risiko (ex.post) for en given portefølje
for et givet regime.
• Bestemmelse af den efficiente rand, dvs. for en givet ønsket risiko (investors ’budget’) find den portefølje der giver højst mulige afkast.
Vi vil her fokusere på spørgsmålet omkring identifikation af regimer. Første
spørgsmål er hvorledes regimer kan bestemmes. Dette spørgsmål giver i sig
selv stof nok til en længere analyse, så vi kommer til at nøjes med en kort
diskussion af emnet. Helt overordnet set må formålet med regimerne være at
finde perioder, hvor markedets karakteristika hvad angår afkast og risiko er
nogenlunde stationære.
59
Lad os her repetere fra afsnit 3 at vi tænker på markedet, som værende beskrevet af n stokastiske variable A1 , . . . , An svarende til de n aktiver i markedet.
Teoretisk set vil A1 , . . . , An være beskrevet af en multivariat fordeling for aktivernes afkast. Vi kan nu formulere kravet ved at sige, at regimer skal dække
perioder hvor den multivariate fordeling er nogenlunde konstant.
Nu er multivariate fordelinger forholdsvis svære at begribe og visualisere. En
særlig gren indenfor statistik kaldet copula-teori har til formål at studere
sådanne fordelinger, blandt andet med henblik på at kunne klassificere og
sammenligne forskellige fordelinger, jævnfør afsnit 5 i [2] og afsnit 5 i [3]. Det
vil føre for vidt at give en formel behandling af spørgsmålet her.
I stedet vil vi simplificere sagen ved at sige, at regimer skal dække perioder
hvor de almindelige korrelationer (dvs. kovarians) er konstante. Korrelationerne er som bekendt givet i form af kovariansmatricen (eller korrelationsmatricen), så man ledes til spørgsmålet, hvordan man herudfra skal identificere
regimerne.
Her kommer principal-aktiverne ind i billedet. Sagen er jo at principal-aktiverne
og de tilhørende egenværdier giver en meget præcis beskrivelse af korrelationerne i markedet. Det første principal-aktiv q1 giver en retning i markedet
for den maksimale varians. En ændring i q1 kan fortolkes som en korrektion i
markedet, hvor korrelationerne har ændret sig, ikke fordi volatiliteten nødvendigvis har ændret sig, men fordi den aktiv-sammensætning (dvs. portefølje)
som giver den største volatilitet (varians) har ændret sig.
Tilsvarende angiver den første egenværdi størrelsen på den maksimale volatilitet i markedet. En ændring i den første egenværdi angiver således en ændring
i markedets volatilitet og dermed et muligt regimeskifte.
Med udgangspunkt i disse ideer kan vi nu lave en model for identificering af
regimer vha. principal-aktiverne som illustreret på Figur 24. Den øverste figur
viser udviklingen af de 6 største egenværdier henover en periode på 30 år. Der
er brugt et glidende vindue på 4 år der skubbes måned for måned. Fx. skal
de første punkter på grafens venstre side hørende til årstallet 1988 fortolkes
således, at der i perioden 1984-1988 har været en markedsdynamik, hvor den
maksimale kovarians (dvs. den maksimale egenværdi) lå et sted mellem 0.01
og 0.02. Det ses også at den højeste egenværdi falder drastisk omkring år 1992
hvorefter den stiger jævnt til ca. år 2004, hvorefter den falder igen.
På den midterste figur er vist et såkaldt egenvektor-delta. Grafen er lavet ved
måned for måned at finde projektionen af den første egenvektor set i forhold
til den første egenvektor måneden før.
projektion til tiden t = q1 (t) · q1 (t − 1)0
Dvs. grafen giver et indtryk af hvilke korrektioner eller chok der sker i markedet. Så længe der er ro i markedet og sålænge den første egenvektor ikke
rigtig ændrer sig henover tid, da ligger projektionen tæt på 1 (projektionen
60
Figur 24: Giver to forskellige overblik over udviklingen i principalaktiverne henover en periode på 30 år. Den øverste graf viser udviklingen
i de 6 første egenværdier. Den midterste graf viser hvilke forskydninger
der har været i det første principal-aktiv fra måned til måned.
er 1 hvis og kun hvis de to vektorer er 100% ens). Når der sker en korrektion
falder projektionen til et sted mellem 0 og 1. På figuren ses således nogle tydelige korrektioner omkring år 1993, igen i år 2003 samt i år 2007 og 2009.
Hvis man sammenligner med den forrige graf vil man se at disse korrektioner
passer ret fint med ændringer i markedsvolatiliteten.
Hermed afrunder vi vores diskussion af principal-aktiver og forecasting. Det
er blevet demonstreret hvorledes modellen åbner op for nye analyse-teknikker
og måder at anskue markedsdynamikkerne på.
61
12 Konklusioner og resultater
Der er givet en definition og gennemført udledning af alle relevante egenskaber ved principal-aktiverne ud fra en central matematisk hovedsætning spektralsætningen. Der er ført beviser for at de er ukorrelerede, at de optimerer variansen og at de udgør en komplet basis for repræsentation af porteføljer
i markedet (se afsnit 4.2 og hovedresultatet (8)). Det er endvidere vist, hvorledes man finder porteføljer på den efficiente rand, når man arbejder med
principal-aktiver (se formel (9)).
Det er vist at man kan anvende principal-aktiver til at lave meget effektive
approximationer af både varians/standardafvigelse (se formel (10)), value-atrisk (se formel (14)) og expected shortfall (se formel (16)).
Der er lavet analyser af historiske data for tre forskellige tidsserier (SP2000,
SP1984 og NYSE77) som strækker sig over et stort antal aktier (op til knap
1600 aktier for NYSE77) og en forholdsvis lang periode - op til 37 år for NYSE77 (se afsnit 3.2). Herunder er der udviklet en række Matlab-programmer
til formålet, hvoraf et uddrag er vist i appendix.
En reduktion i beregningstiden på 99% er generelt muligt for diversificerede
porteføljer i alle tre markeder samtidig med at man nemt opnår en præcision
på omkring 1% for både varians (se afsnit 6.2.3) og expected shortfall (se
afsnit 9.1). Approximation af VaR fungerer lidt dårligere med typiske relative
fejl på omkring 4-5% (se afsnit 8.2) .
Der er gjort rede for en konkret forecasting model, som anvendes i Danske
Capital (se afsnit 11.1). Med udgangspunkt i denne model er der givet et
eksempel på, hvorledes principal-aktiver kan bruges til at udvikle og evt. forbedre denne type forecasting-modeller (se afsnit 11.2).
13 Perspektivering
Vi har med denne opgave kradset i overfladen og taget udvalgte spadestik i
den emnekreds, der åbner sig med introduktionen af principal-aktiver. Den
grundlæggende idé har fra starten været, at finde en ny måde at faktorisere
finansielle markeder på med udgangspunkt i matematisk teori, som allerede
har vist sit værd i mange sammenhænge indenfor finansiering, statistik, fysik
og andre videnskaber.
Det er min overbevisning, at principal-aktiver som forståelsesramme udgør et
vigtigt alternativ til traditionelle faktormodeller. Mange interessante egenskaber er blevet udledt og diskuteret men der er naturligvis mange flere aspekter
som kan og bør undersøges for at få det fulde udbytte af modellen, herunder
kan nævnes følgende:
62
• Det kan undersøges, hvorvidt udledningen af approximationen for VaR
og ESF i afsnit 8 og 9.1 kan underbygges af mere stringente argumenter.
Fx er det forholdsvis oplagt at en multivariat elliptisk fordeling jævnfør
defintion 3.26 i [2] vil have den egenskab, at der er et fast forhold mellem std.afvigelse og fraktil-baserede mål såsom value-at-risk og expected
shortfall. Dermed kan udledningen af (12) forbedres rent teoretisk - uden
at det dog ændrer på approximationens gyldighed og anvendelighed i
virkelighedens verden.
• Det kan undersøges hvor stort et datagrundlag man skal bruge for at
udregne principal-aktiverne op til et givet cut-off k med statistisk signifikans kontra hvor stort et datagrundlag man skal bruge for at udregne
kovarians-matricen med statistisk signifikans. Det skal gerne kunne vises
at de første k principal-aktiver (dvs. både egenværdier og egenvektorer)
kræver et væsentlig mindre datagrundlag end kovariansmatricen som
helhed. Dvs. også her kan der opnås en væsentlig besparelse hvad angår
beregningstid og beregningskompleksitet.
• Som det forklares i [6] og [7] afsnit V.B. er det muligt at rense kovariansmatricen for den støj, som svarer til principal-aktiver i støjbåndet, jævnfør teorien i afsnit 10. Hermed opnår man ifølge disse forfattere bedre
resultater hvad angår allokering af optimale porteføljer.
• Der kan laves reelle målinger der konkret efterviser de besparelser i beregningstid på 99% eller mere, som principelt er påvist i afsnit 6.2.3
• Der kan laves konkrete anvendelser og eftervisninger af formel 9 til fremfinding af den efficiente rand. Det kan eftervises at man kommer frem til
samme efficiente rand som en traditionel Markovitz optimering. Endvidere ville det være interessant at undersøge, om der kan laves effektive
approximationer af den efficiente rand ved at bruge hale-argumenter svarende til dem der blev givet for udledning af varians-approximationen i
afsnit 6.
• Det kan undersøges om man kan føre ideen om principal-aktiver endnu
videre ved at finde de aktiv-sammensætninger i markedet som optimerer ikke variansen men derimod fx VaR−α eller ESFα for et givet α.
På denne måde kunne man måske skabe en endnu bedre basis for at
analysere fraktil-baserede risikomål, jævnfør afsnit VI.C. i [7].
• Man kan gentage mange af de undersøgelser, som er gennemført i denne
opgave, blot hvor kovarians-matricen udregnes som et såkaldt løbende
eksponentielt dæmpet gennemsnit.
Med denne liste af idéer til videre behandling afrundes denne opgave.
63
Litteratur
[1] I. T. Jolliffe,
Principal Component Analysis,
Springer,
Second Edition,
2002.
[2] McNeil, Frey, Embrechts,
Quantitative Risk Management,
Princeton University Press,
First Edition,
2005.
[3] Michael B. Miller,
Mathematics & Statistics for Financial Risk Management,
Wiley,
Second Edition,
2014.
[4] Richard A. Johnson
Miller & Freunds Probability and Statstics for Engineers,
PHI,
Eight Edition.
[5] William H. Press, Saul A. Teukolsky, William T. Vetterling, Brian P. Flannery
Numerical Recipes in C,
Cambridge,
Second Edition.
[6] Laurent Laloux, Pierre Cizeau, Marc Potters, Jean-Philippe Bouchaud
Random matrix theory and financial correlations ,
Science & Finance,
https://www.math.nyu.edu/faculty/avellane/LalouxPCA.pdf,
World Scientific Publishing Company
[7] Jean-Philippe Bouchaud, Marc Potters
Financial Applications of Random Matrix Theory: a short review,
Science & Finance,
http://arxiv.org/pdf/0910.1205.pdf
[8] Yazann Romahi and Katherine S. Santiago,
Diversification - still the only free lunch?,
https://am.jpmorgan.com/blobcontent/800/973/1383169203651_11_566.pdf,
JPMorgan Asset Management
64
[9] Preben Bertelsen, Rasmus Majborn, Per Søgaard-Andersen,
Risikomåling for langsigtede investorer,
Finans Invest 1/2010,
jf. http://www.finansinvest.dk/Default.aspx?Page=172
[10] Analysegruppen, Aarhus School of Business,
Portfolie Optimization and Matrix Calculation in Excel,
http://nikolaschou.dk/principalaktiver/Portfolio-Optimization.pdf
[11] Wikipedia authors,
Eigenvalue algorithm,
http://en.wikipedia.org/wiki/Eigenvalue_algorithm
[12] Wikipedia authors,
Stock Market Index,
http://en.wikipedia.org/wiki/Stock_market_index
[13] Wikipedia authors,
Risk Parity,
http://en.wikipedia.org/wiki/Risk_parity
[14] Wikipedia authors,
Principal component analysis,
http://en.wikipedia.org/wiki/Principal_component_analysis
Appendices
A Programkode
For at give et indtryk af, hvorledes analyserne i denne opgave er udarbejdet,
vises her to centrale programfiler fra de Matlab-programmer, der er udviklet.
classdef Rates
%UNTITLED4 Encapsulates various utility services around fetching,
%loading and saving rates to desk.
%
properties
end
methods(Static)
function dates = loadTradingDaysChron(period)
%Loads trading days chronologically
dates = flip(Rates.loadTradingDays(period));
end
function dates = loadTradingDays(period)
%%Function loadTradingDays
%Loads trading days for each period between given start and end,
%including both ends. Dates are returned in reverse order (newest
%first)
startYear=period.startYear;
startMonth = period.startMonth;
endYear = period.endYear;
65
endMonth = period.endMonth;
fprintf([’Fetching dates from ’ Utils.formatDate(startYear,startMonth) ’ to ’ Utils.formatDate(endYear, endMonth)]);
dateIntervals = getDateIntervals(startYear, startMonth, endYear, endMonth);
dates = [];
for j=numel(dateIntervals):-1:1
dateObj1 = dateIntervals{j};
ds = Rates.loadTradingDaysForMonth(dateObj1.year, dateObj1.month);
% now concatenate the full time series for a single sec along
% dimension 1
dates = cat(1,dates,ds);
fprintf([’.’]);
end
disp(’ - DONE!’);
end
function cacheFolder = getCacheFolder()
cacheFolder = ’/Users/nikolaschou-pedersen/Documents/MATLAB/cache/’;
end
function n = noTradingDaysMonth(startYear, startMonth)
n = numel(Rates.loadTradingDaysForMonth(startYear, startMonth));
end
function n = noTradingDays(period)
dateIntervals = getDateIntervals(period.startYear, period.startMonth, period.endYear, period.endMonth);
n = 0;
for j=1:numel(dateIntervals)
dateObj1 = dateIntervals{j};
n = n+ Rates.noTradingDaysMonth(dateObj1.year, dateObj1.month);
end
end
function p = getPeriod(y1, m1, y2, m2)
%If only two arguments are provided these will be taken
%startYear and endYear respectively.
if nargin==2
y2=m1;
m1=1;
m2=1;
end
p=struct(’startYear’,y1,’startMonth’,m1,’endYear’,y2,’endMonth’,m2);
end
%%Function loadAll
%% Loads the trading days corresponding to a given period as a column vector.
function dates = loadTradingDaysForMonth(startYear, startMonth)
persistent map;
if isempty(map)
map = containers.Map;
end
key = Utils.formatDate(startYear,startMonth);
if ~map.isKey(key)
folder = [Rates.getCacheFolder() ’_dates/’];
if ~exist(folder,’dir’)
mkdir(folder)
end
dateObj1 = Rates.getDateObj(startYear, startMonth);
dateObj2 = Rates.getDateObj(startYear, startMonth+1);
fileName = [folder,’dates-’,dateObj1.title,’.mat’];
if exist(fileName,’file’)
loadObj = load(fileName);
data = loadObj.data;
else
d1 = datenum(dateObj1.year,dateObj1.month,1);
d2 = datenum(dateObj2.year,dateObj2.month,1);
% Subtract one day so date intervals are non-overlapping
d2 = addtodate(d2,-1,’day’);
%Use IBM to fetch the trading days
data = fetch(Rates.getYahoo(),’IBM’,’Close’, d1, d2);
% only keep date information
data = data(:,1);
save(fileName,’data’);
end
map(key)=data;
end
dates = map(key);
end
function conn = getYahoo()
conn = yahoo(’http://download.finance.yahoo.com’);
end
function rates = loadOrFetchGeneric(conn,sec, period, dataType)
%Loads adjusted prices for the given security
%If the data has been saved to a file, load from there instead
%timer = tic();
folder = Rates.getFolder(sec,dataType);
if ~exist(folder,’dir’)
mkdir(folder)
end
secNameCleaned=strrep(sec,’/’,’_’);
secNameCleaned=strrep(secNameCleaned,’^’,’_’);
fileName = [folder,secNameCleaned,’-’,strrep(Utils.formatPeriod(period),’ to ’,’_’),’.mat’];
66
if exist(fileName,’file’)
temp=load(fileName);
rates=temp.data;
fprintf([’1’ sec]);
else
d1 = Utils.yearMonth2date(period.startYear, period.startMonth);
d2 = Utils.yearMonth2date(period.endYear, period.endMonth);
try
data=fetch(conn,sec,dataType,d1,d2);
fprintf([’2’ sec]);
data=flip(data,1);%Make it chronological
catch exc
data=[];
fprintf([’!’ sec]);
end
save(fileName,’data’);
rates=data;
end
%timer2=toc(timer);
%display(timer2);
end
function rates = fetchAdjusted(sec,period)
data = fetch(yahoo,sec,’Adj Close’,Utils.startDate(period),Utils.endDate(period));
rates = flip(data,1);
end
function title = makeTitle(o)
title = ’’;
if isfield(o,’title’)
title = o.title;
end
if isfield(o,’name’) && isfield(o,’period’)
title=[title o.name ’ ’ Utils.formatPeriod(o.period)];
end
%make recursion
if isfield(o,’parentObject’)
title = [title ’ / ’ Rates.makeTitle(o.parentObject)];
end
end
function variance = getGainsVariance(rateObj)
if ~isfield(rateObj,’gainsCleanedVariance’)
rateObj.gainsCleanedVariance = var(rateObj.gainsChronCleaned);
end
variance = rateObj.gainsCleanedVariance;
end
function plotRates(rateObj,securities,type)
%Utility function to plot rates
if nargin<3
type=’rates’;
end
if isstr(securities)
%Wrapp it in a cell structure
securities = {securities};
end
if iscell(securities)
indexes = Utils.findInCellMany(rateObj.securitiesCleaned,securities);
else
%Assume it is given by a vector of index-positions in the cleaned set
indexes=securities;
securities=rateObj.securitiesCleaned(indexes);
end
if strcmp(type,’rates’)
rates=rateObj.ratesChronCleaned(:,indexes);
elseif strcmp(type,’gains’)
rates=rateObj.gainsChronCleaned(:,indexes);
elseif strcmp(type,’loggains’)
rates=rateObj.loggainsChronCleaned(:,indexes);
else
error(’Unkown type’);
end
period=rateObj.period;
sec=strjoin(securities,’, ’);%[num2str(numel(rateObj.securities)) ’ securities’];
dates=rateObj.dates(1:size(rates,1));
if ~isempty(dates)
plot(dates,rates);
datetick(’x’,’yyyy-mm’);
else
plot(rates);
end
title([’Plot of ’ type ’ (’ sec ’) ’ Utils.formatPeriod(period)]);
zoomAdaptiveDateTicks(’on’);
end
function market = getMarketRates(period)
%Loads rates for the market as a whole based on the S&P index
market= Rates.loadAllAdjusted({’^GSPC’},period);
end
67
function rateObj = loadAllAdjusted(securities, period)
%Loads all rates for all securities for the given period.
%A rateObj is returned
conn = Rates.getYahoo();
timer=tic();
r={};
r.securities=securities;
r.securitiesFailed=containers.Map;
r.securitiesConstrained=containers.Map;%Contains securities not having valid rates for the whole period
display([’Loading ’ num2str(numel(securities)) ’ securities’]);
%Will just use IBM to fetch dates
d1 = Utils.startDate(period);
d2 = Utils.endDate(period);
ibmDates=flip(fetch(conn,’IBM’,’Close’,d1,d2),1);%Use IBM to get the trading days
ibmDates=ibmDates(:,1);
r.noTradingDays=numel(ibmDates);
r.dates=ibmDates;
r.period=period;
result = zeros(r.noTradingDays,numel(securities));
%
for i=1:numel(securities)
fprintf([’ ’ num2str(i) ’/’ num2str(numel(securities)) ’ ’]);
sec = securities{i};
data=Rates.loadOrFetchGeneric(conn,sec,period,’Adj Close’);
if isempty(data)
%Just ignore this security fixing the price at 1,
%think of it like an asset with no movements
result(:,i)=1;
r.securitiesFailed(sec)=i;
else
dataRates=data(:,2);
dataDates=data(:,1);
firstDate=dataDates(1);
firstIndex=find(ibmDates==firstDate,1,’first’);
% *******************************************************
********** MERGING TRADING DAYS ************
% *******************************************************
%As we have no guarantee that ibm and other stocks are
%traded at the same days (for instance, I found that IBM wan
%not traded 27-Sep-1985 whereas AAN was.
%To come around this we will move values day by day
counterIBM=firstIndex;
for j=1:numel(dataDates)
if counterIBM>numel(ibmDates)
%This happens in rare cases where dataDates has
%one more date than ibmDates
break;
end
myDate=dataDates(j);
ibmDate=ibmDates(counterIBM);
if myDate<ibmDate
%We found data for a day not valid for IBM, just
%ignore it and wait for next loop iteration
temp=1;%just to allow debugging
elseif myDate>ibmDate
%IBM has more trading days than the loaded data
%Insert yesterdays rate to keep the rate steady
%Make a loop to increment counterIBM until ibmDate
%catches up with myDate
while(myDate>=ibmDate && counterIBM<numel(ibmDates))
result(counterIBM,i)=result(counterIBM-1,i);%Will never happen in the first iteration so this is safe
counterIBM = counterIBM+1;
ibmDate=ibmDates(counterIBM);
end
else
%Dates must match, copy rate
result(counterIBM,i)=dataRates(j);
counterIBM = counterIBM+1;
end
end
counterIBM = counterIBM-1;%we want it to reflect the last index assigned to
if counterIBM<numel(ibmDates)
%If stock has stopped trading let it have constant rate (to
%avoid high volatility caused by a sudden drop to 0).
result(counterIBM+1:end,i)=result(counterIBM,i);
end
if firstIndex>1
%If stock has not been traded from the beginning let it have
%constant rate until it is starting to trade to avoid high
%volatility caused by a sudden start of trading
result(1:firstIndex-1,i)=dataRates(1);
end
%r.securitiesFailed(sec)=true();
%display([’Fetched end date: ’, datestr(d0), ’, expected end date: ’, datestr(d1)]);
end
end
conn.close();
r.ratesChron=result;
68
r.timer=toc(timer);
rateObj=r;
display(’ ’);
display([’Done - running time ’ num2str(r.timer)]);
end
function ratesObj = loadAll(listOfSecurities, period, options)
%Load all rates for the given period. Rates are returned in
%reverse order, that is, newest first.
%This function will build up a matrix as follows (using 4
%securities as an example):
%-------month 1-----------timerVal = tic;
startYear=period.startYear;
startMonth = period.startMonth;
endYear = period.endYear;
endMonth = period.endMonth;
includedSecurities=containers.Map;
excludedSecurities=containers.Map;
dateIntervals = getDateIntervals(startYear, startMonth, endYear, endMonth);
% We will allocate enough storage and then crop in the end
timeSeriesLength=Rates.noTradingDays(period);
resultTotal = zeros(timeSeriesLength,numel(listOfSecurities));
%Used to keep track of the accumulated number of trading days
%in building up the total matrix
tradingDayCounter = 0;
for j=numel(dateIntervals):-1:1
dateObj1 = dateIntervals{j};
noSecs=size(resultTotal,2);
noTradingDaysThisMonth = Rates.noTradingDaysMonth(dateObj1.year,dateObj1.month);
resultForInterval = zeros(noTradingDaysThisMonth, noSecs);
disp(’ ’);
fprintf([dateObj1.title ’: ’]);
secCounter=1;
for i = 1:numel(listOfSecurities)
secu = listOfSecurities{i};
if ~excludedSecurities.isKey(secu)
data = Rates.loadOrFetchRatesForMonth(secu, dateObj1.year, dateObj1.month, options.buildArray);
if (options.buildArray)
if Rates.isValidRates(data) && numel(data)==noTradingDaysThisMonth
resultForInterval(:,secCounter) = data;
secCounter = secCounter + 1;
includedSecurities(secu)=true();
else
% Remove this security from the matrix
excludedSecurities(secu)=true();
resultForInterval(:,secCounter) = [];
resultTotal(:,secCounter) = [];
end
end
end
end
% now concatenate the full time series for a single sec along
% dimension 1
if (options.buildArray)
resultTotal(tradingDayCounter+1:tradingDayCounter+noTradingDaysThisMonth,:) = resultForInterval;
tradingDayCounter = tradingDayCounter + noTradingDaysThisMonth;
end
end
rates = resultTotal;
disp(’ ’);
ratesObj = {};
ratesObj.ratesChron = flip(rates,1);
ratesObj.rates = rates;
ratesObj.excludedSecurities = excludedSecurities;
remove(includedSecurities,keys(excludedSecurities));
ratesObj.includedSecurities = includedSecurities;
ratesObj.period = period;
ratesObj.elapsedTime = toc(timerVal);
ratesObj.dateIntervals = dateIntervals;
end
function [ rates ] = loadOrFetchRatesForMonth( secu, startYear, startMonth, returnData )
%loadOrFetchSecurity Loads or fetches the rates for a given security for
%one month
%
First it is checked whether the security can be found in the file
%
system. Otherwise it is fetched and then saved to desk.
%If returnData is false and a data file is found in the cache, this
%function will return quickly.
folder = Rates.getFolder(secu);
if ~exist(folder,’dir’)
mkdir(folder)
end
dateObj1 = Rates.getDateObj(startYear, startMonth);
dateObj2 = Rates.getDateObj(startYear, startMonth+1);
secName = strrep(secu,’/’,’_’);
fileName = [folder,secName,’-’,dateObj1.title,’.mat’];
if exist(fileName,’file’)
if (returnData)
loadObj = load(fileName);
69
data = loadObj.data;
else
% Ok, no need to do more
data = [];
end
fprintf([’ 1’ secu]);
else
d1 = datenum(dateObj1.year,dateObj1.month,1);
d2 = datenum(dateObj2.year,dateObj2.month,1);
% Subtract one day so date intervals are non-overlapping
d2 = addtodate(d2,-1,’day’);
try
data = fetch(Rates.getYahoo(),secu,’Close’, d1, d2);
% throw away date information
data = data(:,2);
% fprintf([’Fetched from yahoo: ’,secu,’ ’,dateObj1.title]);
fprintf([’ 2’ secu]);
catch exc
data = [];
fprintf([’ !’ secu]);
% fprintf([’Data cannot be loaded for security ’, secu, ’. Used zeros instead.’]);
end
save(fileName,’data’);
end
rates = data;
end
function val=getDateObj(startYear,startMonth)
d = datenum(startYear,startMonth,1);
val = {};
vec =datevec(d);
val.date = d;
val.year = vec(1);
val.month = vec(2);
paddedMonth = sprintf(’%02d’, val.month);
mytitle = [num2str(val.year),’-’,paddedMonth];
val.title=mytitle;
end
function val=isValidRates(data)
%at least 5 trading days
if numel(data)>5 && data(1)>0 && data(end)>0
val=true();
else
val=false();
end
end
function folder = getFolder(sec,type)
%Returns the folder containing cached data for the given
%security sec
if nargin==1
type=’Close’;
end
folder = [Rates.getCacheFolder(), ’_’,strrep(type,’ ’,’’),’/’,sec, ’/’];
end
function fileName = getMetafile(sec)
fileName = [Rates.getFolder(sec) ’meta.mat’];
end
function meta = getMeta(sec)
%Loads or inits a meta object for the given security
metafile = Rates.getMetafile(sec);
if ~exist(metafile,’file’)
meta = {};
else
loadObj = load(metafile);
meta = loadObj.meta;
end
end
function saveMeta(sec,meta)
%Saves the meta object for the given security
metafile = Rates.getMetafile(sec);
save(metafile,’meta’);
end
function yearMonth = findFirstValidMonth(sec)
%Determines which month is the first valid month for which rates
%across the whole month can be fetched for the given security
%The ’first valid month’ M is characterized by the following facts:
%1. Non-zero rates are found for M
%2. A number of non-zero rates are found corresponding to the
%number of banking days for that month
%3. Bullet 1 and 2 are not satisfied for the previous month.
meta = Rates.getMeta(sec);
if ~isfield(meta,’firstValidMonth’)
meta.firstValidMonth = Rates.findFirstValidMonthUtil(sec);
Rates.saveMeta(sec,meta);
70
end
yearMonth = meta.firstValidMonth;
end
function yearMonth = findFirstValidMonthUtil(sec)
%Finds the first valid month using a kind of log2-algorithm
persistent allMonths;
if isempty(allMonths)
%apparently yahoo only delivers data since 1963
allMonths = getDateIntervals(1963,1,2014,1);
end
N = numel(allMonths);
index = round(N/2);
leftEnd = 1;
rightEnd = N;
counter = 0;
if Rates.isValidMonth(sec,allMonths{1}.year, allMonths{1}.month)
%First check if it has been defined from the very beginning
index = 1;
else
while(true())
%display([’Investigate index ’ num2str(index) ]);
m1 = allMonths{index};
isValid = Rates.isValidMonth(sec,m1.year, m1.month);
if isValid
m0 = allMonths{index - 1};
if ~Rates.isValidMonth(sec, m0.year, m0.month)
%if the previous month is invalid we have found the
%right month
break;
end
end
%If we reach this point we know that we did not find the
%first valid month
if isValid
%go left
rightEnd = index;
increment = round((index - leftEnd)/2);
index = index - increment;
if index <= 1
index = 1;
break;
end
else
%go right
leftEnd = index;
increment = round((rightEnd - index)/2);
index = index + increment;
if index >= N
index = N;
break;
end
end
if counter > N
%Just to avoid infinite loops
error(’Could not find the first valid month’);
end
counter = counter + 1;
end
end
yearMonth = allMonths{index};
end
function b = isValidMonth(sec, y, m)
rates = Rates.loadOrFetchRatesForMonth(sec, y, m, true);
if min(rates) == 0
%A month with a rate of 0 cannot be valid
b = false();
else
noTradingDays = Rates.noTradingDaysMonth(y,m);
if numel(rates) == noTradingDays
b = true();
else
b = false();
end
end
end
function [ result ] = filterSecurities( secus, period)
%Filters a list of securites by the criteria that rates should
%be available for the given yearMonth.
result = cell(1,numel(secus));
counter = 1;
for i=1:numel(secus)
sec = secus{i};
%First check whether the data is actually valid on the
%given yearMonth
isStartValid = Rates.isValidMonth(sec, period.startYear, period.startMonth);
isEndValid = Rates.isValidMonth(sec, period.endYear, period.endMonth);
if isStartValid && isEndValid
result{counter} = secus{i};
71
counter = counter + 1;
end
end
if counter<numel(secus)
% shrink it
result(counter:end)=[];
end
end
end
end
classdef Analysis
%UNTITLED2 Summary of this class goes here
%
Detailed explanation goes here
properties
end
methods(Static)
function rateObj=prepare(rateObj)
%Make some further preparation of a rateObj needed for the analysis
rateObj.dates=Rates.loadTradingDaysChron(rateObj.period);
rateObj.datesForPlot=Utils.formatDatesForPlot(rateObj.dates);
rateObj.securities=keys(rateObj.includedSecurities);
rateObj.gainsChron = Analysis.findGains(rateObj.ratesChron);
rateObj.diffsChron = rateObj.ratesChron(2:end,:) - rateObj.ratesChron(1:end-1,:);
end
function rateObj=prepareAdjusted(rateObj, troubledSecurityNames)
%troubledSecurityIndexes: An array of security indexes
%troubledSecurityNames
%Make some further preparation of a rateObj needed for the analysis
rateObj.datesForPlot=Utils.formatDatesForPlot(rateObj.dates);
%Now clean up the rates matrix
indexes = find(prod(rateObj.ratesChron)==0);%Indexes of columns having at least one zero (which should never happen)
for i=1:numel(troubledSecurityNames)
secIndex=Utils.findInCell(rateObj.securities,troubledSecurityNames{i});
if ~isempty(secIndex)
indexes(numel(indexes)+1) = secIndex;
end
end
indexes = unique(indexes);
rateObj.ratesChronCleaned=rateObj.ratesChron;
rateObj.ratesChronCleaned(:,indexes)=[];
rateObj.securitiesCleaned=rateObj.securities;
rateObj.securitiesCleaned(indexes)=[];
rateObj.securityIndexesTroubled=indexes;
rateObj.gainsChronCleaned = Analysis.findGains(rateObj.ratesChronCleaned);
rateObj.loggainsChronCleaned = log(rateObj.gainsChronCleaned+1);
rateObj.diffsChronCleaned = rateObj.ratesChronCleaned(2:end,:) - rateObj.ratesChronCleaned(1:end-1,:);
rateObj.n=numel(rateObj.securitiesCleaned);
rateObj.T=size(rateObj.dates,1);
end
function rateObj=prepareUni(uni,period,includedSecuritiesList)
%Takes the result of buildUniverse yahoo command and aligns it
%with the structure of other rateObjs
rateObj={};
rateObj.period=period;
rateObj.securities=includedSecuritiesList;
rateObj.ratesChron=uni(:,2:end);
rateObj.dates=uni(:,1);
rateObj.datesForPlot=Utils.formatDatesForPlot(rateObj.dates);
rateObj.gainsChron = Analysis.findGains(rateObj.ratesChron);
rateObj.diffsChron = rateObj.ratesChron(2:end,:) - rateObj.ratesChron(1:end-1,:);
end
function showEigen(corrMatrix,period,figNr,figTitle, securities)
%Plots the eigenvalues of a given corrMatrix or covMatrix for a
%given period
figure(figNr);
[eigvec,eigval]=Utils.eig2(corrMatrix);
noBins = round(numel(eigval)/3);
eigval=eigval(1:10);
hist(eigval,noBins);
clear title xlabel ylabel;
title([’Eigenvalues of ’ figTitle ’ ’ Utils.formatPeriod(period)]);
figure(figNr+1);
plot(sort(eigvec(:,1)));
title([’First eigenvector of ’, figTitle, ’ ’, Utils.formatPeriod(period)]);
[max0,index0]=max(abs(eigvec(:,1)));
display([’First eigenvector of ’, figTitle, ’ dominated by ’, securities{index0}]);
end
function full(rates, period, securities)
%%Makes an analysis of different
gains = Analysis.findGains(rates);
72
%loggains = log(gains);
%Analysis.showEigen(corr(rates),period,1,’rates’);
Analysis.showEigen(corr(gains),period,1,’correlation of gains’, securities);
Analysis.showEigen(cov(gains),period,3,’covariance of gains’, securities);
%Analysis.showEigen(corr(loggains),period,5,’log of gains’);
%Analysis.showEigen(corr(exp(gains)),period,7,’exp of gains’);
end
function drawRandomMatrix(sizeT,sizeN)
r2=rand(sizeT,sizeN);
eigvalrand=eig(corr(r2));
figure(9);
hist(eigvalrand,20);
title([’Eigenvalues of correlation of random matrix of size ’ num2str(sizeT) ’X’ num2str(sizeN)]);
end
function gains = findGains(rates)
%Determines the gains from a timeseries of rates
gains = rates(2:end,:)./rates(1:end-1,:) - 1;
end
function analysis = riskForecasting(rateObj, quantile, portfolios, pcaPeriod, figNo)
%
analysis={};
analysis.pcaAnalysis = Analysis.PCA(rateObj,pcaPeriod,figNo);
analysis.periodLength=pcaPeriod.endYear-pcaPeriod.startYear;
forecastingLength = rateObj.period.endYear - pcaPeriod.endYear;
analysis.portfolioValueAtRiskErrorMean = zeros(forecastingLength+1,1);
analysis.portfolioValueAtRiskErrorStdDev = zeros(forecastingLength+1,1);
analysis.portfolioESFErrorMean = zeros(forecastingLength+1,1);
analysis.portfolioESFErrorStdDev = zeros(forecastingLength+1,1);
%Slide through the years
for i = 0:forecastingLength
analysisTemp=Analysis.valueAtRisk(analysis.pcaAnalysis,quantile,portfolios,Rates.getPeriod(pcaPeriod.startYear+i,pcaPeriod.endYear+i));
analysis.portfolioValueAtRiskErrorMean(i+1)=analysisTemp.portfolioValueAtRiskErrorMean;
analysis.portfolioValueAtRiskErrorStdDev(i+1)=analysisTemp.portfolioValueAtRiskErrorStdDev;
analysis.portfolioESFErrorMean(i+1)=analysisTemp.portfolioESFErrorMean;
analysis.portfolioESFErrorStdDev(i+1)=analysisTemp.portfolioESFErrorStdDev;
end
end
function analysis = valueAtRisk(pcaAnalysis, quantile, portfolios, forecast, cutoff)
%
Finds the historical value at risk measure for a given portfolio
%fractile: A number close to 0, e.g. 0.05 for the 5% quantile
%analysis: Expects an analysis object as returned from the PCA
%
function
%portfolios: A n x m matrix where each row corresponds to a vector of stock weights summing to 1.
%nrYearsToForecast: Can either be a number measuring the number
%
of years to forecast ahead of the period used for PCA or it
%
can be a period.
%init
if nargin<3
portfolios=Utils.createPortfolios(numel(pcaAnalysis.eigenValues),20);
end
if nargin<4
forecast = 2;
end
if ~isfield(forecast,’startYear’)
%Assume it is an integer indicating the number of years to forecast
p = pcaAnalysis.periodUsedForPCA;
forecast = Rates.getPeriod(p.endYear,p.endMonth,p.endYear + forecast,p.endMonth);
end
if nargin<5
cutoff = 10;
end
analysis={};
analysis.portfolios=portfolios;
analysis.quantile=quantile;
analysis.cutoff = cutoff;
analysis.periodForecasted=forecast;
[analysis.minIndex, analysis.maxIndex] = Utils.findDateInterval(pcaAnalysis.rateObj.dates,forecast);
min=analysis.minIndex;
max=analysis.maxIndex;
analysis.pcaAnalysis=pcaAnalysis;
analysis.parentObject=pcaAnalysis;
analysis.rateObj=pcaAnalysis.rateObj;
%find VaR of assets
gains = pcaAnalysis.rateObj.gainsChronCleaned(min:max,:);
[analysis.valueAtRisk, analysis.ESF] = Analysis.valueAtRiskUtil(gains,quantile);
analysis.gainsVariance = var(gains);
stdDev = sqrt(analysis.gainsVariance);
analysis.valueAtRiskFromVariance = stdDev * norminv(quantile,0,1);
%VaR and ESF for eigenvectors should be found from the
%PCA-based period
[analysis.eigenValueAtRisk, analysis.eigenValueESF] = Analysis.valueAtRiskUtil(pcaAnalysis.eigenGains,quantile);
73
%analysis.eigenValueAtRisk has one row with VaR calculated
%historically for each eigenvector
analysis.eigenValueAtRiskFromVariance = sqrt(pcaAnalysis.eigenValues) * norminv(quantile,0,1);
if Utils.equalPeriods(forecast,analysis.pcaAnalysis.periodUsedForPCA)
analysis.title=[’ \alpha =’ num2str(analysis.quantile*100) ’%’];
else
analysis.title=[’Forecast for ’ Utils.formatPeriod(forecast) ’, \alpha =’ num2str(analysis.quantile*100) ’%’];
end
analysis.portfolioGains = gains*transpose(portfolios);%Gains for the forecast period projected on each portfolio
[analysis.portfolioValueAtRisk,analysis.portfolioESF] = Analysis.valueAtRiskUtil(analysis.portfolioGains,quantile);
analysis.eigenProjections = portfolios * pcaAnalysis.eigenVectors;%Each row will contain projection constants for the respective portfolio
%At this point the top row of eigenProjections is:
%|alpha1 alpha2 ... alpha_n|
%being projections of
%portfolios(1,:), i.e. the ’first’ portfolio, on the first
%eigenVector.
%Exploit that eigenvectors are uncorrelated, hence
%VaR(portfolio) = sqrt(sum of (eigenvalueVaR^2 x projection_weight^2))
analysis.portfolioValueAtRiskComposedFromEigenVectors = sqrt(analysis.eigenValueAtRisk.^2 * (analysis.eigenProjections.^2)’);
%Now calculate with cutoff
analysis.valueAtRiskTail = mean(analysis.eigenValueAtRisk(cutoff+1:end).^2);
tailAddition = analysis.valueAtRiskTail*sum(analysis.eigenProjections(:,cutoff+1:end).^2,2); %column vector with entries for each portfolio
analysis.portfolioValueAtRiskComposedFromEigenVectorsWithCut = sqrt( tailAddition’ + analysis.eigenValueAtRisk(1:cutoff).^2 * (analysis.eigenPro
analysis.portfolioESFComposedFromEigenVectors = sqrt(analysis.eigenValueESF.^2 * (analysis.eigenProjections.^2)’);
%Now calculate with cutoff
analysis.ESFTail = mean(analysis.eigenValueESF(cutoff+1:end).^2);
tailAddition2 = analysis.ESFTail*sum(analysis.eigenProjections(:,cutoff+1:end).^2,2); %column vector with entries for each portfolio
analysis.portfolioESFComposedFromEigenVectorsWithCut = sqrt( tailAddition2’ + analysis.eigenValueESF(1:cutoff).^2 * (analysis.eigenProjections(:
analysis.portfolioValueAtRiskError = (analysis.portfolioValueAtRiskComposedFromEigenVectors-analysis.portfolioValueAtRisk) ./ analysis.portfolio
analysis.portfolioValueAtRiskErrorMean = mean(analysis.portfolioValueAtRiskError);
analysis.portfolioValueAtRiskErrorStdDev = sqrt(var(analysis.portfolioValueAtRiskError));
analysis.portfolioValueAtRiskErrorWithCut = (analysis.portfolioValueAtRiskComposedFromEigenVectorsWithCut-analysis.portfolioValueAtRisk) ./ anal
analysis.portfolioValueAtRiskErrorMeanWithCut = mean(analysis.portfolioValueAtRiskErrorWithCut);
analysis.portfolioValueAtRiskErrorStdDevWithCut = sqrt(var(analysis.portfolioValueAtRiskErrorWithCut));
analysis.portfolioESFError = (analysis.portfolioESFComposedFromEigenVectors-analysis.portfolioESF) ./ analysis.portfolioESF;
analysis.portfolioESFErrorMean = mean(analysis.portfolioESFError);
analysis.portfolioESFErrorStdDev = sqrt(var(analysis.portfolioESFError));
analysis.portfolioESFErrorWithCut = (analysis.portfolioESFComposedFromEigenVectorsWithCut-analysis.portfolioESF) ./ analysis.portfolioESF;
analysis.portfolioESFErrorMeanWithCut = mean(analysis.portfolioESFErrorWithCut);
analysis.portfolioESFErrorStdDevWithCut = sqrt(var(analysis.portfolioESFErrorWithCut));
%Analysis.plotValueAtRisk(analysis, figNo);
end
function plotValueAtRisk(analysis, figNo)
%%Plot value at risk for original assets
figure(figNo);
a=analysis.valueAtRiskFromVariance;
b=analysis.valueAtRisk;
temp = cat(1,a,b);
temp = (transpose(temp));
hlines=plot(temp);
mytitle=[’Value-at-risk (’ Rates.makeTitle(analysis) ’)’];
title(mytitle);
xlabel(’Aktienr’);
ylabel(’VaR’);
set(hlines(1),’Displayname’,’Udregnet fra standardafvigelser’);
set(hlines(2),’Displayname’,’Udregnet via historisk distribution’);
legend(’Location’,’north’);
%%Plot value at risk for eigen vectors
figure(figNo+1);
a=analysis.eigenValueAtRiskFromVariance;
b=analysis.eigenValueESF;
temp = cat(1,a,b);
temp = (transpose(temp));
hlines=plot(temp);
mytitle=[’Expected Shortfall for Eigenvectors (’ Rates.makeTitle(analysis) ’)’];
title(mytitle);
xlabel(’Eigenvector’);
ylabel(’ESF’);
set(hlines(1),’Displayname’,’Udregnet fra standardafvigelser’);
set(hlines(2),’Displayname’,’Udregnet via historisk distribution’);
legend(’Location’,’north’);
%%Plot value at risk for eigen vectors
figure(figNo+2);
a=analysis.eigenValueAtRiskFromVariance;
74
b=analysis.eigenValueAtRisk;
temp = cat(1,a,b);
temp = (transpose(temp));
hlines=plot(temp);
mytitle=[’Value-at-risk for Eigenvectors (’ Rates.makeTitle(analysis) ’)’];
title(mytitle);
xlabel(’Eigenvector’);
ylabel(’VaR’);
set(hlines(1),’Displayname’,’Udregnet fra standardafvigelser’);
set(hlines(2),’Displayname’,’Udregnet via historisk distribution’);
legend(’Location’,’north’);
if size(analysis.portfolios,1)>1
%%Plot value at risk for portfolios
figure(figNo+3);
a=analysis.portfolioValueAtRisk;
b= analysis.portfolioValueAtRiskComposedFromEigenVectors;
temp = Utils.easyCat(a,b);
hlines=plot(temp);
mytitle=[’Portfolio value-at-risk (’ Rates.makeTitle(analysis) ’)’];
title(mytitle);
xlabel(’Portfolio number’);
ylabel(’VaR’);
set(hlines(1),’Displayname’,’Udregnet fra historiske data’);
set(hlines(2),’Displayname’,’Udregnet via PCA sum’);
legend(’Location’,’north’);
%%Plot ESF for portfolios
figure(figNo+4);
a=analysis.portfolioESF;
b= analysis.portfolioESFComposedFromEigenVectors;
temp = Utils.easyCat(a,b);
hlines=plot(temp);
mytitle=[’Portfolio Expected Shortfall (’ Rates.makeTitle(analysis) ’)’];
title(mytitle);
xlabel(’Portfolio number’);
ylabel(’ESF’);
set(hlines(1),’Displayname’,’Udregnet fra historiske data’);
set(hlines(2),’Displayname’,’Udregnet via PCA sum’);
legend(’Location’,’north’);
%%Plot VaR delta between historical VaR and PCA based VaR
if size(analysis.portfolios,1)>50
figure(figNo+5);
hist(analysis.portfolioValueAtRiskError, numel(analysis.portfolioValueAtRiskError)/30);
mytitle=[’Portfolie VaR relativ fejl, gns=’ Utils.formatPct(analysis.portfolioValueAtRiskErrorMean) ’, std.afv.=’ Utils.formatPct(analys
title(mytitle);
xlabel(’Relativ fejl’);
ylabel(’Hyppighed’);
Utils.formatAxisPct(’x’);
figure(figNo+6);
hist(analysis.portfolioESFError, numel(analysis.portfolioESFError)/30);
mytitle=[’Portfolie ESF relativ fejl, gns=’ Utils.formatPct(analysis.portfolioESFErrorMean) ’, std.afv.=’ Utils.formatPct(analysis.portf
title(mytitle);
xlabel(’Relativ fejl’);
ylabel(’Hyppighed’);
Utils.formatAxisPct(’x’);
figure(figNo+7);
hist(analysis.portfolioValueAtRiskErrorWithCut, numel(analysis.portfolioValueAtRiskErrorWithCut)/30);
mytitle=[’Portfolie VaR relativ fejl, cutoff=’ num2str(analysis.cutoff) ’, gns=’ Utils.formatPct(analysis.portfolioValueAtRiskErrorMeanW
title(mytitle);
xlabel(’Relativ fejl’);
ylabel(’Hyppighed’);
Utils.formatAxisPct(’x’);
figure(figNo+8);
hist(analysis.portfolioESFErrorWithCut, numel(analysis.portfolioESFErrorWithCut)/30);
mytitle=[’Portfolie ESF relativ fejl, cutoff=’ num2str(analysis.cutoff) ’, gns=’ Utils.formatPct(analysis.portfolioESFErrorMeanWithCut)
title(mytitle);
xlabel(’Relativ fejl’);
ylabel(’Hyppighed’);
Utils.formatAxisPct(’x’);
end
end
end
function [valueAtRisk, ESF] = valueAtRiskUtil(gains, quantile)
%quantile: Typically 0.95. Measures the VaR quantile
n=size(gains,1);
m=size(gains,2);
quantileIndex=round(n*(1 - quantile));
valueAtRisk = zeros(1,m);
ESF = zeros(1,m);
for i=1:m
75
s=sort(gains(:,i));
valueAtRisk(1,i)=-s(quantileIndex);
ESF(1,i) = -mean(s(1:quantileIndex));
end
end
function analysis = PCA(rateObj, periodUsedForPCA, figNo)
%This analysis will inspect the market evolution of the portfolios
%corresponding to the first few principal components of the
%whole period considered.
if nargin<=1
periodUsedForPCA=rateObj.period;
end
if nargin<=2
figNo = 1;
end
d1 = Utils.startDate(periodUsedForPCA);
d2 = Utils.endDate(periodUsedForPCA);
[minIndex, maxIndex] = Utils.findDateInterval(rateObj.dates, periodUsedForPCA);
analysis={};
analysis.rateObj=rateObj;
analysis.parentObject=rateObj;
analysis.periodUsedForPCA=periodUsedForPCA;
analysis.minIndex=minIndex;
analysis.maxIndex=maxIndex;
analysis.gainsUsedForPca=rateObj.gainsChronCleaned(minIndex:maxIndex,:);
[V,E]=Utils.eig2(cov(analysis.gainsUsedForPca));
analysis.eigenValues=E;
analysis.eigenVectors=V;
temp=sum(V);
n = numel(temp);
%Normalize so that the eigenvectors have sum = 1
%which means we can think of it as portfolio weights
analysis.eigenVectorsNormalized = V ./ (ones(n,n)*diag(temp));
analysis.eigenGains = analysis.gainsUsedForPca * analysis.eigenVectors;%These are the gains for the PCA-period projected on the eigen vectors
analysis.eigenGainsFullPeriod = rateObj.gainsChronCleaned * analysis.eigenVectors;%These are the gains for the whole period projected on the eige
analysis.eigenRatesFullPeriod=rateObj.ratesChronCleaned * analysis.eigenVectors;
%Makes no sense : analysis.eigenRatesNormalized=rateObj.ratesChronCleaned * analysis.eigenVectorsNormalized;
%Makes no sense: analysis.eigenGainsNormalized = analysis.gainsUsedForPca * analysis.eigenVectorsNormalized;
%Makes no sense : analysis.eigenGainsCalculated = Analysis.findGains(analysis.eigenRates);
market = Rates.getMarketRates(rateObj.period);
firstEigen=analysis.eigenRatesFullPeriod(:,1);
ratio=mean(market.ratesChron ./ firstEigen);
analysis.marketRates = market.ratesChron/ratio;
analysis.title=[’PCA on ’ Utils.formatPeriod(analysis.periodUsedForPCA)];
end
function pcaPlot(analysis, figNo)
try
close(figNo);
catch
end
rateObj=analysis.rateObj;
figure(figNo);
ratesCombined=cat(2, analysis.marketRates, analysis.eigenRatesFullPeriod(:,1:3));
hlines = plot(analysis.rateObj.dates,ratesCombined);
datetick(’x’);
mytitle=[’Prisudvikling for 1. og 2. egenvektor - ’ Utils.formatPeriod(rateObj.period) ’ baseret på data fra ’ Utils.formatPeriod(analysis.period
title(mytitle);
xlabel(’Tid’);
ylabel(’Pris’);
set(hlines(1),’Displayname’,’S&P index’);
set(hlines(2),’Displayname’,’1. egenvektor’);
set(hlines(3),’Displayname’,’2. egenvektor’);
set(hlines(4),’Displayname’,’3. egenvektor’);
legend(’Location’,’north’);
%%
figure(figNo+1);
hlines=semilogy(Utils.easyCat(var(analysis.eigenGainsFullPeriod),analysis.eigenValues));
title([’Varians af afkast af egenaktiverne for hele perioden vs. egenværdier ’ Rates.makeTitle(analysis.rateObj)]);
xlabel(’Egenaktiv nummer’);
ylabel(’Afkast’);
set(hlines(1),’Displayname’,’Historisk varians af egenaktiver’);
set(hlines(2),’Displayname’,’Egenværdier’);
legend(’Location’,’north’);
end
function analysis=varianceApproximation(pcaAnalysis, portfolioWeights, cutoff)
%pcaAnalysis: The result of calling PCA()
%portfolioWeights: A portfolio represented by a row-vector of weights, that
%is the vector elements must sum to 1.
%It is assumed that the portfolio is continously rebalanced in
%order for the weigths to be valid throughout the period
%cutoff: A number or vector of numbers controlling the number of
%eigenvectors used to approximate the variance. If a number
%between 0 and 1 (excluding 1) is used, it is considered as a
76
%percentage of the total number. If the number is 1 or above it
%is consideres as an absolute number. If it is a vector of
%numbers the analysis will be made for each cutoff.
%if size(portfolioWeights,1)>1
% error(’This analysis is designed for a single portfolio’);
%end
analysis={};
analysis.portfolioGains=pcaAnalysis.rateObj.gainsChronCleaned*transpose(portfolioWeights);
analysis.portfolios = portfolioWeights;
analysis.varianceHistorical=var(analysis.portfolioGains);
analysis.pcaAnalysis=pcaAnalysis;
analysis.parentObject=analysis.pcaAnalysis;
analysis.rateObj=pcaAnalysis.rateObj;
lambda = diag(pcaAnalysis.eigenValues);
analysis.projections=portfolioWeights*pcaAnalysis.eigenVectors; %beta factors, 1xn vector
analysis.varianceByPca=analysis.projections * lambda * analysis.projections’; %variance by pca using all egenvectors
N = numel(pcaAnalysis.eigenValues);
analysis.cutoff=Utils.either(numel(cutoff)==1 && cutoff(1)<1, round(numel(pcaAnalysis.eigenValues)*cutoff), cutoff);
nrCutoffs = numel(analysis.cutoff);
analysis.varianceByPcaApprox = zeros(size(portfolioWeights,1),nrCutoffs);
sumOfStockVariance = sum(Rates.getGainsVariance(pcaAnalysis.rateObj));
for i=1:nrCutoffs
K = analysis.cutoff(i);
sumOfInitialEigenValuesProjections = (analysis.projections(:,1:K).^2 * pcaAnalysis.eigenValues(1:K)’);
if K<N
fraction = 1/(numel(pcaAnalysis.eigenValues)-K);
sumOfInitialEigenValues = sum(pcaAnalysis.eigenValues(1:K));
lambdaTail = fraction * (sumOfStockVariance - sumOfInitialEigenValues);
vectorLengthOfPortfolioWeights = sum(portfolioWeights.*portfolioWeights,2);
sumOfInitialBetaSquare = sum(analysis.projections(:,1:K) .* analysis.projections(:,1:K),2);
betaTailSquare = vectorLengthOfPortfolioWeights - sumOfInitialBetaSquare;
else
lambdaTail=0;
betaTailSquare=0;
end
%
alphaCut = analysis.projections .* ((1:N)<=K); %alpha cut off
analysis.lambdaTail = mean(pcaAnalysis.eigenValues(K+1:end));
w = portfolioWeights;
analysis.varianceByPcaApprox(:,i) = sumOfInitialEigenValuesProjections + lambdaTail*betaTailSquare;
%
%
end
histVar = repmat(analysis.varianceHistorical’,1,nrCutoffs);
analysis.varianceByPcaApproxError=abs(analysis.varianceByPcaApprox./histVar - 1);
analysis.stdDevApproxError=abs(sqrt(analysis.varianceByPcaApprox./histVar) - 1);
%Average approximation error across all portfolios and all k’s
analysis.stdDevApproxErrorMean = mean(mean(analysis.stdDevApproxError));
%Average (std.dev. of approximation error across portfolios for fixed k) across k
analysis.stdDevApproxErrorMeanStdDev = mean(std(analysis.stdDevApproxError));
analysis.stdDevApproxCutoff=[];
analysis.stdDevApproxCutoffTreshold=[];
%Find the least cutoff K0 such that no approximation error is greater
%than some limit for any k>=K0
for i=1:8
treshold=10*10^(-i);
analysis.stdDevApproxCutoff(i) = Analysis.findTreshold(analysis.stdDevApproxError,treshold);
analysis.stdDevApproxCutoffTreshold(i) = treshold;
end
end
function result = findTreshold(data, limit)
result = find(max(data)>limit,1,’last’)+1;
if isempty(result)
result = 0;
end
end
function varianceAnalysis=varianceApproximationTotal(rateObj,cutoff, portfolios, portfolioName)
pca=Analysis.PCA(rateObj,rateObj.period,1);
%Analysis.pcaPlot(pca1984,4);
%variance1984=Analysis.varianceApproximation(pca1984,portfolios,4);
if nargin<3
portfolios = Utils.createPortfolios(numel(rateObj.securitiesCleaned),1);
end
varianceAnalysis=Analysis.varianceApproximation(pca,portfolios,cutoff);
Analysis.varianceApproximationPlot(varianceAnalysis,1,portfolioName);
Utils.saveFigures(1:3, [’Variance-approx-’ rateObj.name ’-’ portfolioName]);
end
function totalAnalysis = varianceApproximationTotal2(rateObj, indexes)
a={};
if nargin<2
a.indexes = cat(2,1:30,32:2:60, 65:5:rateObj.n, rateObj.n);
77
else
a.indexes=indexes;
end
portfolio1 = diag(ones(1,rateObj.n));
portfolio4 = Utils.createCircularPortfolios(rateObj.n,4);
portfolio8 = Utils.createCircularPortfolios(rateObj.n,8);
portfolio16 = Utils.createCircularPortfolios(rateObj.n,16);
portfolio32 = Utils.createCircularPortfolios(rateObj.n,32);
portfolio64 = Utils.createCircularPortfolios(rateObj.n,64);
%portfolio(1,1)=1;
portfolioDiversified = Utils.createPortfolios(rateObj.n,100);
a.approx1 = Analysis.varianceApproximationTotal(rateObj, a.indexes, portfolio1 ,’Enkelt-aktier’);
a.approx4 = Analysis.varianceApproximationTotal(rateObj, a.indexes, portfolio4 ,’4 aktier’);
a.approx8 = Analysis.varianceApproximationTotal(rateObj, a.indexes, portfolio8 ,’8 aktier’);
a.approx16 = Analysis.varianceApproximationTotal(rateObj, a.indexes, portfolio16 ,’16 aktier’);
a.approx32 = Analysis.varianceApproximationTotal(rateObj, a.indexes, portfolio32 ,’32 aktier’);
a.approx64 = Analysis.varianceApproximationTotal(rateObj, a.indexes, portfolio32 ,’64 aktier’);
a.approxDiversified = Analysis.varianceApproximationTotal(rateObj, a.indexes, portfolioDiversified ,’Diversificeret’);
totalAnalysis=a;
end
function totalAnalysis = varianceApproximationTotal3(varAnals)
fields={’approx1’,’approx4’,’approx8’,’approx16’,’approx32’,’approx64’,’approxDiversified’};
a={};
a.fixedPrecision001=zeros(1,1);
a.fixedPrecision0001=zeros(1,1);
a.fixedPrecision001Pct=zeros(1,1);
a.fixedPrecision0001Pct=zeros(1,1);
for i=1:numel(varAnals)
for j=1:numel(fields)
analysis = varAnals(i);
fieldName = fields(j);
varAnalysis = analysis.(fieldName{1});
nrEigenvalues=varAnalysis.rateObj.n;
a.fixedPrecision001(i,j) = varAnalysis.stdDevApproxCutoff(3);
a.fixedPrecision0001(i,j) = varAnalysis.stdDevApproxCutoff(4);
a.fixedPrecision001Pct(i,j)= a.fixedPrecision001(i,j)/nrEigenvalues;
a.fixedPrecision0001Pct(i,j)= a.fixedPrecision0001(i,j)/nrEigenvalues;
end
end
totalAnalysis = a;
end
function varianceApproximationPlot(analysis, figNo, portfolioName)
nrPortfolios=size(analysis.portfolios,1);
mytitle=[’PCA approximation af sigma / ’ portfolioName Utils.either(nrPortfolios>1,[’ / #porteføljer=’ num2str(nrPortfolios)] ,’’) ’ (’ Rates.ma
if nrPortfolios == 1
figure(figNo);
result = Utils.easyCat(ones(1,size(analysis.varianceByPcaApprox,2))*sqrt(analysis.varianceHistorical),sqrt(analysis.varianceByPcaApprox));
hlines=plot(analysis.cutoff,result);
title(mytitle);
xlabel(’Antal egenværdier medregnet’);
ylabel(’Standardafvigelse’);
set(hlines(1),’Displayname’,’Historisk std.afv.’);
set(hlines(2),’Displayname’,’Std.afv. udregnet ved egenværdi-approximation’);
Utils.showLegend();
end
figure(figNo+1);
hlines=plot(analysis.cutoff,analysis.stdDevApproxError);
title(mytitle);
xlabel(’Antal egenværdier medregnet’);
ylabel(’Standardafvigelse fejl’);
set(hlines(1),’Displayname’,’Fejl ved egenværdi-approximation’);
Utils.formatAxisPct(’y’);
if nrPortfolios > 1
figure(figNo+2);
s=analysis.stdDevApproxError;
result=cat(1,mean(s),mean(s)+2*sqrt(var(s)),min(s),max(s));
hlines = plot(analysis.cutoff,result’);
title(mytitle);
xlabel(’Antal egenværdier medregnet’);
ylabel(’Standardafvigelse fejl’);
set(hlines(1),’Displayname’,’Fejl ved egenværdi-approximation’);
Utils.formatAxisPct(’y’);
set(hlines(1),’Displayname’,’Gns. fejl’);
set(hlines(2),’Displayname’,’Gns. fejl 95% konfidens’);
set(hlines(3),’Displayname’,’Minimum fejl’);
set(hlines(4),’Displayname’,’Maximum fejl’);
Utils.showLegend();
end
end
function analysis = eigenEvolution(rateObj, periodLenInYears, figNo, useCovariance, useType)
%%
78
% --- Find the evolution in the top eigenvalues using a sliding 6-month span
% Loop over all months, 13 years each having 12 months
analysis = {};
if strcmp(useType,’gains’)
fullmatrix = rateObj.gainsChronCleaned;
elseif strcmp(useType,’diffs’)
fullmatrix = rateObj.diffsChronCleaned;
elseif strcmp(useType,’loggains’)
fullmatrix = rateObj.loggainsChronCleaned;
elseif strcmp(useType,’rates’)
fullmatrix = rateObj.ratesChronCleaned;
else
error([’Uknown type ’ useType]);
end
period = rateObj.period;
%This contains the number of retained eigenvalues
noEigValues = 6;
%The length of the period for which the correlation matrix is built
periodLen = 251*periodLenInYears;
noSecurities = size(fullmatrix,2);
%Determine the counterMax from the periodLength
%counterMax will be the number of samples we make
%Generally we will make a sample each month
counterMax = numel(getDateIntervals(period.startYear,period.startMonth,period.endYear,period.endMonth));
%The sliding window should be subtracted
counterMax = counterMax - periodLenInYears*12;
%Time scale is vertical, eigenvalues are flipped horizontal
eigvalEvolution = zeros(counterMax, noEigValues+1);
%Keep a copy of the first eigenvector throughout the whole
%evolution
eigvecEvolutionFull = zeros(counterMax, noSecurities);
dates=Rates.loadTradingDaysChron(period);
%Timescale will be vertical
dateTicks=zeros(counterMax,1);
%Will contain the first eigenvector for each time span
disp(’**** Now starting the evolution analysis **** ’)
fprintf([’Running up to ’ num2str(counterMax-1) ’: ’]);
for i=0:counterMax-1
fprintf([num2str(i) ’ ’]);
%%
%first day in the period for this loop
startNo = 1+i*21;
%last day in the period for this loop
endNo = startNo + periodLen;
%We use the last date of the period as tick
dateTicks(i+1) = dates(endNo);
slidingData=fullmatrix(startNo:endNo,:);
if useCovariance
cotemp = cov(slidingData);
else
cotemp = corr(slidingData);
end
[eigvec2,eigval2] = Utils.eig2(cotemp);
eigvalEvolution(i+1,2:end) = transpose(eigval2(1:noEigValues));
%eigvalEvolution(i+1,1) = sum(eigval2);
eigvecEvolutionFull(i+1,:) = Analysis.normalizeFirstEigvec(transpose(eigvec2(:,1)));
end
%Now make the analysis of the eigenvector evolution
eigvecEvolutionMean = mean(eigvecEvolutionFull,1);
%Keep track of the projection of the first eigenvector against
%itself in the preceeding period
eigvecEvolutionDelta = zeros(counterMax,1);
%Keep track of the distance from the mean
eigvecEvolutionDiffusion = zeros(counterMax,1);
for i=1:counterMax
eigVec = transpose(eigvecEvolutionFull(i,:));
if i==1
eigvecEvolutionDelta(i,1)=1;
else
eigVecPreceeding = eigvecEvolutionFull(i-1,:);
eigvecEvolutionDelta(i,1)=Analysis.project(eigVecPreceeding,eigVec);
end
eigvecEvolutionDiffusion(i,1) = Analysis.project(eigvecEvolutionMean,eigVec);
end
analysis.eigvecEvolutionDelta=eigvecEvolutionDelta;
analysis.eigvecEvolutionDiffusion=eigvecEvolutionDiffusion;
analysis.eigvalEvolution=eigvalEvolution;
analysis.dates=dates;
analysis.dateTicks = dateTicks;
analysis.rateObj = rateObj;
analysis.eigvecEvolutionFull=eigvecEvolutionFull;
analysis.periodLenInYears = periodLenInYears;
disp(’Done’);
%analysis.title = [Utils.either(useCovariance,’covariance’,’correlation’) ’ of ’ useType ’ ’ Utils.formatPeriod(period) ’ (sliding window=’ num
analysis.title = [Utils.formatPeriod(period) ’ (sliding window=’ num2str(periodLenInYears) ’y)’];
Analysis.eigenEvolutionPlot(analysis, figNo);
end
79
function analysis=eigenEvolutionTotal(rateObj)
analysis = Analysis.eigenEvolution(rateObj,4,1,true,’gains’);
Utils.saveFigures(1:3,[’Evolution-’ analysis.rateObj.name ’-’ num2str(analysis.periodLenInYears) ’y’]);
end
function eigenEvolutionPlot(analysis,figNo)
%%
figure(figNo);
plot(analysis.dateTicks,analysis.eigvalEvolution);
mytitle = [’Eigenvalue evolution of ’ analysis.title];
title(mytitle);
datetick(’x’,’yyyy-mm’);
zoomAdaptiveDateTicks(’on’);
%%
figure(figNo+1);
plot(analysis.dateTicks,transpose(analysis.eigvecEvolutionDelta));
mytitle = [’Eigenvector delta of ’ analysis.title];
title(mytitle);
datetick(’x’,’yyyy-mm’);
zoomAdaptiveDateTicks(’on’);
%%
figure(figNo+2);
plot(analysis.dateTicks,transpose(analysis.eigvecEvolutionDiffusion));
mytitle = [’Eigenvector diffusion of ’ analysis.title];
title(mytitle);
datetick(’x’,’yyyy-mm’);
zoomAdaptiveDateTicks(’on’);
end
function p = project(eigvec1,eigvec2)
%%
%Finds the projection of eigvec1 against eigvec2. If either eigvec1 or eigvec2
%is found to point in the "opposite" direction they are
%reversed to the same direction. This is done by taking the
%absolute value of eigvec1*eigvec2
p = abs(eigvec1*eigvec2);
end
function result = normalizeFirstEigvec(eigvec)
%Normalizes the first eigenvector in the sense that the
%direction of the vector is changed to have dominating positive
%values. If the eigenvector is mixed positive and negative this
%does not make fully sense, but often the first eigenvector in
%a financial market is dominated by either positive or negative
%coordinates, not mixed
noPositive = sum(arrayfun(@(x)x>0,eigvec));
if noPositive<numel(eigvec)/2
result = -1 * eigvec;
else
result = eigvec;
end
end
end
end
80