/** * @covers EfficientRiskyAssetPortfolio::performanceIncreasingPortfolio */ void EfficientRiskyAssetPortfolioTest::testEfficientPortfolio() { _createReturnStatistics(); EfficientRiskyAssetPortfolio model(*_mean, *_variance); { // more than mvp return Eigen::VectorXd ep = model.efficientPortfolio(0.1); CPPUNIT_ASSERT_DOUBLES_EQUAL(28.0 / 97.0, ep.coeff(0), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(41.0 / 97.0, ep.coeff(1), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(28.0 / 97.0, ep.coeff(2), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.1, model.portfolioReturn(ep), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(192.0 / 2425.0, model.portfolioVariance(ep), EPSILON); } { // less than mvp return, i.e. mvp is the efficient portfolio Eigen::VectorXd ep = model.efficientPortfolio(0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL(-24.0 / 70.0, ep.coeff(0), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(51.0 / 70.0, ep.coeff(1), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(43.0 / 70.0, ep.coeff(2), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(73.0 / 1400.0, model.portfolioReturn(ep), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(23.0 / 875.0, model.portfolioVariance(ep), EPSILON); } _destroyReturnStatistics(); }
/** * @covers EfficientRiskyAssetPortfolio::performanceIncreasingPortfolio */ void EfficientRiskyAssetPortfolioTest::testPerformanceIncreasingPortfolio() { _createReturnStatistics(); EfficientRiskyAssetPortfolio model(*_mean, *_variance); Eigen::VectorXd pip = model.performanceIncreasingPortfolio(); CPPUNIT_ASSERT_DOUBLES_EQUAL(1280.0 / 97.0, pip.coeff(0), 1e-14); CPPUNIT_ASSERT_DOUBLES_EQUAL(-620.0 / 97.0, pip.coeff(1), 1e-14); CPPUNIT_ASSERT_DOUBLES_EQUAL(-660.0 / 97.0, pip.coeff(2), 1e-14); _destroyReturnStatistics(); }
/** * @covers EfficientPortfolioWithRisklessAssetTest::performanceIncreasingPortfolio */ void EfficientPortfolioWithRisklessAssetTest::testPerformanceIncreasingPortfolio() { _createReturnStatistics(); EfficientPortfolioWithRisklessAsset model(0.04, *_mean, *_variance); Eigen::VectorXd pip = model.performanceIncreasingPortfolio(); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, pip.coeff(0), 1e-14); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, pip.coeff(1), 1e-14); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, pip.coeff(2), 1e-14); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, pip.coeff(3), 1e-14); _destroyReturnStatistics(); }
/** * @covers EfficientRiskyAssetPortfolio::minimumVariancePortfolio * @covers EfficientRiskyAssetPortfolio::portfolioReturn * @covers EfficientRiskyAssetPortfolio::portfolioVariance */ void EfficientRiskyAssetPortfolioTest::testMinimumVariancePortfolio() { _createReturnStatistics(); EfficientRiskyAssetPortfolio model(*_mean, *_variance); Eigen::VectorXd mvp = model.minimumVariancePortfolio(); CPPUNIT_ASSERT_DOUBLES_EQUAL(-24.0 / 70.0, mvp.coeff(0), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(51.0 / 70.0, mvp.coeff(1), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(43.0 / 70.0, mvp.coeff(2), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(73.0 / 1400.0, model.portfolioReturn(mvp), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(23.0 / 875.0, model.portfolioVariance(mvp), EPSILON); _destroyReturnStatistics(); }
/** * @covers EfficientPortfolioWithRisklessAssetTest::minimumVariancePortfolio * @covers EfficientPortfolioWithRisklessAssetTest::portfolioReturn * @covers EfficientPortfolioWithRisklessAssetTest::portfolioVariance */ void EfficientPortfolioWithRisklessAssetTest::testMinimumVariancePortfolio() { _createReturnStatistics(); EfficientPortfolioWithRisklessAsset model(0.04, *_mean, *_variance); Eigen::VectorXd mvp = model.minimumVariancePortfolio(); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, mvp.coeff(0), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, mvp.coeff(1), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, mvp.coeff(2), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, mvp.coeff(3), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.04, model.portfolioReturn(mvp), EPSILON); CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, model.portfolioVariance(mvp), EPSILON); _destroyReturnStatistics(); }
double test(const lbfgsfloatval_t* parameter, int featsize, boost::shared_ptr<Eigen::SparseMatrix<double, Eigen::RowMajor> >& samples, boost::shared_ptr<Eigen::VectorXi>& labels){ Eigen::Map<Eigen::VectorXd> param((double*)parameter, featsize, 1); Eigen::VectorXd xw = (*(samples))*param; double allcnt=0, rightcnt =0 ; for(int i=0; i < labels->rows(); ++i){ if( xw.coeff(i)*labels->coeff(i) > 0){ rightcnt += 1; } allcnt += 1; } return rightcnt /allcnt; }
static lbfgsfloatval_t evaluate( void *instance, const lbfgsfloatval_t *x, lbfgsfloatval_t *g, const int n, const lbfgsfloatval_t step ){ double fx = 0; timeutil t; optimization_instance_t* optInst = (optimization_instance_t*)instance; Eigen::Map<Eigen::VectorXd> param((double*)x, n, 1); Eigen::Map<Eigen::VectorXd> grad((double*)g, n, 1); // price for sparse A*x t.tic(); Eigen::VectorXd xw = (*(optInst->samples_))*param; if( (xw.cols() != 1) || (xw.rows() != optInst->samples_->rows())){ std::cerr << "Error, column size must be 1" << std::endl; std::cerr << "product of Xw is " << xw.rows() << " by " << xw.cols() << std::endl; std::exit(-1); } int effective_cnt = 0; Eigen::ArrayXd xwy(xw.rows()); xwy.setZero(); for(int i=0; i<xw.rows(); ++i){ double z = xw.coeff(i)*(optInst->labels_->coeff(i)); xwy.coeffRef(i) = z; if( z < 1 ){ fx += (1-z)*(1-z); ++effective_cnt; } } // fx /= optInst->labels_->rows(); // l2 regularization value for(int i = optInst->prog_params_->l2start; i <= optInst->prog_params_->l2end; ++i){ fx += 0.5*optInst->prog_params_->l2c * std::pow(param.coeff(i), 2); } grad.setZero(); for (int k = 0; k < optInst->samples_->outerSize(); ++k){ double z = xwy.coeff(k); if(z >= 1){ continue; } double factor = -2 * optInst->labels_->coeff(k) * (1-z); for (Eigen::SparseMatrix<double, Eigen::RowMajor>::InnerIterator it( *(optInst->samples_) ,k); it; ++it){ int colIdx = it.col(); grad.coeffRef(colIdx) += factor*it.value(); } } // grad /= optInst->samples_->rows(); //l2 regularization for(int i = optInst->prog_params_->l2start; i <= optInst->prog_params_->l2end; ++i){ grad.coeffRef(i) += optInst->prog_params_->l2c * param.coeff(i); } std::cout << "One computation of function value & gradient costs " << t.toc() << " seconds" << std::endl; return fx; }