我的暴力和搜索的表现是
我知道递归搜索会受到尾端优化问题的影响。 (现在我至少做了),但我仍然不确定为什么迭代二进制搜索仍然比我的蛮力慢。
这是我的代码,它不是最优化的,但它不应该慢。 迭代和递归只做6-7循环(我忘了) 蛮力一直有100个循环。
我做了一些谷歌搜索,无法弄明白。
data = [[0.1430903741309869,0.09099423635474843], [0.14312849662493274,0.09181153207084017], [0.1432428032314926,0.09262882778693171], [0.14343311180983973,0.09344612350302323], [0.1436991203996287,0.09426341921911474], [0.14404040960138637,0.09508071493520626], [0.14445644584780032,0.09589801065129779], [0.14494658550706505,0.09671530636738929], [0.1455100797459424,0.09753260208348079], [0.14614608006894764,0.09834989779957232], [0.14685364444133878,0.09916719351566383], [0.14763174389751746,0.09998448923175535], [0.1484792695330778,0.10080178494784686], [0.14939503977798488,0.10161908066393838], [0.15037780785006197,0.10243637638002989], [0.15142626929185626,0.10325367209612141], [0.15253906949973353,0.10407096781221292], [0.15371481116136612,0.10488826352830445], [0.15495206152626528,0.10570555924439595], [0.15624935944329402,0.10652285496048747], [0.15760522210883443,0.10734015067657898], [0.15901815147914886,0.10815744639267053], [0.16048664031018645,0.108974742108762], [0.16200917779740737,0.10979203782485353], [0.16358425479693292,0.11060933354094506], [0.16520993331004336,0.11142662925703659], [0.16688422700115874,0.11224392497312807], [0.16860568677181428,0.1130612206892196], [0.1703728829197052,0.11387851640531109], [0.17218440721942158,0.11469581212140262], [0.17403885930131519,0.11551310783749413], [0.17593071292964196,0.11633040355358565], [0.1778550568320067,0.11714769926967716], [0.17980807653937597,0.11796499498576866], [0.18178758544173265,0.1187822907018602], [0.1837924906630262,0.11959958641795171], [0.1858218126363723,0.12041688213404322], [0.18787312997972483,0.12123417785013477], [0.18994445911670263,0.12205147356622625], [0.19203401732136283,0.12286876928231774], [0.19414001047365512,0.12368606499840928], [0.19626134953048857,0.12450336071450081], [0.19839732373336172,0.12532065643059231], [0.20054614597911763,0.12613795214668383], [0.2027102188697154,0.12695524786277534], [0.20489645895038736,0.12777254357886683], [0.2071056985959593,0.1285898392949584], [0.20933725029121888,0.12940713501104992], [0.21159043799410046,0.1302244307271414], [0.21386545662534603,0.13104172644323292], [0.21616695565805766,0.13185902215932443], [0.21849602526410672,0.13267631787541595], [0.22085249758957576,0.13349361359150747], [0.2232371638584028,0.13431090930759898], [0.22565048466368387,0.13512820502369052], [0.2280915992825535,0.135945500739782], [0.23055962489233886,0.1367627964558735], [0.23305452139473087,0.13758009217196507], [0.2355792572479964,0.13839738788805653], [0.23813358220882275,0.13921468360414807], [0.24071656074747425,0.14003197932023959], [0.2433273963640586,0.14084927503633107], [0.24596524486026825,0.14166657075242262], [0.24863017456672842,0.14248386646851413], [0.2513289284728739,0.14330116218460567], [0.25406210594271644,0.1441184579006972], [0.2568286079689279,0.14493575361678868], [0.2596274973065834,0.1457530493328802], [0.2624581900808146,0.1465703450489717], [0.26531970812660205,0.1473876407650632], [0.26821106483019097,0.14820493648115474], [0.2711313055908074,0.14902223219724625], [0.27407950715527424,0.14983952791333777], [0.27705477691361224,0.15065682362942928], [0.2800562521635541,0.15147411934552082], [0.2830830993510777,0.15229141506161228], [0.2861345132933103,0.15310871077770383], [0.28920971638943616,0.15392600649379534], [0.2923206802678723,0.15474330220988686], [0.2954949457497638,0.1555605979259784], [0.29873543145269177,0.1563778936420699], [0.3020880630603759,0.1571951893581614], [0.30556924631118587,0.15801248507425292], [0.3091771242381686,0.15882978079034443], [0.31290731443442327,0.15964707650643595], [0.31680077310414406,0.1604643722225275], [0.3209282297369517,0.161281667938619], [0.3252820737446184,0.16209896365471044], [0.3298533407620746,0.162916259370802], [0.33463312056489414,0.16373355508689355], [0.33964400822398905,0.16455085080298504], [0.3449710651721094,0.16536814651907655], [0.35075611759025743,0.16618544223516807], [0.35753250940611797,0.16700273795125958], [0.3659658404474907,0.1678200336673511], [0.3759506203869174,0.1686373293834426], [0.3873668972264467,0.16945462509953407], [0.40009215021923283,0.17027192081562567], [0.4140056953351241,0.17108921653171713], [0.4289919281005854,0.17190651224780865]];
var riskFreeRate = .03;
var optimalPoint = {
data: undefined,
stdDev: undefined,
ret: undefined
}
var optimalPoint3 = {
ratio: 0,
stdDev: undefined,
ret: undefined
}
// Find optimal tangent point
// sometsdf
function binaryOptimalSearch(efArray) {
var midIndex = Math.floor(efArray.length / 2);
var leftPoint = efArray[midIndex - 1];
var midPoint = efArray[midIndex];
var rightPoint = efArray[midIndex + 1];
var leftPointSharpeRatio = (leftPoint[1] - riskFreeRate) / leftPoint[0];
var midPointSharpeRatio = (midPoint[1] - riskFreeRate) / midPoint[0];
var rightPointSharpeRatio = rightPoint && ((rightPoint[1] - riskFreeRate) / rightPoint[0]);
if (efArray.length === 2) {
//rightPoint shouldn't exist.
if (leftPointSharpeRatio > midPointSharpeRatio) {
return leftPoint;
}
if (midPointSharpeRatio > leftPointSharpeRatio) {
return midPoint;
}
}
if ((midPointSharpeRatio > leftPointSharpeRatio) && (midPointSharpeRatio > rightPointSharpeRatio)) {
return midPoint;
}
if (leftPointSharpeRatio > midPointSharpeRatio) {
var leftPortion = efArray.slice(0, midIndex + 1); // add 1 to include midindex
return binaryOptimalSearch(leftPortion);
}
if (rightPointSharpeRatio > midPointSharpeRatio) {
var rightPortion = efArray.slice(midIndex, (efArray.length) );
return binaryOptimalSearch(rightPortion);
}
};
// Find optimal tangent point iterative
function binaryIterativeSearch(efArray) {
var leftIndex = 0;
var midIndex = undefined;
var rightIndex = efArray.length - 1;
var leftPoint;
var midPoint;
var rightPoint;
var leftPointSharpeRatio;
var midPointSharpeRatio;
var rightPointSharpeRatio;
while (leftIndex <= rightIndex) {
midIndex = Math.floor((leftIndex + rightIndex) / 2);
leftPoint = efArray[midIndex - 1];
midPoint = efArray[midIndex];
rightPoint = efArray[midIndex + 1];
leftPointSharpeRatio = (leftPoint[1] - riskFreeRate) / leftPoint[0];
midPointSharpeRatio = (midPoint[1] - riskFreeRate) / midPoint[0];
rightPointSharpeRatio = rightPoint && ((rightPoint[1] - riskFreeRate) / rightPoint[0]);
if ((midPointSharpeRatio > leftPointSharpeRatio) && (midPointSharpeRatio > rightPointSharpeRatio)) {
return midPoint;
}
if (leftPointSharpeRatio > midPointSharpeRatio) {
rightIndex = midIndex - 1;
}
if (rightPointSharpeRatio > midPointSharpeRatio) {
leftIndex = midIndex + 1;
}
}
}
// Brute Force
function bruteSearch(){
data.forEach(function (item) { // Find optimal tangent
var stdDev = item[0];
var ret = item[1];
var returnPerRisk = (ret - riskFreeRate) / stdDev;
if (returnPerRisk > optimalPoint3.ratio) {
optimalPoint3.ratio = returnPerRisk;
optimalPoint3.stdDev = stdDev;
optimalPoint3.ret = ret;
}
});
}
//
var timeBinary1 = performance.now();
optimalPoint.data = binaryOptimalSearch(data);
var timeBinary2 = performance.now();
console.log('Recursive Took', (timeBinary2 - timeBinary1).toFixed(4), 'milliseconds to generate:', optimalPoint.data);
optimalPoint.stdDev = optimalPoint.data[0];
optimalPoint.ret = optimalPoint.data[1];
var timeIterative1 = performance.now();
var optimalPoint2 = binaryIterativeSearch(data);
var timeIterative2 = performance.now();
console.log('Iterative Took', (timeIterative2 - timeIterative1).toFixed(4), 'milliseconds to generate:', optimalPoint2);
var timeBrute1 = performance.now();
bruteSearch();
var timeBrute2 = performance.now();
console.log('Brute Took', (timeBrute2 - timeBrute1).toFixed(4), 'milliseconds to generate:', optimalPoint3);