在 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

GEKKO - 如何修复 Python Gekko Max Equation 错误 - 元素数

GEKKO 中的 MPC:错误代码“位置 4”解决方案

如何使用 R reticulate 安装 gekko 包?

如何将 gekko 对象插入/附加到现有列表/数组?

Gekko(python) 用于单圈时间优化