在 Python 中使用 Gekko 求解函数
Posted
技术标签:
【中文标题】在 Python 中使用 Gekko 求解函数【英文标题】:Solving Functions with Gekko in Python 【发布时间】:2021-11-20 23:50:29 【问题描述】:我正在考虑使用 gekko 来解决基于时间的财务分析的优化问题,我一直在使用蛮力循环来解决这个问题,但这很困难,尤其是当变量的数量变得更加复杂时。 这是我正在尝试做的一个非常简单的示例: 函数 ema_cross_strat(x1,x2) 计算时间序列的两个 ema(也可以传递但当前没有传递)然后确定快速 ema 是否高于慢速 ema 并根据该位置计算时间序列的回报.
在 Gekko 中是否有办法做到这一点,以便您可以针对快速和慢速平均线优化最佳移动平均线组合。
closes['SPY'].tail()
date
2021-07-22 434.069275
2021-07-23 438.534973
2021-07-26 439.611511
2021-07-27 437.607941
2021-07-28 437.428497
Name: SPY, dtype: float32
def ema_cross_strat(x1,x2):
f=x1
s=x2
ts = closes['SPY']
ema_fast = ts.ewm(span = f).mean()
ema_slow = ts.ewm(span = s).mean()
strat_position = (ema_fast > ema_slow).astype(float)
strategy = ts.pct_change() * strat_position.shift()
equity = (strategy+1).cumprod()[-1]
return -equity
#initialise model
m = GEKKO()
# Integer constraints for x1 and x2
#x1 is the fast EMA, x2 is the slow ema
x1 = m.Var(value=3,lb=3,ub=30,integer=True)
x2 = m.Var(value=30,lb=30,ub=200,integer=True)
#Equations
#slow ema needs to be higher than the fast ema.
m.Equation(x2-x1>0)
#m.Equation(x1**2+x2**2+x3**2+x4**2==eq)
#Objective
m.Minimize(ema_cross_strat(x1,x2))
#Set global options
m.Minimize(f(x))
m.options.SOLVER=1
m.solve()
这目前会产生一个错误,表明变量没有被正确传递,但我不清楚为什么基于其他示例,或者这种类型的东西是否适用于 gekko。已尝试将 x 与 x1,x2 的数组一起传递,但结果是相同的。
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-76-6fa879b27b94> in <module>
12
13 #Objective
---> 14 m.Minimize(ema_cross_strat(x1,x2))
15 #Set global options
16 m.Minimize(f(x))
<ipython-input-71-caf179a766b9> in ema_cross_strat(x1, x2)
4
5 ts = closes['SPY']
----> 6 ema_fast = ts.ewm(span = f).mean()
7 ema_slow = ts.ewm(span = s).mean()
8 strat_position = (ema_fast > ema_slow).astype(float)
C:\Anaconda3\envs\env_zip36\lib\site-packages\pandas\core\generic.py in ewm(self, com, span, halflife, alpha, min_periods, freq, adjust, ignore_na, axis)
7084 return rwindow.ewm(self, com=com, span=span, halflife=halflife,
7085 alpha=alpha, min_periods=min_periods, freq=freq,
-> 7086 adjust=adjust, ignore_na=ignore_na, axis=axis)
7087
7088 cls.ewm = ewm
C:\Anaconda3\envs\env_zip36\lib\site-packages\pandas\core\window.py in ewm(obj, **kwds)
2087 raise TypeError('invalid type: %s' % type(obj))
2088
-> 2089 return EWM(obj, **kwds)
2090
2091
C:\Anaconda3\envs\env_zip36\lib\site-packages\pandas\core\window.py in __init__(self, obj, com, span, halflife, alpha, min_periods, freq, adjust, ignore_na, axis)
1682 axis=0):
1683 self.obj = obj
-> 1684 self.com = _get_center_of_mass(com, span, halflife, alpha)
1685 self.min_periods = min_periods
1686 self.freq = freq
C:\Anaconda3\envs\env_zip36\lib\site-packages\pandas\core\window.py in _get_center_of_mass(com, span, halflife, alpha)
1986 raise ValueError("com must satisfy: com >= 0")
1987 elif span is not None:
-> 1988 if span < 1:
1989 raise ValueError("span must satisfy: span >= 1")
1990 com = (span - 1) / 2.
C:\Anaconda3\envs\env_zip36\lib\site-packages\gekko\gk_operators.py in __len__(self)
23 return self.name
24 def __len__(self):
---> 25 return len(self.value)
26 def __getitem__(self,key):
27 return self.value[key]
C:\Anaconda3\envs\env_zip36\lib\site-packages\gekko\gk_operators.py in __len__(self)
142
143 def __len__(self):
--> 144 return len(self.value)
145
146 def __getitem__(self,key):
TypeError: object of type 'int' has no len()
【问题讨论】:
【参考方案1】:Gekko 创建一次模型,然后将其传递给求解器。任何函数都需要以符号表示问题的方式定义,这样就不需要重新评估。要尝试的一件事是Scipy.optimize.minimize()
并创建某种方式使决策变量连续(例如仅具有下一个数字的一小部分的平均值)。这是Scipy.optimize.minimize and Gekko for optimization的信息。
Scipy
import numpy as np
from scipy.optimize import minimize
def objective(x):
return x[0]*x[3]*(x[0]+x[1]+x[2])+x[2]
def constraint1(x):
return x[0]*x[1]*x[2]*x[3]-25.0
def constraint2(x):
sum_eq = 40.0
for i in range(4):
sum_eq = sum_eq - x[i]**2
return sum_eq
# initial guesses
n = 4
x0 = np.zeros(n)
x0[0] = 1.0
x0[1] = 5.0
x0[2] = 5.0
x0[3] = 1.0
# show initial objective
print('Initial Objective: ' + str(objective(x0)))
# optimize
b = (1.0,5.0)
bnds = (b, b, b, b)
con1 = 'type': 'ineq', 'fun': constraint1
con2 = 'type': 'eq', 'fun': constraint2
cons = ([con1,con2])
solution = minimize(objective,x0,method='SLSQP',\
bounds=bnds,constraints=cons)
x = solution.x
# show final objective
print('Final Objective: ' + str(objective(x)))
# print solution
print('Solution')
print('x1 = ' + str(x[0]))
print('x2 = ' + str(x[1]))
print('x3 = ' + str(x[2]))
print('x4 = ' + str(x[3]))
壁虎
from gekko import GEKKO
import numpy as np
#Initialize Model
m = GEKKO()
#help(m)
#define parameter
eq = m.Param(value=40)
#initialize variables
x1,x2,x3,x4 = [m.Var(lb=1,ub=5) for i in range(4)]
#initial values
x1.value = 1
x2.value = 5
x3.value = 5
x4.value = 1
m.Equation(x1*x2*x3*x4>=25)
m.Equation(x1**2+x2**2+x3**2+x4**2==eq)
m.Minimize(x1*x4*(x1+x2+x3)+x3)
m.solve()
print('Results')
print('x1: ' + str(x1.value))
print('x2: ' + str(x2.value))
print('x3: ' + str(x3.value))
print('x4: ' + str(x4.value))
如果您想使用 Gekko,请考虑根据平均值和值的数量之间的关系从平均值到 create a cubic spline (cspline) 的连续函数。
【讨论】:
以上是关于在 Python 中使用 Gekko 求解函数的主要内容,如果未能解决你的问题,请参考以下文章
如何在 GEKKO 中级中使用 np.log 或 np.exp