Pandas 通过组合行的值来优化并找到最大值

Pandas 通过组合行的值来优化并找到最大值,pandas,scipy,Pandas,Scipy,我有以下df: level type price1 price2 5250 A 0.233 0.2865 5250 B 0.004 0.006 5500 A 0.197 0.2545 5500 B 0.0055 0.0075 5750 A 0.1615 0.223 5750 B 0.0075 0.009 6000 A 0.127 0.1925 6000 B 0.0105 0.012

我有以下
df

level   type  price1    price2
5250    A   0.233   0.2865
5250    B   0.004   0.006
5500    A   0.197   0.2545
5500    B   0.0055  0.0075
5750    A   0.1615  0.223
5750    B   0.0075  0.009
6000    A   0.127   0.1925
6000    B   0.0105  0.0125
6250    A   0.1215  0.1635
6250    B   0.0135  0.0165
6500    A   0.099   0.136
6500    B   0.021   0.024
6750    A   0.071   0.085
6750    B   0.03    0.0325
7000    A   0.052   0.0555
7000    B   0.044   0.047
7250    A   0.036   0.0395
7250    B   0.063   0.0675
7500    A   0.024   0.0275
7500    B   0.086   0.091
7750    A   0.0165  0.019
7750    B   0.111   0.161
8000    A   0.0105  0.0135
8000    B   0.118   0.1915
8250    A   0.0085  0.0105
8250    B   0.137   0.224
8500    A   0.0055  0.008
8500    B   0.1835  0.257
8750    A   0.0045  0.0065
8750    B   0.2035  0.291
9000    A   0.0035  0.0055
9000    B   0.002   1.956
我根据
类型
列将
df
分为
df_A
df_B
。 下一步,我想找到使以下各项最大化的级别/行:

sum = buy_A + buy_B - sell_A - sell_B 
在哪里

为了清楚起见,我在这里使用了
,但是在我的脚本中
应该等于列
级别
的值。我有个限制。对于
买入A
卖出B
而言,
级别
应该相等,对于
卖出A
买入B
而言,
级别
的值应该相等。包括这一结果:

buy_A = float(df_A.loc[(df_A['level'] == level_1), 'price2'])
buy_B = float(df_B.loc[(df_B['level'] == level_2), 'price2'])
sell_A = float(df_A.loc[(df_A['level'] == level_1), 'price1'])
sell_B = float(df_B.loc[(df_B['level'] == level_2), 'price1'])
基本上,对于上述
df
我得到以下矩阵:

我想返回矩阵中最大值的值以及相应的级别

我的剧本:

import pandas as pd
import numpy as np
from scipy.optimize import minimize


def obj(x, df):
   df_A = df.loc[(df['type'] == 'A')]
   df_B = df.loc[(df['type'] == 'B')]
   sum = df_A['price1'] + df_B['price1'] - df_A['price2'] - df_B['price2']
   return -1 * sum


if __name__ == "__main__":
   df = pd.read_csv('quotes.csv')
   guess = 0
   solver = minimize(obj, args=(df), x0=guess, method='Nelder-Mead', options={'disp': True})

我需要更改什么才能获得最大值和相应的级别?非常感谢

因为
sum
是Python中的内置函数,我想用
z
替换它。既然你在(
buy_A
sell_B
)和(
sell_A
buy_B
)中有相同的
level
的限制,那么让我们重新安排你的等式,让它更清楚:

z = buy_A + buy_B - sell_A - sell_B 
  = (buy_A - sell_B) + (buy_B - sell_A)
  = x + y

让我们深入探讨你的问题。我们要做的第一件事是重新格式化原始数据帧以排列级别:

tmp = df.rename({'price1': 'sell', 'price2': 'buy'}, axis=1) \
        .set_index(['level', 'type']) \
        .unstack()

# tmp:
         sell             buy        
type        A       B       A       B
level                                
5250   0.2330  0.0040  0.2865  0.0060
5500   0.1970  0.0055  0.2545  0.0075
5750   0.1615  0.0075  0.2230  0.0090
6000   0.1270  0.0105  0.1925  0.0125
6250   0.1215  0.0135  0.1635  0.0165
然后计算我们的
x
y

