我制作了一个脚本来获取股票清单的股票信息。对于涉及的股票(groupby中的组),我需要计算MACD。
为了不将一只股票的价格与另一只股票的价格混合,我使用了一只pandas groupby。
# -*- coding: utf-8 -*-
import pandas as pd
from pandas.io.data import DataReader
import numpy as np
import time
from io import StringIO
runstart = time.time() # Start script timer
stocklist = ['nflx','mmm']
tickers = []
days_backtest=102 # MA98 kræver 102 d for at virke!
end = pd.Timestamp.utcnow()
start = end - days_backtest * pd.tseries.offsets.BDay()
# Fetch stockinfo
def GetStock(stocklist, start, end, csv_file_all='alltickers_ohlc.csv'):
'''
Fetches stock-info for analysis of each ticker in stocklist
'''
print('\nGetting Stock-info from Yahoo-Finance')
for ticker in stocklist:
r = DataReader(ticker, "yahoo",
start = start, end = end)
# add a symbol column
r['Ticker'] = ticker
tickers.append(r)
# concatenate all the dfs
df_all = pd.concat(tickers)
# add col without space in adj close
df_all['Adj_Close'] = df_all['Adj Close']
#define df with the columns that i need These can be put back in df_all
df_all = df_all[['Ticker','Adj_Close','Volume']] #'Adj Close','Open','High','Low',
# round to 2 dig.
# df_all['Open'] = np.round(df_all['Open'], decimals=2)
# df_all['High'] = np.round(df_all['High'], decimals=2)
# df_all['Low'] = np.round(df_all['Low'], decimals=2)
# df_all['Adj Close'] = np.round(df_all['Adj Close'], decimals=2)
df_all['Adj_Close'] = np.round(df_all['Adj_Close'], decimals=2)
# # Test the first 3 rows of each group for 'Difference' col transgress groups...
# df_all_test = df_all.groupby('Ticker').head(27).reset_index().set_index('Date')
# print ('\n df_all_test (27d summary from df) (Output)\n',df_all_test,'\n')
# saving to a csv #
df_all.reset_index().sort(['Ticker', 'Date'], ascending=[1,1]).set_index('Ticker').to_csv(csv_file_all, date_format='%Y/%m/%d')
# df_all.sort_index(inplace=True) # Sorts rows from date, mingling tickers - not wanted
print('========= Picked up new stockinfo (df_all) \n')
# print ('df_all.tail (Input)\n',df_all.tail(6),'\n')
print(70 * '-')
# print(df_all)
return df_all
def moving_average(group, n=9, type='simple'):
"""
compute an n period moving average.
type is 'simple' | 'exponential'
"""
group = np.asarray(df_['Adj_Close'])
if type == 'simple':
weights = np.ones(n)
else:
weights = np.exp(np.linspace(-1., 0., n))
weights /= weights.sum()
a = np.convolve(group, weights, mode='full')[:len(group)]
a[:n] = a[n]
return a
# return pd.DataFrame({'MCD_Sign':a})
def moving_average_convergence(group, nslow=26, nfast=12):
"""
compute the MACD (Moving Average Convergence/Divergence) using a fast and slow exponential moving avg'
return value is emaslow, emafast, macd which are len(x) arrays
"""
emaslow = moving_average(group, nslow, type='exponential')
emafast = moving_average(group, nfast, type='exponential')
# return emaslow, emafast, emafast - emaslow
return pd.DataFrame({'emaSlw': emaslow,
'emaFst': emafast,
'MACD': emafast - emaslow})
if __name__ == '__main__':
### Getstocks
df_all = GetStock(stocklist, start, end)
### Sort DF
df_all.reset_index().sort(['Ticker', 'Date'], ascending=[1,1]).set_index('Ticker')
### groupby screeener (filtering to only rel ticker group)
df_ = df_all.set_index('Ticker', append=True)
''' Calculating all the KPIs via groupby (filtering pr ticker)'''
grouped = df_.groupby(level=1).Adj_Close
nslow = 26
nfast = 12
nema = 9
df_[['emaSlw', 'emaFst', 'MACD']] = df_.groupby(level=1).Adj_Close.apply(moving_average_convergence)
df_['MCD_Sign'] = df_.groupby(level=1).Adj_Close.apply(moving_average)
print ('(Output df)\n',df_,'\n')
df = df_.reset_index('Ticker')
# Test the last row of each group for new numbers pr group...
df_test = df.groupby('Ticker').tail(1).reset_index().set_index('Date')
print ('df_test (summary from df) (Output)\n',df_test,'\n')
显然,我在所有MACD数字的列中都没有结果。所以某处计算向南。我不知道出了什么问题......
输出线pr stock-ticker:
df_test (summary from df) (Output)
Ticker Adj_Close Volume emaSlw emaFst MACD MCD_Sign
Date
2016-07-07 nflx 95.10 9902700 NaN NaN NaN NaN
2016-07-07 mmm 174.87 1842300 NaN NaN NaN NaN
你们中的任何人......小费!?
答案 0 :(得分:6)
因此,在我看来,你做的工作比你真正需要的更多。答案有点简单。您不需要定义自己的移动平均功能,这实际上是导致您的问题的原因。
将moving_average
更改为:
def moving_average(group, n=9):
sma = pd.rolling_mean(group, n)
return sma
将moving_average_convergance
更改为:
def moving_average_convergence(group, nslow=26, nfast=12):
emaslow = pd.ewma(group, span=nslow, min_periods=1)
emafast = pd.ewma(group, span=nfast, min_periods=1)
result = pd.DataFrame({'MACD': emafast-emaslow, 'emaSlw': emaslow, 'emaFst': emafast})
return result
N.B。我首先把'MACD'放在这里,因为尽管你已经列出了它,但DataFrame按字母顺序重新排列了这些列。
最后改变:
df_[['emaSlw', 'emaFst', 'MACD']] = df_.groupby(level=1).Adj_Close.apply(moving_average_convergence)
为:
df_[['MACD', 'emaSlw', 'emaFst']] = df_.groupby(level=1).Adj_Close.apply(moving_average_convergence)
应该这样做。