Ich verwende cvxpy, um an einem einfachen Problem der Portfoliooptimierung zu arbeiten. Die einzige Einschränkung, die ich nicht verstehen kann, ist die Kardinalitätseinschränkung für die Anzahl der Portfoliopositionen, die nicht Null sind. Ich habe zwei Ansätze ausprobiert, einen MIP-Ansatz und einen traditionellen konvexen Ansatz.Kardinalitätseinschränkung in der Portfoliooptimierung
Hier ist ein Dummy-Code für ein funktionierendes traditionelles Beispiel.
import numpy as np
import cvxpy as cvx
np.random.seed(12345)
n = 10
k = 6
mu = np.abs(np.random.randn(n, 1))
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
w = cvx.Variable(n)
ret = mu.T*w
risk = cvx.quad_form(w, Sigma)
objective = cvx.Maximize(ret - risk)
constraints = [cvx.sum_entries(w) == 1, w>= 0, cvx.sum_smallest(w, n-k) >= 0, cvx.sum_largest(w, k) <=1 ]
prob = cvx.Problem(objective, constraints)
prob.solve()
print prob.status
output = []
for i in range(len(w.value)):
output.append(round(w[i].value,2))
print 'Number of non-zero elements : ',sum(1 for i in output if i > 0)
hatte ich die Idee zu verwenden, sum_smallest und sum_largest (cvxpy manual) mein Gedanke war es, die kleinsten nk Einträge auf 0 bis Constraint und mein Zielbereich k Summe lassen bis zu einem, ich weiß, ich kann nicht ändern Richtung der Ungleichung, um konvex zu bleiben, aber vielleicht weiß jemand über eine clevere Art, das Problem zu beschränken, während es immer noch einfach bleibt.
Mein zweiter Gedanke war dies ein gemischt-ganzzahlige Problem zu machen, s.th entlang der Linien von
import numpy as np
import cvxpy as cvx
np.random.seed(12345)
n = 10
k = 6
mu = np.abs(np.random.randn(n, 1))
Sigma = np.random.randn(n, n)
Sigma = Sigma.T.dot(Sigma)
w = cvx.Variable(n)
binary = cvx.Bool(n)
integer = cvx.Int(n)
ret = mu.T*w
risk = cvx.quad_form(w, Sigma)
objective = cvx.Maximize(ret - risk)
constraints = [cvx.sum_entries(w) == 1, w>= 0, cvx.sum_entries(binary) == k ]
prob = cvx.Problem(objective, constraints)
prob.solve()
print prob.status
output = []
for i in range(len(w.value)):
output.append(round(w[i].value,2))
print sum(1 for i in output if i > 0)
for i in range(len(w.value)):
print round(binary[i].value,2)
print output
an meinem binären Vektor suchen scheint es, das Richtige zu tun, sondern die sum_entries Einschränkung nicht arbeite, schaue in die binären Vektorwerte Ich habe festgestellt, dass 0 nicht 0 ist, es ist sehr klein zB xxe^-20 Ich nehme an, dies wird Dinge durcheinander bringen. Kann mir jemand eine Anleitung geben, wenn das der richtige Weg ist? Ich kann die Standard-Löser verwenden, genauso wie Mosek, wenn das hilft. Ich würde lieber eine Nicht-MIP-Implementierung haben, da ich weiß, dass dies ein kombinatorisches Problem ist und bei größeren Problemen sehr langsam werden wird. Letztendlich möchte ich entweder die genaue Anzahl der Zielbestände einschränken oder einen Bereich, z. 20-30.
Auch die Dokumentation in cvxpy rund um MIP ist sehr kurz. Danke
Das sieht gut aus Dank, würden Sie etwas dagegen, den Bereich Version in Ihrem Arbeitsbeispiel Putting Ich kämpfe mit, wie Sie Ihre Indikatoren verwenden. Danke, ich werde das als Antwort akzeptieren. – ThatQuantDude