Last active
May 28, 2021 09:53
-
-
Save lequant40/4779fc816adabd30518a42d2e2a1b140 to your computer and use it in GitHub Desktop.
Illustration of random portfolios analysis of the Global Equities Momentum (GEM) TAA strategy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Dependencies | |
var fs = require('fs'); | |
const axios = require('axios'); | |
const { mean, std } = require('mathjs'); | |
// Definition of the risk free returns, and of the indexes prices | |
// In sample period | |
var nbPeriods = 12 * 24; // months of returns data, until 30/12/2012 | |
var rf = [0.67,0.70,0.71,0.68,0.69,0.64,0.63,0.63,0.64,0.63,0.61,0.61,0.62,0.63,0.63,0.63,0.62,0.62,0.60,0.60,0.58,0.57,0.57,0.52,0.50,0.49,0.47,0.45,0.45,0.45,0.45,0.43,0.42,0.39,0.36,0.32,0.31,0.32,0.33,0.30,0.30,0.29,0.26,0.26,0.22,0.24,0.27,0.25,0.24,0.24,0.24,0.24,0.25,0.25,0.25,0.25,0.24,0.25,0.26,0.25,0.24,0.28,0.28,0.32,0.34,0.34,0.35,0.37,0.38,0.41,0.45,0.45,0.47,0.47,0.46,0.46,0.46,0.44,0.44,0.43,0.43,0.43,0.43,0.40,0.40,0.40,0.41,0.41,0.41,0.41,0.42,0.42,0.40,0.41,0.41,0.41,0.41,0.41,0.42,0.42,0.39,0.41,0.42,0.41,0.41,0.41,0.41,0.42,0.41,0.42,0.41,0.40,0.40,0.41,0.40,0.39,0.35,0.34,0.36,0.36,0.36,0.37,0.36,0.36,0.37,0.38,0.38,0.40,0.38,0.40,0.42,0.42,0.45,0.46,0.46,0.46,0.45,0.46,0.49,0.50,0.49,0.50,0.49,0.47,0.39,0.39,0.34,0.31,0.29,0.29,0.28,0.27,0.19,0.17,0.14,0.14,0.14,0.14,0.14,0.14,0.14,0.14,0.14,0.14,0.13,0.12,0.10,0.10,0.10,0.10,0.09,0.09,0.09,0.07,0.08,0.08,0.08,0.08,0.08,0.08,0.07,0.08,0.08,0.08,0.09,0.11,0.12,0.13,0.14,0.15,0.18,0.18,0.20,0.22,0.22,0.23,0.24,0.25,0.27,0.28,0.28,0.31,0.32,0.33,0.36,0.37,0.37,0.38,0.38,0.40,0.40,0.40,0.39,0.40,0.40,0.40,0.41,0.41,0.40,0.39,0.37,0.38,0.39,0.33,0.30,0.31,0.25,0.26,0.15,0.15,0.11,0.11,0.15,0.14,0.14,0.14,0.07,0.04,0.00,0.01,0.02,0.02,0.02,0.01,0.01,0.01,0.01,0.01,0.01,0.00,0.00,0.00,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.00,0.00,0.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00,0.01,0.01,0.01,0.00,0.01,0.01,0.01,0.01,0.01,0.01,0.00]; | |
var sp500 = [623.3995,669.0499,652.3768,667.5958,702.2576,730.6697,726.5255,792.1243,807.6097,804.3327,785.6563,801.6791,820.9313,765.817,775.6812,796.2353,776.371,852.0712,846.3231,843.6089,767.3546,730.0109,726.9019,773.8895,795.4476,830.0895,889.4537,910.9924,913.1483,952.5422,908.9025,951.2658,973.8032,957.5067,970.3799,931.2808,1037.787,1018.448,1031.638,1011.574,1041.275,1046.379,1030.812,1072.923,1050.965,1063.314,1066.988,1103.319,1116.86,1126.197,1141.547,1165.632,1137.458,1167.885,1171.306,1166.594,1210.859,1201.572,1226.428,1214.738,1229.425,1271.222,1236.718,1182.801,1197.969,1217.629,1187.782,1226.786,1277.083,1245.854,1273.843,1227.452,1245.659,1277.963,1327.767,1366.946,1407.198,1463.44,1497.432,1547.091,1550.981,1616.436,1610.658,1681.363,1713.75,1772.079,1788.509,1805.724,1832.347,1879.602,1886.772,1803.415,1841.456,1945.102,1998.75,2149.829,2107.23,2238.881,2256.428,2163.715,2292.885,2432.485,2541.465,2743.683,2589.977,2731.821,2640.585,2762.825,2810.273,2841.357,3046.29,3202.286,3234.503,3178.909,3308.033,3272.807,2799.633,2978.98,3221.295,3416.531,3613.409,3764.508,3647.511,3793.443,3940.345,3847.3,4060.816,3934.018,3914.555,3807.242,4048.167,4130.458,4373.726,4153.979,4075.346,4474.033,4339.428,4250.396,4355.181,4287.092,4553.382,4312.994,4294.759,3956.163,3975.525,4116.573,3741.217,3504.21,3776.524,3801.825,3709.294,3672.779,3442.857,3164.838,3225.188,3472.58,3503.001,3451.881,3385.311,3512.63,3299.666,3275.357,3042.054,2804.913,2823.329,2516.491,2737.982,2899.137,2728.82,2657.33443,2617.464,2642.878,2860.572,3011.289,3049.702,3103.473,3163.997,3130.397,3307.48331,3336.583,3511.569,3576.024,3625.729,3571.03,3514.972,3563.206,3632.492,3512.269,3526.476,3564.67,3619.127,3765.563,3893.7,3798.792,3878.734,3810.049,3737.789,3856.72,3862.195,4005.824,3969.275,4001.423,3934.717,4083.536,4084.957,4193.118,4204.495,4256.831,4313.991,4189.828,4195.508,4221.388,4321.828,4433.201,4577.662,4664.71107,4730.146,4801.681,4707.766,4760.422,4971.287,5144.76,5059.289,4902.426,4975.914,5162.007,5244.119,5024.87981,4990.019,4690.70958,4538.3283,4518.73203,4738.80845,4800.18829,4395.51533,4358.56592,4421.61116,4027.61324,3351.18396,3110.72125,3143.82018,2878.8388,2572.30647,2797.62814,3065.38748,3236.84362,3243.26432,3488.57614,3614.52854,3749.40514,3679.75218,3900.47657,3975.81619,3832.7913,3951.52025,4189.97442,4256.12449,3916.26963,3711.25985,3971.28199,3792.00161,4130.41771,4287.57661,4288.1264,4574.70788,4683.13573,4843.5757,4845.50234,4989.00335,4932.53007,4850.30906,4751.67978,4493.55933,4177.66739,4634.25768,4624.01613,4671.31563,4880.66,5091.71,5259.28,5226.26,4912.16,5114.55,5185.59,5302.38,5439.41,5338.97,5369.94,5418.89]; | |
var acwiexus = [127.897,130.435,131.020,128.777,130.407,123.755,121.435,136.405,130.740,136.774,131.766,138.101,143.286,137.913,128.751,115.699,114.718,127.413,126.361,128.387,116.154,100.671,115.122,108.723,110.708,114.168,126.430,119.472,120.770,122.485,113.966,119.442,117.391,123.364,125.521,119.930,126.156,124.398,120.578,113.286,113.658,120.559,114.741,112.300,118.289,115.862,110.774,111.387,112.317,112.304,115.741,125.271,136.336,139.371,137.703,142.280,149.916,146.834,152.145,140.558,151.521,163.982,162.742,155.288,160.556,160.610,161.749,164.379,169.910,165.704,170.158,161.950,161.571,154.243,153.399,162.066,168.388,167.644,165.325,174.713,168.651,171.533,166.950,170.871,177.627,180.067,180.074,183.426,188.991,186.153,187.097,180.877,181.938,186.456,184.589,191.710,189.490,186.009,189.420,189.023,190.617,202.391,213.558,217.882,200.742,211.595,193.580,191.161,193.361,199.145,212.433,219.773,221.347,217.333,216.516,218.574,187.750,183.784,203.035,213.946,221.317,221.080,216.130,226.565,237.897,226.723,237.141,242.703,243.545,245.192,254.322,264.491,289.716,273.995,281.396,291.986,275.689,268.637,280.075,269.018,272.345,257.238,249.062,237.888,246.012,249.702,229.933,213.680,228.213,221.911,213.400,208.652,203.470,181.884,186.980,195.532,198.051,189.569,190.934,201.306,202.614,204.821,195.977,176.878,176.889,158.144,166.628,174.641,168.999,163.066,159.762,156.663,171.759,182.701,187.758,192.761,198.505,204.063,217.291,222.029,238.980,242.818,248.992,250.524,242.738,243.506,248.784,241.534,243.468,251.296,260.036,278.085,290.025,285.030,299.089,290.976,283.800,285.578,290.953,301.688,309.409,325.369,313.524,324.065,339.657,363.339,362.290,372.813,392.036,373.962,373.589,377.411,388.108,388.360,404.174,418.848,431.901,433.514,436.163,448.452,469.248,482.110,486.216,484.830,477.386,508.999,537.411,513.263,505.844,456.899,470.140,460.002,488.311,496.773,456.055,439.745,419.293,356.439,277.992,262.025,277.004,252.589,229.094,247.589,281.638,320.189,316.757,347.820,360.762,379.369,374.703,385.527,393.734,374.538,374.591,400.267,397.014,355.668,351.198,383.009,372.564,409.715,423.712,407.453,439.420,443.820,455.606,454.742,477.304,464.083,457.500,451.402,412.807,367.011,405.712,385.099,380.862,406.785,429.752,424.057,417.750,370.743,392.775,398.444,406.864,422.207,423.900,432.033,447.090]; | |
var agg = [346.81,351.8,349.25,350.76,358.1,367.51,378.7,386.75,381.02,382.97,392.4,396.14002,397.2,392.48,393.75,394.04,390.43,401.99,408.44,414.09,408.56,411.94,417.17,426.15,432.79,438.14002,441.88,444.92,449.74,452.37,452.14002,458.41,468.33,477.82,483.14002,487.57,502.05,495.22,498.44205,495.634,499.2102,508.63065,515.62921,526.15384,531.47971,537.78497,530.65054,530.7717,539.21249,549.55322,559.16611,561.50494,565.41019,566.12698,576.38586,579.64517,589.81146,591.43094,593.63797,588.59106,591.78113,599.77118,589.35101,574.81918,570.22952,570.15073,568.88913,580.19196,580.9082,572.35922,571.84644,570.57864,574.5239,585.89441,599.82275,603.50021,611.93335,635.61322,640.27185,638.84332,646.54547,652.83978,661.32782,671.23572,680.66003,685.17505,673.26813,668.58618,664.82788,663.48157,672.39386,674.23346,673.10425,684.82593,700.00281,711.9931,705.37195,707.52862,709.28662,701.42535,711.9328,718.66138,727.19434,746.79504,740.43176,751.35474,762.25391,765.76251,773.46826,783.39697,782.80725,785.50061,789.60333,797.08978,803.85168,805.55756,818.66925,837.83563,833.41528,838.13538,840.6557,846.66034,831.87775,836.49329,839.14484,831.79176,829.13535,825.61287,825.19353,834.76928,837.84902,837.79081,833.75123,831.0236,841.07244,852.14575,849.71399,849.32393,866.99273,874.86218,887.54492,893.12402,899.02605,913.72995,930.68371,945.89653,954.13827,958.92641,954.94593,960.71446,964.33876,985.8983,997.19485,1008.8095,1029.9243,1015.72291,1009.26574,1017.43698,1027.29635,1010.21012,1029.80134,1038.54974,1047.53423,1060.16996,1078.06725,1095.53103,1090.53652,1090.24871,1112.76624,1113.71764,1129.13491,1128.26161,1137.57416,1158.78408,1156.48216,1117.60098,1125.01823,1154.79652,1144.03393,1146.76954,1158.43914,1167.76127,1180.3969,1189.24461,1158.298,1153.66096,1160.17932,1171.68056,1194.03308,1197.27043,1207.30916,1197.67942,1208.70134,1216.28535,1209.11182,1202.8963,1219.17543,1232.36524,1239.08557,1227.81498,1243.55492,1230.73515,1220.99908,1226.402,1238.05504,1238.13074,1242.23595,1230.04824,1227.82133,1226.50593,1229.10906,1245.72587,1264.79881,1275.90935,1284.35098,1299.25273,1291.70944,1291.17637,1311.08714,1311.12944,1318.20028,1308.20503,1304.33783,1315.2191,1331.34018,1341.43752,1353.48862,1377.82675,1381.69797,1404.91275,1406.85741,1411.65556,1408.70783,1398.37578,1397.25488,1396.11315,1409.35757,1390.42946,1357.60958,1401.7982,1454.10222,1441.26825,1435.82593,1455.78612,1462.75395,1473.35995,1481.73512,1505.64069,1521.22977,1537.21314,1544.80486,1564.8022,1540.33634,1563.86934,1569.70752,1567.78,1584.10312,1597.42663,1622.47682,1639.79488,1660.89162,1662.66406,1668.58055,1658.98991,1641.10069,1643.0068,1647.11813,1648.02831,1668.95132,1690.73432,1685.78182,1712.53319,1737.55445,1750.19081,1752.07489,1750.55213,1769.79278,1785.3252,1784.91797,1775.13784,1794.82235,1811.05937,1811.76984,1836.7616,1837.96393,1840.48593,1844.10607,1847.01657,1844.38656]; | |
// Out of sample period | |
//var nbPeriods = 93; // months of returns data, from 01/01/2013 to 31/10/2020 | |
//var rf = [0.01,0.01,0.01,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.01,0.01,0.01,0.02,0.03,0.02,0.02,0.02,0.02,0.03,0.02,0.02,0.04,0.04,0.04,0.04,0.05,0.06,0.08,0.08,0.09,0.08,0.09,0.09,0.10,0.10,0.11,0.12,0.13,0.15,0.15,0.16,0.16,0.17,0.18,0.19,0.19,0.19,0.20,0.19,0.20,0.20,0.19,0.17,0.17,0.16,0.15,0.12,0.13,0.13,0.12,0.13,0.09,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01]; | |
//var sp500 = [5699.56,5776.93,5993.59,6109.06,6251.96,6168.01,6481.86,6294.14,6491.52,6789.92,6996.83,7173.97,6925.93,7242.75,7303.63,7357.62,7530.33,7685.89,7579.90,7883.13,7772.58,7962.43,8176.57,8155.98,7911.14,8365.81,8233.50,8312.49,8419.38,8256.40,8429.38,7920.81,7724.82,8376.44,8401.35,8268.84,7858.51,7847.90,8380.29,8412.78,8563.86,8586.05,8902.60,8915.10,8916.79,8754.14,9078.34,9257.79,9433.38,9807.94,9819.38,9920.22,10059.83,10122.62,10330.76,10362.39,10576.15,10822.94,11154.88,11278.91,11924.67,11485.16,11193.29,11236.24,11506.83,11577.65,12008.50,12399.80,12470.38,11618.02,11854.78,10784.40,11648.62,12022.63,12256.26,12752.51,11942.11,12783.74,12967.48,12762.07,13000.85,13282.44,13764.58,14180.02,14174.46,13007.63,11401.02,12862.57,13475.18,13743.17,14518.08,15561.64,14970.35,14572.24]; | |
//var acwiexus = [465.356,460.545,461.691,479.114,468.468,448.306,468.037,461.674,493.882,512.063,513.028,517.641,494.197,519.154,520.809,528.063,538.871,548.143,542.835,545.940,519.677,514.585,518.373,499.859,499.185,525.938,517.827,544.340,536.319,521.578,520.242,480.568,458.469,492.650,482.544,473.599,441.442,436.530,472.348,485.195,477.473,470.438,493.811,497.029,503.377,496.193,484.780,497.346,515.010,523.300,537.046,548.864,567.243,569.237,590.367,593.587,604.829,616.279,621.372,635.454,670.904,639.380,628.601,639.159,625.054,613.572,628.432,615.402,618.464,568.229,573.696,547.933,589.425,601.022,605.110,621.551,588.860,624.610,617.254,598.314,614.001,635.508,641.206,669.191,651.291,599.900,513.510,552.760,571.130,597.192,624.082,650.916,635.175,621.621]; | |
//var agg = [1831.4869,1840.6713,1842.13979,1860.78446,1827.57711,1799.31218,1801.77106,1792.55603,1809.52672,1824.15524,1817.33237,1807.06176,1833.76207,1843.50773,1840.36778,1855.90279,1877.0275,1877.99718,1873.28602,1893.9676,1881.11385,1899.60057,1913.07631,1914.86554,1955.01875,1936.63691,1945.62976,1938.64861,1933.97976,1912.8924,1926.18918,1923.42311,1936.43366,1936.75521,1931.63877,1925.39644,1951.892,1965.739,1983.774,1991.389,1991.9,2027.69,2040.509,2038.176,2036.982,2021.401,1973.587,1976.371,1980.249,1993.558,1992.513,2007.889,2023.344,2021.308,2030.006,2048.214,2038.459,2039.64,2037.022,2046.371,2022.803,2003.628,2016.477,2001.48,2015.764,2013.285,2013.763,2026.721,2013.67,1997.757,2009.683,2046.603,2068.337,2067.139,2106.832,2107.371,2144.78,2171.715,2176.491,2232.888,2220.996,2227.686,2226.551,2225,2267.819,2308.636,2295.05,2335.847,2346.723,2361.505,2396.779,2377.433,2376.129,2365.519]; | |
// Compute asynchronously the Sharpe Ratios for nbPortfolios randomly-rebalanced portfolios made of | |
// the three indexes SP500, ACWI ex-US and Barclays Capital US Aggregate Bond. | |
async function computeRandomPortfolioSharpeRatios(nbPortfolios) { | |
// Compute random portfolios rebalanced at each period (= monthly rebalancing) | |
var response; | |
try { | |
// | |
const url = "https://api.portfoliooptimizer.io/v1/portfolio/simulation/rebalancing/random-weight"; | |
// | |
const data = { | |
assets: 3, | |
portfolios: nbPortfolios, | |
assetsPrices: [sp500, acwiexus, agg] | |
}; | |
// | |
const axiosConfig = { | |
headers: { | |
'Content-Type': 'application/json', | |
// 'X-API-Key': '', // Optional | |
'Accept-Encoding': 'gzip' | |
} | |
}; | |
// | |
response = await axios.post(url, data, axiosConfig); | |
} catch (error) { | |
// It would be needed to catch HTTP 429 error here | |
throw new Error(error); | |
} | |
// For each random portfolio... | |
var sharpeRatios = new Array(nbPortfolios); | |
for (var i = 0; i < nbPortfolios; ++i) { | |
// ... compute the random portfolio monthly excess return for each period | |
var randomPortfolioExcessReturns = new Array(nbPeriods); | |
for (var j = 0; j < nbPeriods; ++j) { | |
// Compute the portfolio return for the period | |
var portfolioReturn = (response.data.portfolios[i].portfolioValues[j+1] - response.data.portfolios[i].portfolioValues[j])/response.data.portfolios[i].portfolioValues[j]; | |
// Compute the portfolio excess return for the period | |
randomPortfolioExcessReturns[j] = portfolioReturn - rf[j]/100; | |
} | |
// ... compute the average portfolio excess return | |
var portfolioAverageExcessReturn = mean(randomPortfolioExcessReturns); | |
// ... compute the volatility of portfolio excess returns | |
var portfolioVolatilityExcessReturn = std(randomPortfolioExcessReturns, 'uncorrected'); | |
// ... compute the Sharpe ratio of the portfolio | |
sharpeRatios[i] = portfolioAverageExcessReturn / portfolioVolatilityExcessReturn; | |
} | |
// Return the computed Sharpe Ratios | |
return sharpeRatios; | |
} | |
// Will hold the Sharpe Ratios of the random portfolios | |
sharpeRatios = []; | |
// Start the asynchronous computation of the Sharpe Ratios of the random portfolios | |
sharpeRatiosPromises = []; | |
var nbBatches = 100; // Will generate 100 * 100 = 10,000 portfolios | |
for (var i = 0; i < nbBatches; ++i) { | |
sharpeRatiosPromises.push(computeRandomPortfolioSharpeRatios(100)); | |
} | |
// Wait until all the Sharpe Ratios of the random portfolios have been computed | |
Promise.all(sharpeRatiosPromises).then(function (results) { | |
// | |
console.log("All done") | |
// Merge all the Sharpe Ratios | |
var idx = 0; | |
for (var i = 0; i < results.length; ++i) { | |
for (var j = 0; j < results[i].length; ++j) { | |
sharpeRatios[idx] = results[i][j] * Math.sqrt(12); // annualized | |
++idx; | |
} | |
} | |
// Save the Sharpe Ratios into a file for further processing | |
var file = fs.createWriteStream('/tmp/sr.txt'); | |
file.on('error', function(err) { /* error handling */ }); | |
sharpeRatios.forEach(function(e) { file.write(e + '\n'); }); | |
file.end(); | |
}).catch(error => { | |
console.log(error) | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment