├── .DS_Store ├── Datasets ├── MRF_sim.csv └── finance.csv ├── LICENSE.txt └── TXT.rtf ├── MacroRandomForest.egg-info ├── PKG-INFO ├── SOURCES.txt ├── dependency_links.txt ├── requires.txt └── top_level.txt ├── MacroRandomForest ├── All_predictors.ipynb ├── Financial-Trading.ipynb ├── MRF.py ├── One-Step-Macro-Forecasting copy.ipynb ├── One-Step-Macro-Forecasting.ipynb ├── README.md ├── Simple-One-Step-Forecasting.ipynb ├── __init__.py └── __pycache__ │ ├── MRF.cpython-310.pyc │ ├── MRF.cpython-311.pyc │ └── MRF.cpython-38.pyc ├── README.md ├── __pycache__ ├── MRF.cpython-38.pyc ├── MRF_2.cpython-38.pyc ├── MRF_non_random.cpython-38.pyc └── MRF_random.cpython-38.pyc ├── dist ├── MacroRandomForest-1.0.5-py3-none-any.whl └── MacroRandomForest-1.0.5.tar.gz ├── setup.cfg └── setup.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/.DS_Store -------------------------------------------------------------------------------- /Datasets/MRF_sim.csv: -------------------------------------------------------------------------------- 1 | index,sim_y,sim_x1,sim_x2,sim_x3,sim_x4,sim_x5,sim_x6,sim_x7,sim_x8,sim_x9,sim_x10,sim_x11,sim_x12,sim_x13,sim_x14,sim_x15,trend 2 | 0,-0.441804832,1.262954285,-1.045717652,-0.390009563,-1.687801029,-1.424031666,-0.286851565,-0.959316423,-0.123545685,-0.614495099,-0.183679589,0.44434582,-0.66185015,1.357600613,0.095308684,-0.27650779,1 3 | 1,-2.793369538,-0.326233361,-0.896211264,-1.81922223,0.647645994,-1.669344412,1.841106893,-1.62031665,0.147392919,2.827807696,0.237403992,0.01192938,-0.346816077,-0.322124931,0.991170347,-0.854417512,2 4 | 2,2.537384071,1.329799263,1.269387164,0.65918071,0.448794227,1.379236132,-0.15676431,0.822513291,-1.240966183,1.500310421,-0.570730016,-0.009280045,1.339732449,-1.106560508,0.428252039,1.484950307,3 5 | 3,1.76959078,1.272429321,0.593840949,0.459621673,1.026302158,-0.919674583,-1.389802635,0.10871267,2.004243464,-0.038203923,0.678865182,-0.302377554,0.592419266,0.038224735,1.118213517,-1.597298664,4 6 | 4,2.299627522,0.414641434,0.775634319,1.616626337,1.074978223,-0.504490044,-1.473103989,0.760994764,-0.77197957,-0.833422908,-1.465345487,0.492355022,0.718904016,0.743778758,-0.739658147,0.374998873,5 7 | 5,-1.555088318,-1.539950042,1.557370376,-1.856190495,0.458309613,-1.134731813,-0.069518934,-2.306256552,-1.178889074,0.441814995,-1.137687797,-0.602719618,-0.411419278,-1.416045015,-2.063933394,1.327244247,6 8 | 6,-1.687818291,-0.928567035,-0.365401797,-0.286823883,0.631586758,0.512773055,0.23924143,1.064045133,-0.569679874,-0.361959366,-0.989656081,-0.68227652,1.16297294,-0.82606497,0.389762625,-1.450355256,7 9 | 7,2.042754436,-0.294720447,0.816556449,1.750321889,-0.580466398,0.527988783,0.250419911,0.343252396,1.754820845,-0.393244089,0.792858052,0.286737237,0.902030483,1.111694433,-0.485376016,1.112487045,8 10 | 8,1.014089262,-0.005767173,-0.060634778,0.116413613,1.584192142,1.188247324,-0.26442395,-0.454694963,-1.775369314,0.164743104,0.253010895,0.165586356,0.212617453,-0.568142043,-2.224558324,-0.677697483,9 11 | 9,3.96705853,2.404653389,-0.501378318,1.384253158,-1.76399294,-0.462036358,-1.975399955,0.537837906,-0.209766913,-0.273551756,-0.751931498,-0.842053935,-0.263459569,1.604992585,-1.1864324,-0.615243132,10 12 | 10,2.485706726,0.763593461,0.926062725,0.574220913,-1.88062197,1.241069288,-0.449876006,0.279674939,-1.234044081,0.476402714,-0.585740794,-0.822113719,-0.831702845,0.914487171,0.610182371,-0.239364532,11 13 | 11,-1.253226102,-0.799009249,0.036937691,0.136490812,-1.291719044,0.137021552,0.926465655,0.631527435,-1.030479782,0.731150603,1.424406714,-1.429350824,-1.190663094,0.285990442,1.514145293,-1.284009898,12 14 | 12,-1.290806605,-1.147657009,-1.066200174,0.914215989,0.909670446,-1.299645239,-2.319971111,0.529627475,0.026885635,-0.736171088,-0.93022732,0.134741719,-1.34739813,-0.362752732,0.36207872,-0.266959315,13 15 | 13,-3.528059793,-0.289461574,-0.238456353,-1.800826318,-1.107755682,1.151408943,0.61393355,0.165790906,0.476041978,1.304384754,1.112958043,0.629984088,-0.612180491,-0.820452009,1.648398984,-0.513585009,14 16 | 14,0.829014204,-0.299215118,1.495223444,-0.339880639,-0.384123875,1.513447478,-1.473140132,0.143169173,1.669779068,0.419843803,1.606579421,1.120535377,0.47516319,0.130878914,0.089483884,-0.488050317,15 17 | 15,2.048624176,-0.411510833,1.172158547,0.606264572,0.082734834,0.802137876,-0.219049185,-0.606080622,-0.395346679,1.505363585,-1.252321592,0.922258127,-0.516932938,0.214580062,0.728601985,0.025105487,16 18 | 16,-0.020451173,0.252223448,-1.45770721,1.341130311,-0.483882474,-0.430536942,-1.403416293,0.456530316,0.436339261,-1.907004959,1.634552926,2.108528331,0.703279493,0.490027519,0.554856588,1.421088751,17 19 | 17,-0.259770462,-0.891921127,0.095056227,0.767287288,-2.084741125,-1.34470094,0.820628408,-0.534031659,-2.767870781,1.109305848,-0.221808313,0.79639367,0.284020218,0.521728233,0.846200169,0.524853063,18 20 | 18,1.673318729,0.435683299,0.847664964,0.193725667,1.167586964,0.03744207,-0.592726276,1.312650796,0.143077908,-0.025426744,1.515525903,-2.6738679,-0.707138196,1.105875047,-0.310977943,1.992208991,19 21 | 19,-0.842522255,-1.237538422,-1.62436453,1.140566691,-0.076825771,-1.345721789,0.421968793,0.106862379,1.648022497,0.080458145,-0.138913875,-0.228189977,0.099389564,0.508100769,0.851076071,-0.131188113,20 22 | 20,0.857422493,-0.224267885,1.408563357,0.013864804,0.530421395,-1.814004316,-0.800152109,1.444751257,0.507068009,0.091011715,-1.53844541,0.052822862,0.261091012,-1.231349919,1.025925413,-0.214149274,21 23 | 21,-1.372265093,0.377395646,-0.541760362,-1.10530591,0.004908796,0.704033532,-1.183201144,-0.349824461,-0.092403542,0.355300704,-0.944662552,0.165821406,-0.718762563,-0.595932118,0.316262389,0.539771925,22 24 | 22,0.470039755,0.133336361,0.278664724,-0.025162639,-0.53023143,-0.299019664,-1.50955729,-0.202977565,-0.153249323,-1.545373709,-0.57891541,-0.164382974,1.787849222,1.070934572,-0.727586672,-0.191752981,23 25 | 23,0.724031261,0.80418951,-0.193972745,-0.163673338,0.10220241,-0.398891296,-1.155943109,0.843323868,-0.584182132,-0.04105797,0.61014112,2.222058088,1.139568171,-0.646405678,-0.55290849,-1.659683075,24 26 | 24,2.087363838,-0.057106774,1.576158181,0.370059748,0.815459636,-0.64331733,-0.354855101,1.134289963,0.47589442,0.084713385,-0.013014755,0.780272529,-0.277005302,0.720211977,-0.363337399,-1.220441365,25 27 | 25,-1.546867832,0.503607972,-1.475547635,-0.380824536,-1.506521863,1.315605055,1.385451186,-1.134146078,0.439854855,0.815728506,-1.42671214,0.904523886,0.451759823,-0.333908224,-0.800390486,1.636737476,26 28 | 26,1.537118511,1.085769362,-0.144608207,0.652952369,-1.157180172,-1.584967881,0.569659859,0.839866477,1.486195063,-0.345048343,1.026577912,-1.292999663,1.491782843,1.285148215,-0.160847547,1.393979638,27 29 | 27,0.372204636,-0.69095384,-1.075010191,2.061341806,1.301554937,-0.444496425,-0.638495083,1.09844703,-2.119558201,0.048246132,0.211805291,-2.07802948,-0.033108577,-0.105309005,1.786050683,0.760435106,28 30 | 28,-1.993748999,-1.284599354,0.406542732,-1.796644937,-0.905640775,0.566183078,0.239804446,-0.440626743,0.021912287,-0.208132678,-0.511779931,0.762792048,-0.046955275,-0.114908931,-1.946049821,0.706908169,29 31 | 29,3.375302272,0.046726172,2.229262202,0.584077124,0.015563481,0.290325674,-1.000774423,0.704830751,-0.593561886,0.228801904,0.952021776,-1.768662113,-1.914633856,-0.419299065,-1.337314054,-0.926139821,30 32 | 30,-2.880975382,-0.235706556,-1.514497008,-0.722753124,-1.428005197,-0.615544332,-0.615286634,-0.650810638,-0.277968861,-1.265159329,1.489575542,-2.092527871,-0.013126394,-1.261049547,0.627200307,1.285462467,31 33 | 31,-1.286331332,-0.542888255,-0.061707422,-0.629164665,0.687979702,-0.062007819,0.157730187,-0.530295274,-0.289927818,-1.6213736,-0.545155024,1.040937039,0.059448309,0.085277537,-1.219597574,0.40888701,32 34 | 32,-3.275514284,-0.433310317,-0.14727079,-1.816206055,0.594196501,-0.192610255,2.684060804,-0.177034943,-0.729067923,-0.735241717,-1.223668061,0.725874333,-1.150067152,0.107114476,-0.677860949,-1.112552085,33 35 | 33,0.734108251,-0.649471647,1.541593069,-0.259289098,-0.270315244,1.683153949,0.22946746,-0.69778164,0.293541481,-1.681901459,-1.768047848,-0.873292285,0.004480675,1.993335099,0.314722125,0.856126641,34 36 | 34,0.433263195,0.726750747,-0.981855669,0.334632273,1.554076076,0.102573846,0.100254667,1.475190672,-0.717230531,1.464273955,0.626209804,-0.681909592,-0.883642641,-1.347849381,0.869550666,-0.905515928,35 37 | 35,0.447069018,1.151911754,0.496578173,-1.427167613,-0.510742458,-0.654835313,-2.302512517,-0.044228378,-1.565152728,1.576854885,-0.381192215,-0.816400702,0.671046073,-0.69240842,0.889574059,-1.021142255,36 38 | 36,4.862843182,0.992160365,1.696947881,1.938628233,-0.291842736,1.1865752,1.175894863,-0.425329831,1.084880017,-2.666810612,0.740656955,1.753333647,0.004894727,-3.036842469,-0.196429933,-1.033532048,37 39 | 37,-1.189147266,-0.429513109,-0.260736309,-0.759530213,1.101438165,-1.272369672,1.24836964,-1.638931473,-0.261736594,0.039090399,2.008043884,-1.4925482,-0.181078157,1.314519433,-0.601043331,-0.296471001,38 40 | 38,-1.254392433,1.238304101,-0.705928586,-2.278776142,0.458665215,0.53806458,-1.623245918,0.065260153,-0.20021679,1.078576657,1.244266444,-0.138713241,0.383879424,0.354791246,-0.173708938,-1.75616157,39 41 | 39,-0.258176072,-0.279346282,-0.161178506,-0.114050766,0.851908039,1.230850392,-0.002656146,-0.778700209,-0.044345812,-1.523092055,-0.541570095,0.592539751,-0.952801062,0.479317198,-0.890033827,0.645153456,40 42 | 40,3.928715616,1.75790309,0.501321828,2.351856666,1.466199919,-1.165706963,-0.837264285,-0.41627648,-1.15434752,-0.2246783,-1.596860459,-0.03356126,-0.367041298,1.64493892,0.251358259,0.488781696,41 43 | 41,0.823664017,0.560746091,-1.01353967,1.596320803,0.243863295,0.324209448,0.118853245,-0.358192742,0.616557586,-0.286800078,1.757805791,-0.20740668,0.314710715,0.760243549,-0.132242204,-1.047243587,42 44 | 42,2.409838711,-0.452783973,1.614752235,1.277445511,0.649421934,0.950867375,-0.501007298,-1.681240457,0.327501215,0.267018252,1.712550096,-0.190824364,-0.709251467,0.772413174,0.196227576,1.274550667,43 45 | 43,0.527924666,-0.832043296,0.005641985,0.788970858,-0.641118156,1.117433602,1.025344726,0.457564224,-1.367324039,0.213084554,-0.730080323,2.056954701,0.429466575,-0.320802439,0.373121006,0.129844744,44 46 | 44,-3.761091174,-1.166570547,-2.90489906,0.461465382,0.464459771,1.523969047,0.217808213,0.202849808,0.277124492,0.519286617,1.456038508,-0.651173381,-0.730365013,1.049811964,-0.438822522,0.220901861,45 47 | 45,-2.575029881,-1.06559058,-1.107164819,-0.438069134,-0.309200447,1.91804841,0.085578656,0.401840134,-0.256183163,2.004881988,1.048505778,-0.697760493,0.02676092,-0.842384622,-1.146581017,0.579971986,46 48 | 46,-1.443238879,-1.563782051,1.547566933,-1.507807009,1.276020709,0.200177306,0.387769029,-0.861463695,0.822373051,1.068294112,0.799473745,1.046057726,0.565023691,0.051498819,0.092773571,0.315860238,47 49 | 47,-2.396466653,1.156536997,-0.97683035,-2.222946131,-0.04761122,-0.847190495,-1.817656629,-1.872698748,-0.24038885,-0.523849838,-0.56273311,-0.049920675,-1.3040743,1.540953425,0.661013499,0.275391997,48 50 | 48,-0.030923306,0.832047129,-0.101503448,-1.178672442,0.030101166,-0.75686754,-1.174550153,1.938031647,0.275620991,0.729769247,0.118180814,1.746908774,0.592417359,1.083764311,0.840569943,-0.286516639,49 51 | 49,-1.695518693,-0.227328691,0.04265025,-1.782760224,-0.00358027,0.695104616,1.366606514,1.40352522,1.341725256,1.071810543,-0.376893544,0.400194688,1.053974723,-2.861205182,1.106005382,0.206340853,50 52 | 50,-2.100292667,0.266137362,-1.596718014,-0.987919139,-2.034572643,-1.572917874,0.190588625,-0.465834428,1.801656603,0.884232239,0.918030855,0.555978476,-0.229403433,-0.196905274,0.592145423,0.699569174,51 53 | 51,0.992446643,-0.376702719,0.490967373,0.728488688,-0.992819963,0.5002338,0.407143173,-1.451391552,-1.076858265,-0.098990571,-0.21430799,2.078951319,-0.801378683,0.857134968,0.038351628,0.467293167,52 54 | 52,1.302168862,2.441364629,0.421603365,-0.884684915,1.963858056,-1.15491866,-1.405579071,-0.19407645,-0.115393405,-2.041881656,1.118540685,-0.689031864,-0.531842296,-0.605311642,0.143989982,-0.866444816,53 55 | 53,-1.188626883,-0.795339117,1.873903899,-1.538441417,0.706528773,-0.925201228,2.172244168,-0.052979473,-1.367735754,2.053746402,0.016378092,1.335536264,0.535023232,0.203025941,-0.105164837,0.885050093,54 56 | 54,-0.014082678,-0.054877474,1.034514324,-0.972226803,0.03967498,0.341904559,-0.539542776,-2.085633166,0.477552542,0.614858577,-1.143232575,-0.597594163,-0.566908813,0.634959076,-1.044785156,-0.155787959,55 57 | 55,-1.098302206,0.250141323,0.08181031,-1.71813619,-0.15851859,-0.589627963,0.486887772,-0.29418827,0.306073004,1.769555784,1.070187312,-0.067447107,-2.370227045,0.364344842,-1.484270704,-0.945728233,56 58 | 56,1.769782175,0.618243294,-0.082523762,0.803757539,-0.162257551,-0.828438381,-0.261532,0.0709752,-0.56952568,1.344560429,0.324475959,-1.118574941,1.658638192,-0.029242957,0.16540946,-0.263509827,57 59 | 57,-1.250265922,-0.172623503,0.606073431,-1.50178717,0.438821912,-0.66373021,0.923313589,1.680361859,-0.963405158,0.328327464,-0.654797051,0.310520634,1.872597267,-1.023716131,-1.038068549,-1.814050206,58 60 | 58,-3.014980634,-2.223900274,-0.887420145,-0.145499071,0.780699292,1.416440853,-0.910911965,-1.11690607,2.361948811,1.038574647,-0.779382765,0.412346115,-2.225174172,0.297060668,0.454609335,0.459004956,59 61 | 59,-0.938005998,-1.263614385,0.10542139,0.579458612,-0.981205622,-1.371502343,0.983827544,2.402962775,-0.018704008,0.716879995,-0.953852766,-1.470685823,-1.351247832,-0.986714676,0.640797584,1.830865599,60 62 | 60,1.961712969,0.358728896,0.352874473,1.201525576,-0.141585732,0.108860723,1.003069942,1.25512582,0.297713284,0.731480672,-0.024810099,-1.335857619,-0.686228054,-0.744535934,2.178518119,0.1819348,61 63 | 61,1.591374533,-0.011045478,0.550393358,1.893910787,-1.256248953,-0.466822252,-0.790760348,-0.069794882,-0.854630033,0.902195698,1.201157495,0.649779329,0.802304552,0.84897342,0.691624541,0.60830192,62 64 | 62,-2.485743316,-0.940649163,-1.134330969,-1.760226343,-0.429033676,2.961743363,-1.658033573,-0.380856078,1.507604241,1.535925123,0.714924585,-0.174650536,0.582972647,0.809733221,0.122333748,-0.492323579,63 65 | 63,2.211189725,-0.115825322,1.462351539,0.924546803,0.508776266,-0.15782718,0.400994752,0.393556572,1.219015933,-1.205443078,-0.435841923,-1.993010999,-1.619649565,0.099829567,-0.141270383,-0.95856158,64 66 | 64,0.097133441,-0.814968709,0.702116711,-0.556542168,-1.446889743,1.819425273,-2.348004883,1.265556269,0.116997409,-1.953715192,0.775660848,-0.330462315,-0.431383604,0.688188552,-0.777518724,-0.647676128,65 67 | 65,2.703002531,0.242263481,2.507111148,-0.180584138,1.019512829,0.863742551,0.73047759,1.43107831,0.093003941,-0.429964735,-1.641619042,0.413252463,0.998104582,-0.00240364,-0.018539943,-0.312371525,66 68 | 66,-2.53041506,-1.425098395,-1.890027144,1.447440285,1.178546976,-1.56644322,0.755255204,0.175970353,0.853229254,0.539067461,0.674118526,-1.087184334,0.173101632,-0.35980968,-0.112835622,0.479079202,67 69 | 67,-0.6658377,0.365941123,-0.58981279,-0.607131453,-0.010258765,0.515455969,0.78856638,-0.789782099,-0.251673129,-0.453723899,1.377422807,0.048162709,0.331471158,1.188265095,-0.317434648,0.681028281,68 70 | 68,-0.397686666,0.248412649,-1.714502297,0.67936243,0.268624871,0.696219512,-0.342063446,1.096179379,-0.14811243,-0.283667456,1.028368421,-0.643207659,0.185473676,-2.07063171,-0.151580071,0.08568541,69 71 | 69,-0.127976981,0.065288182,-0.420997898,-0.09355764,1.342028872,0.025421101,1.823848892,1.040497132,-1.867890143,0.264618303,-0.605855832,1.397682518,1.674073505,-1.719547178,0.472664867,-0.030059269,70 72 | 70,0.632339163,0.019156392,0.310141377,-0.490086292,-0.583606443,-1.951783301,-0.14814048,-0.599075968,0.459839869,-0.719681891,-0.554080359,0.20812468,-0.308894756,-0.053431497,0.296508769,0.517526368,71 73 | 71,3.703779101,0.257338377,1.702570586,1.410659383,-0.937000891,2.245358736,-0.971565897,-1.063155272,2.811991504,-0.474542158,-0.281289604,0.583953051,2.012742573,-0.575781281,0.384192726,-0.296773342,72 74 | 72,-0.953526549,-0.649010078,-0.443384804,-0.22457379,-1.152157056,-0.187737175,-0.389138968,-0.13545373,0.319516336,-0.124557807,-1.231708346,3.023596733,-0.992208318,0.302254351,-1.335915901,0.133820815,73 75 | 73,-1.557796337,-0.119168762,-1.198597083,-0.21249549,-0.975183431,-1.40125119,-1.263656166,0.345990467,-1.23556792,-1.062580614,1.307542417,1.091335996,-1.523578205,-0.573625236,0.455115848,0.86739576,74 76 | 74,0.323374062,0.6641357,-0.307380914,0.696378474,-0.711413598,1.248358506,-1.278265506,-0.235347706,0.842305259,1.964931586,-1.867774031,-0.228666563,-0.639189705,1.496622681,-0.455627544,-0.228651199,75 77 | 75,0.845125034,1.100969102,0.621054203,0.915182505,0.371912476,-0.24707823,0.204386956,-1.04965204,0.596824476,-1.771933072,-0.150015818,-0.46636865,-0.807777317,-1.258644691,-0.58693541,-0.283615131,76 78 | 76,-0.532047603,0.143771481,0.181902191,-0.923374316,-0.943514417,0.245559516,0.046567748,-0.853455092,0.366228494,0.909523056,-0.183419301,0.419783753,-0.43223017,-0.086141949,-0.530433194,-0.01798807,77 79 | 77,1.257907971,-0.117753598,1.318400931,1.146873263,-0.274367308,-0.778723557,-0.538768588,0.815269594,0.093153124,-1.879042521,-0.078063283,-0.415107559,-0.244429865,1.555027187,0.814032595,-0.050704283,78 80 | 78,-0.599987361,-0.912068367,-0.298909313,-0.635865043,0.154468494,-1.790886181,-0.218683231,0.679913372,0.59512111,-1.303376792,-0.04128384,1.168557071,-1.393925505,-0.474839471,-0.469126531,-0.150947486,79 81 | 79,-1.609387486,-1.437586241,-1.648221742,-0.886443308,-1.288653202,-0.167523856,-0.15529542,0.331725219,-0.466791919,1.174782608,1.164769081,0.793371128,-0.661130773,-1.686159849,-0.729109163,0.229958494,80 82 | 80,-1.544764593,-0.797089525,0.95149847,-2.333136685,1.419102319,0.750979937,-0.306256372,-0.661940027,-1.60275927,0.143984716,-0.447220157,0.380697217,2.601174361,1.842768027,-0.300886287,1.317730242,81 83 | 81,-0.560571593,1.254083106,-1.113122953,-0.145490805,1.307827762,-0.017023403,1.769289381,-0.162888273,0.569388628,0.719598783,1.952915696,0.335054157,0.637699988,0.222219381,1.603361064,-1.779920287,82 84 | 82,0.777462562,0.772142186,0.616966476,0.316964024,-1.804975774,0.027578974,-0.593041995,-1.130392439,0.257115383,0.530024225,0.864579088,0.460524337,-0.239202679,-0.191542424,0.091677531,-0.126081956,83 85 | 83,-0.271451388,-0.219515627,0.513493716,-0.707469988,-0.484069527,0.222146147,0.689431248,0.893394174,1.082789769,0.350105945,1.071924895,-0.053733233,2.145345084,-0.863960481,0.931194944,1.147290334,84 86 | 84,1.02203984,-0.424810283,0.369459104,1.242155558,-0.37321178,0.398631825,-0.340080187,-1.794838849,-1.219001014,-0.344855375,-1.763175475,0.346259672,1.030170848,-0.463848933,0.342681888,0.477093974,85 87 | 85,0.646186354,-0.418980099,1.723894131,0.620152195,0.169085902,-0.261518413,-1.061509942,-0.248902063,-1.530554249,0.332256598,-0.773341087,0.22295561,1.136473578,1.132708205,-0.233920744,-0.255590213,86 88 | 86,-0.207953056,0.996986861,-0.206144567,0.099903068,-1.172983603,-0.303177624,-0.939173204,-0.244751584,-1.652111774,-1.788856476,0.121751128,-1.729891695,-0.010610621,-0.373169318,0.672937781,0.092618164,87 89 | 87,-0.45023416,-0.275778029,-1.31419514,1.807703488,-0.376196737,-0.733571785,0.156912588,-0.642571918,0.786249263,-1.490763037,-0.848101064,-0.961006709,0.108348459,1.037260863,1.038904921,2.509934256,88 90 | 88,0.242139394,1.256018817,0.063474096,-1.502429979,0.78312764,-1.381854714,-0.571797205,2.461765777,1.058597356,-1.142110511,-0.988867953,-0.42917099,1.105982629,-0.330148329,1.32446501,0.406955665,89 91 | 89,0.280171079,0.64667439,-0.231977451,0.285640465,0.991171304,-1.441687373,0.158199488,2.212329413,-0.73866489,0.20929912,1.416998013,0.221645844,-0.900719166,1.274789536,0.3925413,0.143169742,90 92 | 90,1.082815497,1.299312303,0.635060328,0.845706964,0.229284475,-0.786310164,0.340690847,-0.517552252,-0.138852471,0.162159503,-2.046280668,0.682797741,-0.304042201,-0.33353795,0.025384921,0.414008965,91 93 | 91,0.111870234,-0.873262112,1.634644285,-0.995342638,0.336850949,-0.74248224,0.735364418,0.443393864,-1.41987601,0.008184724,-0.771162084,0.342167835,0.23041673,1.365644151,-0.184260324,1.950132785,92 94 | 92,-0.928197295,0.00837096,-1.808327579,-0.256854125,-0.647231999,-0.390980247,-1.02482813,0.328105132,0.868555313,-0.438708405,0.572485404,1.0071652,-0.233411122,-0.786266705,0.208957729,-0.099797771,93 95 | 93,-0.764893823,-0.880871723,-0.213885951,-0.055856043,-0.443206682,-1.215755063,1.363362141,0.446249505,-1.624989449,1.135235729,-0.176371962,-0.948486398,0.224893104,0.659470323,0.820346143,0.458880597,94 96 | 94,0.718551484,0.596259017,0.070366141,-0.44500524,1.161751761,-0.890405591,-1.915180723,0.489449364,0.143163456,-0.126318575,-0.951477642,-0.224625504,1.55054594,0.606837484,1.323819978,-0.524247598,95 97 | 95,0.894925724,0.119717641,0.54970767,0.069695103,0.06505101,1.498272631,-1.923833752,-0.672802963,0.710479672,-0.528109312,1.66461986,-2.182837134,1.798420454,2.255449318,0.989649026,0.106244758,96 98 | 96,-0.826953537,-0.282173877,-0.696823546,-0.154671706,-0.68246758,0.371839111,1.13571696,-2.167439027,-0.055470036,0.818102205,0.282131289,1.06320111,-0.872866687,0.76242686,-0.059079553,-2.155071914,97 99 | 97,0.369680722,1.455988401,0.390565942,-0.831263459,1.634341658,0.261106083,1.241223614,-0.449159939,0.171813203,-1.817400491,-1.943938462,-0.683058302,0.066307962,-1.700113423,-0.044568763,1.090091744,98 100 | 98,0.275206634,0.229019591,0.381411259,0.761544352,-0.584849244,-0.024543857,-1.157504888,0.66959282,-0.639099802,0.1723658,-0.44119994,-0.642961431,-0.585265961,-0.111794554,0.672025677,0.730503453,99 101 | 99,-0.374074012,0.996543929,-0.01237277,-0.576506933,1.129936001,-0.917689244,0.496621993,-0.582069807,-0.662710731,0.137942217,1.579159618,1.837217262,0.091225075,-0.1979124,-0.783946769,0.857474697,100 102 | 100,0.072964036,0.781859185,-0.124434986,-0.626368228,0.581201043,-0.591884218,-1.331908129,0.323837305,0.078761716,0.814883723,1.980198247,0.69481122,-0.169317739,-0.532190199,-0.937405937,1.262276623,101 103 | 101,0.466706457,-0.776776622,1.466744593,0.481335326,0.379293067,-0.370993056,1.59262862,-0.785836986,-0.051420603,-1.466616391,0.669008484,-1.076390625,0.879351534,-0.369966713,0.436959284,0.306785426,102 104 | 102,0.365584841,-0.615989908,0.673928676,1.695271084,-0.310740876,0.087924257,0.061958081,0.217898598,-0.260774127,0.439264692,0.032093936,0.459203691,0.137912315,1.170899312,0.36124732,0.191827061,103 105 | 103,-0.282378232,0.046580303,1.956425263,-1.761226294,0.886390001,-0.034726345,-0.145945861,0.476659469,1.566268188,0.67415587,-2.217868254,-1.139876822,0.514483943,-0.464567775,0.770435809,0.519870029,104 106 | 104,-0.26826388,-1.130385778,-0.269041012,0.198013015,-1.64186475,1.806374269,-0.343735779,0.069954447,-0.37201511,-0.601031053,1.433178479,0.138643886,0.394584215,-0.302146007,-0.098183676,-0.964235773,105 107 | 105,-0.336141475,0.576718782,-1.244551518,0.397349099,-0.988563742,-0.340236065,-1.247170993,-1.04096263,1.741944439,1.984577381,-0.745948559,1.232261753,-1.584562141,1.391370891,1.288708793,-1.85513353,106 108 | 106,0.495356734,-1.280749432,-0.395702923,0.029225495,-0.244003429,-0.748963256,0.84333396,1.166413984,-1.098856541,0.174908188,0.453045488,1.830509655,0.588672856,-0.449640632,0.433584943,-0.861322663,107 109 | 107,2.329340564,1.625447303,0.097396655,2.560273389,0.156056926,-1.639136839,-0.002131136,-0.073174702,0.866328444,1.767877111,-1.201462766,0.318410673,0.158435254,-0.84665498,-0.894253961,-0.842981421,108 110 | 108,-0.546000475,-0.500696596,-0.23838695,1.257127712,0.102051958,-1.001187676,0.49188085,-1.285077445,0.534788336,-0.308973149,0.600672571,0.773853808,-0.528154012,-0.032758136,-0.666239268,0.39528554,109 111 | 109,0.236117634,1.678297208,-0.411827957,-0.534537686,-0.287458172,2.595771838,-0.814033523,-0.688795456,-1.394227775,0.442747119,-2.568398152,-0.629624566,-1.590643806,0.151766122,0.414639248,-1.404818039,110 112 | 110,-2.024423045,-0.412519887,-1.577218049,-0.625227429,-0.293194886,0.303198815,-0.430486011,0.09105248,1.496063982,-0.834609138,2.291253944,-0.768106402,-0.825373064,1.414294355,0.463536424,-1.350853341,111 113 | 111,-0.869331458,-0.972286836,-0.797276095,0.913848687,0.469477058,0.908747388,0.236554399,-0.84269181,-1.242427487,1.715631879,-0.714778769,-0.813066513,-1.023118654,-1.819780983,-0.28265075,-0.582332092,112 114 | 112,0.151259864,0.025382868,-1.096236783,1.007199535,-0.662588512,0.207849948,-1.754225843,-1.838814903,-1.026687817,-0.235425279,0.651451051,1.263764834,1.211019935,0.060099221,0.460244053,0.796542132,113 115 | 113,1.093160466,0.027475337,0.308308749,0.719291823,-2.190372666,0.178014002,-0.95278383,-1.032559649,-0.56466094,1.178134979,-1.939598895,-1.315654343,0.749185659,1.178917087,-0.586643397,-0.063441179,114 116 | 114,-1.556720457,-1.680182722,0.344795124,-0.604711661,0.003854672,-0.165764998,-0.628854148,-0.11435889,-1.07303196,0.324431255,0.206583906,-0.813798025,0.78730175,-0.316034949,2.395234315,-0.258465846,115 117 | 115,1.460274246,1.053750863,1.539648088,0.539054406,0.862942829,0.55710362,0.562778893,0.065738832,-0.357698712,0.064208198,2.110791901,1.459961145,0.186775632,0.76160019,-0.241247653,0.463479195,116 118 | 116,-1.756691344,-1.119599105,-0.329514192,-0.076830886,0.980223359,1.444334403,-0.953274417,1.467632026,-0.579333784,1.560251817,1.089979063,0.480003125,-0.259216137,-0.482336163,-0.859584738,0.420127076,117 119 | 117,1.933008326,0.33561721,0.948389351,1.84991956,-0.291724771,0.901357061,-1.094557409,-0.691064579,-0.091615939,0.344360304,0.411433757,-1.587135837,-0.747888314,0.75799337,0.500416086,1.236314435,118 120 | 118,0.589597722,0.494795767,-0.479255587,-0.854907551,-0.061013476,-0.222035044,0.411517133,-0.905274779,-0.360880875,-1.24088274,-0.479493513,0.238737649,-0.269728499,-0.820084002,0.138557478,-0.816119664,119 121 | 119,-0.264446582,0.138052709,-1.514886795,0.032637295,1.511868401,0.106191316,-0.766182568,-0.709007622,-2.444148776,-1.052772032,-0.176673755,-0.406353055,1.591441374,1.784031643,-0.443739703,0.774324735,120 122 | 120,0.384311096,-0.118792026,0.434536656,-1.025059481,-0.643609065,-1.449220833,1.006729041,0.964313072,-0.419301018,-0.430430782,3.039033406,0.825264955,0.399448456,0.346047281,-0.600657749,-1.00585121,121 123 | 121,-1.037667088,0.197684262,-0.519536667,-0.982249076,-0.130950479,1.138551724,-1.69889946,-0.885634952,-0.367715385,1.897956032,-0.420907349,-1.164937017,-0.184208729,0.426250881,0.705694864,-0.763882509,122 124 | 122,-2.06002755,-1.068692711,-0.834559033,0.004101957,0.485211453,1.813824711,-0.384019443,-0.148970529,-0.563246326,-1.879180594,-0.55195499,1.438925479,-0.188084423,-1.308716782,-1.349783905,-0.568438832,123 125 | 123,-1.561771632,-0.803213217,-0.756647609,-0.233427178,-0.645182435,-1.511038733,-0.80877313,2.067510451,-1.389757035,-0.071640922,-0.625227248,0.224060911,-0.036269792,-0.107885526,-1.157650828,1.109217575,124 126 | 124,-0.042494578,-1.113765136,1.089503495,-0.498888219,-0.46395622,-0.018086859,-0.524889374,-1.296593801,-0.632436098,2.232839589,-1.141814175,1.828273861,1.318360346,1.245114697,1.701450862,-0.669352041,125 127 | 125,2.024847774,1.580091684,1.572432917,1.549712963,0.567249697,-0.880188098,0.71488719,-0.846851351,1.610932919,0.41758521,0.396962728,-0.372392142,-0.370601328,0.447912023,0.207304453,-0.788429964,126 128 | 126,1.851200643,1.497818761,1.007364366,0.087496917,-0.723407834,-1.197477099,0.702029289,-0.471162526,-0.239335747,1.179985538,0.17368697,0.079365064,-0.764146956,-0.385840565,1.267715193,-0.281926112,127 129 | 127,0.624269528,0.262645459,-0.273157993,1.318701131,0.455884554,1.068758958,-0.768700129,-1.624931454,-0.595278433,1.694488458,1.192089338,-0.601685616,0.21136144,0.056703558,-1.950697017,-0.00191686,128 130 | 128,-1.344879317,-1.2329012,-1.309679542,-0.981224119,-1.197934626,1.166736858,-1.877124097,0.182127273,-0.162365078,0.948469498,0.441929819,0.16374377,0.388238839,0.585476755,0.283509931,0.300163466,129 131 | 129,0.062812463,-0.003723534,0.222573831,-0.245622588,-2.01818055,2.029958496,-0.770522589,-2.094847822,-2.703013915,0.599024922,-1.266151574,-0.194328978,0.952139515,-0.448643858,-0.625847773,-0.030648219,130 132 | 130,0.688757243,1.511672283,1.113433184,-1.403933837,0.619723405,0.500172741,1.333966526,-0.40979684,-1.211183242,-1.534688691,-0.316275825,-0.292452802,-0.759488667,-0.782214965,0.590831457,-0.342077979,131 133 | 131,1.432784868,-0.475698284,0.837394397,1.440893147,-0.132857466,-1.822749779,-0.020293545,-0.891486678,0.605711746,-1.907126951,0.096958487,0.616207347,0.442527574,1.596581839,1.495720115,0.932520104,132 134 | 132,-0.22185603,0.797916438,0.314516768,-0.981359991,-0.43496074,0.489161061,-0.881977272,-0.732758007,0.280736379,-1.135182758,2.251761876,0.561015584,-0.123499108,-1.652819254,-0.015103668,-2.252575978,133 135 | 133,0.493231805,-0.974002561,0.222218072,1.474244904,-0.521754179,-0.693889397,0.008728021,1.113110482,-0.456470172,0.033450286,-1.0508177,-2.172103982,-0.708286809,-0.848419868,1.275923026,-0.574037114,134 136 | 134,-0.508608751,0.689372698,-0.84361539,-0.991197245,0.992288426,-0.199064512,0.822826091,0.68255038,0.017132293,-0.136510238,-0.23463841,-1.794765139,-1.088603487,-0.129652903,-0.386446715,0.603756377,135 137 | 135,-0.186119181,-0.955839103,0.443805326,-0.094497345,-1.085422408,0.241954076,1.84784878,1.75188651,2.20619316,1.280011887,0.793640773,0.588233838,-1.428601801,-0.455992446,1.513543568,-1.419254226,136 138 | 136,-2.670364795,-1.231707058,0.055797111,-2.875141684,0.959832414,0.070352503,0.541310354,1.016537256,-2.231128465,0.142997759,-0.627199868,-1.572572151,-0.00385755,-0.078980079,1.295041953,0.008025292,137 139 | 137,-0.843175091,-0.956891881,0.06797239,-0.246866101,-1.039010541,0.794146066,-0.990387611,0.140094492,0.752354109,-0.83416416,-0.454552625,1.023097892,-0.704556756,1.091114928,0.165478475,0.60959165,138 140 | 138,-0.744328424,-0.869782874,-0.201961742,0.01474449,-0.137841967,-0.655378696,2.27707702,-0.645259935,0.60185831,-0.512683474,-0.707923609,0.075923839,-0.292416863,-1.225087031,0.688814992,0.009016888,139 141 | 139,-2.305053107,-0.910680682,-1.158015254,-1.919087703,-0.214708418,-0.677465097,0.088089367,0.213205712,0.62481827,-1.905198033,-1.791337818,-0.111459239,-0.496069582,1.088696651,0.344313503,-2.12835467,140 142 | 140,-0.297608597,0.741276305,-0.59274327,-0.287813744,0.573718585,0.183818514,1.42103578,0.275515394,0.90923221,1.506874988,-3.04536393,-1.661785215,2.066324413,2.725948058,0.340159595,0.272121075,141 143 | 141,0.739820337,0.068511533,0.766065384,-0.346637445,-1.776449315,0.877708267,1.30179821,-0.298135578,-0.147238805,-1.679485022,-0.097388392,-0.670606877,1.659180485,0.618609045,0.162454503,-0.192968046,142 144 | 142,-0.700048717,-0.323750755,0.038928117,-1.839588585,-0.256392295,-0.392230913,-2.037916075,-1.495382694,0.977888518,0.977703631,-1.296783557,0.800619551,-0.698221181,-0.466427214,0.786759423,-0.890871461,143 145 | 143,-0.063839356,-1.086503047,0.014646812,0.898588941,-0.138550636,-0.668948305,1.640861968,0.721642697,0.452138604,1.18075778,0.191180067,1.101119311,2.0905114,-1.287148487,-0.110633581,0.57908389,144 146 | 144,-1.187593931,-1.015928947,-0.186316968,-1.212855011,0.557684974,-1.010133243,-0.1099261,-0.827308016,0.950129267,1.307071194,0.811118929,-1.248779945,-1.049138094,0.785175234,-0.405204687,0.150359557,145 147 | 145,0.195727501,-0.767790185,1.400590827,-0.218964232,1.122346289,-0.750830596,-0.837959393,-1.269333501,-1.212329011,0.190404684,-0.735002273,0.883923403,1.240089497,0.563318007,0.495112465,-0.325962548,146 148 | 146,-0.019617019,-1.119720061,0.01848557,0.564268161,-0.982147207,-0.283552997,0.074671122,0.033673463,0.476068058,-0.826422917,-0.104626876,1.091677453,0.310778919,0.615917586,-0.417505825,-0.064914359,147 149 | 147,-0.711418809,-0.448174237,0.249196012,-0.525434376,0.326905556,-1.165802981,0.081318426,-0.417976052,1.266090481,0.987840519,-0.695506182,-1.68195666,-0.632343163,-0.117223397,-2.468550923,-2.223381467,148 150 | 148,0.885396639,0.471736374,0.149220736,0.744374225,0.447826608,0.691224986,0.025691173,0.949049121,0.106647185,0.170720586,0.003144412,-0.38434434,-0.864638743,-0.048230808,0.840822078,0.039597163,149 151 | 149,-0.977554228,-1.180490683,-0.96323318,0.128981753,1.18372412,-2.056537631,-0.147900751,-0.422709861,-1.010398912,-0.735182927,-0.843264997,0.115617078,0.959247155,-0.15283589,1.35183625,-0.884058603,150 152 | 150,1.801626956,1.470256997,-0.066466774,1.488274257,-0.088616917,-0.154174503,1.502843673,1.117319092,1.178892424,0.182589646,-0.68402834,-0.307148834,0.962662147,0.176458401,1.222699765,0.974096878,151 153 | 151,0.336646334,-1.311420592,1.286922041,-0.662681951,1.14699788,-1.444894311,1.032092476,0.289454189,-1.838227927,0.821975601,0.845993521,-0.682252163,-0.952393646,0.92799049,1.519841615,-0.446652685,152 154 | 152,0.089155445,-0.096524923,0.458125259,-1.160655001,0.086812573,1.216150864,0.337354695,0.200478092,-1.212218365,0.100816546,-0.624043001,0.435417274,0.800488259,0.313293234,0.282758442,-0.796320143,153 155 | 153,1.231651724,2.369719908,-1.45202829,0.358774234,-0.295005034,-0.511171137,-0.581434246,-0.226224485,-0.772288901,0.762868775,0.884743296,0.250775217,0.802941518,0.406071646,-1.551473233,-0.862691905,154 156 | 154,0.783581665,0.890626476,0.077342277,-0.194846384,0.512332939,1.128538757,1.244994894,1.193177445,-0.350078968,-0.079096091,0.226134143,2.255961745,-0.771064301,-1.121584015,-0.4712982,-0.714395666,155 157 | 155,0.040585013,-0.252183161,0.559895273,-0.295282008,0.283313635,-0.419643268,0.690653149,-0.456131413,1.681213501,0.657962825,-0.561093103,-0.633142144,-2.159200371,-0.586500578,0.584866968,0.975371647,156 158 | 156,-1.153631278,-0.865763755,-0.07494657,0.496640424,0.384543716,-0.212739735,-0.417081729,-0.662115621,-2.290655613,-0.522582629,-0.548088166,0.121634123,-0.148960788,0.337196754,-1.019230639,-0.079010701,157 159 | 157,2.106869323,0.582586,0.782697698,0.484912788,1.004804339,-1.02066078,-0.489816014,0.209490966,-0.004754307,-0.875358162,0.330497185,-0.927705602,-0.386030708,0.488670338,-0.068561665,-0.619558263,158 160 | 158,-0.015480813,-0.012529347,-0.172668564,0.018784501,-0.285965791,-3.082363618,-0.242281385,0.201259903,-0.2034548,-0.604894535,-0.753474307,-0.875632663,-0.526813646,-0.365247902,-0.642465325,1.312069838,159 161 | 159,-0.411050755,-0.374854762,-1.051293778,0.634774565,-0.237339891,1.646143363,-0.153078892,1.99883064,0.699863428,1.391125793,1.16513796,-0.269017211,1.465568584,-0.339786613,0.775554207,0.076592616,160 162 | 160,0.272054192,0.317885735,0.729451279,0.754444088,-0.203674367,-1.411214006,0.390395215,-0.057076331,0.301407326,-0.313213222,-0.278377708,0.682869143,0.035641528,-0.276574394,0.05096499,0.239757999,161 163 | 161,0.435388656,-0.488805635,0.262665243,0.833589035,1.072472006,2.565137631,0.890180929,0.803540155,-1.663313685,-0.433932651,-0.546895962,1.430435164,0.458915862,-1.967811426,-0.079491172,0.997734549,162 164 | 162,1.883223527,2.658658027,0.543657859,0.965761296,1.950277786,0.325593714,0.225088397,-0.044121274,-0.491325516,0.777692822,-0.279326004,-0.377348936,0.050041338,0.873394781,1.717859293,-1.138102596,163 165 | 163,1.696221513,1.680278205,1.041060298,1.293879968,0.964454067,-0.565537819,-1.67929164,1.53452555,-0.35981963,-0.285538467,0.212086403,-0.794411941,1.478823273,0.713876944,0.489829332,0.384707215,164 166 | 164,0.165738076,0.779584009,0.197506154,-0.136551021,1.038404588,0.698898676,0.360169527,0.566811332,1.669150437,2.521079402,0.182184147,0.260396142,0.676012674,0.753077073,-0.461808359,0.497359889,165 167 | 165,-0.59209689,0.71324052,-1.629578287,-0.440138688,1.768873604,0.880715097,1.109479734,0.649084336,0.941349201,0.60332979,-1.207440093,1.248038471,0.597211031,0.258337982,0.159953041,0.49502696,166 168 | 166,-1.139827128,-0.542881937,0.121040232,-1.227283914,-0.571650147,-0.227754971,-1.306214904,0.285925129,1.622805976,1.733835432,1.554547077,0.778845911,-1.471049666,-0.64942678,1.030633053,1.225440377,167 169 | 167,-0.104977917,0.885778374,-1.637421952,-0.23765307,-1.47028289,0.136300749,-1.888023325,-0.914628937,0.891115794,0.538407002,-1.737773272,-0.030964452,0.353478133,-0.257594379,1.130032727,-1.987110473,168 170 | 168,-0.93168575,-0.348594685,-0.531043106,-0.926858157,-1.110366445,1.843408233,0.793703174,-0.609244687,-0.53101501,-1.737361637,-0.379333079,-1.607829278,0.827618477,-0.202543523,0.446139843,0.796968796,169 171 | 169,-0.173297872,-1.008054578,0.953679792,0.411235356,0.254403389,-1.405391718,-0.384638164,0.557649808,1.020483188,1.26347319,1.131995752,-0.66020866,-0.066629108,0.761007527,0.123550542,-0.343921685,170 172 | 170,0.575573075,1.883182542,-1.720650662,-0.198864577,0.023344681,-0.04908307,0.514865992,-1.034427667,1.115284992,0.569851847,-0.02443501,0.927057562,2.250547337,-1.527547348,1.017838939,-0.89970054,171 173 | 171,-0.515795098,-0.928971079,0.10632062,-0.557449639,-2.715925295,0.794154507,-0.237384993,1.229823128,0.19559671,-1.032964008,-0.896385344,1.023586754,0.559071371,1.823483022,0.039870927,-0.066624358,172 174 | 172,0.207779494,-0.294196454,-0.608668497,-0.977157122,1.185289251,-1.414023515,1.74151053,-1.292256798,1.3485703,0.565584525,-0.390056923,-1.217079611,-1.004164434,0.039570983,0.858307701,-0.297209518,173 175 | 173,0.363133441,-0.614950271,-0.301196983,0.060735249,-0.219755198,-1.789927363,1.204177513,-1.184617891,0.135897719,0.983549854,-1.078648124,0.174986327,0.899908483,0.355913541,0.806473398,0.043654937,174 176 | 174,-0.568231536,-0.947075792,0.976202525,-0.59722948,-0.056672761,1.354397332,0.65597502,-1.144277303,1.554453184,-0.908270382,0.964569706,-0.653398932,0.151802686,-0.147435874,-0.67696362,0.257324539,175 177 | 175,0.159885759,0.59897515,0.456008669,-1.258948697,0.406564509,-0.747766705,0.83932595,0.092296358,-0.138896716,-1.292037549,0.756197921,2.015133813,-0.301307962,-2.096212959,-1.372732673,0.905876449,176 178 | 176,0.023562174,-1.523614882,1.294408067,-1.410047202,-1.30942995,-1.037452478,0.958668065,1.094144689,-0.120680238,0.772685635,-0.278710423,0.223503712,0.051190316,-0.183994369,0.673659048,-0.119588424,177 179 | 177,-0.831957328,-0.206189002,-1.133202206,1.101304079,-0.706691287,-0.036172136,1.13579957,-1.562430655,0.752278212,-0.765549224,-1.050274676,-1.285040275,0.291556325,1.703921486,0.556100894,-0.229456936,178 180 | 178,-1.015645081,-0.574295414,-0.869460351,-0.677242026,1.03389167,-0.554350606,-0.925763153,-0.40569949,0.331288063,0.773837632,-1.113884938,0.483457992,0.244785556,1.650853213,-0.393123793,-2.108012727,179 181 | 179,-1.357885801,-1.390166037,-0.754970292,-0.762173508,1.972760967,-0.558866752,1.59361722,0.073486353,-1.602345131,1.024200734,1.352246427,-0.479856056,0.082719939,1.342807242,-0.199665321,1.170833186,180 182 | 180,-0.931714266,-0.070417383,-0.12963535,-0.291748602,0.687525073,-1.419873383,-1.41596692,-1.585505278,-0.772824783,0.849142794,0.788628699,-0.362424041,-0.040389229,1.40143402,0.446776747,-0.734386453,181 183 | 181,-1.679570842,-0.43087953,-1.001801335,-0.575188529,0.73824255,-0.907959854,-2.148470041,-0.258303487,-1.122847123,0.199449127,-2.247880159,0.307533683,0.756686186,-0.120919688,0.685100824,-0.267543412,182 184 | 182,-1.060078581,-0.592225373,-0.819868279,-0.443941868,-1.708270232,0.847633095,-0.184970096,-0.197744288,0.390834599,-1.336344882,0.047877345,1.149452826,1.720534429,0.307722461,0.900553648,-0.738629165,183 185 | 183,0.224942478,0.98111616,-0.974552469,-0.312570444,1.052619791,0.4994631,0.63395339,1.038719037,-1.121380025,0.360678647,2.525078381,-0.962784803,-0.226413561,-0.520764278,0.472261039,-0.685817664,184 186 | 184,0.355675624,0.532409357,0.604309409,-0.603004426,1.123239109,-0.637825518,0.402342137,0.667308112,-0.066534534,0.139099351,-1.016402099,2.51607414,0.10952391,0.251365867,0.332653999,0.906097949,185 187 | 185,-0.356890492,-0.090456124,0.548787588,-1.09393472,-0.354592006,2.415505148,0.588949745,-1.309604286,0.995625467,-0.833698289,-1.720653337,0.922189547,0.538242157,1.010155692,0.953546268,2.26095326,186 188 | 186,1.146975882,0.156490492,0.916432657,0.714706191,0.188238853,1.480908125,0.108808268,-1.140005277,-2.288000228,-0.165219145,-2.251953936,-1.7932031,0.077257403,1.13567866,0.749919177,1.234677337,187 189 | 187,-0.016128894,-0.737311691,2.661566367,-0.108812263,0.923800027,-0.738981759,-0.597642161,-0.748624469,-0.136758223,-1.051875795,-0.223295382,-1.587110423,-0.461804184,-0.262285027,0.303354714,1.3543494,188 190 | 188,-0.733417628,-0.201341206,-0.180257065,-1.443797935,2.152700843,-0.097765133,0.148902158,-2.114039099,0.820796987,0.201068278,-0.767450613,-0.04285047,0.76599536,-1.503257311,0.221734993,0.083696265,189 191 | 189,1.021435884,1.102176595,0.685014766,0.806123264,-1.109739343,-3.236385732,1.811480863,-1.169804169,-0.979435961,-1.971229024,0.929763401,-0.259892567,1.669878771,0.925970028,1.395814063,0.163520789,190 192 | 190,0.312633221,-0.016748256,3.266414519,-1.739835078,1.029508222,0.957063658,-0.271064093,0.803537215,0.67116764,-0.311029855,-1.290008417,0.387522763,0.908991946,1.271909144,2.919638288,0.351157727,191 193 | 191,-0.05676093,0.161788634,0.56060046,-0.401320309,1.37715475,0.559334175,0.500359049,-0.40811502,0.702056738,0.457731534,-0.570331658,0.643742835,0.551367376,2.289362387,0.107093138,0.744798974,192 194 | 192,0.061069717,2.02476139,-0.069017297,-0.287582489,0.914811052,-0.497700713,0.497216117,0.753422401,-0.312232281,-1.713996145,0.96128165,-1.703471735,-1.230242358,-0.859077266,-0.066677885,-0.471346192,193 195 | 193,-1.236348214,-0.703694254,-0.972442936,-0.9384074,0.293623431,-0.19398031,1.228651798,0.796645366,-0.118990405,-0.817641995,-0.212036108,1.14521306,-0.180058823,0.065029672,-1.143123679,-0.172452017,194 196 | 194,0.186016689,0.960792384,-0.546586586,0.287667139,-0.151738625,0.086334935,-1.089333865,-0.759068152,0.224424832,-0.409473254,-0.533410636,-0.388666069,-1.385531041,1.063516808,-0.589357051,-0.144921522,195 197 | 195,-0.98689208,1.790485054,-1.688692328,-1.505401124,0.16489144,1.017507538,-0.371810022,-0.461154269,-1.123831574,1.108882624,0.002205478,-0.197546348,0.061680831,-0.326253323,0.478526485,-1.590491059,196 198 | 196,-0.458651464,-1.064165163,-1.572372699,1.519297013,0.868577431,-0.969918023,0.291790766,1.904376558,1.08174332,2.059115051,-0.346823573,2.592252087,-1.194685911,1.776473726,-0.540043275,0.734869562,197 199 | 197,0.800347912,0.017636546,-0.404987158,0.367409356,-1.078034493,1.066352402,-0.418050399,-0.348631968,1.261542624,-0.096136937,-0.485861799,1.287147093,1.217083068,-1.643429013,2.498485859,1.150781131,198 200 | 198,1.773410841,-0.389908629,0.319286418,1.699862409,-1.222331968,0.755509155,0.184774465,0.218830943,0.818226074,-1.125490655,0.216737308,-0.243945489,0.431058784,-0.782347338,-0.496727092,-0.842044974,199 201 | 199,0.488845461,-0.490832752,0.040427682,0.644196977,-0.711444696,-0.703252294,-0.250855312,1.144954562,0.519058165,0.050200606,-1.148486416,0.006219053,-0.456680962,0.015476041,-0.432610498,-0.861278455,200 -------------------------------------------------------------------------------- /LICENSE.txt/TXT.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf2513 2 | \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 .SFNSMono-Regular;} 3 | {\colortbl;\red255\green255\blue255;\red38\green38\blue38;} 4 | {\*\expandedcolortbl;;\cssrgb\c20000\c20000\c20000;} 5 | \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 6 | \deftab720 7 | 8 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrt\brdrnil \trbrdrl\brdrnil \trbrdrr\brdrnil 9 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt80 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 10 | \clmrg \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt80 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 11 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 12 | 13 | \f0\fs24 \cf2 \expnd0\expndtw0\kerning0 14 | \outl0\strokewidth0 \strokec2 MIT License\cell 15 | \pard\intbl\itap1\cell \row 16 | 17 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 18 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 19 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 20 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 21 | \cf2 \cell 22 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 23 | \cf2 Copyright (c) 2022 Ryan Lucas\cell \row 24 | 25 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 26 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 27 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 28 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 29 | \cf2 \cell 30 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 31 | \cf2 Permission is hereby granted, free of charge, to any person obtaining a copy\cell \row 32 | 33 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 34 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 35 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 36 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 37 | \cf2 \cell 38 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 39 | \cf2 of this software and associated documentation files (the "Software"), to deal\cell \row 40 | 41 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 42 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 43 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 44 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 45 | \cf2 \cell 46 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 47 | \cf2 in the Software without restriction, including without limitation the rights\cell \row 48 | 49 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 50 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 51 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 52 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 53 | \cf2 \cell 54 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 55 | \cf2 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\cell \row 56 | 57 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 58 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 59 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 60 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 61 | \cf2 \cell 62 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 63 | \cf2 copies of the Software, and to permit persons to whom the Software is\cell \row 64 | 65 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 66 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 67 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 68 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 69 | \cf2 \cell 70 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 71 | \cf2 furnished to do so, subject to the following conditions:\cell \row 72 | 73 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 74 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 75 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 76 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 77 | \cf2 \cell 78 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 79 | \cf2 The above copyright notice and this permission notice shall be included in all\cell \row 80 | 81 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 82 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 83 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 84 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 85 | \cf2 \cell 86 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 87 | \cf2 copies or substantial portions of the Software.\cell \row 88 | 89 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 90 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 91 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 92 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 93 | \cf2 \cell 94 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 95 | \cf2 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\cell \row 96 | 97 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 98 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 99 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 100 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 101 | \cf2 \cell 102 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 103 | \cf2 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\cell \row 104 | 105 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 106 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 107 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 108 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 109 | \cf2 \cell 110 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 111 | \cf2 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\cell \row 112 | 113 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 114 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 115 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 116 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 117 | \cf2 \cell 118 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 119 | \cf2 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\cell \row 120 | 121 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 122 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 123 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 124 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 125 | \cf2 \cell 126 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 127 | \cf2 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\cell \row 128 | 129 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrr\brdrnil 130 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 131 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 132 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 133 | \cf2 \cell 134 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 135 | \cf2 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\cell \row 136 | 137 | \itap1\trowd \taflags1 \trgaph108\trleft-108 \trbrdrl\brdrnil \trbrdrt\brdrnil \trbrdrr\brdrnil 138 | \clvertalt \clshdrawnil \clwWidth1632\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx4320 139 | \clvertalt \clshdrawnil \clwWidth11572\clftsWidth3 \clbrdrt\brdrnil \clbrdrl\brdrnil \clbrdrb\brdrnil \clbrdrr\brdrnil \clpadt20 \clpadl200 \clpadb20 \clpadr200 \gaph\cellx8640 140 | \pard\intbl\itap1\pardeftab720\sl400\qr\partightenfactor0 141 | \cf2 \cell 142 | \pard\intbl\itap1\pardeftab720\sl400\partightenfactor0 143 | \cf2 SOFTWARE.\cell \lastrow\row 144 | } -------------------------------------------------------------------------------- /MacroRandomForest.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 2.1 2 | Name: MacroRandomForest 3 | Version: 1.0.5 4 | Summary: Macroeconomic Random Forest by Ryan Lucas (code) and Philippe Goulet Coulombe (method) 5 | Home-page: https://github.com/RyanLucas3/MacroRandomForest 6 | Download-URL: https://github.com/RyanLucas3/MacroRandomForest/archive/refs/tags/1.0.5.tar.gz 7 | Author: 8 | Author-email: ryanlu@mit.edu 9 | License: MIT 10 | Keywords: Time Series,Forecasting,Economics,Macro,Machine Learning,RandomForest 11 | Classifier: Development Status :: 3 - Alpha 12 | Classifier: Intended Audience :: Developers 13 | Classifier: Topic :: Software Development :: Build Tools 14 | Classifier: License :: OSI Approved :: MIT License 15 | Classifier: Programming Language :: Python :: 3 16 | Classifier: Programming Language :: Python :: 3.4 17 | Classifier: Programming Language :: Python :: 3.5 18 | Classifier: Programming Language :: Python :: 3.6 19 | Classifier: Programming Language :: Python :: 3.7 20 | Classifier: Programming Language :: Python :: 3.8 21 | -------------------------------------------------------------------------------- /MacroRandomForest.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | README.md 2 | setup.cfg 3 | setup.py 4 | MacroRandomForest/MRF.py 5 | MacroRandomForest/__init__.py 6 | MacroRandomForest.egg-info/PKG-INFO 7 | MacroRandomForest.egg-info/SOURCES.txt 8 | MacroRandomForest.egg-info/dependency_links.txt 9 | MacroRandomForest.egg-info/requires.txt 10 | MacroRandomForest.egg-info/top_level.txt -------------------------------------------------------------------------------- /MacroRandomForest.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /MacroRandomForest.egg-info/requires.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | pandas 3 | matplotlib 4 | joblib 5 | -------------------------------------------------------------------------------- /MacroRandomForest.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | MacroRandomForest 2 | -------------------------------------------------------------------------------- /MacroRandomForest/All_predictors.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "source": [ 7 | "# !pip install MacroRandomForest\n", 8 | "from MRF import *" 9 | ], 10 | "outputs": [], 11 | "metadata": {} 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 2, 16 | "source": [ 17 | "import pandas as pd\n", 18 | "import numpy as np" 19 | ], 20 | "outputs": [], 21 | "metadata": {} 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 3, 26 | "source": [ 27 | "start_date = \"2000-01-01\"" 28 | ], 29 | "outputs": [], 30 | "metadata": {} 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 4, 35 | "source": [ 36 | "SP500_returns = pd.read_csv(\"erp_save.csv\", index_col = \"Date\").loc[start_date:]\n", 37 | "quantile_measures = pd.read_csv(\"df1_save.csv\", index_col = \"Date\").loc[start_date:]\n", 38 | "controls = pd.read_csv(\"df2_save.csv\", index_col = \"Date\").loc[start_date:]" 39 | ], 40 | "outputs": [], 41 | "metadata": {} 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 5, 46 | "source": [ 47 | "del controls[\"ERP\"]\n", 48 | "controls[\"ERP_L1\"].fillna(0, inplace = True)" 49 | ], 50 | "outputs": [], 51 | "metadata": {} 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 6, 56 | "source": [ 57 | "MRF_data = pd.concat([SP500_returns['erp1w'], quantile_measures, controls], axis = 1)\n", 58 | "MRF_data = MRF_data.iloc[:-1] # Since the last day is nan for SP500_returns\n", 59 | "MRF_data['trend'] = [i for i in range(MRF_data.shape[0])]" 60 | ], 61 | "outputs": [], 62 | "metadata": {} 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 7, 67 | "source": [ 68 | "x_vars = [\"VRP_monthly\", \"SkewAvg_1_10\", \"SkewAvg_4_7\"]\n", 69 | "x_pos = [MRF_data.columns.get_loc(var) for var in x_vars]" 70 | ], 71 | "outputs": [], 72 | "metadata": {} 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 8, 77 | "source": [ 78 | "training_end = int(0.6*len(MRF_data))\n", 79 | "testing_period = np.arange(training_end+1, len(MRF_data))" 80 | ], 81 | "outputs": [], 82 | "metadata": {} 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 9, 87 | "source": [ 88 | "model = MacroRandomForest(data = MRF_data, \n", 89 | " x_pos = x_pos, \n", 90 | " oos_pos = testing_period, \n", 91 | " parallelise=True, \n", 92 | " n_cores = -1, \n", 93 | " B = 100)" 94 | ], 95 | "outputs": [], 96 | "metadata": {} 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 10, 101 | "source": [ 102 | "fitted = model._ensemble_loop()" 103 | ], 104 | "outputs": [ 105 | { 106 | "output_type": "stream", 107 | "name": "stdout", 108 | "text": [ 109 | "Tree 1 out of 100\n", 110 | "Tree 2 out of 100\n", 111 | "Tree 3 out of 100\n", 112 | "Tree 4 out of 100\n", 113 | "Tree 7 out of 100\n", 114 | "Tree 8 out of 100\n", 115 | "Tree 6 out of 100\n", 116 | "Tree 5 out of 100\n", 117 | "Tree 9 out of 100\n", 118 | "Tree 10 out of 100\n", 119 | "Tree 11 out of 100\n", 120 | "Tree 12 out of 100\n", 121 | "Tree 13 out of 100\n", 122 | "Tree 14 out of 100\n", 123 | "Tree 15 out of 100\n", 124 | "Tree 16 out of 100\n", 125 | "Tree 17 out of 100\n", 126 | "Tree 18 out of 100\n", 127 | "Tree 19 out of 100\n", 128 | "Tree 20 out of 100\n", 129 | "Tree 21 out of 100\n", 130 | "Tree 22 out of 100\n", 131 | "Tree 23 out of 100\n", 132 | "Tree 24 out of 100\n", 133 | "Tree 25 out of 100\n", 134 | "Tree 26 out of 100\n", 135 | "Tree 27 out of 100\n", 136 | "Tree 28 out of 100\n", 137 | "Tree 29 out of 100\n", 138 | "Tree 30 out of 100\n", 139 | "Tree 31 out of 100\n", 140 | "Tree 32 out of 100\n", 141 | "Tree 33 out of 100\n", 142 | "Tree 34 out of 100\n", 143 | "Tree 35 out of 100\n", 144 | "Tree 36 out of 100\n", 145 | "Tree 37 out of 100\n", 146 | "Tree 38 out of 100\n", 147 | "Tree 39 out of 100\n", 148 | "Tree 40 out of 100\n", 149 | "Tree 41 out of 100\n", 150 | "Tree 42 out of 100\n", 151 | "Tree 43 out of 100\n", 152 | "Tree 44 out of 100\n", 153 | "Tree 45 out of 100\n", 154 | "Tree 46 out of 100\n", 155 | "Tree 47 out of 100\n", 156 | "Tree 48 out of 100\n", 157 | "Tree 49 out of 100\n", 158 | "Tree 50 out of 100\n", 159 | "Tree 51 out of 100\n", 160 | "Tree 52 out of 100\n", 161 | "Tree 53 out of 100\n", 162 | "Tree 54 out of 100\n", 163 | "Tree 55 out of 100\n", 164 | "Tree 56 out of 100\n", 165 | "Tree 57 out of 100\n", 166 | "Tree 58 out of 100\n", 167 | "Tree 59 out of 100\n", 168 | "Tree 60 out of 100\n", 169 | "Tree 61 out of 100\n", 170 | "Tree 62 out of 100\n", 171 | "Tree 63 out of 100\n", 172 | "Tree 64 out of 100\n", 173 | "Tree 65 out of 100\n", 174 | "Tree 66 out of 100\n", 175 | "Tree 67 out of 100\n", 176 | "Tree 68 out of 100\n", 177 | "Tree 69 out of 100\n", 178 | "Tree 70 out of 100\n", 179 | "Tree 71 out of 100\n", 180 | "Tree 72 out of 100\n", 181 | "Tree 73 out of 100\n", 182 | "Tree 74 out of 100\n", 183 | "Tree 75 out of 100\n", 184 | "Tree 76 out of 100\n", 185 | "Tree 77 out of 100\n", 186 | "Tree 78 out of 100\n", 187 | "Tree 79 out of 100\n", 188 | "Tree 80 out of 100\n", 189 | "Tree 81 out of 100\n", 190 | "Tree 82 out of 100\n", 191 | "Tree 83 out of 100\n", 192 | "Tree 84 out of 100\n", 193 | "Tree 85 out of 100\n", 194 | "Tree 86 out of 100\n", 195 | "Tree 87 out of 100\n", 196 | "Tree 88 out of 100\n", 197 | "Tree 89 out of 100\n", 198 | "Tree 90 out of 100\n", 199 | "Tree 91 out of 100\n", 200 | "Tree 92 out of 100\n", 201 | "Tree 93 out of 100\n", 202 | "Tree 94 out of 100\n", 203 | "Tree 95 out of 100\n", 204 | "Tree 96 out of 100\n", 205 | "Tree 97 out of 100\n", 206 | "Tree 98 out of 100\n", 207 | "Tree 99 out of 100\n", 208 | "Tree 100 out of 100\n" 209 | ] 210 | } 211 | ], 212 | "metadata": {} 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 11, 217 | "source": [ 218 | "index_for_plotting = pd.DatetimeIndex(controls.index[:-1])" 219 | ], 220 | "outputs": [], 221 | "metadata": {} 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 12, 226 | "source": [ 227 | "fig, ax = plt.subplots()\n", 228 | "\n", 229 | "VRP_beta1 = pd.DataFrame(fitted['betas'])[0]\n", 230 | "VRP_beta2 = pd.DataFrame(fitted['betas'])[1]\n", 231 | "VRP_beta3 = pd.DataFrame(fitted['betas'])[2]\n", 232 | "VRP_beta1.index = index_for_plotting\n", 233 | "VRP_beta2.index = index_for_plotting\n", 234 | "VRP_beta3.index = index_for_plotting\n", 235 | "ax.plot(VRP_beta1.rolling(63).mean())\n", 236 | "ax.plot(VRP_beta2.rolling(63).mean())\n", 237 | "ax.plot(VRP_beta3.rolling(63).mean())" 238 | ], 239 | "outputs": [ 240 | { 241 | "output_type": "execute_result", 242 | "data": { 243 | "text/plain": [ 244 | "[]" 245 | ] 246 | }, 247 | "metadata": {}, 248 | "execution_count": 12 249 | }, 250 | { 251 | "output_type": "display_data", 252 | "data": { 253 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXgAAAD4CAYAAADmWv3KAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAABm6UlEQVR4nO2ddXhVV9aH33Pj7gZJSAju7u6UFlqoUnefdqbu7fSrTn0qU512KlSoQFsoTpHibiHECXF3P98f+0oCCbk3uZrs93l4zrnnnrvPIrlZZ5+11/otRVVVJBKJRNL50NjaAIlEIpFYBungJRKJpJMiHbxEIpF0UqSDl0gkkk6KdPASiUTSSXG2xUWDg4PVmJgYW1xaIpFIHJZ9+/blq6oaYuz5NnHwMTEx7N271xaXlkgkEodFUZQ0U86XIRqJRCLppEgHL5FIJJ0U6eAlEomkkyIdvEQikXRSpIOXSCSSTop08BKJRNJJkQ5eIpFIOilGO3hFUaIURdmkKMpxRVGOKYpyn/Z4oKIo6xRFOaXdBljO3C5KURrs+wKktLNEIjEBU2bw9cADqqoOAMYBdyuKMgB4FNigqmpvYIP2tcScfH0p/Po3+OEGSFhra2skEomDYLSDV1U1S1XV/dr9MuAE0B1YBHyhPe0L4GIz29i1Sd0G+Qli//gv8N01UFthU5MkEolj0K4YvKIoMcBwYBcQpqpqlvatbCCslc/cpijKXkVR9ubl5bXnsl2PmnL4fEHzYw01wulLJBJJG5js4BVF8QZ+BO5XVbW06Xuq6P/XYqBYVdWPVFUdparqqJAQo7VyujYpW8T2gtfg4g9g7kviddZh29kkkUgcBpPExhRFcUE4969VVf1JezhHUZQIVVWzFEWJAHLNbWSXpeCU2A6+DDz8xf6u/0DucZuZJJFIHAdTsmgU4FPghKqqbzR5ayVwvXb/emCF+czr4hQkgmewwbkDBMXBsZ9kHF4ikbSJKSGaicC1wAxFUQ5q/10AvAzMVhTlFDBL+1piDgqShENvSkCM2Mb/bnVzJBKJY2F0iEZV1W2A0srbM81jjkRPQRKkbRfhmabMfBr2fgZFqTYxSyKROA6yktVeydYupPZf2Py4RwD4dIOsQ9a3SSKROBTSwdsrJWfENnbKue8NuUyEaPJOWtcmiUTiUEgHb6+UZoKLF7j7nfveyBsAFU7vsrZVEonEgZAO3l4pzQDfbqC0sOzh3wOc3CBjj/XtkkgkDoN08PZKznHh4FtC4wTDroL9/4MM2bxcIpG0jHTw9sjpPaLIKaBH6+fMeUGEb764SIRzJBKJ5Cykg7dHNj4PGheY8VTr57h5w4I3oK4STq2znm0SicRhkA7eHsk9AUOuAO/Q8583aAl4hxk0ayQSiaQJ0sHbG40NUJkPvhFtn6soEDVG5sRLJJIWkQ7e3qgqArURvNqYvevwDocKKb8skUjORTp4e0PnrL2CjTvfKxiqi6GhzmImSSQSx0Q6eHtD7+CN1Mz3DBLbykLL2CORSBwW6eDtjXKtnL6xDl6XK19y2jL2SCQSh0U6eHujVKtBY6yDDxsottlHLGOPRCJxWKSDtyfK82DL6+AfLVQjjcFfWwz12/0iA0cikUi0SAdvTySshpoSWPAmaIz81TTVqpHpkhKJpAnSwdsTp9aCbyT0MrF/ytIfxDZbNuOWSCQGpIO3J/JPQbdhLStIno/es8HNT87gJRJJM6SDtydKM8G3u+mfUxSIGCKUJWUc3jzU10BZjq2tkEg6RKd18JnlmdQ1OlDxT3UJ1JSCXzscPEDEUBGi+Xi6ee3qqiy/CV7vA6pqa0skknbTKR18QlECc3+cy4eHPrS1Kcaja78X1Lt9n48YKrYyTGMe4n8T28oC29ohkXSATungX9r1EgB7cxyoGYZugVSX124qYYMM+/GrRIhBYhr1tfDdNfBskzaJuroEicQB6XQOvqSmRO/YS2pKbGyNCaTvBJ8IkQPfHsIGwOhbxf63V8GWf5nPtq5C5n448WvzY/v/B42NtrFHIukgnc7BxxfGAzAoaBApJSnUNDjITDY/QczCTc2gacqMJyF2qtjPOWYeu7oCqgqfzYPP5p773p5PYNd/rG+TRGIGOp2DzyjLAGBOzBwa1AaSipNsbJGRFKW1f/auw8Mfrl8JwX3g5CooTjeLaZ2eg99A+g7D66uXw7THDK9P77S+TRKJGXBIB6+qKv8+8G9OFZ065728KqHGOLH7RABOFp60qm3toqpYSP521MHryE8Q273/Nc94nZ0Vd4nt2Dvh5vWirmDqI4b366ptY5dE0kEc0sGX1pby0eGPuHnNzfpjNQ011DfWk1+Vj5+bH3F+cbg7uZNQlGBDS42kUPuUEdTLPOMt+VRsT60TC4eS1qnIF9vRt8D8lyFqtHjdNFQmm5pLHBSHdPBltWUAFNUU6Y9N+24aw78czncnvyPEIwQnjRN9AvpwssgBZvAFyWIbFGee8QZfCrOeg5wjsOsD84zZWTm9W2z7XnDuew8mwojrxM9xw/OG40WpsPtjWVQmsXuMdvCKonymKEquoihHmxx7VlGUM4qiHNT+a+GvxPzoHLyO8tpyyuvK9a8bVZH10CewD0fzj1LbYOez2IJEQIGAWPONOel+8IsWWSFyFt86J1eBuz/0mHjue94h0H2U2N/6miGb5vcHYdWD4glJIrFjTJnBfw7Ma+H4m6qqDtP+W2Ues85PaW1ps9f7c/c3e51eKhYXJ3abSFV9Fb8l/2YNs9pPYRL4RYKLu3nH9fCDjD3w19vmHbczUZoJgT1b/9kPWmIoPss6KLaZB8Q23wGeDiVdGqMdvKqqWwC76AvXdAavqiq7s3bjqnFl19JdAEyPFuX6M6NnEugeyL6cfTax02hy4yGkr/nHnf6E2O7+RPZsbYn6WkjaAN5hrZ/j5g03rwVXH/jzVVh+M1Rq4/brnoYd71vHVomkHZgjBn+PoiiHtSGcVrtUKIpym6IoexVF2ZuXl9ehCxZWG+4zRTVFFNUUEegRiKeLJ+suXceLk17UXZNhIcM4kHugQ9ezKLs/FjHekH7mH7vvfJj5DJRnGzJrJAZ2vCu2oW387D0DYeiVQq//6HJxLGKY2B740mLmSSQdpaMO/gMgDhgGZAGvt3aiqqofqao6SlXVUSEhRraja4Xcylz9fmZ5JiU1JQS4iXtLuFc47s6Gx+3BIYM5XXaa8tryc8axC1Y9KLaBZoy/NyV6vNiWZVlmfEcl7S/Y8JyYveuedM7H/Febv554H4y7C4plL1yJ/eLckQ+rqqrXU1UU5WPAKsHupg4+ozyDopoi/N38Wzw3xjcGgLSyNAYGtVPnxRo01ZIxJz7hYluWbZnxHY3yXHitiaBbYBw4ubT9OY0G7jsMdVVQlgkxk8VTUW2ZyKbROFnOZomknXRoBq8oSkSTl5cAR1s715zkVuXqHXdGWQaFVYX4u/u3eG4PX9GzNK0kzRqmmY5/NESOhuhxlhlfOvjmJP/Z/HVIH+M/G9BDhHPiZoibgrtWlKym9Pyfk0hshClpksuAHUBfRVEyFEW5GXhVUZQjiqIcBqYDf7eQnc3Iq8wjxi+GALcAMsoyyKnMIdwrvMVzo3yiADGDtzsKkoScQJyJLfpMwcVDOCLp4AUlTeQbgnrB7H+2fyydg692IFE7SZfC6BCNqqpXtXD4UzPaYjR5lXkMCxlGpE8ke7L3UNdYR4RXRIvnuju7E+kdyYa0Ddw+5HY0ih3VdmUfEdt+Fi4f8A6H1K0ij9vYZt6dlZIm8r83rTU46fag+2xVMbSaXiCR2A6H+2uvbailqKaIEM8QJkdOJr1MzMji/FqvAr1tyG2cLDppf+mSull1e9r0mYJPOOTFw79HWPY6jkBTATavoI6N5RUqtrZ6OlJVWPUwbJd1DpKWcTgHrxMTC/UMZWjwUP3xkWEjW/3M7B6z0SgadmXtsrh9JlGeDRoX8Ai07HXmiQYoFKVY9jr2TmkWpG4T+4E9Oz5eQIzYFtso/FeeA7s/FPn4BQ6imiqxKo7n4CsNDr5PoFggu2HgDTidJ4vB29WbfoH97KvDU0MdHF8hCpwsHTYJGwh95gMKNNRb9lr2zMlVUF8Ft26Cu3d3fDyvYHD2sJ0sc3mTpuC/3AXVcrFX0hyHc/AFVaJHZpB7EMEewWy/ajsPjHqgzc+NChvFkbwj9tMAJGkTFCbDsKutc72+8wEVSjOscz17pCwbFI3oX2tMamRbKIpw8pU2KvAub1IweHqnLLqSnIPDOXidqJi3izcAvq6+Rn1uRNgIahtr7UcfPu+E2A690jrX04UkCrtwmKYsC7xCzJuz7hEAVTZy8CXaIqtrfxbbzS/bxg6J3eJwDr6irgIATxdPkz4X7inSKHVPADYnN15kt3haOP6uI7Q/KE6QtNE617M3VBXO7DNfUxUdnoFQaaPvVMYesX7Tc7pY8K0pNejbSyQ4oIOvrK8EwMvFy6TP+bmJlLbimmJzm9Q+8k60rYFiTryCRZjmwFfCyXe1RtJl2ZB7HAZcbN5xPQJtE6JpbBS/x+jxIlS05BNxXKevI5HggA6+oq4CJ8UJNyc3kz6nc/BnSw3bjKJUUSZvTUbfLMIJX14CJ1YYju/6SIiedWZ0IbGIIeYd190XasraPs/cHP9FhJx6zxKve0wUzn7721BbYX17JHaJQzp4TxdPlKYt1YzA28UbZ8XZPmbwtZVQVQR+Fs5/P5vYaQZt89TtIky04z1Y/ZAQPevMvUdz48U2pL95x3X1BlsI2aVtBxcvGHG9eO3kDBPuBbURsq2iGCJxABzSwZsangEhHezr5msfDv5P7WKYb6R1r6vRwN27ILgP7PkY3h8Lax43vJ+23br2WJO8E+AZJLo0mRM3X6irtH766eldon9s0wVjnYTxZ3Osa4vEbnE4B19ZV4mXs+kOHsDfzZ+SGjvQDdFVHkaOsv61NU6tN7hIXG9dW6xJxj6RHmlu3EQ2l1Vn8TVlkHMMIsc0P+7bzbDfmZ/GJEbjcA6+vTN4EHF4mzv4em0evpuf+Zpsm8rs54Q88cgbxesrvoboCZBhR4Vg5qSxQczguw03/9iuWgdvzTh82g4Riok6y8ErCix4Q+wXyspWiSM6+PoKk1Mkdfi5+dk+RKOrerzg1fOfZ0m6j4Q7t8MFr8HN66D/hRA2QOjVqKrt7LIUlYXCIXq3rDjaIdx8xNaaDv7YTyL/Pmbyue/pwjQfTDDIMki6LA7n4CvrKts9gw9yDyK/ysZ5wkWpYqvTMbElTs6GWWBIP5FHXZppW5ssQYW24tPc8XdoordvpZ+bqor4e/T4lhuFNw3T/HVWymRZDny1BPJPWdZGid3gcA6+IyGaSJ9ICqsL9cVSNkFXSRpgoRZ97SVUm12Sd0IsGHamitcKbQcwLws4eF3h1B+PmX/slkjdKiQu+sxr+X3vUMN+wmpxro7TO8U6y8+3W9ZGid3gcA6+sr4ST+f2hWh0XaASimzYgLowScRtm/4h2gO6pt+58SJt8p1hsPe/NjXJbCRvFltLPDX5aPsQWKupecIacHaHwZe1/L7GCZZ8KvrFAmx6yfCern9sWc65n5N0ShzOwXdkBj82YiwaRcNfmX+Z2SoTKEgUi6sm5vFbHK9g8AyGw9/C3s/Esd/uFwuUjkz6Ttj2pti3hO6+xglG3wountZZv8g5Jp62XM8zyRl8qaFTVaU2JJm0CdZqm4uXZkgn30VwKAdf21BLfWN9ux28j6sPwe7B5FTY8MtdkChaxdkjQXGGLlO6kv4vLxaP+SdXN++G5Cic2S+2M56y3E3VP0rkwls6VbIwWWQ6hRrRPN7JBcbeIeQMnvUTv8emnLGz5jcSi+BQDr69QmNNCfEMIbcq11wmmUZ9jciisVcH31SIa4m2G2PKFnhnOCy7Et4c4Hhl8EUpohhpctuS0u1Gl51jyQXqinzxe6gtg4n3GfeZmEnNX0/6u8iaAvj2Klj1kHltlNgdDung2zuDB+HgbTaDL0wR6Xr26uBnPQdXfAWPZ4kMm4s/OPec9J3Wt6sjVOSJ9Q5LhsRCROMZ8uItdw1dx6Z+Fxqu1xZNtY6ezINZz4qsqbBB4tjuj8xqosT+6HIOPsY3hvTSdBpsEVsuSBRbWxU4tYVfd+h/kSG+O2ypcApNsaQTswSVBUKiwJKE9AMUyDluuWvoJIlNeRLRTSRC+oOzq+H4rOcM+46+xiI5Lw7l4PVSwe2UKgDo6deT2sZazpTbIJ6sc/DWVpHsCCOuF/8WvC4c5ZrH4X+LoL7W1pYZR8kZsXhsSVw8REOVbW9Yrm2ebrHUy4T/i7MrPJgIN/zW/HjvWTD/X2K/3EbhSolVcCgHb44YfJy/cK5JxTYo5S5IFLnYHv7Wv3Z78QyEhe/A6Fu0bf8QaYebXrCpWW2iqnDga5GWGtDD8tdzcoWGWqHKaQmOabs2mXqz8g5p+aagK/qyVTcqiVVwSAffkRBNTz/Rui6l1AaFPPacQWMMw6817Gfut50dxnD0R1ihzQVvLWfcnHgEiK0lpHrP7DN04jpfeqQpuPuLbVWxecaT2CUO5eAr69rXzakp3q7e+Lj6kFWeRVppGt+c+MZc5p0fVYXcExDS1zrXswTR4+CWjdBnPuTZSW/b1kjdatgPNnJRsiMs0soC1FebPx/++Eqx7T3XfGPqniKri803psTucCgHb44ZPEC4VzjZldlc+POFvLT7JarrrSCtWp4r/pjM3XDC2kSOFKqM5TkGZUx7JO8kaJxhysMGSV9LEhQnxNsKk+BPMwvJxf8OPafB1d+bb0zdDL7aDuSzJRbDIR18R2LwIBpwN02VLK+zgpa3LvvEkWfwOvy0jUrsOQ5flg0DL4EZT1jvmrFTxHbzi4ZjZ/bDd9fCkeXtG7M0EwpOmXf2DoaQki36yUqshmM5+PoKXDWuuGhcOjROmFcYGeUZhnGtIT6mC2mEWLHRtqXoNUvkUv/1byjNsrU1LWON9MizCekLftGGgrGsQ/DxdDixEn68uX0NVXQTg/BB5rMTwN1PtPxL3Wr9blQSq+FQDr4jUsFNCfcMp6zWoN9ttRm8m59BXtaR8QmDi94WRVsZe2xtzbnU1wrpY0unR7bEgIVQngeNjbD8JnFMVxW85knTxzu9G1AgdIDZTARE4VdDDST8AQf+Z96xJXaD0Q5eUZTPFEXJVRTlaJNjgYqirFMU5ZR2G2AZMwU3DbqJ92a+1+FxBgU3nw2VW6PdWsoW6DbM/kTG2kvYIBHjtsdsGl1RkKdFv44tEzEM6qvg3yNE1tTIG4T4V0h/Qy67sTTUw55PRPzdlPx3Y9EVTWUeMP/YErvAlBn858DZItSPAhtUVe0NbNC+thjdvLsxOGRwh8eZ0G1Cs9cWd/BVRSKO2mumZa9jTVzcxazSHp2DrqDMFpr7/S4QN74ibRpuj4li23uWkE2oMMHJl54Rnxl4ifntBJj+OESO7lza/5JmGO3gVVXdApy9IrMI+EK7/wVwsXnMsizKWbPo0loLVR/qKEoTW3tr8tFRuo8QDt7e2vzp4tahNshYcvWCpd8Lud6YyYaFV39tsdVPtxo3TmMj/FdbWNZUBM7chPRzPPkJidF0NAYfpqqqbpUtGwhr7URFUW5TFGWvoih78/LyOnjZjvPchOd4bIzowlNQXWDZiyX8IbbBvS17HWsTPkSk2ZXamYxwWRYoTpbpwWoMvWYKxccbfjOsuQy/VjQHSdkKiRvO3zavIh/+GWD4uZo7/t6UkH7iKUHXK1jSqTDbIquqqirQ6lROVdWPVFUdparqqJAQC7ROM5HFvReztP9SPJw9KKousuzFso+I2bstZpSWRNdAw96aR5TnCkkIjR3lELi4w8T7obEOvlos9Hxa49RasfWPhqfyxaK2pdCl7b491HLXkNiMjv4F5CiKEgGg3TqcclGgeyCF1RbOBa4u6RzZM2ejczy5x2xrx9lU5FmmwXZHaeqo66paP2/Xh2J75w7RuMOSdB8ptmqjZa8jsQkddfArgeu1+9cDKzo4ntXxdfW1fAy+uljkHXc2fLUFT1tft60dZ1OeC1521vMWwLuJg2/tht/YCLnHRf9Ya1TgegbC+HvEflGq5a8nsSqmpEkuA3YAfRVFyVAU5WbgZWC2oiingFna1w6Fr6svpTWWdvClndPBe4cI6WNLSeS2l/Jc+2tqDhDUW3SXgtZlesuyhCrlhHutZ9egxWKb/Kf1rimxCqZk0VylqmqEqqouqqpGqqr6qaqqBaqqzlRVtbeqqrNUVXW4umdfN2vM4Es6p4MHGHK5SAOts4KejzGc3iOaSju72dqSc/EOgUfTRROVyvyWG4To0iutmXEVPgQUDZSctt41JVbBjlahbIOvq2+zqlaz09ggHLyHDYpurEFALKBCcZqtLRHowkX22pBEUSBYu7C5/MZz39flpAda0cE7uYgFc5lJ0+no8g7ex9XHsjP4ykJAFVkdnRGdIzpf2p810enPzLVjIbRes8TWzefc94pSRIqnX5R1bfKPhmI5g+9sdHkH7+vqS01DDTUNFpK+rdDm/Ftb+MpahPYX0rMHv7a1JYLiNIgaKxYP7RVnVxi0ROj4vD0U3hwscuNBLHT6R1k+e+Zs/KPlDL4T0uUdvI+rmEVZLEzTnl6ajoSbDwy9Ek6uEiJbtqY4zbKVn+ai7wViW5QKJemw833xujDFNhXPflFQlgkNdda/tsRidHkH7+sqshoslkmjy5awVVWlNeg9W2x/vt22djTUiybbOlkAeyZuRvPXuhTK4nTb3KD8o0UuvL1VJUs6RJd38LoZvMXi8GVaJQdLViPamp5aZ2XrPOqiFFAbHKPvrWdg816x1SWi+KkyX4RorI3upiLDNJ2KLu/g/dxE+qLlHHw2uHga8p87IxoNDF16/upMa6DvmmWFHqzmYMknolrVxUus1ZRoZ8/WXmAFUVgFtr9JS8xKl3fwwR4iNp5XaaH4cVmWqFrsLDrwreEfpS3SsWEMV9c1yxpNts1F2ADoO1/r4LVZLLqWiNbELxI0LlI6uJPR5R18iIdIX8yttJCMTlm2UBHs7PhFAqroIWorco8L+YSW0g/tGa8QKEyGLy8Wr23h4DVOIkxTmGz9a0ssRpd38C5OLgS6B5JTaSFFxLLszik0djY6p1SScf7zLIWqQtJGiJlkm+t3hLMzrHy62caOwFhDJa2kU9DlHTxAmGeYZWbwqtqFZvDauLGtHHxNqZBMCBtom+t3hG7DDfu3bhR58rYgIBYKU+2vgYuk3Tjb2gB7INQzlOyKbPMPXFMGdRXNVQQ7Kzpt+M0vCvEqaxfqVDhwvUGvmXD3bpH9o3GynR2BsVBTIqqvvTppYV4XQ87g0Tr4ymy2ndmGas7ZS5n2ptEVZvCunmJblAoHvrL+9XWNth1VEiKkr22dOxgKrIpTbWqGxHxIB49w8CU1Jdy5/k7Wpq0138D6HPguEIMH0ZYOzK9Lo6pCJXLTS5Cxr+VzdDP4zioJYQ10N8dKhxOFlbSCdPCIGLyOxOJE8w1crl247QozeICL3gG/aKgw83rG4e/h01nw58vwx6Mtn9PZJSGsgYe/2FZZuIWlxGpIB4+Yweswq2RBV6hibYpGIxpt6GbT5uLn2wz7ucdbnmHqRd2kg283OknrqmLDsdpK2xewSdqNdPA0d/BmbcBdkgGuPo6Xl90RPIMMs2lzc+cOqC2Hry+FlX+DNwYYuklVFIiKYd1agMR0dE1pqovFtqYMXusNy2+ymUmSjiEdPM0d/JlyM4ot5Z6A0H7mG88R8AkTJffmWqyurRTbWc+Kqs9Jf4cz+2D/F0IYa8u/xPt5J7rOWoelcHIBj0BDRW3+KXFDPblKxuUdFOngMShKAhwvOE5JTUnHB1VVyDkGoQM6PpYjETEUqgrNJ1qly47RLZ72v8jwXuhA2PEu7PyPKHIattQ81+zKdBtuWMgua5I6nLHHNvZIOoR08ICiKHw852OeGf8M9Wo9p4rMkAVSli0cXdigjo/lSHQfJbZn9ppnvNO7xFYnt+zbpIx/1rNC4vaPR0SK38T7zXPNrkzkaMg9JiQnmhatpf1lO5sk7UY6eC3jIsYxOnw0AI9te4z6xvqODZhzTGwdsbKyI4QNBI0zZB8VTzE15R0bL3WbUOKMmy5ee4dCSD/oPQd6TjUUWMXNsH5xVWekz1yxXfcMJPwhtPUjR0P6TtvaJWkX0sE3IcJLpDNmV2TzV2YHZyzHfxHbsC4WonFyEZW75Tmw/S14qTu8NRhOrjZ9rA3Pw77/QmBPg/NWFLhjO1z1HTi7wcBLxPGu9nO2FN1HwIR74cj3kLRBVNn2mCDWPWQ2jcMhHXwTXJ0MGiCrU9rhkHSoKsT/Dj2nGVLPuhJeISJEtf5Z8bo4Hb692vRxtr4mtmdLPTg5i5RMgGmPwbTHYcgV7TZXchZNQ13RE6DHRGisgwwzhd0kVkM6+Fb4Lfk38qvame5Xnivi733mmdcoR8E7TMz+mqI2mD4DdPMDZw+4+P3znOMN0x7pWqmolsYrGJ7Ihmt+gsGXiibmKJCyxdaWSUxEOviz+HD2h/r9zPJ2apvrCpxs0ZnHHghopSfqC+FQfBryEtoeo7FBKERO/JusTrUFLh4iPKMoosI1bjrs+g+UWUhWW2IRpIM/iwndJvDoGFEO324Hryv17orhGTBIM0x/Ah5KhqU/GN57axC8N1o48NY4vRveHASoIi9bYntm/1PccE+ZUaupNX68FX693/LX6QJIB98Ci3svxklx4lRxO9Mlu7qDH3UjzH1RxHK9gqDPHOHk+y80nHN6d+uf3/kBlGlvrq09DUisS9ggcbNN32HZ61TkiwXeff9tWxNnx3uwbKkswjoP0sG3gIezB3H+cRwvON6+Abq6g/cIgPF3N29c0WcOXPpfw+vEda1/PvuIYT96nPntk5iOokD0eEjbbtnrZB0y7B9fAWufgqM/ikK21/vDoW/Fe9vfhjWPw8nfYdOL4lhxOjR0ML25kyEbfrRCtE80ySXt7E+ZewIUp67r4FvDyRmeyoePpsOZ/S2fU1Mu+oIG94EpD8ufoT0RNUY41I0vwIwnLHON07sBRVQuH/jq3Aran28Xjr2yQKTI1laIfP3xd8M7w2D8PTD3BcvY5oCYZQavKEqqoihHFEU5qChKp8ilCvcKJ6siq30NQJI3Q69Z4OJudrscHicXkWudeeBcvZrGBpE3rzbAgjdgyGW2sVHSMrqag72fWu4ap9aIrJ0xt53r3Cf9QytmVyAqmhe+CyOuE9o57wwT5+x4F1K2Ws4+B8OcIZrpqqoOU1V1lBnHtBkRXhFU1VeZrkvT2AjFaaJDj6RlIkcJxcKzqyO/WmLY7z7CqiZJjCCgB0x5SMgJ19eYf/yKAsg8KCZHgy81HF/0HvzjBMx6Bu7dBw+nwN+PihTZvguay1e4+cKKu2RfWS0yBt8K3bxFZ/usiizTPliaAQ21EBBjfqM6CwMXg8YFEs4qJmu68OrqZV2bJMYR3Fc8YeWdNP/YKZsBVchOBMXBsKvFU8Pwa8BX/D3iEQCegWJNAETB213aqnPvMLG4X5wu+gZIzObgVWCtoij7FEW5raUTFEW5TVGUvYqi7M3LyzPTZS2HTrbgfKmSFXUVvLjrRYp1+tkgSrpBqPJJWsbNW+jJ5Jz1R+gTJrI1brJCKp6kfegWvU+thbQd5mnPWFUM658TuvMuXtBtmDh+8ftw2edtf97dD65bIfoF9Jop1r9s0RfYDjGXg5+kquoIYD5wt6IoU84+QVXVj1RVHaWq6qiQEPtvjBzrF4uLxoW9Oa0vKXx29DOWxS/j58SfDQcLU8Q2pIvpwJtK2AAxy6qrFq/rqkQRVK9ZED3WtrZJWsc/CpzdYePz8N958F4Hf1cn/4BXesC2N8TreS+2r/l4z2kiJde3mxCiS/ijY3Z1Eszi4FVVPaPd5gI/A2PMMa4t8XTxZErkFH5N/pVGtbHFc7IrhF721jNNFnWqCkV5vewsdH7CBoqGHS+EwZonRJVrY51cu3AEmiqtqg3tT02sLoFf7hD7sVPgbwdg5A0dNo+4GSITK/dEx8dycDrs4BVF8VIUxUe3D8wBjnZ0XHtgXMQ4SmpKyKtsOaSUWymaS+/J3mMI5VQWiRih5Pw0bdyx413DfrB08HbP0u9h8cdw4ZvitTFN1qtL4a9/G1osAvz1rqgZuWEVXP+rUA01B321GlBSw94sM/gwYJuiKIeA3cDvqqp2iuejKB+hJfPxkY9bfD+jLAMPZw8A5v44l18SfxEpXNLBt01gT5ENEXXWI35wb9vYIzGeXjNhyOUGlc9yI/Rp1j8La5+EbdqbQvJmISc98BKImWhe+/yiRC/kvHjzjuuAdLjQSVXVZGCoGWyxOwaHDAYgvfTc9nN1jXVkVWSxoOcCViatBOCp7U+xqCYIxVOKYxmFZyAseh+SNwmBtqM/grtv25+T2Ad6B9/GDP70bkPufFEKNNTBL3eJZiJzXzK/XYoiQn0yRCPTJM+Hr6svo8JGUdNwbs5vRlkGDWoDo8Kap/3nlmWAf7S1THR8gnvBmFth5tNw36G2z5fYD7pU4G8ubz3vvLER/nhUCNBFjROx8azDYv1l2qPgG2EZ20L7yRk80sG3SYB7AMU1xecc35Au9M5Hh49m0+Wb9MdP1JdLBy/pGjSVcT5b/1/HqTUidXjm0xA+CApTDX12zw7PmZOQ/lCRJ4qnujDSwbeBv5t/iw7+UN4hYnxjiPSJJNgjmF1Ld6GgcMLNRTx6SiRdget/E9uvlsCml+DX+5q/v+cTMXsffLlojF5TAge+FA7Y34L9EkK1acq5xyx3DQdAOvg28Hfzp6Sm5JxUycSiRPoFGnLdPV086eEeTLyrq5zBS7oOsZNF3jnAny/Dvs8NaZOFyZC4AUZcL4TmAmPF8dzjMGBhi8OZjW4jAAUS1lj2OnaOdPBtEOAeQIPaQFltmf5YQ2MD2RXZRPpENju3t4s/Sa4ulp2ZSCT2RlMZaBCOHYReu6KBkdeL1wGxhnPGtFjwbj48A6HfAvEEUW2inlQnQjr4NvB38wdoFqY5UXiCerVen0apI0pVOOPsTIOn/VfqSiRmw827+ev3RsPpPXD4B5FOqdOR0S3K9rvQOm0Yx98D9dWQtKntczsp0sG3QYC70CMvqjZ0l3lpl0jtGhfRvBlFVG0N9YpCbnU7m3VLJJ2FT2eJePuAiw3HXD3h/qNw2RfWsSFylNC2Se268sHSwbdBiIeYjedUGoo5siqyGBQ0SK84qSOyQjwKni47bT0DJRJ7YMT15x7TuBiqSnX4R4l4vDVwcoEe47u0Prx08G2gi7PrnHZ1fTV5VXlMiTpHT42oUnETyCjPsJ6BEok9sPAdeKYYrlsJC14XxyY/YFOTAKFxk38SyrIhYW2XC9fIln1t4OXiRZB7kN7BZ1YIzZlI7+YLrNTXEFaag3NQDzmDl3RNFAV6ThX/+l1oqHS1Jb1mw7qn4fUmGkfPFBv05Ds5cgZvBNG+0Xq5gjNlZwDOyaChshBnoJurHxllcgYv6eL4hNuHEw0bAN7hzY8lbRDy1F0A6eCNIMonivQy4eB123Nm8JWiYq6bW9B5m4RIJBIrc8VXMONJePAUuHqLoqyPZ4gewJ0c6eCNINonmtzKXCrrKtmUvolA90CCPc5K86oqBCDYI4iC6q5dHi2R2BVRo0UvWe9QWKSVps49LsI2jS33eugsSAdvBNG+ojL1s6OfsSt7F7N7zEY5+/GzQqRGBnuGUVBVgCqb/kok9sfAS+AWrW5ORR4su7JTN+iWDt4IBgYNBODDwx8C8MjoR849SauJHewXRXWDyLSRSCR2SOQoeFSbCHFqzbn6OZ0I6eCNQDeDBxF7d3FyOfek0kxwcmNSj9kAbErvWulYEvOwNWMrXx3/ihMFUsvcorj7ii5STm6w/ws4vtJ8Y9fXQmWh+cbrANLBG8mDox4EWsie0VGQBL4R9PSPw8vFi8TiRCtaJ3Ekrl99Pa/vFbnia1LX8M2JbwDYlbWLuzbcxSt7XuHy3y5nfdp6W5rZ+YmdAg/ECwmFFXdDbUXHx6wqgs/mwhsDIGNfx8frINLBG8mg4EEAXNnvynPfrC4Vj3p95qEoCnF+caSUpFjZQomjsD93P58f+xyAB/98kJd2v4Sqqvye/Huz8/bm7LWBdV0Mz0C4+AOoKYVjv4hjxelQmsmZ4lQO5ZnYhGb9c5C5H+qr4Pe/m91cU5EO3khGho1k3zX7mBk989w3U7eKTvPaRtKxfrEklSRZ2UKJI1BZV6nfn/DNBP3+3zf/nZ8Tf2Z2j9l8d+F3gAjzFVQV0NAF0vlsSvR4CO4DW1+D/y6AtwajvtGfpb8s5JpV13C84Lhx49TXwLGfYMiVMPt5yDokbhY6CpLgw6mQtsMy/48WkA7eBFydXFt+I/lPIWoUOQaAGL8Y8qvym/0xSyQABVWGFNqyOoMEta5D2C2Db2FA0ACu7HslmRWZTPt+GsO+HMaxgq7duMKiKIpwyCVnIGMPAMdcXSlURHbNfevvpmL3R/DjLeS8PZhftzzHBwc/IK00jVvW3MJXx78S4xz9UUgTD7kMBiwSxz6aZsi3zz4CWQfB2c1q/zUpVWAOCpNFb1FncQMIdA8EhMSwp4unLS2T2BmrU1cD8Nncz/By8eKBzQ/otYu2XrEVf3d/AB4d8yiltaWsSlkFwPM7nufbC7+1ic1dgr7z4JFUUBs5dXQZVx19BydV5Ylh9/LPQ++ydsuzOKsqj4cGQ8pyAN4/9D4Au7J3MaH7BHpu+Rf4RkLsNIOgWmUBvBIDHv4QNkjo44f0O/f6FkLO4DtK3klIXCcez7ToNOSLaopa+ZCkq/Lfo6I5xpCQIQwIGsDqJavpE9AHfzd/vXMHcNI48cqUVxgdPhoAH1cfW5jbtXD1BDdvNjiLGffbOXks2fg2/WpqeTokiMdDg+nmFsDtRSV8HjqL+bHz9R89lrVXTPRG3Whw7jdrF8lrSkWo5uQqUBvFdayEdPAdoaEe/nxV7IcYxIx0GvIlXbiTjAQO5x1m3o/zyK7I5lj+MfKr8imvK+fGQTfi5mR4TF+2YBnrLl3X4hivTH4Ffzd/ahpqWnxfYl7SS9P56PBHDAkewtSA/mhKz/B/ReXMiJrOorhFvDPnY+4JHsPIE2t5ddLLHLj2AB7OHjy+63kKNRoIH2IYLGo03LYZYqdC+GBxzIqzd5AhGuPRVbspishzLTglFkwa60R3+EXv60/1c/MD5Ay+K5NXmcfVq64G4NrV15Jdka1PtZ3cfXKzc1td2wFCPENYGLeQb+O/pa6hruUaDInZWPDzAgAeH/s45CbB99fSN24ub894x3DS0Cvhx5sh/S+cYyZx7/B7eXXPq6zx8uSq8EHNB+w2HK7X5tjnJ4r8eysiHfz5KMuBj6bCqJvE4smOdyGot3DuTRl/d7O2ZQFuYgbftM2fpGuxK3uXfj+7IhuA1/a+BkD/wP4mjTUgaAC1jbW8se8NHhnTQhW1xCw07drWP6g/BA+EBxLA5yzZ474XgKsPbHkNoidwTdQcPtjzGok+geAT0foFgntZyPLWkSGa85F1EMqyYNMLwrlDc+d+1bdwzz7o37xDvK+rLwpKsy+MpGUa1cZO+XM6Xx2Et6t3q++1RIxvDABfnfiK3MrcjphlMbLKs3hx14vcu+Fetp/Zbmtz2sWOTJG++M0F36BRtK7xbOcOIoY++1lI3gT/DEB5vQ99qir53g22Z/5lPYONQDr481F4nmKlJ3Oh73xxVz5LeMxJ44Sfm5+cwbdBdX01s5fPZtr306hrqLO1OWYlpSSFHr499LH25Rct566hd/HomEdNHqtPYB+GhQwDYFn8MnOa2W5yK3NpVIUSo6qqPPDnAyyLX8bmjM3csf4ONqZvtLGFxlHXaPjebc/cjr+bPwOCBrT9wVE369OiASb5xAJwx/o77KofhHTw56Mwufnrp7UzTf8ebeay+rv5d1kH/0PCD7yw84Vmx8pry88571DeIb2jOF3eubpgJRYnEusXy6rFq1h58Ur6BvblzmF3cnX/q00ey0XjwidzPwHgkyOfUNtQa25zTSKvMo+ZP8zk+Z3Po6oqB3IPcCT/CENChtDduzsA9226z26fNnSsTV3LjO9n8PjWx6mur2b7me2MjxiPk8ap7Q8rClz9PVz8H3gqn+uv+p3Xpwr5ieUJyy1sufGYxcErijJPUZSTiqIkKopi+hTFXilKgZD+ou3XhW+CRgOPpsPtf7b5UX83f4qriy1vox3yzx3/5NuT37IuTWSGnCg4wfhl43ll9yvNzjuSf0S/n1qSak0TLcqpolOklKQwJnwMoZ6hxPrFdnjMplk3ySXJ5znT8vyQ8AMgHNmQ/w3h+j9Ew+0PZn3A8ouWszBOhCyb/n7tjbLaMh7Z8gjFNcX8mvwro78eTUF1ARO7TzR+EI8AGHYVOLngonFhTswcpkdN5+fEn+3mibTDDl5RFCfgPWA+MAC4SlEUI55xHIDCFAjuDdcsFwutAO5+4hfbBv7uXXcGr1tk/r+d/0ddQx0Hcg8AIobc9JH4cN5hgtyDAEgtTbW6nZbiaP5RAKZEntuYvSP8cJFwrFsztpp1XFP5Lfk3xoSPwcPZQ38s0jsSX1dfvF29eWrcU/i4+nD/pvsprS1t9tm8yjy7SPm8Z8M91Kv1XNXvqmbHJ3Sb0MonjOPSPpdSWF3YbJHdlphjBj8GSFRVNVlV1VrgW2CRGca1HMYI/KsqlJyGgB7tuoS/mz9FNUU8v+N5pn43tV1jOBq1DbUsi19GUU0Ro8JGUVhdyEdHPuKl3S/pz0kqTiK7Ipu6xjoO5x1mQrcJBLkHdYoZfE1DDaqqklCUgIezx7ltHTtIv8B+9PLvZboAlhnJq8zjdNlppkZO5ZdFv/B/E/+PWwbfwpPjntSf4+7srk8JfffAu/rjlXWVLPh5AZeuvNRmDXFUVWV1ymr25+4H4KHRD/HE2Cf074d4hnRo/JFhI1FQOJJnH08v5kiT7A40DaBmAGPPPklRlNuA2wCio6PPftt61FXD++Ogz1yY/0rr55XnQn21iLe3gwC3AIqri/k+4XtALEqFeoa2ayx7J6EogTi/OF7f+zrfxAvp28fHPs7ilYv5z6H/APDQqId4c/+bfHLkE9akrqF/YH8KqgsYEjKEzIpMh5/Bp5emc9EvF/Hs+Gc5VXyKOL8442K5JhLjG8P69PVU11fj7uxu9vHbQqeJMzhkMN28u7GoV8tzucW9F7M1YytrU9eSVZFFcXUxB/MOAuJpbduZbUyOnNziZy3JsYJjPLzlYQDenPYmLhoXrux3JdOippnlpuPl4sXg4MGsSV3DHUPvOLfzm5Wx2iKrqqofqao6SlXVUSEhHbtLdoj8kyK2vus/zZXezkb3nn/7bkb+7v7UNhoWw+b/OJ89qYVU13UeZcDcylzm/TiPJSuX8LdNf9M79+lR0+kd0FuvyTMgaADXDbyOoSFDWZO6BoAThaKhxejw0cT4xpBckqzPynBENqZvpFFt5Om/nmZX1i76BPaxyHV0zWf2ZO+xyPhtcTT/KBpFQ9+Avm2ee2mfSymoLmDz6c16565j6xnLh5myyrO46OeLmPnDTLLKswA4mCvs8HH1YVL3Sfpzw73CifA+Tw67CVza51KSSpL4x+Z/2HxB3BwO/gwQ1eR1pPaY/VFRYJAWANj1YevnFqeJbTsdvC4OraO2sZYrv/wfd3zjmDnCZ7MhfQMzf5jJmXLxq96SsQWA92a+xzvaqr8QD3Ej1y0yhnuFNxtDQSHaN5pR4aMoqSmx60W5ttAJhumI9e34wmpLXNrnUgDyq/ItMv75UFWVPzP+pG9AX6NE9CZ2n3hO1tD+a/YzJnyM3tG2lz3Ze0goSjjvOTeuuZHU0lRyK3OZ8+McBn8xmFf2vEIv/15su3KbxZ6ALoy7kIVxC1mfvt7m6yXmcPB7gN6KosQqiuIKXAmYsf+VmVBVeHckxP8Gw6+BmMmQvrP183UzeL+o1s85Dzq5gqZ4Rn/KrorX+eNodrvGtCde3v0yIJQz35j2BhO7T6R/YH/GdxuvP0c3I9I5O19XUaYd4SWOe7p44qJxYUy4yCfWLU46GrmVuWw7s40BQQN4ZfIrzIyeycweLfQNMAO6RemC6oI2zjQ/L+x6gfjCeC7ve7nRn3l0zKPsvWYv/5ryL3Yt3YWLkwtDQ4aSUJRAVX1Vu225ac1NLFm5hAf/fJC6xjr2ZO/h+tXX6xd1Gxob9JOPz+d93vz/MekFQyGTBXDRuPDshGfxcfVhc8Zmi13HGDocg1dVtV5RlHuANYAT8JmqqvYnXp25X7TT8ouCeS/Dmsfh5OrWzy9OB8+gZhIEpqDLMKivjKG+dDDu4b8C4OyVzD9+3MKUPovZlVLIgbQiZvYPY2iUf7uuYyvKaoWW+dJ+S5ndYzaztb1om3JF3ytILUnVv3fbkNsorS1lROgInt/5vD71L8QjBD83P17e/TKjwkbRN7Dtx397oVFtZOYPwpmPixjHBT0v4IKeF1jsep4unng6e5JXad2m7sklySxPWE6oRyiL4kzLoXBzcmNe7Dz964FBA2lQG0gqTtJ3SjMF3XcPRMvDfoH9eHv/2wBc8esVLOmzRN8d66lxTzEybCSHrzvMobxDBHsEt95204y4aFyY1H0SWzK20NDYYJH1GGMwy21MVdVVqqr2UVU1TlXVF9r+RMfZeiqP45mlbZ+oY9/n4OoNt28BNx+xeFqRB7WtNOUoTm93eAbEavr08MuozriGdxfdwNyYubw6RYSHGvzWMeDpNdz43z28szGRRe9tZ2ey9Wdk7aWkpoTKukpuHHQjtw65tdXzJnWfxK+X/EpP/54ABHsE8/Lkl1nUaxEL4xby0mSRXaMoij6kdc/Geyz/HzAjaaVp+n1TNWbaS9/AvhZ72lFVlWXxy7ht7W3N8u23ZWyjQW3g83mfd1jwTHcDb+86gk5S4I6hdwDonTuIUNnb+9/W90TWyTwoisKw0GFWce465vSYQ2F1IXesv4MHNj9gk85cDlnJWlJZx7Wf7mbJB0bqPpRmwv7/Qcwk0YMRRKNdgJWtOJQOOnhXJ1d6Ol0Jjd5Miu3Ja1NfY37sfCZ1n0xYiCFEMyZW2HPlRzs5eqZteeHDeYdZnrDcZmlmIP4wVVSmRU5r16Oum5MbL0x6oVnO8UVxot2hu5P1M0M6gs7R+rj4NJulWpIRoSM4XnDcIh3Dlp9azou7XmRH1g6+i/9Of/xE4QnCPMOI8m1fyLIpkT6R9Avs166F1rTSNB748wEAFsQu0B9/dvyzrLt0HS9PfpneAb15c9qbfHPBN3o9fVswM3omF/W8iJ1ZO1mbtvacdRpr4JAOPiFXPKJV1TWQXVJNRU09l7y/nQve3kpaQQud0eO1zYyHLTUc8+0mtkd/hMazsjd0OfAmOvj6hkZWHDzDscwSPtmazPubkogL8cbLzRAJi/WLoZocDj41m3V/n8L3t4/n1skiRr183/m/AL8m/crVq67muR3PseTXJZTUlKCqKh8c+oBTRafO+1lzsj93P25ObgwOHmy2MW8ZfAvzY+aTWprKm/veNNu4luZI/hE8nD3YeuXWFtddLMHw0OHUq/X6TCRzsil9k37/r8y/9BOJtNI0s1Tk6oj1iyWzPLPd9oV4hBDpE8nWK7ay/5r9LOmzhHCvcBb0XMBPC39iVo9ZDA4ZbNM0RUVReG7Cc/qbzKdHPrW6DY7p4HMMMbhtifm8vjaBA+nFHM8qZd5bW6lvOMthp/wJftHNVR9DmxTblp6V9KPLgfcz3sH/b0cqvZ5YzX3fHmTBO9v4v99PUNvQSP+I5vrPMb4xVNVXUUMRvcNEl54nFgxgSp8QtiWePzPit+Tf9Punik4x6dtJnCo+xfsH32fxysVWm9UfyDnAwKCBZtUm1yga/Sz+s6OfdWgBzhqU15bz4aEP+fP0nwwMGmjVGGvvgN4AxBfGm3VcVVWJL4xnQc8FPDXuKVJLU0kpTUFVVVJLUunh276akJbo5tWNnIoco+U8CqoKOFV0ivcPvU+oZygbL9+Is8YZf3d/u9bId3Fy4f2Z7xPlE8WKpBVWz35ySAd/KqccDxcnogI9+GZXGvvThQjYFaOiqKpr4OL3t3Ptp7uoqKkXDW9TtkLPKc1VHz384QbR75Ltbze/QJnImdXP8o1g5UExG5nYK6jZ8YuGNM+t1eUx/5DwAxf/cjGPbBH63pN7BZOYW87pwpYfuyvrKtmTvYf+gf35eM7H+uNLVi7R7ycVJxltb3s5ln+MowVHGddtnNnHnhw5mftH3A/Avpx9Zh/fXDy9/WnGLxvPuwffJbMi06xPMsYQ7hVOoHsgr+99nZyKHLONuzZtLXlVeYyPGM/QkKEALFmxhMyKTMrqyvTxbHMwN2YuiqLw4JYH25Qu2JKxhWnfT2PxysVU1VcxMnSk2eywBu7O7rw1/S0a1Uarq2w6pINPyCmjT7gP14+PYX96MQdPF3PDhBhu0YY6jp4pZeupfPamFYlO5tXFom3W2USOEts9H0NloeF4mTZG7hN+7mda4HRhJXvTirhqTBRf3zKO5Bcv4NDTc9j9+EzmDGw+Rp8AUQDz4eEPSSpJYlXKKirrKpk3SJw3+dVN3PLFnnMKonZk7aCusY4HRz3IuIhxbLzs3C+KrsrQkjP5zRmbUVBY2m9p2ye3g6X9l+KsONu1g/858edmr9uTCdIRNIqGR0Y/Ql1jHSeLTppt3LWpa/Fz82Ne7Dx6+fciwiuCerWeeT+KtYU4/zizXat/UH+eGPsEu7J28V38d5TUlPDl8S+pb6w/59x39hu6KXX37s6zE541mx3Word/b3r49mB1ymqrrp85qIMvp0+oN9P6Gipih0X5ExlgKL5QFDiYXgynd4sD0eM5h6aSv4ea6GyXm+bgt5wSKWtT+wh7NBoFP08XQn3PXTAMdA9kUFBzh7AvZx9RgZ4sHCqeGNafyOXN9Qk0NBq+CEfzj+KkOLH/lB/70opwwY/7RtzHVf2u4seFP+Lp7MnxguPszd7LrOWz2JqxlYq6FtYjOkBtQy0/JfzE6PDRLcabGxpV6hoa2ZdWxPrj7ZtZejh70NO/J8cLjnfUXIugq7bVKBrCPEUzCF0evzUZGyHUQF7b+9o5DqO6vpqSGtP7AZ8pP8PAoIG4ObnhpHHil0W/6IvVfFx8GBlm3pnzkj5LGBk2kk+OfMINf9zAq3teZWdW89qUqvoq0svSmR8zn33X7GP14tVGFVnZG4qicGHPC9mbs5c1aWusdl2Ha9lXWFFLfnkNfcN96BXqw/2zenM8s5R5g8Jxd3HirmlxTOkTwtMrjrI3rRD8doFPN/BrJT1q6ffwzeWQ28Sh6GbwXsZpxyTmluPp6sScAcbdEN6e8TYv736Z8tpyEooS+DnxZyZHTualxYO5YnQUn21L4cM/kykor+W1y8Sj8l/px6itDuLlVYlAImG+bqy4+xrC/dw5klGCS30M38R/o5cLuGvDXYBQIOwX2LFGv7mVuVy68lJm95hNblUuz054lo+2JHGmqIr7Z/XhsZ+OkFdeQ0J2GWU1hhlYyksXtGuRa2zEWJbFL6OkpsRqC5fGonOcD416iJnRM8muzMbf3d/qduhkIFJKUkgpSdGnooJQ8VyRtIItV2zRN4Cva2jExen887kz5WeaNbvwdPHkx4U/olE0uDq5nrd3bHt5ePTDXPHbFfr+xZ8c+UQvIZBcnMzmjM1U1Vcxs8dMi1zfFPamFvLm+gTcnJ3w93Bh3qBwZvQLxfmsn+vhjGI2xudyyfDu9Ajy0h+/dfCthHqGMit6ltVsdjgHr1tg1S1Q3j+ruebHw/OEM5veL5RPtqZQG7gT1x5jz+m6pKf3HLE98BUcWS4EyJI2gmcwOBv3hUrMLScuxBuNxjhnFuoZyhvT3gDgmb+eYV3qOuob6/Fyc2Zir2CiAjzZEJ/L8n0Z9Ar15khGCUcrT9JYI25Srs4aCitqmfbaJq4YFcUXO9LQuM/EMyYeRWm+wPzvA//mvZnvGWVXU8pqy1gWv4zsimx+OvUTDWoD3yd8j4ezB2PCx3Dtu+sB+GKHIQ+8Z4gXkc6enMgS9Qlrj+cwd6BxN72mTI+azpfHv2RZ/DJ9rrM9UF1fzdwf5wIQ7BlMhHeE2fRLTEVRFP4x8h+8se8NMisy9Q5eVVVWJK0AYPuZnYQ7D+XjLZmsOZbDlD4hvLJkMDuTC5jRLww/D8PiZEVdBcU1xXT37k5tfSOuzsJp6W4QlmJA0ABuHnQznx79lAndJvBX5l/M/3E+g0MGszpFFCIGuAW0WEhnbX45eIY9KUX0Cffm0OlifjpwhlAfN15aPBg3Zyc+3prM0Ch/Np/M5XBGCW9vOMWDc/py86RYXJw0OGmcWNx7sVVtdjgHn5wnwg5xIV7nPe/2KXFs238U1/IMktyvp6eqtjybVBTQuEBjncic+fU+cTyot9E2JeaWM65nUNsntsDEbhP56dRPLP19Kd9d+B2KohAd5MnJ/5vHNZ/s4uXV8aDU4tOvkKsHLubvt89Do4G/Egu48fM9fLEjDTdnDUPDB7M7/nlAg5d7NTfP1nCifC07MndQ21Br8uznj9Q/+PeBfwMi71pRFA7lHuLimBvo++R6/Xmuzho+v3E0QyL98damg+aWVjPmxQ2sa6eDHxw8mG5e3Xj/4PssiF3Qau51XWMdnx35jKX9l+Lj6mPydUzlZNFJfXZPDx/zZZS0l/mx83lj3xtkVWTpjzUtvHpsm1BNrEy9DejJloQ8xr8k1m4mxAXxza2GhXJdm7mfdlfx/Ner6Rvmw3e3j8Pf0/Kz5r+N+BsL4xbSw7cH3578lrf3v6137gDPTHjGotICbfHiqhNsPZXPiaxShkf78/NdE6lvaGRjfC4vrjrBzV/s1Z/7Z4II1z40ty87kwv415qT/GvNSS4e1o23rhxuddsdzsGnFlTg6qyhm5/Hec8L9HLl+Wm+sA6e31HH5u0iY+aS4d15duHAZrMXLnwDVt4r9sffIxpsm7DAmlVSzZDI9oUSdNkoJwpPcDT/KINDREaGm7MTT104gFu+2EtgQBlngBERffFwFel40/uFsvq+ybg6awjwdCXQy5WU/Ap+P5zJ17vSeefXapy8e+EZtZ0dmTuYGmWaJv3B3IMoKGy4bINeI7umvp4bPtsLFNA3zIf/3TwGD1cnfN2bp6mF+rozd2AYy/dlcMvkWPqF+7ZwhdZxd3bnkzmfcMHPF/BT4k/cN+K+Fs/7I+UP3j34LuV15Tww6gGTrtEemragM2fKYHsJ8QjBSXEiszyT8pp6vN2ceeeAWJBUG9xQnER2ypihJ/hq4T28tOoEn21PISbYi7+SCkjMLSM22JszRVV8e1w41PRsP5w1CidzyrjnmwPcPCmWospa9qcX8dSFA3BzNn86qEbR6J9Aru5/NVf0vYKPDn9ETmUOT4x9wmahmYZGlU3xuXy0RVT09gzx4uZJIpHD2UnDnIHhZBRV8c/fjjO5dzCPzOvHr4cyCfJ25dbJPbltSk8+/DOJ19YmsP5ELmprk0wL4nAOPiW/gh6BnkaFQ0YEVAOQoxoeM38+cAZ3Fw0vLR5iOFEXa48aB3P+DwJ7iobaRrBWu5ioW2A1FV9XX96d8S73bLyH/bn79Q4eYEikP7ufmMW6tHX8Y7MhxVLH2Tn2scFe3DOjN7X1jbyzMZGG8j6o9T7cu/FvzPR8n0fnjiSshYXfs8ksz+T35N+5KO4iQjxDaGxU+fVwJt/tOc2O5AIuHxXJq5cOPe8Yt0zuyZpjOfy4L4MnFpje4CvKN4rR4aPZmbmzmYNfnrCcseFjifKNIqdS/OxbyrywBCcKRGHRp3M+tYuFPieNE2GeYaw8epy3f1jDAwv8WZe2Dr/6ieRljGPw4B1EBXiyP3c/GgWevHAAT144gJzSaia8vJFZb2zRj+XV63tQg7ht7Fjunt6LCS9vZFtifrPajJggL26Z3LMlU8yKs8aZu4bdZfHrnI+9qYVc/uEOGlUxWfzr0Rm4u5x7c7t2fA8GdvNlTGwgiqIwqLthoufipHDPjN74erjw9Ipj5JTWEO5n3Upth8uiSc2vICb4/OEZPdrF0lVPXMa7Sw2PR1tP5dPYqJKQU8a7G0+h9hgPI2+Ahf8WIZvRNxuVA59eUMnzvx0nNtiLniHtEyUDmBo1lSD3oFZ7bZ4sFKlw0T7GFV7dNb0X7y4dzp8PzUStDUOlkTWFzzH2xQ3MfH0zMY/+zs2f70FVVUoq6yisqKWhUSW3tJp7l+3kxlV34+rkqv8jW3s8m/u+PchfSQXcNqUnL17Sdt736JhAhkX5cyjD9GwOHXF+cfpCG4Ccihye2/EcV68SErTZFeL3q2L5tLP9Ofv5+MjHjAgdwZgI62fNtEZ9rR9ZFRk0qirvHhIVwJlpY3lyzjSWL/6QsRFjKawuJLPCUDUa5uvOW1cM078e2N0VjUsZIwPnceuUnjg7afj9b5O5YUIMw6L8GRLpR2ywF8v3ZfDYT4dZtvs8fRQ6CR9vTaZRhdExAfz7quEtOncAFycNY3sGnXdmHh0oJgOni8wvLdEWDjWDb2xUSSusZHo/IzsjlWWBxgXFM4gLh2i45xvRGzSjqIoT2aVc+sEOquoauHZcDH4Xvd3GYOey7oSYQd4xteOzmli/WFJKUs45vjVjKx8eFrr13q7G3UTcXZy4cIi4Qd0/6g7eOf4gTu5ZgEqSdg1jQ3wuk1/dREaRiCkHeLpQVF2Oi+8B3CMSeWv6WxxJdeLpvXvYEJ+Lk0bh4+tGMqNfmNH/p6GRfvywL4OGRhUnIxegmzIkZAjfnvyWX5N/5aKeF/FXptAe0mVc6ASlmoZOLIWusbSvm2nhJkvy+fYUMrJDcAlI4IWlzrx8QEwELhk0lKVjRQhJ90R4JO8I3b276z970dBuXDgkgiP5R/Q3zNvHTcbTVbiEEB83nl04sNm1nv31OPHZZSzbfZq+4T6MiLbsAqytKK+pZ2N8LrdMiuXJCzveXlrn4NMLKhkdE9jh8UzBoWbwWaXV1NY3EhNkwgzeJxw04r9557Q4wrUhivisMqq0xUS5ZdXtsudAehHd/T24YnTHWxC25uB3ZYnmvfNjjQsZnc2to+fy7PhnAVj38EBW3zeZPU+INC2dcwcoqqzDK/Zt3CN+oaE6jJd/dOLeZfvZEJ9Ld38PVtw90STnDiLEVFnbwLiXNrAjyXS1TF263BPbnmB75nZ9NyjdMV0xVF5lHi/uelHfdMTcNNX5aSpwZUuKKmp59tfjNFRFoWga+CtPyFGPcX+clxYP099Q+wT0wc3J7Zw+rjuzdvLAnw/onfuwkGHnbTh9w8RYtjw0nfeWjiDY2403152/2Yaj8tXONB7/6Qh1DSoz+5v2fW+N7gEeKAqkt1KlbkkcysGn5ovZZ0ywkfHPsqxmi6WPzOvH1kem4+qk4eDpYv3x3LL2dXk/llnK4O7mydOO9YuluKZYX+Dz6ZFP2Xx6M9mV2YR6huqlhtuDrtLyVPEJ+kf4EuLjxifXjeL5RQMZHRPAj3eO5+DTs9G4imreqozrOZVTQaCXK1sfns6GB6Y2iy0ay9Ao8Zm8shqu+ninyRV8TVP07lx/J9sztzMqTFQfr0wy9JQ5mHeQZfHLuHvD3SbbeD62ndlGcnGyXp724dEPW00xsi2OaJVHn54rtOi3ZGxhYNBAPr3iKn2KIwhd8lFho1iRtIK6hjpACHbduvZW1qWtAyDUI5QPZ3/Y5gJgdJAnC4ZEsGRkd3YmF1BZa521D2vR2Kjy5C9HWXkoE283Z0b2MM8TipuzExG+7tLBt0WK1sHHmhKDPysbxsVJQ1yoNz/sM/QJz2hHbKykqo6U/AoGtzN75mzmx85HQeG/R/9LZnkmb+1/i3s33suGtA2MCB3RobHj/ONwd3LXd5IHmDUgjGvHx/DDHRMY2SMQb3fxVbhj6B1sum8xzy8ayNaHZxAV6Nlq/LEtegY3DyntTSsyeYzXp77e7PXUyKk8N+E5/euO/mxaQ1VV7lx/J4tWLOJfe/8FwJX9rrTItdqDzsEv6G+oim6t0vTCuAspqy0jpTSFEwUn+Numv+nf83D24JsF35i0aDwhLpi6BpUxL2xg/ttbScorb+f/wr5I1SrRujpreP/qEc1ulB1lUHc/fj5whk3xlg8nNsWhHHxqfgXuLhrCfIxciS7LAp9zC1F6BntRXWcoCIrPLjvnnLZYeUgsWrU3//1sgj2CifOP44/UP/TFNAD1aj0Tu0/s0NjOGmfGRIzh+5PfN5ODbYquQjPALYCYYC+uHR/T4S+4RqNw9dhoZg8Qj7qJuaY7gjkxc5q9DvUMZXHvxXw4+0OmRU5rJrxmTnQZOk1x0ZiuWlhUUcu3u9OpO1vhtINsPplLz2Avgrw89JXK06KmtXiurjr1hZ0v8NWJrwBRiXtRz4tYtXgVYV6mhSJGx4iZbXlNPSeySln07nYWvbutmcqrI3IooxiAlfdMZEo7s+JaY5b2b+DGz/ew+khWG2ebD4daZB3XMwg/DxfjKkZrK6G6pMV89gAv8YcaG+yFl5uTfuHRFA6fLibEx81sj3EghJR0C4cAo8NHU9tQy9yYuef5lHG8PPllrl11LY9ve5yLe11MVkUWb01/S/++rhlBkId5blg6XrhkMHUNjfR5cjXZJe1b63hv5nv68Euop1hgn9BtQosx47rGunY54rNJLm45o8lUnll5jJWHMqlraOTa8TFmGXNXcgF7Uot45iLhuP815V8U1RQxPLTlQpqefj3pG9CX/bn72Z+7n36B/bhu4HXtvr6nqzMz+oWyLTGfFXdP5OHlhzmUUcKF/97GCxcPIiW/glAfN64e16NNeQR74tDpEjxdnegdav6iuXmDwtl6Kh9VVY1PEjEDDuXgZw0I098J26RE2zzDt/s5b/1jdl8GRPhx2ahI7v/2IMcyTU/lO5VbTq8OpEa2hK545vYht5Nflc8z458xW2GEj6sPl/S+hNf2vqafxZXXluszc1anrMZF48K4CPPLALs4aQj2diOzuH0a71Mip3DfiPtYmbSSISFDznn/2wu/5f92/B9HC45SVlum12lpLyU1Jdy+/nYAFsUtYkXSimYaLcZyJKNE/6S3I7mAJSMj9VkqHeHrXekEeLpwpXZxP8YvhhhizvuZ92e9r+8dOzO64w3B31s6AieNgquzhhV3T+TJFUf5Zlc6Dy0/rD+nqLKOv8/uc55R7IvDGcUM6ubXroyvtvB1d+HfV8lKVvNRqNVGD+p1zluBXq4sHSv+OKKDPFlzLNukVL66hkZOZJVy7TjzVjPeNewupkRO0SsFmpuFcQv5JfEX/VNCQlECI8JGUNdYx6rkVUyLmmYxca9+4T4cM6WH7lncMvgWbhl8S4vvDQwayNL+S3l82+OU1pR22MEfyzf0jH9+4vNcO+DaZimGZ/NXYj65ZTVcPNxwzuojWdz59X7cXTQEebmx6kg2Z4qrWXG3ceE2VVX5MyGPb3efZnCkH5EBHmyKz6W8poHNJ3O5aGg3fVWzMYR6hnLk+iNklWcR7mW6fMTZNL22RqPwzEUDOHS6mABPV26ZHMsnW1P4YHMS143vQZC323lGsg9UVeVUTnmz32FnwLEdvKpCfoLQfB+4WJ8OCUCBNtQReP4c9R6BntQ3qmQWVxEVaNxC08nsMmrqGxka5d9Ow1vGy8XLYs4dRFbKz4t+Jrcyl5k/zOShPx9iYa+F7M/ZT1FNkUUFnQZ39+OjLclGqRq2B51TL6wuJMYvpkNj5VUJPZHXp76Ooij6JtEtsepIFnd9LRavh0f7U9egUlhRy6M/HQHg+9vH46RRWPDONg6dLqaxUTUqxLjlVD43/Fc0pf7jWPY57181pn2puZYSR3NzduL3v03Wvw70cmXhu9vZfDKPJSOt1+i6veSW1VBWU0+vUPM+ldsax3XwqgpfXgzJm8VrF0/od4Hh/YIk8AgwNNluheggbRFCYaXRDl6XYjnMzA7eWoR4hNDDtwdppWl8cuQT/fFe/uc+7ZiLPmE+1DeqpBVU0MsCMU6dNvvNX62nt3cN7141vEU9fmPILM9EQWlTv6exUeW5Xw2z/an/2qzfd3PWsO7vU/Sqpy9eMpjHfz5CZkmVvm9Bcl45+eW11Dc0MqFXcLOxt2l7DLx5xVAOnS4hMsCD0up63tkgcvLNlZ5rKQZ18yPY25WHlh8ir7yGmf1C9T8Le0SXANDZHLzjrICcTWGywbnrXjd7PwkC2+5Ao0u5TM43fqH10OligrxciQw4v+CZvaIoCt9f+D0KzWeSlhTQ0v3hnMqxTEqdLhOkvCGf3Sl5fLglsY1PtMyb6xJYdfIg3b274+bUemihsVHliV+OklNawytLmks3LBzajf9cO7KZQ+uu/a5kaRea/0rMZ+Ybf3L5hztY+skuiipqm42xO7WI0TEBXDI8kmcXDuSWyT35x+w+fH7jaG6f0tOk8Iwt0GgUpvUNpVGFl1fHM/vNLfx+2HrZI6YiHby9kadtOHzLBnB2N3RhAqivgZQtENS2gw/zccfDxYkkE1L4Dp4uZmiUv007tncUTxdPfRm7RtHw7ox3LaraFxfijaKIxWlLsCW+nMbaQJy9TuHZ822+L7iKpb8vbVaFagxvbzhFUnFyswYaLfHr4UyW7U4nNtiLGf3CuGxkJBF+7iy7dRzvXDWc6X2bZ0p09xdPEy+vjqexUeXr3ek0rfu6+P3trD2WTXVdA//dnsKh08UtlrVP6xvKYxf0N+n/ZCuevmgAT184gJnarJG7v9nf7qpxgNr6Rv7563GL5JIn5pbj4+ZMqI/9rxeYguM7+OA+IhWy5IzhPZ2me2tdnJqg0SiMjg1ko5FfmrLqOhLzyh02PNMUXUjm49kfmywnbCoerk5EBnhYzMH/588kXKqH4eydiJOb+F0eyT/CH6l/mDiSisalkO7e5//ufLUzjR5Bnmz4x1RCfNz412VD+evRGYyPaznNtGewN+N6BrIvrYivd6ez5WQei0d0J/XlBXx+42g8XJy47ct99HvqD577VVQzj461rm6JufF1d+GmSbHN/h/bm6hTmsr/dqTy2fYUbvx8D1W1DW1/wEhUVWV3SiG9w7wdetLWEo7p4FUVdn4gUiDdfSF0AGRr07Ma6uH4SkCBMbcbNdyEuCDSCyspqaxr89wjZ0pQVcy+wGoLHhz1IE+MfYLR4aOtcr3eoT6cskAxTG19I8ezSpne49wMleP5J4waQ1VVNp3MBadKFKdavDWt5yrHZ5eyJ7WIq8dGN1swPZ9z0GgU/nfTWEJ83Hjql6PUNDRy7wzRVGZa31C+uXWcvqdAzxAvrhkXzeSz4vKOytVjo7l5UizOGoVdyYVtf6AVdiYb9IyOZ7U/I+tsTmSVcTKnzCEWg03FMR18fgJU5EGUVrY1fIjImqmvEbH4ugq4+H3wMS5nvk+YiLsl5rXtfHQLrEPNJFFgS3xcfbiy35VWm7X0DvUmPruMIx2QEG5KSn4FMY/+znd7T9PQqDKu2yj9e+M8HqeudDDH8hL5KymfitoaMsszWfTLIu7beB+DvxjMDwk/6M//cmcaN/53DxoXIaew+VjLOiv1DY18tCUZN2cNl41sudNUa7g6a/jPNSOICfLkg6tHNJPcCPRyZeU9k0h9eQEbH5jG/108+Jxen46Kj7sLT104gGl9Q9idaryDLyivIb2gkjfWJZCUV87ulEJ9henRM+b5DgHsSxM2tbengz3jmFk0KVrVwBlPia0uFFOaaQjdhBofp+zmLxbAckrbFh3bl1pETJCnVVqZdTZ0C1gXvbuNR+f3446pba+RnI8t2vZo/9ZmlvQJDaBPZh8SihJ4cNYIDnxziKK6I9z0+/34BWRQ2ShmgDrd/X/u+CcTuk0gzCOCp1eIbBiNi/hjP5ii0XdJ0lFQXsPI/xPtCm+b0pMAL9O/AyN7BLL5oent/B87NsOi/Fl/Ipey6jp83NuuNtb9rAF99tCiod04dqaEw00mCVW1DZzIFsJ/uhRcVVVZeSiTgd382lw4Tcwtx9vNme7+jpk0cT4ca4qQdRiO/QJrnwLvcEOOu87BF6eJfwABMUYPG6ItxLjr6/1klTSvtnxjXYK+GjElv4Itp/LMJiPa1Rgba4hPf7L1XGlkUymvEbNsnRpoz2Bv3pr2Fkv7LSXOP44hfkIW2cXvkN65n828H+fxj41PAnDd+B48sUgUATXWBZ7zpNG0u9GdHbw5dUUGR/oDBqG083G6ifLi8Gh//f7EXsFEBnjw4/4MTmo1pB744SCL3/+L3k+s5tmVx6iua+CWL/Zy37cHmfXGn5RUnT/0eiKrjF6hnS/+Dh108IqiPKsoyhlFUQ5q/13Q9qc6wO4P4Yfrob4Khi0V3ZcAIoaKPPhjPwuJAlcfcPc3etiAJrPxV1bH6/dVVeWdDaf42zLRKGTDiRzqGlRu0vZllJhGdJAn3942jjumxpFfXkNuafszKsAgHw2iQYWfpwtRvlE8NvYxnDXODImIpibXIO/bzauHXr+ml38v/j7y74wIHcGmM7+BppKLh3fnTPkZfFx8odGdxNzmIbttp/Lx83Ah6cUL2jV77+rocveNCdHp4u2r75vMh9eMJMjLlYfm9iXcz52B2nFe/SOe3NJq1hwzCMN9/lcq/Z76gw1Nkibe39R6ymxtfSOHMorNqillT5gjRPOmqqqvmWGctpn6KBwQOioMv8Zw3DMQosbCvs8hbgb4RxmcvxFoNApuzhpq6hv59XAWGUVVvHbZULzdDT+erJIq4rPLCPZ265SPctZiXM8g3F2c+M+fSexILmDRsPaVhlfU1LP+hOEP+/JR5y6Q3T4lDiflVg7WVrA/Phy/6tm8cmF/Ll5xMY+MeYRxEePwV/qyP/cO+sRkMTzKn48SMoj06U4m8M/fjnPJiEi83ZxRVZVtifmM7xlkEa2SrkCglytRgR7NwistoaoqP+7PIMLPnb5hPmg0Cjsfn6kPvzxxQX+2nsojpaCCnw+coaFRZcMDU6mqbWDNsWyqahvw93Th4uHdufbT3Xy1M43LRkU2K7BLzC3nfztS8XZzpqa+Ua+Q2dlwrBi8fxQs/UHE2c/OcQ8bCMmbIGkj9J7T8ufPw87HZvLcr8f45WAme9OKmPba5mbl4A/+cIjtiQXMsKISXGdlcHc//D1d+HJHGjP6hRoVjz2b41mlFDXJerqyha5aHq5O3DuzD/A+77kn8q81J6modmPzFZv152w67Iaqaqj2/Qm4lzNlZ+gd0Bs1JoA9qUW8tuYkfcN9eHdjIlkl1fx9lvz9d4TRMYGsO55DdV1Dsz4DP+w9ja+HC3MHhhOfXcbO5EKeuKC/PkupqbyFl5szl42M4s31CWw4kUufMG/itMJ/Zzem+ebWsVz0723c+r99/HL3RPw8xHftps/36BtwRAV6MD6uc2QsnY05YvD3KIpyWFGUzxRFafU2qCjKbYqi7FUUZW9eXl77r9ZnDkz827nHpz1m2PczLbsBIMDLlQfnNtccWbY7nW5+7gR5ubI9UTwyTuokqWu2xEmjcMWoKPamFTH42bVtZkTkl9dw3We7ySyuYuupPN7blMhl/xFdlhYO7Yars6bNquIFg4UGy5qjhoK4hkaVracK8dXEUlRTwLGCY2RVZNHduzuf3jAaHzdnPv8rlcd+OsKZ4ir+NrM3i0d0LjEqa7NwaDfKquvZlVLIb4czeXblMY5nlvLQ8sPc/uU+qusaWH9cPJnNHdi6KNrg7n6oKuxOLaR/ROt9ciP8PHj/6pGcLqxkzAvriXn0dy54eyvphZXcPCmWVy8dwh/3TdE7/s5GmzN4RVHWAy39pJ8APgCeB1Tt9nXgppbGUVX1I+AjgFGjRpnWu80Y3LxF3L262KgCp5aIDPDkxzvH0yfMh6S8Cj7aksQ143rwwu8nKKiopVeoN1eP63j/VQk8PK8fKfkVrD2ew88Hzpy3JeDaYzlsSchjwssbz3nvrSuGGSXeFRPsRTc/d/7523GuHBOFp6szT/5yhOLKOhaH38YPWY+wL2cfNQ01dPPuhq+7CxN6Benjuw/M7sO9M3u3/z8sAcRCu6uThvc3JbIrRWQsff5Xqv79nw+c4T9/JjGtbwhRga3ftMfHBTGpVzA5pdXcOvn8VcdjYgN5/uJBPKYVgNPl0M8bFG71JtjWpk0Hr6rqLGMGUhTlY+C3DlvUEVy9hIP3b78THtlD/MKHRfnz/tWiBdp143vwyI9HeP2yobg527cGiKPgpFH46LpR3PT5Hj7dlsLcgeH0j/ChuLLOaNG3oVH+xjV/0TJ/cASfbkvhzXUJPLFgAKuOiNn81cPH80MWvLZXLCXppIGfvmggXm7OPLVggFxUNRMerk6M7BHADu0i6k0TY9mfLlKPN8bn8vSKowA8c9HA82a1uLs48dUtxiuvXjUmmglxQVTWNjD/7a0ADDjPzL+z0KEYvKIoEaqq6hSELgGOdtykDtD3AtjzMQSYN8vlitHRTO0TSrhf+9QJJa1z7bgebIzP5fIPd+iP7XhsBhF+htmbTr/knum9uG5CDwI9XXlxVTzXjTdNHO3JBf1Jyivnm13p/GN2X2rrG7lpYixxIc0ji5FamYLu/h68cfmwdv7PJK0xvV8IO5ILuGtaHA/P66c//sjyw3y39zQ3T4o1vu+yCfQIEmNufGAqaQWVeLk51hJke+hoDP5VRVGOKIpyGJgO/N0MNrWf+a/AjX9Ad/M3YpbO3TJM6xvCe0ub/74OnW4ek9+VXEh0oCcPzu1LqI87zk4anr5oADEmOgFFUbhlUk8qahv4Znc6VXUN9AwRY3ww6wP9eVG+pq/hSIznpomx/OeaEXqpBh03TIxhZr9Q7p1hOdlqgJ4h3lZtm2dLOnQLU1X1WnMZYhY0TtBjvK2tkJiAoigsGBLBkTNxLNudTklVHfHZpcwbFM6m+Fw+257CjuQCHp3fr+3BjGBcz0ACvVx5/rfjOGsUxmqFsCZ1n8Tvl/xOfWO9WXq6SlrH2UnDvEHnNh7pH+HLpzdYRxepq9D5n1EkDsGj8/vx6Px+XP6fHby1/hQeLk681KTo7IpR5plVOztpmDswjGW7T3PB4Ihmmu3RvnIBXdK5cCypAkmn57YpIiPipdXx+lq1S0dGmnWRU6fV3t1BG7ZIJMYiZ/ASu2JGv1DumBpHdKAnk3sHG51RYwqzB4Tx1hXDmDNQagpJOjfSwUvsCo1GMVu8vTUUReHi4bJgSdL5kSEaiUQi6aRIBy+RSCSdFOngJRKJpJMiHbxEIpF0UqSDl0gkkk6KdPASiUTSSZEOXiKRSDop0sFLJBJJJ0VRVfP33mjzooqSB6RZ+bLBQL6VryltsF8bwD7skDYYsAc77N2GHqqqhhg7kE0cvC1QFGWvqqqjpA3SBnuyQ9pgX3Z0NhtkiEYikUg6KdLBSyQSSSelKzn4j2xtANIGHfZgA9iHHdIGA/ZgR6eyocvE4CUSiaSr0ZVm8BKJRNKlkA5eIpFIOiuqqjrkPyAK2AQcB44B92mPBwLrgFPabYD2uAK8AyQCh4ER2uPDgB3aMQ4DV1jbhibj+QIZwLu2sAGIBtYCJ7TjxdjIjle1Y5zQnqNYyIZ+2t99DfDgWWPNA05q7XvUgj+HFm1obRxr/xy07zsBB4DfLPw3er7fhz+wHIjXfi/G28CGv2vHOAosA9wtZMPViL+JI8BfwND2fi+t5pDN/Q+IwOCkfYAEYADCOTyqPf4o8Ip2/wJgNcKxjAN2aY/3AXpr97sBWYC/NW1oMt7bwDeY5uDNZgOwGZit3fcGPG3w+5gAbEc4FSftH9s0C9kQCowGXqC5c3UCkoCegCtwCBhgZRtaHMeaNjQZ7x/a76WpDt5sdgBfALdo912x3N9oa7+P7kAK4KF9/T1wg4VsmIDB2c/H8Ldh8vfSpk7anP+AFcBsxN0toskP9qR2/0Pgqibn6887a5xDaB2+NW0ARgLfAjdggoM3lw3aL9w2W/8+gPHAPsAD8AT2Av0tYUOT85496495PLCmyevHgMesaUNr41jbBiAS2ADMwEQHb8bfhx/CuRr1JGchG7oDpxGzbmfgN2COJW3QHg8AzrT3e9kpYvCKosQAw4FdQJiqqlnat7IBXWdl3S9IR4b2WNNxxiDujEnWtEFRFA3wOvCgqdc1lw2IJ5liRVF+UhTlgKIo/1IUxcnadqiqugPxOJul/bdGVdUTFrKhNdr8rljBhtbGsbYNbwEPA42mXtuMdsQCecB/td/NTxRF8bKmDaqqngFeA9IR38sSVVXXWsGGmxFPutCO76XDO3hFUbyBH4H7VVUtbfqeKm5zqpHjRABfAjeqqmrSl9kMNtwFrFJVNcOU65rZBmdgMuImMxrxGHiDte1QFKUX0B8xc+wOzFAUZbI1bTAHZvxetjqOpW1QFOVCIFdV1X2mXNfcdiC+myOAD1RVHQ5UIEIaVrNBUZQAYBHiZtMN8FIU5RpL2qAoynSEg3/ElOs0xaEdvKIoLogf2Neqqv6kPZyjddY6p52rPX4GsdihI1J7DEVRfIHfgSdUVd1pAxvGA/coipKKmCVcpyjKy1a2IQM4qKpqsqqq9cAviD8qozGTHZcAO1VVLVdVtRwxexlvIRtao9XvihVtaG0ca9owEVio/V5+i7jZfmUDOzKADFVVdU8wyzHhu2kmG2YBKaqq5qmqWgf8hIiVW8QGRVGGAJ8Ai1RVLdAeNvl76bAOXlEUBfgUOKGq6htN3loJXK/dvx4R79Idv04RjEM8YmUpiuIK/Az8T1XV5bawQVXVq1VVjVZVNQYxg/6fqqpGzVDMZQOwB/BXFEWnVDcDsepvFGa0Ix2YqiiKs/aPYioia8ISNrTGHqC3oiix2u/HldoxrGbDecaxmg2qqj6mqmqk9nt5JbBRVVWjZ61mtCMbOK0oSl/toZkY+d0043ciHRinKIqndsyZWOh7qShKNOIGcq2qqglNzjf9e9meRQJ7+AdMQjzSHAYOav9dAAQhFoVOAeuBQO35CvAeIr5+BBilPX4NUNdkjIPAMGvacNaYN2BaFo3ZbEAs/OjSsz4HXG3w+3BCLMDqUjXfsKAN4YjZYSlQrN331b53ASLbIQnxZGdVG1obx9o/hyZjTsP0LBpz/j6GIRbcDyOeLgNsYMNziDTNo4hwrpuFbPgEKGpy7t4mY5n0vZRSBRKJRNJJcdgQjUQikUjOj3TwEolE0kmRDl4ikUg6KdLBSyQSSSdFOniJRCLppEgHL5FIJJ0U6eAlEomkk/L/rq7N4xq3jbgAAAAASUVORK5CYII=", 254 | "text/plain": [ 255 | "
" 256 | ] 257 | }, 258 | "metadata": { 259 | "needs_background": "light" 260 | } 261 | } 262 | ], 263 | "metadata": {} 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": 13, 268 | "source": [ 269 | "actual_oos = SP500_returns['erp1w'].iloc[testing_period]\n", 270 | "actual_oos.index = pd.DatetimeIndex(actual_oos.index)\n", 271 | "predictions = fitted['pred'].set_index(actual_oos.index)" 272 | ], 273 | "outputs": [], 274 | "metadata": {} 275 | }, 276 | { 277 | "cell_type": "code", 278 | "execution_count": 14, 279 | "source": [ 280 | "together = pd.concat([actual_oos, predictions], axis = 1)" 281 | ], 282 | "outputs": [], 283 | "metadata": {} 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": 15, 288 | "source": [ 289 | "together['In-Sample Mean'] = SP500_returns['erp1w'].iloc[:training_end].mean()" 290 | ], 291 | "outputs": [], 292 | "metadata": {} 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": 16, 297 | "source": [ 298 | "MAE_MRF = abs(together['erp1w'].subtract(together['Ensembled_Prediction'])).mean()" 299 | ], 300 | "outputs": [], 301 | "metadata": {} 302 | }, 303 | { 304 | "cell_type": "code", 305 | "execution_count": 17, 306 | "source": [ 307 | "MAE_IS_Mean = abs(together['erp1w'].subtract(together['In-Sample Mean'])).mean()" 308 | ], 309 | "outputs": [], 310 | "metadata": {} 311 | }, 312 | { 313 | "cell_type": "code", 314 | "execution_count": 18, 315 | "source": [ 316 | "MAE_MRF, MAE_IS_Mean" 317 | ], 318 | "outputs": [ 319 | { 320 | "output_type": "execute_result", 321 | "data": { 322 | "text/plain": [ 323 | "(5.320851054164453, 5.126104264766212)" 324 | ] 325 | }, 326 | "metadata": {}, 327 | "execution_count": 18 328 | } 329 | ], 330 | "metadata": {} 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": 20, 335 | "source": [ 336 | "fig, ax = plt.subplots()\n", 337 | "actual_oos.rolling(2).mean().plot(ax =ax)\n", 338 | "predictions.rolling(2).mean().plot(ax = ax)\n", 339 | "ax.axhline(together[\"In-Sample Mean\"][0], linestyle = '--', color = 'grey')" 340 | ], 341 | "outputs": [ 342 | { 343 | "output_type": "execute_result", 344 | "data": { 345 | "text/plain": [ 346 | "" 347 | ] 348 | }, 349 | "metadata": {}, 350 | "execution_count": 20 351 | }, 352 | { 353 | "output_type": "display_data", 354 | "data": { 355 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXkAAAEGCAYAAACAd+UpAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAACRqklEQVR4nO2dd5wdVd3Gv2fmtq3Zkt5D6ISQQOi9CKEogi82VCIqqNjbi74W7KgoKiKKDQugFEFApfdOAgklvZKeLUm23zbn/WPmzJyZnbv17uZumOfz2c/u3jt35twzZ37nOc+vHCGlJEKECBEi7J0w9nQDIkSIECHC0CEy8hEiRIiwFyMy8hEiRIiwFyMy8hEiRIiwFyMy8hEiRIiwFyO2pxugY/To0XL69Ol7uhkRIkSIMKKwaNGiRinlmLD3SsrIT58+nYULF+7pZkSIECHCiIIQYkOh9yK5JkKECBH2YkRGPkKECBH2YkRGPkKECBH2YpSUJh8hwt6MbDbLpk2b6Orq2tNNiTBCkUqlmDx5MvF4vM+fiYx8hAjDhE2bNlFVVcX06dMRQuzp5kQYYZBS0tTUxKZNm5gxY0afPxfJNREiDBO6urqor6+PDHyEAUEIQX19fb9XgpGRjxBhGBEZ+AiDwUDGz4gx8lJK7ly0ia5sfk83JUKECBFGDEaMkX9mdRNfvH0JP/jPsj3dlAgRIkQYMRgxRr6lKwtAQ2t6D7ckQoSRC9M0mTNnjvtz9dVXD3sbrrrqKq655ppur69fv55Zs2b161wLFizgjjvuKPj+KaecwgEHHMBhhx3G8ccfz4oVK/rdXoWbbrqJT33qUwD85je/4S9/+UvBY9evX88tt9zi/r9w4UI+85nPDPjag8GIia5RG1hFkmaECANHWVkZixcv3tPNGFbcfPPNzJs3jxtvvJEvf/nL3HPPPb738/k8pmn265wf//jHe3xfGfn3v//9AMybN4958+b1r+FFwsgx8kTbFEbYi/DfK2Hba8U95/hD4eyBMfPp06dzySWXcO+995LNZrn99ts58MADeeKJJ/jsZz8L2E6/J598kqqqKn7yk59w2223kU6nueCCC/j2t7/N+vXrmT9/PscccwzPPvssRx55JB/+8If51re+xY4dO7j55ps56qijAFiyZAnHHnssjY2NfOUrX+FjH/uYrz35fJ4rr7ySxx9/nHQ6zRVXXMHll1+OlJJPf/rTPPTQQ0yZMoVEItHn73jSSSfx85//HIDKykouv/xyHn74Ya6//nrWr1/PL3/5SzKZDEcffTS//vWvMU2TP/3pT/zwhz+kpqaGww47jGQyCdirkcrKSr70pS+xevVqPv7xj9PQ0IBpmtx+++1ceeWVLFu2jDlz5nDJJZcwd+5crrnmGu677z6am5u59NJLWbt2LeXl5dx4443Mnj2bq666ijfffJO1a9fy5ptv8rnPfa4o7H/EyDUukyei8hEiDBSdnZ0+ueYf//iH+97o0aN5+eWX+cQnPuHKKddccw3XX389ixcv5qmnnqKsrIwHH3yQVatW8eKLL7J48WIWLVrEk08+CcDq1av54he/yPLly1m+fDm33HILTz/9NNdccw0/+MEP3Gu9+uqrPProozz33HN85zvfYcuWLb52/uEPf2DUqFG89NJLvPTSS/zud79j3bp13HXXXaxYsYKlS5fyl7/8hWeffbbP3/3ee+/l0EMPBaC9vZ2jjz6aJUuWUF9fzz/+8Q+eeeYZFi9ejGma3HzzzWzdupVvfetbPPPMMzz99NMsXbo09LwXX3wxV1xxBUuWLOHZZ59lwoQJXH311Zx44oksXryYz3/+877jv/WtbzF37lxeffVVfvCDH/ChD33IfW/58uU88MADvPjii3z7298mm832+fsVwghi8g4iGx9hb8AAGfdg0ZNcc+GFFwJwxBFH8M9//hOA448/ni984QtcfPHFXHjhhUyePJkHH3yQBx98kLlz5wLQ1tbGqlWrmDp1KjNmzHAN6SGHHMLpp5+OEIJDDz2U9evXu9c6//zzKSsro6ysjFNPPZUXX3yROXPmuO8/+OCDvPrqq67evnv3blatWsWTTz7J+973PkzTZOLEiZx22mm9fueLL76YsrIypk+fznXXXQfYvol3vetdADzyyCMsWrSII488ErAnwrFjx/LCCy9wyimnMGaMXcH3Pe95DytXrvSdu7W1lc2bN3PBBRcAdkZqb3j66ae58847ATjttNNoamqipaUFgHPPPZdkMkkymWTs2LFs376dyZMn93rOnlAUIy+E+CNwHrBDSjnLee0q4GNAg3PY16SU/xn0tQZ7gggRIoRCSRGmaZLL5QC48sorOffcc/nPf/7D8ccfzwMPPICUkq9+9atcfvnlvs+vX7/ePQeAYRju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", 356 | "text/plain": [ 357 | "
" 358 | ] 359 | }, 360 | "metadata": { 361 | "needs_background": "light" 362 | } 363 | } 364 | ], 365 | "metadata": {} 366 | } 367 | ], 368 | "metadata": { 369 | "kernelspec": { 370 | "name": "python3", 371 | "display_name": "Python 3.8.8 64-bit ('base': conda)" 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.8" 384 | }, 385 | "interpreter": { 386 | "hash": "4e7a58de4b7e505b0e82f0adcc21bb9621f61c2c1c0bdf66b0394a18a0c298a7" 387 | } 388 | }, 389 | "nbformat": 4, 390 | "nbformat_minor": 5 391 | } -------------------------------------------------------------------------------- /MacroRandomForest/MRF.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import math 4 | import matplotlib.pyplot as plt 5 | from joblib import Parallel, delayed 6 | 7 | 8 | class MacroRandomForest: 9 | 10 | ''' 11 | Open Source implementation of Macroeconomic Random Forest. 12 | This class runs MRF, where RF is employed to generate generalized time-varying parameters 13 | for a linear (macroeconomic) equation. See: https://arxiv.org/pdf/2006.12724.pdf for more details. 14 | ''' 15 | 16 | def __init__(self, data, x_pos, oos_pos, S_pos='', y_pos=0, 17 | minsize=10, mtry_frac=1/3, min_leaf_frac_of_x=1, 18 | VI=False, ERT=False, quantile_rate=None, 19 | S_priority_vec=None, random_x=False, trend_push=1, howmany_random_x=1, 20 | howmany_keep_best_VI=20, cheap_look_at_GTVPs=True, 21 | prior_var=[], prior_mean=[], subsampling_rate=0.75, 22 | rw_regul=0.75, keep_forest=False, block_size=12, 23 | fast_rw=True, ridge_lambda=0.1, HRW=0, 24 | B=50, resampling_opt=2, print_b=True, 25 | parallelise=True, n_cores=-1): 26 | 27 | ######## INITIALISE VARIABLES ########### 28 | 29 | # Dataset handling 30 | self.data, self.x_pos, self.oos_pos, self.y_pos, self.S_pos = data, x_pos, oos_pos, y_pos, S_pos 31 | 32 | self.ori_col_names = self.data.copy().columns 33 | self.data.columns = [i for i in range(len(data.columns))] 34 | 35 | if y_pos != 0: 36 | temp_y = self.data.iloc[:, y_pos] 37 | del self.data[y_pos] 38 | self.data = pd.concat([temp_y, self.data], axis = 1) 39 | 40 | for col in data.columns: 41 | if data[col].isna().sum() > 0: 42 | raise Exception("NaN error - please do not run MRF with missing values") 43 | 44 | for col in data.columns: 45 | try: 46 | _ = data[col].astype(float) 47 | except: 48 | ValueError("Data must be numeric. Check that you haven't accidentally used date as your first column.") 49 | 50 | # Properties of the tree 51 | self.minsize, self.mtry_frac, self.min_leaf_frac_of_x = minsize, mtry_frac, min_leaf_frac_of_x 52 | 53 | # Hyperparameters 54 | self.VI, self.ERT, self.quantile_rate, self.S_priority_vec, self.B, self.resampling_opt, self.HRW = VI, ERT, quantile_rate, S_priority_vec, B, resampling_opt, HRW 55 | 56 | # Properties of the randomness 57 | self.random_x, self.howmany_random_x, self.howmany_keep_best_VI, self.subsampling_rate = random_x, howmany_random_x, howmany_keep_best_VI, subsampling_rate 58 | 59 | # Bayesian Priors 60 | self.prior_var, self.prior_mean = prior_var, prior_mean 61 | 62 | # Regularisation (ridge) options: 63 | self.rw_regul, self.ridge_lambda = rw_regul, ridge_lambda 64 | 65 | # User Options 66 | self.keep_forest, self.cheap_look_at_GTVPs, self.print_b = keep_forest, cheap_look_at_GTVPs, print_b 67 | 68 | # Speed Variables 69 | self.block_size, self.fast_rw, self.parallelise, self.n_cores = block_size, fast_rw, parallelise, n_cores 70 | 71 | if isinstance(self.S_pos, str): 72 | self.S_pos = np.arange(1, len(self.data.columns)) 73 | 74 | self.trend_pos = max(self.S_pos) 75 | self.trend_push = trend_push 76 | self.cons_w = 0.01 77 | self.ori_index = self.data.copy().index 78 | 79 | if len(self.prior_mean) != 0: 80 | self.have_prior_mean = True 81 | else: 82 | self.have_prior_mean = False 83 | 84 | ######## RUN LOGISTICS ########### 85 | self._name_translations() 86 | self._array_setup() 87 | self._input_safety_checks() 88 | 89 | def _name_translations(self): 90 | ''' 91 | Translation block and misc. 92 | ''' 93 | 94 | self.ET = self.ERT # translation to older names in the code 95 | self.ET_rate = self.quantile_rate # translation to older names in the code 96 | self.z_pos = self.x_pos # translation to older names in the code 97 | self.x_pos = self.S_pos # translation to older names in the code 98 | self.random_z = self.random_x # translation to older names in the code 99 | # translation to older names in the code 100 | self.min_leaf_fracz = self.min_leaf_frac_of_x 101 | # translation to older names in the code 102 | self.random_z_number = self.howmany_random_x 103 | self.x_pos = self.S_pos # translation to older names in the code 104 | self.VI_rep = 10*self.VI # translation to older names in the code 105 | # translation to older names in the code 106 | self.bootstrap_opt = self.resampling_opt 107 | self.regul_lambda = self.ridge_lambda # translation to older names in the code 108 | self.prob_vec = self.S_priority_vec # translation to older names in the code 109 | # translation to older names in the code 110 | self.keep_VI = self.howmany_keep_best_VI 111 | # used to be an option, but turns out I can't think of a good reason to choose 'False'. So I impose it. 112 | self.no_rw_trespassing = True 113 | self.BS4_frac = self.subsampling_rate # translation to older names in the code 114 | self.trend_pos = np.where(self.S_pos == self.trend_pos) 115 | 116 | if self.prior_var != []: 117 | # those are infact implemented in terms of heterogeneous lambdas 118 | self.prior_var = 1/self.prior_var 119 | 120 | def _input_safety_checks(self): 121 | ''' 122 | Sanity checks of input variables 123 | ''' 124 | 125 | if len(self.z_pos) > 10 and (self.regul_lambda < 0.25 or self.rw_regul == 0): 126 | raise Exception( 127 | 'For models of this size, consider using a higher ridge lambda (>0.25) and RW regularization.') 128 | if(min(self.x_pos) < 1): 129 | raise Exception('S.pos cannot be non-postive.') 130 | if(max(self.x_pos) > len(self.data.columns)): 131 | raise Exception( 132 | 'S.pos specifies variables beyond the limit of your data matrix.') 133 | 134 | if self.y_pos in list(self.x_pos): 135 | self.x_pos = self.x_pos[self.x_pos != self.y_pos] 136 | print('Beware: foolproof 1 activated. self.S_pos and self.y_pos overlap.') 137 | self.trend_pos = np.where( 138 | self.x_pos == self.trend_pos) # foolproof 1 139 | 140 | if self.y_pos in list(self.z_pos): 141 | self.z_pos = self.z_pos[self.z_pos != self.y_pos] 142 | # foolproof 2 143 | print('Beware: foolproof 2 activated. self.x_pos and self.y_pos overlap.') 144 | 145 | if self.regul_lambda < 0.0001: 146 | self.regul_lambda = 0.0001 147 | # foolproof 3 148 | print('Ridge lambda was too low or negative. Was imposed to be 0.0001') 149 | 150 | if self.ET_rate != None: 151 | if self.ET_rate < 0: 152 | self.ET_rate = 0 153 | # foolproof 4 154 | print('Quantile Rate/ERT rate was forced to 0, It cannot be negative.') 155 | 156 | if self.prior_mean != None and self.random_z: 157 | print('Are you sure you want to mix a customized prior with random X?') 158 | 159 | if len(self.z_pos) < 1: 160 | raise Exception('You need to specificy at least one X.') 161 | 162 | if len(self.prior_var) != 0 or self.have_prior_mean: 163 | if self.prior_var == None and self.prior_mean != None: 164 | raise Exception('Need to additionally specificy prior_var.') 165 | if self.prior_mean == None and self.prior_var != None: 166 | raise Exception('Need to additionally specificy prior_mean.') 167 | if len(self.prior_mean) != len(self.z_pos) + 1 or len(self.prior_var) != len(self.z_pos) + 1: 168 | raise Exception( 169 | 'Length of prior vectors do not match that of X.') 170 | 171 | if len(self.x_pos) < 5: 172 | print( 173 | 'Your S_t is small. Consider augmentating with noisy carbon copies it for better results.') 174 | if len(self.x_pos) * self.mtry_frac < 1: 175 | raise Exception('Mtry.frac is too small.') 176 | if self.min_leaf_fracz > 2: 177 | self.min_leaf_fracz = 2 178 | print('min.leaf.frac.of.x forced to 2. Let your trees run deep!') 179 | 180 | if self.min_leaf_fracz*(len(self.z_pos)+1) < 2: 181 | self.min_leaf_fracz = 2/(len(self.z_pos)+1) 182 | print(f'Min.leaf.frac.of.x was too low. Thus, it was forced to ', 2 / 183 | ({len(self.z_pos)}+1), ' -- a bare minimum. You should consider a higher one.', sep='') 184 | 185 | if len(self.oos_pos) == 0: 186 | self.oos_flag = True 187 | self.shit = np.zeros(shape=(2, len(self.data.columns))) 188 | self.shit.columns = self.data.columns 189 | self.new_data = pd.concat([self.data, self.shit]) 190 | self.original_data = self.data.copy() 191 | self.data = self.new_data 192 | self.oos_pos = [len(self.data)-1, len(self.data)] 193 | self.fake_pos = self.oos_pos 194 | self.data.index = None 195 | 196 | else: 197 | self.oos_flag = False 198 | 199 | def _array_setup(self): 200 | ''' 201 | Initialising helpful arrays. 202 | ''' 203 | 204 | self.dat = self.data 205 | self.K = len(self.z_pos)+1 206 | 207 | if self.random_z: 208 | self.K = self.random_z_number+1 209 | 210 | self.commitee = np.tile(np.nan, (self.B, len(self.oos_pos))) 211 | 212 | self.avg_pred = [0]*len(self.oos_pos) 213 | 214 | self.pred_kf = np.stack( 215 | [np.tile(np.nan, (self.B, len(self.data)))]*(len(self.x_pos)+1)) 216 | 217 | self.all_fits = np.tile( 218 | np.nan, (self.B, len(self.data)-len(self.oos_pos))) 219 | 220 | self.avg_beta = np.zeros(shape=(len(self.data), self.K)) 221 | 222 | self.whos_in_mat = np.zeros(shape=(len(self.data), self.B)) 223 | 224 | self.beta_draws = np.stack( 225 | [np.zeros(shape=self.avg_beta.shape)]*self.B) 226 | 227 | self.betas_draws_nonOVF = self.beta_draws 228 | 229 | self.betas_shu = np.stack( 230 | [np.zeros(shape=self.avg_beta.shape)]*(len(self.x_pos)+1)) 231 | 232 | self.betas_shu_nonOVF = np.stack( 233 | [np.zeros(shape=self.avg_beta.shape)]*(len(self.x_pos)+1)) 234 | 235 | self.avg_beta_nonOVF = self.avg_beta 236 | 237 | self.forest = [] 238 | 239 | self.random_vecs = [] 240 | 241 | def _ensemble_loop(self): 242 | ''' 243 | Core random forest ensemble loop. 244 | ''' 245 | 246 | Bs = np.arange(0, self.B) 247 | 248 | # The original basis for this code is taken from publicly available code for a simple tree by André Bleier. 249 | # Standardize data (remeber, we are doing ridge in the end) 250 | 251 | self.std_stuff = standard(self.data) 252 | 253 | 254 | if self.parallelise: 255 | 256 | result = Parallel(n_jobs=self.n_cores)(delayed(self._one_MRF_tree)(b) 257 | for b in Bs) 258 | 259 | else: 260 | 261 | result = [self._one_MRF_tree(b) for b in Bs] 262 | 263 | for b in Bs: 264 | 265 | rt_output = result[b] 266 | 267 | if self.random_z: 268 | 269 | z_pos_effective = np.random.choice(a=self.z_pos, 270 | replace=False, 271 | size=self.random_z_number) 272 | else: 273 | 274 | z_pos_effective = self.z_pos 275 | 276 | rando_vec = rt_output["rando_vec"] 277 | if self.keep_forest: 278 | self.forest[[b]] = rt_output['tree'] 279 | self.random_vec[[b]] = rando_vec 280 | 281 | self.commitee[b, :] = rt_output['pred'] 282 | self.avg_pred = pd.DataFrame(self.commitee).mean(axis=0) 283 | 284 | in_out = np.repeat(0, repeats=len(self.data)) 285 | 286 | for i in range(len(self.data)): 287 | if i not in rando_vec: 288 | in_out[i] = 1 289 | 290 | self.whos_in_mat[:, b] = in_out 291 | 292 | if b == 0: 293 | b_avg = b+1 294 | 295 | self.avg_beta = ((b_avg-1)/b_avg)*np.array(self.avg_pred) + \ 296 | (1/b_avg)*rt_output['pred'] 297 | 298 | self.beta_draws[b, :, :] = rt_output['betas'] 299 | 300 | rt_output['betas'][np.where(in_out == 0), :] = np.repeat( 301 | 0, repeats=len(z_pos_effective) + 1) 302 | 303 | self.avg_beta_nonOVF = self.avg_beta_nonOVF + \ 304 | rt_output['betas'] 305 | 306 | rt_output['betas'][np.where(in_out == 0), :] = np.repeat( 307 | np.nan, repeats=len(z_pos_effective) + 1) 308 | 309 | self.betas_draws_nonOVF[b, :, :] = rt_output['betas'] 310 | 311 | if self.VI_rep > 0: 312 | self.pred_kf[:, self.b, -rando_vec] 313 | self.betas_shu = ((b_avg-1)/b_avg)*self.betas_shu + \ 314 | (1/b_avg)*rt_output['betas_shu'] 315 | rt_output['betas_shu'][:, np.where(in_out == 0), :] 316 | self.betas_shu_nonOVF = self.betas_shu_nonOVF + \ 317 | rt_output['betas_shu'] 318 | 319 | how_many_in = pd.DataFrame(self.whos_in_mat).sum(axis=1) 320 | 321 | self.avg_beta_nonOVF = self.avg_beta_nonOVF / \ 322 | np.transpose(np.tile(how_many_in, reps=( 323 | len(z_pos_effective)+1, 1))) 324 | 325 | for kk in range(1, self.betas_shu_nonOVF.shape[0]): 326 | self.betas_shu_nonOVF[kk, :, :] = self.betas_shu_nonOVF[kk, :, :] / np.transpose(np.tile(how_many_in, reps=( 327 | len(z_pos_effective)+1, 1))) 328 | 329 | if self.oos_flag: 330 | self.avg_beta_nonOVF = self.avg_beta_nonOVF[-self.fake_pos, :] 331 | self.avg_beta = self.avg_beta[-self.fake_pos, :] 332 | self.betas_draws_nonOVF = self.betas_draws_nonOVF[-self.fake_pos, :] 333 | self.betas_draws = self.betas_draws[-self.fake_pos, :] 334 | 335 | # cancel VI_POOS 336 | self.VI_poos = None 337 | 338 | # cancel pred and the commitee 339 | self.avg_pred = None 340 | self.commitee = None 341 | 342 | self.data = self.data[-self.fake_pos, :] 343 | 344 | if self.random_z: 345 | self.VI_betas = None 346 | self.VI_betas_nonOVF = None 347 | self.VI_oob = None 348 | self.VI_poos = None 349 | self.impZ = None 350 | self.avg_beta = None 351 | self.avg_beta_nonOVF = None 352 | self.betas_draws = None 353 | self.betas_draws_nonOVF = None 354 | 355 | self.avg_pred = pd.DataFrame(self.avg_pred, columns=[ 356 | 'Ensembled_Prediction']) 357 | self.avg_pred.set_index( 358 | self.oos_pos, inplace=True) 359 | 360 | return {"YandX": self.data.iloc[:, [self.y_pos] + self.z_pos], 361 | "pred_ensemble": self.commitee, 362 | "pred": self.avg_pred, 363 | "S_names": self.data.iloc[:, self.x_pos].columns, 364 | "betas": self.avg_beta_nonOVF, 365 | "betas_draws_raw": self.beta_draws, 366 | "betas_draws": self.betas_draws_nonOVF, 367 | "model": {"forest": self.forest, 368 | "data": self.data, 369 | "regul_lambda": self.regul_lambda, 370 | "prior_var": self.prior_var, 371 | "prior_mean": self.prior_mean, 372 | "rw_regul": self.rw_regul, 373 | "HRW": self.HRW, 374 | "no_rw_trespassing": self.no_rw_trespassing, 375 | "B": self.B, 376 | "random_vecs": self.random_vecs, 377 | "y_pos": self.y_pos, 378 | "S_pos": self.x_pos, 379 | "x_pos": self.z_pos 380 | } 381 | } 382 | 383 | def _process_subsampling_selection(self): 384 | ''' 385 | Processes user choice for subsampling technique. 386 | ''' 387 | 388 | # No bootstap/sub-sampling. Should not be used for looking at GTVPs. 389 | if self.bootstrap_opt == 0: 390 | 391 | rando_vec = np.arange( 392 | 0, len(self.data.iloc[:self.oos_pos[0]])) 393 | 394 | elif self.bootstrap_opt == 1: # Plain sub-sampling 395 | chosen_ones = np.random.choice(a=np.arange(0, len(self.data.iloc[-self.oos_pos, :]) + 1), 396 | replace=False, 397 | size=self.BS4_frac*len(self.data.iloc[-self.oos_pos, :])) # Is size equivalent to n here? Why both options appear in R? 398 | chosen_ones_plus = list(chosen_ones) 399 | 400 | rando_vec = list(sorted(chosen_ones_plus)) 401 | 402 | # Block sub-sampling. Recommended when looking at TVPs. 403 | elif self.bootstrap_opt == 2: 404 | 405 | n_obs = self.data[:self.oos_pos[0] - 1].shape[0] 406 | 407 | groups = sorted(np.random.choice( 408 | list(np.arange(0, int(n_obs/self.block_size))), size=n_obs, replace=True)) 409 | 410 | rando_vec = np.random.exponential( 411 | 1, size=int(n_obs/self.block_size)) + 0.1 412 | 413 | rando_vec = [rando_vec[i] for i in groups] 414 | 415 | chosen_ones_plus = rando_vec 416 | 417 | rando_vec = np.where(chosen_ones_plus > np.quantile( 418 | chosen_ones_plus, 1 - self.BS4_frac))[0] 419 | 420 | chosen_ones_plus = rando_vec 421 | 422 | rando_vec = sorted(chosen_ones_plus.tolist()) 423 | 424 | elif self.bootstrap_opt == 3: # Plain bayesian bootstrap 425 | chosen_ones = np.random.exponential( 426 | scale=1, size=len(self.data.iloc[-self.oos_pos, :])) 427 | chosen_ones_plus = chosen_ones/np.mean(chosen_ones) 428 | rando_vec = chosen_ones_plus 429 | 430 | return rando_vec 431 | 432 | def _one_MRF_tree(self, b): 433 | ''' 434 | Function to create a single MRF tree. 435 | ''' 436 | 437 | if self.print_b: 438 | print(f"Tree {b+1} out of {self.B}") 439 | 440 | rando_vec = self._process_subsampling_selection() 441 | 442 | data = self.std_stuff["Y"] 443 | 444 | # Adjust prior.mean according to standarization 445 | if self.have_prior_mean: 446 | self.prior_mean[-1] = (1/self.std_stuff["std"][:, self.y_pos]) * \ 447 | (self.prior_mean[-1]*self.std_stuff["std"][:, self.z_pos]) 448 | 449 | self.prior_mean[1] = (self.prior_mean[1]-self.std_stuff["mean"][:, self.y_pos] + 450 | self.std_stuff["mean"][:, self.z_pos]@self.prior_mean[-1])/self.std_stuff["std"][:, self.y_pos] 451 | 452 | # Just a simple/convenient way to detect you're using BB or BBB rather than sub-sampling 453 | if min(rando_vec) < 0: 454 | weights = rando_vec 455 | rando_vec = np.arange(0, min(self.oos_pos)) 456 | bayes = True 457 | 458 | else: 459 | bayes = False 460 | 461 | if self.minsize < (2 * self.min_leaf_fracz * (len(self.z_pos)+2)): 462 | self.minsize = 2*self.min_leaf_fracz*(len(self.z_pos)+1)+2 463 | 464 | noise = 0.00000015 * \ 465 | np.random.normal(size=len(rando_vec)) 466 | 467 | # coerce to a dataframe 468 | self.data_ori = pd.DataFrame(data.copy()) 469 | 470 | data = pd.DataFrame(data) 471 | 472 | data = data.iloc[rando_vec, 473 | :].add(noise, axis=0) 474 | 475 | rw_regul_dat = self.data_ori.iloc[: self.oos_pos[0], [ 476 | 0] + list(self.z_pos)] 477 | 478 | row_of_ones = pd.Series([1]*len(data), index=data.index) 479 | 480 | X = pd.concat([row_of_ones, 481 | data.iloc[:, list(self.x_pos)]], axis=1) 482 | 483 | y = data.iloc[:, self.y_pos] 484 | 485 | z = data.iloc[:, self.z_pos] 486 | 487 | if bayes: 488 | 489 | z = pd.DataFrame(weights*z) 490 | y = pd.DataFrame(weights*y) 491 | 492 | do_splits = True 493 | 494 | tree_info = {"NODE": 1, "NOBS": len( 495 | data), "FILTER": None, "TERMINAL": "SPLIT"} 496 | 497 | for i in range(1, len(self.z_pos) + 2): 498 | tree_info[f'b0.{i}'] = 0 499 | 500 | tree_info = pd.DataFrame(tree_info, index=[0]) 501 | 502 | column_binded_data = data.copy() 503 | column_binded_data.insert( 504 | 0, "rando_vec", rando_vec) 505 | 506 | while do_splits: 507 | 508 | to_calculate = tree_info[tree_info['TERMINAL'] 509 | == "SPLIT"].index.tolist() 510 | 511 | all_stop_flags = [] 512 | 513 | for j in to_calculate: 514 | 515 | self.wantPrint = False 516 | 517 | # Handle root node 518 | 519 | filterr = tree_info.loc[j, "FILTER"] 520 | 521 | if filterr != None: 522 | 523 | # subset data according to the filter 524 | parsed_filter = filterr.replace("[", "data[") 525 | 526 | this_data = data[eval(parsed_filter)] 527 | 528 | find_out_who = column_binded_data.loc[this_data.index] 529 | 530 | whos_who = find_out_who.iloc[:, 1] 531 | 532 | # Get the design matrix 533 | X = this_data.iloc[:, self.x_pos] 534 | X.insert(0, "Intercept", [1]*len(X)) 535 | 536 | y = this_data.iloc[:, self.y_pos] 537 | z = this_data.iloc[:, self.z_pos] 538 | 539 | if bayes: 540 | z = weights[whos_who]*z 541 | y = weights[whos_who]*np.matrix(y) 542 | 543 | else: 544 | 545 | this_data = data 546 | whos_who = rando_vec 547 | 548 | if bayes: 549 | 550 | this_data = weights * data 551 | 552 | self.old_b0 = tree_info.loc[j, "b0.1"] 553 | 554 | ############## Select potential candidates for this split ############### 555 | SET = X.iloc[:, 1:] # all X's but the intercept 556 | 557 | n_cols_split = len(SET.columns) 558 | 559 | if self.prob_vec == None: 560 | prob_vec = np.repeat(1, repeats=n_cols_split) 561 | 562 | if self.trend_push > 1: 563 | prob_vec[self.trend_pos] = self.trend_push 564 | 565 | prob_vec = np.array([value/sum(prob_vec) 566 | for value in prob_vec]) 567 | 568 | # classic mtry move 569 | select_from = np.random.choice(np.arange(0, len( 570 | SET.columns)), size=round(n_cols_split*self.mtry_frac), p=prob_vec, replace=False) 571 | 572 | if len(SET.columns) < 5: 573 | select_from = np.arange(0, n_cols_split) 574 | 575 | splitting = SET.iloc[:, select_from].apply( 576 | lambda x: self._splitter_mrf(x, y, z, whos_who, rando_vec, rw_regul_dat)) 577 | 578 | splitting = splitting.reset_index(drop=True) 579 | 580 | sse = splitting.iloc[0, :] 581 | 582 | stop_flag = all(np.array(sse) == np.inf) 583 | 584 | tmp_splitter = sse.idxmin() 585 | 586 | mn = max(tree_info['NODE']) 587 | 588 | criteria = round(splitting.loc[1, tmp_splitter], 15) 589 | 590 | tmp_filter = [f"[{tmp_splitter}] >= {criteria}", 591 | f"[{tmp_splitter}] < {criteria}"] 592 | 593 | if filterr != None: 594 | tmp_filter = ["(" + filterr + ")" + " & " + "(" + f + ")" 595 | for f in tmp_filter] 596 | 597 | 598 | nobs = np.array([splitting.loc[len(splitting)-1, tmp_splitter], 599 | splitting.loc[len(splitting)-2, tmp_splitter]]) 600 | 601 | if any(nobs <= self.minsize): 602 | split_here = np.repeat(False, repeats=2, axis=0) 603 | 604 | split_here = np.repeat(False, repeats=2, axis=0) 605 | split_here[nobs >= self.minsize] = True 606 | 607 | terminal = np.repeat("SPLIT", repeats=2, axis=0) 608 | terminal[nobs < self.minsize] = "LEAF" 609 | terminal[nobs == 0] = "TRASH" 610 | 611 | if not stop_flag: 612 | 613 | children = {"NODE": [ 614 | mn+1, mn+2], "NOBS": nobs, "FILTER": tmp_filter, "TERMINAL": terminal} 615 | 616 | for i in range(1, len(self.z_pos) + 2): 617 | children[f'b0.{i}'] = [ 618 | splitting.loc[1 + i, tmp_splitter]]*2 619 | 620 | children = pd.DataFrame(children) 621 | 622 | tree_info.loc[j, "TERMINAL"] = "PARENT" 623 | 624 | if stop_flag: 625 | tree_info.loc[j, "TERMINAL"] = "LEAF" 626 | 627 | tree_info = pd.concat( 628 | [tree_info, children]).reset_index(drop=True) 629 | 630 | do_splits = not ( 631 | all(np.array(tree_info['TERMINAL']) != "SPLIT")) 632 | 633 | all_stop_flags.append(stop_flag) 634 | 635 | if all(all_stop_flags): 636 | do_splits = False 637 | 638 | self.ori_y = self.data_ori.iloc[:, self.y_pos] 639 | 640 | self.ori_z = pd.concat([pd.Series( 641 | [1]*len(self.data_ori)), self.data_ori.iloc[:, self.z_pos]], axis=1) 642 | 643 | leafs = tree_info[tree_info["TERMINAL"] == "LEAF"] 644 | 645 | pga = self._pred_given_tree(leafs, rando_vec, rw_regul_dat) 646 | 647 | beta_bank = pga['beta_bank'] 648 | 649 | fitted = pga['fitted'] 650 | 651 | ################################################################################### 652 | ################################################################################### 653 | ########################## Back to original units ################################# 654 | ################################################################################### 655 | ################################################################################### 656 | 657 | fitted = fitted * \ 658 | self.std_stuff['std'].flat[self.y_pos] + \ 659 | self.std_stuff['mean'].flat[self.y_pos] 660 | 661 | betas = beta_bank 662 | 663 | betas[:, 0] = beta_bank[:, 0]*self.std_stuff['std'].flat[self.y_pos] + \ 664 | self.std_stuff['mean'].flat[self.y_pos] 665 | 666 | for kk in range(1, betas.shape[1]): 667 | 668 | betas[:, kk] = beta_bank[:, kk]*self.std_stuff['std'].flat[self.y_pos] / \ 669 | self.std_stuff['std'].flat[self.z_pos[kk-1]] 670 | 671 | betas[:, 0] = betas[:, 0] - betas[:, kk] * \ 672 | self.std_stuff['mean'].flat[self.z_pos[kk-1]] 673 | 674 | beta_bank_shu = np.stack( 675 | [np.zeros(shape=beta_bank.shape)]*(len(self.x_pos)+1)) 676 | 677 | fitted_shu = np.zeros(shape=(len(fitted), (len(self.x_pos) + 1))) 678 | 679 | return {"tree": tree_info[tree_info['TERMINAL'] == "LEAF"], 680 | "fit": fitted[:self.oos_pos[0]], 681 | "pred": fitted[self.oos_pos], 682 | "data": self.data_ori, 683 | "betas": betas, 684 | 'betas_shu': beta_bank_shu, 685 | "fitted_shu": fitted_shu, 686 | "rando_vec": rando_vec} 687 | 688 | def _splitter_mrf(self, x, y, z, whos_who, rando_vec, rw_regul_dat): 689 | 690 | x = np.array(x) 691 | 692 | uni_x = np.unique(x) 693 | 694 | splits = sorted(uni_x) 695 | 696 | z = np.column_stack([np.ones(len(z)), z]) 697 | min_frac_times_no_cols = self.min_leaf_fracz*z.shape[1] 698 | 699 | y_as_list = np.array(y) 700 | y = np.matrix(y) 701 | 702 | sse = np.repeat(np.inf, repeats=len(uni_x), axis=0) 703 | the_seq = np.arange(0, len(splits)) 704 | 705 | whos_who = np.array(whos_who) 706 | 707 | nobs1 = {} 708 | nobs2 = {} 709 | 710 | if self.rw_regul <= 0: 711 | self.fast_rw = True 712 | 713 | if self.ET_rate != None: 714 | if self.ET and len(z) > 2*self.minsize: 715 | 716 | samp = splits[min_frac_times_no_cols-1: len( 717 | splits) - min_frac_times_no_cols] 718 | 719 | splits = np.random.choice( 720 | samp, size=max(1, self.ET_rate*len(samp)), replace=False) 721 | 722 | the_seq = np.arange(0, len(splits)) 723 | 724 | elif self.ET == False and z.shape[0] > 4*self.minsize: 725 | 726 | samp = splits[min_frac_times_no_cols-1: len( 727 | splits) - min_frac_times_no_cols] 728 | 729 | splits = np.quantile(samp, np.linspace( 730 | start=0.01, stop=0.99, num=math.floor(max(1, self.ET_rate*len(samp))))) 731 | 732 | the_seq = np.arange(0, len(splits)) 733 | 734 | reg_mat = np.identity(z.shape[1])*self.regul_lambda 735 | reg_mat[0, 0] = self.cons_w*reg_mat[0, 0] 736 | 737 | if len(self.prior_var) > 0: 738 | 739 | reg_mat = np.diag(np.array(self.prior_var))*self.regul_lambda 740 | 741 | if not self.have_prior_mean: 742 | 743 | z_T = z.T 744 | b0 = np.linalg.solve(z_T @ z + reg_mat, z_T@y.T) 745 | 746 | else: 747 | 748 | # WIP # 749 | z_T = z.T 750 | b0 = np.linalg.solve( 751 | z_T @ z + reg_mat, np.matmul(z_T, y - z @ self.prior_mean)) + self.prior_mean 752 | 753 | dimension = rw_regul_dat.shape 754 | nrrd = dimension[0] 755 | ncrd = dimension[1] 756 | 757 | for i in the_seq: 758 | 759 | sp = splits[i] 760 | 761 | id1 = np.where(x < sp)[0] 762 | 763 | id2 = np.where(x >= sp)[0] 764 | 765 | num_first_split = len(id1) 766 | num_second_split = len(id2) 767 | 768 | nobs1[i] = num_first_split 769 | nobs2[i] = num_second_split 770 | 771 | if num_first_split >= min_frac_times_no_cols and num_second_split >= min_frac_times_no_cols: 772 | 773 | yy = np.array([[y_as_list[i] for i in id1]]) 774 | zz = z[id1, :] 775 | 776 | zz_privy = zz 777 | 778 | if not self.fast_rw: 779 | 780 | everybody = self._find_n_neighbours( 781 | whos_who, id1, 1, nrrd, rando_vec) 782 | 783 | everybody2 = self._find_n_neighbours( 784 | whos_who, id1, 2, nrrd, rando_vec) 785 | 786 | everybody2 = np.array( 787 | [a for a in everybody2 if not a in everybody]) 788 | 789 | yy, zz = self._random_walk_regularisation(yy, 790 | zz, 791 | everybody, 792 | everybody2, 793 | rw_regul_dat, 794 | ncrd) 795 | 796 | zz_T = zz.T 797 | 798 | # bvars or not 799 | if not self.have_prior_mean: 800 | 801 | p1 = zz_privy@((1-self.HRW)*np.linalg.solve(zz_T @ zz + 802 | reg_mat, zz_T @ yy.T) + self.HRW*b0) 803 | 804 | else: 805 | 806 | p1 = zz_privy@((1-self.HRW)*np.linalg.solve(zz @ zz_T + reg_mat, np.matmul( 807 | zz, yy - zz @ self.prior_mean)) + self.prior_mean + self.HRW*b0) 808 | 809 | yy = np.array([[y_as_list[i] for i in id2]]) 810 | zz = z[id2, :] 811 | zz_privy = zz 812 | 813 | if not self.fast_rw: 814 | 815 | everybody = self._find_n_neighbours( 816 | whos_who, id2, 1, nrrd, rando_vec) 817 | 818 | everybody2 = self._find_n_neighbours( 819 | whos_who, id2, 2, nrrd, rando_vec) 820 | 821 | everybody2 = np.array( 822 | [a for a in everybody2 if not a in everybody]) 823 | 824 | yy, zz = self._random_walk_regularisation(yy, 825 | zz, 826 | everybody, 827 | everybody2, 828 | rw_regul_dat, 829 | ncrd) 830 | 831 | zz_T = zz.T 832 | 833 | if not self.have_prior_mean: 834 | 835 | p2 = zz_privy@((1-self.HRW)*np.linalg.solve(zz_T @ zz + 836 | reg_mat, zz_T @ yy.T) + self.HRW*b0) 837 | 838 | else: 839 | 840 | p2 = zz_privy@((1-self.HRW)*np.linalg.solve(zz_T @ zz + reg_mat, np.matmul( 841 | zz, yy - zz @ self.prior_mean)) + self.prior_mean+self.HRW*b0) 842 | 843 | sse[i] = sum(np.subtract(y_as_list.take(id1), np.array(p1.flat)) ** 2) + \ 844 | sum(np.subtract( 845 | y_as_list.take(id2), np.array(p2.flat)) ** 2) 846 | 847 | # implement a mild preference for 'center' splits, allows trees to run deeper 848 | sse = DV_fun(sse, DV_pref=0.15) 849 | 850 | split_no_chosen = sse.argmin() 851 | 852 | return [min(sse)] + [splits[split_no_chosen]] + list(b0.flat) + [nobs1[split_no_chosen]] + [nobs2[split_no_chosen]] 853 | 854 | def _pred_given_tree(self, leafs, rando_vec, rw_regul_dat): 855 | 856 | fitted = np.repeat(np.nan, repeats=len(self.ori_y)) 857 | 858 | beta_bank = np.full(fill_value=np.nan, shape=( 859 | len(self.ori_y), len(self.ori_z.columns))) 860 | 861 | ori_z = np.matrix(self.ori_z) 862 | 863 | regul_mat = np.matrix(rw_regul_dat) 864 | 865 | leafs_mat = np.matrix(leafs) 866 | 867 | for i in range(0, len(leafs)): 868 | 869 | ind_all = list(self.data_ori[eval( 870 | leafs_mat[i, 2].replace("[", "self.data_ori["))].index) 871 | 872 | ind = np.array([j for j in ind_all if j < 873 | self.oos_pos[0] if not np.isnan(j)]) 874 | 875 | if len(ind) > 0: 876 | 877 | yy = np.array(self.ori_y.iloc[ind]) 878 | 879 | zz = ori_z[ind, :] 880 | 881 | zz_all = ori_z[ind_all, :] 882 | 883 | # Simple ridge prior 884 | reg_mat = np.identity(len(self.z_pos) + 1)*self.regul_lambda 885 | reg_mat[0, 0] = 0.01 * reg_mat[0, 0] 886 | 887 | # Adds RW prior in the mix 888 | nrrd = regul_mat.shape[0] 889 | ncrd = regul_mat.shape[1] 890 | 891 | if self.rw_regul > 0: 892 | 893 | everybody = self._find_n_neighbours( 894 | ind, None, 1, nrrd, rando_vec, ind_all, "prediction") 895 | 896 | everybody2 = self._find_n_neighbours( 897 | ind, None, 2, nrrd, rando_vec, ind_all, "prediction") 898 | 899 | everybody2 = np.array( 900 | [j for j in everybody2 if j not in everybody]) 901 | 902 | yy, zz = self._random_walk_regularisation( 903 | yy, zz, everybody, everybody2, regul_mat, ncrd) 904 | 905 | if yy.ndim == 2: 906 | yy = yy.reshape((-1,)) 907 | 908 | if len(self.prior_var) != 0: 909 | 910 | reg_mat = np.diag( 911 | np.array(self.prior_var))*self.regul_lambda 912 | prior_mean_vec = self.prior_mean 913 | 914 | zz_T = zz.T 915 | 916 | beta_hat = np.linalg.solve( 917 | zz_T @ zz + reg_mat, np.matmul(zz_T, yy - zz @ prior_mean_vec)) + prior_mean_vec 918 | 919 | b0 = np.transpose( 920 | leafs_mat[i, 4: 4+len(self.z_pos)+1]) 921 | 922 | else: 923 | 924 | zz_T = zz.T 925 | 926 | beta_hat = np.linalg.solve( 927 | np.matmul(zz_T, zz) + reg_mat, np.matmul(zz_T, yy).T) 928 | 929 | b0 = np.transpose(leafs_mat[i, 4: 4+len(self.z_pos)+1]) 930 | 931 | if len(ind_all) == 1: 932 | if np.matrix(np.transpose(zz_all)).shape[0] != 1: 933 | zz_all = np.transpose(zz_all) 934 | 935 | fitted_vals = zz_all.T @ ((1-self.HRW) 936 | * beta_hat + self.HRW*b0) 937 | 938 | for j in range(len(fitted_vals)): 939 | fitted[ind_all[j]] = fitted_vals[j] 940 | 941 | else: 942 | 943 | if zz_all.shape[1] != len(b0): 944 | zz_all = zz_all.T 945 | 946 | fitted_vals = zz_all@((1-self.HRW) 947 | * beta_hat+self.HRW*b0) 948 | 949 | for j in range(len(fitted_vals)): 950 | 951 | fitted[ind_all[j]] = fitted_vals[j] 952 | 953 | beta_bank[ind_all, :] = np.tile(A=np.transpose( 954 | (1-self.HRW)*beta_hat+self.HRW*b0), reps=(len(ind_all), 1)) 955 | 956 | return {"fitted": fitted, "beta_bank": beta_bank} 957 | 958 | def _find_n_neighbours(self, array, i_d, n_neighbours, nrrd, rando_vec, ind_all=None, stage='splitting'): 959 | 960 | if stage == 'splitting': 961 | everybody_n = np.unique(np.concatenate((array.take( 962 | i_d)+n_neighbours, array.take(i_d)-n_neighbours))) 963 | everybody_n = np.array([ 964 | a for a in everybody_n if not a in array]) 965 | 966 | elif stage == 'prediction': 967 | everybody_n = np.unique(np.concatenate( 968 | (array+n_neighbours, array-n_neighbours))) 969 | everybody_n = np.array([ 970 | a for a in everybody_n if not a in ind_all]) 971 | 972 | # Check that it's a valid index i.e. not -1 (which would incorrectly index the last obsv) 973 | everybody_n = everybody_n[everybody_n >= 0] 974 | # check that we're not leaking into OOS 975 | everybody_n = everybody_n[everybody_n < nrrd] 976 | 977 | if self.no_rw_trespassing: 978 | everybody_n = np.intersect1d(everybody_n, rando_vec) 979 | 980 | return everybody_n 981 | 982 | def _random_walk_regularisation(self, yy, zz, everybody, everybody2, rw_regul_dat, ncrd): 983 | 984 | add_neighbors = True 985 | add_neighbors_2 = True 986 | 987 | if len(everybody) == 0: 988 | add_neighbors = False 989 | 990 | else: 991 | y_neighbors = np.matrix( 992 | self.rw_regul*rw_regul_dat[everybody, 0]) 993 | z_neighbors = np.matrix(self.rw_regul * np.column_stack( 994 | [np.repeat(1, repeats=len(everybody)), rw_regul_dat[everybody, 1: ncrd]])) 995 | 996 | if len(everybody2) == 0: 997 | add_neighbors_2 = False 998 | 999 | else: 1000 | y_neighbors2 = np.matrix( 1001 | self.rw_regul ** 2 * rw_regul_dat[everybody2, 0]) 1002 | z_neighbors2 = np.matrix(self.rw_regul ** 2*np.column_stack( 1003 | [np.repeat(1, repeats=len(everybody2)), 1004 | np.matrix(rw_regul_dat[everybody2, 1: ncrd])])) 1005 | 1006 | if len(zz) == len(self.z_pos) + 1: 1007 | zz_copy = np.transpose(zz) 1008 | 1009 | else: 1010 | zz_copy = zz 1011 | 1012 | if add_neighbors and add_neighbors_2: 1013 | 1014 | yy = np.append( 1015 | np.append(np.array(yy), y_neighbors), y_neighbors2) 1016 | zz = np.vstack([zz_copy, z_neighbors, z_neighbors2]) 1017 | 1018 | elif add_neighbors == True and add_neighbors_2 == False: 1019 | 1020 | yy = np.append(np.array(yy), y_neighbors) 1021 | zz = np.vstack( 1022 | [zz_copy, z_neighbors]) 1023 | 1024 | elif add_neighbors == False and add_neighbors_2 == True: 1025 | 1026 | yy = np.append(np.array(yy), y_neighbors2) 1027 | zz = np.vstack( 1028 | [zz_copy, z_neighbors2]) 1029 | 1030 | return yy, zz 1031 | 1032 | def _variable_importance(self, leafs, fitted, fitted_scaled, y, z, rando_vec, rw_regul_dat): 1033 | 1034 | ''' 1035 | Variable Importance from the Forest 1036 | ''' 1037 | 1038 | if self.VI_rep > 0: 1039 | 1040 | whos_in = np.repeat(np.nan, repeats=len(self.x_pos), axis=0) 1041 | 1042 | for k in range(len(self.x_pos)): 1043 | 1044 | x = f"[{self.x_pos[k]}]" 1045 | 1046 | x_in_filters = False 1047 | 1048 | for filtr in leafs['FILTER']: 1049 | if x in filtr: 1050 | x_in_filters = True 1051 | 1052 | whos_in[k] = x_in_filters 1053 | 1054 | beta_bank_shu = np.stack([self.beta_bank for _ in range(len(self.x_pos)+1)]) 1055 | 1056 | fitted_shu = np.zeros((len(fitted), len(self.x_pos)+1)) 1057 | 1058 | for k in range(len(self.x_pos)): 1059 | if whos_in[k]: 1060 | for ii in range(self.VI_rep): 1061 | data_shu = self.data_ori.copy() 1062 | data_shu.iloc[:, self.x_pos[k]] = np.random.choice(a=self.data_ori.iloc[:, self.x_pos[k]], 1063 | replace=False, 1064 | size=len(self.data_ori)) 1065 | 1066 | pga = self._pred_given_tree(leafs, rando_vec, rw_regul_dat) 1067 | 1068 | weight = ((ii-1)/ii) if ii != 0 else 0 1069 | beta_bank_shu[k+1] = weight * beta_bank_shu[k+1] + pga['beta_bank']/ii 1070 | fitted_shu[:, k+1] = weight * fitted_shu[:, k+1] + pga['fitted']/ii 1071 | 1072 | else: 1073 | beta_bank_shu[k+1] = self.beta_bank 1074 | fitted_shu[:, k+1] = fitted_scaled 1075 | 1076 | else: 1077 | beta_bank_shu = np.stack([np.zeros(shape=self.beta_bank.shape) for _ in range(len(self.x_pos)+1)]) 1078 | fitted_shu = np.zeros((len(fitted), len(self.x_pos)+1)) 1079 | 1080 | return beta_bank_shu, fitted_shu 1081 | 1082 | 1083 | def band_plots(self): 1084 | 1085 | if self.cheap_look_at_GTVPs: 1086 | if self.B*(1-self.BS4_frac) < 30: 1087 | print( 1088 | 'Warning: those bands may have missing values or be innacurate if B is low and subsampling.rate is high.') 1089 | 1090 | bands = np.stack( 1091 | [np.zeros(shape=(len(self.data), len(self.z_pos)+1))]*2) 1092 | 1093 | bands[0] = self.avg_beta_nonOVF 1094 | bands[1] = self.avg_beta_nonOVF 1095 | 1096 | for t in range(len(self.data)): 1097 | for k in range(len(self.z_pos) + 1): 1098 | bands[0, t, k] = np.nanquantile( 1099 | self.betas_draws_nonOVF[:, t, k], 0.16) 1100 | 1101 | bands[1, t, k] = np.nanquantile( 1102 | self.betas_draws_nonOVF[:, t, k], 0.84) 1103 | 1104 | nrows = math.ceil((len(self.z_pos)+1)/2) 1105 | 1106 | fig, ax = plt.subplots( 1107 | nrows=nrows, ncols=2, gridspec_kw={"wspace": 0.1, 'hspace': 0.3}) 1108 | 1109 | # display(bands[0]) 1110 | data = np.matrix(self.data) 1111 | z_mat = np.hstack([np.ones(shape=(len(data), 1)), data[:, self.z_pos]]) 1112 | 1113 | keep_OLS = np.linalg.inv( 1114 | (z_mat.T@z_mat)) @ (z_mat.T @ data[:, self.y_pos]) 1115 | 1116 | ax_positions = [] 1117 | 1118 | j = 0 1119 | k = 0 1120 | 1121 | for i in range(len(self.z_pos)+1): 1122 | 1123 | ax_positions.append(ax[k, j]) 1124 | if i % 2 == 0: 1125 | j += 1 1126 | 1127 | if i % 2 != 0: 1128 | k += 1 1129 | j -= 1 1130 | 1131 | original_x_names = [self.ori_col_names[i] for i in self.z_pos] 1132 | 1133 | beta_titles = [r"$\beta_{0,t}$" + " : Const", r"$\beta_{1,t}$", r"$\beta_{2, t}$", r"$\beta_{3, t}$", r"$\beta_{4, t}$", r"$\beta_{5 ,t}$", r"$\beta_{6, t}$", r"$\beta_{7, t}$", r"$\beta_{8, t}$", r"$\beta_{9, t}$", 1134 | r"$\beta_{10,t}$", r"$\beta_{11, t}$", r"$\beta_{12, t}$", r"$\beta_{13, t}$", r"$\beta_{14, t}$", r"$\beta_{15, t}$", r"$\beta_{16, t}$", r"$\beta_{17, t}$", r"$\beta_{18, t}$"] 1135 | 1136 | for i in range(len(original_x_names)): 1137 | 1138 | beta_titles[1+i] += f" : {original_x_names[i]}" 1139 | 1140 | for k in range(len(self.z_pos) + 1): 1141 | 1142 | ax_positions[k].plot( 1143 | self.avg_beta_nonOVF[:, k].reshape(-1, 1), color='blue', label='Posterior Mean') 1144 | 1145 | for i in [0, 1]: 1146 | if i == 0: 1147 | ax_positions[k].plot(bands[i, :, k].T, 1148 | color='orange', label="16% and 84% Quantiles") 1149 | elif i == 1: 1150 | ax_positions[k].plot(bands[i, :, k].T, 1151 | color='orange', label="_nolegend_") 1152 | 1153 | ax_positions[k].axhline( 1154 | y=keep_OLS[k], color="green", linestyle='-', label="OLS") 1155 | 1156 | ax_positions[k].set_title(beta_titles[k], fontsize=16) 1157 | 1158 | if not self.oos_flag: 1159 | ax_positions[k].axvline( 1160 | min(self.oos_pos), linestyle='--', color='black', label='OOS Start') 1161 | 1162 | else: 1163 | ax_positions[k].legend(loc='best') 1164 | 1165 | ax_positions[k].set_xlabel(r"$t$", fontsize=13) 1166 | 1167 | fig.set_size_inches([20, nrows*5]) 1168 | 1169 | ax_positions[0].legend(loc='best', bbox_to_anchor=( 1170 | 1.6, 1.3), ncol=4, fontsize=14) 1171 | 1172 | return None 1173 | 1174 | def financial_evaluation(self, model_forecasts, close_prices, k=1): 1175 | ''' 1176 | Method for generating signals and backtesting the financial performance of MRF 1177 | ''' 1178 | 1179 | if isinstance(close_prices.index[0], str): 1180 | close_prices = close_prices.reset_index(drop=True) 1181 | 1182 | daily_profit = [] 1183 | 1184 | T_profit = np.arange(self.oos_pos[0] + k, self.oos_pos[-1]+1) 1185 | 1186 | for t in T_profit: 1187 | 1188 | # Produce a trading signal and calculate daily profit. 1189 | daily_profit.append(trading_strategy(model_forecasts, 1190 | stock_price=close_prices, 1191 | k=1, 1192 | t=t)) 1193 | 1194 | daily_profit = pd.Series(daily_profit) 1195 | cumulative_profit = daily_profit.cumsum() 1196 | annualised_return = get_annualised_return( 1197 | cumulative_profit, T_profit) 1198 | 1199 | sharpe_ratio = get_sharpe_ratio(daily_profit) 1200 | max_drawdown = get_max_dd_and_date( 1201 | cumulative_profit) 1202 | 1203 | # Return the output. 1204 | return daily_profit, cumulative_profit, annualised_return, sharpe_ratio, max_drawdown 1205 | 1206 | def monkey_trader_plot(self, close_prices): 1207 | 1208 | np.random.seed(1) 1209 | fig, ax = plt.subplots() 1210 | 1211 | if isinstance(close_prices.index[0], str): 1212 | close_prices = close_prices.reset_index(drop=True) 1213 | 1214 | for i in range(1, 101): 1215 | plots = self.financial_evaluation(pd.DataFrame(np.random.normal(0, 1, size=len( 1216 | self.oos_pos)), index=self.oos_pos), close_prices.loc[self.oos_pos])[1].plot(ax=ax, color='grey', label='_nolegend_') 1217 | 1218 | if i == 100: 1219 | plots = self.financial_evaluation(pd.DataFrame(np.random.normal(0, 1, size=len( 1220 | self.oos_pos)), index=self.oos_pos), close_prices.loc[self.oos_pos])[1].plot(ax=ax, color='grey', label="Monkey Traders") 1221 | 1222 | benchmark = (close_prices.loc[self.oos_pos] - close_prices.loc[self.oos_pos].shift( 1223 | 1))/close_prices.loc[self.oos_pos].shift(1) 1224 | self.financial_evaluation(self.avg_pred, close_prices)[0].cumsum().plot( 1225 | ax=ax, linewidth=3, color='green', label="MRF") 1226 | benchmark.cumsum().reset_index(drop=True).plot( 1227 | ax=ax, color='blue', linewidth=3, label='Buy and hold') 1228 | 1229 | fig.set_size_inches(18, 8) 1230 | ax.set_title("Backtested MRF trading strategy") 1231 | ax.set_ylabel("Cumulative Profit") 1232 | ax.set_xlabel(r"OOS $t$") 1233 | ax.legend(loc=2, fontsize=15) 1234 | ax.grid() 1235 | plt.show() 1236 | 1237 | def statistical_evaluation(self): 1238 | ''' 1239 | Method for evaluating statistical performance metrics, MAE and MSE, for MRF predictions 1240 | ''' 1241 | 1242 | errors = collect_errors(self.oos_pos, self.avg_pred, self.ori_y) 1243 | MAE = get_MAE(errors, self.oos_pos) 1244 | MSE = get_MSE(errors, self.oos_pos) 1245 | 1246 | return MAE, MSE 1247 | 1248 | def DV_fun(sse, DV_pref=0.25): 1249 | ''' 1250 | Implementing a middle of the range preference for middle of the range splits. 1251 | 1252 | Args: 1253 | sse (np.array): Sum of Squared Errors obtained from split-sample OLS. 1254 | DV_pref (float): Parameter controlling the rate of down-voting. 1255 | ''' 1256 | 1257 | seq = np.arange(1, len(sse)+1) 1258 | down_voting = 0.5*seq**2 - seq 1259 | down_voting = down_voting/np.mean(down_voting) 1260 | down_voting = down_voting - min(down_voting) + 1 1261 | down_voting = down_voting**DV_pref 1262 | 1263 | return sse*down_voting 1264 | 1265 | 1266 | def standard(Y): 1267 | ''' 1268 | Function to standardise the data. Remember we are doing ridge. 1269 | 1270 | Args: 1271 | - Y (np.matrix): Matrix of variables to standardise. 1272 | 1273 | Returns: 1274 | - Standardised Data (dict): Including standardised matrix ("Y"), mean ("mean") and standard deviation "std" 1275 | ''' 1276 | 1277 | Y = np.matrix(Y) 1278 | size = Y.shape 1279 | mean_y = Y.mean(axis=0) 1280 | sd_y = Y.std(axis=0, ddof=1) 1281 | Y0 = (Y - np.repeat(mean_y, 1282 | repeats=size[0], axis=0)) / np.repeat(sd_y, repeats=size[0], axis=0) 1283 | 1284 | return {"Y": Y0, "mean": mean_y, "std": sd_y} 1285 | 1286 | 1287 | def collect_errors(oos_pos, actual, forecasts, k=1): 1288 | ''' 1289 | Collecting forecasting errors based on MRF forecasts and observed values of the target variable. 1290 | 1291 | Args: 1292 | - oos_pos (numpy.array): Represents OOS period of interst for statistical evaluation. Passed in automatically when MRF.statistical_evaluation() is called. 1293 | - actual (pd.Series): Actual (observed) values for the target variable over the OOS period. Passed in automatically when MRF.statistical_evaluation() is called. 1294 | - forecasts (pd.Series): k-period forecasted values for the target variable. 1295 | - k (int, default 1): Forecast horizon. 1296 | 1297 | Returns: 1298 | - errors (dict): Dictionary containing forecast errors corresponding to OOS period. 1299 | ''' 1300 | 1301 | errors = {} 1302 | 1303 | for t in oos_pos: 1304 | 1305 | actual_value = actual.loc[t+k] 1306 | forecasted_value = forecasts.loc[t] 1307 | 1308 | errors[t] = actual_value - forecasted_value 1309 | 1310 | return errors 1311 | 1312 | 1313 | def get_MAE(error_dict, oos_pos): 1314 | ''' 1315 | Calculating Mean Absolute Error (MAE) based on collected forecasting errors. 1316 | 1317 | Args: 1318 | - error_dict (dict): List of forecasting errors obtained via collect_errors() 1319 | - oos_pos (numpy.array): Time indices of OOS period 1320 | 1321 | Returns: 1322 | - MAE (float) 1323 | 1324 | ''' 1325 | abs_errors = map(abs, list(error_dict.values())) 1326 | sum_abs_errors = sum(abs_errors) 1327 | return (1/len(oos_pos))*sum_abs_errors 1328 | 1329 | 1330 | def get_MSE(error_dict, oos_pos): 1331 | ''' 1332 | Calculating Mean Squared Error (MSE) based on collected forecasting errors. 1333 | 1334 | Args: 1335 | - error_dict (dict) 1336 | - oos_pos (numpy.array) 1337 | 1338 | Returns: 1339 | - MSE (float) 1340 | 1341 | ''' 1342 | errors_as_array = np.array(list(error_dict.values())) 1343 | sum_squared_errors = sum(np.power(errors_as_array, 2)) 1344 | return (1/len(oos_pos))*sum_squared_errors 1345 | 1346 | 1347 | def get_sharpe_ratio(daily_profit): 1348 | ''' 1349 | Calculating Sharpe Ratio financial return metric. 1350 | 1351 | Args: 1352 | 1353 | - daily_profit (pd.Series): Series corresponding to daily profit values obtained from financial_evaluation() and trading_strategy() functions 1354 | 1355 | Returns: 1356 | - sharpe_ratio (float): Sharpe Ratio corresponding to OOS period 1357 | 1358 | ''' 1359 | mean = daily_profit.mean() 1360 | std_dev = daily_profit.std() 1361 | return 252**(0.5)*mean/std_dev 1362 | 1363 | 1364 | def get_max_dd_and_date(cumulative_profit): 1365 | ''' 1366 | Calculating Maximum Drawdown financial return metric. 1367 | 1368 | Args: 1369 | - cumulative_profit (pd.Series): Series corresponding to cumulative profit values obtained from financial_evaluation() and trading_strategy() functions 1370 | 1371 | Returns: 1372 | - drawdown (float): Maximum Drawdown metric corresponding to OOS period 1373 | ''' 1374 | 1375 | rolling_max = (cumulative_profit+1).cummax() 1376 | period_drawdown = ( 1377 | ((1+cumulative_profit)/rolling_max) - 1).astype(float) 1378 | drawdown = round(period_drawdown.min(), 3) 1379 | return drawdown 1380 | 1381 | 1382 | def get_annualised_return(cumulative_profit, T_profit): 1383 | ''' 1384 | Calculating Annualised Return financial return metric. 1385 | 1386 | Args: 1387 | 1388 | - cumulative_profit (pandas.Series): Series corresponding to cumulative profit values obtained from financial_evaluation() and trading_strategy() functions. 1389 | - T_profit: Time indices corresponding to profit-generating period. Note this starts k days after OOS start, since we need a previous signal to generate profit! 1390 | 1391 | Returns: 1392 | - annualised_return (float): Yearly profit earned over OOS period 1393 | ''' 1394 | return cumulative_profit.iloc[-1]*(252/len(T_profit)) 1395 | 1396 | 1397 | def trading_strategy(model_forecasts, stock_price, t, k=1): 1398 | ''' 1399 | 1400 | Strategy for generating binary (long/short) trading signals based on MRF predictions. This strategy is agnostic to the forecast-horizon used. 1401 | 1402 | Args: 1403 | - forecasts (pd.Series): k-period forecasted values for the target variable. 1404 | - stock_price (pd.Series): Series of stock prices corresponding to target variable (returns) during same OOS period. 1405 | - k (int, default 1): Forecast horizon. 1406 | 1407 | Returns: 1408 | - PL_t (pd.Series): Backtested daily profit corresponding to implementing MRF trading signals. 1409 | 1410 | ''' 1411 | PL_t = 0 1412 | signal_t_minus_1 = 0 1413 | 1414 | # Long if return prediction > 0 ; otherwise short. 1415 | 1416 | for i in range(1, k+1): 1417 | if model_forecasts.loc[t-i].values > 0: 1418 | signal_t_minus_1 += 1 1419 | elif model_forecasts.loc[t-i].values < 0: 1420 | signal_t_minus_1 -= 1 1421 | 1422 | PL_t += (1/k)*signal_t_minus_1 * \ 1423 | ((stock_price.loc[t] - stock_price.loc[t-1])/stock_price.loc[t-1]) 1424 | 1425 | return PL_t 1426 | -------------------------------------------------------------------------------- /MacroRandomForest/README.md: -------------------------------------------------------------------------------- 1 | # MacroRandomForest 2 | 3 | 4 | --------------------------------------------------------------------------------------------------------------------------------- 5 | *"Machine Learning is useful for macroeconomic forecasting but not so useful for macroeconomics" - Philippe Goulet Coulombe* 6 | ------------------------------------------------------------------------------------------------------------------------------- 7 | ![MRF_logo_2](https://user-images.githubusercontent.com/55145311/156574873-e72ef942-6979-4639-9089-9b2e06f7a80e.svg) 8 | 9 | Ever wanted the power of a Random Forest with the interpretability of a Linear Regression model? Well now you can... 10 | 11 | This code base is the official open-source Python implementation of "The Macroeconomy as a Random Forest (MRF)" by Philippe Goulet Coulombe. MRF is a time series modification of the canonical Random Forest Machine Learning algorithm. It uses a Random Forest to flexibly model time-varying parameters in a linear macro equation. This means that, unlike most Machine Learning methods, MRF is directly interpretable via its main output - what are known as Generalised Time Varying Parameters (GTVPs). 12 | 13 | The model has also shown forecasting gains over numerous alternatives and across many time series datasets. It is well suited to macroeconomic forecasting, but there are also many possible extensions to quantitative finance, or any other field of science with time series data. The full paper corresponding to the implementation can be found here: https://arxiv.org/abs/2006.12724 14 | 15 | -------------------------------------------------------------------------------- /MacroRandomForest/__init__.py: -------------------------------------------------------------------------------- 1 | from .MRF import * 2 | -------------------------------------------------------------------------------- /MacroRandomForest/__pycache__/MRF.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/MacroRandomForest/__pycache__/MRF.cpython-310.pyc -------------------------------------------------------------------------------- /MacroRandomForest/__pycache__/MRF.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/MacroRandomForest/__pycache__/MRF.cpython-311.pyc -------------------------------------------------------------------------------- /MacroRandomForest/__pycache__/MRF.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/MacroRandomForest/__pycache__/MRF.cpython-38.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MacroRandomForest 2 | 3 | We documented this package in much more detail at: https://mrf-web.readthedocs.io/en/latest/index.html. 4 | 5 | --------------------------------------------------------------------------------------------------------------------------------- 6 | *"Machine Learning is useful for macroeconomic forecasting but not so useful for macroeconomics" - Philippe Goulet Coulombe* 7 | ------------------------------------------------------------------------------------------------------------------------------- 8 | ![MRF_logo_2](https://user-images.githubusercontent.com/55145311/156574873-e72ef942-6979-4639-9089-9b2e06f7a80e.svg) 9 | 10 | # How it works 11 | 12 | Random forest is an extremely popular algorithm because it allows for complex nonlinearities, handles high-dimensional data, bypasses overfitting, and requires little to no tuning. However, while random forest gladly delivers gains in prediction accuracy (and ergo a conditional mean closer to the truth), it is much more reluctant to disclose its inherent model. 13 | 14 | MRF shifts the focus of the forest away from predicting $y_t$ into modelling $\beta_t$, which are the economically meaningful coefficients in a time-varying linear macro equation. More formally: 15 | 16 | $$y_t = X_t \beta_t + \varepsilon_t$$ 17 | 18 | $$\beta_t = \mathcal{F}(S_t)$$ 19 | 20 | Where $S_t$ are the state variables governing time variation and $\mathcal{F}$ is a forest. $X_t$ is typically a subset of $S_t$ which we want to emphasize and for which associated coefficients may be of economic interest. There are interesting special cases. For instance, $X_t$ could use lags of $y_t$ -- an autoregressive random forest (ARRF) – which will outperform RF when applied to persistent time series. Typically $X_t \subset S_t$ is rather small (and focused) compared to $S_t$. 21 | 22 | The new algorithm comes with some benefits. First, it can be interpreted. Its main output, Generalized Time-Varying Parameters (GTVPs) is a versatile device nesting many popular nonlinearities (threshold/switching, smooth transition, structural breaks/change). In the end, we simply get a linear equation with time-varying coefficients following a very general law of motion. The latter is powered by a large data set, and an algorithm particularly apt with complex nonlinearities and high-dimensionality. 23 | 24 | By striking an appealing balance of efficiency and flexibility, it forecasts better. Most ML algorithms are designed for large cross-sectional data sets, whereas macroeconomics is characterized by short dependent time series. If persistence (or any other linear relationship) is pervasive, important efficiency gains ensue from modeling them directly. When measured against econometric approaches, MRF can again perform better, but now by being less rigid about $\beta_t$'s law of motion and avoiding overfitting. 25 | -------------------------------------------------------------------------------- /__pycache__/MRF.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/__pycache__/MRF.cpython-38.pyc -------------------------------------------------------------------------------- /__pycache__/MRF_2.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/__pycache__/MRF_2.cpython-38.pyc -------------------------------------------------------------------------------- /__pycache__/MRF_non_random.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/__pycache__/MRF_non_random.cpython-38.pyc -------------------------------------------------------------------------------- /__pycache__/MRF_random.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/__pycache__/MRF_random.cpython-38.pyc -------------------------------------------------------------------------------- /dist/MacroRandomForest-1.0.5-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/dist/MacroRandomForest-1.0.5-py3-none-any.whl -------------------------------------------------------------------------------- /dist/MacroRandomForest-1.0.5.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RyanLucas3/MacroRandomForest/8069107d6e1f92e8ef9fade782dfda97f8bd66d8/dist/MacroRandomForest-1.0.5.tar.gz -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_build = 3 | tag_date = 0 4 | 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | # How you named your package folder (MyLib) 5 | name='MacroRandomForest', 6 | packages=['MacroRandomForest'], # Chose the same as "name" 7 | # Start with a small number and increase it with every change you make 8 | version='1.0.5', 9 | # Chose a license from here: https://help.github.com/articles/licensing-a-repository 10 | license='MIT', 11 | # Give a short description about your library 12 | description='Macroeconomic Random Forest by Ryan Lucas (code) and Philippe Goulet Coulombe (method)', 13 | author='', # Type in your name 14 | author_email='ryanlu@mit.edu', # Type in your E-Mail 15 | # Provide either the link to your github or to your website 16 | url='https://github.com/RyanLucas3/MacroRandomForest', 17 | # I explain this later on 18 | download_url='https://github.com/RyanLucas3/MacroRandomForest/archive/refs/tags/1.0.5.tar.gz', 19 | # Keywords that define your package best 20 | keywords=['Time Series', 'Forecasting', 'Economics', 21 | "Macro", "Machine Learning", "RandomForest"], 22 | install_requires=[ 23 | 'numpy', 24 | 'pandas', 25 | 'matplotlib', 26 | 'joblib', 27 | ], 28 | classifiers=[ 29 | # Chose either "3 - Alpha", "4 - Beta" or "5 - Production/Stable" as the current state of your package 30 | 'Development Status :: 3 - Alpha', 31 | # Define that your audience are developers 32 | 'Intended Audience :: Developers', 33 | 'Topic :: Software Development :: Build Tools', 34 | 'License :: OSI Approved :: MIT License', # Again, pick a license 35 | # Specify which pyhton versions that you want to support 36 | 'Programming Language :: Python :: 3', 37 | 'Programming Language :: Python :: 3.4', 38 | 'Programming Language :: Python :: 3.5', 39 | 'Programming Language :: Python :: 3.6', 40 | 'Programming Language :: Python :: 3.7', 41 | 'Programming Language :: Python :: 3.8', 42 | ], 43 | ) 44 | --------------------------------------------------------------------------------