├── LICENSE ├── README.md ├── _config.yml ├── advanced-portfolio-construction-and-analysis-with-python ├── articles │ ├── A STEP-BY-STEP GUIDE TO THE BLACK-LITTERMAN MODEL.pdf │ ├── ARCH & GARCH models.pdf │ ├── Black-Litterman Model - UC Berkeley Statistics.pdf │ ├── COMPARISON OF OPTIMAL PORTFOLIO PERFORMANCES OF THREE OPTIMIZATION METHODS.pdf │ ├── EDHEC_Publication_Alternative_Equity_Beta_Investing_Survey.pdf │ ├── Factor Models.pdf │ ├── Heuristic_diversification.pdf │ ├── Honey, I Shrunk the Sample Covariance Matrix.pdf │ ├── The Intuition Behind Black-Litterman Model Portfolios.pdf │ ├── USING EVMA AND GARCH METHODS IN VAR CALCULATIONS.pdf │ ├── black_litterman_vs_markowitz_site_rationnel.pdf │ ├── factor-investing_balanced-portfolios.pdf │ └── summary.pdf ├── data │ ├── BRK-A.csv │ ├── F-F_Research_Data_Factors.CSV │ ├── F-F_Research_Data_Factors_daily.CSV │ ├── F-F_Research_Data_Factors_m.csv │ ├── Portfolios_Formed_on_ME_monthly_EW.csv │ ├── brka_d_ret.csv │ ├── edhec-hedgefundindices.csv │ ├── ind30_m_ew_rets.csv │ ├── ind30_m_nfirms.csv │ ├── ind30_m_size.csv │ ├── ind30_m_vw_rets.csv │ ├── ind49_m_ew_rets.csv │ ├── ind49_m_nfirms.csv │ ├── ind49_m_size.csv │ ├── ind49_m_vw_rets.csv │ └── sample_prices.csv ├── edhec_risk_kit.py ├── estimating-covariance-and-expected-returns.ipynb ├── factor-analysis-using-the-CAPM-and-Fama-French-Factor-models.ipynb ├── reproducing-the he-litterman-1999-results-in-python.ipynb └── risk-contributions-and-risk-parity.ipynb ├── implementing-graph-theory-with-NetworkX-and-Python ├── Generate random graphs.ipynb ├── Load graphs from Excel.ipynb ├── Manipulate nodes and edges attr.ipynb ├── Nodes and edges from graphs.ipynb ├── Summarize graphs through centrality metrics.ipynb ├── Visualize graphs with options and layouts.ipynb └── Visualize sub-graphs.ipynb ├── portfolio-construction-and-analysis-with-python ├── GHP-construction-with-duration-matching.ipynb ├── analysing-returns.ipynb ├── articles │ ├── Cornish Fisher expansion.png │ ├── Deviation from normality and Sharpe ratio behavior.pdf │ ├── Kurtosis as Peakedness.pdf │ ├── Liability-Driven-Investing-Technical-supplement.pdf │ ├── Liability-Driven-Investing.pdf │ ├── Measures of Skewness and Kurtosis.pdf │ ├── Portfolio Selection Harry Markowitz.pdf │ ├── Why Does an Equal-Weighted Portfolio Outperform Value- and Price-Weighted Portfolios.pdf │ ├── llustration-of-skewness-and-kurtosis.png │ └── value-at-risk-var-intro-7-728.jpg ├── asset-liability-management.ipynb ├── data │ ├── BRK-A.csv │ ├── F-F_Research_Data_Factors.CSV │ ├── F-F_Research_Data_Factors_daily.CSV │ ├── F-F_Research_Data_Factors_m.csv │ ├── Portfolios_Formed_on_ME_monthly_EW.csv │ ├── brka_d_ret.csv │ ├── edhec-hedgefundindices.csv │ ├── ind30_m_ew_rets.csv │ ├── ind30_m_nfirms.csv │ ├── ind30_m_size.csv │ ├── ind30_m_vw_rets.csv │ ├── ind49_m_ew_rets.csv │ ├── ind49_m_nfirms.csv │ ├── ind49_m_size.csv │ ├── ind49_m_vw_rets.csv │ └── sample_prices.csv ├── edhec_risk_kit.py ├── monte-carlo-simulation-of-dynamic-risk-budgeting-between-PSP-and-GHP.ipynb ├── monte-carlo-simulations-of-CPPI-and-diversification.ipynb └── portfolio-optimization.ipynb └── stock-price-analysis-with-spark ├── AMZN.csv ├── GOOG.csv ├── TSLA.csv └── amzn-goog-tsla-stock-price-analysis.ipynb /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # finance-and-risk-management 2 | 3 | _notes and practical hands-on applications for risk management through computational portfolio construction methods_ 4 | 5 | ![](https://i.imgur.com/k5pWGJD.jpg) 6 | 7 | ## REPOS 8 | ____________ 9 | 10 | ### [AMZN, GOOG and TSLA Stock Price Analysis with SparkSQL](https://github.com/salimt/finance-and-risk-management/tree/master/stock-price-analysis-with-spark) 11 | ____________ 12 | 13 | ### [Portfolio Construction and Analysis with Python](https://github.com/salimt/finance-and-risk-management/tree/master/portfolio-construction-and-analysis-with-python) 14 | 15 | **Topics**: 16 | 1. Returns and Value at Risk 17 | 2. Portfolio Optimization 18 | 3. Beyond diversification 19 | 4. Asset-Liability Management 20 | 21 | ____________ 22 | 23 | ### [Advanced Portfolio Construction and Analysis with Python](https://github.com/salimt/finance-and-risk-management/tree/master/advanced-portfolio-construction-and-analysis-with-python) 24 | 25 | **Topics**: 26 | 1. Style & Factors 27 | 2. Robust estimates for the covariance matrix 28 | 3. Robust estimates for expected returns 29 | 4. Portfolio optimization in practice 30 | 31 | ____________ 32 | 33 | ### [Implementing Graph Theory with NetworkX and Python](https://github.com/salimt/finance-and-risk-management/tree/master/implementing-graph-theory-with-NetworkX-and-Python) 34 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-dinky -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/A STEP-BY-STEP GUIDE TO THE BLACK-LITTERMAN MODEL.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/A STEP-BY-STEP GUIDE TO THE BLACK-LITTERMAN MODEL.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/ARCH & GARCH models.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/ARCH & GARCH models.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/Black-Litterman Model - UC Berkeley Statistics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/Black-Litterman Model - UC Berkeley Statistics.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/COMPARISON OF OPTIMAL PORTFOLIO PERFORMANCES OF THREE OPTIMIZATION METHODS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/COMPARISON OF OPTIMAL PORTFOLIO PERFORMANCES OF THREE OPTIMIZATION METHODS.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/EDHEC_Publication_Alternative_Equity_Beta_Investing_Survey.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/EDHEC_Publication_Alternative_Equity_Beta_Investing_Survey.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/Factor Models.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/Factor Models.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/Heuristic_diversification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/Heuristic_diversification.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/Honey, I Shrunk the Sample Covariance Matrix.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/Honey, I Shrunk the Sample Covariance Matrix.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/The Intuition Behind Black-Litterman Model Portfolios.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/The Intuition Behind Black-Litterman Model Portfolios.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/USING EVMA AND GARCH METHODS IN VAR CALCULATIONS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/USING EVMA AND GARCH METHODS IN VAR CALCULATIONS.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/black_litterman_vs_markowitz_site_rationnel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/black_litterman_vs_markowitz_site_rationnel.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/factor-investing_balanced-portfolios.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/factor-investing_balanced-portfolios.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/articles/summary.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/advanced-portfolio-construction-and-analysis-with-python/articles/summary.pdf -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/data/edhec-hedgefundindices.csv: -------------------------------------------------------------------------------- 1 | date,Convertible Arbitrage,CTA Global,Distressed Securities,Emerging Markets,Equity Market Neutral,Event Driven,Fixed Income Arbitrage,Global Macro,Long/Short Equity,Merger Arbitrage,Relative Value,Short Selling,Funds Of Funds 2 | 31/01/1997,1.19,3.93,1.78,7.91,1.89,2.13,1.91,5.73,2.81,1.50,1.80,-1.66,3.17 3 | 28/02/1997,1.23,2.98,1.22,5.25,1.01,0.84,1.22,1.75,-0.06,0.34,1.18,4.26,1.06 4 | 31/03/1997,0.78,-0.21,-0.12,-1.20,0.16,-0.23,1.09,-1.19,-0.84,0.60,0.10,7.78,-0.77 5 | 30/04/1997,0.86,-1.70,0.30,1.19,1.19,-0.05,1.30,1.72,0.84,-0.01,1.22,-1.29,0.09 6 | 31/05/1997,1.56,-0.15,2.33,3.15,1.89,3.46,1.18,1.08,3.94,1.97,1.73,-7.37,2.75 7 | 30/06/1997,2.12,0.85,2.17,5.81,1.65,2.58,1.08,2.18,2.23,2.31,1.98,-0.65,2.25 8 | 31/07/1997,1.93,5.91,2.34,5.60,2.47,3.07,0.95,7.38,4.54,2.00,1.81,-4.29,4.35 9 | 31/08/1997,1.34,-4.73,1.47,-0.66,0.17,0.71,0.87,-1.80,1.07,0.79,1.03,-0.72,0.51 10 | 30/09/1997,1.22,1.98,3.50,2.29,2.02,3.29,1.19,2.90,4.29,1.97,1.83,-1.55,3.34 11 | 31/10/1997,1.00,-0.98,-0.64,-5.72,0.95,0.61,-0.32,-1.42,0.10,0.94,0.79,5.72,-0.99 12 | 30/11/1997,0.00,1.33,0.54,-3.78,0.41,1.34,0.53,1.06,-0.26,2.23,1.11,2.17,-0.34 13 | 31/12/1997,0.68,2.86,0.73,1.60,0.66,1.54,0.79,2.64,1.04,1.58,0.82,1.61,0.89 14 | 31/01/1998,1.45,1.04,0.95,-4.29,0.60,0.55,-0.26,-0.50,0.13,0.55,1.32,0.14,-0.36 15 | 28/02/1998,1.46,-0.65,2.27,3.39,1.35,2.94,0.98,1.28,3.42,2.12,1.30,1.55,2.56 16 | 31/03/1998,1.44,1.22,2.52,3.18,1.79,2.63,1.28,5.70,3.36,1.64,1.45,6.37,3.73 17 | 30/04/1998,1.26,-2.96,1.65,0.41,0.67,1.04,0.75,0.34,1.20,1.39,1.45,6.57,1.25 18 | 31/05/1998,0.56,1.93,0.06,-8.25,0.80,-0.83,0.40,0.95,-0.87,-0.09,0.53,14.37,-0.72 19 | 30/06/1998,-0.06,0.51,-0.47,-4.22,1.08,0.02,-0.80,1.20,1.67,0.72,0.26,-0.53,0.21 20 | 31/07/1998,0.60,-0.10,-0.69,0.19,0.12,-0.37,1.06,0.58,-0.06,0.07,0.11,3.43,-0.07 21 | 31/08/1998,-3.19,6.91,-8.36,-19.22,-1.07,-8.86,-1.43,-2.63,-5.52,-5.44,-3.41,24.63,-6.16 22 | 30/09/1998,-1.96,4.54,-2.15,-3.95,0.61,-1.10,-3.62,-0.59,2.06,0.76,0.05,-3.76,-0.37 23 | 31/10/1998,-2.14,0.04,-0.29,1.40,0.52,0.91,-8.01,-2.23,1.69,1.59,-1.40,-10.77,-0.02 24 | 30/11/1998,2.69,-0.89,1.64,4.30,1.58,2.44,0.52,1.94,2.91,2.20,1.98,-7.56,2.20 25 | 31/12/1998,1.13,2.21,1.08,-0.98,2.09,2.19,1.20,2.33,4.08,2.24,1.64,-5.31,2.22 26 | 31/01/1999,2.19,-1.67,1.81,-1.20,1.01,2.01,1.58,0.86,2.58,1.12,1.95,-6.65,2.02 27 | 28/02/1999,0.82,1.97,-0.21,1.02,0.23,-0.42,2.08,-1.11,-1.69,0.36,0.85,8.33,-0.63 28 | 31/03/1999,1.36,-0.65,1.59,5.85,0.33,1.93,1.60,0.24,2.29,1.33,1.16,-1.54,2.13 29 | 30/04/1999,2.43,2.10,4.18,6.30,1.07,4.29,1.06,3.29,3.12,2.18,2.38,-3.75,4.00 30 | 31/05/1999,1.66,-1.50,2.07,0.61,0.89,2.15,0.72,-0.55,0.95,2.10,1.46,0.09,1.19 31 | 30/06/1999,1.02,2.34,2.73,6.54,1.68,2.97,0.88,2.14,3.15,2.22,1.48,-4.12,2.82 32 | 31/07/1999,1.01,-0.51,0.84,-0.61,1.35,0.96,0.51,-0.18,1.77,1.47,1.10,0.92,0.88 33 | 31/08/1999,0.48,-0.27,0.20,-1.47,0.95,-0.27,-0.28,-0.61,0.22,0.50,0.62,4.68,0.28 34 | 30/09/1999,0.96,0.64,-0.41,-0.69,0.95,0.90,0.92,-0.02,1.13,1.16,1.05,4.01,0.52 35 | 31/10/1999,0.45,-3.54,0.27,2.88,0.66,0.54,0.87,0.73,2.12,0.96,0.70,-1.30,1.30 36 | 30/11/1999,1.24,1.66,2.20,6.92,1.33,2.84,1.06,4.05,4.81,2.37,1.37,-12.39,4.83 37 | 31/12/1999,1.40,1.42,3.00,12.30,1.98,2.86,0.97,6.12,7.45,0.90,1.83,-11.37,6.22 38 | 31/01/2000,2.27,1.28,0.88,0.77,0.75,0.88,0.41,0.21,0.75,1.43,1.73,4.27,1.69 39 | 29/02/2000,2.67,-0.22,4.21,5.28,2.53,3.46,0.97,4.08,6.99,2.39,1.85,-13.40,6.66 40 | 31/03/2000,2.43,-1.38,1.03,3.18,1.34,0.69,-0.61,-1.04,0.06,1.31,1.63,-2.30,0.39 41 | 30/04/2000,2.23,-2.41,-1.01,-5.41,1.68,-0.59,-0.06,-3.04,-2.01,1.88,0.92,10.28,-2.69 42 | 31/05/2000,1.49,1.14,-1.32,-4.33,0.62,-0.34,1.07,-0.70,-0.97,1.46,0.80,7.04,-1.22 43 | 30/06/2000,1.79,-1.24,2.03,3.34,1.71,2.68,0.58,1.54,3.49,1.67,1.76,-11.07,3.11 44 | 31/07/2000,0.93,-1.31,0.64,0.25,0.63,0.57,0.18,0.37,0.06,1.16,0.84,5.53,-0.22 45 | 31/08/2000,1.62,1.89,1.40,3.68,2.10,1.73,1.07,2.48,3.45,1.57,1.57,-11.35,2.67 46 | 30/09/2000,1.41,-2.08,-0.19,-4.62,0.58,0.48,0.76,-1.49,-0.16,1.37,0.75,12.04,-0.69 47 | 31/10/2000,0.52,0.75,-0.73,-2.56,0.40,-0.68,0.06,-0.24,-0.84,0.26,-0.04,7.84,-1.04 48 | 30/11/2000,-0.81,4.25,-2.09,-3.85,0.45,-1.36,0.66,1.25,-1.53,1.02,0.06,16.57,-2.05 49 | 31/12/2000,-0.02,6.82,0.01,1.16,1.60,1.27,0.48,4.72,2.48,1.25,0.75,0.63,1.33 50 | 31/01/2001,3.44,0.25,3.08,5.86,0.75,2.98,1.63,2.14,1.65,1.11,3.33,-2.71,2.23 51 | 28/02/2001,1.82,-0.16,1.00,-2.21,1.20,0.45,0.54,-0.72,-2.64,0.54,0.30,10.21,-0.89 52 | 31/03/2001,1.62,4.38,-0.37,-1.75,1.08,-0.42,0.51,0.38,-1.99,-0.61,-0.11,6.20,-0.68 53 | 30/04/2001,1.57,-3.62,0.48,1.14,0.75,1.10,0.94,0.49,2.46,0.58,1.74,-9.91,1.04 54 | 31/05/2001,0.33,0.81,2.35,2.78,0.77,1.85,0.68,0.32,0.43,1.61,1.41,-1.30,0.80 55 | 30/06/2001,0.12,-0.77,3.60,1.60,0.17,0.63,0.17,0.17,0.19,-0.87,0.19,1.10,0.13 56 | 31/07/2001,0.91,-0.40,0.73,-2.86,0.31,0.49,0.54,-0.40,-1.44,0.79,0.10,3.53,-0.40 57 | 31/08/2001,1.42,1.53,1.06,0.30,0.94,0.90,1.05,0.06,-0.96,0.99,-0.31,7.52,0.19 58 | 30/09/2001,0.78,2.46,-0.14,-4.25,0.23,-2.54,-0.13,-0.70,-3.48,-2.67,-2.21,9.41,-1.42 59 | 31/10/2001,1.17,3.36,1.03,2.78,0.58,1.48,1.34,2.08,0.99,0.85,1.64,-2.98,0.95 60 | 30/11/2001,0.80,-5.43,0.86,4.83,0.55,1.05,-0.24,0.21,2.00,0.14,1.36,-6.55,0.58 61 | 31/12/2001,-0.94,1.48,0.15,4.21,0.56,1.07,0.53,1.38,1.80,0.45,0.97,-2.51,0.99 62 | 31/01/2002,1.48,-0.72,1.86,2.73,0.65,0.78,0.86,0.69,-0.37,0.77,0.97,3.43,0.30 63 | 28/02/2002,-0.49,-2.02,-0.33,1.81,-0.07,-0.71,0.56,-0.35,-1.23,-0.44,-0.11,3.90,-0.15 64 | 31/03/2002,0.53,0.09,0.52,3.31,0.47,1.53,0.45,0.64,1.55,0.73,1.45,-4.46,0.90 65 | 30/04/2002,0.96,-1.04,1.39,1.44,0.76,0.46,1.13,0.98,-0.42,-0.13,0.70,4.83,0.52 66 | 31/05/2002,0.33,2.70,0.91,0.01,0.53,0.01,0.99,1.23,-0.34,0.00,0.31,3.46,0.50 67 | 30/06/2002,0.04,6.55,-1.17,-2.92,0.22,-2.83,0.69,-0.22,-2.49,-1.70,-1.07,5.48,-0.95 68 | 31/07/2002,-1.59,4.13,-1.33,-3.09,-0.13,-3.00,0.57,-0.78,-3.89,-1.74,-1.85,6.44,-1.40 69 | 31/08/2002,0.50,2.20,0.09,1.19,0.69,0.60,0.97,0.63,0.41,0.61,0.58,0.15,0.37 70 | 30/09/2002,1.46,2.84,-0.44,-2.52,0.15,-0.70,-0.33,0.54,-1.60,-0.28,-1.10,7.31,-0.33 71 | 31/10/2002,1.04,-3.76,-0.31,1.54,0.16,0.31,-0.63,-0.86,1.23,0.32,0.84,-4.05,-0.31 72 | 30/11/2002,2.51,-1.64,2.39,1.90,0.25,2.16,0.54,0.47,2.24,0.54,1.85,-5.47,1.06 73 | 31/12/2002,1.57,4.89,2.22,0.48,0.94,0.44,1.53,1.92,-1.49,0.46,0.23,4.43,0.77 74 | 31/01/2003,2.83,4.41,2.43,0.12,0.83,1.54,1.06,1.82,0.05,0.40,0.67,1.62,0.72 75 | 28/02/2003,1.33,4.02,0.92,0.84,0.24,0.26,0.79,1.66,-0.37,0.18,-0.04,1.30,0.31 76 | 31/03/2003,0.89,-4.45,1.13,0.19,0.15,0.83,0.19,-1.22,0.20,-0.07,0.49,-0.75,-0.04 77 | 30/04/2003,1.50,0.65,3.45,4.50,0.31,2.72,0.91,1.17,2.98,0.99,1.86,-6.56,1.34 78 | 31/05/2003,1.36,4.90,2.70,4.33,1.07,3.01,2.07,3.97,3.62,1.54,2.12,-4.99,2.05 79 | 30/06/2003,-0.58,-1.92,2.67,2.68,0.34,1.81,0.44,0.56,1.28,0.48,0.71,-1.62,0.68 80 | 31/07/2003,-0.72,-1.71,1.17,1.04,-0.06,1.19,-0.92,-0.35,1.18,0.53,0.41,-3.61,0.25 81 | 31/08/2003,-0.87,0.78,1.37,3.74,0.31,1.33,0.43,2.02,1.79,0.70,0.58,-3.54,0.78 82 | 30/09/2003,1.71,-0.19,2.42,2.64,0.78,1.33,1.05,2.15,0.94,0.77,0.86,1.36,1.21 83 | 31/10/2003,1.46,1.04,2.67,2.59,1.15,1.91,0.35,1.11,2.99,1.11,1.59,-6.56,1.52 84 | 30/11/2003,0.92,0.18,1.54,0.96,0.46,1.16,0.69,0.31,1.30,0.44,1.02,-1.36,0.70 85 | 31/12/2003,0.54,3.81,1.98,4.03,0.54,1.72,1.01,2.93,1.91,0.98,1.27,-1.78,1.39 86 | 31/01/2004,1.19,1.99,3.01,2.51,1.09,2.34,0.92,1.17,1.92,0.97,1.46,-0.90,1.56 87 | 29/02/2004,0.17,5.29,0.75,2.53,0.63,1.13,0.84,1.50,1.23,0.51,0.57,0.18,1.11 88 | 31/03/2004,0.61,-0.51,0.46,1.72,0.32,0.16,0.03,0.64,0.41,0.17,0.38,-1.48,0.43 89 | 30/04/2004,0.20,-5.32,0.93,-2.52,-0.82,0.02,0.62,-1.78,-1.65,-0.39,-0.45,3.84,-0.68 90 | 31/05/2004,-1.28,-1.18,-0.10,-1.81,0.24,-0.23,0.40,-0.81,-0.35,0.00,-0.37,-0.24,-0.82 91 | 30/06/2004,-1.06,-3.16,2.02,0.20,0.42,1.13,0.55,-0.19,0.91,0.17,0.22,-0.51,0.34 92 | 31/07/2004,0.13,-1.19,0.19,-0.27,0.06,-0.82,0.62,-0.14,-1.54,-0.92,0.07,6.38,-0.49 93 | 31/08/2004,0.40,-0.84,0.88,1.33,-0.09,0.35,0.36,-0.39,-0.22,0.11,0.31,1.26,-0.10 94 | 30/09/2004,-0.17,2.20,1.04,2.80,0.85,1.03,0.12,0.08,2.10,0.42,0.52,-2.16,0.99 95 | 31/10/2004,-0.44,3.58,1.43,1.85,-0.05,1.24,0.28,1.38,0.74,0.74,0.40,-0.92,0.68 96 | 30/11/2004,0.81,4.75,3.37,3.28,1.40,3.06,0.75,2.80,3.08,1.64,1.49,-5.74,2.44 97 | 31/12/2004,0.56,0.00,2.66,2.01,0.58,2.44,0.60,0.33,1.78,1.33,0.99,-3.91,1.45 98 | 31/01/2005,-0.96,-4.38,0.37,1.43,0.81,0.04,0.44,-0.47,-0.17,0.00,0.12,3.87,0.06 99 | 28/02/2005,-0.58,0.05,1.34,3.46,0.80,1.44,0.85,1.71,2.10,0.65,0.81,1.18,1.36 100 | 31/03/2005,-1.40,-0.06,0.32,-1.97,0.19,-0.04,0.24,-0.27,-0.96,0.32,-0.42,2.44,-0.44 101 | 30/04/2005,-3.16,-3.54,-0.52,-0.49,-0.30,-1.28,-0.03,-0.80,-1.84,-1.05,-1.08,3.93,-1.41 102 | 31/05/2005,-1.33,2.32,0.06,0.72,0.47,0.65,-0.10,0.88,1.15,0.95,-0.02,-4.75,0.18 103 | 30/06/2005,1.07,2.60,1.33,1.60,0.81,1.33,0.10,1.16,1.95,0.85,0.95,-0.32,1.31 104 | 31/07/2005,1.64,-0.13,1.73,2.57,0.78,2.15,0.81,1.19,2.65,1.15,1.49,-2.42,1.34 105 | 31/08/2005,0.66,1.00,1.24,1.52,0.62,0.92,0.36,0.83,0.97,0.61,0.53,2.59,0.79 106 | 30/09/2005,1.42,0.79,1.12,4.02,0.87,1.00,0.62,2.69,2.22,0.35,1.22,1.98,1.47 107 | 31/10/2005,-0.15,-0.92,-0.32,-2.30,0.01,-1.73,0.57,-0.74,-1.74,-1.45,-0.38,2.33,-1.49 108 | 30/11/2005,0.04,3.79,1.00,2.79,0.61,1.25,0.15,1.64,2.11,1.12,0.67,-3.00,1.60 109 | 31/12/2005,0.92,-1.53,1.22,2.84,0.68,1.42,0.54,1.35,2.49,1.38,1.26,-0.35,1.91 110 | 31/01/2006,2.50,1.74,2.53,5.26,1.15,3.41,0.93,2.58,3.81,2.72,2.38,-2.88,2.86 111 | 28/02/2006,1.16,-1.86,0.65,1.61,0.46,0.51,0.41,0.02,0.16,1.04,0.73,0.64,0.37 112 | 31/03/2006,1.07,2.84,1.72,1.22,0.98,1.85,0.55,0.94,2.38,1.44,1.57,-1.39,1.64 113 | 30/04/2006,0.64,3.87,1.93,3.65,1.02,1.64,1.21,2.38,1.72,1.19,1.26,-0.12,1.71 114 | 31/05/2006,0.91,-1.46,0.86,-3.89,0.02,0.08,0.59,-1.55,-2.48,0.09,-0.25,2.46,-1.33 115 | 30/06/2006,0.12,-1.42,-0.15,-0.97,0.63,0.12,0.36,-0.15,-0.62,0.87,0.21,1.18,-0.28 116 | 31/07/2006,0.66,-2.16,0.09,0.67,0.51,-0.11,0.64,0.06,-0.31,0.58,0.17,1.73,-0.05 117 | 31/08/2006,0.98,0.20,0.99,1.33,-0.09,1.12,0.37,-0.39,1.14,0.53,0.92,-1.56,0.66 118 | 30/09/2006,0.93,-0.55,0.33,0.11,0.09,0.35,0.14,-0.67,0.05,0.41,0.40,-2.36,-0.03 119 | 31/10/2006,0.54,1.02,1.94,2.57,0.65,2.06,0.67,0.97,1.94,1.32,1.32,-3.80,1.63 120 | 30/11/2006,0.92,2.26,1.79,3.23,0.75,1.82,0.60,1.99,2.00,1.42,1.29,-2.68,1.85 121 | 31/12/2006,1.27,1.46,1.65,2.91,1.07,1.68,0.72,1.16,1.53,1.33,1.28,0.39,1.75 122 | 31/01/2007,1.30,1.13,1.50,0.79,0.83,2.01,0.69,0.61,1.21,1.91,1.35,-1.07,1.21 123 | 28/02/2007,1.17,-1.44,1.45,1.00,0.51,2.07,1.06,0.18,0.82,2.55,1.14,0.28,0.96 124 | 31/03/2007,0.60,-1.41,1.08,1.85,1.01,1.46,0.60,0.27,1.15,0.63,0.81,-0.51,0.96 125 | 30/04/2007,0.26,2.41,1.64,2.55,0.89,1.97,0.71,1.52,1.98,1.60,1.34,-2.65,1.63 126 | 31/05/2007,1.10,2.30,1.80,2.70,1.21,2.13,0.55,1.92,2.24,1.71,1.56,-1.99,2.04 127 | 30/06/2007,0.11,2.29,0.27,2.36,0.77,-0.07,0.48,1.07,0.77,-0.53,1.00,2.36,0.82 128 | 31/07/2007,-0.53,-1.22,-0.56,2.75,0.51,-0.32,0.07,1.16,0.09,-0.54,0.04,4.86,0.41 129 | 31/08/2007,-1.45,-2.80,-1.18,-2.74,-0.94,-1.44,-0.48,-1.16,-1.60,0.01,-0.77,0.92,-2.22 130 | 30/09/2007,1.61,4.69,0.95,4.28,1.23,1.34,1.64,3.30,2.56,1.31,1.53,-2.07,1.99 131 | 31/10/2007,1.77,2.80,1.75,4.85,1.68,2.14,1.14,3.04,2.81,1.91,2.00,-0.26,3.03 132 | 30/11/2007,-1.31,-0.16,-1.69,-2.37,-0.18,-2.02,-0.94,-0.63,-2.25,-1.49,-1.12,7.19,-1.48 133 | 31/12/2007,-0.77,1.17,0.02,1.30,0.54,0.07,0.36,1.04,0.43,-0.25,0.22,0.56,0.40 134 | 31/01/2008,-0.09,2.55,-2.33,-5.03,-1.12,-2.71,-0.12,-0.10,-4.00,-1.26,-1.18,5.56,-2.72 135 | 29/02/2008,-0.83,6.20,0.14,2.80,1.20,0.84,-0.49,3.12,1.40,0.60,0.64,3.00,1.42 136 | 31/03/2008,-3.17,-0.56,-1.26,-3.79,-0.49,-1.68,-3.06,-1.69,-2.36,-0.45,-1.62,1.92,-2.62 137 | 30/04/2008,0.76,-0.78,0.88,1.90,0.59,1.18,1.87,0.78,2.23,1.49,1.30,-4.61,0.97 138 | 31/05/2008,1.07,1.62,1.37,1.63,1.26,1.76,1.03,1.14,2.27,1.36,1.59,-1.42,1.72 139 | 30/06/2008,-0.81,3.30,-0.31,-2.74,1.56,-1.13,-0.27,0.30,-1.64,-1.09,-0.84,7.51,-0.68 140 | 31/07/2008,-1.88,-3.33,-1.82,-3.30,-1.00,-1.66,-0.23,-2.13,-2.61,0.11,-1.25,0.72,-2.64 141 | 31/08/2008,-0.66,-1.14,-0.72,-3.36,-1.35,-0.25,-0.03,-1.33,-1.46,0.51,-0.23,-2.15,-1.56 142 | 30/09/2008,-10.27,0.10,-5.18,-9.82,-2.85,-6.27,-5.06,-3.13,-6.75,-2.76,-5.38,3.78,-6.18 143 | 31/10/2008,-12.37,3.45,-7.75,-13.31,-0.44,-6.25,-8.67,-1.57,-6.29,-2.45,-6.92,11.70,-6.00 144 | 30/11/2008,-2.76,2.14,-4.35,-3.91,-5.87,-3.01,-3.08,0.33,-1.88,0.06,-2.09,4.28,-1.92 145 | 31/12/2008,1.77,1.40,-1.97,-0.10,0.05,-0.71,-0.35,1.18,0.81,1.62,0.31,-1.46,-1.19 146 | 31/01/2009,4.91,-0.16,0.82,-1.12,0.79,1.32,1.12,0.29,-0.17,0.56,1.00,2.82,0.60 147 | 28/02/2009,1.64,-0.31,-1.22,-1.33,-0.46,-0.91,0.65,-0.55,-1.61,0.06,-0.16,3.28,-0.37 148 | 31/03/2009,2.35,-1.80,0.22,3.50,0.21,1.17,0.57,0.48,1.88,1.25,1.00,-4.62,0.08 149 | 30/04/2009,5.00,-1.40,3.87,6.63,-0.12,3.37,2.21,1.27,3.75,0.81,3.42,-8.20,0.92 150 | 31/05/2009,5.78,2.13,5.04,8.84,1.46,4.42,3.65,3.48,5.16,1.07,3.92,0.08,3.12 151 | 30/06/2009,2.41,-1.47,1.98,0.13,0.36,1.23,1.26,-0.76,0.09,1.04,1.01,-0.94,0.24 152 | 31/07/2009,6.11,-0.12,3.11,4.51,0.42,2.91,3.22,1.66,2.77,0.68,2.60,-5.96,1.53 153 | 31/08/2009,3.15,0.54,2.44,1.66,0.70,2.07,2.02,0.50,1.57,1.02,1.62,-1.65,1.13 154 | 30/09/2009,3.68,1.51,4.10,5.36,0.85,3.36,3.25,2.31,2.85,1.10,2.20,-3.94,1.71 155 | 31/10/2009,1.19,-1.47,1.39,1.08,-0.05,0.43,1.85,-0.04,-0.86,0.26,0.32,3.14,-0.21 156 | 30/11/2009,0.80,3.32,2.02,1.51,0.09,1.52,0.96,1.65,1.30,0.68,0.89,-2.27,0.82 157 | 31/12/2009,2.15,-2.53,3.24,2.29,0.72,2.35,1.41,-0.28,1.86,1.02,1.61,-3.73,0.66 158 | 31/01/2010,0.53,-2.78,1.87,-0.78,0.28,0.77,1.72,-0.84,-0.95,0.48,0.60,1.83,-0.36 159 | 28/02/2010,0.36,0.90,0.31,-0.19,0.50,0.76,0.23,0.47,0.84,0.57,0.57,-2.61,0.13 160 | 31/03/2010,2.29,2.75,3.36,4.21,0.77,2.73,1.36,1.71,2.87,1.09,1.79,-4.96,1.71 161 | 30/04/2010,1.99,1.00,2.51,1.33,0.18,1.64,1.13,0.76,1.00,0.38,1.22,-2.87,0.85 162 | 31/05/2010,-2.44,-2.48,-2.50,-4.80,-0.50,-2.57,-1.02,-1.28,-3.71,-1.15,-1.86,4.45,-2.72 163 | 30/06/2010,0.17,0.11,-1.05,-0.39,-0.45,-1.06,0.78,-0.23,-1.61,0.23,-0.34,4.19,-0.79 164 | 31/07/2010,2.27,-0.80,1.43,2.96,0.90,1.70,1.00,0.33,1.91,1.27,1.74,-4.26,0.69 165 | 31/08/2010,1.21,3.10,-0.49,0.28,-0.44,-0.32,0.88,1.08,-0.96,0.70,0.31,3.89,0.06 166 | 30/09/2010,1.89,2.67,2.17,4.29,1.60,2.72,1.32,2.63,4.08,1.34,2.15,-8.26,2.19 167 | 31/10/2010,2.14,3.11,2.06,2.32,1.05,1.87,1.07,1.59,2.08,0.47,1.49,-1.79,1.48 168 | 30/11/2010,-0.12,-2.24,0.65,-0.49,0.44,0.28,0.56,-0.47,0.66,-0.25,0.37,-1.62,-0.09 169 | 31/12/2010,1.45,4.36,3.11,2.26,0.94,2.60,0.55,2.50,3.42,1.16,1.57,-5.07,2.05 170 | 31/01/2011,1.81,-0.63,1.73,-0.65,0.56,1.41,1.81,-0.55,0.52,0.93,0.97,-0.76,0.13 171 | 28/02/2011,1.62,1.77,1.44,0.11,0.59,1.29,1.03,0.95,1.39,0.62,1.12,-3.14,0.83 172 | 31/03/2011,0.38,-1.64,0.43,1.54,0.80,0.20,0.22,-0.28,0.21,0.31,0.34,-1.70,-0.18 173 | 30/04/2011,0.20,3.67,1.29,1.40,1.05,1.14,0.97,2.11,1.39,0.89,0.72,-1.97,1.14 174 | 31/05/2011,-0.17,-3.39,-0.14,-1.91,-0.37,-0.52,0.33,-1.50,-1.08,-0.11,-0.05,1.34,-1.16 175 | 30/06/2011,-0.91,-2.39,-0.68,-1.00,-0.14,-1.38,-0.10,-1.30,-1.17,-0.14,-0.56,2.70,-1.38 176 | 31/07/2011,-0.33,2.58,-0.15,0.77,-0.03,-0.30,0.18,1.29,-0.30,-0.49,-0.06,1.99,0.34 177 | 31/08/2011,-1.95,0.07,-4.02,-3.90,-1.61,-4.01,-0.85,-0.63,-4.21,-1.19,-2.00,6.69,-2.52 178 | 30/09/2011,-1.90,-0.57,-3.70,-6.95,-1.59,-3.41,-0.48,-1.42,-4.61,-1.02,-1.97,7.77,-2.62 179 | 31/10/2011,1.29,-3.17,2.37,3.65,1.61,2.98,0.63,0.53,3.90,1.72,1.47,-7.21,0.94 180 | 30/11/2011,-0.94,0.14,-1.08,-2.72,0.02,-0.58,-0.34,-0.66,-1.31,0.17,-0.24,1.31,-0.93 181 | 31/12/2011,0.29,0.34,0.50,-1.81,0.06,-0.34,0.45,-0.22,-0.56,0.56,0.12,0.41,-0.54 182 | 31/01/2012,2.36,0.46,3.24,3.95,0.95,2.88,1.16,1.90,3.27,0.95,2.02,-6.79,1.47 183 | 29/02/2012,2.18,0.91,2.02,3.41,0.71,1.70,1.19,1.34,2.48,1.11,1.72,-5.22,1.40 184 | 31/03/2012,0.65,-2.04,0.91,-1.33,0.23,0.58,0.61,-0.61,0.33,0.24,0.55,-1.23,0.01 185 | 30/04/2012,-0.17,-0.03,-0.12,-0.27,-0.13,-0.18,0.34,-0.59,-0.68,-0.11,-0.20,0.57,-0.33 186 | 31/05/2012,-0.77,2.59,-1.86,-5.31,-1.15,-1.91,-0.03,-0.67,-3.75,-0.48,-1.00,6.77,-1.40 187 | 30/06/2012,0.72,-2.72,-0.09,0.26,0.06,0.07,0.46,-0.63,0.60,0.23,0.70,-2.58,-0.37 188 | 31/07/2012,0.92,3.12,0.89,0.81,0.41,0.48,1.25,1.44,0.39,0.06,1.17,0.87,0.76 189 | 31/08/2012,0.76,-0.82,1.61,0.75,0.49,1.29,0.82,0.37,1.08,0.44,0.95,-3.67,0.68 190 | 30/09/2012,0.57,-1.04,1.69,2.73,0.43,1.20,0.76,0.51,1.57,0.06,1.02,-3.85,0.73 191 | 31/10/2012,0.17,-3.10,1.18,0.28,0.28,0.48,0.58,-0.83,0.09,-0.79,0.30,0.05,-0.25 192 | 30/11/2012,0.41,-0.04,0.82,1.31,0.37,0.80,0.54,0.27,0.52,1.00,0.56,-1.50,0.46 193 | 31/12/2012,0.98,0.57,2.59,3.30,0.37,1.93,0.73,1.11,1.45,1.45,1.17,-3.87,1.08 194 | 31/01/2013,1.58,1.86,2.19,3.03,1.35,2.14,1.16,1.65,3.08,-0.16,2.04,-4.52,2.06 195 | 28/02/2013,0.09,-0.99,0.52,-0.12,0.33,0.41,0.56,-0.12,0.37,0.39,0.47,-0.35,0.32 196 | 31/03/2013,0.77,0.89,1.49,0.68,0.35,1.43,1.13,0.64,1.44,0.69,1.30,-1.89,0.93 197 | 30/04/2013,0.52,1.92,1.75,0.63,0.08,0.78,0.50,1.14,0.64,0.61,0.55,-2.86,0.76 198 | 31/05/2013,1.34,-2.61,2.23,0.33,0.24,1.87,0.50,-0.23,1.35,0.59,1.01,-2.45,0.67 199 | 30/06/2013,-0.81,-2.73,-1.05,-3.21,0.28,-1.13,-1.22,-1.76,-0.94,-0.22,-1.02,0.56,-1.33 200 | 31/07/2013,0.60,-0.76,1.40,0.75,1.00,1.49,0.67,0.16,2.15,1.03,1.17,-3.69,0.91 201 | 31/08/2013,0.46,-1.39,-0.34,-1.22,-0.59,-0.11,0.14,-0.91,-0.76,-0.01,-0.46,1.07,-0.68 202 | 30/09/2013,0.43,-0.57,1.64,2.35,0.63,1.60,0.47,0.69,2.33,0.84,1.40,-4.52,1.27 203 | 31/10/2013,0.95,1.45,1.61,2.38,1.42,1.45,0.85,0.94,2.04,0.45,1.45,-2.07,1.25 204 | 30/11/2013,0.07,1.14,1.22,0.30,1.05,1.19,0.67,0.69,1.54,0.30,0.87,-1.65,1.09 205 | 31/12/2013,0.48,0.52,1.20,1.01,0.76,1.22,0.40,0.65,1.57,0.61,1.02,-1.55,1.09 206 | 31/01/2014,1.37,-1.75,0.47,-1.95,0.42,0.30,0.75,-0.88,-0.32,0.46,0.02,0.94,-0.33 207 | 28/02/2014,0.62,1.37,2.43,1.90,0.66,2.23,0.99,0.90,2.53,1.10,1.49,-3.22,1.57 208 | 31/03/2014,0.47,-1.19,0.63,0.08,-0.05,-0.14,0.36,-0.54,-0.56,-0.50,0.28,0.00,-0.70 209 | 30/04/2014,0.29,0.50,0.25,0.04,-0.23,0.15,0.55,-0.23,-0.83,0.13,0.45,1.25,-0.71 210 | 31/05/2014,0.45,1.50,0.91,2.15,0.20,0.87,0.59,0.72,1.05,0.62,1.03,-1.68,1.14 211 | 30/06/2014,0.29,1.01,1.45,1.15,0.34,1.55,0.63,0.64,1.31,0.89,1.26,-2.64,0.91 212 | 31/07/2014,-0.01,-0.54,-0.59,0.40,-0.05,-0.70,0.25,-0.27,-0.90,-0.53,0.04,0.61,-0.40 213 | 31/08/2014,-0.03,2.83,-0.11,0.69,0.52,0.35,0.21,1.12,1.28,0.43,0.56,-1.70,0.80 214 | 30/09/2014,-0.95,1.79,-1.99,-1.56,0.15,-1.65,0.22,0.60,-0.93,-0.75,-0.05,2.42,-0.12 215 | 31/10/2014,-1.11,0.41,-1.68,-0.69,0.30,-1.52,-0.07,-0.41,-0.13,-1.36,-0.60,-2.36,-0.62 216 | 30/11/2014,-0.09,4.19,-0.34,-0.14,0.59,0.70,0.14,1.77,1.16,0.80,0.61,-0.61,1.26 217 | 31/12/2014,-0.66,0.88,-0.89,-2.20,0.13,-0.22,-0.35,-0.04,0.12,0.32,-0.16,0.33,0.21 218 | 31/01/2015,0.13,3.99,-1.55,-0.34,0.48,-1.04,-0.04,2.29,-0.09,0.04,0.25,1.09,0.17 219 | 28/02/2015,1.21,-0.29,1.85,1.62,0.20,2.70,0.86,0.70,2.52,1.39,1.50,-3.85,1.71 220 | 31/03/2015,0.21,0.97,0.28,0.39,0.80,0.43,0.21,1.01,0.36,0.56,0.33,0.06,0.69 221 | 30/04/2015,1.57,-2.32,0.71,3.78,-0.29,1.13,0.51,-0.91,0.55,0.66,0.69,-1.43,0.26 222 | 31/05/2015,0.46,-0.53,0.25,0.21,0.56,0.83,0.26,0.63,1.42,1.09,0.50,-0.96,0.97 223 | 30/06/2015,-0.86,-3.43,-1.59,-1.77,0.30,-1.24,-0.39,-1.76,-0.72,-0.50,-0.91,0.85,-1.08 224 | 31/07/2015,-0.58,2.09,-0.45,-1.97,0.37,-0.74,-0.05,1.46,0.31,0.03,0.03,0.46,0.22 225 | 31/08/2015,-0.45,-2.20,-2.27,-3.84,0.18,-2.49,-0.37,-1.31,-2.29,-0.56,-1.03,5.78,-2.02 226 | 30/09/2015,-0.63,1.46,-1.36,-1.55,0.63,-2.76,-0.54,-0.52,-1.42,-0.97,-0.72,1.56,-1.76 227 | 31/10/2015,1.23,-1.57,-0.10,3.13,0.57,1.45,-0.14,0.28,2.10,0.74,1.09,-5.19,0.83 228 | 30/11/2015,-0.39,2.19,-1.01,-0.39,0.00,-0.69,0.02,1.35,0.23,-0.01,0.00,-1.44,0.25 229 | 31/12/2015,-1.27,-1.84,-1.60,-0.62,0.29,-1.03,-0.28,-1.43,-0.49,1.24,-0.67,1.81,-0.59 230 | 31/01/2016,-2.39,2.29,-2.34,-4.07,-0.34,-2.88,-0.88,-0.04,-3.24,0.29,-1.37,7.46,-2.66 231 | 29/02/2016,-0.02,2.36,-1.29,-0.35,-0.86,-0.54,-0.62,0.20,-0.95,0.40,-0.38,1.40,-1.26 232 | 31/03/2016,1.70,-2.01,1.90,4.28,0.95,2.43,1.08,-0.43,1.84,0.58,1.56,-6.05,0.71 233 | 30/04/2016,1.40,-0.91,2.08,1.52,-0.60,1.61,1.33,0.20,0.34,-0.55,1.06,-2.00,0.53 234 | 31/05/2016,0.75,-1.76,1.35,-0.12,0.58,1.00,0.40,-0.37,1.06,0.72,0.64,-1.93,0.59 235 | 30/06/2016,0.16,3.52,0.82,1.49,-0.37,-0.12,-0.21,1.07,-0.93,-0.18,0.27,1.73,-0.74 236 | 31/07/2016,1.54,0.67,1.92,2.33,0.80,1.86,1.14,0.64,2.03,0.70,1.25,-5.92,1.34 237 | 31/08/2016,1.02,-2.25,2.09,1.69,-0.19,1.49,0.76,-0.61,0.62,0.82,0.64,-3.98,0.43 238 | 30/09/2016,0.70,-0.66,0.97,0.97,0.40,0.39,0.62,-0.28,0.64,0.41,0.56,-1.48,0.40 239 | 31/10/2016,0.27,-2.57,2.03,0.64,0.24,-0.15,0.63,0.14,-0.72,-0.62,0.52,2.11,-0.27 240 | 30/11/2016,0.31,-0.50,1.15,-1.26,0.13,1.40,0.25,0.88,0.79,0.97,0.31,-3.01,0.22 241 | 31/12/2016,0.90,0.58,1.84,0.35,0.33,1.53,0.85,1.21,0.87,0.88,0.94,-0.08,0.90 242 | 31/01/2017,1.47,-1.02,1.91,2.46,0.58,1.63,1.16,-0.13,1.28,-0.20,1.11,-3.56,0.95 243 | 28/02/2017,0.72,1.49,0.71,1.71,0.09,0.97,0.66,0.59,1.00,0.79,0.74,-6.72,0.80 244 | 31/03/2017,-0.02,-1.37,-0.84,1.05,0.58,0.16,0.29,-0.12,0.78,0.22,0.27,-2.71,0.41 245 | 30/04/2017,0.44,-0.17,0.51,1.09,0.32,0.98,0.30,-0.07,0.88,1.10,0.31,-1.65,0.57 246 | 31/05/2017,0.22,0.11,-0.48,0.18,-0.71,0.53,0.43,0.10,0.65,0.67,0.37,-1.21,0.33 247 | 30/06/2017,0.32,-2.22,0.28,0.61,0.22,0.17,0.28,-0.68,0.42,0.69,0.29,-3.02,-0.06 248 | 31/07/2017,0.84,0.94,1.17,2.35,0.78,1.00,0.50,0.58,1.20,0.59,0.66,-2.32,0.97 249 | 31/08/2017,-0.12,1.60,-0.04,1.48,0.58,-0.29,0.15,0.46,0.69,-0.04,0.26,-0.03,0.75 250 | 30/09/2017,0.65,-1.94,0.58,0.91,0.45,1.08,-0.33,-0.11,1.10,0.39,0.41,-6.52,0.39 251 | 31/10/2017,0.60,3.67,0.00,1.37,0.72,0.18,0.31,1.28,1.44,0.23,0.65,-9.90,1.13 252 | 30/11/2017,0.02,0.04,0.09,0.80,0.23,0.10,0.05,-0.23,0.66,-0.77,0.06,-0.08,-0.07 253 | 31/12/2017,0.25,1.15,1.66,1.62,0.52,1.50,0.09,0.55,0.91,0.78,0.55,0.43,0.64 254 | 31/01/2018,0.84,3.57,1.77,3.56,1.06,1.43,0.72,2.64,2.42,0.77,0.84,11.22,2.09 255 | 28/02/2018,-0.05,-5.68,-0.43,-1.51,-0.76,-0.95,0.46,-2.31,-1.55,-0.46,-0.40,-1.18,-1.27 256 | 31/03/2018,-0.14,-0.29,-0.39,-1.09,0.22,-1.03,-0.01,-0.62,-0.48,-0.56,-0.21,0.56,-0.44 257 | 30/04/2018,0.32,0.08,0.49,-0.61,0.03,0.46,0.53,0.26,0.49,-0.28,0.33,-0.22,0.22 258 | 31/05/2018,-0.26,-0.74,0.82,-0.92,0.33,1.16,0.16,0.30,1.08,1.11,0.39,1.39,0.73 259 | 30/06/2018,0.16,0.23,0.91,-3.08,-0.45,0.44,0.08,-0.17,-0.47,1.12,-0.29,-1.83,-0.37 260 | 31/07/2018,0.21,-0.58,0.93,0.40,-0.10,0.55,0.22,-0.14,0.67,-0.21,0.45,-0.52,0.18 261 | 31/08/2018,0.24,1.66,0.02,-2.77,0.04,0.11,0.17,-0.07,0.35,0.50,-0.02,-2.14,0.15 262 | 30/09/2018,0.34,-0.54,0.50,-1.10,-0.16,0.32,0.36,0.06,-0.23,0.28,0.18,0.36,-0.22 263 | 31/10/2018,-0.73,-3.14,-1.58,-3.15,-1.29,-2.57,-0.23,-0.96,-4.02,-0.80,-1.09,2.37,-2.69 264 | 30/11/2018,-0.68,-0.53,-1.93,1.20,-2.11,-0.34,-0.67,-0.87,-0.44,1.19,-0.63,-0.21,-0.71 265 | -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/data/sample_prices.csv: -------------------------------------------------------------------------------- 1 | BLUE,ORANGE 2 | 8.7,10.66 3 | 8.9055,11.0828 4 | 8.7113,10.71 5 | 8.4346,11.5907 6 | 8.7254,12.107 7 | 9.0551,11.7876 8 | 8.9514,11.2078 9 | 9.2439,12.5192 10 | 9.1276,13.3624 11 | 9.3976,14.408 12 | 9.4554,11.9837 13 | 9.5704,12.2718 14 | 9.7728,11.5892 15 | -------------------------------------------------------------------------------- /advanced-portfolio-construction-and-analysis-with-python/edhec_risk_kit.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def get_ffme_returns(): 5 | """ 6 | Load the Fama-French Dataset for the returns of the Top and Bottom Deciles by MarketCap 7 | """ 8 | me_m = pd.read_csv("data/Portfolios_Formed_on_ME_monthly_EW.csv", 9 | header=0, index_col=0, na_values=-99.99) 10 | rets = me_m[['Lo 10', 'Hi 10']] 11 | rets.columns = ['SmallCap', 'LargeCap'] 12 | rets = rets/100 13 | rets.index = pd.to_datetime(rets.index, format="%Y%m").to_period('M') 14 | return rets 15 | 16 | def get_fff_returns(): 17 | """ 18 | Load the Fama-French Research Factor Monthly Dataset 19 | """ 20 | rets = pd.read_csv("data/F-F_Research_Data_Factors_m.csv", 21 | header=0, index_col=0, na_values=-99.99)/100 22 | rets.index = pd.to_datetime(rets.index, format="%Y%m").to_period('M') 23 | return rets 24 | 25 | 26 | def get_hfi_returns(): 27 | """ 28 | Load and format the EDHEC Hedge Fund Index Returns 29 | """ 30 | hfi = pd.read_csv("data/edhec-hedgefundindices.csv", 31 | header=0, index_col=0, parse_dates=True) 32 | hfi = hfi/100 33 | hfi.index = hfi.index.to_period('M') 34 | return hfi 35 | 36 | def get_ind_file(filetype, weighting="vw", n_inds=30): 37 | """ 38 | Load and format the Ken French Industry Portfolios files 39 | Variant is a tuple of (weighting, size) where: 40 | weighting is one of "ew", "vw" 41 | number of inds is 30 or 49 42 | """ 43 | if filetype is "returns": 44 | name = f"{weighting}_rets" 45 | divisor = 100 46 | elif filetype is "nfirms": 47 | name = "nfirms" 48 | divisor = 1 49 | elif filetype is "size": 50 | name = "size" 51 | divisor = 1 52 | else: 53 | raise ValueError(f"filetype must be one of: returns, nfirms, size") 54 | 55 | ind = pd.read_csv(f"data/ind{n_inds}_m_{name}.csv", header=0, index_col=0, na_values=-99.99)/divisor 56 | ind.index = pd.to_datetime(ind.index, format="%Y%m").to_period('M') 57 | ind.columns = ind.columns.str.strip() 58 | return ind 59 | 60 | def get_ind_returns(weighting="vw", n_inds=30): 61 | """ 62 | Load and format the Ken French Industry Portfolios Monthly Returns 63 | """ 64 | return get_ind_file("returns", weighting=weighting, n_inds=n_inds) 65 | 66 | def get_ind_nfirms(n_inds=30): 67 | """ 68 | Load and format the Ken French 30 Industry Portfolios Average number of Firms 69 | """ 70 | return get_ind_file("nfirms", n_inds=n_inds) 71 | 72 | def get_ind_size(n_inds=30): 73 | """ 74 | Load and format the Ken French 30 Industry Portfolios Average size (market cap) 75 | """ 76 | return get_ind_file("size", n_inds=n_inds) 77 | 78 | 79 | def get_ind_market_caps(n_inds=30, weights=False): 80 | """ 81 | Load the industry portfolio data and derive the market caps 82 | """ 83 | ind_nfirms = get_ind_nfirms(n_inds=n_inds) 84 | ind_size = get_ind_size(n_inds=n_inds) 85 | ind_mktcap = ind_nfirms * ind_size 86 | if weights: 87 | total_mktcap = ind_mktcap.sum(axis=1) 88 | ind_capweight = ind_mktcap.divide(total_mktcap, axis="rows") 89 | return ind_capweight 90 | #else 91 | return ind_mktcap 92 | 93 | def get_total_market_index_returns(n_inds=30): 94 | """ 95 | Load the 30 industry portfolio data and derive the returns of a capweighted total market index 96 | """ 97 | ind_capweight = get_ind_market_caps(n_inds=n_inds) 98 | ind_return = get_ind_returns(weighting="vw", n_inds=n_inds) 99 | total_market_return = (ind_capweight * ind_return).sum(axis="columns") 100 | return total_market_return 101 | 102 | def skewness(r): 103 | """ 104 | Alternative to scipy.stats.skew() 105 | Computes the skewness of the supplied Series or DataFrame 106 | Returns a float or a Series 107 | """ 108 | demeaned_r = r - r.mean() 109 | # use the population standard deviation, so set dof=0 110 | sigma_r = r.std(ddof=0) 111 | exp = (demeaned_r**3).mean() 112 | return exp/sigma_r**3 113 | 114 | 115 | def kurtosis(r): 116 | """ 117 | Alternative to scipy.stats.kurtosis() 118 | Computes the kurtosis of the supplied Series or DataFrame 119 | Returns a float or a Series 120 | """ 121 | demeaned_r = r - r.mean() 122 | # use the population standard deviation, so set dof=0 123 | sigma_r = r.std(ddof=0) 124 | exp = (demeaned_r**4).mean() 125 | return exp/sigma_r**4 126 | 127 | 128 | def compound(r): 129 | """ 130 | returns the result of compounding the set of returns in r 131 | """ 132 | return np.expm1(np.log1p(r).sum()) 133 | 134 | 135 | def annualize_rets(r, periods_per_year): 136 | """ 137 | Annualizes a set of returns 138 | We should infer the periods per year 139 | but that is currently left as an exercise 140 | to the reader :-) 141 | """ 142 | compounded_growth = (1+r).prod() 143 | n_periods = r.shape[0] 144 | return compounded_growth**(periods_per_year/n_periods)-1 145 | 146 | 147 | def annualize_vol(r, periods_per_year): 148 | """ 149 | Annualizes the vol of a set of returns 150 | We should infer the periods per year 151 | but that is currently left as an exercise 152 | to the reader :-) 153 | """ 154 | return r.std()*(periods_per_year**0.5) 155 | 156 | 157 | def sharpe_ratio(r, riskfree_rate, periods_per_year): 158 | """ 159 | Computes the annualized sharpe ratio of a set of returns 160 | """ 161 | # convert the annual riskfree rate to per period 162 | rf_per_period = (1+riskfree_rate)**(1/periods_per_year)-1 163 | excess_ret = r - rf_per_period 164 | ann_ex_ret = annualize_rets(excess_ret, periods_per_year) 165 | ann_vol = annualize_vol(r, periods_per_year) 166 | return ann_ex_ret/ann_vol 167 | 168 | 169 | import scipy.stats 170 | def is_normal(r, level=0.01): 171 | """ 172 | Applies the Jarque-Bera test to determine if a Series is normal or not 173 | Test is applied at the 1% level by default 174 | Returns True if the hypothesis of normality is accepted, False otherwise 175 | """ 176 | if isinstance(r, pd.DataFrame): 177 | return r.aggregate(is_normal) 178 | else: 179 | statistic, p_value = scipy.stats.jarque_bera(r) 180 | return p_value > level 181 | 182 | 183 | def drawdown(return_series: pd.Series): 184 | """Takes a time series of asset returns. 185 | returns a DataFrame with columns for 186 | the wealth index, 187 | the previous peaks, and 188 | the percentage drawdown 189 | """ 190 | wealth_index = 1000*(1+return_series).cumprod() 191 | previous_peaks = wealth_index.cummax() 192 | drawdowns = (wealth_index - previous_peaks)/previous_peaks 193 | return pd.DataFrame({"Wealth": wealth_index, 194 | "Previous Peak": previous_peaks, 195 | "Drawdown": drawdowns}) 196 | 197 | 198 | def semideviation(r): 199 | """ 200 | Returns the semideviation aka negative semideviation of r 201 | r must be a Series or a DataFrame, else raises a TypeError 202 | """ 203 | if isinstance(r, pd.Series): 204 | is_negative = r < 0 205 | return r[is_negative].std(ddof=0) 206 | elif isinstance(r, pd.DataFrame): 207 | return r.aggregate(semideviation) 208 | else: 209 | raise TypeError("Expected r to be a Series or DataFrame") 210 | 211 | 212 | def var_historic(r, level=5): 213 | """ 214 | Returns the historic Value at Risk at a specified level 215 | i.e. returns the number such that "level" percent of the returns 216 | fall below that number, and the (100-level) percent are above 217 | """ 218 | if isinstance(r, pd.DataFrame): 219 | return r.aggregate(var_historic, level=level) 220 | elif isinstance(r, pd.Series): 221 | return -np.percentile(r, level) 222 | else: 223 | raise TypeError("Expected r to be a Series or DataFrame") 224 | 225 | 226 | def cvar_historic(r, level=5): 227 | """ 228 | Computes the Conditional VaR of Series or DataFrame 229 | """ 230 | if isinstance(r, pd.Series): 231 | is_beyond = r <= -var_historic(r, level=level) 232 | return -r[is_beyond].mean() 233 | elif isinstance(r, pd.DataFrame): 234 | return r.aggregate(cvar_historic, level=level) 235 | else: 236 | raise TypeError("Expected r to be a Series or DataFrame") 237 | 238 | 239 | from scipy.stats import norm 240 | def var_gaussian(r, level=5, modified=False): 241 | """ 242 | Returns the Parametric Gauusian VaR of a Series or DataFrame 243 | If "modified" is True, then the modified VaR is returned, 244 | using the Cornish-Fisher modification 245 | """ 246 | # compute the Z score assuming it was Gaussian 247 | z = norm.ppf(level/100) 248 | if modified: 249 | # modify the Z score based on observed skewness and kurtosis 250 | s = skewness(r) 251 | k = kurtosis(r) 252 | z = (z + 253 | (z**2 - 1)*s/6 + 254 | (z**3 -3*z)*(k-3)/24 - 255 | (2*z**3 - 5*z)*(s**2)/36 256 | ) 257 | return -(r.mean() + z*r.std(ddof=0)) 258 | 259 | 260 | def portfolio_return(weights, returns): 261 | """ 262 | Computes the return on a portfolio from constituent returns and weights 263 | weights are a numpy array or Nx1 matrix and returns are a numpy array or Nx1 matrix 264 | """ 265 | return weights.T @ returns 266 | 267 | 268 | def portfolio_vol(weights, covmat): 269 | """ 270 | Computes the vol of a portfolio from a covariance matrix and constituent weights 271 | weights are a numpy array or N x 1 maxtrix and covmat is an N x N matrix 272 | """ 273 | vol = (weights.T @ covmat @ weights)**0.5 274 | return vol 275 | 276 | 277 | def plot_ef2(n_points, er, cov): 278 | """ 279 | Plots the 2-asset efficient frontier 280 | """ 281 | if er.shape[0] != 2 or er.shape[0] != 2: 282 | raise ValueError("plot_ef2 can only plot 2-asset frontiers") 283 | weights = [np.array([w, 1-w]) for w in np.linspace(0, 1, n_points)] 284 | rets = [portfolio_return(w, er) for w in weights] 285 | vols = [portfolio_vol(w, cov) for w in weights] 286 | ef = pd.DataFrame({ 287 | "Returns": rets, 288 | "Volatility": vols 289 | }) 290 | return ef.plot.line(x="Volatility", y="Returns", style=".-") 291 | 292 | 293 | from scipy.optimize import minimize 294 | 295 | def minimize_vol(target_return, er, cov): 296 | """ 297 | Returns the optimal weights that achieve the target return 298 | given a set of expected returns and a covariance matrix 299 | """ 300 | n = er.shape[0] 301 | init_guess = np.repeat(1/n, n) 302 | bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples! 303 | # construct the constraints 304 | weights_sum_to_1 = {'type': 'eq', 305 | 'fun': lambda weights: np.sum(weights) - 1 306 | } 307 | return_is_target = {'type': 'eq', 308 | 'args': (er,), 309 | 'fun': lambda weights, er: target_return - portfolio_return(weights,er) 310 | } 311 | weights = minimize(portfolio_vol, init_guess, 312 | args=(cov,), method='SLSQP', 313 | options={'disp': False}, 314 | constraints=(weights_sum_to_1,return_is_target), 315 | bounds=bounds) 316 | return weights.x 317 | 318 | 319 | def tracking_error(r_a, r_b): 320 | """ 321 | Returns the Tracking Error between the two return series 322 | """ 323 | return np.sqrt(((r_a - r_b)**2).sum()) 324 | 325 | 326 | def msr(riskfree_rate, er, cov): 327 | """ 328 | Returns the weights of the portfolio that gives you the maximum sharpe ratio 329 | given the riskfree rate and expected returns and a covariance matrix 330 | """ 331 | n = er.shape[0] 332 | init_guess = np.repeat(1/n, n) 333 | bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples! 334 | # construct the constraints 335 | weights_sum_to_1 = {'type': 'eq', 336 | 'fun': lambda weights: np.sum(weights) - 1 337 | } 338 | def neg_sharpe(weights, riskfree_rate, er, cov): 339 | """ 340 | Returns the negative of the sharpe ratio 341 | of the given portfolio 342 | """ 343 | r = portfolio_return(weights, er) 344 | vol = portfolio_vol(weights, cov) 345 | return -(r - riskfree_rate)/vol 346 | 347 | weights = minimize(neg_sharpe, init_guess, 348 | args=(riskfree_rate, er, cov), method='SLSQP', 349 | options={'disp': False}, 350 | constraints=(weights_sum_to_1,), 351 | bounds=bounds) 352 | return weights.x 353 | 354 | 355 | def gmv(cov): 356 | """ 357 | Returns the weights of the Global Minimum Volatility portfolio 358 | given a covariance matrix 359 | """ 360 | n = cov.shape[0] 361 | return msr(0, np.repeat(1, n), cov) 362 | 363 | 364 | def optimal_weights(n_points, er, cov): 365 | """ 366 | Returns a list of weights that represent a grid of n_points on the efficient frontier 367 | """ 368 | target_rs = np.linspace(er.min(), er.max(), n_points) 369 | weights = [minimize_vol(target_return, er, cov) for target_return in target_rs] 370 | return weights 371 | 372 | 373 | def plot_ef(n_points, er, cov, style='.-', legend=False, show_cml=False, riskfree_rate=0, show_ew=False, show_gmv=False): 374 | """ 375 | Plots the multi-asset efficient frontier 376 | """ 377 | weights = optimal_weights(n_points, er, cov) 378 | rets = [portfolio_return(w, er) for w in weights] 379 | vols = [portfolio_vol(w, cov) for w in weights] 380 | ef = pd.DataFrame({ 381 | "Returns": rets, 382 | "Volatility": vols 383 | }) 384 | ax = ef.plot.line(x="Volatility", y="Returns", style=style, legend=legend) 385 | if show_cml: 386 | ax.set_xlim(left = 0) 387 | # get MSR 388 | w_msr = msr(riskfree_rate, er, cov) 389 | r_msr = portfolio_return(w_msr, er) 390 | vol_msr = portfolio_vol(w_msr, cov) 391 | # add CML 392 | cml_x = [0, vol_msr] 393 | cml_y = [riskfree_rate, r_msr] 394 | ax.plot(cml_x, cml_y, color='green', marker='o', linestyle='dashed', linewidth=2, markersize=10) 395 | if show_ew: 396 | n = er.shape[0] 397 | w_ew = np.repeat(1/n, n) 398 | r_ew = portfolio_return(w_ew, er) 399 | vol_ew = portfolio_vol(w_ew, cov) 400 | # add EW 401 | ax.plot([vol_ew], [r_ew], color='goldenrod', marker='o', markersize=10) 402 | if show_gmv: 403 | w_gmv = gmv(cov) 404 | r_gmv = portfolio_return(w_gmv, er) 405 | vol_gmv = portfolio_vol(w_gmv, cov) 406 | # add EW 407 | ax.plot([vol_gmv], [r_gmv], color='midnightblue', marker='o', markersize=10) 408 | 409 | return ax 410 | 411 | 412 | def run_cppi(risky_r, safe_r=None, m=3, start=1000, floor=0.8, riskfree_rate=0.03, drawdown=None): 413 | """ 414 | Run a backtest of the CPPI strategy, given a set of returns for the risky asset 415 | Returns a dictionary containing: Asset Value History, Risk Budget History, Risky Weight History 416 | """ 417 | # set up the CPPI parameters 418 | dates = risky_r.index 419 | n_steps = len(dates) 420 | account_value = start 421 | floor_value = start*floor 422 | peak = account_value 423 | if isinstance(risky_r, pd.Series): 424 | risky_r = pd.DataFrame(risky_r, columns=["R"]) 425 | 426 | if safe_r is None: 427 | safe_r = pd.DataFrame().reindex_like(risky_r) 428 | safe_r.values[:] = riskfree_rate/12 # fast way to set all values to a number 429 | # set up some DataFrames for saving intermediate values 430 | account_history = pd.DataFrame().reindex_like(risky_r) 431 | risky_w_history = pd.DataFrame().reindex_like(risky_r) 432 | cushion_history = pd.DataFrame().reindex_like(risky_r) 433 | floorval_history = pd.DataFrame().reindex_like(risky_r) 434 | peak_history = pd.DataFrame().reindex_like(risky_r) 435 | 436 | for step in range(n_steps): 437 | if drawdown is not None: 438 | peak = np.maximum(peak, account_value) 439 | floor_value = peak*(1-drawdown) 440 | cushion = (account_value - floor_value)/account_value 441 | risky_w = m*cushion 442 | risky_w = np.minimum(risky_w, 1) 443 | risky_w = np.maximum(risky_w, 0) 444 | safe_w = 1-risky_w 445 | risky_alloc = account_value*risky_w 446 | safe_alloc = account_value*safe_w 447 | # recompute the new account value at the end of this step 448 | account_value = risky_alloc*(1+risky_r.iloc[step]) + safe_alloc*(1+safe_r.iloc[step]) 449 | # save the histories for analysis and plotting 450 | cushion_history.iloc[step] = cushion 451 | risky_w_history.iloc[step] = risky_w 452 | account_history.iloc[step] = account_value 453 | floorval_history.iloc[step] = floor_value 454 | peak_history.iloc[step] = peak 455 | risky_wealth = start*(1+risky_r).cumprod() 456 | backtest_result = { 457 | "Wealth": account_history, 458 | "Risky Wealth": risky_wealth, 459 | "Risk Budget": cushion_history, 460 | "Risky Allocation": risky_w_history, 461 | "m": m, 462 | "start": start, 463 | "floor": floor, 464 | "risky_r":risky_r, 465 | "safe_r": safe_r, 466 | "drawdown": drawdown, 467 | "peak": peak_history, 468 | "floor": floorval_history 469 | } 470 | return backtest_result 471 | 472 | 473 | def summary_stats(r, riskfree_rate=0.03): 474 | """ 475 | Return a DataFrame that contains aggregated summary stats for the returns in the columns of r 476 | """ 477 | ann_r = r.aggregate(annualize_rets, periods_per_year=12) 478 | ann_vol = r.aggregate(annualize_vol, periods_per_year=12) 479 | ann_sr = r.aggregate(sharpe_ratio, riskfree_rate=riskfree_rate, periods_per_year=12) 480 | dd = r.aggregate(lambda r: drawdown(r).Drawdown.min()) 481 | skew = r.aggregate(skewness) 482 | kurt = r.aggregate(kurtosis) 483 | cf_var5 = r.aggregate(var_gaussian, modified=True) 484 | hist_cvar5 = r.aggregate(cvar_historic) 485 | return pd.DataFrame({ 486 | "Annualized Return": ann_r, 487 | "Annualized Vol": ann_vol, 488 | "Skewness": skew, 489 | "Kurtosis": kurt, 490 | "Cornish-Fisher VaR (5%)": cf_var5, 491 | "Historic CVaR (5%)": hist_cvar5, 492 | "Sharpe Ratio": ann_sr, 493 | "Max Drawdown": dd 494 | }) 495 | 496 | 497 | def gbm(n_years = 10, n_scenarios=1000, mu=0.07, sigma=0.15, steps_per_year=12, s_0=100.0, prices=True): 498 | """ 499 | Evolution of Geometric Brownian Motion trajectories, such as for Stock Prices through Monte Carlo 500 | :param n_years: The number of years to generate data for 501 | :param n_paths: The number of scenarios/trajectories 502 | :param mu: Annualized Drift, e.g. Market Return 503 | :param sigma: Annualized Volatility 504 | :param steps_per_year: granularity of the simulation 505 | :param s_0: initial value 506 | :return: a numpy array of n_paths columns and n_years*steps_per_year rows 507 | """ 508 | # Derive per-step Model Parameters from User Specifications 509 | dt = 1/steps_per_year 510 | n_steps = int(n_years*steps_per_year) + 1 511 | # the standard way ... 512 | # rets_plus_1 = np.random.normal(loc=mu*dt+1, scale=sigma*np.sqrt(dt), size=(n_steps, n_scenarios)) 513 | # without discretization error ... 514 | rets_plus_1 = np.random.normal(loc=(1+mu)**dt, scale=(sigma*np.sqrt(dt)), size=(n_steps, n_scenarios)) 515 | rets_plus_1[0] = 1 516 | ret_val = s_0*pd.DataFrame(rets_plus_1).cumprod() if prices else rets_plus_1-1 517 | return ret_val 518 | 519 | 520 | import statsmodels.api as sm 521 | def regress(dependent_variable, explanatory_variables, alpha=True): 522 | """ 523 | Runs a linear regression to decompose the dependent variable into the explanatory variables 524 | returns an object of type statsmodel's RegressionResults on which you can call 525 | .summary() to print a full summary 526 | .params for the coefficients 527 | .tvalues and .pvalues for the significance levels 528 | .rsquared_adj and .rsquared for quality of fit 529 | """ 530 | if alpha: 531 | explanatory_variables = explanatory_variables.copy() 532 | explanatory_variables["Alpha"] = 1 533 | 534 | lm = sm.OLS(dependent_variable, explanatory_variables).fit() 535 | return lm 536 | 537 | def portfolio_tracking_error(weights, ref_r, bb_r): 538 | """ 539 | returns the tracking error between the reference returns 540 | and a portfolio of building block returns held with given weights 541 | """ 542 | return tracking_error(ref_r, (weights*bb_r).sum(axis=1)) 543 | 544 | def style_analysis(dependent_variable, explanatory_variables): 545 | """ 546 | Returns the optimal weights that minimizes the Tracking error between 547 | a portfolio of the explanatory variables and the dependent variable 548 | """ 549 | n = explanatory_variables.shape[1] 550 | init_guess = np.repeat(1/n, n) 551 | bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples! 552 | # construct the constraints 553 | weights_sum_to_1 = {'type': 'eq', 554 | 'fun': lambda weights: np.sum(weights) - 1 555 | } 556 | solution = minimize(portfolio_tracking_error, init_guess, 557 | args=(dependent_variable, explanatory_variables,), method='SLSQP', 558 | options={'disp': False}, 559 | constraints=(weights_sum_to_1,), 560 | bounds=bounds) 561 | weights = pd.Series(solution.x, index=explanatory_variables.columns) 562 | return weights 563 | 564 | 565 | def ff_analysis(r, factors): 566 | """ 567 | Returns the loadings of r on the Fama French Factors 568 | which can be read in using get_fff_returns() 569 | the index of r must be a (not necessarily proper) subset of the index of factors 570 | r is either a Series or a DataFrame 571 | """ 572 | if isinstance(r, pd.Series): 573 | dependent_variable = r 574 | explanatory_variables = factors.loc[r.index] 575 | tilts = regress(dependent_variable, explanatory_variables).params 576 | elif isinstance(r, pd.DataFrame): 577 | tilts = pd.DataFrame({col: ff_analysis(r[col], factors) for col in r.columns}) 578 | else: 579 | raise TypeError("r must be a Series or a DataFrame") 580 | return tilts 581 | 582 | def weight_ew(r, cap_weights=None, max_cw_mult=None, microcap_threshold=None, **kwargs): 583 | """ 584 | Returns the weights of the EW portfolio based on the asset returns "r" as a DataFrame 585 | If supplied a set of capweights and a capweight tether, it is applied and reweighted 586 | """ 587 | n = len(r.columns) 588 | ew = pd.Series(1/n, index=r.columns) 589 | if cap_weights is not None: 590 | cw = cap_weights.loc[r.index[0]] # starting cap weight 591 | ## exclude microcaps 592 | if microcap_threshold is not None and microcap_threshold > 0: 593 | microcap = cw < microcap_threshold 594 | ew[microcap] = 0 595 | ew = ew/ew.sum() 596 | #limit weight to a multiple of capweight 597 | if max_cw_mult is not None and max_cw_mult > 0: 598 | ew = np.minimum(ew, cw*max_cw_mult) 599 | ew = ew/ew.sum() #reweight 600 | return ew 601 | 602 | def weight_cw(r, cap_weights, **kwargs): 603 | """ 604 | Returns the weights of the CW portfolio based on the time series of capweights 605 | """ 606 | w = cap_weights.loc[r.index[0]] 607 | return w/w.sum() 608 | 609 | def backtest_ws(r, estimation_window=60, weighting=weight_ew, verbose=False, **kwargs): 610 | """ 611 | Backtests a given weighting scheme, given some parameters: 612 | r : asset returns to use to build the portfolio 613 | estimation_window: the window to use to estimate parameters 614 | weighting: the weighting scheme to use, must be a function that takes "r", and a variable number of keyword-value arguments 615 | """ 616 | n_periods = r.shape[0] 617 | # return windows 618 | windows = [(start, start+estimation_window) for start in range(n_periods-estimation_window)] 619 | weights = [weighting(r.iloc[win[0]:win[1]], **kwargs) for win in windows] 620 | # convert List of weights to DataFrame 621 | weights = pd.DataFrame(weights, index=r.iloc[estimation_window:].index, columns=r.columns) 622 | returns = (weights * r).sum(axis="columns", min_count=1) #mincount is to generate NAs if all inputs are NAs 623 | return returns 624 | 625 | def sample_cov(r, **kwargs): 626 | """ 627 | Returns the sample covariance of the supplied returns 628 | """ 629 | return r.cov() 630 | 631 | def weight_gmv(r, cov_estimator=sample_cov, **kwargs): 632 | """ 633 | Produces the weights of the GMV portfolio given a covariance matrix of the returns 634 | """ 635 | est_cov = cov_estimator(r, **kwargs) 636 | return gmv(est_cov) 637 | 638 | def cc_cov(r, **kwargs): 639 | """ 640 | Estimates a covariance matrix by using the Elton/Gruber Constant Correlation model 641 | """ 642 | rhos = r.corr() 643 | n = rhos.shape[0] 644 | # this is a symmetric matrix with diagonals all 1 - so the mean correlation is ... 645 | rho_bar = (rhos.values.sum()-n)/(n*(n-1)) 646 | ccor = np.full_like(rhos, rho_bar) 647 | np.fill_diagonal(ccor, 1.) 648 | sd = r.std() 649 | return pd.DataFrame(ccor * np.outer(sd, sd), index=r.columns, columns=r.columns) 650 | 651 | def shrinkage_cov(r, delta=0.5, **kwargs): 652 | """ 653 | Covariance estimator that shrinks between the Sample Covariance and the Constant Correlation Estimators 654 | """ 655 | prior = cc_cov(r, **kwargs) 656 | sample = sample_cov(r, **kwargs) 657 | return delta*prior + (1-delta)*sample 658 | 659 | def risk_contribution(w,cov): 660 | """ 661 | Compute the contributions to risk of the constituents of a portfolio, given a set of portfolio weights and a covariance matrix 662 | """ 663 | total_portfolio_var = portfolio_vol(w,cov)**2 664 | # Marginal contribution of each constituent 665 | marginal_contrib = cov@w 666 | risk_contrib = np.multiply(marginal_contrib,w.T)/total_portfolio_var 667 | return risk_contrib 668 | 669 | def target_risk_contributions(target_risk, cov): 670 | """ 671 | Returns the weights of the portfolio that gives you the weights such 672 | that the contributions to portfolio risk are as close as possible to 673 | the target_risk, given the covariance matrix 674 | """ 675 | n = cov.shape[0] 676 | init_guess = np.repeat(1/n, n) 677 | bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples! 678 | # construct the constraints 679 | weights_sum_to_1 = {'type': 'eq', 680 | 'fun': lambda weights: np.sum(weights) - 1 681 | } 682 | def msd_risk(weights, target_risk, cov): 683 | """ 684 | Returns the Mean Squared Difference in risk contributions 685 | between weights and target_risk 686 | """ 687 | w_contribs = risk_contribution(weights, cov) 688 | return ((w_contribs-target_risk)**2).sum() 689 | 690 | weights = minimize(msd_risk, init_guess, 691 | args=(target_risk, cov), method='SLSQP', 692 | options={'disp': False}, 693 | constraints=(weights_sum_to_1,), 694 | bounds=bounds) 695 | return weights.x 696 | 697 | def equal_risk_contributions(cov): 698 | """ 699 | Returns the weights of the portfolio that equalizes the contributions 700 | of the constituents based on the given covariance matrix 701 | """ 702 | n = cov.shape[0] 703 | return target_risk_contributions(target_risk=np.repeat(1/n,n), cov=cov) 704 | 705 | def weight_erc(r, cov_estimator=sample_cov, **kwargs): 706 | """ 707 | Produces the weights of the ERC portfolio given a covariance matrix of the returns 708 | """ 709 | est_cov = cov_estimator(r, **kwargs) 710 | return equal_risk_contributions(est_cov) 711 | -------------------------------------------------------------------------------- /implementing-graph-theory-with-NetworkX-and-Python/Load graphs from Excel.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Network Data Science with NetworkX and Python" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Load graphs from Excel spreadsheet files" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 1, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "import pandas as pd" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 2, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "link = (\"https://github.com/dnllvrvz/Social-Network-Dataset/\"\n", 33 | " \"raw/master/Social%20Network%20Dataset.xlsx\")" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 3, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "network_data = pd.read_excel(link, sheet_name=['Elements', 'Connections'])" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 4, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "elements_data = network_data['Elements'] # node list\n", 52 | "connections_data = network_data['Connections'] # edge list" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 5, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "import networkx as nx" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 6, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "edge_cols = ['Type', 'Weight', 'When']\n", 71 | "\n", 72 | "graph = nx.convert_matrix.from_pandas_edgelist(connections_data,\n", 73 | " source='From',\n", 74 | " target='To',\n", 75 | " edge_attr=edge_cols)" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 7, 81 | "metadata": {}, 82 | "outputs": [], 83 | "source": [ 84 | "from random import sample\n", 85 | "sampled_edges = sample(graph.edges, 10)" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 8, 91 | "metadata": {}, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "{'Type': 'Work', 'Weight': 0.8, 'When': 2017.0}" 97 | ] 98 | }, 99 | "execution_count": 8, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "graph.edges[sampled_edges[0]]" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 9, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "node_dict = elements_data.set_index('Label').to_dict(orient='index')\n", 115 | "nx.set_node_attributes(graph, node_dict)" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 10, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [ 124 | "sampled_nodes = sample(graph.nodes, 10)" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 11, 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "data": { 134 | "text/plain": [ 135 | "{'Type': 'Student', 'School (ID)': 27, 'Answered the form': 'Yes'}" 136 | ] 137 | }, 138 | "execution_count": 11, 139 | "metadata": {}, 140 | "output_type": "execute_result" 141 | } 142 | ], 143 | "source": [ 144 | "graph.nodes[sampled_nodes[0]]" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [] 153 | } 154 | ], 155 | "metadata": { 156 | "kernelspec": { 157 | "display_name": "Python 3", 158 | "language": "python", 159 | "name": "python3" 160 | }, 161 | "language_info": { 162 | "codemirror_mode": { 163 | "name": "ipython", 164 | "version": 3 165 | }, 166 | "file_extension": ".py", 167 | "mimetype": "text/x-python", 168 | "name": "python", 169 | "nbconvert_exporter": "python", 170 | "pygments_lexer": "ipython3", 171 | "version": "3.7.6" 172 | } 173 | }, 174 | "nbformat": 4, 175 | "nbformat_minor": 4 176 | } 177 | -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/Cornish Fisher expansion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/Cornish Fisher expansion.png -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/Deviation from normality and Sharpe ratio behavior.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/Deviation from normality and Sharpe ratio behavior.pdf -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/Kurtosis as Peakedness.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/Kurtosis as Peakedness.pdf -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/Liability-Driven-Investing-Technical-supplement.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/Liability-Driven-Investing-Technical-supplement.pdf -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/Liability-Driven-Investing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/Liability-Driven-Investing.pdf -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/Measures of Skewness and Kurtosis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/Measures of Skewness and Kurtosis.pdf -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/Portfolio Selection Harry Markowitz.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/Portfolio Selection Harry Markowitz.pdf -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/Why Does an Equal-Weighted Portfolio Outperform Value- and Price-Weighted Portfolios.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/Why Does an Equal-Weighted Portfolio Outperform Value- and Price-Weighted Portfolios.pdf -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/llustration-of-skewness-and-kurtosis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/llustration-of-skewness-and-kurtosis.png -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/articles/value-at-risk-var-intro-7-728.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salimt/Finance-and-Risk-Management-Algorithms/a6afddcc765ab3beec9e755e48fc39f591962757/portfolio-construction-and-analysis-with-python/articles/value-at-risk-var-intro-7-728.jpg -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/asset-liability-management.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Asset-Liability Management\n", 8 | "#### salimt" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "import pandas as pd\n", 18 | "import numpy as np\n", 19 | "import scipy\n", 20 | "import matplotlib\n", 21 | "import edhec_risk_kit_129 as erk" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "- B1 is a 15 Year Bond with a Face Value of $1000 that pays a 5 percent coupon semi-annually (2 times a year)\n", 29 | "\n", 30 | "- B2 is a 5 Year Bond with a Face value of $1000 that pays a 6 percent coupon quarterly (4 times a year)\n", 31 | "\n", 32 | "- B3 is a 10 Year Zero-Coupon Bond with a Face Value of $1000" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": {}, 39 | "outputs": [ 40 | { 41 | "data": { 42 | "text/plain": [ 43 | "0 1000.0\n", 44 | "dtype: float64" 45 | ] 46 | }, 47 | "execution_count": 2, 48 | "metadata": {}, 49 | "output_type": "execute_result" 50 | } 51 | ], 52 | "source": [ 53 | "b1Price = erk.bond_price(15, 1000, .05, 2, .05)\n", 54 | "b1Price" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": 3, 60 | "metadata": {}, 61 | "outputs": [ 62 | { 63 | "data": { 64 | "text/plain": [ 65 | "0 1043.99829\n", 66 | "dtype: float64" 67 | ] 68 | }, 69 | "execution_count": 3, 70 | "metadata": {}, 71 | "output_type": "execute_result" 72 | } 73 | ], 74 | "source": [ 75 | "b2Price = erk.bond_price(5, 1000, .06, 4, .05)\n", 76 | "b2Price" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 4, 82 | "metadata": {}, 83 | "outputs": [ 84 | { 85 | "data": { 86 | "text/plain": [ 87 | "0 613.913254\n", 88 | "dtype: float64" 89 | ] 90 | }, 91 | "execution_count": 4, 92 | "metadata": {}, 93 | "output_type": "execute_result" 94 | } 95 | ], 96 | "source": [ 97 | "b3Price = erk.bond_price(10, 1000, .00, 1, .05)\n", 98 | "b3Price" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "**Macaulay Duration**" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 5, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "b1Flow = erk.bond_cash_flows(15, 1000, 0.05, 2)\n", 115 | "b2Flow = erk.bond_cash_flows(5, 1000, .06, 4)\n", 116 | "b3Flow = erk.bond_cash_flows(10, 1000, 0.00, 1)" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 6, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "data": { 126 | "text/plain": [ 127 | "10.72677495379012" 128 | ] 129 | }, 130 | "execution_count": 6, 131 | "metadata": {}, 132 | "output_type": "execute_result" 133 | } 134 | ], 135 | "source": [ 136 | "b1Dur = erk.macaulay_duration(b1Flow, .05/2)/2\n", 137 | "b1Dur" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 7, 143 | "metadata": {}, 144 | "outputs": [ 145 | { 146 | "data": { 147 | "text/plain": [ 148 | "4.373363222636413" 149 | ] 150 | }, 151 | "execution_count": 7, 152 | "metadata": {}, 153 | "output_type": "execute_result" 154 | } 155 | ], 156 | "source": [ 157 | "b2Dur = erk.macaulay_duration(b2Flow, .05/4)/4\n", 158 | "b2Dur" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 8, 164 | "metadata": {}, 165 | "outputs": [ 166 | { 167 | "data": { 168 | "text/plain": [ 169 | "10.0" 170 | ] 171 | }, 172 | "execution_count": 8, 173 | "metadata": {}, 174 | "output_type": "execute_result" 175 | } 176 | ], 177 | "source": [ 178 | "b3Dur = erk.macaulay_duration(b3Flow, .05/1)/1\n", 179 | "b3Dur" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "**Duration of the liabilities**" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 9, 192 | "metadata": {}, 193 | "outputs": [ 194 | { 195 | "data": { 196 | "text/plain": [ 197 | "6.750917852744651" 198 | ] 199 | }, 200 | "execution_count": 9, 201 | "metadata": {}, 202 | "output_type": "execute_result" 203 | } 204 | ], 205 | "source": [ 206 | "liabilities = pd.Series(data = [100000, 200000, 300000], index=[3, 5, 10])\n", 207 | "erk.macaulay_duration(liabilities, .05)" 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": {}, 213 | "source": [ 214 | "**Duration Matched Portfolio of B1 and B2 to match these liabilities.**" 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "metadata": {}, 220 | "source": [ 221 | "$$ w_s = \\frac{d_l -d_t}{d_l - d_s} $$" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": 10, 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [ 230 | "def match_durations(cf_t, cf_s, ys, cf_l, yl, discount_rate):\n", 231 | " \"\"\"\n", 232 | " Returns the weight W in cf_s that, along with (1-W) in cf_l will have an effective\n", 233 | " duration that matches cf_t\n", 234 | " \"\"\"\n", 235 | " d_t = erk.macaulay_duration(cf_t, discount_rate)\n", 236 | " d_s = erk.macaulay_duration(cf_s, discount_rate/ys)/ys\n", 237 | " d_l = erk.macaulay_duration(cf_l, discount_rate/yl)/yl\n", 238 | " return (d_l - d_t)/(d_l - d_s)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "**Duration Matched Portfolio of B1 and B2 to match these liabilities**" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": 11, 251 | "metadata": {}, 252 | "outputs": [], 253 | "source": [ 254 | "liabs = pd.Series(data=[100000, 200000, 300000], index=[3, 5, 10])" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "**weight of B2 in the portfolio**" 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "execution_count": 12, 267 | "metadata": {}, 268 | "outputs": [ 269 | { 270 | "data": { 271 | "text/plain": [ 272 | "0.6257830075060314" 273 | ] 274 | }, 275 | "execution_count": 12, 276 | "metadata": {}, 277 | "output_type": "execute_result" 278 | } 279 | ], 280 | "source": [ 281 | "ws21 = match_durations(liabs, b2Flow, 4, b1Flow, 2, 0.05)\n", 282 | "ws21" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "**Duration Matched Portfolio of B2 and B3 to match the liabilities**" 290 | ] 291 | }, 292 | { 293 | "cell_type": "markdown", 294 | "metadata": {}, 295 | "source": [ 296 | "**weight of B2 in this portfolio**" 297 | ] 298 | }, 299 | { 300 | "cell_type": "code", 301 | "execution_count": 13, 302 | "metadata": {}, 303 | "outputs": [ 304 | { 305 | "data": { 306 | "text/plain": [ 307 | "0.5774465770256697" 308 | ] 309 | }, 310 | "execution_count": 13, 311 | "metadata": {}, 312 | "output_type": "execute_result" 313 | } 314 | ], 315 | "source": [ 316 | "ws23 = match_durations(liabs, b2Flow, 4, b3Flow, 1, 0.05)\n", 317 | "ws23" 318 | ] 319 | } 320 | ], 321 | "metadata": { 322 | "kernelspec": { 323 | "display_name": "Python 3", 324 | "language": "python", 325 | "name": "python3" 326 | }, 327 | "language_info": { 328 | "codemirror_mode": { 329 | "name": "ipython", 330 | "version": 3 331 | }, 332 | "file_extension": ".py", 333 | "mimetype": "text/x-python", 334 | "name": "python", 335 | "nbconvert_exporter": "python", 336 | "pygments_lexer": "ipython3", 337 | "version": "3.8.5" 338 | } 339 | }, 340 | "nbformat": 4, 341 | "nbformat_minor": 1 342 | } -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/data/edhec-hedgefundindices.csv: -------------------------------------------------------------------------------- 1 | date,Convertible Arbitrage,CTA Global,Distressed Securities,Emerging Markets,Equity Market Neutral,Event Driven,Fixed Income Arbitrage,Global Macro,Long/Short Equity,Merger Arbitrage,Relative Value,Short Selling,Funds Of Funds 2 | 31/01/1997,1.19,3.93,1.78,7.91,1.89,2.13,1.91,5.73,2.81,1.50,1.80,-1.66,3.17 3 | 28/02/1997,1.23,2.98,1.22,5.25,1.01,0.84,1.22,1.75,-0.06,0.34,1.18,4.26,1.06 4 | 31/03/1997,0.78,-0.21,-0.12,-1.20,0.16,-0.23,1.09,-1.19,-0.84,0.60,0.10,7.78,-0.77 5 | 30/04/1997,0.86,-1.70,0.30,1.19,1.19,-0.05,1.30,1.72,0.84,-0.01,1.22,-1.29,0.09 6 | 31/05/1997,1.56,-0.15,2.33,3.15,1.89,3.46,1.18,1.08,3.94,1.97,1.73,-7.37,2.75 7 | 30/06/1997,2.12,0.85,2.17,5.81,1.65,2.58,1.08,2.18,2.23,2.31,1.98,-0.65,2.25 8 | 31/07/1997,1.93,5.91,2.34,5.60,2.47,3.07,0.95,7.38,4.54,2.00,1.81,-4.29,4.35 9 | 31/08/1997,1.34,-4.73,1.47,-0.66,0.17,0.71,0.87,-1.80,1.07,0.79,1.03,-0.72,0.51 10 | 30/09/1997,1.22,1.98,3.50,2.29,2.02,3.29,1.19,2.90,4.29,1.97,1.83,-1.55,3.34 11 | 31/10/1997,1.00,-0.98,-0.64,-5.72,0.95,0.61,-0.32,-1.42,0.10,0.94,0.79,5.72,-0.99 12 | 30/11/1997,0.00,1.33,0.54,-3.78,0.41,1.34,0.53,1.06,-0.26,2.23,1.11,2.17,-0.34 13 | 31/12/1997,0.68,2.86,0.73,1.60,0.66,1.54,0.79,2.64,1.04,1.58,0.82,1.61,0.89 14 | 31/01/1998,1.45,1.04,0.95,-4.29,0.60,0.55,-0.26,-0.50,0.13,0.55,1.32,0.14,-0.36 15 | 28/02/1998,1.46,-0.65,2.27,3.39,1.35,2.94,0.98,1.28,3.42,2.12,1.30,1.55,2.56 16 | 31/03/1998,1.44,1.22,2.52,3.18,1.79,2.63,1.28,5.70,3.36,1.64,1.45,6.37,3.73 17 | 30/04/1998,1.26,-2.96,1.65,0.41,0.67,1.04,0.75,0.34,1.20,1.39,1.45,6.57,1.25 18 | 31/05/1998,0.56,1.93,0.06,-8.25,0.80,-0.83,0.40,0.95,-0.87,-0.09,0.53,14.37,-0.72 19 | 30/06/1998,-0.06,0.51,-0.47,-4.22,1.08,0.02,-0.80,1.20,1.67,0.72,0.26,-0.53,0.21 20 | 31/07/1998,0.60,-0.10,-0.69,0.19,0.12,-0.37,1.06,0.58,-0.06,0.07,0.11,3.43,-0.07 21 | 31/08/1998,-3.19,6.91,-8.36,-19.22,-1.07,-8.86,-1.43,-2.63,-5.52,-5.44,-3.41,24.63,-6.16 22 | 30/09/1998,-1.96,4.54,-2.15,-3.95,0.61,-1.10,-3.62,-0.59,2.06,0.76,0.05,-3.76,-0.37 23 | 31/10/1998,-2.14,0.04,-0.29,1.40,0.52,0.91,-8.01,-2.23,1.69,1.59,-1.40,-10.77,-0.02 24 | 30/11/1998,2.69,-0.89,1.64,4.30,1.58,2.44,0.52,1.94,2.91,2.20,1.98,-7.56,2.20 25 | 31/12/1998,1.13,2.21,1.08,-0.98,2.09,2.19,1.20,2.33,4.08,2.24,1.64,-5.31,2.22 26 | 31/01/1999,2.19,-1.67,1.81,-1.20,1.01,2.01,1.58,0.86,2.58,1.12,1.95,-6.65,2.02 27 | 28/02/1999,0.82,1.97,-0.21,1.02,0.23,-0.42,2.08,-1.11,-1.69,0.36,0.85,8.33,-0.63 28 | 31/03/1999,1.36,-0.65,1.59,5.85,0.33,1.93,1.60,0.24,2.29,1.33,1.16,-1.54,2.13 29 | 30/04/1999,2.43,2.10,4.18,6.30,1.07,4.29,1.06,3.29,3.12,2.18,2.38,-3.75,4.00 30 | 31/05/1999,1.66,-1.50,2.07,0.61,0.89,2.15,0.72,-0.55,0.95,2.10,1.46,0.09,1.19 31 | 30/06/1999,1.02,2.34,2.73,6.54,1.68,2.97,0.88,2.14,3.15,2.22,1.48,-4.12,2.82 32 | 31/07/1999,1.01,-0.51,0.84,-0.61,1.35,0.96,0.51,-0.18,1.77,1.47,1.10,0.92,0.88 33 | 31/08/1999,0.48,-0.27,0.20,-1.47,0.95,-0.27,-0.28,-0.61,0.22,0.50,0.62,4.68,0.28 34 | 30/09/1999,0.96,0.64,-0.41,-0.69,0.95,0.90,0.92,-0.02,1.13,1.16,1.05,4.01,0.52 35 | 31/10/1999,0.45,-3.54,0.27,2.88,0.66,0.54,0.87,0.73,2.12,0.96,0.70,-1.30,1.30 36 | 30/11/1999,1.24,1.66,2.20,6.92,1.33,2.84,1.06,4.05,4.81,2.37,1.37,-12.39,4.83 37 | 31/12/1999,1.40,1.42,3.00,12.30,1.98,2.86,0.97,6.12,7.45,0.90,1.83,-11.37,6.22 38 | 31/01/2000,2.27,1.28,0.88,0.77,0.75,0.88,0.41,0.21,0.75,1.43,1.73,4.27,1.69 39 | 29/02/2000,2.67,-0.22,4.21,5.28,2.53,3.46,0.97,4.08,6.99,2.39,1.85,-13.40,6.66 40 | 31/03/2000,2.43,-1.38,1.03,3.18,1.34,0.69,-0.61,-1.04,0.06,1.31,1.63,-2.30,0.39 41 | 30/04/2000,2.23,-2.41,-1.01,-5.41,1.68,-0.59,-0.06,-3.04,-2.01,1.88,0.92,10.28,-2.69 42 | 31/05/2000,1.49,1.14,-1.32,-4.33,0.62,-0.34,1.07,-0.70,-0.97,1.46,0.80,7.04,-1.22 43 | 30/06/2000,1.79,-1.24,2.03,3.34,1.71,2.68,0.58,1.54,3.49,1.67,1.76,-11.07,3.11 44 | 31/07/2000,0.93,-1.31,0.64,0.25,0.63,0.57,0.18,0.37,0.06,1.16,0.84,5.53,-0.22 45 | 31/08/2000,1.62,1.89,1.40,3.68,2.10,1.73,1.07,2.48,3.45,1.57,1.57,-11.35,2.67 46 | 30/09/2000,1.41,-2.08,-0.19,-4.62,0.58,0.48,0.76,-1.49,-0.16,1.37,0.75,12.04,-0.69 47 | 31/10/2000,0.52,0.75,-0.73,-2.56,0.40,-0.68,0.06,-0.24,-0.84,0.26,-0.04,7.84,-1.04 48 | 30/11/2000,-0.81,4.25,-2.09,-3.85,0.45,-1.36,0.66,1.25,-1.53,1.02,0.06,16.57,-2.05 49 | 31/12/2000,-0.02,6.82,0.01,1.16,1.60,1.27,0.48,4.72,2.48,1.25,0.75,0.63,1.33 50 | 31/01/2001,3.44,0.25,3.08,5.86,0.75,2.98,1.63,2.14,1.65,1.11,3.33,-2.71,2.23 51 | 28/02/2001,1.82,-0.16,1.00,-2.21,1.20,0.45,0.54,-0.72,-2.64,0.54,0.30,10.21,-0.89 52 | 31/03/2001,1.62,4.38,-0.37,-1.75,1.08,-0.42,0.51,0.38,-1.99,-0.61,-0.11,6.20,-0.68 53 | 30/04/2001,1.57,-3.62,0.48,1.14,0.75,1.10,0.94,0.49,2.46,0.58,1.74,-9.91,1.04 54 | 31/05/2001,0.33,0.81,2.35,2.78,0.77,1.85,0.68,0.32,0.43,1.61,1.41,-1.30,0.80 55 | 30/06/2001,0.12,-0.77,3.60,1.60,0.17,0.63,0.17,0.17,0.19,-0.87,0.19,1.10,0.13 56 | 31/07/2001,0.91,-0.40,0.73,-2.86,0.31,0.49,0.54,-0.40,-1.44,0.79,0.10,3.53,-0.40 57 | 31/08/2001,1.42,1.53,1.06,0.30,0.94,0.90,1.05,0.06,-0.96,0.99,-0.31,7.52,0.19 58 | 30/09/2001,0.78,2.46,-0.14,-4.25,0.23,-2.54,-0.13,-0.70,-3.48,-2.67,-2.21,9.41,-1.42 59 | 31/10/2001,1.17,3.36,1.03,2.78,0.58,1.48,1.34,2.08,0.99,0.85,1.64,-2.98,0.95 60 | 30/11/2001,0.80,-5.43,0.86,4.83,0.55,1.05,-0.24,0.21,2.00,0.14,1.36,-6.55,0.58 61 | 31/12/2001,-0.94,1.48,0.15,4.21,0.56,1.07,0.53,1.38,1.80,0.45,0.97,-2.51,0.99 62 | 31/01/2002,1.48,-0.72,1.86,2.73,0.65,0.78,0.86,0.69,-0.37,0.77,0.97,3.43,0.30 63 | 28/02/2002,-0.49,-2.02,-0.33,1.81,-0.07,-0.71,0.56,-0.35,-1.23,-0.44,-0.11,3.90,-0.15 64 | 31/03/2002,0.53,0.09,0.52,3.31,0.47,1.53,0.45,0.64,1.55,0.73,1.45,-4.46,0.90 65 | 30/04/2002,0.96,-1.04,1.39,1.44,0.76,0.46,1.13,0.98,-0.42,-0.13,0.70,4.83,0.52 66 | 31/05/2002,0.33,2.70,0.91,0.01,0.53,0.01,0.99,1.23,-0.34,0.00,0.31,3.46,0.50 67 | 30/06/2002,0.04,6.55,-1.17,-2.92,0.22,-2.83,0.69,-0.22,-2.49,-1.70,-1.07,5.48,-0.95 68 | 31/07/2002,-1.59,4.13,-1.33,-3.09,-0.13,-3.00,0.57,-0.78,-3.89,-1.74,-1.85,6.44,-1.40 69 | 31/08/2002,0.50,2.20,0.09,1.19,0.69,0.60,0.97,0.63,0.41,0.61,0.58,0.15,0.37 70 | 30/09/2002,1.46,2.84,-0.44,-2.52,0.15,-0.70,-0.33,0.54,-1.60,-0.28,-1.10,7.31,-0.33 71 | 31/10/2002,1.04,-3.76,-0.31,1.54,0.16,0.31,-0.63,-0.86,1.23,0.32,0.84,-4.05,-0.31 72 | 30/11/2002,2.51,-1.64,2.39,1.90,0.25,2.16,0.54,0.47,2.24,0.54,1.85,-5.47,1.06 73 | 31/12/2002,1.57,4.89,2.22,0.48,0.94,0.44,1.53,1.92,-1.49,0.46,0.23,4.43,0.77 74 | 31/01/2003,2.83,4.41,2.43,0.12,0.83,1.54,1.06,1.82,0.05,0.40,0.67,1.62,0.72 75 | 28/02/2003,1.33,4.02,0.92,0.84,0.24,0.26,0.79,1.66,-0.37,0.18,-0.04,1.30,0.31 76 | 31/03/2003,0.89,-4.45,1.13,0.19,0.15,0.83,0.19,-1.22,0.20,-0.07,0.49,-0.75,-0.04 77 | 30/04/2003,1.50,0.65,3.45,4.50,0.31,2.72,0.91,1.17,2.98,0.99,1.86,-6.56,1.34 78 | 31/05/2003,1.36,4.90,2.70,4.33,1.07,3.01,2.07,3.97,3.62,1.54,2.12,-4.99,2.05 79 | 30/06/2003,-0.58,-1.92,2.67,2.68,0.34,1.81,0.44,0.56,1.28,0.48,0.71,-1.62,0.68 80 | 31/07/2003,-0.72,-1.71,1.17,1.04,-0.06,1.19,-0.92,-0.35,1.18,0.53,0.41,-3.61,0.25 81 | 31/08/2003,-0.87,0.78,1.37,3.74,0.31,1.33,0.43,2.02,1.79,0.70,0.58,-3.54,0.78 82 | 30/09/2003,1.71,-0.19,2.42,2.64,0.78,1.33,1.05,2.15,0.94,0.77,0.86,1.36,1.21 83 | 31/10/2003,1.46,1.04,2.67,2.59,1.15,1.91,0.35,1.11,2.99,1.11,1.59,-6.56,1.52 84 | 30/11/2003,0.92,0.18,1.54,0.96,0.46,1.16,0.69,0.31,1.30,0.44,1.02,-1.36,0.70 85 | 31/12/2003,0.54,3.81,1.98,4.03,0.54,1.72,1.01,2.93,1.91,0.98,1.27,-1.78,1.39 86 | 31/01/2004,1.19,1.99,3.01,2.51,1.09,2.34,0.92,1.17,1.92,0.97,1.46,-0.90,1.56 87 | 29/02/2004,0.17,5.29,0.75,2.53,0.63,1.13,0.84,1.50,1.23,0.51,0.57,0.18,1.11 88 | 31/03/2004,0.61,-0.51,0.46,1.72,0.32,0.16,0.03,0.64,0.41,0.17,0.38,-1.48,0.43 89 | 30/04/2004,0.20,-5.32,0.93,-2.52,-0.82,0.02,0.62,-1.78,-1.65,-0.39,-0.45,3.84,-0.68 90 | 31/05/2004,-1.28,-1.18,-0.10,-1.81,0.24,-0.23,0.40,-0.81,-0.35,0.00,-0.37,-0.24,-0.82 91 | 30/06/2004,-1.06,-3.16,2.02,0.20,0.42,1.13,0.55,-0.19,0.91,0.17,0.22,-0.51,0.34 92 | 31/07/2004,0.13,-1.19,0.19,-0.27,0.06,-0.82,0.62,-0.14,-1.54,-0.92,0.07,6.38,-0.49 93 | 31/08/2004,0.40,-0.84,0.88,1.33,-0.09,0.35,0.36,-0.39,-0.22,0.11,0.31,1.26,-0.10 94 | 30/09/2004,-0.17,2.20,1.04,2.80,0.85,1.03,0.12,0.08,2.10,0.42,0.52,-2.16,0.99 95 | 31/10/2004,-0.44,3.58,1.43,1.85,-0.05,1.24,0.28,1.38,0.74,0.74,0.40,-0.92,0.68 96 | 30/11/2004,0.81,4.75,3.37,3.28,1.40,3.06,0.75,2.80,3.08,1.64,1.49,-5.74,2.44 97 | 31/12/2004,0.56,0.00,2.66,2.01,0.58,2.44,0.60,0.33,1.78,1.33,0.99,-3.91,1.45 98 | 31/01/2005,-0.96,-4.38,0.37,1.43,0.81,0.04,0.44,-0.47,-0.17,0.00,0.12,3.87,0.06 99 | 28/02/2005,-0.58,0.05,1.34,3.46,0.80,1.44,0.85,1.71,2.10,0.65,0.81,1.18,1.36 100 | 31/03/2005,-1.40,-0.06,0.32,-1.97,0.19,-0.04,0.24,-0.27,-0.96,0.32,-0.42,2.44,-0.44 101 | 30/04/2005,-3.16,-3.54,-0.52,-0.49,-0.30,-1.28,-0.03,-0.80,-1.84,-1.05,-1.08,3.93,-1.41 102 | 31/05/2005,-1.33,2.32,0.06,0.72,0.47,0.65,-0.10,0.88,1.15,0.95,-0.02,-4.75,0.18 103 | 30/06/2005,1.07,2.60,1.33,1.60,0.81,1.33,0.10,1.16,1.95,0.85,0.95,-0.32,1.31 104 | 31/07/2005,1.64,-0.13,1.73,2.57,0.78,2.15,0.81,1.19,2.65,1.15,1.49,-2.42,1.34 105 | 31/08/2005,0.66,1.00,1.24,1.52,0.62,0.92,0.36,0.83,0.97,0.61,0.53,2.59,0.79 106 | 30/09/2005,1.42,0.79,1.12,4.02,0.87,1.00,0.62,2.69,2.22,0.35,1.22,1.98,1.47 107 | 31/10/2005,-0.15,-0.92,-0.32,-2.30,0.01,-1.73,0.57,-0.74,-1.74,-1.45,-0.38,2.33,-1.49 108 | 30/11/2005,0.04,3.79,1.00,2.79,0.61,1.25,0.15,1.64,2.11,1.12,0.67,-3.00,1.60 109 | 31/12/2005,0.92,-1.53,1.22,2.84,0.68,1.42,0.54,1.35,2.49,1.38,1.26,-0.35,1.91 110 | 31/01/2006,2.50,1.74,2.53,5.26,1.15,3.41,0.93,2.58,3.81,2.72,2.38,-2.88,2.86 111 | 28/02/2006,1.16,-1.86,0.65,1.61,0.46,0.51,0.41,0.02,0.16,1.04,0.73,0.64,0.37 112 | 31/03/2006,1.07,2.84,1.72,1.22,0.98,1.85,0.55,0.94,2.38,1.44,1.57,-1.39,1.64 113 | 30/04/2006,0.64,3.87,1.93,3.65,1.02,1.64,1.21,2.38,1.72,1.19,1.26,-0.12,1.71 114 | 31/05/2006,0.91,-1.46,0.86,-3.89,0.02,0.08,0.59,-1.55,-2.48,0.09,-0.25,2.46,-1.33 115 | 30/06/2006,0.12,-1.42,-0.15,-0.97,0.63,0.12,0.36,-0.15,-0.62,0.87,0.21,1.18,-0.28 116 | 31/07/2006,0.66,-2.16,0.09,0.67,0.51,-0.11,0.64,0.06,-0.31,0.58,0.17,1.73,-0.05 117 | 31/08/2006,0.98,0.20,0.99,1.33,-0.09,1.12,0.37,-0.39,1.14,0.53,0.92,-1.56,0.66 118 | 30/09/2006,0.93,-0.55,0.33,0.11,0.09,0.35,0.14,-0.67,0.05,0.41,0.40,-2.36,-0.03 119 | 31/10/2006,0.54,1.02,1.94,2.57,0.65,2.06,0.67,0.97,1.94,1.32,1.32,-3.80,1.63 120 | 30/11/2006,0.92,2.26,1.79,3.23,0.75,1.82,0.60,1.99,2.00,1.42,1.29,-2.68,1.85 121 | 31/12/2006,1.27,1.46,1.65,2.91,1.07,1.68,0.72,1.16,1.53,1.33,1.28,0.39,1.75 122 | 31/01/2007,1.30,1.13,1.50,0.79,0.83,2.01,0.69,0.61,1.21,1.91,1.35,-1.07,1.21 123 | 28/02/2007,1.17,-1.44,1.45,1.00,0.51,2.07,1.06,0.18,0.82,2.55,1.14,0.28,0.96 124 | 31/03/2007,0.60,-1.41,1.08,1.85,1.01,1.46,0.60,0.27,1.15,0.63,0.81,-0.51,0.96 125 | 30/04/2007,0.26,2.41,1.64,2.55,0.89,1.97,0.71,1.52,1.98,1.60,1.34,-2.65,1.63 126 | 31/05/2007,1.10,2.30,1.80,2.70,1.21,2.13,0.55,1.92,2.24,1.71,1.56,-1.99,2.04 127 | 30/06/2007,0.11,2.29,0.27,2.36,0.77,-0.07,0.48,1.07,0.77,-0.53,1.00,2.36,0.82 128 | 31/07/2007,-0.53,-1.22,-0.56,2.75,0.51,-0.32,0.07,1.16,0.09,-0.54,0.04,4.86,0.41 129 | 31/08/2007,-1.45,-2.80,-1.18,-2.74,-0.94,-1.44,-0.48,-1.16,-1.60,0.01,-0.77,0.92,-2.22 130 | 30/09/2007,1.61,4.69,0.95,4.28,1.23,1.34,1.64,3.30,2.56,1.31,1.53,-2.07,1.99 131 | 31/10/2007,1.77,2.80,1.75,4.85,1.68,2.14,1.14,3.04,2.81,1.91,2.00,-0.26,3.03 132 | 30/11/2007,-1.31,-0.16,-1.69,-2.37,-0.18,-2.02,-0.94,-0.63,-2.25,-1.49,-1.12,7.19,-1.48 133 | 31/12/2007,-0.77,1.17,0.02,1.30,0.54,0.07,0.36,1.04,0.43,-0.25,0.22,0.56,0.40 134 | 31/01/2008,-0.09,2.55,-2.33,-5.03,-1.12,-2.71,-0.12,-0.10,-4.00,-1.26,-1.18,5.56,-2.72 135 | 29/02/2008,-0.83,6.20,0.14,2.80,1.20,0.84,-0.49,3.12,1.40,0.60,0.64,3.00,1.42 136 | 31/03/2008,-3.17,-0.56,-1.26,-3.79,-0.49,-1.68,-3.06,-1.69,-2.36,-0.45,-1.62,1.92,-2.62 137 | 30/04/2008,0.76,-0.78,0.88,1.90,0.59,1.18,1.87,0.78,2.23,1.49,1.30,-4.61,0.97 138 | 31/05/2008,1.07,1.62,1.37,1.63,1.26,1.76,1.03,1.14,2.27,1.36,1.59,-1.42,1.72 139 | 30/06/2008,-0.81,3.30,-0.31,-2.74,1.56,-1.13,-0.27,0.30,-1.64,-1.09,-0.84,7.51,-0.68 140 | 31/07/2008,-1.88,-3.33,-1.82,-3.30,-1.00,-1.66,-0.23,-2.13,-2.61,0.11,-1.25,0.72,-2.64 141 | 31/08/2008,-0.66,-1.14,-0.72,-3.36,-1.35,-0.25,-0.03,-1.33,-1.46,0.51,-0.23,-2.15,-1.56 142 | 30/09/2008,-10.27,0.10,-5.18,-9.82,-2.85,-6.27,-5.06,-3.13,-6.75,-2.76,-5.38,3.78,-6.18 143 | 31/10/2008,-12.37,3.45,-7.75,-13.31,-0.44,-6.25,-8.67,-1.57,-6.29,-2.45,-6.92,11.70,-6.00 144 | 30/11/2008,-2.76,2.14,-4.35,-3.91,-5.87,-3.01,-3.08,0.33,-1.88,0.06,-2.09,4.28,-1.92 145 | 31/12/2008,1.77,1.40,-1.97,-0.10,0.05,-0.71,-0.35,1.18,0.81,1.62,0.31,-1.46,-1.19 146 | 31/01/2009,4.91,-0.16,0.82,-1.12,0.79,1.32,1.12,0.29,-0.17,0.56,1.00,2.82,0.60 147 | 28/02/2009,1.64,-0.31,-1.22,-1.33,-0.46,-0.91,0.65,-0.55,-1.61,0.06,-0.16,3.28,-0.37 148 | 31/03/2009,2.35,-1.80,0.22,3.50,0.21,1.17,0.57,0.48,1.88,1.25,1.00,-4.62,0.08 149 | 30/04/2009,5.00,-1.40,3.87,6.63,-0.12,3.37,2.21,1.27,3.75,0.81,3.42,-8.20,0.92 150 | 31/05/2009,5.78,2.13,5.04,8.84,1.46,4.42,3.65,3.48,5.16,1.07,3.92,0.08,3.12 151 | 30/06/2009,2.41,-1.47,1.98,0.13,0.36,1.23,1.26,-0.76,0.09,1.04,1.01,-0.94,0.24 152 | 31/07/2009,6.11,-0.12,3.11,4.51,0.42,2.91,3.22,1.66,2.77,0.68,2.60,-5.96,1.53 153 | 31/08/2009,3.15,0.54,2.44,1.66,0.70,2.07,2.02,0.50,1.57,1.02,1.62,-1.65,1.13 154 | 30/09/2009,3.68,1.51,4.10,5.36,0.85,3.36,3.25,2.31,2.85,1.10,2.20,-3.94,1.71 155 | 31/10/2009,1.19,-1.47,1.39,1.08,-0.05,0.43,1.85,-0.04,-0.86,0.26,0.32,3.14,-0.21 156 | 30/11/2009,0.80,3.32,2.02,1.51,0.09,1.52,0.96,1.65,1.30,0.68,0.89,-2.27,0.82 157 | 31/12/2009,2.15,-2.53,3.24,2.29,0.72,2.35,1.41,-0.28,1.86,1.02,1.61,-3.73,0.66 158 | 31/01/2010,0.53,-2.78,1.87,-0.78,0.28,0.77,1.72,-0.84,-0.95,0.48,0.60,1.83,-0.36 159 | 28/02/2010,0.36,0.90,0.31,-0.19,0.50,0.76,0.23,0.47,0.84,0.57,0.57,-2.61,0.13 160 | 31/03/2010,2.29,2.75,3.36,4.21,0.77,2.73,1.36,1.71,2.87,1.09,1.79,-4.96,1.71 161 | 30/04/2010,1.99,1.00,2.51,1.33,0.18,1.64,1.13,0.76,1.00,0.38,1.22,-2.87,0.85 162 | 31/05/2010,-2.44,-2.48,-2.50,-4.80,-0.50,-2.57,-1.02,-1.28,-3.71,-1.15,-1.86,4.45,-2.72 163 | 30/06/2010,0.17,0.11,-1.05,-0.39,-0.45,-1.06,0.78,-0.23,-1.61,0.23,-0.34,4.19,-0.79 164 | 31/07/2010,2.27,-0.80,1.43,2.96,0.90,1.70,1.00,0.33,1.91,1.27,1.74,-4.26,0.69 165 | 31/08/2010,1.21,3.10,-0.49,0.28,-0.44,-0.32,0.88,1.08,-0.96,0.70,0.31,3.89,0.06 166 | 30/09/2010,1.89,2.67,2.17,4.29,1.60,2.72,1.32,2.63,4.08,1.34,2.15,-8.26,2.19 167 | 31/10/2010,2.14,3.11,2.06,2.32,1.05,1.87,1.07,1.59,2.08,0.47,1.49,-1.79,1.48 168 | 30/11/2010,-0.12,-2.24,0.65,-0.49,0.44,0.28,0.56,-0.47,0.66,-0.25,0.37,-1.62,-0.09 169 | 31/12/2010,1.45,4.36,3.11,2.26,0.94,2.60,0.55,2.50,3.42,1.16,1.57,-5.07,2.05 170 | 31/01/2011,1.81,-0.63,1.73,-0.65,0.56,1.41,1.81,-0.55,0.52,0.93,0.97,-0.76,0.13 171 | 28/02/2011,1.62,1.77,1.44,0.11,0.59,1.29,1.03,0.95,1.39,0.62,1.12,-3.14,0.83 172 | 31/03/2011,0.38,-1.64,0.43,1.54,0.80,0.20,0.22,-0.28,0.21,0.31,0.34,-1.70,-0.18 173 | 30/04/2011,0.20,3.67,1.29,1.40,1.05,1.14,0.97,2.11,1.39,0.89,0.72,-1.97,1.14 174 | 31/05/2011,-0.17,-3.39,-0.14,-1.91,-0.37,-0.52,0.33,-1.50,-1.08,-0.11,-0.05,1.34,-1.16 175 | 30/06/2011,-0.91,-2.39,-0.68,-1.00,-0.14,-1.38,-0.10,-1.30,-1.17,-0.14,-0.56,2.70,-1.38 176 | 31/07/2011,-0.33,2.58,-0.15,0.77,-0.03,-0.30,0.18,1.29,-0.30,-0.49,-0.06,1.99,0.34 177 | 31/08/2011,-1.95,0.07,-4.02,-3.90,-1.61,-4.01,-0.85,-0.63,-4.21,-1.19,-2.00,6.69,-2.52 178 | 30/09/2011,-1.90,-0.57,-3.70,-6.95,-1.59,-3.41,-0.48,-1.42,-4.61,-1.02,-1.97,7.77,-2.62 179 | 31/10/2011,1.29,-3.17,2.37,3.65,1.61,2.98,0.63,0.53,3.90,1.72,1.47,-7.21,0.94 180 | 30/11/2011,-0.94,0.14,-1.08,-2.72,0.02,-0.58,-0.34,-0.66,-1.31,0.17,-0.24,1.31,-0.93 181 | 31/12/2011,0.29,0.34,0.50,-1.81,0.06,-0.34,0.45,-0.22,-0.56,0.56,0.12,0.41,-0.54 182 | 31/01/2012,2.36,0.46,3.24,3.95,0.95,2.88,1.16,1.90,3.27,0.95,2.02,-6.79,1.47 183 | 29/02/2012,2.18,0.91,2.02,3.41,0.71,1.70,1.19,1.34,2.48,1.11,1.72,-5.22,1.40 184 | 31/03/2012,0.65,-2.04,0.91,-1.33,0.23,0.58,0.61,-0.61,0.33,0.24,0.55,-1.23,0.01 185 | 30/04/2012,-0.17,-0.03,-0.12,-0.27,-0.13,-0.18,0.34,-0.59,-0.68,-0.11,-0.20,0.57,-0.33 186 | 31/05/2012,-0.77,2.59,-1.86,-5.31,-1.15,-1.91,-0.03,-0.67,-3.75,-0.48,-1.00,6.77,-1.40 187 | 30/06/2012,0.72,-2.72,-0.09,0.26,0.06,0.07,0.46,-0.63,0.60,0.23,0.70,-2.58,-0.37 188 | 31/07/2012,0.92,3.12,0.89,0.81,0.41,0.48,1.25,1.44,0.39,0.06,1.17,0.87,0.76 189 | 31/08/2012,0.76,-0.82,1.61,0.75,0.49,1.29,0.82,0.37,1.08,0.44,0.95,-3.67,0.68 190 | 30/09/2012,0.57,-1.04,1.69,2.73,0.43,1.20,0.76,0.51,1.57,0.06,1.02,-3.85,0.73 191 | 31/10/2012,0.17,-3.10,1.18,0.28,0.28,0.48,0.58,-0.83,0.09,-0.79,0.30,0.05,-0.25 192 | 30/11/2012,0.41,-0.04,0.82,1.31,0.37,0.80,0.54,0.27,0.52,1.00,0.56,-1.50,0.46 193 | 31/12/2012,0.98,0.57,2.59,3.30,0.37,1.93,0.73,1.11,1.45,1.45,1.17,-3.87,1.08 194 | 31/01/2013,1.58,1.86,2.19,3.03,1.35,2.14,1.16,1.65,3.08,-0.16,2.04,-4.52,2.06 195 | 28/02/2013,0.09,-0.99,0.52,-0.12,0.33,0.41,0.56,-0.12,0.37,0.39,0.47,-0.35,0.32 196 | 31/03/2013,0.77,0.89,1.49,0.68,0.35,1.43,1.13,0.64,1.44,0.69,1.30,-1.89,0.93 197 | 30/04/2013,0.52,1.92,1.75,0.63,0.08,0.78,0.50,1.14,0.64,0.61,0.55,-2.86,0.76 198 | 31/05/2013,1.34,-2.61,2.23,0.33,0.24,1.87,0.50,-0.23,1.35,0.59,1.01,-2.45,0.67 199 | 30/06/2013,-0.81,-2.73,-1.05,-3.21,0.28,-1.13,-1.22,-1.76,-0.94,-0.22,-1.02,0.56,-1.33 200 | 31/07/2013,0.60,-0.76,1.40,0.75,1.00,1.49,0.67,0.16,2.15,1.03,1.17,-3.69,0.91 201 | 31/08/2013,0.46,-1.39,-0.34,-1.22,-0.59,-0.11,0.14,-0.91,-0.76,-0.01,-0.46,1.07,-0.68 202 | 30/09/2013,0.43,-0.57,1.64,2.35,0.63,1.60,0.47,0.69,2.33,0.84,1.40,-4.52,1.27 203 | 31/10/2013,0.95,1.45,1.61,2.38,1.42,1.45,0.85,0.94,2.04,0.45,1.45,-2.07,1.25 204 | 30/11/2013,0.07,1.14,1.22,0.30,1.05,1.19,0.67,0.69,1.54,0.30,0.87,-1.65,1.09 205 | 31/12/2013,0.48,0.52,1.20,1.01,0.76,1.22,0.40,0.65,1.57,0.61,1.02,-1.55,1.09 206 | 31/01/2014,1.37,-1.75,0.47,-1.95,0.42,0.30,0.75,-0.88,-0.32,0.46,0.02,0.94,-0.33 207 | 28/02/2014,0.62,1.37,2.43,1.90,0.66,2.23,0.99,0.90,2.53,1.10,1.49,-3.22,1.57 208 | 31/03/2014,0.47,-1.19,0.63,0.08,-0.05,-0.14,0.36,-0.54,-0.56,-0.50,0.28,0.00,-0.70 209 | 30/04/2014,0.29,0.50,0.25,0.04,-0.23,0.15,0.55,-0.23,-0.83,0.13,0.45,1.25,-0.71 210 | 31/05/2014,0.45,1.50,0.91,2.15,0.20,0.87,0.59,0.72,1.05,0.62,1.03,-1.68,1.14 211 | 30/06/2014,0.29,1.01,1.45,1.15,0.34,1.55,0.63,0.64,1.31,0.89,1.26,-2.64,0.91 212 | 31/07/2014,-0.01,-0.54,-0.59,0.40,-0.05,-0.70,0.25,-0.27,-0.90,-0.53,0.04,0.61,-0.40 213 | 31/08/2014,-0.03,2.83,-0.11,0.69,0.52,0.35,0.21,1.12,1.28,0.43,0.56,-1.70,0.80 214 | 30/09/2014,-0.95,1.79,-1.99,-1.56,0.15,-1.65,0.22,0.60,-0.93,-0.75,-0.05,2.42,-0.12 215 | 31/10/2014,-1.11,0.41,-1.68,-0.69,0.30,-1.52,-0.07,-0.41,-0.13,-1.36,-0.60,-2.36,-0.62 216 | 30/11/2014,-0.09,4.19,-0.34,-0.14,0.59,0.70,0.14,1.77,1.16,0.80,0.61,-0.61,1.26 217 | 31/12/2014,-0.66,0.88,-0.89,-2.20,0.13,-0.22,-0.35,-0.04,0.12,0.32,-0.16,0.33,0.21 218 | 31/01/2015,0.13,3.99,-1.55,-0.34,0.48,-1.04,-0.04,2.29,-0.09,0.04,0.25,1.09,0.17 219 | 28/02/2015,1.21,-0.29,1.85,1.62,0.20,2.70,0.86,0.70,2.52,1.39,1.50,-3.85,1.71 220 | 31/03/2015,0.21,0.97,0.28,0.39,0.80,0.43,0.21,1.01,0.36,0.56,0.33,0.06,0.69 221 | 30/04/2015,1.57,-2.32,0.71,3.78,-0.29,1.13,0.51,-0.91,0.55,0.66,0.69,-1.43,0.26 222 | 31/05/2015,0.46,-0.53,0.25,0.21,0.56,0.83,0.26,0.63,1.42,1.09,0.50,-0.96,0.97 223 | 30/06/2015,-0.86,-3.43,-1.59,-1.77,0.30,-1.24,-0.39,-1.76,-0.72,-0.50,-0.91,0.85,-1.08 224 | 31/07/2015,-0.58,2.09,-0.45,-1.97,0.37,-0.74,-0.05,1.46,0.31,0.03,0.03,0.46,0.22 225 | 31/08/2015,-0.45,-2.20,-2.27,-3.84,0.18,-2.49,-0.37,-1.31,-2.29,-0.56,-1.03,5.78,-2.02 226 | 30/09/2015,-0.63,1.46,-1.36,-1.55,0.63,-2.76,-0.54,-0.52,-1.42,-0.97,-0.72,1.56,-1.76 227 | 31/10/2015,1.23,-1.57,-0.10,3.13,0.57,1.45,-0.14,0.28,2.10,0.74,1.09,-5.19,0.83 228 | 30/11/2015,-0.39,2.19,-1.01,-0.39,0.00,-0.69,0.02,1.35,0.23,-0.01,0.00,-1.44,0.25 229 | 31/12/2015,-1.27,-1.84,-1.60,-0.62,0.29,-1.03,-0.28,-1.43,-0.49,1.24,-0.67,1.81,-0.59 230 | 31/01/2016,-2.39,2.29,-2.34,-4.07,-0.34,-2.88,-0.88,-0.04,-3.24,0.29,-1.37,7.46,-2.66 231 | 29/02/2016,-0.02,2.36,-1.29,-0.35,-0.86,-0.54,-0.62,0.20,-0.95,0.40,-0.38,1.40,-1.26 232 | 31/03/2016,1.70,-2.01,1.90,4.28,0.95,2.43,1.08,-0.43,1.84,0.58,1.56,-6.05,0.71 233 | 30/04/2016,1.40,-0.91,2.08,1.52,-0.60,1.61,1.33,0.20,0.34,-0.55,1.06,-2.00,0.53 234 | 31/05/2016,0.75,-1.76,1.35,-0.12,0.58,1.00,0.40,-0.37,1.06,0.72,0.64,-1.93,0.59 235 | 30/06/2016,0.16,3.52,0.82,1.49,-0.37,-0.12,-0.21,1.07,-0.93,-0.18,0.27,1.73,-0.74 236 | 31/07/2016,1.54,0.67,1.92,2.33,0.80,1.86,1.14,0.64,2.03,0.70,1.25,-5.92,1.34 237 | 31/08/2016,1.02,-2.25,2.09,1.69,-0.19,1.49,0.76,-0.61,0.62,0.82,0.64,-3.98,0.43 238 | 30/09/2016,0.70,-0.66,0.97,0.97,0.40,0.39,0.62,-0.28,0.64,0.41,0.56,-1.48,0.40 239 | 31/10/2016,0.27,-2.57,2.03,0.64,0.24,-0.15,0.63,0.14,-0.72,-0.62,0.52,2.11,-0.27 240 | 30/11/2016,0.31,-0.50,1.15,-1.26,0.13,1.40,0.25,0.88,0.79,0.97,0.31,-3.01,0.22 241 | 31/12/2016,0.90,0.58,1.84,0.35,0.33,1.53,0.85,1.21,0.87,0.88,0.94,-0.08,0.90 242 | 31/01/2017,1.47,-1.02,1.91,2.46,0.58,1.63,1.16,-0.13,1.28,-0.20,1.11,-3.56,0.95 243 | 28/02/2017,0.72,1.49,0.71,1.71,0.09,0.97,0.66,0.59,1.00,0.79,0.74,-6.72,0.80 244 | 31/03/2017,-0.02,-1.37,-0.84,1.05,0.58,0.16,0.29,-0.12,0.78,0.22,0.27,-2.71,0.41 245 | 30/04/2017,0.44,-0.17,0.51,1.09,0.32,0.98,0.30,-0.07,0.88,1.10,0.31,-1.65,0.57 246 | 31/05/2017,0.22,0.11,-0.48,0.18,-0.71,0.53,0.43,0.10,0.65,0.67,0.37,-1.21,0.33 247 | 30/06/2017,0.32,-2.22,0.28,0.61,0.22,0.17,0.28,-0.68,0.42,0.69,0.29,-3.02,-0.06 248 | 31/07/2017,0.84,0.94,1.17,2.35,0.78,1.00,0.50,0.58,1.20,0.59,0.66,-2.32,0.97 249 | 31/08/2017,-0.12,1.60,-0.04,1.48,0.58,-0.29,0.15,0.46,0.69,-0.04,0.26,-0.03,0.75 250 | 30/09/2017,0.65,-1.94,0.58,0.91,0.45,1.08,-0.33,-0.11,1.10,0.39,0.41,-6.52,0.39 251 | 31/10/2017,0.60,3.67,0.00,1.37,0.72,0.18,0.31,1.28,1.44,0.23,0.65,-9.90,1.13 252 | 30/11/2017,0.02,0.04,0.09,0.80,0.23,0.10,0.05,-0.23,0.66,-0.77,0.06,-0.08,-0.07 253 | 31/12/2017,0.25,1.15,1.66,1.62,0.52,1.50,0.09,0.55,0.91,0.78,0.55,0.43,0.64 254 | 31/01/2018,0.84,3.57,1.77,3.56,1.06,1.43,0.72,2.64,2.42,0.77,0.84,11.22,2.09 255 | 28/02/2018,-0.05,-5.68,-0.43,-1.51,-0.76,-0.95,0.46,-2.31,-1.55,-0.46,-0.40,-1.18,-1.27 256 | 31/03/2018,-0.14,-0.29,-0.39,-1.09,0.22,-1.03,-0.01,-0.62,-0.48,-0.56,-0.21,0.56,-0.44 257 | 30/04/2018,0.32,0.08,0.49,-0.61,0.03,0.46,0.53,0.26,0.49,-0.28,0.33,-0.22,0.22 258 | 31/05/2018,-0.26,-0.74,0.82,-0.92,0.33,1.16,0.16,0.30,1.08,1.11,0.39,1.39,0.73 259 | 30/06/2018,0.16,0.23,0.91,-3.08,-0.45,0.44,0.08,-0.17,-0.47,1.12,-0.29,-1.83,-0.37 260 | 31/07/2018,0.21,-0.58,0.93,0.40,-0.10,0.55,0.22,-0.14,0.67,-0.21,0.45,-0.52,0.18 261 | 31/08/2018,0.24,1.66,0.02,-2.77,0.04,0.11,0.17,-0.07,0.35,0.50,-0.02,-2.14,0.15 262 | 30/09/2018,0.34,-0.54,0.50,-1.10,-0.16,0.32,0.36,0.06,-0.23,0.28,0.18,0.36,-0.22 263 | 31/10/2018,-0.73,-3.14,-1.58,-3.15,-1.29,-2.57,-0.23,-0.96,-4.02,-0.80,-1.09,2.37,-2.69 264 | 30/11/2018,-0.68,-0.53,-1.93,1.20,-2.11,-0.34,-0.67,-0.87,-0.44,1.19,-0.63,-0.21,-0.71 265 | -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/data/sample_prices.csv: -------------------------------------------------------------------------------- 1 | BLUE,ORANGE 2 | 8.7,10.66 3 | 8.9055,11.0828 4 | 8.7113,10.71 5 | 8.4346,11.5907 6 | 8.7254,12.107 7 | 9.0551,11.7876 8 | 8.9514,11.2078 9 | 9.2439,12.5192 10 | 9.1276,13.3624 11 | 9.3976,14.408 12 | 9.4554,11.9837 13 | 9.5704,12.2718 14 | 9.7728,11.5892 15 | -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/edhec_risk_kit.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import math 4 | 5 | def get_ffme_returns(): 6 | """ 7 | Load the Fama-French Dataset for the returns of the Top and Bottom Deciles by MarketCap 8 | """ 9 | me_m = pd.read_csv("data/Portfolios_Formed_on_ME_monthly_EW.csv", 10 | header=0, index_col=0, na_values=-99.99) 11 | rets = me_m[['Lo 10', 'Hi 10']] 12 | rets.columns = ['SmallCap', 'LargeCap'] 13 | rets = rets/100 14 | rets.index = pd.to_datetime(rets.index, format="%Y%m").to_period('M') 15 | return rets 16 | 17 | 18 | def get_hfi_returns(): 19 | """ 20 | Load and format the EDHEC Hedge Fund Index Returns 21 | """ 22 | hfi = pd.read_csv("data/edhec-hedgefundindices.csv", 23 | header=0, index_col=0, parse_dates=True) 24 | hfi = hfi/100 25 | hfi.index = hfi.index.to_period('M') 26 | return hfi 27 | 28 | def get_ind_file(filetype): 29 | """ 30 | Load and format the Ken French 30 Industry Portfolios files 31 | """ 32 | known_types = ["returns", "nfirms", "size"] 33 | if filetype not in known_types: 34 | sep = ',' 35 | raise ValueError(f'filetype must be one of:{sep.join(known_types)}') 36 | if filetype is "returns": 37 | name = "vw_rets" 38 | divisor = 100 39 | elif filetype is "nfirms": 40 | name = "nfirms" 41 | divisor = 1 42 | elif filetype is "size": 43 | name = "size" 44 | divisor = 1 45 | ind = pd.read_csv(f"data/ind30_m_{name}.csv", header=0, index_col=0)/divisor 46 | ind.index = pd.to_datetime(ind.index, format="%Y%m").to_period('M') 47 | ind.columns = ind.columns.str.strip() 48 | return ind 49 | 50 | def get_ind_returns(): 51 | """ 52 | Load and format the Ken French 30 Industry Portfolios Value Weighted Monthly Returns 53 | """ 54 | return get_ind_file("returns") 55 | 56 | def get_ind_nfirms(): 57 | """ 58 | Load and format the Ken French 30 Industry Portfolios Average number of Firms 59 | """ 60 | return get_ind_file("nfirms") 61 | 62 | def get_ind_size(): 63 | """ 64 | Load and format the Ken French 30 Industry Portfolios Average size (market cap) 65 | """ 66 | return get_ind_file("size") 67 | 68 | 69 | def get_total_market_index_returns(): 70 | """ 71 | Load the 30 industry portfolio data and derive the returns of a capweighted total market index 72 | """ 73 | ind_nfirms = get_ind_nfirms() 74 | ind_size = get_ind_size() 75 | ind_return = get_ind_returns() 76 | ind_mktcap = ind_nfirms * ind_size 77 | total_mktcap = ind_mktcap.sum(axis=1) 78 | ind_capweight = ind_mktcap.divide(total_mktcap, axis="rows") 79 | total_market_return = (ind_capweight * ind_return).sum(axis="columns") 80 | return total_market_return 81 | 82 | def skewness(r): 83 | """ 84 | Alternative to scipy.stats.skew() 85 | Computes the skewness of the supplied Series or DataFrame 86 | Returns a float or a Series 87 | """ 88 | demeaned_r = r - r.mean() 89 | # use the population standard deviation, so set dof=0 90 | sigma_r = r.std(ddof=0) 91 | exp = (demeaned_r**3).mean() 92 | return exp/sigma_r**3 93 | 94 | 95 | def kurtosis(r): 96 | """ 97 | Alternative to scipy.stats.kurtosis() 98 | Computes the kurtosis of the supplied Series or DataFrame 99 | Returns a float or a Series 100 | """ 101 | demeaned_r = r - r.mean() 102 | # use the population standard deviation, so set dof=0 103 | sigma_r = r.std(ddof=0) 104 | exp = (demeaned_r**4).mean() 105 | return exp/sigma_r**4 106 | 107 | 108 | def compound(r): 109 | """ 110 | returns the result of compounding the set of returns in r 111 | """ 112 | return np.expm1(np.log1p(r).sum()) 113 | 114 | 115 | def annualize_rets(r, periods_per_year): 116 | """ 117 | Annualizes a set of returns 118 | We should infer the periods per year 119 | but that is currently left as an exercise 120 | to the reader :-) 121 | """ 122 | compounded_growth = (1+r).prod() 123 | n_periods = r.shape[0] 124 | return compounded_growth**(periods_per_year/n_periods)-1 125 | 126 | 127 | def annualize_vol(r, periods_per_year): 128 | """ 129 | Annualizes the vol of a set of returns 130 | We should infer the periods per year 131 | but that is currently left as an exercise 132 | to the reader :-) 133 | """ 134 | return r.std()*(periods_per_year**0.5) 135 | 136 | 137 | def sharpe_ratio(r, riskfree_rate, periods_per_year): 138 | """ 139 | Computes the annualized sharpe ratio of a set of returns 140 | """ 141 | # convert the annual riskfree rate to per period 142 | rf_per_period = (1+riskfree_rate)**(1/periods_per_year)-1 143 | excess_ret = r - rf_per_period 144 | ann_ex_ret = annualize_rets(excess_ret, periods_per_year) 145 | ann_vol = annualize_vol(r, periods_per_year) 146 | return ann_ex_ret/ann_vol 147 | 148 | 149 | import scipy.stats 150 | def is_normal(r, level=0.01): 151 | """ 152 | Applies the Jarque-Bera test to determine if a Series is normal or not 153 | Test is applied at the 1% level by default 154 | Returns True if the hypothesis of normality is accepted, False otherwise 155 | """ 156 | if isinstance(r, pd.DataFrame): 157 | return r.aggregate(is_normal) 158 | else: 159 | statistic, p_value = scipy.stats.jarque_bera(r) 160 | return p_value > level 161 | 162 | 163 | def drawdown(return_series: pd.Series): 164 | """Takes a time series of asset returns. 165 | returns a DataFrame with columns for 166 | the wealth index, 167 | the previous peaks, and 168 | the percentage drawdown 169 | """ 170 | wealth_index = 1000*(1+return_series).cumprod() 171 | previous_peaks = wealth_index.cummax() 172 | drawdowns = (wealth_index - previous_peaks)/previous_peaks 173 | return pd.DataFrame({"Wealth": wealth_index, 174 | "Previous Peak": previous_peaks, 175 | "Drawdown": drawdowns}) 176 | 177 | 178 | def semideviation(r): 179 | """ 180 | Returns the semideviation aka negative semideviation of r 181 | r must be a Series or a DataFrame, else raises a TypeError 182 | """ 183 | if isinstance(r, pd.Series): 184 | is_negative = r < 0 185 | return r[is_negative].std(ddof=0) 186 | elif isinstance(r, pd.DataFrame): 187 | return r.aggregate(semideviation) 188 | else: 189 | raise TypeError("Expected r to be a Series or DataFrame") 190 | 191 | 192 | def var_historic(r, level=5): 193 | """ 194 | Returns the historic Value at Risk at a specified level 195 | i.e. returns the number such that "level" percent of the returns 196 | fall below that number, and the (100-level) percent are above 197 | """ 198 | if isinstance(r, pd.DataFrame): 199 | return r.aggregate(var_historic, level=level) 200 | elif isinstance(r, pd.Series): 201 | return -np.percentile(r, level) 202 | else: 203 | raise TypeError("Expected r to be a Series or DataFrame") 204 | 205 | 206 | def cvar_historic(r, level=5): 207 | """ 208 | Computes the Conditional VaR of Series or DataFrame 209 | """ 210 | if isinstance(r, pd.Series): 211 | is_beyond = r <= -var_historic(r, level=level) 212 | return -r[is_beyond].mean() 213 | elif isinstance(r, pd.DataFrame): 214 | return r.aggregate(cvar_historic, level=level) 215 | else: 216 | raise TypeError("Expected r to be a Series or DataFrame") 217 | 218 | 219 | from scipy.stats import norm 220 | def var_gaussian(r, level=5, modified=False): 221 | """ 222 | Returns the Parametric Gauusian VaR of a Series or DataFrame 223 | If "modified" is True, then the modified VaR is returned, 224 | using the Cornish-Fisher modification 225 | """ 226 | # compute the Z score assuming it was Gaussian 227 | z = norm.ppf(level/100) 228 | if modified: 229 | # modify the Z score based on observed skewness and kurtosis 230 | s = skewness(r) 231 | k = kurtosis(r) 232 | z = (z + 233 | (z**2 - 1)*s/6 + 234 | (z**3 -3*z)*(k-3)/24 - 235 | (2*z**3 - 5*z)*(s**2)/36 236 | ) 237 | return -(r.mean() + z*r.std(ddof=0)) 238 | 239 | 240 | def portfolio_return(weights, returns): 241 | """ 242 | Computes the return on a portfolio from constituent returns and weights 243 | weights are a numpy array or Nx1 matrix and returns are a numpy array or Nx1 matrix 244 | """ 245 | return weights.T @ returns 246 | 247 | 248 | def portfolio_vol(weights, covmat): 249 | """ 250 | Computes the vol of a portfolio from a covariance matrix and constituent weights 251 | weights are a numpy array or N x 1 maxtrix and covmat is an N x N matrix 252 | """ 253 | return (weights.T @ covmat @ weights)**0.5 254 | 255 | 256 | def plot_ef2(n_points, er, cov): 257 | """ 258 | Plots the 2-asset efficient frontier 259 | """ 260 | if er.shape[0] != 2 or er.shape[0] != 2: 261 | raise ValueError("plot_ef2 can only plot 2-asset frontiers") 262 | weights = [np.array([w, 1-w]) for w in np.linspace(0, 1, n_points)] 263 | rets = [portfolio_return(w, er) for w in weights] 264 | vols = [portfolio_vol(w, cov) for w in weights] 265 | ef = pd.DataFrame({ 266 | "Returns": rets, 267 | "Volatility": vols 268 | }) 269 | return ef.plot.line(x="Volatility", y="Returns", style=".-") 270 | 271 | 272 | from scipy.optimize import minimize 273 | 274 | def minimize_vol(target_return, er, cov): 275 | """ 276 | Returns the optimal weights that achieve the target return 277 | given a set of expected returns and a covariance matrix 278 | """ 279 | n = er.shape[0] 280 | init_guess = np.repeat(1/n, n) 281 | bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples! 282 | # construct the constraints 283 | weights_sum_to_1 = {'type': 'eq', 284 | 'fun': lambda weights: np.sum(weights) - 1 285 | } 286 | return_is_target = {'type': 'eq', 287 | 'args': (er,), 288 | 'fun': lambda weights, er: target_return - portfolio_return(weights,er) 289 | } 290 | weights = minimize(portfolio_vol, init_guess, 291 | args=(cov,), method='SLSQP', 292 | options={'disp': False}, 293 | constraints=(weights_sum_to_1,return_is_target), 294 | bounds=bounds) 295 | return weights.x 296 | 297 | 298 | 299 | def msr(riskfree_rate, er, cov): 300 | """ 301 | Returns the weights of the portfolio that gives you the maximum sharpe ratio 302 | given the riskfree rate and expected returns and a covariance matrix 303 | """ 304 | n = er.shape[0] 305 | init_guess = np.repeat(1/n, n) 306 | bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples! 307 | # construct the constraints 308 | weights_sum_to_1 = {'type': 'eq', 309 | 'fun': lambda weights: np.sum(weights) - 1 310 | } 311 | def neg_sharpe(weights, riskfree_rate, er, cov): 312 | """ 313 | Returns the negative of the sharpe ratio 314 | of the given portfolio 315 | """ 316 | r = portfolio_return(weights, er) 317 | vol = portfolio_vol(weights, cov) 318 | return -(r - riskfree_rate)/vol 319 | 320 | weights = minimize(neg_sharpe, init_guess, 321 | args=(riskfree_rate, er, cov), method='SLSQP', 322 | options={'disp': False}, 323 | constraints=(weights_sum_to_1,), 324 | bounds=bounds) 325 | return weights.x 326 | 327 | 328 | def gmv(cov): 329 | """ 330 | Returns the weights of the Global Minimum Volatility portfolio 331 | given a covariance matrix 332 | """ 333 | n = cov.shape[0] 334 | return msr(0, np.repeat(1, n), cov) 335 | 336 | 337 | def optimal_weights(n_points, er, cov): 338 | """ 339 | Returns a list of weights that represent a grid of n_points on the efficient frontier 340 | """ 341 | target_rs = np.linspace(er.min(), er.max(), n_points) 342 | weights = [minimize_vol(target_return, er, cov) for target_return in target_rs] 343 | return weights 344 | 345 | 346 | def plot_ef(n_points, er, cov, style='.-', legend=False, show_cml=False, riskfree_rate=0, show_ew=False, show_gmv=False): 347 | """ 348 | Plots the multi-asset efficient frontier 349 | """ 350 | weights = optimal_weights(n_points, er, cov) 351 | rets = [portfolio_return(w, er) for w in weights] 352 | vols = [portfolio_vol(w, cov) for w in weights] 353 | ef = pd.DataFrame({ 354 | "Returns": rets, 355 | "Volatility": vols 356 | }) 357 | ax = ef.plot.line(x="Volatility", y="Returns", style=style, legend=legend) 358 | if show_cml: 359 | ax.set_xlim(left = 0) 360 | # get MSR 361 | w_msr = msr(riskfree_rate, er, cov) 362 | r_msr = portfolio_return(w_msr, er) 363 | vol_msr = portfolio_vol(w_msr, cov) 364 | # add CML 365 | cml_x = [0, vol_msr] 366 | cml_y = [riskfree_rate, r_msr] 367 | ax.plot(cml_x, cml_y, color='green', marker='o', linestyle='dashed', linewidth=2, markersize=10) 368 | if show_ew: 369 | n = er.shape[0] 370 | w_ew = np.repeat(1/n, n) 371 | r_ew = portfolio_return(w_ew, er) 372 | vol_ew = portfolio_vol(w_ew, cov) 373 | # add EW 374 | ax.plot([vol_ew], [r_ew], color='goldenrod', marker='o', markersize=10) 375 | if show_gmv: 376 | w_gmv = gmv(cov) 377 | r_gmv = portfolio_return(w_gmv, er) 378 | vol_gmv = portfolio_vol(w_gmv, cov) 379 | # add EW 380 | ax.plot([vol_gmv], [r_gmv], color='midnightblue', marker='o', markersize=10) 381 | 382 | return ax 383 | 384 | 385 | def run_cppi(risky_r, safe_r=None, m=3, start=1000, floor=0.8, riskfree_rate=0.03, drawdown=None): 386 | """ 387 | Run a backtest of the CPPI strategy, given a set of returns for the risky asset 388 | Returns a dictionary containing: Asset Value History, Risk Budget History, Risky Weight History 389 | """ 390 | # set up the CPPI parameters 391 | dates = risky_r.index 392 | n_steps = len(dates) 393 | account_value = start 394 | floor_value = start*floor 395 | peak = account_value 396 | if isinstance(risky_r, pd.Series): 397 | risky_r = pd.DataFrame(risky_r, columns=["R"]) 398 | 399 | if safe_r is None: 400 | safe_r = pd.DataFrame().reindex_like(risky_r) 401 | safe_r.values[:] = riskfree_rate/12 # fast way to set all values to a number 402 | # set up some DataFrames for saving intermediate values 403 | account_history = pd.DataFrame().reindex_like(risky_r) 404 | risky_w_history = pd.DataFrame().reindex_like(risky_r) 405 | cushion_history = pd.DataFrame().reindex_like(risky_r) 406 | floorval_history = pd.DataFrame().reindex_like(risky_r) 407 | peak_history = pd.DataFrame().reindex_like(risky_r) 408 | 409 | for step in range(n_steps): 410 | if drawdown is not None: 411 | peak = np.maximum(peak, account_value) 412 | floor_value = peak*(1-drawdown) 413 | cushion = (account_value - floor_value)/account_value 414 | risky_w = m*cushion 415 | risky_w = np.minimum(risky_w, 1) 416 | risky_w = np.maximum(risky_w, 0) 417 | safe_w = 1-risky_w 418 | risky_alloc = account_value*risky_w 419 | safe_alloc = account_value*safe_w 420 | # recompute the new account value at the end of this step 421 | account_value = risky_alloc*(1+risky_r.iloc[step]) + safe_alloc*(1+safe_r.iloc[step]) 422 | # save the histories for analysis and plotting 423 | cushion_history.iloc[step] = cushion 424 | risky_w_history.iloc[step] = risky_w 425 | account_history.iloc[step] = account_value 426 | floorval_history.iloc[step] = floor_value 427 | peak_history.iloc[step] = peak 428 | risky_wealth = start*(1+risky_r).cumprod() 429 | backtest_result = { 430 | "Wealth": account_history, 431 | "Risky Wealth": risky_wealth, 432 | "Risk Budget": cushion_history, 433 | "Risky Allocation": risky_w_history, 434 | "m": m, 435 | "start": start, 436 | "floor": floor, 437 | "risky_r":risky_r, 438 | "safe_r": safe_r, 439 | "drawdown": drawdown, 440 | "peak": peak_history, 441 | "floor": floorval_history 442 | } 443 | return backtest_result 444 | 445 | 446 | def summary_stats(r, riskfree_rate=0.03): 447 | """ 448 | Return a DataFrame that contains aggregated summary stats for the returns in the columns of r 449 | """ 450 | ann_r = r.aggregate(annualize_rets, periods_per_year=12) 451 | ann_vol = r.aggregate(annualize_vol, periods_per_year=12) 452 | ann_sr = r.aggregate(sharpe_ratio, riskfree_rate=riskfree_rate, periods_per_year=12) 453 | dd = r.aggregate(lambda r: drawdown(r).Drawdown.min()) 454 | skew = r.aggregate(skewness) 455 | kurt = r.aggregate(kurtosis) 456 | cf_var5 = r.aggregate(var_gaussian, modified=True) 457 | hist_cvar5 = r.aggregate(cvar_historic) 458 | return pd.DataFrame({ 459 | "Annualized Return": ann_r, 460 | "Annualized Vol": ann_vol, 461 | "Skewness": skew, 462 | "Kurtosis": kurt, 463 | "Cornish-Fisher VaR (5%)": cf_var5, 464 | "Historic CVaR (5%)": hist_cvar5, 465 | "Sharpe Ratio": ann_sr, 466 | "Max Drawdown": dd 467 | }) 468 | 469 | 470 | def gbm(n_years = 10, n_scenarios=1000, mu=0.07, sigma=0.15, steps_per_year=12, s_0=100.0, prices=True): 471 | """ 472 | Evolution of Geometric Brownian Motion trajectories, such as for Stock Prices through Monte Carlo 473 | :param n_years: The number of years to generate data for 474 | :param n_paths: The number of scenarios/trajectories 475 | :param mu: Annualized Drift, e.g. Market Return 476 | :param sigma: Annualized Volatility 477 | :param steps_per_year: granularity of the simulation 478 | :param s_0: initial value 479 | :return: a numpy array of n_paths columns and n_years*steps_per_year rows 480 | """ 481 | # Derive per-step Model Parameters from User Specifications 482 | dt = 1/steps_per_year 483 | n_steps = int(n_years*steps_per_year) + 1 484 | # the standard way ... 485 | # rets_plus_1 = np.random.normal(loc=mu*dt+1, scale=sigma*np.sqrt(dt), size=(n_steps, n_scenarios)) 486 | # without discretization error ... 487 | rets_plus_1 = np.random.normal(loc=(1+mu)**dt, scale=(sigma*np.sqrt(dt)), size=(n_steps, n_scenarios)) 488 | rets_plus_1[0] = 1 489 | ret_val = s_0*pd.DataFrame(rets_plus_1).cumprod() if prices else rets_plus_1-1 490 | return ret_val 491 | 492 | 493 | def discount(t, r): 494 | """ 495 | Compute the price of a pure discount bond that pays a dollar at time period t 496 | and r is the per-period interest rate 497 | returns a |t| x |r| Series or DataFrame 498 | r can be a float, Series or DataFrame 499 | returns a DataFrame indexed by t 500 | """ 501 | discounts = pd.DataFrame([(r+1)**-i for i in t]) 502 | discounts.index = t 503 | return discounts 504 | 505 | def pv(flows, r): 506 | """ 507 | Compute the present value of a sequence of cash flows given by the time (as an index) and amounts 508 | r can be a scalar, or a Series or DataFrame with the number of rows matching the num of rows in flows 509 | """ 510 | dates = flows.index 511 | discounts = discount(dates, r) 512 | return discounts.multiply(flows, axis='rows').sum() 513 | 514 | def funding_ratio(assets, liabilities, r): 515 | """ 516 | Computes the funding ratio of a series of liabilities, based on an interest rate and current value of assets 517 | """ 518 | return pv(assets, r)/pv(liabilities, r) 519 | 520 | def inst_to_ann(r): 521 | """ 522 | Convert an instantaneous interest rate to an annual interest rate 523 | """ 524 | return np.expm1(r) 525 | 526 | def ann_to_inst(r): 527 | """ 528 | Convert an instantaneous interest rate to an annual interest rate 529 | """ 530 | return np.log1p(r) 531 | 532 | def cir(n_years = 10, n_scenarios=1, a=0.05, b=0.03, sigma=0.05, steps_per_year=12, r_0=None): 533 | """ 534 | Generate random interest rate evolution over time using the CIR model 535 | b and r_0 are assumed to be the annualized rates, not the short rate 536 | and the returned values are the annualized rates as well 537 | """ 538 | if r_0 is None: r_0 = b 539 | r_0 = ann_to_inst(r_0) 540 | dt = 1/steps_per_year 541 | num_steps = int(n_years*steps_per_year) + 1 # because n_years might be a float 542 | 543 | shock = np.random.normal(0, scale=np.sqrt(dt), size=(num_steps, n_scenarios)) 544 | rates = np.empty_like(shock) 545 | rates[0] = r_0 546 | 547 | ## For Price Generation 548 | h = math.sqrt(a**2 + 2*sigma**2) 549 | prices = np.empty_like(shock) 550 | #### 551 | 552 | def price(ttm, r): 553 | _A = ((2*h*math.exp((h+a)*ttm/2))/(2*h+(h+a)*(math.exp(h*ttm)-1)))**(2*a*b/sigma**2) 554 | _B = (2*(math.exp(h*ttm)-1))/(2*h + (h+a)*(math.exp(h*ttm)-1)) 555 | _P = _A*np.exp(-_B*r) 556 | return _P 557 | prices[0] = price(n_years, r_0) 558 | #### 559 | 560 | for step in range(1, num_steps): 561 | r_t = rates[step-1] 562 | d_r_t = a*(b-r_t)*dt + sigma*np.sqrt(r_t)*shock[step] 563 | rates[step] = abs(r_t + d_r_t) 564 | # generate prices at time t as well ... 565 | prices[step] = price(n_years-step*dt, rates[step]) 566 | 567 | rates = pd.DataFrame(data=inst_to_ann(rates), index=range(num_steps)) 568 | ### for prices 569 | prices = pd.DataFrame(data=prices, index=range(num_steps)) 570 | ### 571 | return rates, prices 572 | 573 | def bond_cash_flows(maturity, principal=100, coupon_rate=0.03, coupons_per_year=12): 574 | """ 575 | Returns the series of cash flows generated by a bond, 576 | indexed by the payment/coupon number 577 | """ 578 | n_coupons = round(maturity*coupons_per_year) 579 | coupon_amt = principal*coupon_rate/coupons_per_year 580 | coupons = np.repeat(coupon_amt, n_coupons) 581 | coupon_times = np.arange(1, n_coupons+1) 582 | cash_flows = pd.Series(data=coupon_amt, index=coupon_times) 583 | cash_flows.iloc[-1] += principal 584 | return cash_flows 585 | 586 | def bond_price(maturity, principal=100, coupon_rate=0.03, coupons_per_year=12, discount_rate=0.03): 587 | """ 588 | Computes the price of a bond that pays regular coupons until maturity 589 | at which time the principal and the final coupon is returned 590 | This is not designed to be efficient, rather, 591 | it is to illustrate the underlying principle behind bond pricing! 592 | If discount_rate is a DataFrame, then this is assumed to be the rate on each coupon date 593 | and the bond value is computed over time. 594 | i.e. The index of the discount_rate DataFrame is assumed to be the coupon number 595 | """ 596 | if isinstance(discount_rate, pd.DataFrame): 597 | pricing_dates = discount_rate.index 598 | prices = pd.DataFrame(index=pricing_dates, columns=discount_rate.columns) 599 | for t in pricing_dates: 600 | prices.loc[t] = bond_price(maturity-t/coupons_per_year, principal, coupon_rate, coupons_per_year, 601 | discount_rate.loc[t]) 602 | return prices 603 | else: # base case ... single time period 604 | if maturity <= 0: return principal+principal*coupon_rate/coupons_per_year 605 | cash_flows = bond_cash_flows(maturity, principal, coupon_rate, coupons_per_year) 606 | return pv(cash_flows, discount_rate/coupons_per_year) 607 | 608 | def macaulay_duration(flows, discount_rate): 609 | """ 610 | Computes the Macaulay Duration of a sequence of cash flows, given a per-period discount rate 611 | """ 612 | discounted_flows = discount(flows.index, discount_rate)*pd.DataFrame(flows) 613 | weights = discounted_flows/discounted_flows.sum() 614 | return np.average(flows.index, weights=weights.iloc[:,0]) 615 | 616 | def match_durations(cf_t, cf_s, cf_l, discount_rate): 617 | """ 618 | Returns the weight W in cf_s that, along with (1-W) in cf_l will have an effective 619 | duration that matches cf_t 620 | """ 621 | d_t = macaulay_duration(cf_t, discount_rate) 622 | d_s = macaulay_duration(cf_s, discount_rate) 623 | d_l = macaulay_duration(cf_l, discount_rate) 624 | return (d_l - d_t)/(d_l - d_s) 625 | 626 | def bond_total_return(monthly_prices, principal, coupon_rate, coupons_per_year): 627 | """ 628 | Computes the total return of a Bond based on monthly bond prices and coupon payments 629 | Assumes that dividends (coupons) are paid out at the end of the period (e.g. end of 3 months for quarterly div) 630 | and that dividends are reinvested in the bond 631 | """ 632 | coupons = pd.DataFrame(data = 0, index=monthly_prices.index, columns=monthly_prices.columns) 633 | t_max = monthly_prices.index.max() 634 | pay_date = np.linspace(12/coupons_per_year, t_max, int(coupons_per_year*t_max/12), dtype=int) 635 | coupons.iloc[pay_date] = principal*coupon_rate/coupons_per_year 636 | total_returns = (monthly_prices + coupons)/monthly_prices.shift()-1 637 | return total_returns.dropna() 638 | 639 | 640 | def bt_mix(r1, r2, allocator, **kwargs): 641 | """ 642 | Runs a back test (simulation) of allocating between a two sets of returns 643 | r1 and r2 are T x N DataFrames or returns where T is the time step index and N is the number of scenarios. 644 | allocator is a function that takes two sets of returns and allocator specific parameters, and produces 645 | an allocation to the first portfolio (the rest of the money is invested in the GHP) as a T x 1 DataFrame 646 | Returns a T x N DataFrame of the resulting N portfolio scenarios 647 | """ 648 | if not r1.shape == r2.shape: 649 | raise ValueError("r1 and r2 should have the same shape") 650 | weights = allocator(r1, r2, **kwargs) 651 | if not weights.shape == r1.shape: 652 | raise ValueError("Allocator returned weights with a different shape than the returns") 653 | r_mix = weights*r1 + (1-weights)*r2 654 | return r_mix 655 | 656 | 657 | def fixedmix_allocator(r1, r2, w1, **kwargs): 658 | """ 659 | Produces a time series over T steps of allocations between the PSP and GHP across N scenarios 660 | PSP and GHP are T x N DataFrames that represent the returns of the PSP and GHP such that: 661 | each column is a scenario 662 | each row is the price for a timestep 663 | Returns an T x N DataFrame of PSP Weights 664 | """ 665 | return pd.DataFrame(data = w1, index=r1.index, columns=r1.columns) 666 | 667 | def terminal_values(rets): 668 | """ 669 | Computes the terminal values from a set of returns supplied as a T x N DataFrame 670 | Return a Series of length N indexed by the columns of rets 671 | """ 672 | return (rets+1).prod() 673 | 674 | def terminal_stats(rets, floor = 0.8, cap=np.inf, name="Stats"): 675 | """ 676 | Produce Summary Statistics on the terminal values per invested dollar 677 | across a range of N scenarios 678 | rets is a T x N DataFrame of returns, where T is the time-step (we assume rets is sorted by time) 679 | Returns a 1 column DataFrame of Summary Stats indexed by the stat name 680 | """ 681 | terminal_wealth = (rets+1).prod() 682 | breach = terminal_wealth < floor 683 | reach = terminal_wealth >= cap 684 | p_breach = breach.mean() if breach.sum() > 0 else np.nan 685 | p_reach = reach.mean() if reach.sum() > 0 else np.nan 686 | e_short = (floor-terminal_wealth[breach]).mean() if breach.sum() > 0 else np.nan 687 | e_surplus = (-cap+terminal_wealth[reach]).mean() if reach.sum() > 0 else np.nan 688 | sum_stats = pd.DataFrame.from_dict({ 689 | "mean": terminal_wealth.mean(), 690 | "std" : terminal_wealth.std(), 691 | "p_breach": p_breach, 692 | "e_short":e_short, 693 | "p_reach": p_reach, 694 | "e_surplus": e_surplus 695 | }, orient="index", columns=[name]) 696 | return sum_stats 697 | 698 | def glidepath_allocator(r1, r2, start_glide=1, end_glide=0.0): 699 | """ 700 | Allocates weights to r1 starting at start_glide and ends at end_glide 701 | by gradually moving from start_glide to end_glide over time 702 | """ 703 | n_points = r1.shape[0] 704 | n_col = r1.shape[1] 705 | path = pd.Series(data=np.linspace(start_glide, end_glide, num=n_points)) 706 | paths = pd.concat([path]*n_col, axis=1) 707 | paths.index = r1.index 708 | paths.columns = r1.columns 709 | return paths 710 | 711 | def floor_allocator(psp_r, ghp_r, floor, zc_prices, m=3): 712 | """ 713 | Allocate between PSP and GHP with the goal to provide exposure to the upside 714 | of the PSP without going violating the floor. 715 | Uses a CPPI-style dynamic risk budgeting algorithm by investing a multiple 716 | of the cushion in the PSP 717 | Returns a DataFrame with the same shape as the psp/ghp representing the weights in the PSP 718 | """ 719 | if zc_prices.shape != psp_r.shape: 720 | raise ValueError("PSP and ZC Prices must have the same shape") 721 | n_steps, n_scenarios = psp_r.shape 722 | account_value = np.repeat(1, n_scenarios) 723 | floor_value = np.repeat(1, n_scenarios) 724 | w_history = pd.DataFrame(index=psp_r.index, columns=psp_r.columns) 725 | for step in range(n_steps): 726 | floor_value = floor*zc_prices.iloc[step] ## PV of Floor assuming today's rates and flat YC 727 | cushion = (account_value - floor_value)/account_value 728 | psp_w = (m*cushion).clip(0, 1) # same as applying min and max 729 | ghp_w = 1-psp_w 730 | psp_alloc = account_value*psp_w 731 | ghp_alloc = account_value*ghp_w 732 | # recompute the new account value at the end of this step 733 | account_value = psp_alloc*(1+psp_r.iloc[step]) + ghp_alloc*(1+ghp_r.iloc[step]) 734 | w_history.iloc[step] = psp_w 735 | return w_history 736 | 737 | 738 | def drawdown_allocator(psp_r, ghp_r, maxdd, m=3): 739 | """ 740 | Allocate between PSP and GHP with the goal to provide exposure to the upside 741 | of the PSP without going violating the floor. 742 | Uses a CPPI-style dynamic risk budgeting algorithm by investing a multiple 743 | of the cushion in the PSP 744 | Returns a DataFrame with the same shape as the psp/ghp representing the weights in the PSP 745 | """ 746 | n_steps, n_scenarios = psp_r.shape 747 | account_value = np.repeat(1, n_scenarios) 748 | floor_value = np.repeat(1, n_scenarios) 749 | peak_value = np.repeat(1, n_scenarios) 750 | w_history = pd.DataFrame(index=psp_r.index, columns=psp_r.columns) 751 | for step in range(n_steps): 752 | floor_value = (1-maxdd)*peak_value ### Floor is based on Prev Peak 753 | cushion = (account_value - floor_value)/account_value 754 | psp_w = (m*cushion).clip(0, 1) # same as applying min and max 755 | ghp_w = 1-psp_w 756 | psp_alloc = account_value*psp_w 757 | ghp_alloc = account_value*ghp_w 758 | # recompute the new account value and prev peak at the end of this step 759 | account_value = psp_alloc*(1+psp_r.iloc[step]) + ghp_alloc*(1+ghp_r.iloc[step]) 760 | peak_value = np.maximum(peak_value, account_value) 761 | w_history.iloc[step] = psp_w 762 | return w_history 763 | -------------------------------------------------------------------------------- /portfolio-construction-and-analysis-with-python/monte-carlo-simulations-of-CPPI-and-diversification.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Interactive Plotting and Monte Carlo Simulations of CPPI\n", 8 | "#### salimt" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "import ipywidgets as widgets\n", 18 | "from IPython.display import display\n", 19 | "import pandas as pd\n", 20 | "import edhec_risk_kit_123 as erk\n", 21 | "\n", 22 | "%load_ext autoreload\n", 23 | "%autoreload 2" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## GBM Simulations" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 2, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "def show_gbm(n_scenarios, mu, sigma):\n", 40 | " \"\"\"\n", 41 | " Draw the results of a stock price evolution under a Geometric Brownian Motion model\n", 42 | " \"\"\"\n", 43 | " s_0=100\n", 44 | " prices = erk.gbm(n_scenarios=n_scenarios, mu=mu, sigma=sigma, s_0=s_0)\n", 45 | " ax = prices.plot(legend=False, color=\"indianred\", alpha = 0.5, linewidth=2, figsize=(12,5))\n", 46 | " ax.axhline(y=100, ls=\":\", color=\"black\")\n", 47 | " # draw a dot at the origin\n", 48 | " ax.plot(0,s_0, marker='o',color='darkred', alpha=0.2)\n" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 3, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "gbm_controls = widgets.interactive(show_gbm, \n", 58 | " n_scenarios=widgets.IntSlider(min=1, max=1000, step=1, value=1), \n", 59 | " mu=(0., +.2,.01),\n", 60 | " sigma=(0, .3, .01)\n", 61 | ")" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 4, 67 | "metadata": {}, 68 | "outputs": [ 69 | { 70 | "data": { 71 | "application/vnd.jupyter.widget-view+json": { 72 | "model_id": "32fee7fdb10b4a05909f4982cf1460cd", 73 | "version_major": 2, 74 | "version_minor": 0 75 | }, 76 | "text/plain": [ 77 | "interactive(children=(IntSlider(value=1, description='n_scenarios', max=1000, min=1), FloatSlider(value=0.1, d…" 78 | ] 79 | }, 80 | "metadata": {}, 81 | "output_type": "display_data" 82 | } 83 | ], 84 | "source": [ 85 | "display(gbm_controls)" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "# Interactive CPPI Monte Carlo Testing" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 5, 98 | "metadata": {}, 99 | "outputs": [ 100 | { 101 | "data": { 102 | "application/vnd.jupyter.widget-view+json": { 103 | "model_id": "1c463e1176ed424892f88d7a728a9244", 104 | "version_major": 2, 105 | "version_minor": 0 106 | }, 107 | "text/plain": [ 108 | "interactive(children=(IntSlider(value=50, description='n_scenarios', max=1000, min=1, step=5), FloatSlider(val…" 109 | ] 110 | }, 111 | "metadata": {}, 112 | "output_type": "display_data" 113 | } 114 | ], 115 | "source": [ 116 | "def show_cppi(n_scenarios=50, mu=0.07, sigma=0.15, m=3, floor=0., riskfree_rate=0.03, y_max=100):\n", 117 | " \"\"\"\n", 118 | " Plot the results of a Monte Carlo Simulation of CPPI\n", 119 | " \"\"\"\n", 120 | " start = 100\n", 121 | " sim_rets = erk.gbm(n_scenarios=n_scenarios, mu=mu, sigma=sigma, prices=False, steps_per_year=12)\n", 122 | " risky_r = pd.DataFrame(sim_rets)\n", 123 | " # run the \"back\"-test\n", 124 | " btr = erk.run_cppi(risky_r=pd.DataFrame(risky_r),riskfree_rate=riskfree_rate,m=m, start=start, floor=floor)\n", 125 | " wealth = btr[\"Wealth\"]\n", 126 | " y_max=wealth.values.max()*y_max/100\n", 127 | " ax = wealth.plot(legend=False, alpha=0.3, color=\"indianred\", figsize=(12, 6))\n", 128 | " ax.axhline(y=start, ls=\":\", color=\"black\")\n", 129 | " ax.axhline(y=start*floor, ls=\"--\", color=\"red\")\n", 130 | " ax.set_ylim(top=y_max)\n", 131 | "\n", 132 | "cppi_controls = widgets.interactive(show_cppi, \n", 133 | " n_scenarios=widgets.IntSlider(min=1, max=1000, step=5, value=50), \n", 134 | " mu=(0., +.2, .01),\n", 135 | " sigma=(0, .30, .05),\n", 136 | " floor=(0, 2, .1),\n", 137 | " m=(1, 5, .5),\n", 138 | " riskfree_rate=(0, .05, .01),\n", 139 | " y_max=widgets.IntSlider(min=0, max=100, step=1, value=100,\n", 140 | " description=\"Zoom Y Axis\")\n", 141 | ")\n", 142 | "display(cppi_controls)" 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "metadata": {}, 148 | "source": [ 149 | "# Adding a Histogram and Reporting Floor Violations" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "import matplotlib.pyplot as plt\n", 159 | "\n", 160 | "def show_cppi(n_scenarios=50, mu=0.07, sigma=0.15, m=3, floor=0., riskfree_rate=0.03, y_max=100):\n", 161 | " \"\"\"\n", 162 | " Plot the results of a Monte Carlo Simulation of CPPI\n", 163 | " \"\"\"\n", 164 | " start = 100\n", 165 | " sim_rets = erk.gbm(n_scenarios=n_scenarios, mu=mu, sigma=sigma, prices=False, steps_per_year=12)\n", 166 | " risky_r = pd.DataFrame(sim_rets)\n", 167 | " # run the \"back\"-test\n", 168 | " btr = erk.run_cppi(risky_r=pd.DataFrame(risky_r),riskfree_rate=riskfree_rate,m=m, start=start, floor=floor)\n", 169 | " wealth = btr[\"Wealth\"]\n", 170 | " # calculate terminal wealth stats\n", 171 | " y_max=wealth.values.max()*y_max/100\n", 172 | " terminal_wealth = wealth.iloc[-1]\n", 173 | " # Plot!\n", 174 | " fig, (wealth_ax, hist_ax) = plt.subplots(nrows=1, ncols=2, sharey=True, gridspec_kw={'width_ratios':[3,2]}, figsize=(24, 9))\n", 175 | " plt.subplots_adjust(wspace=0.0)\n", 176 | " \n", 177 | " wealth.plot(ax=wealth_ax, legend=False, alpha=0.3, color=\"indianred\")\n", 178 | " wealth_ax.axhline(y=start, ls=\":\", color=\"black\")\n", 179 | " wealth_ax.axhline(y=start*floor, ls=\"--\", color=\"red\")\n", 180 | " wealth_ax.set_ylim(top=y_max)\n", 181 | " \n", 182 | " terminal_wealth.plot.hist(ax=hist_ax, bins=50, ec='w', fc='indianred', orientation='horizontal')\n", 183 | " hist_ax.axhline(y=start, ls=\":\", color=\"black\")\n", 184 | "\n", 185 | "cppi_controls = widgets.interactive(show_cppi, \n", 186 | " n_scenarios=widgets.IntSlider(min=1, max=1000, step=5, value=50), \n", 187 | " mu=(0., +.2, .01),\n", 188 | " sigma=(0, .3, .05),\n", 189 | " floor=(0, 2, .1),\n", 190 | " m=(1, 5, .5),\n", 191 | " riskfree_rate=(0, .05, .01),\n", 192 | " y_max=widgets.IntSlider(min=0, max=100, step=1, value=100,\n", 193 | " description=\"Zoom Y Axis\")\n", 194 | ")\n", 195 | "display(cppi_controls)" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "# Adding Terminal Wealth Statistics" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [ 211 | "import matplotlib.pyplot as plt\n", 212 | "import numpy as np\n", 213 | "\n", 214 | "def show_cppi(n_scenarios=50, mu=0.07, sigma=0.15, m=3, floor=0., riskfree_rate=0.03, steps_per_year=12, y_max=100):\n", 215 | " \"\"\"\n", 216 | " Plot the results of a Monte Carlo Simulation of CPPI\n", 217 | " \"\"\"\n", 218 | " start = 100\n", 219 | " sim_rets = erk.gbm(n_scenarios=n_scenarios, mu=mu, sigma=sigma, prices=False, steps_per_year=steps_per_year)\n", 220 | " risky_r = pd.DataFrame(sim_rets)\n", 221 | " # run the \"back\"-test\n", 222 | " btr = erk.run_cppi(risky_r=pd.DataFrame(risky_r),riskfree_rate=riskfree_rate,m=m, start=start, floor=floor)\n", 223 | " wealth = btr[\"Wealth\"]\n", 224 | "\n", 225 | " # calculate terminal wealth stats\n", 226 | " y_max=wealth.values.max()*y_max/100\n", 227 | " terminal_wealth = wealth.iloc[-1]\n", 228 | " \n", 229 | " tw_mean = terminal_wealth.mean()\n", 230 | " tw_median = terminal_wealth.median()\n", 231 | " failure_mask = np.less(terminal_wealth, start*floor)\n", 232 | " n_failures = failure_mask.sum()\n", 233 | " p_fail = n_failures/n_scenarios\n", 234 | "\n", 235 | " e_shortfall = np.dot(terminal_wealth-start*floor, failure_mask)/n_failures if n_failures > 0 else 0.0\n", 236 | "\n", 237 | " # Plot!\n", 238 | " fig, (wealth_ax, hist_ax) = plt.subplots(nrows=1, ncols=2, sharey=True, gridspec_kw={'width_ratios':[3,2]}, figsize=(24, 9))\n", 239 | " plt.subplots_adjust(wspace=0.0)\n", 240 | " \n", 241 | " wealth.plot(ax=wealth_ax, legend=False, alpha=0.3, color=\"indianred\")\n", 242 | " wealth_ax.axhline(y=start, ls=\":\", color=\"black\")\n", 243 | " wealth_ax.axhline(y=start*floor, ls=\"--\", color=\"red\")\n", 244 | " wealth_ax.set_ylim(top=y_max)\n", 245 | " \n", 246 | " terminal_wealth.plot.hist(ax=hist_ax, bins=50, ec='w', fc='indianred', orientation='horizontal')\n", 247 | " hist_ax.axhline(y=start, ls=\":\", color=\"black\")\n", 248 | " hist_ax.axhline(y=tw_mean, ls=\":\", color=\"blue\")\n", 249 | " hist_ax.axhline(y=tw_median, ls=\":\", color=\"purple\")\n", 250 | " hist_ax.annotate(f\"Mean: ${int(tw_mean)}\", xy=(.7, .9),xycoords='axes fraction', fontsize=24)\n", 251 | " hist_ax.annotate(f\"Median: ${int(tw_median)}\", xy=(.7, .85),xycoords='axes fraction', fontsize=24)\n", 252 | " if (floor > 0.01):\n", 253 | " hist_ax.axhline(y=start*floor, ls=\"--\", color=\"red\", linewidth=3)\n", 254 | " hist_ax.annotate(f\"Violations: {n_failures} ({p_fail*100:2.2f}%)\\nE(shortfall)=${e_shortfall:2.2f}\", xy=(.7, .7), xycoords='axes fraction', fontsize=24)\n", 255 | "\n", 256 | "cppi_controls = widgets.interactive(show_cppi,\n", 257 | " n_scenarios=widgets.IntSlider(min=1, max=1000, step=5, value=50), \n", 258 | " mu=(0., +.2, .01),\n", 259 | " sigma=(0, .3, .05),\n", 260 | " floor=(0, 2, .1),\n", 261 | " m=(1, 5, .5),\n", 262 | " riskfree_rate=(0, .05, .01),\n", 263 | " steps_per_year=widgets.IntSlider(min=1, max=12, step=1, value=12,\n", 264 | " description=\"Rebals/Year\"),\n", 265 | " y_max=widgets.IntSlider(min=0, max=100, step=1, value=100,\n", 266 | " description=\"Zoom Y Axis\")\n", 267 | ")\n", 268 | "display(cppi_controls)" 269 | ] 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "metadata": {}, 274 | "source": [ 275 | "## SOME INSIGHTS" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "**Consider the Monte Carlo Simulation we ran for CPPI. Assume there is no floor set (i.e. Floor is set to Zero) As you increase the number of scenarios, which of the following would you expect:**\n", 283 | "- The difference in terminal wealth between the Worst Scenario and the Best Scenario will INCREASE" 284 | ] 285 | }, 286 | { 287 | "cell_type": "markdown", 288 | "metadata": {}, 289 | "source": [ 290 | "**As you increase the FLOOR, the WORST CASE scenario will:**\n", 291 | "- INCREASE" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "**Assume a non-zero floor that is less than the starting wealth. As you increase mu and keep other parameters fixed, you would expect that the terminal wealth:**\n", 299 | "- INCREASES" 300 | ] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "metadata": {}, 305 | "source": [ 306 | "**All other things being equal, which of these changes will cause an INCREASE in floor violations**\n", 307 | "- Increasing both “m” and “sigma”" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "**All other things being equal, which of these changes will cause an INCREASE in floor violations**\n", 315 | "- Increasing “m” but decreasing “rebals per year”" 316 | ] 317 | }, 318 | { 319 | "cell_type": "markdown", 320 | "metadata": {}, 321 | "source": [ 322 | "**All other things being equal, which of these changes will cause in INCREASE in Expected Shortfall**\n", 323 | "- Increasing “m” but decreasing “rebals per year”" 324 | ] 325 | }, 326 | { 327 | "cell_type": "markdown", 328 | "metadata": {}, 329 | "source": [ 330 | "**Parameter changes that increase the probability of floor violations will also tend to increase the Expected Shortfall. This statement is:**\n", 331 | "- TRUE" 332 | ] 333 | }, 334 | { 335 | "cell_type": "markdown", 336 | "metadata": {}, 337 | "source": [ 338 | "**A CPPI Based Principal Protection Strategy aims to return at least the invested principal by setting the floor equal to the initial value of the assets. Which of the following is true:**\n", 339 | "- It is only possible to run a CPPI based Principal Protection Strategy if the risk free rate is greater than or equal to 0" 340 | ] 341 | }, 342 | { 343 | "cell_type": "markdown", 344 | "metadata": {}, 345 | "source": [ 346 | "**A CPPI based Principal Protection Strategy with 12 rebals per year can have a zero expected shortfall only if:**\n", 347 | "- m = 1" 348 | ] 349 | }, 350 | { 351 | "cell_type": "markdown", 352 | "metadata": {}, 353 | "source": [ 354 | "**All other things being equal, A CPPI based Principal Protection Strategy is more likely to have a final negative return if:**\n", 355 | "- sigma increases" 356 | ] 357 | }, 358 | { 359 | "cell_type": "markdown", 360 | "metadata": {}, 361 | "source": [ 362 | "**All other things being equal, A CPPI based Principal Protection Strategy is more likely to have a final negative return if:**\n", 363 | "- sigma increases" 364 | ] 365 | } 366 | ], 367 | "metadata": { 368 | "kernelspec": { 369 | "display_name": "Python 3", 370 | "language": "python", 371 | "name": "python3" 372 | }, 373 | "language_info": { 374 | "codemirror_mode": { 375 | "name": "ipython", 376 | "version": 3 377 | }, 378 | "file_extension": ".py", 379 | "mimetype": "text/x-python", 380 | "name": "python", 381 | "nbconvert_exporter": "python", 382 | "pygments_lexer": "ipython3", 383 | "version": "3.8.5" 384 | } 385 | }, 386 | "nbformat": 4, 387 | "nbformat_minor": 4 388 | } 389 | -------------------------------------------------------------------------------- /stock-price-analysis-with-spark/AMZN.csv: -------------------------------------------------------------------------------- 1 | Date,Open,High,Low,Close,AdjClose,Volume 2 | 2019-07-15,2021.400024,2022.900024,2001.550049,2020.989990,2020.989990,2981300 3 | 2019-07-16,2010.579956,2026.319946,2001.219971,2009.900024,2009.900024,2618200 4 | 2019-07-17,2007.050049,2012.000000,1992.030029,1992.030029,1992.030029,2558800 5 | 2019-07-18,1980.010010,1987.500000,1951.550049,1977.900024,1977.900024,3504300 6 | 2019-07-19,1991.209961,1996.000000,1962.229980,1964.520020,1964.520020,3185600 7 | 2019-07-22,1971.140015,1989.000000,1958.260010,1985.630005,1985.630005,2900000 8 | 2019-07-23,1995.989990,1997.790039,1973.130005,1994.489990,1994.489990,2703500 9 | 2019-07-24,1969.300049,2001.300049,1965.869995,2000.810059,2000.810059,2631300 10 | 2019-07-25,2001.000000,2001.199951,1972.719971,1973.819946,1973.819946,4136500 11 | 2019-07-26,1942.000000,1950.900024,1924.510010,1943.050049,1943.050049,4927100 12 | 2019-07-29,1930.000000,1932.229980,1890.540039,1912.449951,1912.449951,4493200 13 | 2019-07-30,1891.119995,1909.890015,1883.479980,1898.530029,1898.530029,2910900 14 | 2019-07-31,1898.109985,1899.550049,1849.439941,1866.780029,1866.780029,4470700 15 | 2019-08-01,1871.719971,1897.920044,1844.010010,1855.319946,1855.319946,4713300 16 | 2019-08-02,1845.069946,1846.359985,1808.020020,1823.239990,1823.239990,4956200 17 | 2019-08-05,1770.219971,1788.670044,1748.780029,1765.130005,1765.130005,6058200 18 | 2019-08-06,1792.229980,1793.770020,1753.400024,1787.829956,1787.829956,5070300 19 | 2019-08-07,1773.989990,1798.930054,1757.000000,1793.400024,1793.400024,4526900 20 | 2019-08-08,1806.000000,1834.260010,1798.109985,1832.890015,1832.890015,3701200 21 | 2019-08-09,1828.949951,1831.089966,1802.219971,1807.579956,1807.579956,2879800 22 | 2019-08-12,1795.989990,1800.979980,1777.000000,1784.920044,1784.920044,2905500 23 | 2019-08-13,1783.000000,1831.739990,1780.000000,1824.339966,1824.339966,3994000 24 | 2019-08-14,1793.010010,1795.650024,1757.219971,1762.959961,1762.959961,4893600 25 | 2019-08-15,1781.989990,1788.000000,1761.959961,1776.119995,1776.119995,3759100 26 | 2019-08-16,1792.890015,1802.910034,1784.550049,1792.569946,1792.569946,3018000 27 | 2019-08-19,1818.079956,1826.000000,1812.609985,1816.119995,1816.119995,2816300 28 | 2019-08-20,1814.500000,1816.819946,1799.880005,1801.380005,1801.380005,1929500 29 | 2019-08-21,1819.390015,1829.579956,1815.000000,1823.540039,1823.540039,2031800 30 | 2019-08-22,1828.000000,1829.410034,1800.099976,1804.660034,1804.660034,2653500 31 | 2019-08-23,1793.030029,1804.900024,1745.229980,1749.619995,1749.619995,5270800 32 | 2019-08-26,1766.910034,1770.000000,1743.510010,1768.869995,1768.869995,3080000 33 | 2019-08-27,1775.729980,1779.400024,1746.680054,1761.829956,1761.829956,3019700 34 | 2019-08-28,1755.000000,1767.859985,1744.050049,1764.250000,1764.250000,2419700 35 | 2019-08-29,1783.000000,1798.550049,1777.250000,1786.400024,1786.400024,3015100 36 | 2019-08-30,1797.489990,1799.739990,1764.569946,1776.290039,1776.290039,3058700 37 | 2019-09-03,1770.000000,1800.800049,1768.000000,1789.839966,1789.839966,3543000 38 | 2019-09-04,1805.000000,1807.630005,1796.229980,1800.619995,1800.619995,2324100 39 | 2019-09-05,1821.949951,1842.000000,1815.579956,1840.719971,1840.719971,3310800 40 | 2019-09-06,1838.219971,1840.650024,1826.400024,1833.510010,1833.510010,2496900 41 | 2019-09-09,1841.000000,1850.000000,1824.609985,1831.349976,1831.349976,2999500 42 | 2019-09-10,1822.750000,1825.810059,1805.339966,1820.550049,1820.550049,2613900 43 | 2019-09-11,1812.140015,1833.420044,1809.079956,1822.989990,1822.989990,2432800 44 | 2019-09-12,1837.630005,1853.660034,1834.280029,1843.550049,1843.550049,2823500 45 | 2019-09-13,1842.010010,1846.119995,1835.170044,1839.339966,1839.339966,1971300 46 | 2019-09-16,1824.020020,1825.689941,1800.199951,1807.839966,1807.839966,3675500 47 | 2019-09-17,1807.079956,1823.989990,1804.099976,1822.550049,1822.550049,1982400 48 | 2019-09-18,1817.040039,1822.060059,1795.500000,1817.459961,1817.459961,2505600 49 | 2019-09-19,1821.020020,1832.569946,1817.900024,1821.500000,1821.500000,2031500 50 | 2019-09-20,1821.709961,1830.630005,1780.920044,1794.160034,1794.160034,5341900 51 | 2019-09-23,1777.000000,1792.699951,1767.319946,1785.300049,1785.300049,2922300 52 | 2019-09-24,1790.609985,1795.709961,1735.550049,1741.609985,1741.609985,4616000 53 | 2019-09-25,1747.359985,1773.000000,1723.000000,1768.329956,1768.329956,3493200 54 | 2019-09-26,1762.790039,1763.369995,1731.500000,1739.839966,1739.839966,3536800 55 | 2019-09-27,1748.000000,1749.119995,1713.819946,1725.449951,1725.449951,3907200 56 | 2019-09-30,1726.989990,1737.459961,1709.219971,1735.910034,1735.910034,2644700 57 | 2019-10-01,1746.000000,1755.599976,1728.410034,1735.650024,1735.650024,3084500 58 | 2019-10-02,1727.739990,1728.890015,1705.000000,1713.229980,1713.229980,3301100 59 | 2019-10-03,1713.000000,1725.000000,1685.060059,1724.420044,1724.420044,3468200 60 | 2019-10-04,1726.020020,1740.579956,1719.229980,1739.650024,1739.650024,2471900 61 | 2019-10-07,1731.630005,1747.829956,1723.699951,1732.660034,1732.660034,2154700 62 | 2019-10-08,1722.489990,1727.000000,1705.000000,1705.510010,1705.510010,2542000 63 | 2019-10-09,1719.609985,1729.949951,1714.359985,1721.989990,1721.989990,2043500 64 | 2019-10-10,1725.239990,1738.290039,1713.750000,1720.260010,1720.260010,2575200 65 | 2019-10-11,1742.920044,1745.449951,1729.859985,1731.920044,1731.920044,3255000 66 | 2019-10-14,1728.910034,1741.890015,1722.000000,1736.430054,1736.430054,1910200 67 | 2019-10-15,1742.140015,1776.449951,1740.619995,1767.380005,1767.380005,3111700 68 | 2019-10-16,1773.329956,1786.239990,1770.520020,1777.430054,1777.430054,2763400 69 | 2019-10-17,1796.489990,1798.849976,1782.020020,1787.479980,1787.479980,2647400 70 | 2019-10-18,1787.800049,1793.979980,1749.199951,1757.510010,1757.510010,3362500 71 | 2019-10-21,1769.660034,1785.880005,1765.000000,1785.660034,1785.660034,2130400 72 | 2019-10-22,1788.150024,1789.780029,1762.000000,1765.729980,1765.729980,2111700 73 | 2019-10-23,1761.300049,1770.050049,1742.000000,1762.170044,1762.170044,2138200 74 | 2019-10-24,1771.089966,1788.339966,1760.270020,1780.780029,1780.780029,4446100 75 | 2019-10-25,1697.550049,1764.209961,1695.000000,1761.329956,1761.329956,9626400 76 | 2019-10-28,1748.060059,1778.699951,1742.500000,1777.079956,1777.079956,3708900 77 | 2019-10-29,1774.810059,1777.000000,1755.810059,1762.709961,1762.709961,2276900 78 | 2019-10-30,1760.239990,1782.380005,1759.119995,1779.989990,1779.989990,2449400 79 | 2019-10-31,1775.989990,1792.000000,1771.479980,1776.660034,1776.660034,2781200 80 | 2019-11-01,1788.010010,1797.449951,1785.209961,1791.439941,1791.439941,2790400 81 | 2019-11-04,1801.010010,1815.060059,1801.010010,1804.660034,1804.660034,2771900 82 | 2019-11-05,1809.160034,1810.250000,1794.000000,1801.709961,1801.709961,1885500 83 | 2019-11-06,1801.000000,1802.500000,1788.579956,1795.770020,1795.770020,2029800 84 | 2019-11-07,1803.760010,1805.900024,1783.479980,1788.199951,1788.199951,2651100 85 | 2019-11-08,1787.890015,1789.880005,1774.040039,1785.880005,1785.880005,2123300 86 | 2019-11-11,1778.000000,1780.000000,1767.130005,1771.650024,1771.650024,1946000 87 | 2019-11-12,1774.660034,1786.219971,1771.910034,1778.000000,1778.000000,2037600 88 | 2019-11-13,1773.390015,1775.000000,1747.319946,1753.109985,1753.109985,2989500 89 | 2019-11-14,1751.430054,1766.589966,1749.560059,1754.599976,1754.599976,2264800 90 | 2019-11-15,1760.050049,1761.680054,1732.859985,1739.489990,1739.489990,3927600 91 | 2019-11-18,1738.300049,1753.699951,1722.709961,1752.530029,1752.530029,2839500 92 | 2019-11-19,1756.989990,1760.680054,1743.030029,1752.790039,1752.790039,2270800 93 | 2019-11-20,1749.140015,1762.520020,1734.119995,1745.530029,1745.530029,2790000 94 | 2019-11-21,1743.000000,1746.869995,1730.359985,1734.709961,1734.709961,2662900 95 | 2019-11-22,1739.020020,1746.430054,1731.000000,1745.719971,1745.719971,2479100 96 | 2019-11-25,1753.250000,1777.420044,1753.239990,1773.839966,1773.839966,3486200 97 | 2019-11-26,1779.920044,1797.030029,1778.349976,1796.939941,1796.939941,3181200 98 | 2019-11-27,1801.000000,1824.500000,1797.310059,1818.510010,1818.510010,3025600 99 | 2019-11-29,1817.780029,1824.689941,1800.790039,1800.800049,1800.800049,1923400 100 | 2019-12-02,1804.400024,1805.550049,1762.680054,1781.599976,1781.599976,3925600 101 | 2019-12-03,1760.000000,1772.869995,1747.229980,1769.959961,1769.959961,3380900 102 | 2019-12-04,1774.010010,1789.089966,1760.219971,1760.689941,1760.689941,2670100 103 | 2019-12-05,1763.500000,1763.500000,1740.000000,1740.479980,1740.479980,2823800 104 | 2019-12-06,1751.199951,1754.400024,1740.130005,1751.599976,1751.599976,3117400 105 | 2019-12-09,1750.660034,1766.890015,1745.609985,1749.510010,1749.510010,2442800 106 | 2019-12-10,1747.400024,1750.670044,1735.000000,1739.209961,1739.209961,2514300 107 | 2019-12-11,1741.670044,1750.000000,1735.709961,1748.719971,1748.719971,2097600 108 | 2019-12-12,1750.000000,1764.000000,1745.439941,1760.329956,1760.329956,3095900 109 | 2019-12-13,1765.000000,1768.989990,1755.000000,1760.939941,1760.939941,2745700 110 | 2019-12-16,1767.000000,1769.500000,1757.050049,1769.209961,1769.209961,3145200 111 | 2019-12-17,1778.010010,1792.000000,1777.390015,1790.660034,1790.660034,3644400 112 | 2019-12-18,1795.020020,1798.199951,1782.359985,1784.030029,1784.030029,3351400 113 | 2019-12-19,1780.500000,1792.989990,1774.060059,1792.280029,1792.280029,2652800 114 | 2019-12-20,1799.619995,1802.969971,1782.449951,1786.500000,1786.500000,5150800 115 | 2019-12-23,1788.260010,1793.000000,1784.510010,1793.000000,1793.000000,2136400 116 | 2019-12-24,1793.810059,1795.569946,1787.579956,1789.209961,1789.209961,881300 117 | 2019-12-26,1801.010010,1870.459961,1799.500000,1868.770020,1868.770020,6005400 118 | 2019-12-27,1882.920044,1901.400024,1866.010010,1869.800049,1869.800049,6186600 119 | 2019-12-30,1874.000000,1884.000000,1840.619995,1846.890015,1846.890015,3674700 120 | 2019-12-31,1842.000000,1853.260010,1832.229980,1847.839966,1847.839966,2506500 121 | 2020-01-02,1875.000000,1898.010010,1864.150024,1898.010010,1898.010010,4029000 122 | 2020-01-03,1864.500000,1886.199951,1864.500000,1874.969971,1874.969971,3764400 123 | 2020-01-06,1860.000000,1903.689941,1860.000000,1902.880005,1902.880005,4061800 124 | 2020-01-07,1904.500000,1913.890015,1892.040039,1906.859985,1906.859985,4044900 125 | 2020-01-08,1898.040039,1911.000000,1886.439941,1891.969971,1891.969971,3508000 126 | 2020-01-09,1909.890015,1917.819946,1895.800049,1901.050049,1901.050049,3167300 127 | 2020-01-10,1905.369995,1906.939941,1880.000000,1883.160034,1883.160034,2853700 128 | 2020-01-13,1891.310059,1898.000000,1880.800049,1891.300049,1891.300049,2780800 129 | 2020-01-14,1885.880005,1887.109985,1858.550049,1869.439941,1869.439941,3440900 130 | 2020-01-15,1872.250000,1878.859985,1855.089966,1862.020020,1862.020020,2896600 131 | 2020-01-16,1882.989990,1885.589966,1866.020020,1877.939941,1877.939941,2659500 132 | 2020-01-17,1885.890015,1886.640015,1857.250000,1864.719971,1864.719971,3997300 133 | 2020-01-21,1865.000000,1894.270020,1860.000000,1892.000000,1892.000000,3707800 134 | 2020-01-22,1896.089966,1902.500000,1883.339966,1887.459961,1887.459961,3216300 135 | 2020-01-23,1885.109985,1889.979980,1872.760010,1884.579956,1884.579956,2484600 136 | 2020-01-24,1891.369995,1894.989990,1847.439941,1861.640015,1861.640015,3766200 137 | 2020-01-27,1820.000000,1841.000000,1815.339966,1828.339966,1828.339966,3528500 138 | 2020-01-28,1840.500000,1858.109985,1830.020020,1853.250000,1853.250000,2808000 139 | 2020-01-29,1864.000000,1874.750000,1855.020020,1858.000000,1858.000000,2088000 140 | 2020-01-30,1858.000000,1872.869995,1850.609985,1870.680054,1870.680054,6327400 141 | 2020-01-31,2051.469971,2055.719971,2002.270020,2008.719971,2008.719971,15567300 142 | 2020-02-03,2010.599976,2048.500000,2000.250000,2004.199951,2004.199951,5899100 143 | 2020-02-04,2029.880005,2059.800049,2015.369995,2049.669922,2049.669922,5289300 144 | 2020-02-05,2071.020020,2071.020020,2032.000000,2039.869995,2039.869995,4376200 145 | 2020-02-06,2041.020020,2056.300049,2024.800049,2050.229980,2050.229980,3183000 146 | 2020-02-07,2041.989990,2098.530029,2038.099976,2079.280029,2079.280029,5095300 147 | 2020-02-10,2085.010010,2135.600098,2084.959961,2133.909912,2133.909912,5056200 148 | 2020-02-11,2150.899902,2185.949951,2136.000000,2150.800049,2150.800049,5746000 149 | 2020-02-12,2163.199951,2180.250000,2155.290039,2160.000000,2160.000000,3334300 150 | 2020-02-13,2144.989990,2170.280029,2142.000000,2149.870117,2149.870117,3031800 151 | 2020-02-14,2155.679932,2159.040039,2125.889893,2134.870117,2134.870117,2606200 152 | 2020-02-18,2125.020020,2166.070068,2124.110107,2155.669922,2155.669922,2945600 153 | 2020-02-19,2167.800049,2185.100098,2161.120117,2170.219971,2170.219971,2561200 154 | 2020-02-20,2173.070068,2176.790039,2127.449951,2153.100098,2153.100098,3131300 155 | 2020-02-21,2142.149902,2144.550049,2088.000000,2095.969971,2095.969971,4646300 156 | 2020-02-24,2003.180054,2039.300049,1987.969971,2009.290039,2009.290039,6547000 157 | 2020-02-25,2026.420044,2034.599976,1958.420044,1972.739990,1972.739990,6219100 158 | 2020-02-26,1970.280029,2014.670044,1960.449951,1979.589966,1979.589966,5224600 159 | 2020-02-27,1934.380005,1975.000000,1882.760010,1884.300049,1884.300049,8112100 160 | 2020-02-28,1814.630005,1889.760010,1811.130005,1883.750000,1883.750000,9493800 161 | 2020-03-02,1906.489990,1954.510010,1870.000000,1953.949951,1953.949951,6761700 162 | 2020-03-03,1975.369995,1996.329956,1888.089966,1908.989990,1908.989990,7534500 163 | 2020-03-04,1946.569946,1978.000000,1922.000000,1975.829956,1975.829956,4772900 164 | 2020-03-05,1933.000000,1960.719971,1910.000000,1924.030029,1924.030029,4748200 165 | 2020-03-06,1875.000000,1910.869995,1869.500000,1901.089966,1901.089966,5273600 166 | 2020-03-09,1773.859985,1862.770020,1761.290039,1800.609985,1800.609985,7813200 167 | 2020-03-10,1870.880005,1894.270020,1818.170044,1891.819946,1891.819946,7133300 168 | 2020-03-11,1857.849976,1871.319946,1801.500000,1820.859985,1820.859985,5624800 169 | 2020-03-12,1721.979980,1765.000000,1675.000000,1676.609985,1676.609985,11346200 170 | 2020-03-13,1755.000000,1786.310059,1680.619995,1785.000000,1785.000000,8809700 171 | 2020-03-16,1641.510010,1759.449951,1626.030029,1689.150024,1689.150024,8917300 172 | 2020-03-17,1775.469971,1857.780029,1689.239990,1807.839966,1807.839966,10917100 173 | 2020-03-18,1750.000000,1841.660034,1745.000000,1830.000000,1830.000000,9645200 174 | 2020-03-19,1860.000000,1945.000000,1832.650024,1880.930054,1880.930054,10399900 175 | 2020-03-20,1926.310059,1957.000000,1820.729980,1846.089966,1846.089966,9817900 176 | 2020-03-23,1827.750000,1919.400024,1812.000000,1902.829956,1902.829956,7808500 177 | 2020-03-24,1951.500000,1955.000000,1900.339966,1940.099976,1940.099976,7147100 178 | 2020-03-25,1920.689941,1950.260010,1885.780029,1885.839966,1885.839966,6479100 179 | 2020-03-26,1902.000000,1956.489990,1889.290039,1955.489990,1955.489990,6221300 180 | 2020-03-27,1930.859985,1939.790039,1899.920044,1900.099976,1900.099976,5387900 181 | 2020-03-30,1922.829956,1973.630005,1912.339966,1963.949951,1963.949951,6126100 182 | 2020-03-31,1964.349976,1993.020020,1944.010010,1949.719971,1949.719971,5123600 183 | 2020-04-01,1932.969971,1944.959961,1893.000000,1907.699951,1907.699951,4121900 184 | 2020-04-02,1901.640015,1927.530029,1890.000000,1918.829956,1918.829956,4336000 185 | 2020-04-03,1911.150024,1926.329956,1889.150024,1906.589966,1906.589966,3609900 186 | 2020-04-06,1936.000000,1998.520020,1930.020020,1997.589966,1997.589966,5773200 187 | 2020-04-07,2017.109985,2035.719971,1997.619995,2011.599976,2011.599976,5114000 188 | 2020-04-08,2021.000000,2044.000000,2011.150024,2043.000000,2043.000000,3977300 189 | 2020-04-09,2044.300049,2053.000000,2017.660034,2042.760010,2042.760010,4655600 190 | 2020-04-13,2040.000000,2180.000000,2038.000000,2168.870117,2168.870117,6716700 191 | 2020-04-14,2200.469971,2292.000000,2186.209961,2283.320068,2283.320068,8087200 192 | 2020-04-15,2257.679932,2333.370117,2245.000000,2307.679932,2307.679932,6866600 193 | 2020-04-16,2346.000000,2461.000000,2335.000000,2408.189941,2408.189941,12038200 194 | 2020-04-17,2372.330078,2400.000000,2316.020020,2375.000000,2375.000000,7930000 195 | 2020-04-20,2389.949951,2444.979980,2386.050049,2393.610107,2393.610107,5770700 196 | 2020-04-21,2416.610107,2428.310059,2279.659912,2328.120117,2328.120117,7476700 197 | 2020-04-22,2369.000000,2394.000000,2351.000000,2363.489990,2363.489990,4218300 198 | 2020-04-23,2399.979980,2424.219971,2382.080078,2399.449951,2399.449951,5066600 199 | 2020-04-24,2417.000000,2420.429932,2382.000000,2410.219971,2410.219971,3831800 200 | 2020-04-27,2443.199951,2444.879883,2363.000000,2376.000000,2376.000000,5645600 201 | 2020-04-28,2372.100098,2373.500000,2306.000000,2314.080078,2314.080078,5269400 202 | 2020-04-29,2330.010010,2391.889893,2310.000000,2372.709961,2372.709961,4591600 203 | 2020-04-30,2419.840088,2475.000000,2396.010010,2474.000000,2474.000000,9415000 204 | 2020-05-01,2336.800049,2362.439941,2258.189941,2286.040039,2286.040039,9772600 205 | 2020-05-04,2256.379883,2326.979980,2256.379883,2315.989990,2315.989990,4865900 206 | 2020-05-05,2340.000000,2351.000000,2307.129883,2317.800049,2317.800049,3242500 207 | 2020-05-06,2329.439941,2357.449951,2320.000000,2351.260010,2351.260010,3117800 208 | 2020-05-07,2374.780029,2376.000000,2343.110107,2367.610107,2367.610107,3396400 209 | 2020-05-08,2372.139893,2387.239990,2357.000000,2379.610107,2379.610107,3211200 210 | 2020-05-11,2374.699951,2419.669922,2372.110107,2409.000000,2409.000000,3253700 211 | 2020-05-12,2411.850098,2419.000000,2355.000000,2356.949951,2356.949951,3074900 212 | 2020-05-13,2366.800049,2407.699951,2337.800049,2367.919922,2367.919922,4782900 213 | 2020-05-14,2361.010010,2391.370117,2353.209961,2388.850098,2388.850098,3648100 214 | 2020-05-15,2368.520020,2411.000000,2356.370117,2409.780029,2409.780029,4235000 215 | 2020-05-18,2404.350098,2433.000000,2384.010010,2426.260010,2426.260010,4366600 216 | 2020-05-19,2429.830078,2485.000000,2428.969971,2449.330078,2449.330078,4320500 217 | 2020-05-20,2477.870117,2500.010010,2467.270020,2497.939941,2497.939941,3998100 218 | 2020-05-21,2500.000000,2525.449951,2442.540039,2446.739990,2446.739990,5114400 219 | 2020-05-22,2455.010010,2469.850098,2430.129883,2436.879883,2436.879883,2867100 220 | 2020-05-26,2458.000000,2462.000000,2414.060059,2421.860107,2421.860107,3568200 221 | 2020-05-27,2404.989990,2413.580078,2330.000000,2410.389893,2410.389893,5056900 222 | 2020-05-28,2384.330078,2436.969971,2378.229980,2401.100098,2401.100098,3190200 223 | 2020-05-29,2415.939941,2442.370117,2398.199951,2442.370117,2442.370117,3529300 224 | 2020-06-01,2448.000000,2476.929932,2444.169922,2471.040039,2471.040039,2928900 225 | 2020-06-02,2467.000000,2473.530029,2445.310059,2472.409912,2472.409912,2529900 226 | 2020-06-03,2468.010010,2488.000000,2461.169922,2478.399902,2478.399902,2671000 227 | 2020-06-04,2477.429932,2507.540039,2450.010010,2460.600098,2460.600098,2948700 228 | 2020-06-05,2444.510010,2488.649902,2437.129883,2483.000000,2483.000000,3306400 229 | 2020-06-08,2500.199951,2530.000000,2487.340088,2524.060059,2524.060059,3970700 230 | 2020-06-09,2529.439941,2626.429932,2525.000000,2600.860107,2600.860107,5176000 231 | 2020-06-10,2645.000000,2722.350098,2626.260010,2647.449951,2647.449951,4946000 232 | 2020-06-11,2603.500000,2671.379883,2536.229980,2557.959961,2557.959961,5800100 233 | 2020-06-12,2601.209961,2621.479980,2503.350098,2545.020020,2545.020020,5429600 234 | 2020-06-15,2526.600098,2584.000000,2508.000000,2572.679932,2572.679932,3865100 235 | 2020-06-16,2620.000000,2620.000000,2576.000000,2615.270020,2615.270020,3585600 236 | 2020-06-17,2647.500000,2655.000000,2631.820068,2640.979980,2640.979980,2951100 237 | 2020-06-18,2647.010010,2659.639893,2636.110107,2653.979980,2653.979980,2487800 238 | 2020-06-19,2678.080078,2697.429932,2659.000000,2675.010010,2675.010010,5777000 239 | 2020-06-22,2684.500000,2715.000000,2669.000000,2713.820068,2713.820068,3208800 240 | 2020-06-23,2726.020020,2783.110107,2718.040039,2764.409912,2764.409912,4231700 241 | 2020-06-24,2780.000000,2796.000000,2721.000000,2734.399902,2734.399902,4526600 242 | 2020-06-25,2739.550049,2756.229980,2712.139893,2754.580078,2754.580078,2968700 243 | 2020-06-26,2775.060059,2782.570068,2688.000000,2692.870117,2692.870117,6500800 244 | 2020-06-29,2690.010010,2696.800049,2630.080078,2680.379883,2680.379883,4223400 245 | 2020-06-30,2685.070068,2769.629883,2675.030029,2758.820068,2758.820068,3769700 246 | 2020-07-01,2757.989990,2895.000000,2754.000000,2878.699951,2878.699951,6363400 247 | 2020-07-02,2912.010010,2955.560059,2871.100098,2890.300049,2890.300049,6593400 248 | 2020-07-06,2934.969971,3059.879883,2930.000000,3057.040039,3057.040039,6880600 249 | 2020-07-07,3058.550049,3069.550049,2990.000000,3000.120117,3000.120117,5257500 250 | 2020-07-08,3022.610107,3083.969971,3012.429932,3081.110107,3081.110107,5037600 251 | 2020-07-09,3115.989990,3193.879883,3074.000000,3182.629883,3182.629883,6388700 252 | 2020-07-10,3191.760010,3215.000000,3135.699951,3200.000000,3200.000000,5486000 253 | 2020-07-13,3251.060059,3344.290039,3068.389893,3104.000000,3104.000000,7689300 254 | 2020-07-14,3089.000000,3125.500000,2950.000000,3084.000000,3084.000000,7104062 -------------------------------------------------------------------------------- /stock-price-analysis-with-spark/GOOG.csv: -------------------------------------------------------------------------------- 1 | Date,Open,High,Low,Close,AdjClose,Volume 2 | 2019-07-15,1146.859985,1150.819946,1139.400024,1150.339966,1150.339966,903800 3 | 2019-07-16,1146.000000,1158.579956,1145.000000,1153.579956,1153.579956,1238800 4 | 2019-07-17,1150.969971,1158.359985,1145.770020,1146.349976,1146.349976,1170000 5 | 2019-07-18,1141.739990,1147.604980,1132.729980,1146.329956,1146.329956,1291300 6 | 2019-07-19,1148.189941,1151.140015,1129.619995,1130.099976,1130.099976,1647200 7 | 2019-07-22,1133.449951,1139.250000,1124.239990,1138.069946,1138.069946,1301500 8 | 2019-07-23,1144.000000,1146.900024,1131.800049,1146.209961,1146.209961,1093700 9 | 2019-07-24,1131.900024,1144.000000,1126.989990,1137.810059,1137.810059,1589800 10 | 2019-07-25,1137.819946,1141.699951,1120.920044,1132.119995,1132.119995,2209800 11 | 2019-07-26,1224.040039,1265.550049,1224.000000,1250.410034,1250.410034,4805800 12 | 2019-07-29,1241.050049,1247.369995,1228.229980,1239.410034,1239.410034,2223700 13 | 2019-07-30,1225.410034,1234.869995,1223.300049,1225.140015,1225.140015,1453300 14 | 2019-07-31,1223.000000,1234.000000,1207.764038,1216.680054,1216.680054,1725500 15 | 2019-08-01,1214.030029,1234.109985,1205.719971,1209.010010,1209.010010,1698500 16 | 2019-08-02,1200.739990,1206.900024,1188.939941,1193.989990,1193.989990,1645100 17 | 2019-08-05,1170.040039,1175.239990,1140.140015,1152.319946,1152.319946,2597500 18 | 2019-08-06,1163.310059,1179.959961,1160.000000,1169.949951,1169.949951,1709400 19 | 2019-08-07,1156.000000,1178.444946,1149.624023,1173.989990,1173.989990,1444300 20 | 2019-08-08,1182.829956,1205.010010,1173.020020,1204.800049,1204.800049,1468000 21 | 2019-08-09,1197.989990,1203.880005,1183.603027,1188.010010,1188.010010,1065700 22 | 2019-08-12,1179.209961,1184.959961,1167.671997,1174.709961,1174.709961,1003000 23 | 2019-08-13,1171.459961,1204.780029,1171.459961,1197.270020,1197.270020,1294400 24 | 2019-08-14,1176.310059,1182.300049,1160.540039,1164.290039,1164.290039,1578700 25 | 2019-08-15,1163.500000,1175.839966,1162.109985,1167.260010,1167.260010,1218700 26 | 2019-08-16,1179.550049,1182.719971,1171.810059,1177.599976,1177.599976,1313300 27 | 2019-08-19,1190.089966,1206.989990,1190.089966,1198.449951,1198.449951,1231600 28 | 2019-08-20,1195.250000,1196.060059,1182.109985,1182.689941,1182.689941,915500 29 | 2019-08-21,1193.150024,1199.000000,1187.430054,1191.250000,1191.250000,740700 30 | 2019-08-22,1194.069946,1198.011963,1178.579956,1189.530029,1189.530029,947500 31 | 2019-08-23,1181.989990,1194.079956,1147.750000,1151.290039,1151.290039,1687000 32 | 2019-08-26,1157.260010,1169.469971,1152.959961,1168.890015,1168.890015,1226100 33 | 2019-08-27,1180.530029,1182.400024,1161.449951,1167.839966,1167.839966,1077200 34 | 2019-08-28,1161.709961,1176.420044,1157.300049,1171.020020,1171.020020,802000 35 | 2019-08-29,1181.119995,1196.060059,1181.119995,1192.849976,1192.849976,1088400 36 | 2019-08-30,1198.500000,1198.500000,1183.802979,1188.099976,1188.099976,1129800 37 | 2019-09-03,1177.030029,1186.890015,1163.199951,1168.390015,1168.390015,1479900 38 | 2019-09-04,1176.709961,1183.479980,1171.000000,1181.410034,1181.410034,1068900 39 | 2019-09-05,1191.530029,1213.040039,1191.530029,1211.380005,1211.380005,1408100 40 | 2019-09-06,1208.130005,1212.015015,1202.521973,1204.930054,1204.930054,1072100 41 | 2019-09-09,1204.000000,1220.000000,1192.619995,1204.410034,1204.410034,1471900 42 | 2019-09-10,1195.150024,1210.000000,1194.579956,1206.000000,1206.000000,1260100 43 | 2019-09-11,1203.410034,1222.599976,1202.199951,1220.170044,1220.170044,1307000 44 | 2019-09-12,1224.300049,1241.859985,1223.020020,1234.250000,1234.250000,1725900 45 | 2019-09-13,1231.349976,1240.880005,1227.010010,1239.560059,1239.560059,1301400 46 | 2019-09-16,1229.520020,1239.560059,1225.609985,1231.300049,1231.300049,1053300 47 | 2019-09-17,1230.400024,1235.000000,1223.689941,1229.150024,1229.150024,955100 48 | 2019-09-18,1227.510010,1235.609985,1216.530029,1232.410034,1232.410034,1135100 49 | 2019-09-19,1232.060059,1244.439941,1232.020020,1238.709961,1238.709961,996000 50 | 2019-09-20,1233.119995,1243.319946,1223.079956,1229.930054,1229.930054,2270000 51 | 2019-09-23,1226.000000,1239.089966,1224.170044,1234.030029,1234.030029,1062400 52 | 2019-09-24,1240.000000,1246.739990,1210.680054,1218.760010,1218.760010,1583200 53 | 2019-09-25,1215.819946,1248.300049,1210.089966,1246.520020,1246.520020,1453000 54 | 2019-09-26,1241.959961,1245.000000,1232.267944,1241.390015,1241.390015,1538000 55 | 2019-09-27,1243.010010,1244.020020,1214.449951,1225.089966,1225.089966,1353900 56 | 2019-09-30,1220.969971,1226.000000,1212.300049,1219.000000,1219.000000,1404100 57 | 2019-10-01,1219.000000,1231.229980,1203.579956,1205.099976,1205.099976,1273500 58 | 2019-10-02,1196.979980,1196.979980,1171.290039,1176.630005,1176.630005,1615100 59 | 2019-10-03,1180.000000,1189.060059,1162.430054,1187.829956,1187.829956,1621200 60 | 2019-10-04,1191.890015,1211.439941,1189.170044,1209.000000,1209.000000,1162400 61 | 2019-10-07,1204.400024,1218.203979,1203.750000,1207.680054,1207.680054,842900 62 | 2019-10-08,1197.589966,1206.079956,1189.010010,1189.130005,1189.130005,1039300 63 | 2019-10-09,1199.349976,1208.349976,1197.630005,1202.310059,1202.310059,867700 64 | 2019-10-10,1198.579956,1215.000000,1197.339966,1208.670044,1208.670044,846600 65 | 2019-10-11,1222.209961,1228.390015,1213.739990,1215.449951,1215.449951,1272700 66 | 2019-10-14,1212.339966,1226.329956,1211.760010,1217.140015,1217.140015,867500 67 | 2019-10-15,1220.400024,1247.329956,1220.400024,1243.010010,1243.010010,1381700 68 | 2019-10-16,1241.170044,1254.739990,1238.449951,1243.640015,1243.640015,1094600 69 | 2019-10-17,1250.930054,1263.324951,1249.939941,1253.069946,1253.069946,952400 70 | 2019-10-18,1253.459961,1258.890015,1241.079956,1245.489990,1245.489990,1352800 71 | 2019-10-21,1252.260010,1254.629028,1240.599976,1246.150024,1246.150024,1027200 72 | 2019-10-22,1247.849976,1250.599976,1241.380005,1242.800049,1242.800049,1023800 73 | 2019-10-23,1242.359985,1259.890015,1242.359985,1259.130005,1259.130005,911500 74 | 2019-10-24,1260.900024,1264.000000,1253.714966,1260.989990,1260.989990,1028100 75 | 2019-10-25,1251.030029,1269.599976,1250.010010,1265.130005,1265.130005,1213100 76 | 2019-10-28,1275.449951,1299.310059,1272.540039,1290.000000,1290.000000,2613200 77 | 2019-10-29,1276.229980,1281.589966,1257.212036,1262.619995,1262.619995,1886400 78 | 2019-10-30,1252.969971,1269.359985,1252.000000,1261.290039,1261.290039,1408900 79 | 2019-10-31,1261.280029,1267.670044,1250.843018,1260.109985,1260.109985,1455700 80 | 2019-11-01,1265.000000,1274.619995,1260.500000,1273.739990,1273.739990,1670100 81 | 2019-11-04,1276.449951,1294.130005,1276.354980,1291.369995,1291.369995,1501000 82 | 2019-11-05,1292.890015,1298.930054,1291.229004,1292.030029,1292.030029,1282700 83 | 2019-11-06,1289.459961,1293.729980,1282.500000,1291.800049,1291.800049,1152700 84 | 2019-11-07,1294.280029,1323.739990,1294.244995,1308.859985,1308.859985,2030000 85 | 2019-11-08,1305.280029,1318.000000,1304.364990,1311.369995,1311.369995,1251400 86 | 2019-11-11,1303.180054,1306.425049,1297.410034,1299.189941,1299.189941,1011900 87 | 2019-11-12,1300.000000,1310.000000,1295.770020,1298.800049,1298.800049,1085900 88 | 2019-11-13,1294.069946,1304.300049,1293.510010,1298.000000,1298.000000,826700 89 | 2019-11-14,1297.500000,1317.000000,1295.650024,1311.459961,1311.459961,1193500 90 | 2019-11-15,1318.939941,1334.880005,1314.280029,1334.869995,1334.869995,1782600 91 | 2019-11-18,1332.219971,1335.529053,1317.500000,1320.699951,1320.699951,1487400 92 | 2019-11-19,1327.699951,1327.699951,1312.800049,1315.459961,1315.459961,1269200 93 | 2019-11-20,1311.739990,1315.000000,1291.150024,1303.050049,1303.050049,1308600 94 | 2019-11-21,1301.479980,1312.589966,1293.000000,1301.349976,1301.349976,995500 95 | 2019-11-22,1305.619995,1308.729980,1291.410034,1295.339966,1295.339966,1385700 96 | 2019-11-25,1299.180054,1311.310059,1298.130005,1306.689941,1306.689941,1036200 97 | 2019-11-26,1309.859985,1314.800049,1305.089966,1313.550049,1313.550049,1069700 98 | 2019-11-27,1315.000000,1318.359985,1309.630005,1312.989990,1312.989990,995600 99 | 2019-11-29,1307.119995,1310.204956,1303.969971,1304.959961,1304.959961,587000 100 | 2019-12-02,1301.000000,1305.829956,1281.000000,1289.920044,1289.920044,1510900 101 | 2019-12-03,1279.569946,1298.461060,1279.000000,1295.280029,1295.280029,1143800 102 | 2019-12-04,1307.010010,1325.800049,1304.869995,1320.540039,1320.540039,1537500 103 | 2019-12-05,1328.000000,1329.358032,1316.439941,1328.130005,1328.130005,1212700 104 | 2019-12-06,1333.439941,1344.000000,1333.439941,1340.619995,1340.619995,1314800 105 | 2019-12-09,1338.040039,1359.449951,1337.839966,1343.560059,1343.560059,1354300 106 | 2019-12-10,1341.500000,1349.974976,1336.040039,1344.660034,1344.660034,1094100 107 | 2019-12-11,1350.839966,1351.199951,1342.670044,1345.020020,1345.020020,850400 108 | 2019-12-12,1345.939941,1355.775024,1340.500000,1350.270020,1350.270020,1281000 109 | 2019-12-13,1347.949951,1353.093018,1343.869995,1347.829956,1347.829956,1549600 110 | 2019-12-16,1356.500000,1364.680054,1352.670044,1361.170044,1361.170044,1397300 111 | 2019-12-17,1362.890015,1365.000000,1351.322998,1355.119995,1355.119995,1854000 112 | 2019-12-18,1356.599976,1360.469971,1351.000000,1352.619995,1352.619995,1522600 113 | 2019-12-19,1351.819946,1358.099976,1348.984985,1356.040039,1356.040039,1469900 114 | 2019-12-20,1363.349976,1363.640015,1349.000000,1349.589966,1349.589966,3315000 115 | 2019-12-23,1355.869995,1359.800049,1346.510010,1348.839966,1348.839966,883100 116 | 2019-12-24,1348.500000,1350.260010,1342.780029,1343.560059,1343.560059,347500 117 | 2019-12-26,1346.170044,1361.327026,1344.469971,1360.400024,1360.400024,667500 118 | 2019-12-27,1362.989990,1364.530029,1349.310059,1351.890015,1351.890015,1038400 119 | 2019-12-30,1350.000000,1353.000000,1334.020020,1336.140015,1336.140015,1050900 120 | 2019-12-31,1330.109985,1338.000000,1329.084961,1337.020020,1337.020020,961800 121 | 2020-01-02,1341.550049,1368.140015,1341.550049,1367.369995,1367.369995,1406600 122 | 2020-01-03,1347.859985,1372.500000,1345.543945,1360.660034,1360.660034,1186400 123 | 2020-01-06,1350.000000,1396.500000,1350.000000,1394.209961,1394.209961,1732300 124 | 2020-01-07,1397.939941,1402.989990,1390.380005,1393.339966,1393.339966,1502700 125 | 2020-01-08,1392.079956,1411.579956,1390.839966,1404.319946,1404.319946,1528000 126 | 2020-01-09,1420.569946,1427.329956,1410.270020,1419.829956,1419.829956,1500900 127 | 2020-01-10,1427.560059,1434.928955,1418.349976,1429.729980,1429.729980,1820700 128 | 2020-01-13,1436.130005,1440.520020,1426.020020,1439.229980,1439.229980,1652300 129 | 2020-01-14,1439.010010,1441.800049,1428.369995,1430.880005,1430.880005,1558900 130 | 2020-01-15,1430.209961,1441.395020,1430.209961,1439.199951,1439.199951,1282700 131 | 2020-01-16,1447.439941,1451.989990,1440.920044,1451.699951,1451.699951,1173700 132 | 2020-01-17,1462.910034,1481.295044,1458.219971,1480.390015,1480.390015,2396200 133 | 2020-01-21,1479.119995,1491.849976,1471.199951,1484.400024,1484.400024,2036700 134 | 2020-01-22,1491.000000,1503.213989,1484.930054,1485.949951,1485.949951,1610800 135 | 2020-01-23,1487.640015,1495.520020,1482.099976,1486.650024,1486.650024,1351200 136 | 2020-01-24,1493.589966,1495.494995,1465.250000,1466.709961,1466.709961,1784600 137 | 2020-01-27,1431.000000,1438.069946,1421.199951,1433.900024,1433.900024,1755200 138 | 2020-01-28,1443.000000,1456.000000,1432.469971,1452.560059,1452.560059,1577400 139 | 2020-01-29,1458.800049,1465.430054,1446.739990,1458.630005,1458.630005,1077700 140 | 2020-01-30,1439.959961,1457.280029,1436.400024,1455.839966,1455.839966,1339400 141 | 2020-01-31,1468.900024,1470.130005,1428.530029,1434.229980,1434.229980,2417200 142 | 2020-02-03,1462.000000,1490.000000,1458.989990,1485.939941,1485.939941,3055200 143 | 2020-02-04,1457.069946,1469.500000,1426.300049,1447.069946,1447.069946,3933000 144 | 2020-02-05,1462.420044,1463.839966,1430.560059,1448.229980,1448.229980,1986200 145 | 2020-02-06,1450.329956,1482.000000,1449.569946,1476.229980,1476.229980,1679400 146 | 2020-02-07,1467.300049,1485.839966,1466.349976,1479.229980,1479.229980,1172300 147 | 2020-02-10,1474.319946,1509.500000,1474.319946,1508.680054,1508.680054,1419900 148 | 2020-02-11,1511.810059,1529.630005,1505.637939,1508.790039,1508.790039,1344600 149 | 2020-02-12,1514.479980,1520.694946,1508.109985,1518.270020,1518.270020,1167600 150 | 2020-02-13,1512.689941,1527.180054,1504.599976,1514.660034,1514.660034,929500 151 | 2020-02-14,1515.599976,1520.739990,1507.339966,1520.739990,1520.739990,1197800 152 | 2020-02-18,1515.000000,1531.630005,1512.589966,1519.670044,1519.670044,1120700 153 | 2020-02-19,1525.069946,1532.105957,1521.400024,1526.689941,1526.689941,949300 154 | 2020-02-20,1522.000000,1529.640015,1506.819946,1518.150024,1518.150024,1096600 155 | 2020-02-21,1508.030029,1512.214966,1480.439941,1485.109985,1485.109985,1731700 156 | 2020-02-24,1426.109985,1436.969971,1411.390015,1421.589966,1421.589966,2867100 157 | 2020-02-25,1433.000000,1438.140015,1382.400024,1388.449951,1388.449951,2478300 158 | 2020-02-26,1396.140015,1415.699951,1379.000000,1393.180054,1393.180054,2202400 159 | 2020-02-27,1362.060059,1371.703979,1317.170044,1318.089966,1318.089966,2971100 160 | 2020-02-28,1277.500000,1341.140015,1271.000000,1339.329956,1339.329956,3790600 161 | 2020-03-02,1351.609985,1390.869995,1326.814941,1389.109985,1389.109985,2431500 162 | 2020-03-03,1399.420044,1410.150024,1332.000000,1341.390015,1341.390015,2402300 163 | 2020-03-04,1359.229980,1388.089966,1343.109985,1386.520020,1386.520020,1913300 164 | 2020-03-05,1350.199951,1358.910034,1305.099976,1319.040039,1319.040039,2561300 165 | 2020-03-06,1277.060059,1306.219971,1261.050049,1298.410034,1298.410034,2660600 166 | 2020-03-09,1205.300049,1254.760010,1200.000000,1215.560059,1215.560059,3365400 167 | 2020-03-10,1260.000000,1281.150024,1218.770020,1280.390015,1280.390015,2611400 168 | 2020-03-11,1249.699951,1260.959961,1196.069946,1215.410034,1215.410034,2608500 169 | 2020-03-12,1126.000000,1193.869995,1113.300049,1114.910034,1114.910034,4226700 170 | 2020-03-13,1179.000000,1219.760010,1117.142944,1219.729980,1219.729980,3700100 171 | 2020-03-16,1096.000000,1152.266968,1074.439941,1084.329956,1084.329956,4252400 172 | 2020-03-17,1093.109985,1130.859985,1056.010010,1119.800049,1119.800049,3861500 173 | 2020-03-18,1056.510010,1106.500000,1037.280029,1096.800049,1096.800049,4233400 174 | 2020-03-19,1093.050049,1157.969971,1060.108032,1115.290039,1115.290039,3651100 175 | 2020-03-20,1135.719971,1143.989990,1065.489990,1072.319946,1072.319946,3601800 176 | 2020-03-23,1061.319946,1071.319946,1013.536011,1056.619995,1056.619995,4044100 177 | 2020-03-24,1103.770020,1135.000000,1090.619995,1134.459961,1134.459961,3344500 178 | 2020-03-25,1126.469971,1148.900024,1086.010010,1102.489990,1102.489990,4081500 179 | 2020-03-26,1111.800049,1169.969971,1093.530029,1161.750000,1161.750000,3571700 180 | 2020-03-27,1125.670044,1150.670044,1105.910034,1110.709961,1110.709961,3208500 181 | 2020-03-30,1125.040039,1151.630005,1096.479980,1146.819946,1146.819946,2574100 182 | 2020-03-31,1147.300049,1175.310059,1138.140015,1162.810059,1162.810059,2486400 183 | 2020-04-01,1122.000000,1129.689941,1097.449951,1105.619995,1105.619995,2344200 184 | 2020-04-02,1098.260010,1126.859985,1096.400024,1120.839966,1120.839966,1964900 185 | 2020-04-03,1119.015015,1123.540039,1079.810059,1097.880005,1097.880005,2313400 186 | 2020-04-06,1138.000000,1194.660034,1130.939941,1186.920044,1186.920044,2664700 187 | 2020-04-07,1221.000000,1225.000000,1182.229980,1186.510010,1186.510010,2387300 188 | 2020-04-08,1206.500000,1219.069946,1188.160034,1210.280029,1210.280029,1975100 189 | 2020-04-09,1224.079956,1225.569946,1196.734985,1211.449951,1211.449951,2175400 190 | 2020-04-13,1209.180054,1220.510010,1187.598022,1217.560059,1217.560059,1739800 191 | 2020-04-14,1245.089966,1282.069946,1236.930054,1269.229980,1269.229980,2470400 192 | 2020-04-15,1245.609985,1280.459961,1240.400024,1262.469971,1262.469971,1671700 193 | 2020-04-16,1274.099976,1279.000000,1242.619995,1263.469971,1263.469971,2518100 194 | 2020-04-17,1284.849976,1294.430054,1271.229980,1283.250000,1283.250000,1949000 195 | 2020-04-20,1271.000000,1281.599976,1261.369995,1266.609985,1266.609985,1695500 196 | 2020-04-21,1247.000000,1254.270020,1209.709961,1216.339966,1216.339966,2153000 197 | 2020-04-22,1245.540039,1285.613037,1242.000000,1263.209961,1263.209961,2093100 198 | 2020-04-23,1271.550049,1293.310059,1265.670044,1276.310059,1276.310059,1566200 199 | 2020-04-24,1261.170044,1280.400024,1249.449951,1279.310059,1279.310059,1640400 200 | 2020-04-27,1296.000000,1296.150024,1269.000000,1275.880005,1275.880005,1600600 201 | 2020-04-28,1287.930054,1288.050049,1232.199951,1233.670044,1233.670044,2951300 202 | 2020-04-29,1341.459961,1359.989990,1325.339966,1341.479980,1341.479980,3793600 203 | 2020-04-30,1324.880005,1352.819946,1322.489990,1348.660034,1348.660034,2665400 204 | 2020-05-01,1328.500000,1352.069946,1311.000000,1320.609985,1320.609985,2072500 205 | 2020-05-04,1308.229980,1327.660034,1299.000000,1326.800049,1326.800049,1504000 206 | 2020-05-05,1337.920044,1373.939941,1337.459961,1351.109985,1351.109985,1651500 207 | 2020-05-06,1361.689941,1371.119995,1347.290039,1347.300049,1347.300049,1215400 208 | 2020-05-07,1365.939941,1377.599976,1355.270020,1372.560059,1372.560059,1397600 209 | 2020-05-08,1383.130005,1398.760010,1375.479980,1388.369995,1388.369995,1388100 210 | 2020-05-11,1378.280029,1416.530029,1377.151978,1403.260010,1403.260010,1410600 211 | 2020-05-12,1407.119995,1415.000000,1374.770020,1375.739990,1375.739990,1390600 212 | 2020-05-13,1377.050049,1385.482056,1328.400024,1349.329956,1349.329956,1812600 213 | 2020-05-14,1335.020020,1357.420044,1323.910034,1356.130005,1356.130005,1603100 214 | 2020-05-15,1350.000000,1374.479980,1339.000000,1373.189941,1373.189941,1707700 215 | 2020-05-18,1361.750000,1392.324951,1354.250000,1383.939941,1383.939941,1824000 216 | 2020-05-19,1386.996948,1392.000000,1373.484985,1373.484985,1373.484985,1280600 217 | 2020-05-20,1389.579956,1410.420044,1387.250000,1406.719971,1406.719971,1655400 218 | 2020-05-21,1408.000000,1415.489990,1393.449951,1402.800049,1402.800049,1385000 219 | 2020-05-22,1396.709961,1412.760010,1391.829956,1410.420044,1410.420044,1309400 220 | 2020-05-26,1437.270020,1441.000000,1412.130005,1417.020020,1417.020020,2060600 221 | 2020-05-27,1417.250000,1421.739990,1391.290039,1417.839966,1417.839966,1685800 222 | 2020-05-28,1396.859985,1440.839966,1396.000000,1416.729980,1416.729980,1692200 223 | 2020-05-29,1416.939941,1432.569946,1413.349976,1428.920044,1428.920044,1838100 224 | 2020-06-01,1418.390015,1437.959961,1418.000000,1431.819946,1431.819946,1217100 225 | 2020-06-02,1430.550049,1439.609985,1418.829956,1439.219971,1439.219971,1278100 226 | 2020-06-03,1438.300049,1446.552002,1429.776978,1436.380005,1436.380005,1256200 227 | 2020-06-04,1430.400024,1438.959961,1404.729980,1412.180054,1412.180054,1484300 228 | 2020-06-05,1413.170044,1445.050049,1406.000000,1438.390015,1438.390015,1734900 229 | 2020-06-08,1422.339966,1447.989990,1422.339966,1446.609985,1446.609985,1404200 230 | 2020-06-09,1445.359985,1468.000000,1443.209961,1456.160034,1456.160034,1409200 231 | 2020-06-10,1459.540039,1474.259033,1456.270020,1465.849976,1465.849976,1525200 232 | 2020-06-11,1442.479980,1454.474976,1402.000000,1403.839966,1403.839966,1991300 233 | 2020-06-12,1428.489990,1437.000000,1386.020020,1413.180054,1413.180054,1944200 234 | 2020-06-15,1390.800049,1424.800049,1387.920044,1419.849976,1419.849976,1503900 235 | 2020-06-16,1445.219971,1455.020020,1425.900024,1442.719971,1442.719971,1709200 236 | 2020-06-17,1447.160034,1460.000000,1431.380005,1451.119995,1451.119995,1548300 237 | 2020-06-18,1449.160034,1451.410034,1427.010010,1435.959961,1435.959961,1581900 238 | 2020-06-19,1444.000000,1447.800049,1421.349976,1431.719971,1431.719971,3157900 239 | 2020-06-22,1429.000000,1452.750000,1423.209961,1451.859985,1451.859985,1542400 240 | 2020-06-23,1455.640015,1475.941040,1445.239990,1464.410034,1464.410034,1429800 241 | 2020-06-24,1461.510010,1475.420044,1429.750000,1431.969971,1431.969971,1756000 242 | 2020-06-25,1429.900024,1442.900024,1420.000000,1441.329956,1441.329956,1230500 243 | 2020-06-26,1431.390015,1433.449951,1351.989990,1359.900024,1359.900024,4267700 244 | 2020-06-29,1358.180054,1395.599976,1347.010010,1394.969971,1394.969971,1810200 245 | 2020-06-30,1390.439941,1418.650024,1383.959961,1413.609985,1413.609985,2042400 246 | 2020-07-01,1411.099976,1443.000000,1409.819946,1438.040039,1438.040039,1775200 247 | 2020-07-02,1446.939941,1482.949951,1446.420044,1464.699951,1464.699951,1859100 248 | 2020-07-06,1480.060059,1506.589966,1472.859985,1495.699951,1495.699951,1564000 249 | 2020-07-07,1490.000000,1516.800049,1483.550049,1485.180054,1485.180054,1458200 250 | 2020-07-08,1494.319946,1505.880005,1485.630005,1496.000000,1496.000000,1249700 251 | 2020-07-09,1506.449951,1522.719971,1488.084961,1510.989990,1510.989990,1423300 252 | 2020-07-10,1506.150024,1543.829956,1496.540039,1541.739990,1541.739990,1856300 253 | 2020-07-13,1550.000000,1577.131958,1505.243042,1511.339966,1511.339966,1845000 254 | 2020-07-14,1490.310059,1522.729980,1484.091553,1520.579956,1520.579956,1524081 -------------------------------------------------------------------------------- /stock-price-analysis-with-spark/TSLA.csv: -------------------------------------------------------------------------------- 1 | Date,Open,High,Low,Close,AdjClose,Volume 2 | 2019-07-15,248.000000,254.419998,244.860001,253.500000,253.500000,11000100 3 | 2019-07-16,249.300003,253.529999,247.929993,252.380005,252.380005,8149000 4 | 2019-07-17,255.669998,258.309998,253.350006,254.860001,254.860001,9764700 5 | 2019-07-18,255.050003,255.750000,251.889999,253.539993,253.539993,4764500 6 | 2019-07-19,255.690002,259.959991,254.619995,258.179993,258.179993,7048400 7 | 2019-07-22,258.750000,262.149994,254.190002,255.679993,255.679993,6842400 8 | 2019-07-23,256.709991,260.480011,254.500000,260.170013,260.170013,5023100 9 | 2019-07-24,259.170013,266.070007,258.160004,264.880005,264.880005,11072800 10 | 2019-07-25,233.500000,234.500000,225.550003,228.820007,228.820007,22418300 11 | 2019-07-26,226.919998,230.259995,222.250000,228.039993,228.039993,10027700 12 | 2019-07-29,227.089996,235.940002,226.029999,235.770004,235.770004,9273300 13 | 2019-07-30,232.899994,243.360001,232.179993,242.259995,242.259995,8109000 14 | 2019-07-31,243.000000,246.679993,236.649994,241.610001,241.610001,9178200 15 | 2019-08-01,242.649994,244.509995,231.770004,233.850006,233.850006,8259500 16 | 2019-08-02,231.350006,236.270004,229.229996,234.339996,234.339996,6136500 17 | 2019-08-05,229.600006,231.369995,225.779999,228.320007,228.320007,7028300 18 | 2019-08-06,231.880005,232.500000,225.750000,230.750000,230.750000,5564200 19 | 2019-08-07,226.500000,233.570007,225.800003,233.419998,233.419998,4776500 20 | 2019-08-08,234.449997,239.800003,232.649994,238.300003,238.300003,5274300 21 | 2019-08-09,236.050003,238.960007,233.809998,235.009995,235.009995,3898200 22 | 2019-08-12,232.990005,235.770004,228.750000,229.009995,229.009995,4663900 23 | 2019-08-13,228.809998,236.000000,227.550003,235.000000,235.000000,4848100 24 | 2019-08-14,231.210007,231.500000,216.690002,219.619995,219.619995,9562600 25 | 2019-08-15,220.860001,221.559998,211.550003,215.639999,215.639999,8159600 26 | 2019-08-16,216.660004,222.240005,216.020004,219.940002,219.940002,5098500 27 | 2019-08-19,224.210007,227.830002,221.699997,226.830002,226.830002,5309600 28 | 2019-08-20,227.619995,229.089996,224.539993,225.860001,225.860001,4125200 29 | 2019-08-21,222.009995,223.220001,217.600006,220.830002,220.830002,7794300 30 | 2019-08-22,222.800003,225.399994,218.220001,222.149994,222.149994,6559000 31 | 2019-08-23,219.970001,221.169998,211.000000,211.399994,211.399994,8538600 32 | 2019-08-26,213.600006,215.020004,211.539993,215.000000,215.000000,5051900 33 | 2019-08-27,215.740005,218.800003,212.029999,214.080002,214.080002,5416200 34 | 2019-08-28,213.690002,217.250000,212.309998,215.589996,215.589996,3225500 35 | 2019-08-29,219.000000,223.399994,218.000000,221.710007,221.710007,5179500 36 | 2019-08-30,229.149994,232.440002,224.210007,225.610001,225.610001,9320600 37 | 2019-09-03,224.080002,228.949997,223.160004,225.009995,225.009995,5354100 38 | 2019-09-04,226.889999,228.460007,219.210007,220.679993,220.679993,5761000 39 | 2019-09-05,222.500000,229.800003,220.850006,229.580002,229.580002,7395300 40 | 2019-09-06,227.199997,229.639999,225.169998,227.449997,227.449997,4189400 41 | 2019-09-09,230.000000,233.759995,229.229996,231.789993,231.789993,4802700 42 | 2019-09-10,230.800003,235.539993,228.940002,235.539993,235.539993,4883700 43 | 2019-09-11,237.380005,248.169998,236.000000,247.100006,247.100006,10042800 44 | 2019-09-12,247.699997,253.500000,244.399994,245.869995,245.869995,8581200 45 | 2019-09-13,246.960007,248.449997,244.869995,245.199997,245.199997,5313100 46 | 2019-09-16,246.000000,247.429993,241.169998,242.809998,242.809998,4728100 47 | 2019-09-17,242.470001,245.600006,240.369995,244.789993,244.789993,3865400 48 | 2019-09-18,245.000000,248.169998,242.369995,243.490005,243.490005,4170200 49 | 2019-09-19,246.000000,247.940002,244.839996,246.600006,246.600006,4795800 50 | 2019-09-20,246.490005,246.949997,238.160004,240.619995,240.619995,6353000 51 | 2019-09-23,240.000000,245.179993,239.220001,241.229996,241.229996,4340200 52 | 2019-09-24,241.520004,241.990005,222.610001,223.210007,223.210007,12891500 53 | 2019-09-25,224.559998,228.979996,218.360001,228.699997,228.699997,9427100 54 | 2019-09-26,230.660004,243.309998,227.399994,242.559998,242.559998,11884500 55 | 2019-09-27,242.199997,248.710007,238.729996,242.130005,242.130005,11116400 56 | 2019-09-30,243.000000,243.979996,236.110001,240.869995,240.869995,5879800 57 | 2019-10-01,241.500000,245.949997,239.130005,244.690002,244.690002,6162600 58 | 2019-10-02,243.289993,244.649994,239.429993,243.130005,243.130005,5631400 59 | 2019-10-03,231.860001,234.479996,224.279999,233.029999,233.029999,15084500 60 | 2019-10-04,231.610001,234.779999,228.070007,231.429993,231.429993,7995000 61 | 2019-10-07,229.800003,238.559998,228.550003,237.720001,237.720001,8064200 62 | 2019-10-08,235.869995,243.940002,234.500000,240.050003,240.050003,8678200 63 | 2019-10-09,241.320007,247.300003,240.649994,244.529999,244.529999,6894400 64 | 2019-10-10,245.279999,249.279999,241.580002,244.740005,244.740005,6283300 65 | 2019-10-11,247.149994,251.080002,246.809998,247.889999,247.889999,8475400 66 | 2019-10-14,247.899994,258.549988,247.130005,256.959991,256.959991,10205000 67 | 2019-10-15,257.700012,260.000000,254.119995,257.890015,257.890015,6432800 68 | 2019-10-16,257.390015,262.100006,256.920013,259.750000,259.750000,6684100 69 | 2019-10-17,262.500000,264.779999,260.170013,261.970001,261.970001,4769300 70 | 2019-10-18,260.700012,262.799988,255.100006,256.950012,256.950012,5749800 71 | 2019-10-21,258.329987,259.500000,250.179993,253.500000,253.500000,5020300 72 | 2019-10-22,254.320007,258.329987,250.850006,255.580002,255.580002,4600800 73 | 2019-10-23,254.500000,256.140015,251.350006,254.679993,254.679993,5261100 74 | 2019-10-24,298.369995,304.929993,289.200012,299.679993,299.679993,29720900 75 | 2019-10-25,297.720001,330.000000,296.109985,328.130005,328.130005,30006100 76 | 2019-10-28,327.540009,340.839996,322.600006,327.709991,327.709991,18870300 77 | 2019-10-29,319.989990,324.299988,314.750000,316.220001,316.220001,12684300 78 | 2019-10-30,313.000000,318.790009,309.970001,315.010010,315.010010,9641800 79 | 2019-10-31,313.100006,319.000000,313.000000,314.920013,314.920013,5067000 80 | 2019-11-01,316.320007,316.480011,309.799988,313.309998,313.309998,6383900 81 | 2019-11-04,314.799988,321.940002,309.260010,317.470001,317.470001,8787000 82 | 2019-11-05,319.619995,323.510010,316.119995,317.220001,317.220001,6943400 83 | 2019-11-06,318.000000,326.720001,314.500000,326.579987,326.579987,7940900 84 | 2019-11-07,329.140015,341.500000,328.019989,335.540009,335.540009,14467300 85 | 2019-11-08,334.500000,337.459991,332.500000,337.140015,337.140015,6069200 86 | 2019-11-11,343.950012,349.190002,342.000000,345.089996,345.089996,9986700 87 | 2019-11-12,346.899994,350.369995,344.040009,349.929993,349.929993,7359400 88 | 2019-11-13,355.000000,356.329987,345.179993,346.109985,346.109985,8420100 89 | 2019-11-14,346.109985,353.839996,342.910004,349.350006,349.350006,6464900 90 | 2019-11-15,350.640015,352.799988,348.359985,352.170013,352.170013,4809000 91 | 2019-11-18,352.920013,353.149994,346.100006,349.989990,349.989990,4400400 92 | 2019-11-19,351.750000,359.989990,347.799988,359.519989,359.519989,7724800 93 | 2019-11-20,360.000000,361.200012,349.570007,352.220001,352.220001,6725100 94 | 2019-11-21,354.510010,360.839996,354.000000,354.829987,354.829987,6110000 95 | 2019-11-22,340.160004,341.000000,330.000000,333.040009,333.040009,16870600 96 | 2019-11-25,344.320007,344.570007,334.459991,336.339996,336.339996,12339500 97 | 2019-11-26,335.269989,335.500000,327.100006,328.920013,328.920013,7947400 98 | 2019-11-27,331.119995,333.929993,328.570007,331.290009,331.290009,5555600 99 | 2019-11-29,331.109985,331.260010,327.500000,329.940002,329.940002,2465600 100 | 2019-12-02,329.399994,336.380005,328.690002,334.869995,334.869995,6074500 101 | 2019-12-03,332.619995,337.910004,332.190002,336.200012,336.200012,6573700 102 | 2019-12-04,337.750000,337.859985,332.850006,333.029999,333.029999,5533000 103 | 2019-12-05,332.829987,334.420013,327.250000,330.369995,330.369995,3724600 104 | 2019-12-06,335.000000,338.859985,334.769989,335.890015,335.890015,7612400 105 | 2019-12-09,336.589996,344.450012,335.079987,339.529999,339.529999,9023100 106 | 2019-12-10,339.959991,350.730011,339.309998,348.839996,348.839996,8828300 107 | 2019-12-11,351.880005,357.190002,351.089996,352.700012,352.700012,6897800 108 | 2019-12-12,354.920013,362.739990,353.230011,359.679993,359.679993,7763900 109 | 2019-12-13,361.049988,365.209991,354.640015,358.390015,358.390015,6570900 110 | 2019-12-16,362.549988,383.609985,362.500000,381.500000,381.500000,18174200 111 | 2019-12-17,378.989990,385.500000,375.899994,378.989990,378.989990,8496800 112 | 2019-12-18,380.630005,395.220001,380.579987,393.149994,393.149994,14121000 113 | 2019-12-19,397.320007,406.850006,396.500000,404.040009,404.040009,18107100 114 | 2019-12-20,410.290009,413.000000,400.190002,405.589996,405.589996,14752700 115 | 2019-12-23,411.779999,422.010010,410.000000,419.220001,419.220001,13319600 116 | 2019-12-24,418.359985,425.470001,412.690002,425.250000,425.250000,8054700 117 | 2019-12-26,427.910004,433.480011,426.350006,430.940002,430.940002,10633900 118 | 2019-12-27,435.000000,435.309998,426.109985,430.380005,430.380005,9945700 119 | 2019-12-30,428.790009,429.000000,409.260010,414.700012,414.700012,12586400 120 | 2019-12-31,405.000000,421.290009,402.079987,418.329987,418.329987,10285700 121 | 2020-01-02,424.500000,430.700012,421.709991,430.260010,430.260010,9532100 122 | 2020-01-03,440.500000,454.000000,436.920013,443.010010,443.010010,17778500 123 | 2020-01-06,440.470001,451.559998,440.000000,451.540009,451.540009,10133000 124 | 2020-01-07,461.399994,471.630005,453.359985,469.059998,469.059998,17882100 125 | 2020-01-08,473.700012,498.489990,468.230011,492.140015,492.140015,31144300 126 | 2020-01-09,497.100006,498.799988,472.869995,481.339996,481.339996,28440400 127 | 2020-01-10,481.790009,484.940002,473.700012,478.149994,478.149994,12959500 128 | 2020-01-13,493.500000,525.630005,492.000000,524.859985,524.859985,26517600 129 | 2020-01-14,544.260010,547.409973,524.900024,537.919983,537.919983,28996200 130 | 2020-01-15,529.760010,537.840027,516.789978,518.500000,518.500000,17368800 131 | 2020-01-16,493.750000,514.460022,492.170013,513.489990,513.489990,21736700 132 | 2020-01-17,507.609985,515.669983,503.160004,510.500000,510.500000,13629100 133 | 2020-01-21,530.250000,548.580017,528.409973,547.200012,547.200012,17803500 134 | 2020-01-22,571.890015,594.500000,559.099976,569.559998,569.559998,31369000 135 | 2020-01-23,564.250000,582.000000,555.599976,572.200012,572.200012,19651000 136 | 2020-01-24,570.630005,573.859985,554.260010,564.820007,564.820007,14353600 137 | 2020-01-27,541.989990,564.440002,539.280029,558.020020,558.020020,13608100 138 | 2020-01-28,568.489990,576.809998,558.080017,566.900024,566.900024,11788500 139 | 2020-01-29,575.690002,589.799988,567.429993,580.989990,580.989990,17801500 140 | 2020-01-30,632.419983,650.880005,618.000000,640.809998,640.809998,29005700 141 | 2020-01-31,640.000000,653.000000,632.520020,650.570007,650.570007,15719300 142 | 2020-02-03,673.690002,786.140015,673.520020,780.000000,780.000000,47233500 143 | 2020-02-04,882.960022,968.989990,833.880005,887.059998,887.059998,60938800 144 | 2020-02-05,823.260010,845.979980,704.109985,734.700012,734.700012,48423800 145 | 2020-02-06,699.919983,795.830017,687.000000,748.960022,748.960022,39880800 146 | 2020-02-07,730.549988,769.750000,730.000000,748.070007,748.070007,17063500 147 | 2020-02-10,800.000000,819.989990,752.400024,771.280029,771.280029,24689200 148 | 2020-02-11,768.789978,783.510010,758.000000,774.380005,774.380005,11697500 149 | 2020-02-12,777.869995,789.750000,763.369995,767.289978,767.289978,12022500 150 | 2020-02-13,741.840027,818.000000,735.000000,804.000000,804.000000,26289300 151 | 2020-02-14,787.219971,812.969971,785.500000,800.030029,800.030029,15693700 152 | 2020-02-18,841.599976,860.000000,832.359985,858.400024,858.400024,16381700 153 | 2020-02-19,923.500000,944.780029,901.020020,917.419983,917.419983,25423000 154 | 2020-02-20,911.950012,912.000000,859.940002,899.409973,899.409973,17634900 155 | 2020-02-21,906.979980,913.059998,880.450012,901.000000,901.000000,14314800 156 | 2020-02-24,839.000000,863.500000,822.200012,833.789978,833.789978,15192200 157 | 2020-02-25,849.000000,856.599976,787.000000,799.909973,799.909973,17290500 158 | 2020-02-26,782.500000,813.309998,776.109985,778.799988,778.799988,14085500 159 | 2020-02-27,730.000000,739.770020,669.000000,679.000000,679.000000,24149300 160 | 2020-02-28,629.700012,690.520020,611.520020,667.989990,667.989990,24564200 161 | 2020-03-02,711.260010,743.690002,686.669983,743.619995,743.619995,20195000 162 | 2020-03-03,805.000000,806.979980,716.109985,745.510010,745.510010,25784000 163 | 2020-03-04,763.960022,766.520020,724.729980,749.500000,749.500000,15049000 164 | 2020-03-05,723.770020,745.750000,718.070007,724.539978,724.539978,10852700 165 | 2020-03-06,690.000000,707.000000,684.270020,703.479980,703.479980,12662900 166 | 2020-03-09,605.390015,663.000000,605.000000,608.000000,608.000000,17073700 167 | 2020-03-10,659.429993,668.000000,608.000000,645.330017,645.330017,15594400 168 | 2020-03-11,640.200012,653.580017,613.000000,634.229980,634.229980,13322500 169 | 2020-03-12,580.890015,594.500000,546.250000,560.549988,560.549988,18909100 170 | 2020-03-13,595.000000,607.570007,502.000000,546.619995,546.619995,22640300 171 | 2020-03-16,469.500000,494.869995,442.170013,445.070007,445.070007,20489500 172 | 2020-03-17,440.010010,471.850006,396.000000,430.200012,430.200012,23994600 173 | 2020-03-18,389.000000,404.859985,350.510010,361.220001,361.220001,23786200 174 | 2020-03-19,374.700012,452.000000,358.459991,427.640015,427.640015,30195500 175 | 2020-03-20,438.200012,477.000000,425.790009,427.529999,427.529999,28285500 176 | 2020-03-23,433.600006,442.000000,410.500000,434.290009,434.290009,16454500 177 | 2020-03-24,477.299988,513.690002,474.000000,505.000000,505.000000,22895200 178 | 2020-03-25,545.250000,557.000000,511.109985,539.250000,539.250000,21222700 179 | 2020-03-26,547.390015,560.000000,512.250000,528.159973,528.159973,17380700 180 | 2020-03-27,505.000000,525.799988,494.029999,514.359985,514.359985,14377400 181 | 2020-03-30,510.260010,516.650024,491.230011,502.130005,502.130005,11998100 182 | 2020-03-31,501.250000,542.960022,497.000000,524.000000,524.000000,17771500 183 | 2020-04-01,504.000000,513.950012,475.100006,481.559998,481.559998,13353200 184 | 2020-04-02,481.029999,494.260010,446.399994,454.470001,454.470001,19858400 185 | 2020-04-03,509.500000,515.489990,468.390015,480.010010,480.010010,22562100 186 | 2020-04-06,511.200012,521.000000,497.959991,516.239990,516.239990,14901800 187 | 2020-04-07,545.000000,565.000000,532.340027,545.450012,545.450012,17919800 188 | 2020-04-08,554.200012,557.210022,533.330017,548.840027,548.840027,12656000 189 | 2020-04-09,562.090027,575.179993,557.109985,573.000000,573.000000,13650000 190 | 2020-04-13,590.159973,652.000000,580.530029,650.950012,650.950012,22475400 191 | 2020-04-14,698.969971,741.880005,692.429993,709.890015,709.890015,30576500 192 | 2020-04-15,742.000000,753.130005,710.000000,729.830017,729.830017,23577000 193 | 2020-04-16,716.940002,759.450012,706.719971,745.210022,745.210022,20657900 194 | 2020-04-17,772.280029,774.950012,747.659973,753.890015,753.890015,13128200 195 | 2020-04-20,732.700012,765.570007,712.210022,746.359985,746.359985,14746600 196 | 2020-04-21,730.119995,753.330017,673.789978,686.719971,686.719971,20209100 197 | 2020-04-22,703.979980,734.000000,688.710022,732.109985,732.109985,14224800 198 | 2020-04-23,727.599976,734.000000,703.130005,705.630005,705.630005,13236700 199 | 2020-04-24,710.809998,730.729980,698.179993,725.150024,725.150024,13237600 200 | 2020-04-27,737.609985,799.489990,735.000000,798.750000,798.750000,20681400 201 | 2020-04-28,795.640015,805.000000,756.690002,769.119995,769.119995,15222000 202 | 2020-04-29,790.169983,803.200012,783.159973,800.510010,800.510010,16216000 203 | 2020-04-30,855.190002,869.820007,763.500000,781.880005,781.880005,28400100 204 | 2020-05-01,755.000000,772.770020,683.039978,701.320007,701.320007,32531800 205 | 2020-05-04,701.000000,762.000000,698.000000,761.190002,761.190002,19237100 206 | 2020-05-05,789.789978,798.919983,762.179993,768.210022,768.210022,16991700 207 | 2020-05-06,776.500000,789.799988,761.109985,782.580017,782.580017,11123200 208 | 2020-05-07,777.210022,796.400024,772.349976,780.039978,780.039978,11527700 209 | 2020-05-08,793.770020,824.000000,787.010010,819.419983,819.419983,16130100 210 | 2020-05-11,790.510010,824.000000,785.000000,811.289978,811.289978,16471100 211 | 2020-05-12,827.000000,843.289978,808.000000,809.409973,809.409973,15906900 212 | 2020-05-13,820.830017,826.000000,763.299988,790.960022,790.960022,19065500 213 | 2020-05-14,780.000000,803.359985,764.000000,803.330017,803.330017,13682200 214 | 2020-05-15,790.349976,805.049988,786.549988,799.169983,799.169983,10518400 215 | 2020-05-18,827.780029,834.719971,803.880005,813.630005,813.630005,11698100 216 | 2020-05-19,815.169983,822.070007,806.080017,808.010010,808.010010,9636500 217 | 2020-05-20,820.500000,826.000000,811.799988,815.559998,815.559998,7309300 218 | 2020-05-21,816.000000,832.500000,796.000000,827.599976,827.599976,12254600 219 | 2020-05-22,822.169983,831.780029,812.000000,816.880005,816.880005,9987500 220 | 2020-05-26,834.500000,834.599976,815.710022,818.869995,818.869995,8089700 221 | 2020-05-27,820.859985,827.710022,785.000000,820.229980,820.229980,11549500 222 | 2020-05-28,813.510010,824.750000,801.690002,805.809998,805.809998,7255600 223 | 2020-05-29,808.750000,835.000000,804.210022,835.000000,835.000000,11812500 224 | 2020-06-01,858.000000,899.000000,854.099976,898.099976,898.099976,14939500 225 | 2020-06-02,894.700012,908.659973,871.000000,881.559998,881.559998,13565600 226 | 2020-06-03,888.119995,897.940002,880.099976,882.960022,882.960022,7949500 227 | 2020-06-04,889.880005,895.750000,858.440002,864.380005,864.380005,8887700 228 | 2020-06-05,877.840027,886.520020,866.200012,885.659973,885.659973,7811900 229 | 2020-06-08,919.000000,950.000000,909.159973,949.919983,949.919983,14174700 230 | 2020-06-09,940.010010,954.440002,923.929993,940.669983,940.669983,11388200 231 | 2020-06-10,991.880005,1027.479980,982.500000,1025.050049,1025.050049,18563400 232 | 2020-06-11,990.200012,1018.960022,972.000000,972.840027,972.840027,15916500 233 | 2020-06-12,980.000000,987.979980,912.599976,935.280029,935.280029,16730200 234 | 2020-06-15,917.789978,998.840027,908.500000,990.900024,990.900024,15697200 235 | 2020-06-16,1011.849976,1012.880005,962.390015,982.130005,982.130005,14051100 236 | 2020-06-17,987.710022,1005.000000,982.570007,991.789978,991.789978,9869400 237 | 2020-06-18,1003.000000,1019.200012,994.469971,1003.960022,1003.960022,9751900 238 | 2020-06-19,1012.780029,1015.969971,991.340027,1000.900024,1000.900024,8679700 239 | 2020-06-22,999.950012,1008.880005,990.020020,994.320007,994.320007,6362400 240 | 2020-06-23,998.880005,1012.000000,994.010010,1001.780029,1001.780029,6365300 241 | 2020-06-24,994.109985,1000.880005,953.140015,960.849976,960.849976,10959600 242 | 2020-06-25,954.270020,985.979980,937.150024,985.979980,985.979980,9254500 243 | 2020-06-26,994.780029,995.000000,954.869995,959.739990,959.739990,8854900 244 | 2020-06-29,969.010010,1010.000000,948.520020,1009.349976,1009.349976,9026400 245 | 2020-06-30,1006.500000,1087.689941,1003.729980,1079.810059,1079.810059,16918500 246 | 2020-07-01,1083.000000,1135.329956,1080.500000,1119.630005,1119.630005,13326900 247 | 2020-07-02,1221.479980,1228.000000,1185.599976,1208.660034,1208.660034,17250100 248 | 2020-07-06,1276.689941,1377.790039,1266.040039,1371.579956,1371.579956,20569900 249 | 2020-07-07,1405.010010,1429.500000,1336.709961,1389.859985,1389.859985,21489700 250 | 2020-07-08,1405.000000,1417.260010,1311.339966,1365.880005,1365.880005,16311300 251 | 2020-07-09,1396.989990,1408.560059,1351.280029,1394.280029,1394.280029,11717600 252 | 2020-07-10,1396.000000,1548.920044,1376.010010,1544.650024,1544.650024,23337600 253 | 2020-07-13,1659.000000,1794.989990,1471.109985,1497.060059,1497.060059,38725700 254 | 2020-07-14,1556.000000,1590.000000,1431.000000,1516.800049,1516.800049,22833862 --------------------------------------------------------------------------------