Commit 1f2a9f99 authored by Dr.李's avatar Dr.李

added mean variance optimizer

parent 614b98a4
...@@ -10,5 +10,4 @@ Alpha_Mind.egg-info/* ...@@ -10,5 +10,4 @@ Alpha_Mind.egg-info/*
*.nbc *.nbc
*.nbi *.nbi
/notebooks/.ipynb_checkpoints /notebooks/.ipynb_checkpoints
alphamind/examples/* alphamind/examples/*
notebooks/* \ No newline at end of file
\ No newline at end of file
...@@ -29,7 +29,7 @@ cdef class LPOptimizer: ...@@ -29,7 +29,7 @@ cdef class LPOptimizer:
cnp.ndarray[double] ubound, cnp.ndarray[double] ubound,
cnp.ndarray[double] objective): cnp.ndarray[double] objective):
self.cobj = new LpOptimizer(cons_matrix.flatten(), self.cobj = new LpOptimizer(cons_matrix.flatten(order='C'),
lbound, lbound,
ubound, ubound,
objective) objective)
...@@ -47,25 +47,30 @@ cdef class LPOptimizer: ...@@ -47,25 +47,30 @@ cdef class LPOptimizer:
return np.array(self.cobj.xValue()) return np.array(self.cobj.xValue())
cdef extern from "meanvariance.hpp" namespace "pfopt": cdef extern from "mvoptimizer.hpp" namespace "pfopt":
cdef cppclass MeanVariance: cdef cppclass MVOptimizer:
MeanVariance(vector[double], vector[double], double) except + MVOptimizer(vector[double], vector[double], vector[double], vector[double], double) except +
vector[double] xValue() vector[double] xValue()
double feval() double feval()
int status()
cdef class MVOptimizer: cdef class QPOptimizer:
cdef MeanVariance* cobj cdef MVOptimizer* cobj
def __init__(self, def __init__(self,
cnp.ndarray[double] expected_return, cnp.ndarray[double] expected_return,
cnp.ndarray[double, ndim=2] cov_matrix, cnp.ndarray[double, ndim=2] cov_matrix,
cnp.ndarray[double] lbound,
cnp.ndarray[double] ubound,
double risk_aversion): double risk_aversion):
self.cobj = new MeanVariance(expected_return, self.cobj = new MVOptimizer(expected_return,
cov_matrix.flatten(), cov_matrix.flatten(order='C'),
risk_aversion) lbound,
ubound,
risk_aversion)
def __del__(self): def __del__(self):
del self.cobj del self.cobj
...@@ -74,4 +79,7 @@ cdef class MVOptimizer: ...@@ -74,4 +79,7 @@ cdef class MVOptimizer:
return self.cobj.feval() return self.cobj.feval()
def x_value(self): def x_value(self):
return np.array(self.cobj.xValue()) return np.array(self.cobj.xValue())
\ No newline at end of file
def status(self):
return self.cobj.status()
\ No newline at end of file
...@@ -8,19 +8,19 @@ ...@@ -8,19 +8,19 @@
namespace pfopt { namespace pfopt {
class PFOPT_CLASS LpOptimizer { class PFOPT_CLASS LpOptimizer {
public: public:
LpOptimizer(const std::vector<double>& constraintsMatraix, LpOptimizer(const std::vector<double>& constraintsMatraix,
const std::vector<double>& lowerBound, const std::vector<double>& lowerBound,
const std::vector<double>& upperBound, const std::vector<double>& upperBound,
const std::vector<double>& objective); const std::vector<double>& objective);
std::vector<double> xValue() const; std::vector<double> xValue() const;
double feval() const; double feval() const;
int status() const { return model_.status();} int status() const { return model_.status(); }
private: private:
ClpSimplex model_; ClpSimplex model_;
int numberOfProb_; int numberOfProb_;
}; };
} }
......
...@@ -21,7 +21,7 @@ namespace pfopt { ...@@ -21,7 +21,7 @@ namespace pfopt {
const std::vector<double> &varMatrix, const std::vector<double> &varMatrix,
double riskAversion=1.); double riskAversion=1.);
bool setBoundedConstraint(const VectorXd& lb, const VectorXd& ub); bool setBoundedConstraint(const std::vector<double>& lb, const std::vector<double>& ub);
virtual bool get_nlp_info(Index &n, Index &m, Index &nnz_jac_g, virtual bool get_nlp_info(Index &n, Index &m, Index &nnz_jac_g,
Index &nnz_h_lag, IndexStyleEnum &index_style); Index &nnz_h_lag, IndexStyleEnum &index_style);
......
#ifndef pfopt_mv_optimizer_hpp
#define pfopt_mv_optimizer_hpp
#include "meanvariance.hpp"
#include <coin/IpIpoptApplication.hpp>
namespace pfopt {
class PFOPT_CLASS MVOptimizer {
public:
MVOptimizer(const std::vector<double> &expectReturn,
const std::vector<double> &varMatrix,
const std::vector<double> &lbound,
const std::vector<double> &ubound,
double riskAversion);
std::vector<double> xValue() const { return mvImpl_->xValue(); }
double feval() const { return mvImpl_->feval(); }
int status() const { return status_; }
private:
Ipopt::SmartPtr<MeanVariance> mvImpl_;
Ipopt::SmartPtr<Ipopt::IpoptApplication> app_;
Ipopt::ApplicationReturnStatus status_;
};
}
#endif
\ No newline at end of file
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"from cvxpy import *\n",
"from cvxopt import *\n",
"from alphamind.cython.optimizers import QPOptimizer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Data Preparing\n",
"--------------------------"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"risk_penlty = 0.5"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"sec_cov_values_full = np.genfromtxt('sec_cov_values.csv', delimiter=',')\n",
"signal_full = np.genfromtxt('signal.csv', delimiter=',')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"n = 200\n",
"\n",
"sec_cov_values = sec_cov_values_full[:n, :n]\n",
"signal = signal_full[:n]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Optimizing Weights\n",
"-------------------------------------"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"w = Variable(n)\n",
"\n",
"lbound = 0.\n",
"ubound = 1. / n * 20\n",
"\n",
"objective = Minimize(risk_penlty * quad_form(w, sec_cov_values) - signal * w)\n",
"constraints = [w >= lbound,\n",
" w <= ubound,\n",
" sum_entries(w) == 1,]\n",
"\n",
"prob = Problem(objective, constraints)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"prob.solve(verbose=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"prob.status, prob.value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"prob.solve(verbose=True, solver='CVXOPT')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"prob.status, prob.value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"P = matrix(sec_cov_values)\n",
"q = -matrix(signal)\n",
"\n",
"G = np.zeros((2*n, n))\n",
"h = np.zeros(2*n)\n",
"for i in range(n):\n",
" G[i, i] = 1.\n",
" h[i] = 1. / n * 20\n",
" G[i+n, i] = -1.\n",
" h[i+n] = 0.\n",
" \n",
"G = matrix(G)\n",
"h = matrix(h)\n",
" \n",
"A = np.ones((1, n))\n",
"b = np.ones(1)\n",
"\n",
"A = matrix(A)\n",
"b = matrix(b)\n",
"\n",
"sol = solvers.qp(P, q, G, h, A, b)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"lbound = np.zeros(n)\n",
"ubound = np.ones(n) * 20 / n\n",
"qpopt = QPOptimizer(signal, sec_cov_values, lbound, ubound, 1.)\n",
"qpopt.feval()\n",
"qpopt.status()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Performace Timing\n",
"-------------------------"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import datetime as dt"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def time_function(py_callable, n):\n",
" start = dt.datetime.now()\n",
" py_callable(n)\n",
" return (dt.datetime.now() - start).total_seconds()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def cvxpy(n):\n",
" w = Variable(n)\n",
"\n",
" lbound = 0.\n",
" ubound = 0.01\n",
"\n",
" objective = Minimize(risk_penlty * quad_form(w, sec_cov_values) - signal * w)\n",
" constraints = [w >= lbound,\n",
" w <= ubound,\n",
" sum_entries(w) == 1,]\n",
"\n",
" prob = Problem(objective, constraints)\n",
" prob.solve(verbose=False, solver='CVXOPT', display=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def cvxopt(n):\n",
" P = matrix(sec_cov_values)\n",
" q = -matrix(signal)\n",
"\n",
" G = np.zeros((2*n, n))\n",
" h = np.zeros(2*n)\n",
" for i in range(n):\n",
" G[i, i] = 1.\n",
" h[i] = 0.01\n",
" G[i+n, i] = -1.\n",
" h[i+n] = 0.\n",
"\n",
" G = matrix(G)\n",
" h = matrix(h)\n",
"\n",
" A = np.ones((1, n))\n",
" b = np.ones(1)\n",
"\n",
" A = matrix(A)\n",
" b = matrix(b)\n",
" \n",
" solvers.options['show_progress'] = False\n",
" sol = solvers.qp(P, q, G, h, A, b)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def ipopt(n):\n",
" lbound = np.zeros(n)\n",
" ubound = np.ones(n) * 0.01\n",
" qpopt = QPOptimizer(signal, sec_cov_values, lbound, ubound, 1.)\n",
" qpopt.feval()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"n_steps = list(range(200, 3201, 200))\n",
"cvxpy_times = [None] * len(n_steps)\n",
"cvxopt_times = [None] * len(n_steps)\n",
"ipopt_times = [None] * len(n_steps)\n",
"print(\"{0:<8}{1:>12}{2:>12}{3:>12}\".format('Scale(n)', 'cvxpy', 'cvxopt', 'ipopt'))\n",
"\n",
"for i, n in enumerate(n_steps):\n",
" sec_cov_values = sec_cov_values_full[:n, :n]\n",
" signal = signal_full[:n]\n",
" cvxpy_times[i] = time_function(cvxpy, n) * 1000\n",
" cvxopt_times[i] = time_function(cvxopt, n) * 1000\n",
" ipopt_times[i] = time_function(ipopt, n) * 1000\n",
" \n",
" print(\"{0:<8}{1:>12.2f}{2:>12.2f}{3:>12.2f}\".format(n, cvxpy_times[i], cvxopt_times[i], ipopt_times[i]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"df = pd.DataFrame({'cvxpy': cvxpy_times,\n",
" 'cvxopt': cvxopt_times,\n",
" 'ipopt': ipopt_times},\n",
" index=n_steps)\n",
"df.index.name = 'Problem Scale (n)'\n",
"df"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [default]",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
This diff is collapsed.
...@@ -3,7 +3,7 @@ cvxpy >= 0.4.9 ...@@ -3,7 +3,7 @@ cvxpy >= 0.4.9
cython >= 0.25.2 cython >= 0.25.2
mysqlclient >= 1.3.10 mysqlclient >= 1.3.10
numpy >= 1.12.1 numpy >= 1.12.1
numba >= 0.34.0 numba >= 0.33.0
scikit-learn >= 0.18.1 scikit-learn >= 0.18.1
scipy >= 0.19.0 scipy >= 0.19.0
simpleutils >= 0.1.0 simpleutils >= 0.1.0
......
...@@ -43,7 +43,7 @@ else: ...@@ -43,7 +43,7 @@ else:
"./libs/include/pfopt", "./libs/include/pfopt",
"./libs/include/eigen", "./libs/include/eigen",
"./libs/include/alglib"], "./libs/include/alglib"],
libraries=['pfopt', 'alglib', 'libClp', 'libCoinUtils'], libraries=['pfopt', 'alglib', 'libClp', 'libCoinUtils', 'IpOptFSS', 'Ipopt-vc8'],
library_dirs=['./libs/lib/windows']), library_dirs=['./libs/lib/windows']),
] ]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment