我正在测试我的函数,计算价格指标,我有一个奇怪的错误,我不知道如何解决。
编辑:列中的csv我已经分享都是小写,在测试的情况下,这个csv的功能,你想使用这个代码:
data = pd.read_csv(csv_path)
data = data.drop(['symbol'], axis=1)
data.rename(columns={'open': 'Open', 'high': 'High', 'low': 'Low', 'close': 'Close', 'volume': 'Volume'}, inplace=True)
Link to data .csv file您可以尝试使用默认参数的函数。(在帖子的底部,我还分享了一个input_type
辅助函数,只是要确保不要使用高于4的输入模式,因为HL2
,HLC3
,OHLC4
和HLCC4
输入模式不计算此csv。
所以我用这个函数来计算Weighted Moving Average
:
(我正在使用默认参数测试此函数)
def wma(price_df: PandasDataFrame, n: int = 14, input_mode: int = 2, from_price: bool = True, *,
indicator_name: str = 'None') -> PandasDataFrame:
if from_price:
name_var, state = input_type(__input_mode__=input_mode)
else:
if indicator_name == 'None':
raise TypeError('Invalid input argument. indicator_name cannot be set to None if from_price is False.')
else:
name_var = indicator_name
wma_n = pd.DataFrame(index=range(price_df.shape[0]), columns=range(1))
wma_n.rename(columns={0: f'WMA{n}'}, inplace=True)
weight = np.arange(1, (n + 1)).astype('float64')
weight = weight * n
norm = sum(weight)
weight_df = pd.DataFrame(weight)
weight_df.rename(columns={0: 'weight'}, inplace=True)
product = pd.DataFrame()
product_sum = 0
for i in range(price_df.shape[0]):
if i < (n - 1):
# creating NaN values where it is impossible to calculate EMA to drop the later
wma_n[f'WMA{n}'].iloc[i] = np.nan
elif i == (n - 1):
product = price_df[f'{name_var}'].iloc[:(i + 1)] * weight_df['weight']
product_sum = product.sum()
wma_n[f'WMA{n}'].iloc[i] = product_sum / norm
print(f'index: {i}, wma: ', wma_n[f'WMA{n}'].iloc[i])
print(product_sum)
print(norm)
product = product.iloc[0:0]
product_sum = 0
elif i > (n - 1):
product = price_df[f'{name_var}'].iloc[(i - (n - 1)): (i + 1)] * weight_df['weight']
product_sum = product.sum()
wma_n[f'WMA{n}'].iloc[i] = product_sum / norm
print(f'index: {i}, wma: ', wma_n[f'WMA{n}'].iloc[i])
print(product_sum)
print(norm)
product = product.iloc[0:0]
product_sum = 0
return wma_n
由于某种原因,在26次迭代后,值下降到0.0
,我不知道为什么。有人能帮帮我吗?
我的输出:
index: 13, wma: 14467.42857142857
product_sum: 21267120.0
norm 1470.0
index: 14, wma: 14329.609523809524
product_sum: 21064526.0
norm 1470.0
index: 15, wma: 14053.980952380953
product_sum: 20659352.0
norm 1470.0
index: 16, wma: 13640.480952380953
product_sum: 20051507.0
norm 1470.0
index: 17, wma: 13089.029523809522
product_sum: 19240873.4
norm 1470.0
index: 18, wma: 12399.72
product_sum: 18227588.4
norm 1470.0
index: 19, wma: 11572.234285714285
product_sum: 17011184.4
norm 1470.0
index: 20, wma: 10607.100952380953
product_sum: 15592438.4
norm 1470.0
index: 21, wma: 9504.32
product_sum: 13971350.4
norm 1470.0
index: 22, wma: 8263.905714285715
product_sum: 12147941.4
norm 1470.0
index: 23, wma: 6885.667619047619
product_sum: 10121931.4
norm 1470.0
index: 24, wma: 5369.710476190477
product_sum: 7893474.4
norm 1470.0
index: 25, wma: 3716.270476190476
product_sum: 5462917.6
norm 1470.0
index: 26, wma: 1926.48
product_sum: 2831925.6
norm 1470.0
index: 27, wma: 0.0
product_sum: 0.0
norm 1470.0
index: 28, wma: 0.0
product_sum: 0.0
norm 1470.0
运行我的函数所需的辅助函数。
def input_type(__input_mode__: int) -> (str, bool):
list_of_inputs = ['Open', 'Close', 'High', 'Low', 'HL2', 'HLC3', 'OHLC4', 'HLCC4']
if __input_mode__ in range(1, 10, 1):
input_name = list_of_inputs[__input_mode__ - 1]
state = True
return input_name, state
else:
raise TypeError('__input_mode__ out of range.')
2条答案
按热度按时间iklwldmw1#
这个问题是由Pandas的alignment特性引起的。假设你有两个 Dataframe 。一个 Dataframe 显示你持有的每只股票的数量。另一个 Dataframe 显示每只股票的价格。但是,它们的顺序不一样,并且有数据丢失。
这些 Dataframe 如下所示:
Pandas会让你把这两列相乘。
请注意,它将ABC的价格与ABC的股票数量匹配起来,尽管它们在原始 Dataframe 中的顺序不同,DEF缺少一个股票价格,现在变成了NaN,因为乘法的一边缺少一个值。
Pandas在这里做了类似的事情,这是
price_df[f'{name_var}'].iloc[(i - (n - 1)): (i + 1)]
在循环过程中的值:请注意,这从1开始,到14结束。
这是同一循环中
weights_df['weights']
的值:请注意,这从0开始,到13结束。
这是两者的乘积:
现在,第一个和最后一个值都有NaN,并且只有13个真实的值。每次循环,它都会多丢失一个值。
但是为什么它返回零而不是NaN呢?Pandas在对列求和时忽略NaN值。如果只对NaN值求和,那么它返回零。
那么,如何才能避免对齐呢?有很多方法。
1.方法1:可以调用
reset_index()
:这将使索引恢复为从零开始。
1.方法#2:你可以用numpy来计算,Numpy不关心对齐与否。
1.方法#3:Pandas已经有了一种方法来计算你要找的东西--它们被称为rolling window计算。
这不仅更简单,而且更快。
8fq7wneg2#
我认为发生这种情况的原因是因为
weight_df
的索引为0 - 13,但当您迭代price_df
时,索引最初为0 - 13,然后为1 - 14,然后为2 - 15、3 - 16、4 - 17等。这意味着当您将这些索引相乘时:由于索引不对齐,您将得到一大堆NaN值!下面是一个越来越糟糕的示例:
输出:
在您的示例中,
weight_df
和price_df
的索引在迭代过程中越来越远离,从而创建了越来越多的NaN。我相信这个问题是可以解决的,但我强烈建议你用一种更"Pandas"的方式来解决这个问题。https://stackoverflow.com/a/53833851/9499196
Pandas DataFrames提供了
.rolling
方法,该方法可以生成您想要手动创建的窗口,然后您可以通过在price_df[your_col].rolling()
返回的Rolling对象上调用.apply
,对每个窗口应用一个函数(加权平均值)。