x = tmp[('buy', 'A')] - tmp[('sell', 'B')]
y = tmp[('buy', 'B')] - tmp[('sell', 'A')]
接下来,我们需要计算
z
z
不仅仅是
x
+
y
,而是
x
中的每个值都添加到
y
中的每个值;因此,
z
是一个方阵。但我们也不想要整个矩阵。我们只想要主对角线下方的三角形。
numpy.ma
模块在屏蔽数组上提供函数,我们可以将某些元素标记为不存在

import numpy.ma as ma

# Mask away the upper triangle, including the main diagonal
# len(x) == len(y)
mask = np.triu(np.ones((len(x), len(y))))

# Use numpy broadcasting to add every value in `x` to every value in `y`
# `x` and `y` are pandas Series. `.values` get the underlying numpy array
#
# `y.values[:, None]` raises `y` to another dimension. This is what
# triggers numpy's array broadcasting and make `z` a square matrix
z = -ma.array(x.values + y.values[:, None], mask=mask)

# If you want to visualize `z`, type this into the debugger
# pd.DataFrame(z, index=tmp.index, columns=tmp.index)
最后一步是获得相加时产生最大值的级别。如果存在多个具有最大值的单元格,则仅获取第一个:

i,j = np.unravel_index(z.argmax(), z.shape)

# The level with the max sum
level1, level2 = tmp.index[[i,j]]   # 7250, 7000

# The max value of the sums
z[i,j]                              # -0.043

因为
sum
是Python中的内置函数,所以我想用
z
替换它。既然你在(
buy_A
sell_B
)和(
sell_A
buy_B
)中有相同的
level
的限制,那么让我们重新安排你的等式,让它更清楚:

z = buy_A + buy_B - sell_A - sell_B 
  = (buy_A - sell_B) + (buy_B - sell_A)
  = x + y

让我们深入探讨你的问题。我们要做的第一件事是重新格式化原始数据帧以排列级别:

tmp = df.rename({'price1': 'sell', 'price2': 'buy'}, axis=1) \
        .set_index(['level', 'type']) \
        .unstack()

# tmp:
         sell             buy        
type        A       B       A       B
level                                
5250   0.2330  0.0040  0.2865  0.0060
5500   0.1970  0.0055  0.2545  0.0075
5750   0.1615  0.0075  0.2230  0.0090
6000   0.1270  0.0105  0.1925  0.0125
6250   0.1215  0.0135  0.1635  0.0165
然后计算我们的
x
y

x = tmp[('buy', 'A')] - tmp[('sell', 'B')]
y = tmp[('buy', 'B')] - tmp[('sell', 'A')]
接下来,我们需要计算
z
z
不仅仅是
x
+
y
,而是
x
中的每个值都添加到
y
中的每个值;因此,
z
是一个方阵。但我们也不想要整个矩阵。我们只想要主对角线下方的三角形。
numpy.ma
模块在屏蔽数组上提供函数,我们可以将某些元素标记为不存在

import numpy.ma as ma

# Mask away the upper triangle, including the main diagonal
# len(x) == len(y)
mask = np.triu(np.ones((len(x), len(y))))

# Use numpy broadcasting to add every value in `x` to every value in `y`
# `x` and `y` are pandas Series. `.values` get the underlying numpy array
#
# `y.values[:, None]` raises `y` to another dimension. This is what
# triggers numpy's array broadcasting and make `z` a square matrix
z = -ma.array(x.values + y.values[:, None], mask=mask)

# If you want to visualize `z`, type this into the debugger
# pd.DataFrame(z, index=tmp.index, columns=tmp.index)
最后一步是获得相加时产生最大值的级别。如果存在多个具有最大值的单元格,则仅获取第一个:

i,j = np.unravel_index(z.argmax(), z.shape)

# The level with the max sum
level1, level2 = tmp.index[[i,j]]   # 7250, 7000

# The max value of the sums
z[i,j]                              # -0.043

为什么
df_B.loc[row,'price2']
既等于
buy_B
又等于
sell_B
?这是打字错误吗?是的,很抱歉,为什么
df_B.loc[row,'price2']
既等于
buy_B
又等于
sell_B
?那是打字错误吗?是的很抱歉