Проблема с оптимизатором пульпы в коде MPTheory - PullRequest
0 голосов
/ 18 февраля 2020

Я действительно новичок в python и недавно решил создать мой алгоритм оптимизации Марковица. Я уже делал это в Excel раньше, поэтому я подумал, что было бы здорово скопировать его в python. Проблема вышла из-под контроля, когда пришло время оптимизировать вес портфеля для достижения максимального коэффициента Шарпа с данным ограничением (определенный уровень SD или условие отсутствия короткого замыкания). Это относительно простая задача, которую можно решить с помощью Excel Solver, но не в python (по крайней мере, для меня). Я прилагаю свой код ниже.

ibm = pd.DataFrame(stock_ibm)
aapl = pd.DataFrame(stock_aapl)
ford = pd.DataFrame(stock_ford)
verizon = pd.DataFrame(stock_verizon)
netflix = pd.DataFrame(stock_netflix)
chevron = pd.DataFrame(stock_chevron)
tesla = pd.DataFrame(stock_tesla)
microsoft = pd.DataFrame(stock_microsoft)
mastercard = pd.DataFrame(stock_mastercard)
google = pd.DataFrame(stock_google)
​
risk_free_rate = 0.0013
​
ibm.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
aapl.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
ford.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
verizon.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
netflix.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
chevron.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
tesla.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
microsoft.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
mastercard.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
google.drop(['High','Low','Open','Volume','Adj Close'], axis = 1, inplace = True)
ibm
Alldf = pd.concat([ibm, aapl, ford, verizon, netflix, chevron, tesla, microsoft, mastercard, google], axis=1)
Alldf
import numpy as np
Alldf_logret = Alldf.apply(lambda x: np.log(x) - np.log(x.shift(1))) 
Alldf_logret
​
Alldf_logret.drop(Alldf_logret.index[0], inplace = True)
Alldf_logret.columns = ['IBM', 'APPLE', 'FORD', 'VERIZON', 'NETFLIX', 'CHEVRON', 'TESLA', 'MICROSOFT', 'MASTERCARD', 'GOOGLE']
Alldf_logret
import statistics
import numpy as np
std1 = np.std(Alldf_logret)
​
mean1 = np.mean(Alldf_logret)
​
CovTable = Alldf_logret.cov()
CovTable
CorrTable=Alldf_logret.corr()
CorrTable
data = {'σ 10%':[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], 
        'σ 12%':[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
        'σ 14%':[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
        'No shorting':[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
        'MVP':[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
        'Max Sharpe/Optimal risky':[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]}
df1 = pd.DataFrame(data, index = Alldf_logret.columns)
df1
import math
​
m10 = df1['σ 10%'].dot(mean1)
m12 = df1['σ 12%'].dot(mean1)
m14 = df1['σ 14%'].dot(mean1)
mNS = df1['No shorting'].dot(mean1)
mMVP = df1['MVP'].dot(mean1)
mMaxSO = df1['Max Sharpe/Optimal risky'].dot(mean1)
​
var10 = (df1['σ 10%']).dot((CovTable.to_numpy())).dot((df1['σ 10%']))
var12 = (df1['σ 12%']).dot((CovTable.to_numpy())).dot((df1['σ 12%']))
var14 = (df1['σ 14%']).dot((CovTable.to_numpy())).dot((df1['σ 14%']))
varNS = (df1['No shorting']).dot((CovTable.to_numpy())).dot((df1['No shorting']))
varMVP = (df1['MVP']).dot((CovTable.to_numpy())).dot((df1['MVP']))
varMaxSO = (df1['Max Sharpe/Optimal risky']).dot((CovTable.to_numpy())).dot((df1['Max Sharpe/Optimal risky']))
​
sd10 = math.sqrt(var10)
sd12 = math.sqrt(var12)
sd14 = math.sqrt(var14)
sdNS = math.sqrt(varNS)
sdMVP = math.sqrt(varMVP)
sdMaxSO = math.sqrt(varMaxSO)
​
sharpe10 = (m10 - risk_free_rate)/sd10
sharpe12 = (m12 - risk_free_rate)/sd12
sharpe14 = (m14 - risk_free_rate)/sd14
sharpeNS = (mNS - risk_free_rate)/sdNS
sharpeMVP = (mMVP - risk_free_rate)/sdMVP
sharpeMaxSO = (mMaxSO - risk_free_rate)/sdMaxSO
​

Итак, чего я хочу достичь в конечном итоге: я хочу максимизировать sharpe10, sharpe12 ..., sharpeMaxSO, изменяя только веса (или df1 другими словами) с такими ограничениями, как : sd10 == 0,1 и сумма веса не должна превышать 1; sd12 == 0,12 и сумма веса не должна превышать 1; для шарпенов сужение должно ограничивать вес от отрицания (я думаю, я выясню, как добавить оставшиеся ограничения, если я только выясню основную идею). Было бы идеально иметь новый фрейм данных с оптимизированными весами в качестве результата оптимизации. Я понимаю, что вся логическая структура моего кода может быть неправильной, учитывая тот факт, что мне нужно запустить оптимизацию (я не уверен, что смогу использовать уже существующие переменные в качестве входных данных в Pulp или другом оптимизаторе, я написал этот код на основе алгоритм Excel) но в любом случае любая помощь будет высоко ценится. Заранее спасибо!

...